Repository: zertovitch/hac Branch: master Commit: 482c22ea8a00 Files: 670 Total size: 4.3 MB Directory structure: gitextract_y017oy4y/ ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── LICENSE ├── build.cmd ├── debug.pra ├── demo/ │ ├── data_exchange/ │ │ ├── exchange_common.ads │ │ ├── exchange_hac_side.adb │ │ ├── exchange_native_side.adb │ │ ├── exchange_native_side_pkg.adb │ │ └── exchange_native_side_pkg.ads │ ├── data_exchange_simple/ │ │ ├── exchange_hac_side_simple.adb │ │ ├── exchange_native_side_pkg_simple.adb │ │ ├── exchange_native_side_pkg_simple.ads │ │ └── exchange_native_side_simple.adb │ ├── hac_demo.gpr │ └── hac_demo.prj ├── doc/ │ ├── archeology/ │ │ └── smallada_doc.txt │ ├── hac.txt │ └── hac_work.xls ├── exm/ │ ├── ackermann.adb │ ├── anti_primes.adb │ ├── aoc/ │ │ ├── 2020/ │ │ │ ├── aoc_2020.gpr │ │ │ ├── aoc_2020.prj │ │ │ ├── aoc_2020_02.adb │ │ │ ├── aoc_2020_02.txt │ │ │ ├── aoc_2020_03.adb │ │ │ ├── aoc_2020_03.txt │ │ │ ├── aoc_2020_04.adb │ │ │ ├── aoc_2020_04.txt │ │ │ ├── aoc_2020_04_b_full_ada.adb │ │ │ ├── aoc_2020_05.adb │ │ │ ├── aoc_2020_05.txt │ │ │ ├── aoc_2020_06.adb │ │ │ ├── aoc_2020_06.txt │ │ │ ├── aoc_2020_06_full_ada.adb │ │ │ ├── aoc_2020_06_full_ada_using_hat.adb │ │ │ ├── aoc_2020_07.adb │ │ │ ├── aoc_2020_07.txt │ │ │ ├── aoc_2020_07_full_ada.adb │ │ │ ├── aoc_2020_07_full_ada_vectors_2x.adb │ │ │ ├── aoc_2020_08.adb │ │ │ ├── aoc_2020_08.txt │ │ │ ├── aoc_2020_09.adb │ │ │ ├── aoc_2020_09.txt │ │ │ ├── aoc_2020_10.adb │ │ │ ├── aoc_2020_10.txt │ │ │ ├── aoc_2020_11.adb │ │ │ ├── aoc_2020_11.txt │ │ │ ├── aoc_2020_11_full_ada.adb │ │ │ ├── aoc_2020_11_mini.txt │ │ │ ├── aoc_2020_12.adb │ │ │ ├── aoc_2020_12.txt │ │ │ ├── aoc_2020_13.adb │ │ │ ├── aoc_2020_13.txt │ │ │ ├── aoc_2020_14.txt │ │ │ ├── aoc_2020_14_exm_1.txt │ │ │ ├── aoc_2020_14_exm_2.txt │ │ │ ├── aoc_2020_14_full_ada.adb │ │ │ ├── aoc_2020_14_jc.txt │ │ │ ├── aoc_2020_15.adb │ │ │ ├── aoc_2020_15_full_ada.adb │ │ │ ├── aoc_2020_15_full_ada_hashed_maps.adb │ │ │ ├── aoc_2020_16.adb │ │ │ ├── aoc_2020_16.txt │ │ │ ├── aoc_2020_17.adb │ │ │ ├── aoc_2020_17.txt │ │ │ ├── aoc_2020_18.txt │ │ │ ├── aoc_2020_18_full_ada.adb │ │ │ ├── aoc_2020_18_weird_formulas.adb │ │ │ ├── aoc_2020_18_weird_formulas.ads │ │ │ ├── aoc_2020_19.txt │ │ │ ├── aoc_2020_19_full_ada.adb │ │ │ ├── aoc_2020_20.adb │ │ │ ├── aoc_2020_20.txt │ │ │ ├── aoc_2020_21.txt │ │ │ ├── aoc_2020_21_full_ada.adb │ │ │ ├── aoc_2020_21_full_ada_preproc.adb │ │ │ ├── aoc_2020_22.adb │ │ │ ├── aoc_2020_22.txt │ │ │ ├── aoc_2020_22_full_ada.adb │ │ │ ├── aoc_2020_23.adb │ │ │ ├── aoc_2020_23_simple_array.adb │ │ │ ├── aoc_2020_24.adb │ │ │ ├── aoc_2020_24.txt │ │ │ └── aoc_2020_25.adb │ │ ├── 2021/ │ │ │ ├── aoc_2021.gpr │ │ │ ├── aoc_2021_01.adb │ │ │ ├── aoc_2021_01.txt │ │ │ ├── aoc_2021_01_questions.txt │ │ │ ├── aoc_2021_02.adb │ │ │ ├── aoc_2021_02.txt │ │ │ ├── aoc_2021_02_questions.txt │ │ │ ├── aoc_2021_03.adb │ │ │ ├── aoc_2021_03.txt │ │ │ ├── aoc_2021_03_questions.txt │ │ │ ├── aoc_2021_04.adb │ │ │ ├── aoc_2021_04.txt │ │ │ ├── aoc_2021_04_questions.txt │ │ │ ├── aoc_2021_05.adb │ │ │ ├── aoc_2021_05.txt │ │ │ ├── aoc_2021_05_questions.txt │ │ │ ├── aoc_2021_06.adb │ │ │ ├── aoc_2021_06.txt │ │ │ ├── aoc_2021_06_questions.txt │ │ │ ├── aoc_2021_07.adb │ │ │ ├── aoc_2021_07.txt │ │ │ ├── aoc_2021_07_questions.txt │ │ │ ├── aoc_2021_08.adb │ │ │ ├── aoc_2021_08.txt │ │ │ ├── aoc_2021_08_questions.txt │ │ │ ├── aoc_2021_09.adb │ │ │ ├── aoc_2021_09.txt │ │ │ ├── aoc_2021_09_questions.txt │ │ │ ├── aoc_2021_10.adb │ │ │ ├── aoc_2021_10.txt │ │ │ ├── aoc_2021_10_questions.txt │ │ │ ├── aoc_2021_11.adb │ │ │ ├── aoc_2021_11.txt │ │ │ ├── aoc_2021_11_questions.txt │ │ │ ├── aoc_2021_12.adb │ │ │ ├── aoc_2021_12.txt │ │ │ ├── aoc_2021_12_questions.txt │ │ │ ├── aoc_2021_13.adb │ │ │ ├── aoc_2021_13.txt │ │ │ ├── aoc_2021_13_questions.txt │ │ │ ├── aoc_2021_14.adb │ │ │ ├── aoc_2021_14.txt │ │ │ ├── aoc_2021_14_questions.txt │ │ │ ├── aoc_2021_15.adb │ │ │ ├── aoc_2021_15.txt │ │ │ ├── aoc_2021_15_questions.txt │ │ │ ├── aoc_2021_16.adb │ │ │ ├── aoc_2021_16.txt │ │ │ ├── aoc_2021_16_questions.txt │ │ │ ├── aoc_2021_17.adb │ │ │ ├── aoc_2021_17_questions.txt │ │ │ ├── aoc_2021_18.txt │ │ │ ├── aoc_2021_18_full_ada.adb │ │ │ ├── aoc_2021_18_questions.txt │ │ │ ├── aoc_2021_19.adb │ │ │ ├── aoc_2021_19.txt │ │ │ ├── aoc_2021_19_questions.txt │ │ │ ├── aoc_2021_20.adb │ │ │ ├── aoc_2021_20.txt │ │ │ ├── aoc_2021_20_questions.txt │ │ │ ├── aoc_2021_21.adb │ │ │ ├── aoc_2021_21_questions.txt │ │ │ ├── aoc_2021_22.adb │ │ │ ├── aoc_2021_22.txt │ │ │ └── aoc_2021_22_questions.txt │ │ ├── 2022/ │ │ │ ├── aoc_2022.gpr │ │ │ ├── aoc_2022_01.adb │ │ │ ├── aoc_2022_01.txt │ │ │ ├── aoc_2022_01_questions.txt │ │ │ ├── aoc_2022_02.adb │ │ │ ├── aoc_2022_02.txt │ │ │ ├── aoc_2022_02_questions.txt │ │ │ ├── aoc_2022_03.adb │ │ │ ├── aoc_2022_03.txt │ │ │ ├── aoc_2022_03_questions.txt │ │ │ ├── aoc_2022_04.adb │ │ │ ├── aoc_2022_04.txt │ │ │ ├── aoc_2022_04_questions.txt │ │ │ ├── aoc_2022_05.adb │ │ │ ├── aoc_2022_05.txt │ │ │ ├── aoc_2022_05_questions.txt │ │ │ ├── aoc_2022_06.adb │ │ │ ├── aoc_2022_06.txt │ │ │ ├── aoc_2022_06_questions.txt │ │ │ ├── aoc_2022_07.adb │ │ │ ├── aoc_2022_07.txt │ │ │ ├── aoc_2022_07_questions.txt │ │ │ ├── aoc_2022_08.adb │ │ │ ├── aoc_2022_08.txt │ │ │ ├── aoc_2022_08_questions.txt │ │ │ ├── aoc_2022_09.adb │ │ │ ├── aoc_2022_09.txt │ │ │ ├── aoc_2022_09_questions.txt │ │ │ ├── aoc_2022_10.adb │ │ │ ├── aoc_2022_10.txt │ │ │ ├── aoc_2022_10_questions.txt │ │ │ ├── aoc_2022_11.adb │ │ │ ├── aoc_2022_11.txt │ │ │ ├── aoc_2022_11_questions.txt │ │ │ ├── aoc_2022_12.adb │ │ │ ├── aoc_2022_12.txt │ │ │ ├── aoc_2022_12_questions.txt │ │ │ ├── aoc_2022_13.adb │ │ │ ├── aoc_2022_13.txt │ │ │ ├── aoc_2022_13_questions.txt │ │ │ ├── aoc_2022_14.adb │ │ │ ├── aoc_2022_14.txt │ │ │ ├── aoc_2022_14_questions.txt │ │ │ ├── aoc_2022_15.adb │ │ │ ├── aoc_2022_15.txt │ │ │ ├── aoc_2022_15_questions.txt │ │ │ ├── aoc_2022_16.adb │ │ │ ├── aoc_2022_16.txt │ │ │ ├── aoc_2022_16_questions.txt │ │ │ ├── aoc_2022_17.adb │ │ │ ├── aoc_2022_17.txt │ │ │ ├── aoc_2022_17_questions.txt │ │ │ ├── aoc_2022_18.adb │ │ │ ├── aoc_2022_18.txt │ │ │ ├── aoc_2022_18_questions.txt │ │ │ ├── aoc_2022_19.adb │ │ │ ├── aoc_2022_19_full_ada.adb │ │ │ ├── aoc_2022_19_questions.txt │ │ │ ├── aoc_2022_20.adb │ │ │ ├── aoc_2022_20.txt │ │ │ ├── aoc_2022_20_questions.txt │ │ │ ├── aoc_2022_21.adb │ │ │ ├── aoc_2022_21_pkg.adb │ │ │ ├── aoc_2022_21_pkg.ads │ │ │ ├── aoc_2022_21_questions.txt │ │ │ ├── aoc_2022_22.adb │ │ │ ├── aoc_2022_22.txt │ │ │ ├── aoc_2022_22_questions.txt │ │ │ ├── aoc_2022_23.adb │ │ │ ├── aoc_2022_23.txt │ │ │ ├── aoc_2022_23_questions.txt │ │ │ ├── aoc_2022_24.adb │ │ │ ├── aoc_2022_24.txt │ │ │ ├── aoc_2022_24_questions.txt │ │ │ ├── aoc_2022_25.adb │ │ │ ├── aoc_2022_25.txt │ │ │ ├── aoc_2022_25_question.txt │ │ │ ├── aoc_2022_xx.adb │ │ │ └── gen_jumbo_day_1.adb │ │ ├── 2023/ │ │ │ ├── aoc_2023.gpr │ │ │ ├── aoc_2023_01.adb │ │ │ ├── aoc_2023_01.txt │ │ │ ├── aoc_2023_01_questions.txt │ │ │ ├── aoc_2023_02.adb │ │ │ ├── aoc_2023_02.txt │ │ │ ├── aoc_2023_02_questions.txt │ │ │ ├── aoc_2023_03.adb │ │ │ ├── aoc_2023_03.txt │ │ │ ├── aoc_2023_03_questions.txt │ │ │ ├── aoc_2023_04.adb │ │ │ ├── aoc_2023_04.txt │ │ │ ├── aoc_2023_04_questions.txt │ │ │ ├── aoc_2023_05.adb │ │ │ ├── aoc_2023_05.txt │ │ │ ├── aoc_2023_05_questions.txt │ │ │ ├── aoc_2023_06.adb │ │ │ ├── aoc_2023_06_questions.txt │ │ │ ├── aoc_2023_07.adb │ │ │ ├── aoc_2023_07.txt │ │ │ ├── aoc_2023_07_questions.txt │ │ │ ├── aoc_2023_08.adb │ │ │ ├── aoc_2023_08.txt │ │ │ ├── aoc_2023_08_questions.txt │ │ │ ├── aoc_2023_09.adb │ │ │ ├── aoc_2023_09.txt │ │ │ ├── aoc_2023_09_questions.txt │ │ │ ├── aoc_2023_10.adb │ │ │ ├── aoc_2023_10.txt │ │ │ ├── aoc_2023_10_questions.txt │ │ │ ├── aoc_2023_11.adb │ │ │ ├── aoc_2023_11.txt │ │ │ ├── aoc_2023_11_questions.txt │ │ │ ├── aoc_2023_12.adb │ │ │ ├── aoc_2023_12.txt │ │ │ ├── aoc_2023_12_questions.txt │ │ │ ├── aoc_2023_13.adb │ │ │ ├── aoc_2023_13.txt │ │ │ ├── aoc_2023_13_questions.txt │ │ │ ├── aoc_2023_14.adb │ │ │ ├── aoc_2023_14.txt │ │ │ ├── aoc_2023_14_questions.txt │ │ │ ├── aoc_2023_15.adb │ │ │ ├── aoc_2023_15.txt │ │ │ ├── aoc_2023_15_questions.txt │ │ │ ├── aoc_2023_16.adb │ │ │ ├── aoc_2023_16.txt │ │ │ ├── aoc_2023_16_questions.txt │ │ │ ├── aoc_2023_17.adb │ │ │ ├── aoc_2023_17.txt │ │ │ ├── aoc_2023_17_questions.txt │ │ │ ├── aoc_2023_18.adb │ │ │ ├── aoc_2023_18.txt │ │ │ ├── aoc_2023_18_questions.txt │ │ │ ├── aoc_2023_19.adb │ │ │ ├── aoc_2023_19.txt │ │ │ ├── aoc_2023_19_questions.txt │ │ │ ├── aoc_2023_20.adb │ │ │ ├── aoc_2023_20.txt │ │ │ ├── aoc_2023_20_questions.txt │ │ │ ├── aoc_2023_21.adb │ │ │ ├── aoc_2023_21.txt │ │ │ ├── aoc_2023_21_questions.txt │ │ │ ├── aoc_2023_22.adb │ │ │ ├── aoc_2023_22.txt │ │ │ ├── aoc_2023_22_questions.txt │ │ │ ├── aoc_2023_23.adb │ │ │ ├── aoc_2023_23.txt │ │ │ ├── aoc_2023_23_questions.txt │ │ │ ├── aoc_2023_24.adb │ │ │ ├── aoc_2023_24.txt │ │ │ ├── aoc_2023_24_questions.txt │ │ │ ├── aoc_2023_25.adb │ │ │ ├── aoc_2023_25.txt │ │ │ └── aoc_2023_25_questions.txt │ │ ├── 2024/ │ │ │ ├── aoc_2024.gpr │ │ │ ├── aoc_2024_01.adb │ │ │ ├── aoc_2024_01.txt │ │ │ ├── aoc_2024_01_questions.txt │ │ │ ├── aoc_2024_02.adb │ │ │ ├── aoc_2024_02.txt │ │ │ ├── aoc_2024_02_questions.txt │ │ │ ├── aoc_2024_03.adb │ │ │ ├── aoc_2024_03.txt │ │ │ ├── aoc_2024_03_questions.txt │ │ │ ├── aoc_2024_04.adb │ │ │ ├── aoc_2024_04.txt │ │ │ ├── aoc_2024_04_questions.txt │ │ │ ├── aoc_2024_05.adb │ │ │ ├── aoc_2024_05.txt │ │ │ ├── aoc_2024_05_questions.txt │ │ │ ├── aoc_2024_06.adb │ │ │ ├── aoc_2024_06.txt │ │ │ ├── aoc_2024_06_questions.txt │ │ │ ├── aoc_2024_07.adb │ │ │ ├── aoc_2024_07.txt │ │ │ ├── aoc_2024_07_questions.txt │ │ │ ├── aoc_2024_08.adb │ │ │ ├── aoc_2024_08.txt │ │ │ ├── aoc_2024_08_questions.txt │ │ │ ├── aoc_2024_09.adb │ │ │ ├── aoc_2024_09.txt │ │ │ ├── aoc_2024_09_questions.txt │ │ │ ├── aoc_2024_10.adb │ │ │ ├── aoc_2024_10.txt │ │ │ ├── aoc_2024_10_questions.txt │ │ │ ├── aoc_2024_11.adb │ │ │ ├── aoc_2024_11_questions.txt │ │ │ ├── aoc_2024_12.adb │ │ │ ├── aoc_2024_12.txt │ │ │ ├── aoc_2024_12_questions.txt │ │ │ ├── aoc_2024_13.adb │ │ │ ├── aoc_2024_13.txt │ │ │ ├── aoc_2024_13_questions.txt │ │ │ ├── aoc_2024_14.adb │ │ │ ├── aoc_2024_14.txt │ │ │ ├── aoc_2024_14_questions.txt │ │ │ ├── aoc_2024_15.adb │ │ │ ├── aoc_2024_15.txt │ │ │ ├── aoc_2024_15_questions.txt │ │ │ ├── aoc_2024_16.adb │ │ │ ├── aoc_2024_16.txt │ │ │ ├── aoc_2024_16_questions.txt │ │ │ ├── aoc_2024_17.adb │ │ │ ├── aoc_2024_17_questions.txt │ │ │ ├── aoc_2024_18.adb │ │ │ ├── aoc_2024_18.txt │ │ │ ├── aoc_2024_18_questions.txt │ │ │ ├── aoc_2024_19.adb │ │ │ ├── aoc_2024_19.txt │ │ │ ├── aoc_2024_19_questions.txt │ │ │ ├── aoc_2024_20.adb │ │ │ ├── aoc_2024_20.txt │ │ │ ├── aoc_2024_20_mini.txt │ │ │ ├── aoc_2024_20_questions.txt │ │ │ ├── aoc_2024_21.adb │ │ │ ├── aoc_2024_21_questions.txt │ │ │ ├── aoc_2024_22.adb │ │ │ ├── aoc_2024_22.txt │ │ │ ├── aoc_2024_22_full_ada.adb │ │ │ ├── aoc_2024_22_mini.txt │ │ │ ├── aoc_2024_22_questions.txt │ │ │ ├── aoc_2024_23.adb │ │ │ ├── aoc_2024_23.txt │ │ │ ├── aoc_2024_23_questions.txt │ │ │ ├── aoc_2024_24.adb │ │ │ ├── aoc_2024_24_questions.txt │ │ │ ├── aoc_2024_25.adb │ │ │ ├── aoc_2024_25.txt │ │ │ └── aoc_2024_25_questions.txt │ │ ├── 2025/ │ │ │ ├── aoc_2025.gpr │ │ │ ├── aoc_2025_01.adb │ │ │ ├── aoc_2025_01.txt │ │ │ ├── aoc_2025_01_questions.txt │ │ │ ├── aoc_2025_02.adb │ │ │ ├── aoc_2025_02.txt │ │ │ ├── aoc_2025_02_mini.txt │ │ │ ├── aoc_2025_02_questions.txt │ │ │ ├── aoc_2025_03.adb │ │ │ ├── aoc_2025_03.txt │ │ │ ├── aoc_2025_03_questions.txt │ │ │ ├── aoc_2025_04.adb │ │ │ ├── aoc_2025_04.txt │ │ │ ├── aoc_2025_04_questions.txt │ │ │ ├── aoc_2025_05.adb │ │ │ ├── aoc_2025_05.txt │ │ │ ├── aoc_2025_05_questions.txt │ │ │ ├── aoc_2025_06.adb │ │ │ ├── aoc_2025_06.txt │ │ │ ├── aoc_2025_06_questions.txt │ │ │ ├── aoc_2025_07.adb │ │ │ ├── aoc_2025_07.txt │ │ │ ├── aoc_2025_07_questions.txt │ │ │ ├── aoc_2025_08.adb │ │ │ ├── aoc_2025_08.txt │ │ │ ├── aoc_2025_08_mini.txt │ │ │ ├── aoc_2025_08_questions.txt │ │ │ ├── aoc_2025_09.adb │ │ │ ├── aoc_2025_09.m │ │ │ ├── aoc_2025_09.txt │ │ │ ├── aoc_2025_09_questions.txt │ │ │ ├── aoc_2025_10.adb │ │ │ ├── aoc_2025_10.txt │ │ │ ├── aoc_2025_10_mini.txt │ │ │ ├── aoc_2025_10_questions.txt │ │ │ ├── aoc_2025_11.adb │ │ │ ├── aoc_2025_11.txt │ │ │ └── aoc_2025_11_questions.txt │ │ ├── aoc_check_list.txt │ │ ├── aoc_toolbox.adb │ │ └── aoc_toolbox.ads │ ├── arguments.adb │ ├── attributes.adb │ ├── auto_complete.adb │ ├── barnes.adb │ ├── binomials.adb │ ├── bwt.adb │ ├── ce_b_2.adb │ ├── ce_b_4.adb │ ├── ce_c_2.adb │ ├── ce_c_4.adb │ ├── ce_e_1.adb │ ├── ce_e_2.adb │ ├── ce_e_4.adb │ ├── ce_i_1.adb │ ├── ce_i_2.adb │ ├── ce_i_3.adb │ ├── ce_i_4.adb │ ├── console_io.adb │ ├── covid_19_s.adb │ ├── cross_a.adb │ ├── cross_a.ads │ ├── cross_b.adb │ ├── cross_b.ads │ ├── days_1901.adb │ ├── directories.adb │ ├── doors.adb │ ├── draw_sphere.adb │ ├── e.cmd │ ├── echo.adb │ ├── einmaleins.adb │ ├── embed_text.adb │ ├── env.adb │ ├── existence.adb │ ├── file_append.adb │ ├── file_copy.adb │ ├── file_read.adb │ ├── fill_drive.adb │ ├── gallery.adb │ ├── hac_exm.gpr │ ├── hac_exm.prj │ ├── hello.adb │ ├── hello_big.adb │ ├── hofstadter.adb │ ├── mandelbrot.adb │ ├── mathe_kal/ │ │ └── 2022/ │ │ ├── mathe_plus_2022_02.adb │ │ ├── mathe_plus_2022_04.adb │ │ ├── mathe_plus_2022_09.adb │ │ └── mkp_2022.gpr │ ├── maze_gen.adb │ ├── md2html.adb │ ├── merge_sort.adb │ ├── names_in_boxes.adb │ ├── native.adb │ ├── not_working/ │ │ ├── din_sm.adb │ │ ├── din_ws.adb │ │ ├── dinersmo.adb │ │ ├── newrace.adb │ │ ├── overloading.adb │ │ ├── pgm0.adb │ │ ├── pgm1.adb │ │ ├── pgm2.adb │ │ ├── race.adb │ │ ├── racedead.adb │ │ └── roland_01.adb │ ├── pack_list.adb │ ├── pdf/ │ │ ├── hac_pdf_out.adb │ │ ├── hac_pdf_out.ads │ │ ├── hilbert_curve.adb │ │ ├── koch_curve.adb │ │ ├── pdf_hello.adb │ │ └── peano_curve.adb │ ├── permutations.adb │ ├── pkg_1.adb │ ├── pkg_1.ads │ ├── pkg_2.ads │ ├── pkg_demo.adb │ ├── pkg_demo_gen.adb │ ├── prc.adb │ ├── random.adb │ ├── record_code_gen.adb │ ├── remarks.adb │ ├── series.adb │ ├── shell.adb │ ├── shell_sort.adb │ ├── strings_demo.adb │ ├── sudoku_sample.adb │ ├── sudokus.adb │ ├── sudokus.ads │ ├── tasking/ │ │ ├── tasks_01.adb │ │ └── tasks_02.adb │ ├── three_lakes_s.adb │ ├── timing.adb │ ├── triangles_overlap.adb │ ├── unit_a.adb │ ├── unit_b.adb │ ├── unit_b.ads │ ├── unit_c.adb │ ├── unit_e.adb │ ├── unit_f.adb │ ├── unit_f.ads │ ├── unit_g.adb │ └── unit_g.ads ├── fast.cmd ├── hac.gpr ├── hac_objectada.prj ├── profiling.cmd ├── readme.md ├── save.hac ├── save_modif.hac ├── save_modif_and_untracked.hac ├── small.cmd ├── src/ │ ├── apps/ │ │ ├── hac.adb │ │ ├── hac_mini.adb │ │ ├── hac_multi.adb │ │ ├── hac_pkg.adb │ │ ├── hac_pkg.ads │ │ └── show_mit_license.adb │ ├── compile/ │ │ ├── emit/ │ │ │ ├── hac_sys-targets-amd64_windows_console_fasm.adb │ │ │ ├── hac_sys-targets-amd64_windows_console_fasm.ads │ │ │ ├── hac_sys-targets-hac_virtual_machine.adb │ │ │ ├── hac_sys-targets-hac_virtual_machine.ads │ │ │ ├── hac_sys-targets-semantics.adb │ │ │ ├── hac_sys-targets-semantics.ads │ │ │ └── hac_sys-targets.ads │ │ ├── hac_sys-builder.adb │ │ ├── hac_sys-builder.ads │ │ ├── hac_sys-co_defs.adb │ │ ├── hac_sys-co_defs.ads │ │ ├── hac_sys-compiler-pcode_emit.adb │ │ ├── hac_sys-compiler-pcode_emit.ads │ │ ├── hac_sys-compiler.adb │ │ ├── hac_sys-compiler.ads │ │ ├── hac_sys-defs.adb │ │ ├── hac_sys-defs.ads │ │ ├── hac_sys-errors.adb │ │ ├── hac_sys-errors.ads │ │ ├── hac_sys-multi_precision_integers.adb │ │ ├── hac_sys-multi_precision_integers.ads │ │ ├── hac_sys-parser-attributes.adb │ │ ├── hac_sys-parser-attributes.ads │ │ ├── hac_sys-parser-calls.adb │ │ ├── hac_sys-parser-calls.ads │ │ ├── hac_sys-parser-const_var.adb │ │ ├── hac_sys-parser-const_var.ads │ │ ├── hac_sys-parser-enter_def.adb │ │ ├── hac_sys-parser-enter_def.ads │ │ ├── hac_sys-parser-expressions.adb │ │ ├── hac_sys-parser-expressions.ads │ │ ├── hac_sys-parser-helpers.adb │ │ ├── hac_sys-parser-helpers.ads │ │ ├── hac_sys-parser-modularity.adb │ │ ├── hac_sys-parser-modularity.ads │ │ ├── hac_sys-parser-packages.adb │ │ ├── hac_sys-parser-packages.ads │ │ ├── hac_sys-parser-ranges.adb │ │ ├── hac_sys-parser-ranges.ads │ │ ├── hac_sys-parser-standard_functions.adb │ │ ├── hac_sys-parser-standard_functions.ads │ │ ├── hac_sys-parser-standard_procedures.adb │ │ ├── hac_sys-parser-standard_procedures.ads │ │ ├── hac_sys-parser-statements-case_statement.adb │ │ ├── hac_sys-parser-statements.adb │ │ ├── hac_sys-parser-statements.ads │ │ ├── hac_sys-parser-tasking.adb │ │ ├── hac_sys-parser-tasking.ads │ │ ├── hac_sys-parser-type_conversion.adb │ │ ├── hac_sys-parser-type_conversion.ads │ │ ├── hac_sys-parser-type_def.adb │ │ ├── hac_sys-parser-type_def.ads │ │ ├── hac_sys-parser.adb │ │ ├── hac_sys-parser.ads │ │ ├── hac_sys-scanner.adb │ │ └── hac_sys-scanner.ads │ ├── execute/ │ │ ├── hac_sys-interfacing.adb │ │ ├── hac_sys-pcode-interpreter-calls.adb │ │ ├── hac_sys-pcode-interpreter-calls.ads │ │ ├── hac_sys-pcode-interpreter-composite_data.adb │ │ ├── hac_sys-pcode-interpreter-composite_data.ads │ │ ├── hac_sys-pcode-interpreter-exceptions.adb │ │ ├── hac_sys-pcode-interpreter-exceptions.ads │ │ ├── hac_sys-pcode-interpreter-in_defs.adb │ │ ├── hac_sys-pcode-interpreter-in_defs.ads │ │ ├── hac_sys-pcode-interpreter-multi_statement.adb │ │ ├── hac_sys-pcode-interpreter-multi_statement.ads │ │ ├── hac_sys-pcode-interpreter-operators.adb │ │ ├── hac_sys-pcode-interpreter-operators.ads │ │ ├── hac_sys-pcode-interpreter-tasking-scheduler.adb │ │ ├── hac_sys-pcode-interpreter-tasking.adb │ │ ├── hac_sys-pcode-interpreter-tasking.ads │ │ ├── hac_sys-pcode-interpreter.adb │ │ ├── hac_sys-pcode-interpreter.ads │ │ ├── hac_sys-pcode.adb │ │ └── hac_sys-pcode.ads │ ├── hac_sys-interfacing.ads │ ├── hac_sys.ads │ ├── hat-non_standard.adb │ ├── hat-non_standard_oawin64.adb │ ├── hat.adb │ ├── hat.ads │ └── manage/ │ ├── hac_sys-files-default.adb │ ├── hac_sys-files-default.ads │ ├── hac_sys-files.ads │ ├── hac_sys-librarian-built_in_packages.adb │ ├── hac_sys-librarian-built_in_packages.ads │ ├── hac_sys-librarian.adb │ └── hac_sys-librarian.ads └── test/ ├── all_noisy_tests.adb ├── all_silent_tests.adb ├── attributes_test.adb ├── case_statement.adb ├── constants.adb ├── declarations.adb ├── digitz.adb ├── enumerations.adb ├── exception_01.adb ├── exception_02.adb ├── exception_03.adb ├── exception_04.adb ├── floats.adb ├── forward.adb ├── future/ │ └── block_statements.adb ├── hac_test.gpr ├── hac_test.prj ├── if_then_elsif_else.adb ├── integers.adb ├── loops.adb ├── object_init.adb ├── open_files.adb ├── optim.adb ├── recursion.adb ├── remarks_check.adb ├── remarks_k_ok.txt ├── remarks_r_ok.txt ├── remarks_u_ok.txt ├── remarks_v_ok.txt ├── shell_test.adb ├── silent_tests_single_build.adb ├── sorting_tests.adb ├── strings.adb ├── t.cmd ├── test.adb ├── test1.adb ├── test_tail_after_match.adb ├── testing_utilities.adb ├── testing_utilities.ads ├── tf.cmd ├── toa.cmd ├── ts.cmd ├── type_conversion.adb └── verif_hac.aru ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: https://www.paypal.com/donate/?item_name=Donation+to+the+author+of+HAC&cmd=_donations&business=esgm%40bluewin.ch ================================================ FILE: .gitignore ================================================ /obj/ /bin/ /hac /hac_mini /hac_multi ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2013 .. 2025 Gautier de Montmollin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: build.cmd ================================================ @echo off gprbuild %1 -P hac -XHAC_OS=Win64 gprbuild %1 -P demo/hac_demo -XHAC_OS=Win64 if %errorlevel% == 9009 goto error echo Press Return pause goto :eof :error echo. echo The GNAT Ada compiler was not found in the PATH! echo. echo Check https://www.adacore.com/download for GNAT echo or https://alire.ada.dev/ for ALIRE. echo The HAC project is available as an ALIRE crate. echo. echo Press Return pause ================================================ FILE: debug.pra ================================================ pragma Initialize_Scalars; -- pragma Normalize_Scalars; -- For all units! ================================================ FILE: demo/data_exchange/exchange_common.ads ================================================ ------------------------------------------- -- HAC <-> Native data exchange demo -- ------------------------------------------- -- Package used by both HAC and -- -- Native sides -- ------------------------------------------- package Exchange_Common is type Animal is (ant, bat, cat, dog); subtype Beast is Animal; subtype Insect is Animal range ant .. ant; subtype Mammal is Animal range bat .. dog; end Exchange_Common; ================================================ FILE: demo/data_exchange/exchange_hac_side.adb ================================================ ----------------------------------------- -- HAC <-> Native data exchange demo -- ----------------------------------------- -- HAC side -- ----------------------------------------- -- This file is meant to be compiled by the HAC compiler which is -- embedded in Exchange_Native_Side (exchange_native_side.adb). with HAT; with Exchange_Common; procedure Exchange_HAC_Side is use HAT; procedure Demo_Parameterless is procedure Parameterless_Callback with Import => True; begin Put_Line (" HAC: I call a parameterless callback."); Parameterless_Callback; Put_Line (" HAC: done calling."); New_Line; end Demo_Parameterless; procedure Demo_Data_to_Native is procedure Hello_Callback (message : in VString) with Import => True; procedure Ints_Callback (i, j, k : in Integer) with Import => True; procedure Floats_Callback (f, g, h : in Real) with Import => True; begin Put_Line (" HAC: I send some stuff through callbacks."); Hello_Callback (+"I'm HAC and I say hello!"); Ints_Callback (123, 456, 789); Floats_Callback (123.0, 456.0, 789.0); New_Line; end Demo_Data_to_Native; procedure Demo_Data_Bidirectional is procedure Hello_Callback_in_out (message : in out VString) with Import => True; procedure Ints_Callback_in_out (i : in out Integer) with Import => True; procedure Floats_Callback_in_out (f : in out Real) with Import => True; m : VString := +"I'm HAC"; i : Integer := 12; f : Real := 11.0; begin m := +"I'm HAC"; Put_Line (" HAC: message before call: [" & m & ']'); Hello_Callback_in_out (m); Put_Line (" HAC: message after call: [" & m & ']'); Put_Line (+" HAC: integer before call: [" & i & ']'); Ints_Callback_in_out (i); Put_Line (+" HAC: integer after call: [" & i & ']'); Put_Line (+" HAC: float before call: [" & f & ']'); Floats_Callback_in_out (f); Put_Line (+" HAC: float after call: [" & f & ']'); New_Line; end Demo_Data_Bidirectional; procedure Demo_Composite is type Matrix is array (1 .. 2, 1 .. 2) of HAT.Real; type Some_Record is record i : Integer; v : VString; e : Exchange_Common.Animal; end record; procedure Composite_Callback (a, b : in Matrix; r : in out Some_Record; c : out Matrix) with Import => True; m, n, o : Matrix; s : Some_Record; begin -- HAC 0.2: no aggregates, we have to write the matrix' contents cell by cell. m (1, 1) := 1.1; m (1, 2) := 1.2; m (2, 1) := 1.3; m (2, 2) := 1.4; n (1, 1) := -2.1; n (1, 2) := 2.2; n (2, 1) := -2.3; n (2, 2) := 2.4; s.i := 13; s.v := +"I'm a HAC record field"; s.e := Exchange_Common.bat; Put_Line (+" HAC: integer before call: [" & s.i & ']'); Put_Line (+" message before call: [" & s.v & ']'); Put_Line (+" enum before call: [" & s.e'Image & ']'); Composite_Callback (m, n, s, o); Put_Line (+" HAC: integer after call: [" & s.i & ']'); Put_Line (+" message after call: [" & s.v & ']'); Put_Line (+" enum after call: [" & s.e'Image & ']'); Put_Line (+" matrix product:"); for i in o'Range (1) loop Put (" "); for j in o'Range (2) loop Put (o (i, j), 2, 2, 0); end loop; New_Line; end loop; end Demo_Composite; begin Put_Line (" Exchange_HAC_Side is started."); New_Line; -- Demo_Parameterless; Demo_Data_to_Native; Demo_Data_Bidirectional; Demo_Composite; -- Set_VM_Variable ("Demo_Variable", Get_VM_Variable ("Demo_Variable") & "HAC... "); end Exchange_HAC_Side; ================================================ FILE: demo/data_exchange/exchange_native_side.adb ================================================ ------------------------------------------- -- HAC <-> Native data exchange demo -- ------------------------------------------- -- Native side -- ------------------------------------------- -- Native & master side of the demo. -- HAC is embedded in this application. -- Compile this program with a "full Ada" compiler like GNAT. with Ada.Directories, Ada.Text_IO; with HAC_Sys.Builder, HAC_Sys.PCode.Interpreter; with Exchange_Native_Side_Pkg; procedure Exchange_Native_Side is use Ada.Text_IO; use HAC_Sys.PCode.Interpreter; BD : HAC_Sys.Builder.Build_Data; procedure Build is hac_program_name : constant String := "exchange_hac_side.adb"; begin Put_Line ("Native: building a HAC program: " & hac_program_name); New_Line; BD.Build_Main_from_File (hac_program_name); end Build; procedure Run is post_mortem : Post_Mortem_Data; begin Interpret_on_Current_IO (BD, 1, "", post_mortem); if Is_Exception_Raised (post_mortem.Unhandled) then Put_Line (Current_Error, "HAC VM: raised " & Image (post_mortem.Unhandled)); Put_Line (Current_Error, Message (post_mortem.Unhandled)); end if; end Run; begin Put_Line ("Exchange_Native_Side is started."); New_Line; Exchange_Native_Side_Pkg.Register_All_Callbacks (BD); Exchange_Native_Side_Pkg.Set_Global_VM_Variable (BD); Ada.Directories.Set_Directory ("data_exchange"); Build; if BD.Build_Successful then for i in 1 .. 2 loop Put_Line ("Native: Run #" & Integer'Image (i)); Run; Put_Line ("Native: Run #" & Integer'Image (i) & ". Global string variable is: " & Exchange_Native_Side_Pkg.Get_Global_VM_Variable (BD)); New_Line; end loop; end if; end Exchange_Native_Side; ================================================ FILE: demo/data_exchange/exchange_native_side_pkg.adb ================================================ ------------------------------------------- -- HAC <-> Native data exchange demo -- ------------------------------------------- -- Callbacks on Native side. with Exchange_Common; with HAC_Sys.Interfacing; with Ada.Numerics.Long_Real_Arrays, Ada.Text_IO; package body Exchange_Native_Side_Pkg is use Ada.Text_IO; use HAC_Sys.Interfacing; procedure Parameterless_Callback (Dummy : in out HAC_Element_Array) is begin Put_Line (" Native: Parameterless_Callback is speaking!"); end Parameterless_Callback; procedure Hello_Callback (Data : in out HAC_Element_Array) is begin Put_Line (" Native: HAC is saying: [" & To_Native (Data (1)) & ']'); end Hello_Callback; procedure Ints_Callback (Data : in out HAC_Element_Array) is i, j, k : Integer; begin i := To_Native (Data (1)); j := To_Native (Data (2)); k := To_Native (Data (3)); Put_Line (" Native: HAC has sent me the numbers:" & Integer'Image (i) & Integer'Image (j) & Integer'Image (k)); end Ints_Callback; procedure Floats_Callback (Data : in out HAC_Element_Array) is f, g, h : Long_Float; begin f := To_Native (Data (1)); g := To_Native (Data (2)); h := To_Native (Data (3)); Put_Line (" Native: HAC has sent me the numbers:" & Long_Float'Image (f) & Long_Float'Image (g) & Long_Float'Image (h)); end Floats_Callback; procedure Hello_Callback_in_out (Data : in out HAC_Element_Array) is begin Put_Line (" Native: HAC is saying: [" & To_Native (Data (1)) & ']'); Data (1) := To_HAC ("No, I'm Native, you loser!"); end Hello_Callback_in_out; procedure Ints_Callback_in_out (Data : in out HAC_Element_Array) is i : Integer; begin i := To_Native (Data (1)); Put_Line (" Native: HAC has sent me the number:" & Integer'Image (i) & "; I will send it back squared."); Data (1) := To_HAC (i ** 2); end Ints_Callback_in_out; procedure Floats_Callback_in_out (Data : in out HAC_Element_Array) is f : Long_Float; begin f := To_Native (Data (1)); Put_Line (" Native: HAC has sent me the number:" & Long_Float'Image (f) & "; I will send it back squared."); Data (1) := To_HAC (f ** 2); end Floats_Callback_in_out; procedure Composite_Callback (Data : in out HAC_Element_Array) is m_pos : constant := 1; -- Index for matrix 1 n_pos : constant := 5; -- Index for matrix 2 r_pos : constant := 9; -- Index for record 1 o_pos : constant := 12; -- Index for matrix 3 use Ada.Numerics.Long_Real_Arrays; package LFIO is new Ada.Text_IO.Float_IO (Long_Float); use LFIO; procedure Show (m : Real_Matrix) is begin for i in m'Range (1) loop Put (" "); for j in m'Range (2) loop Put (m (i, j), 2, 2, 0); end loop; New_Line; end loop; end Show; -- m, n, o : Real_Matrix (1 .. 2, 1 .. 2); e : Exchange_Common.Animal; -- function To_HAC is new To_HAC_Any_Enum (Exchange_Common.Animal); function To_Native is new To_Native_Any_Enum (Exchange_Common.Animal); begin e := To_Native (Data (r_pos + 2)); Put_Line (" Native: Enum = " & Exchange_Common.Animal'Image (e)); m := ((To_Native (Data (m_pos)), To_Native (Data (m_pos + 1))), (To_Native (Data (m_pos + 2)), To_Native (Data (m_pos + 3)))); Put_Line (" Native: Matrix m:"); Show (m); n := ((To_Native (Data (n_pos)), To_Native (Data (n_pos + 1))), (To_Native (Data (n_pos + 2)), To_Native (Data (n_pos + 3)))); Put_Line (" Native: Matrix n:"); Show (n); o := m * n; Put_Line (" Native: Matrix o = m * n:"); Show (o); Data (o_pos .. o_pos + 3) := (To_HAC (o (1, 1)), To_HAC (o (1, 2)), To_HAC (o (2, 1)), To_HAC (o (2, 2))); Data (r_pos) := To_HAC (Integer'(To_Native (Data (r_pos))) ** 2); Data (r_pos + 1) := To_HAC ("I'm a Native message now (niarg niarg niarg)!"); e := Exchange_Common.cat; Data (r_pos + 2) := To_HAC (e); Put_Line (" Native: Enum = " & Exchange_Common.Animal'Image (e)); end Composite_Callback; procedure Register_All_Callbacks (BD : HAC_Sys.Builder.Build_Data) is begin Register (BD, Parameterless_Callback'Access, "Parameterless_Callback"); Register (BD, Hello_Callback'Access, "Hello_Callback"); Register (BD, Ints_Callback'Access, "Ints_Callback"); Register (BD, Floats_Callback'Access, "Floats_Callback"); Register (BD, Hello_Callback_in_out'Access, "Hello_Callback_in_out"); Register (BD, Ints_Callback_in_out'Access, "Ints_Callback_in_out"); Register (BD, Floats_Callback_in_out'Access, "Floats_Callback_in_out"); Register (BD, Composite_Callback'Access, "Composite_Callback"); end Register_All_Callbacks; procedure Set_Global_VM_Variable (BD : in out HAC_Sys.Builder.Build_Data) is begin Set_VM_Variable (BD, "Demo_Variable", "Native... "); end Set_Global_VM_Variable; function Get_Global_VM_Variable (BD : HAC_Sys.Builder.Build_Data) return String is begin return Get_VM_Variable (BD, "Demo_Variable"); end Get_Global_VM_Variable; end Exchange_Native_Side_Pkg; ================================================ FILE: demo/data_exchange/exchange_native_side_pkg.ads ================================================ ------------------------------------------- -- HAC <-> Native data exchange demo -- ------------------------------------------- -- Registration of callbacks on Native side. with HAC_Sys.Builder; package Exchange_Native_Side_Pkg is procedure Register_All_Callbacks (BD : HAC_Sys.Builder.Build_Data); procedure Set_Global_VM_Variable (BD : in out HAC_Sys.Builder.Build_Data); function Get_Global_VM_Variable (BD : HAC_Sys.Builder.Build_Data) return String; end Exchange_Native_Side_Pkg; ================================================ FILE: demo/data_exchange_simple/exchange_hac_side_simple.adb ================================================ ----------------------------------------- -- HAC <-> Native data exchange demo -- ----------------------------------------- -- HAC side (simple version) -- ----------------------------------------- -- This file is meant to be compiled by the HAC compiler which is -- embedded in Exchange_Native_Side_Simple (exchange_native_side_simple.adb). with HAT; procedure Exchange_HAC_Side_Simple is use HAT; procedure In_Out_Callback (i : in out Integer) with Import => True; x : Integer := 1234; begin HAT.Put_Line (" [HAC]: before callback, variable x has value:" & x'Image); In_Out_Callback (x); HAT.Put_Line (" [HAC]: after callback, variable x has value:" & x'Image); end Exchange_HAC_Side_Simple; ================================================ FILE: demo/data_exchange_simple/exchange_native_side_pkg_simple.adb ================================================ ------------------------------------------- -- HAC <-> Native data exchange demo -- ------------------------------------------- -- Callbacks on Native side. with HAC_Sys.Interfacing; with Ada.Text_IO; package body Exchange_Native_Side_Pkg_Simple is use HAC_Sys.Interfacing; procedure In_Out_Callback (Data : in out HAC_Element_Array) is my_val : constant := 9876; begin Ada.Text_IO.Put_Line (" [Native] (callback): HAC has given the following value:" & Integer'Image (To_Native (Data (1)))); Data (1) := To_HAC (my_val); Ada.Text_IO.Put_Line (" [Native] (callback): I just changed the value to..." & my_val'Image); end In_Out_Callback; procedure Register_All_Callbacks (BD : HAC_Sys.Builder.Build_Data) is begin Register (BD, In_Out_Callback'Access, "In_Out_Callback"); end Register_All_Callbacks; end Exchange_Native_Side_Pkg_Simple; ================================================ FILE: demo/data_exchange_simple/exchange_native_side_pkg_simple.ads ================================================ ------------------------------------------------------------ -- HAC <-> Native data exchange demo (simple version) -- ------------------------------------------------------------ -- Registration of callbacks on Native side. with HAC_Sys.Builder; package Exchange_Native_Side_Pkg_Simple is procedure Register_All_Callbacks (BD : HAC_Sys.Builder.Build_Data); end Exchange_Native_Side_Pkg_Simple; ================================================ FILE: demo/data_exchange_simple/exchange_native_side_simple.adb ================================================ ------------------------------------------- -- HAC <-> Native data exchange demo -- ------------------------------------------- -- Native side -- ------------------------------------------- -- Native & master side of the demo. -- HAC is embedded in this application. -- Compile this program with a "full Ada" compiler like GNAT. with Ada.Directories, Ada.Text_IO; with HAC_Sys.Builder, HAC_Sys.PCode.Interpreter; with Exchange_Native_Side_Pkg_Simple; procedure Exchange_Native_Side_Simple is use Ada.Text_IO; use HAC_Sys.PCode.Interpreter; use Exchange_Native_Side_Pkg_Simple; BD : HAC_Sys.Builder.Build_Data; procedure Run_with_HAC is post_mortem : Post_Mortem_Data; begin Interpret_on_Current_IO (BD, 1, "", post_mortem); if Is_Exception_Raised (post_mortem.Unhandled) then Put_Line (Current_Error, "HAC VM: raised " & Image (post_mortem.Unhandled)); Put_Line (Current_Error, Message (post_mortem.Unhandled)); end if; end Run_with_HAC; begin Register_All_Callbacks (BD); Ada.Directories.Set_Directory ("data_exchange_simple"); for i in Positive loop New_Line (3); Put_Line ("[Native]: Run #" & i'Image & " --------------------------------------------------------"); BD.Build_Main_from_File ("exchange_hac_side_simple.adb"); if BD.Build_Successful then Run_with_HAC; end if; Put_Line ("[Native]: Delay"); delay 3.0; end loop; end Exchange_Native_Side_Simple; ================================================ FILE: demo/hac_demo.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the demos of the HAC project ( https://sf.net/projects/hacadacompiler/ ). -- -- Build me with "gprbuild -P hac_demo", or open me with GNAT Studio. -- project HAC_Demo is type HAC_Build_Mode_Type is ("Debug", "Fast", "Small"); HAC_Build_Mode : HAC_Build_Mode_Type := external ("HAC_Build_Mode", "Debug"); for Main use ("exchange_native_side_simple.adb", -- Data exchange demo between HAC and "full Ada" - "full Ada" (native) side, simple version "exchange_native_side.adb"); -- Data exchange demo between HAC and "full Ada" - "full Ada" (native) side case HAC_Build_Mode is when "Debug" => for Object_Dir use "../obj/debug"; when "Fast" => for Object_Dir use "../obj/fast"; when "Small" => for Object_Dir use "../obj/small"; end case; for Source_Dirs use ("../src", "../src/compile", "../src/compile/emit", "../src/execute", "../src/manage", ".", "./data_exchange", "./data_exchange_simple"); for Exec_Dir use "."; for Create_Missing_Dirs use "True"; -- Flips by default the "-p" switch package Pretty_Printer is for Default_Switches ("ada") use ("-i2"); end Pretty_Printer; Common_Compiler_Options := ( "-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwcijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatwCKMUV", -- Warnings switches (turn off some irrelevant for the tests) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ", -- Don't quit, write ali/tree file even if compile errors -- "-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens -- "-gnatye", -- Style: check e:end/exit labels present "-gnatytc" -- Style: check t:token separation rules, c:comment format (two spaces) ); Debug_Options := ( "-gnata", -- Assertions enabled "-gnato", -- Enable overflow checking in STRICT mode "-gnatVa", -- Enable all validity checking options "-fstack-check", "-fno-inline", -- "-g" -- Generate debugging information ); Fast_Options := ("-O2", "-gnatn", "-fipa-cp-clone", "-fgcse-after-reload", "-funroll-loops", "-fpeel-loops", "-funswitch-loops", "-ftracer", "-fweb", "-ftree-vectorize", "-frename-registers", "-ffunction-sections", "-g"); package Compiler is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Compiler_Options & Debug_Options; for Local_Configuration_Pragmas use project'Project_Dir & "../debug.pra"; when "Fast" => for Default_Switches ("ada") use Common_Compiler_Options & Fast_Options; when "Small" => for Default_Switches ("ada") use Common_Compiler_Options & "-Os"; end case; end Compiler; Common_Binder_Options := (); package Binder is case HAC_Build_Mode is when "Small" => for Default_Switches ("ada") use Common_Binder_Options; -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks when others => for Default_Switches ("ada") use Common_Binder_Options & ("-Es"); end case; end Binder; Common_Linker_Options := (); package Linker is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Linker_Options & ("-g"); when "Fast" => for Default_Switches ("ada") use Common_Linker_Options & ("-g", "-Wl,--gc-sections"); when "Small" => for Default_Switches ("ada") use Common_Linker_Options & ( "-Wl,--gc-sections"); end case; end Linker; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-g", "-j0"); end Builder; end HAC_Demo; ================================================ FILE: doc/archeology/smallada_doc.txt ================================================ S M A L L A d a 1 9 9 1 IBM PC-family version Department of Electrical Engineering and Computer Science The George Washington University Washington, DC 20052 USA This is a compiler/interpreter for a part of the Ada language, namely the "Pascal subset" plus the Ada tasking support. It is not intended ever to be a full Ada compiler, rather a vehicle for teaching, learning, and experimenting with concurrent programming. The compiler is quite fast, producing P-code which is then interpreted by the interpreter. The system will run on an IBM PC (or compatible) with the following minimum configuration: 640K of memory; one disk drive. A hard disk will greatly improve the speed. The entire system runs in RAM with no disk accesses, so expect capacity to be limited. 250 statements or so can be safely accommodated. SmallAda executables and demo programs are distributed as a self- extracting archive created by LHA. To install SmallAda, just create a directory on your hard disk called, say, smallada, move to that directory, and execute the self-extracting archive sm-archv directly from your diskette. If your diskette is in drive A:, just type A:\SM-ARCHV. The current version is not particularly robust, rather it is a preliminary step toward effective window-oriented monitoring of task execution. This package may be copied and used for educational purposes but not for profit; please let us know by e-mail or regular mail how you like the idea of this package and what you are doing with it. The more users we know we have, the better our case for getting funding to continue the work. project supervised by Prof. Michael B. Feldman Department of Electrical Engineering and Computer Science The George Washington University Washington, DC 20052 202-994-5253 (voice) 202-994-5294 (fax) mfeldman@seas.gwu.edu authors: 1986 Charles Schoening DOS version of CoPascal 1987 Frederick C. Hathorn conversion of CoPascal to Ada 1988 Stuart Cramer and Jay Kurtz refinement of tasking model 1989 Arthur V. Lopes window-oriented monitoring for IBM-PC 1990 Manuel A. Perez Macintosh version 1990 Arthur V. Lopes integrated environment for IBM-PC 1991 Amr El-Kadi user-selectable task scheduling HOW TO RUN THE PC PROGRAM ========================= To run SMALLAda PC you will need the following files: SMALLADA.EXE -- Small Ada integrated environment SMADA-IN.AVL -- Small Ada interpreter pseudo code; it can be tunned -- to suit any level of interpreter monitoring Type SMALLADA RACE . You will be placed in the editor mode. To compile and run the race program follow these steps: press F10. A menu will appear on the top of your screen. Press C, for compiler. Then a sub menu will be displayed. Press E (or . This will start the compilation process. If the program is correctly compiled then it will run thereafter. If an error is found an error message will be issued and after pressing any key the editor will be activated. The cursor will be at the line where the error was found. The program will run much faster if you disable the window-oriented execution monitoring by pressing , which toggles monitoring on and off. If monitoring is enabled, pressing toggles step-by-step execution on and off. With stepped execution on, pressing the space bar moves through each source line. You can create and compile your own Ada programs, but we make no promises about which parts of the language will be handled correctly. We assure you that there is no support for packages, generics, exceptions, access types and dynamic data structures. Some of this may change in future versions, but we make no commitment to support full Ada. And don't be surprised if the compiler hangs here and there: error repair is in a rather primitive state. If the compiler actually finds your errors, it will display the messsages in a window. THE SmallAda IBM-PC RUNTIME ENVIRONMENT ======================================= The runtime monitoring of tasking is really the whole point of this project. Each task is given a window. If there are more than five tasks some tasks will share a physical window. To obtain help on the runtime environment press F1 while a program is running. In summary, you can control the overall execution speed of the interpreter (to "slow down the action"), and exert some influence on the open windows. There is no magic in all this runtime monitoring: it all takes machine cycles. If you wish your program to run faster, remove all the monitoring windows (by pressing INS while they are open). You can also step through execution, source line by source line, by pressing INS while windows are open. Then pressing the space bar steps through one source line. THE SmallAda EDITOR =================== The editor was adapted from the Turbo Pascal Editor Toobox Version 4.0. The editor works much like the Wordstar editor. Next some of its basic options are shown. Function Keystrokes BASIC MOVEVMENT COMMANDS: Character left: left arrow or ^S (^ ==> Control) Character right right arrow or ^D Word left ^left arrow or ^A Word right ^right arrow or ^F Line up up arrow or ^E Line down down arrow or ^X Scroll up ^W Scroll down ^Z Page up PgUp or ^R Page down PGDn or ^C Beginning of Line Home or ^Q S End of Line End or ^Q D Tab Tab or ^I Backward tab Shift tab BASIC EDITING COMMANDS: New line Enter or ^M Insert line ^N Delete current character Del or ^G Delete character left Backspace or ^H Delete word ^T Delete to end of line ^Q Y Activate menus F10 Abort command ^U THE SmallAda TASKING MODEL =========================== We have tried to be reasonably faithful to Ada tasking. The scheduler is designed to show some of the important issues of concurrent programming, therefore time-slicing is implemented, and the length of the slice is randomly determined. Also, at each rescheduling point the next task to be scheduled is selected randomly. This is to give a reasonable model of nondeterministic (unpredictable) behavior, and serves to highlight the need for mutual exclusion. The dining philosophers examples on the disk, taken together, show this point rather well. Current incompletenesses in the tasking model: only named tasks (i.e. no task types), no dynamically created tasks. We also don't support nested task declarations; all tasks must be declared in MAIN's declarative section. The "select" statement is functional including the "terminate" alternative; checking for termination is tricky in Ada and you might find that some select structures with terminate alternatives deadlock or don't work at all. In general, be gentle with the select statement; try to avoid tricky or pathological code, which will surely choke the compiler or interpreter! You will also discover quickly that though the "delay" statement is functional, the elapsed time to expiration of the delay is considerably more than was requested in the delay statement. As it happens, this is correct Ada, as the standard says only that a task will be suspended for _at least_ the amount of time requested. This is to take account of the likelihood that contention will make it impossible for a task to take immediate control when it wakes up from a nap. Indeed, we think that the sometimes too-long delays may be due to the interference in the interpreter caused by all the references to the user interface for monitoring purposes. The relationship of the delay to reality depends upon your PC's speed as well. We are working on this problem but do not yet see an obvious solution. So take the time given in a delay statement with a grain of salt, please. If you have tasks in finite (counting) loops, if they complete but there are other tasks with infinite loops that can never terminate, the system may detect no activity and report a deadlock state. The current version now supports user-selected task scheduling. Pressing during execution opens a window giving scheduler options. THE SmallAda SUPPORT PACKAGE (SMALL_SP.PKG) =========================================== A large number of "intrinsic" library subroutines are included in a pseudo-package called SMALL_SP.PKG. It is not necessary (or proper) to compile this package; it is included in the environment. It is necessary to begin each program with a context clause WITH SMALL_SP; USE SMALL_SP; to give the effect of writing genuine Ada. A specification for this package is included in the distribution; it includes I/O routines, math functions, and the like. This is not really good Ada-like decomposition, and we will change it in subsequent versions of the system. Meanwhile, use the package spec as a guide to all the intrinsic routines. Note especially that the formatting parameters supplied to the I/O procedures are more Pascal-like than Ada-like. This will change later to look more like standard TEXT_IO. THE DEMONSTRATION PROGRAMS ========================== We have supplied a set of what we hope will be interesting and instructive programs illustrating both the sequential aspects of the Ada subset and the tasking model. TEST1 through TEST6 can be thought of as "validation" programs testing specific features of the language; reading them can serve a useful purpose in understanding our subset. ATEST1 through ATEST4 demonstrate the differences in program behavior under different scheduling policies. Each program contains a block comment explaining its purpose in this demonstration. SHELLSORT is what its name implies: a standard implementation of Shell sort in which the state of the array is displayed on the screen as it is sorted; RACE is a tasking program which we have used with success in concurrent programming courses: three sort algorithms are activated as Ada tasks and run in parallel. 4TASKSEM shows the use of the semaphore primitives "exported" by the SMALL_SP pseudo-package. A semaphore SCREEN is declared and used to give mutual exclusion on the terminal screen. Attention: semaphores are NOT Ada primitives! SmallAda was originally constructed as a modification to the CoPascal system of Ben-Ari (as described in "Principles of Concurrent Programming", Prentice Hall 1982), and the semaphore primitives are still there from the system's last incarnation. To show how to do it in "real" Ada, we include the program 4TASKMON, in which a screen monitor task is declared. Finally, there are three versions of Dijkstra's legendary dining philosophers problem. SmallAda has a capacity limitation of around ten tasks. We are limited to four instead of the usual five philosophers, because four diners, four chopsticks, and MAIN add up to 9 tasks. EATCHAOS is very instructive: it demonstrates why it's nice to have monitors for mutual exclusion: without a monitor guarding the screen, the display becomes rather chaotic. EAT-SEM uses the SmallAda semaphore primitives; EAT-MON does the same thing but with a "genuine" Ada monitor. FINALLY ======= In case you are curious, the system is coded in Turbo Pascal with the Turbo Toolbox libraries used for the editor and environment. Please let us know about bugs; tell us what you're doing with the sytem. Good luck; have fun! Good luck; have fun! ================================================ FILE: doc/hac.txt ================================================ HAC - HAC Ada Compiler ====================== HAC is perhaps the first open-source (albeit very partial) Ada compiler (and virtual machine interpreter) fully programmed in Ada itself. Note: HAC was not written from scratch, but is based on a renovation of SmallAda, a system developped around 1990 and abandoned since then. Objectives ========== - Fun! - Have a simple, quick Ada compiler and execution tool. - Be useful for small Ada sandboxed prototypes. - Produce the smallest Hello-world executable! - Have a tool for script-like jobs (avoid long programming-compiling-binding-linking-running cycles). - Stay Ada-compatible (HAC programs can be compiled and run by other Ada compilers, through the compatibility package HAT). HAC will most probably never be a complete compiler. Warning & legal =============== There is NO WARRANTY in this software. Read copyright notice and license in hac_sys.ads . The license is the open-source license MIT. Getting started =============== Assuming you have the GNAT (*) compiler installed, do the following from a command line interpreter (please replace '\' by '/' on Unix-like platforms): gnatmake -P hac cd exm ..\hac gallery.adb If `gnatmake` doesn't work, try `gprbuild`. Alternatively, on Windows and with mouse only, you can go into the "exm" folder and double-click "e.cmd" . The program "gallery.adb" will run a bunch of demos that are located in the "exm" directory. You can test HAC on any other example of course (the "*.adb" files in the "exm" and "test" directories). As a bonus, you can build some examples with GNAT to compare the output. You can do it easily with the hac_exm.gpr project file. Since hac_exm.gpr is a text file, you can see there the progress (or the lack thereof) in the pieces of Ada code that are really working with HAC. See the "Limitations" section below as well. ___ (*) On Debian-based Linuxes like Ubuntu, GNAT is part of the standard packages. For other systems, you can get GNAT from AdaCore's Web site: https://www.adacore.com/community or from other sites providing GCC (the GNU Compiler Collection) with Ada support. Check http://www.getadanow.com/ for instance. Directories =========== src sources of HAC, plus the compatibility package HAT doc documentation exm examples exm/aoc Advent of Code solutions - also used for regression testing exm/pdf demos of Acrobat (tm) PDF documents produced by HAC demo demos of applications embedding HAC test testing (notably, the all_silent_tests.adb regression test suite) Key files in the main directory =============================== hac.gpr project file for building HAC with GNAT hac_objectada.prj equivalent project file with ObjectAda64 for Windows save.hac backup program save_modif.hac backup program Documentation ============= hac.txt this file HAC Ada Compiler User Manual.pdf an 80+ pages user manual; source here: https://github.com/sowebio/hac-doc hac_work.xls Excel workbook containing, notably, a bug list and a "to-do" list and a "done" (history) list Some design points ================== - HAC is a single-pass, recursive-descent Ada compiler which, in its simplest form, emits machine code on the fly. It means that there are no advanced optimizations available, such as common subexpression elimination, that are provided by compilers like GNAT; but, the compilation is very fast, which is very pleasant for some usages like prototyping and programming-for-fun. - Current targets are: - p-code (a virtual machine specially adapted for HAC) - "Semantics", a pseudo-target that is used for smart editors (for example, LEA). - AMD x64/Windows (currently, only an embryo that can do "Hello World" only) - HAC reads Ada sources from any stream. In addition to files, it is able to read from a Zip archive (plan is to have sets with many sources like libraries in Zip files, for instance), from an internet stream, from an editor buffer (see the LEA project), from a source stored in memory, etc. - HAC Ada source file naming follows the GNAT convention: "parent-child.ads" for specification and "parent-child.adb" for body. An exception for HAC is the main program, where the extension can be anything. We recommend using ".hac" for programs that are meant to be principally executed through HAC. That way you can associate the ".hac" extension with the "hac[.exe]" executable on your operating system or your file explorer. - One goal is to complement or challenge GNAT, for instance in terms of compilation speed, or object code compactness, or useability on certain targets or for certain purposes (like scripting jobs). - HAC could theoretically be also used for tuning run-time performance; this would require a completion of the code emission for other targets than p-code (HAC's virtual machine), including, perhaps, an intermediary target that builds a syntax tree. To-do list ========== The to-do list is located in the spreadsheet "To do", within the workbook "doc/hac_work.xls". Language subset =============== HAC supports a small subset of the Ada language. On the other hand, Ada is very large, so even a small subset could already fit your needs. There is a growing list of programs that are working (in the meaning: the compilation succeeds and the execution gives a correct output). They are located in the "exm" directory and subdirectories (except the "not_working" one), as well as in the "test" subdirectory. The available Ada language subset supported by HAC is so far, roughly, the "Pascal subset", plus tasking, plus packages, less pointers. From a different perspective, HAC supports Ada 83, less pointers, less generics, less unconstrained types, plus a few items from later Ada versions: 95, 2005, 2012 and 2022. Since each Ada version is compatible with previous ones, one can say simply that HAC is a subset of Ada 2022. - Recursion and nested subprograms are supported. - You can define your own data types: enumerations, records, arrays (and every combination of records and arrays). - Only constrained types are supported (unconstrained types are Ada-only types and not in the "Pascal subset" anyway). - The "String" type (unconstrained) is implemented in a very limited way. So far you can only define fixed-sized constants, variables, types, record fields with it, like: Digitz : constant String (1..10) := "0123456789"; ... output them with Put, Put_Line, do comparisons and concatenations with expressions of the VString variable-length string type. For general string manipulation, the most practical way with the current versions of HAC is to use the VString's. - There are no pointers (access types) and nor heap allocation, but you will be surprised how far you can go without pointers! - Subprograms names cannot be overloaded, although some *predefined* subprograms, including operators, of the Standard or the HAT package, are overloaded many times, like "Put", "Get", "+", "&", ... - Programmable modularity (packages or subprograms that you can "with") is implemented. See exm/unit_a.adb for an example with subprograms as modules. See exm/prc.adb for an example with packages as modules. See exm/pkg_demo.adb for a larger example with packages. - Generics are not yet implemented. - Tasks are implemented, but not fully working yet (they used to work on SmallAda). See in exm/tasking for what is working and exm/not_working for what is not. - Small parts of the standard Ada library are available indirectly through the HAT, Interfaces and Standard built-in packages. You can see the currently available HAT items in its specification, src/hat.ads . A systematic testing is done in the "test" directory, via the all_silent_tests.adb test suite. Thanks ====== - The authors of SmallAda (list below) for making their work open-source. - Stphane Rivire, for extensive testing, contributions, suggestions, remarks, feedbacks and the User Manual. - J-P. Rosen for the free AdaControl tool ( https://www.adalog.fr/en/adacontrol.html , https://sourceforge.net/projects/adacontrol/ ) which was very helpful detecting global variables stemming from SmallAda's code. - Pierre van de Laar for running his Renaissance-Ada tool ( https://github.com/TNO/Renaissance-Ada ) on HAC's sources. - AdaCore for providing their excellent Ada compiler for free: https://www.adacore.com/community (via the Alire crate system) https://www.adacore.com/download (versions till 2021, standalone) HAC on the Web ============== Home page: http://hacadacompiler.sf.net/ Project page: http://sf.net/projects/hacadacompiler/ Mirror: https://github.com/zertovitch/hac Alire crate: https://alire.ada.dev/crates/hac History of HAC ============== - Now: HAC is being made more and more usable for real applications, with Ada compatibility, modularity, a library with I/O, system subprograms,... - 2020: Presentation at FOSDEM's Ada Developer Room: https://fosdem.org/2020/schedule/event/ada_hac/ . Starting a bit more serious testing and code cleanup. - 2013: January 24th: Day One of HAC: Hello World, Fibonacci and other tests work! - 2009: A bit further trying to make the translation of SmallAda sources succeed (P2Ada was improved on the way, for WITH statements and UCSD/Turbo/Delphi-style modularity)... - 1999: Automatic translation of Mac Pascal SmallAda sources to Ada, using P2Ada. - 1989: SmallAda is derived from CoPascal; works only within two very system-dependent environments (a Mac GUI, a DOS GUI); two similar source sets in two Pascal dialects (Mac Pascal, Turbo Pascal). - 1986: CoPascal (Schoening). - 1975: Pascal-S (Wirth) Reference: PASCAL-S, a subset and its implementation https://doi.org/10.3929/ethz-a-000147073 Authors of SmallAda (in Pascal): 1990 Manuel A. Perez Macintosh version 1990 Arthur V. Lopes integrated environment for IBM-PC 1989 Arthur V. Lopes window-oriented monitoring for IBM-PC 1988 Stuart Cramer and Jay Kurtz refinement of tasking model 1987 Frederick C. Hathorn conversion of CoPascal Author of CoPascal (derived from Niklaus Wirth's Pascal-S) 1986 Charles Schoening You can find the SmallAda sources and examples in the "archeology" folder. The Turbo Pascal sources files are smaller than the Mac Pascal ones, probably because of the memory constraints of the 16-bit DOS system. So the Turbo Pascal sources are especially cryptic and sparsely commented, full with magic numbers and 1-letter variables, many of them global - ouch! ================================================ FILE: exm/ackermann.adb ================================================ -- https://en.wikipedia.org/wiki/Ackermann_function -- https://rosettacode.org/wiki/Ackermann_function#Ada with HAT; procedure Ackermann is function A (M, N : Natural) return Positive is begin if M = 0 then return N + 1; elsif N = 0 then return A (M - 1, 1); else return A (M - 1, A (M, N - 1)); end if; end A; use HAT; begin Put_Line ("Ackermann function"); -- With M >= 4, numbers and recursions become HUGE. -- See table of values in the Wikipedia page! for M in 0 .. 3 loop for N in 0 .. 6 loop Put (A (M, N), 6); end loop; New_Line; end loop; end Ackermann; ================================================ FILE: exm/anti_primes.adb ================================================ -- https://rosettacode.org/wiki/Anti-primes#Ada -- -- The anti-primes (or highly composite numbers, sequence A002182 in -- the OEIS) are the natural numbers with more factors than any -- smaller than itself. with HAT; use HAT; procedure Anti_Primes is function Count_Divisors (n : Integer) return Integer is count : Integer := 1; begin for i in 1 .. n / 2 loop if n mod i = 0 then count := count + 1; end if; end loop; return count; end Count_Divisors; stop : constant := 15; results, div_count : array (1 .. stop) of Integer; procedure Search is candidate : Integer := 1; divisors : Integer; max_divisors : Integer := 0; begin for i in 1 .. stop loop loop divisors := Count_Divisors (candidate); if max_divisors < divisors then results (i) := candidate; div_count (i) := divisors; max_divisors := divisors; exit; end if; candidate := candidate + 1; end loop; end loop; end Search; begin Put_Line (+"The first " & stop & " anti-primes are:"); Search; -- for i in 1 .. stop loop Put (results (i), 5); Put (" has"); Put (div_count (i), 3); Put_Line (" divisors."); end loop; end Anti_Primes; ================================================ FILE: exm/aoc/2020/aoc_2020.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the Advent of Code 2020 examples. -- Some work with both HAC and "full Ada" compilers, -- some (titled *_full_ada.adb) work only with "full Ada". -- project AoC_2020 is for Source_Dirs use ( ".", "../../../src" -- GNAT's access to the HAT package. ); for Exec_Dir use "."; for Create_Missing_Dirs use "True"; type AoC_Build_Mode_Type is ("Debug", "Fast", "Style_Checks" ); AoC_Build_Mode : AoC_Build_Mode_Type := external ("AoC_Build_Mode", "Debug"); for Main use ( "aoc_2020_25.adb", "aoc_2020_24.adb", "aoc_2020_23.adb", "aoc_2020_23_simple_array.adb", "aoc_2020_22.adb", "aoc_2020_22_full_ada.adb", "aoc_2020_21_full_ada.adb", "aoc_2020_21_full_ada_preproc.adb", "aoc_2020_20.adb", "aoc_2020_19_full_ada.adb", "aoc_2020_18_full_ada.adb", "aoc_2020_17.adb", "aoc_2020_16.adb", "aoc_2020_15.adb", "aoc_2020_15_full_ada.adb", "aoc_2020_15_full_ada_hashed_maps.adb", "aoc_2020_14_full_ada.adb", "aoc_2020_13.adb", "aoc_2020_12.adb", "aoc_2020_11.adb", "aoc_2020_11_full_ada.adb", "aoc_2020_10.adb", "aoc_2020_09.adb", "aoc_2020_08.adb", "aoc_2020_07.adb", "aoc_2020_07_full_ada.adb", "aoc_2020_07_full_ada_vectors_2x.adb", "aoc_2020_06.adb", "aoc_2020_06_full_ada.adb", "aoc_2020_06_full_ada_using_hat.adb", "aoc_2020_05.adb", "aoc_2020_04.adb", "aoc_2020_04_b_full_ada.adb", "aoc_2020_03.adb", "aoc_2020_02.adb" ); case AoC_Build_Mode is when "Debug" | "Style_Checks" => for Object_Dir use "obj_debug"; when "Fast" => for Object_Dir use "obj_fast"; end case; Common_Options := ( "-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwCijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ" -- Don't quit, write ali/tree file even if compile errors ); Fast_Options := ( "-O3", "-funroll-loops", "-fpeel-loops", "-funswitch-loops", "-ftracer", "-fweb", "-frename-registers", "-ftree-vectorize", "-fipa-cp-clone", "-fgcse-after-reload" ); Debug_Options := ( -- "-gnateV", -- Validity check for parameters, GNAT > 4.6, redundant with -gnatVim ? "-gnatVa", -- Turn on all validity checking options "-gnato", -- Enable overflow checking in STRICT (-gnato1) mode "-g", "-fno-inline", "-fstack-check" ); package Compiler is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Options & Debug_Options ; when "Style_Checks" => for Default_Switches ("ada") use Common_Options & Debug_Options & ("-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyO", -- Style: check that overriding subprograms are explicitly marked as such. "-gnatyx", -- Style: check x:no extra parens "-gnatye", -- Style: check e:end/exit labels present "-gnaty2", -- Style: check indentation "-gnatytc"); -- Style: check t:token separation rules, c:comment format (two spaces) when "Fast" => for Default_Switches ("ada") use Common_Options & Fast_Options & ("-gnatpn", "-ffunction-sections"); end case; end Compiler; package Linker is case AoC_Build_Mode is when "Debug" | "Style_Checks" => for Default_Switches ("ada") use ("-g"); when "Fast" => for Default_Switches ("ada") use ("-g", "-s", "-Wl,--gc-sections"); end case; end Linker; package Binder is -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks for Default_Switches ("ada") use ("-Es"); end Binder; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-j0"); end Builder; end AoC_2020; ================================================ FILE: exm/aoc/2020/aoc_2020_02.adb ================================================ -- Solution to Advent of Code 2020, Day 2 ------------------------------------------ -- Password Philosophy -- -- https://adventofcode.com/2020/day/2 -- -- Part One ------------ -- Each line gives the password policy and then the password. -- The password policy indicates the lowest and highest number of times -- a given letter must appear for the password to be valid. -- For example, 1-3 a means that the password must contain 'a' -- at least 1 time and at most 3 times. -- -- 1-3 a: abcde -> valid (1 time 'a') -- 1-3 b: cdefg -> invalid (0 times 'b') -- 2-9 c: ccccccccc -> valid (9 times 'c') -- -- Part Two ------------ -- Each policy actually describes two positions in the password, where 1 -- means the first character, 2 means the second character, and so on. -- Exactly one of these two positions must contain the given letter. -- -- 1-3 a: abcde is valid : position 1 contains 'a' and position 3 does not. -- 1-3 b: cdefg is invalid : neither position 1 nor position 3 contains 'b'. -- 2-9 c: ccccccccc is invalid : both position 2 and position 9 contain 'c'. -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_02 is s : VString; f : File_Type; c, sep1, sep2, sep3, sep4 : Character; i, n, valid, arg1, arg2 : Integer; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := False; begin for part in 1 .. 2 loop Open (f, "aoc_2020_02.txt"); valid := 0; while not End_Of_File (f) loop Get (f, arg1); Get (f, sep1); Get (f, arg2); Get (f, sep2); Get (f, c); Get (f, sep3); Get (f, sep4); Get_Line (f, s); i := 1; n := 0; while i <= Length (s) loop if part = 1 then if c = Element (s, i) then n := n + 1; end if; else if c = Element (s, i) and (i = arg1 or i = arg2) then n := n + 1; end if; end if; i := i + 1; end loop; if (part = 1 and n >= arg1 and n <= arg2) or (part = 2 and n = 1) then valid := valid + 1; elsif verbose then Put_Line (+"Invalid: " & arg1 & ',' & arg2 & ',' & c & " --> " & n & " |----| " & s); end if; end loop; Close (f); if compiler_test_mode then if valid /= Integer_Value (Argument (part)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Valid passwords (part " & part & "): " & valid); end if; end loop; -- Part 1: validated by AoC: 607 -- Part 2: validated by AoC: 321 end AoC_2020_02; ================================================ FILE: exm/aoc/2020/aoc_2020_02.txt ================================================ 1-4 m: mrfmmbjxr 5-16 b: bbbbhbbbbpbxbbbcb 7-8 x: qxrxmxccxxx 9-11 k: kkkkkkktmkhk 8-12 g: sgwvdxzhkvndv 6-9 v: zvmvvmvvvd 8-19 f: ffffsplmfflffhtfrfj 5-16 p: pppppppppspppjpcp 2-3 w: wwmw 7-19 j: jjjjjjjjjjjjjjjjjjvj 5-9 q: wqzqqqqqq 14-15 g: gggggggggglggfgg 4-6 p: tppzkppdt 11-14 p: vppgpktpppppptpppqp 5-9 f: bfflffrfgf 7-9 p: ppppptbzn 1-3 l: lllvn 2-4 g: qvcdg 1-3 m: wsmdv 1-5 v: vvvvvvvv 10-14 l: lckqlgjllltlwbl 3-4 t: bsttftltjhbqbgtm 15-17 j: jjzjjjjjhjjjjjjpzjj 2-3 t: thtt 6-17 f: ffwkwzjtjktvsfmfhvsf 3-5 b: rqxbb 4-7 m: nbcmcwmmxrxqvtjfmm 1-2 v: gzvvvv 1-3 w: hkwhv 7-8 p: pppppppp 3-4 h: hhnwh 2-4 t: ttrtjtththkr 3-4 w: wwww 4-6 s: xsntgrftmpx 4-7 s: ssskssmsbs 10-15 m: bmmrbmmmmlmmmmmm 12-13 w: wqpwdmwllnjwx 5-14 n: nnnnlnnnnnnnnmnn 5-6 k: kktkfczk 5-7 r: nrdrtrvr 4-6 c: ccqchcc 2-9 l: fnldtfnbxjlvnlsnjhml 1-13 d: dlchvkccnwrcc 5-7 j: jjjjjjj 3-5 z: zzzzz 6-12 f: ffffflvmfhfx 8-10 w: wwwwwwwwww 3-4 r: rrbtr 3-11 b: bbbrbbvphbxbqk 16-17 n: nqhknnnnsnnnnnnnnnb 18-20 k: kkkkkkkkkkkkkkkkkhtj 3-15 r: ktvzqbmbrvczprfcw 9-11 q: qnqqdqqqgrrqsqq 3-5 p: pvppp 7-11 m: mfcdmmxmmmp 7-8 t: ttttktnt 5-6 b: bbpbbbv 14-16 z: zzzzzzzzzrzzblzw 11-12 j: jkjjjkjjjjjjgj 7-9 q: qqqqqqqqqq 10-11 f: cfffffffffff 4-6 c: nccccc 7-8 r: gmdlqfpwmrr 6-8 v: nvvpdnjx 8-12 x: xxlxxbbxxxxx 8-10 s: ssxssssssss 5-12 z: zhzdfzgdzzhzlz 11-12 k: qbkhvqjpqzfq 2-11 w: wwmlttwjflwdjcpclww 2-16 w: twkkmcrxmvjtwxlwsksf 6-8 s: sssfxbskvs 5-6 s: ssnsxsbs 10-19 l: ndzmdxqlnllxsbbwvsl 2-4 g: gggg 5-10 x: zxxxsxxxxxxxsxx 7-15 f: ffbrbdtzvdffktxfm 7-8 m: xmkmmmmmtmm 9-13 s: hksrdhzlsdmps 15-17 b: bbbbbbbrbbbbbbbrbb 3-5 x: xxxxxxx 2-6 t: wtltztnct 3-15 v: vvwvvvvvhvvvbwwvmdvr 12-14 p: ppphsppppppbphp 8-9 t: ttttvttttttt 2-3 c: cchvj 8-9 z: vzzzzzzgl 11-12 q: qqmqqqqqqqsnqqqqqqq 12-13 d: dddddddddddmd 8-9 t: wttttttqt 7-8 p: ppppvvcw 4-5 g: gncgj 12-13 s: sssssssssssmw 7-9 f: pswpnjftf 11-16 p: ppppnpkpkzppcpzbppp 1-12 q: ksqrqpqnqmqxqb 2-10 l: lllllllllll 17-18 z: zzzzzzzzzzzxzzzzzz 11-12 g: qggbjgggggssgggrk 3-4 s: bpss 6-8 v: vwvvvrvvv 3-4 t: tglktt 4-12 l: kvrnzqslwrdkfll 12-16 b: fbbbbbnbbvbbbbbcbbb 5-6 t: ttttzz 5-8 w: sqwhwwxw 8-9 z: zzzvztzrzzzz 3-6 l: llvdlt 7-8 r: mrcvnrrr 10-11 k: kkkkkkkkkmc 1-3 n: nnnmn 4-16 c: dqlcbclcrxkkszvcv 9-10 g: fxssmlmgbh 5-6 p: nwpfpp 3-7 w: cwhgrfshdwhwwll 14-16 l: llllllllllllllpll 3-4 f: ffff 4-9 d: dcdddxzvmrd 4-11 w: jwwnwwwwwvx 3-4 t: ttvc 4-17 r: rrsrrrrrrrrrbtrrrr 8-9 x: wqxxxcfdx 6-8 d: qgddwddtdddlc 12-13 v: vvjvvvvvzvvtvv 3-4 g: sghxg 3-4 b: ckbbmprfbbmzgqtkbw 5-6 x: xxxxxv 10-13 f: zpfffbfchxfffffjff 5-6 f: ffffwf 12-19 l: mlllllplllldllnsllql 4-5 v: vvvvp 5-8 w: vjwvghggwww 1-3 n: lnnn 16-18 p: ppppppvpppppwppppppp 15-18 z: zzzzzzzzzzzzzzjzzg 4-6 b: bbmbbb 5-7 z: wzlwzmzzzzzzzzzzzwz 8-12 p: gppmpppvppkzpcnpb 16-19 h: hhbhhhhhhhhhhhlnhhw 2-3 n: nnnn 3-10 m: mmntfkdjftmtmmbm 3-5 j: jjjjw 4-6 z: zjnzzzdzz 1-7 s: zsvsssf 6-7 v: vtvvvcg 3-12 f: qsrtmnxkvlcmt 5-11 q: mqgqqqqqrpch 5-9 g: msxkggnggg 3-8 v: vvvvhvjvdvxtr 4-6 k: jcklxdhkwhsqhq 6-7 x: vppxbhcjzxdqx 2-3 n: ntrg 7-8 g: gggwgjdhg 1-3 d: dddd 14-18 l: llllllllwlllxllllllz 8-19 g: ggggghggkhgrtzcgrrk 7-14 q: phzxvmbxxfsfwr 8-14 r: hbjmdrhnpxnwgz 15-17 d: dddddpddddldddtdgddd 6-7 k: kkkkkgkkq 2-12 w: wwzwwwwwwwwww 5-8 q: qqqqqqqzqqwqqzqcq 5-6 z: czzzrz 14-15 b: bbbrzhbbbbnxbgbb 12-13 d: dgddddddddtvddddvbz 3-5 v: vvvvv 13-16 q: qqqqqvzwqqqqqqqq 2-3 n: jpznnwfpchs 7-10 w: jwwpwkwwwpw 6-7 b: bbcnbcjxbbb 14-17 w: wqtwwwwwnwcwwbsww 3-14 w: gwwwwwwwhwwnxwwwww 4-9 w: mwllcfjfwwwjp 9-12 n: nnnnnnnhnwjnn 2-4 j: jjjjj 3-6 t: mrmttccttqt 16-17 p: ppmjpgptzgbppphfbp 12-17 v: vvvvvvvvvvvvvfvvvv 13-15 x: xxxxxxxxxxxxxxgx 2-4 d: dddddddd 2-5 t: ttmvt 13-14 j: jjjjjjjjjjjjtj 3-5 r: ggmrdf 7-8 f: ffdfflszfsfffqff 10-11 t: ttpttttttrgtt 8-12 j: jjjjqdhzjhjdj 19-20 z: zbzzzzzzzzzzzzzzzzrq 7-11 b: bbbbbhbbbxbbb 4-9 p: gzmkkbtpkzpgthklpq 2-5 b: bbbbxgb 4-13 k: kkkkkkzktckkkwkjkk 10-12 q: vrxznfqqnqgq 15-16 m: mmmmkmmmmmmmmmmmm 15-18 h: hlhhvhchthhhhtphhh 2-3 m: mftzmc 6-11 s: ksssssssssszs 5-6 q: qqqpqkq 7-8 n: nnfnnnnpn 6-8 c: chfcllrvxcnnjhtc 6-8 k: kkkkkxlk 2-4 s: tsspb 9-12 q: qqqqqqqqqqqqqq 17-20 h: hhhhhhhhhhhhhhhhhhhh 6-13 r: rrrrrgrrrrrrn 4-8 f: fffrfffz 13-14 n: nbnnnngnnnnnnpz 8-11 f: fvffsfqftcffff 3-5 w: vwhxz 8-10 x: nmxxknlptx 3-4 p: pppt 17-18 v: vvvvvvhkvvvvvnvvjlvv 10-15 z: twnsdkmgpvzfmzg 3-5 n: njnjnkghp 10-12 q: qvqqqqqqqqqq 6-7 r: rrrrrrrr 3-4 t: qltt 2-16 f: gffflcvtpfkfcjfrjvfs 3-5 s: swssp 11-13 l: lrpllllllvtslwllllld 1-3 n: nnnn 3-5 g: jjggnvg 4-5 b: bvbbb 13-15 l: llvllllllllllnll 5-6 j: hjjjjfsj 3-4 b: bkfbnb 5-8 z: zdzzzzzzzrzzz 3-4 r: rrrx 2-12 c: mczhvchkmjdrjh 12-16 x: sjxbcgdqtpfxflsxx 2-4 c: tcxf 4-5 w: kwjww 1-2 r: rrrwzc 4-7 d: ddddddkdd 5-6 q: qqqqqp 13-16 l: flljlllvnzlllllclldl 3-6 j: jjjpjj 3-4 g: gxgg 10-11 n: nnnnnnnnnnn 2-5 j: ztchj 4-6 j: pjzzrmjvhcxn 4-11 c: jchcccgccckc 11-12 d: dddddddddddd 6-7 n: nznnnnnntnnnnzpjfjnn 8-9 k: kbkkkkkkk 13-18 x: xbxxmxqxxxmxkxsxxxx 7-16 r: rrrrrrzrrrrrrrjmrrr 3-5 h: hhqhd 1-2 b: bbmb 2-3 n: rlnntn 2-8 q: qnfqnqhx 2-5 b: bjbbh 5-11 t: twtjnpttqtvtttptt 16-17 w: wtmwwhxtgwrrswwfblll 8-16 g: ggggghshggdggggcpwg 1-3 l: lsllzl 11-13 n: nnnvncnnmvnqnnnnn 6-7 s: ssqssss 10-18 t: tttnmjxttjttttttdzt 4-10 n: nkvncgtdpz 16-18 p: cphtrgffcpphfspxppgp 2-6 k: kkhgkskkm 6-20 r: fhrwtrzwrddfrndnrlgr 2-8 w: lkwnccgw 6-10 x: lxxxxxxgxwxxxrxqxx 4-9 q: tqtpgqjzdmqfq 9-12 k: kkkkkqbkkckkkjkql 5-9 r: rrrrrrrhcr 17-20 h: hhshshhhhhhhshhhbhhq 7-9 s: dngddfsss 12-13 q: qqqqqqqqqqqcq 2-6 v: vqtvvvv 8-10 c: cccfcncccccc 14-15 m: mmmmmmmmmmmmmmdm 7-14 s: ssslssfdssflvvsj 2-5 z: wcllj 2-11 n: cvnrlftcjct 8-16 k: krzkfbkkqkhnsjkjgkk 2-7 q: mvhvqnzdjw 5-8 l: lgbnlnclkllll 4-12 l: llllmllrlgllrklnlrbt 7-10 j: jjjjjjnjjcjsj 1-2 k: dgwmgsn 2-5 z: zjmxc 6-7 c: ccccccccc 14-17 k: bkkkkkkkkkkkndkkkk 2-4 x: xxjxtxbq 7-9 w: drjcfwzwwwfwwfzxww 4-5 p: pppwc 4-5 r: rrrvm 1-8 r: qrrrmrrrrr 16-18 l: llllllllldllltlklk 1-11 p: pwcpppbppppppp 5-19 w: wwwwwwwwwwwwwwwcwww 17-18 k: kkkkkwkkkkkkkkkkkxk 12-15 f: fsffffffflfqgfx 6-13 d: zddpdvddrvrdxq 1-10 f: ffffffrfkb 13-14 x: xxxxxxxxxxxxxxx 16-20 j: jjjjjjjdwjjfjjjjjjdj 8-11 r: rrrrrrrrrrrr 15-16 x: dxjxxxdxxxxxxxxxwxx 3-9 m: mjhqdgkmzmsmtdmhfn 2-7 k: kkkhwgtxlkmkqkk 11-15 m: mmgmmmmnsjmmlmmm 1-2 v: wvvk 8-14 s: zssssssssssssts 3-4 z: ztbzzr 4-10 x: xxkmqxxxxx 3-5 p: pkppppppppzpp 3-15 q: qpqmkqfqqlqqdfqtkqq 16-17 d: ddddddzbxcdddcddq 4-5 s: nqssf 4-5 s: sssbks 4-5 s: tsjlhsbsmt 1-5 z: zzzbztzf 1-4 l: pvsgtvt 3-6 b: bbbjbb 2-4 d: wkdvd 16-18 w: wwwwwwwrwwwwwwwzwkw 15-17 t: tqttjttttttttvtttt 5-9 q: qcqqqqdtqq 8-11 s: sssssssfssssssssssss 5-6 x: xxxvcpbxr 13-15 d: ddwdtctnjdcdpch 5-6 z: zzzwzzzq 3-7 v: bsphcnvwvtvphdp 3-4 q: vhcprqqgdmlfpwqqw 11-18 b: bfbbbfbbbbvhwbbbzlb 12-15 c: cccccccccccccqfcc 4-10 j: jjjjjjjjjjjw 8-14 s: ssssssspmssssssssms 6-15 b: jxnbdvxbbbcbrsbxrs 10-12 s: ssssjsssssfs 8-12 f: ffffdfkqflfpf 8-9 w: wwwwwwwwz 7-10 z: fzzlzzbtmthzzzz 2-3 k: kqzzb 11-12 s: ssssssssssls 16-17 r: rrrrhrrrrrrrrrrnr 3-11 b: czpbpbzswgcddm 4-8 z: cnzztzgzqz 18-19 m: mjmmmmmmmmmmmmmmmpk 10-13 q: gqqqqqqsxqqqqdtqkq 10-11 x: nxmbxxxrgpmxxxfnxxxz 2-5 x: xbxzrxd 9-14 l: llllpljlllfllwv 1-2 m: mmmmmm 1-3 b: fblbbfbbbbbtbbgbbb 3-4 g: gnnccg 8-9 f: fffffffkffff 5-6 r: rrrrhf 7-8 l: lwlwllllllctl 5-7 j: jrjjwgjvkkncnjbqc 3-4 b: bbsbb 4-13 c: jmcczvkbxccdf 4-5 g: wgrgg 7-8 d: dgddddzh 3-8 h: hhbhhhhhhhh 15-16 l: llldllllllldlllllll 11-15 r: rrgrrrrrrrnrrgxr 10-11 l: lllllllllll 4-5 x: xfdbjsmbbcxdphvlfkxr 9-12 m: rqmnmrmhcmmms 3-8 b: tzsnnndnbwgbskbb 4-10 v: vvkvvdrvwvc 9-11 j: jjjdjjjjjsj 6-11 b: hbbmbbbbbbjbtrbbbz 13-16 v: vvpvvvbvcvvvvvvvv 11-14 j: jjjjjjljjjtjjmj 7-11 v: cvdglnvjxkvvgptxvp 1-6 t: ttjqtttzt 7-10 f: ffwpzfxjfgffzf 4-7 d: dddgddp 4-19 n: mjbdzqxhtfbnbfxrpgnh 6-13 d: ddddddddddddd 2-4 t: rhkd 5-9 c: ccrcxzjdzccx 3-4 j: fwjj 15-19 q: qqqtxqqqqqqqqqqqqqqq 1-11 c: gcccccmccctcc 3-5 d: dxhhdr 8-12 k: pkvrkkkvkkmbkcxjwktk 9-11 p: ppnpppppxppp 11-12 p: dppcsppppppqppp 7-8 b: bbbbbbmbqp 7-8 c: cbccccccc 8-9 b: bbbbbbbcrbb 2-6 z: gzlnpzpkhjwwqtswcrz 5-6 d: dddsdkd 1-5 w: dxwkgwwwwwwmwwwww 4-7 q: qqqnwqlqrqdcqpq 6-9 m: lmmmdmmvmmmm 7-8 h: hhhghhxh 2-3 j: jjjj 1-4 r: rrrw 4-7 m: mmjmmrm 4-5 j: vljjrj 19-20 j: jjjjjtjjjjjjjjjjjjgx 2-6 h: xhltfh 5-11 s: ssssjsssssss 3-4 b: bbbb 1-5 g: chgmtgnn 6-7 j: jjjjjjz 3-8 c: cccccrccccc 3-17 s: sslstssssssssspsgs 17-18 x: bxxxxxxxqxxxxxxxkwxx 9-10 q: qfqqzqqqsddqqqqqqq 6-10 k: kmkkkxvqkrk 5-9 f: kffffffffcdfffffplf 5-6 r: rrrrrz 2-5 d: hdgzt 7-10 k: zkrllwkkkjrkqfkkk 9-11 b: bbrkbbbbcbqqb 8-12 g: gfgkgggggggggggggg 12-14 s: sssjsspstlvlsrsssss 4-8 g: pqgzcgvgflgntlp 13-14 j: jjjjjjjjjjjjjx 4-6 k: kkkmqpk 3-5 j: sjjbjlvjjvjr 2-9 c: ckccjxzcrcctbfn 10-12 n: hvnnnnxnntnlnn 11-15 m: mmrmmmdmmmlmmmjqm 6-8 p: qpzrrpcpbxg 5-8 w: xwdzcgclxwsvfwtwbxnw 3-8 q: qzqzhlzc 2-3 v: hvvvvltft 5-12 s: tgvsswttkwfssnsqjsxk 5-17 b: bbbbbbbbbbbrbcbbbhb 3-6 p: ppjpzw 3-5 k: kkxvkswk 4-8 v: vbvrvxvgrvvwwvvm 3-12 v: njvvgvdcjvvtvvcnvg 4-5 n: bnnnrn 8-9 l: jlvxdlpll 12-14 w: fkwwwwwwcwwjwmwc 1-4 q: wmqrzpqhj 4-7 t: tctsttlt 13-14 h: hhhhhhhhhhhhhf 2-3 j: jmjjjjj 5-6 v: vvvvlv 5-13 v: fnxvvvvvnvqvvvvvws 16-17 l: gllllllllllgwqlll 1-2 s: pnpfsqw 6-13 g: ntzqggvbnwxrgskg 5-12 k: krxmbxqbkhxlnvdxdkkq 14-18 d: ddddddddjdddbdddddd 4-7 z: zzzzxzzs 15-18 d: dddddddddbddddpddh 8-11 x: slxxxxxjkxxxrsdx 4-6 n: nnnfzzn 1-4 h: gslcmnhhfhvz 1-4 d: tddqds 2-3 c: fccp 2-5 k: mkqrknj 9-16 g: gpggdggwgwgwglggg 2-5 h: hhjds 4-5 b: zbnvld 6-14 m: mfqmnmqtdmmzmm 7-8 j: thvcsgjn 1-5 x: xwjdxdqjtc 4-17 r: fqbrqrnpslndrmjdhpjp 4-5 c: ccccw 5-6 v: vvvvdm 5-12 n: nnqzjntfnnnd 3-4 c: nccqlccq 1-10 p: nrvvzpppqpn 9-16 v: jvvrpvvvvvzvhhvvgz 12-13 s: sjsslsssfxxkrssstkss 1-3 t: vtwbh 5-16 q: sxxfrqhqtvzbzqwg 5-9 z: dnzlhzzzsdzz 15-16 d: pdddddjddpkdddtdddd 3-4 p: pplqppp 7-9 s: scsslshsqssw 2-3 v: vxvxv 8-9 w: wqwwwwwgshww 8-9 k: kkkkkkkkc 9-10 v: vhfvvnvvtvvb 1-12 z: zzzbzzzzzzzdzzzz 6-7 b: bbbbbwhb 12-13 z: zzzsvtlzzzzzz 1-3 s: pssssssxw 8-9 w: xwwwwwwdzw 1-4 x: xxkxxx 10-12 f: fffffffpffvffff 18-19 w: wwspwwzwwqcrwwhwwww 6-8 s: ssssstsks 5-6 j: jjcjgm 2-5 p: wprwpxbdkrfpmppqpd 8-18 n: nnnnnnnnnnnnnnnnnn 4-11 c: txncpqclrlc 2-10 f: ffcffftfffxrxf 1-4 t: ttttttt 4-9 f: zdpjffffbfbl 6-7 f: kfsffffffm 1-4 b: bbdn 6-12 k: kkhkkkkdqkbkjkkkl 3-4 n: kmnn 4-11 l: kllcllldllclll 7-19 w: pfwdwdnkblwzgkfnfmh 3-9 z: zzphzdnhqwlzzwzz 15-16 h: hhhhhhhnhhhhhhhd 1-4 l: vllll 2-13 l: hdhvgdrlltlmjptzq 1-3 p: njvpltppbkxpfpppp 1-2 j: kkjv 10-11 c: ccccccmcccjcc 5-8 v: tqvmvtwvzfczvvvvw 6-9 x: xxmxxxfxxxxx 1-10 z: zgzzztmdtkzzpxztbgpp 10-12 g: ggwzjgdsgbnggl 5-6 j: jvxjvjj 4-7 x: xnxxmgxxtjxxkj 13-14 d: ddddmddddddddd 12-15 c: cccccccccccnccc 16-17 n: nnnnnnnntnnnnngnmn 1-12 m: bzckgvmmbdcxtgtmb 4-7 l: ljllllljl 5-11 w: wzvzwwrkmtwh 11-13 l: lmtpwxlllhlgllwvqnp 6-10 f: fvgkffqvcfffdbfff 3-5 j: kbfjjj 1-2 h: hhztdpbttnc 8-10 b: bbbbjbbqkbbbd 1-13 c: hccvcxtcclpckzd 6-10 w: wwwwwtwwzrwwf 2-3 j: fjnnj 2-4 j: njtjjjxrjv 4-5 w: fwwzw 7-9 k: qbnkghdbqlz 2-9 s: dsdftlzsszlf 4-5 v: vvvvd 1-2 w: fbfwwb 4-7 t: tttttmt 3-10 h: hhhhnhhhskhh 3-8 w: qwswwswfl 1-3 p: pmpgpp 2-7 n: nmmgnssmtn 2-3 j: djvjgjp 6-13 x: jxxbxxgnxvbxx 6-10 v: vrvvvvvvdz 2-3 b: bbbbjrkwnc 1-2 h: fshnf 1-5 n: htsknrzqnntknfnjx 5-9 d: kkgtwrdjmxkzc 12-13 x: xxxxxxxxxxxxx 2-10 m: wmmmmmdpmmmmh 2-12 n: xttqcmfkvnlkzskjhmzn 6-9 m: mmmmmxmkp 10-16 m: gmmdqmjmflmmmmmcmmm 13-14 p: pprprppppspxfgnptppp 1-16 b: gcnbbnbbmsjxnbppcb 10-11 d: dkdddddfjmpvdddd 1-9 f: zlfwstnzp 14-15 n: nnnnnndnnnnnrnnvcndn 2-6 l: lvvldlzdzgdf 6-10 z: zzzzztzzzhzz 13-14 n: nnnnnnnnnnnngln 8-9 z: zjqztzztqzzbxzz 2-3 v: dwcv 4-6 m: kmmmkmm 5-9 g: wtgfgdmxkx 3-5 b: vbzbf 10-11 w: wwwwwwwvwwz 2-8 s: sztstsnssq 2-6 l: lldzcslxdwghmn 1-2 n: vmznndnnnbrhknjwzkzx 3-4 k: kknp 1-5 h: hhhhhhh 12-13 z: zzzzzlszzzzzxz 1-12 m: mtbspfpdgpznrsmvgq 11-13 q: qqqqkqnqhqrqrq 14-18 d: dtdrdddddddddxfddddd 1-6 q: bqqqqqgqqqq 1-7 c: dlmvcsztzpx 4-6 g: gmgggg 5-6 s: ssswsssgdghv 8-9 k: kkkkkkkgn 1-17 s: ssssssssssksssssss 4-5 b: qqtlsh 5-6 g: gggggg 2-11 r: drkpvrrlrtrvrjhpd 3-7 k: fkkhmddh 6-7 h: hhhwhnfph 3-4 p: ptppmwpnps 3-6 w: hwcshlrm 7-8 d: dtddqddzn 1-6 s: sslsbssbsg 12-15 n: tbnnjknnkwnnnnsnnnz 8-9 z: zzzzzzzzz 2-5 w: kjnwn 4-7 m: mmmtdjmmmmtl 4-7 h: dqfhzrqhfhntzhkhhdvb 3-5 g: zvflgg 5-12 s: lvsvqnvssgcx 11-19 p: pcppvppplpwppppjlps 5-19 p: gkpmfxlmppczdnhbqcw 5-17 b: mdzljsdvxdmbbbbddvrw 1-5 s: shpdss 2-5 t: btggtltvw 1-6 b: sbbbbbb 3-6 w: wwpsfkwnrrr 13-18 f: ffffwfffsfffwffffn 4-5 m: mpmmmxmmggvnb 5-6 z: pwsqhcztlf 8-11 d: ddddddddddlf 1-2 t: xttt 6-8 m: mmmpmvmmm 16-17 h: hhhhhhhhhhhhhhhrw 1-5 g: gpgpgg 3-7 p: gplrpzp 11-18 t: ftqnxttzttxtgttntrtt 10-11 z: zzzzzzdzzlgzzz 3-10 z: lzfzzzzszbzzztj 2-10 l: khdbddnxltnk 4-8 b: tbbcjsnbrbhfb 3-6 x: xgsxmn 9-13 t: ttttttttmtttt 7-11 l: fllllllzllmdshrll 18-19 g: hffqfwssgqpcnmddkcw 3-4 m: mmhvmc 1-3 w: vwnw 5-6 r: rrrrrb 2-4 j: rjqj 5-7 b: kgblcbbdrb 3-5 g: jgggggg 1-11 v: vvrvvhxvrvvnrvvv 3-14 w: ncwphcwvjwhdpwqkg 6-7 x: xxxfqmkvxx 13-14 v: vvvvvvvvvvvvkt 2-12 x: xzcvvxhhwwxxc 6-14 m: mdtnmjmhmnmmmmm 15-16 z: zzzzzzzzzznzzzzzzz 4-6 s: mcssdssjshscvcl 11-12 b: bnbbbmbjsbxbbbbbj 7-13 c: cccfhccczccwcccsc 3-4 m: cgtmmm 5-10 l: hxhbggrllmtgn 6-8 d: sdfdddlv 4-9 x: xxxxxvxxcx 11-12 c: rcmqkzjccccrdccmc 1-3 g: jgng 4-5 l: lvlll 9-16 n: rnnnqjnvqnnnlnnwdnnn 4-10 x: crdxgxrfjhr 1-5 f: tgdffffffqf 15-16 q: qqqqqqqqvqbfqknqqqqq 9-11 s: sssnffssksq 3-4 v: vqvvv 5-19 z: jthjzpgmwjbftzvmnpzk 3-10 w: mpxhrrnqdvncwssqwlxz 14-15 b: bzbbbbbsbbbbbbbbbbb 3-5 j: jpjvjjrjtmjj 3-6 w: wwmwwzw 1-6 c: ccccvzcccm 10-11 m: mmvwgmjmmmrqjmmmglm 2-3 f: fffw 6-12 m: bmbzmmrshmmz 5-6 n: nnnnnn 4-5 k: kmsgkwvkk 6-8 t: tttttbttt 4-5 j: vtmvsqjl 5-6 q: qshzdqqk 1-3 w: dwgw 8-9 q: qbqqqqqwq 5-10 m: lmmmkgmmwb 6-9 n: nnnlnnnnn 4-5 t: tntct 6-8 g: hgngghgw 6-9 t: gttwtgvpgtlt 6-7 l: lllllll 4-5 j: jhjkjjm 13-15 h: hhhhhhhhhhhhxnh 1-4 m: mmmmm 4-6 q: cqrtqsdqqzrknf 9-13 f: fffffffffzfvff 2-16 p: prxdxjpkppgpxsjwpppp 3-4 r: rrzh 1-2 g: cglblsnkg 1-3 f: xqnfwjmmwqffd 13-14 q: qqqqqqqqqqqqvjqq 18-19 g: dggggggggggggggggvgg 5-6 s: dsssssss 4-6 z: szdzzb 9-12 t: xtltpgftttmtt 10-16 m: mqmmmmmmmcmmmmqx 3-7 c: cpccngcvccm 2-16 s: jsdfsjsjtswhkvmsskj 2-3 c: kccc 4-16 k: qhndnqmrvjcczfkpds 4-6 n: nnnrkxl 9-10 s: ssssssssds 2-3 z: hfzcz 2-3 s: sssz 8-10 b: qbbbjbbbbw 7-16 k: gcvskkjkkkkwkzkz 7-9 n: nnnnnnhnnnn 1-10 q: qjxqmqxcgg 9-11 l: jdhjbbcnlzll 7-14 l: llrlxlllllltlnl 3-6 f: wfdqfbrf 3-8 t: ttzttmtvttzpl 10-12 v: vfvvvvvvvsvv 5-6 v: vvvvvm 11-13 t: ttttxtttttptttctttt 3-4 k: kkdm 4-6 n: nnnlnt 13-15 m: mmmmmbmmmbmmmmmm 5-6 l: klllnl 2-3 f: flzff 3-4 r: frrs 1-5 d: cqwkvsdqdvb 9-15 l: jvtfqczlnlwdpclxwp 12-14 t: ttttttlqtpttnt 11-12 m: mmmmmmmmmmmm 4-5 j: jjjkbjjjjj 9-12 w: wwwwwwwwkwxkwcb 6-12 q: tcqrqqqqxjqqqqmqhq 5-6 m: mmmsmmmm 2-5 t: mttbttprttddtv 10-13 t: tttttttttttztt 10-11 f: kmqfxttfkfd 5-7 v: vrlzpvjtvv 6-7 l: nlllllj 1-5 q: szdbqqkqqtkmssq 3-4 q: kcmlwqzczwms 13-16 b: bsbbbbbbbbrbsbbpzbb 9-11 d: dddsdbddkdkdd 2-15 j: xkjnntffvvxfnntcv 4-6 v: hvvvcvqvrwv 9-12 j: qjjjjdjgqhrjjfjrdj 8-10 v: vvvvvvvnvnvv 4-9 t: ttttthttt 8-16 g: ggggklggcggggxgg 1-3 z: wpqz 4-5 g: wgdnmxccgj 8-11 r: rrrrrrrxrrmd 1-9 f: ffffsfgdbsqfffzf 7-8 q: qzqqqqrrq 12-13 n: nnnnnnnnnnnnnn 8-12 j: jpjjjmjjjjjzj 1-4 j: nvjw 7-13 z: zzzzsnzxzznzrzgzzzz 14-16 z: zzzzzzzzzzzzzzzm 1-4 x: xxxxnxh 8-15 k: gnrkktkpcmklkksnkk 2-4 h: klph 11-16 c: ccckzdccgckpcccsc 15-16 l: dlllllllllllllll 2-3 s: dsxss 1-4 v: jvvv 2-8 t: ktkdtxkt 1-3 t: ftftttttt 4-5 k: kkkbkk 4-6 g: llqcggg 4-14 r: fmdvrrwlstlbjr 2-16 p: rpdfhpbqfwxlxhhc 6-8 j: jjjjjjjjj 1-7 f: fnnffblbqffkrff 1-3 k: rfqwlnnkzdq 15-16 s: ssssswssssssskssss 11-13 z: zzzzngfzzzzzz 5-7 h: hhbhhcnhfghhhv 2-7 j: zjrmjgmjdkp 5-8 z: bzzzpzzrzzzz 12-16 j: jtjnjjjjgjjjjjjsj 5-9 s: ssssssssms 2-3 s: ssss 13-14 d: ddddddddddddkt 12-13 r: wfdtrknrhvrrc 6-8 p: vpxphxngzhnkppppfp 2-3 j: jtjx 3-6 k: tkkvjkb 2-6 t: tvftftvbfx 5-7 z: zzzqzzz 14-15 h: whdhxhhhhhhhfxzhhh 3-4 g: ngjgg 9-10 z: zzzzztzztq 2-7 f: fffffqfszchff 4-6 f: lfqjnzccffjslsdf 5-6 z: lpzzzzsz 11-13 t: tttttwtttttttttttt 2-6 z: zzzzzz 9-10 m: mmmmmmmmjm 5-6 w: xwggfcwvwlx 1-4 j: jjjjjljjjjjjj 8-10 t: ttttttwttt 5-12 x: zxxxxxxpxxxn 3-4 v: vvlrv 3-6 h: hhhwhlxhlrhl 2-5 p: cptsjktp 4-11 j: bmjjjjjjnwwdk 15-17 p: ppppppppppfpppvpp 7-11 m: wnnmmwmtmmxmm 9-19 k: kkkkkjkkhwkcvkkkmknw 11-15 s: sspssbshssscssssss 1-8 s: sssssmssssssssssss 4-8 x: xxxxdxxx 9-10 n: nnnrnlnnnnnnnnnnnnnn 10-11 d: ddddddddddn 5-9 z: tzzzqzbmzzzqzjkzlr 9-20 f: fffffnfffffffsfnffff 5-6 g: gvggggg 13-14 x: xxxxxxxxxxxxxxx 6-7 v: vvvzvvvv 5-10 l: kbcvlfvlszndtlldjlh 4-9 s: vkcsdvszthkwmmmxs 3-4 b: jbmb 2-4 w: nmwm 5-10 z: tztzzfzgdzzszq 2-8 k: kzkkkkzwf 16-17 d: vxvzdgzwssqdcgbdb 4-5 b: bbbbb 7-9 w: wwfwwwjwln 5-12 k: ljkkkqfvqtkkxsd 5-7 q: qqqqhqqq 8-9 n: vnnnnnnpstnn 5-10 m: mmgzmmmmmm 3-14 q: qgbvqjxqnqqqqqqq 2-4 c: cccc 3-7 b: szbbkbdbmbbzbqs 1-5 m: mhmmc 3-6 n: nnlvnnvnq 2-3 c: mccc 11-12 m: ddmmmmxmmmmwfmmm 8-10 n: nnnnnrnnnn 1-12 g: sgbggglnggddgggsngrx 7-9 p: phppppppp 4-5 q: qxqqqq 3-7 v: vwsvvrvxvvvvvvwvvdlv 8-18 j: jmjcjjltjmjwjzrllgcj 2-14 r: rdrrrrrrrrrrrp 2-4 r: cxcbkmr 6-9 r: vtlnnvbcndqhrxkkjp 2-3 s: hxssnsswzc 10-16 r: csrsrxrrrrrrfrfdrr 7-9 w: wwbwmvrwdxww 12-14 p: pppbpppppppgpt 2-7 n: nnnnnnnn 3-12 f: mhjxfxgbbvffpclfffg 10-14 l: lllskllljllllll 11-16 l: lwlklllglzllllllll 13-14 h: hhhhhhhhhhhhhdhhhh 1-2 t: tttb 1-6 z: zzzrrzzbf 1-6 v: jrvzvvrs 3-6 g: jggbnl 17-18 x: xxxxxxxxxxxxxxxxrx 8-17 f: xnmffffbwfdcfrdfw 3-9 k: jmkdvkdnk 7-9 m: mmmmmmdml 9-11 c: cdmshccckqmcccccckp 16-17 g: gggggngggggggggggdg 7-8 n: nnknnnnnnn 3-13 n: fjhgrspsnkmnf 14-17 z: zzzzzzzzzzzzzqzzzzzt 13-14 r: rrrtrrfsvrzngw 7-8 k: kvkvkpvc 1-2 b: bbpbb 1-7 n: tchnrtbtldnmnnvvnn 3-4 s: sssssjv 1-9 l: cllllztmlllrzfl 9-10 x: qjxxxxxxdhxxxxxh 6-7 p: ppppfppv 3-8 q: mkqzqqbqzjrqbq 6-8 x: xxxxxxxx 1-7 f: ffffffff 5-16 b: jbbbbbqcbbbbbbfb 9-11 c: ccccccccccq 1-2 x: fqkx 4-12 z: znzzzzzzzzzzzzz 3-4 l: lglll 9-11 m: mmmmmmmmmms 14-17 x: xrxpxgkxxzdrxxxxckxv 3-5 t: gxjbbfcpmkbkxbtwbt 5-6 j: jmjjjj 14-15 g: ggggggggggggggx 6-7 l: lllllbl 2-14 q: qqtsqkqvqqqpxzqqcqq 2-4 w: fwhw 4-5 m: mzmtkm 2-4 g: ghghgp 5-6 r: rrrrnl 1-4 h: chghhw 7-12 r: rrrzglvrrrrsrr 1-7 x: xxcxdwxjmx 5-12 r: rrgrrffwtrrnrrqrrjnr 2-5 r: srdqrlxrkrrdkr 3-4 t: ttdg 11-12 s: bfjrkqqgdtlwrskmfrp 3-5 n: nnrnfzsnm 10-15 z: zzzzhzzqqczxwzqztv 2-7 f: ffgdfgff 7-10 d: ddtbdddddjtdqfdddfq 2-9 k: gkrkkkkkkkkhkqkx 13-14 n: nngnlnnnhnnnnnnnn 6-9 r: qrxrxzrff 7-9 m: mmmmmtmqqmml 11-12 p: pppppppppppp 10-13 j: jjjjjjjjjznvbjj 1-2 c: ccvc 7-8 m: mmmmtdmckkpmcbkjmm 5-8 j: sjptjjbjjjjj 6-8 d: jchdwrhd 5-6 z: lqzzzzkrzzvzwbbzktp 6-8 l: ztbltlll 2-3 z: zkrxzp 7-18 g: phgpgggqgzgnmwlpkwd 8-9 f: hffffffqf 17-19 p: pppppphpppppppppzpp 2-3 z: zzzfg 1-2 v: bfvj 4-8 b: bcbbbbbb 15-16 s: ppsnsssssssnssss 2-3 m: mnsm 2-4 h: hwfshh 9-15 h: hhwhhhhxhhhhhhh 17-18 n: nnnnnnnnnnnnnnnnnn 7-11 n: nnnnnqpnlbgqnqnshn 15-16 j: cdjmbcwdppvvjqvv 6-11 p: ppplppppxpt 4-5 r: rrrrrr 10-11 w: wwwwwwwwwww 3-7 p: pzppzspppmkxbldwpnwf 2-12 w: zwdljlzwgxfwvtdm 2-10 f: mzfjqfspgfrfhst 14-15 m: mzmmmvhwmdmmdpz 1-12 r: vrxrrtrxgvrd 4-5 n: nnnnnnpn 6-12 x: xkbwfsxxxxxkxxxxk 4-6 n: mncnxn 9-10 f: ffffpfqftbf 3-5 b: bzwbk 4-7 c: ncdcccc 11-12 t: dgdkrjgsgtlf 8-11 z: rqzdjqznrpkzmblbt 1-3 z: zfzx 2-4 z: kzgzkp 6-10 v: jvvvvvvvvs 2-9 v: vrvvvvvvvc 5-6 q: qqqqqqc 6-10 p: ppdknlgpqkp 10-13 z: zzzzzzzzzzzzvz 19-20 g: dtckblrmggknmxwnrjgg 4-18 p: ppcjpqfpcxtphlppmhcx 6-7 n: nnsnnknthn 10-11 f: fffffffffff 2-4 f: ffccltsfgk 6-11 d: dsqddtddddjcnssrcd 7-13 x: xxxxxqlxxxxfw 12-13 r: rrrdrrrrrmrrrr 15-17 p: pqppppppppppvppppppp 7-8 j: jjjjjrdp 4-6 v: vvvvvt 1-4 t: tltftjtjhz 9-15 j: jjjjjjhjjjjjjjkjj 6-7 c: ccccccccz 8-9 x: xxjxxxxxsx 4-5 h: hhrhh 2-3 g: cgnm 8-10 l: llqlgllzlvrllg 12-13 c: cvnbccpzzxcccfh 3-8 z: zbzrwzzzwrzbqnr 6-7 n: nnnnnnn 8-11 j: tjqjrjggjxxjggjj 7-12 l: bsvxdhljlcsj 3-6 j: jjfjjjjb 2-3 z: dzztwhmzqdx 9-12 v: vvvvvvmvzvvcv 13-14 v: vvvzvvvvvvvvvk 6-7 g: fgggghgng 13-14 h: wcghlwdbjhpdphkcv 1-2 t: nncsg 6-7 w: kwjwwxlwz 4-5 z: zzztvz 3-4 n: nvbvngnw 15-17 z: zzzzzzzzzzzzzzzzzzp 8-10 r: rrrstrgxrhrr 8-10 g: cggggggvgcg 1-4 m: mmvbz 3-14 j: bdbhbjnjnrldhwlbrkrj 1-4 r: rrkrnnd 2-3 f: fvwc 4-13 c: ccccvcgwbhwrcqf 3-9 c: jcghltcfkjchxmccccbs 3-5 h: hhhshm 5-9 h: hhhsjhhhhgthfgldw 4-12 h: mcwvwwphwwbc 6-11 g: gqgggvggggh 9-15 x: xxxxxxxxxxxxxxsx 16-18 t: rmqqtbtvttsdtjvbttl 9-20 f: cllnvlfkfrwzpqxwqgnn 9-18 v: vvvvvvvvzvvvvvvzvxvv 4-5 f: fzffbfvfff 1-5 p: pppppp 1-7 z: zjvchwzqjrtxzgz 4-9 v: vvvvvvvvvv 5-8 w: cwwwzwwb 7-8 r: rrrrxrrr 8-9 f: sgdcqfhfcfsflb 3-7 g: gdgtnfggq ================================================ FILE: exm/aoc/2020/aoc_2020_03.adb ================================================ -- Solution to Advent of Code 2020, Day 3 ------------------------------------------ -- Toboggan Trajectory -- -- Count trees (#) at integer locations, on a straight line -- going through a map. -- The line has a given rational slope. -- -- https://adventofcode.com/2020/day/3 -- with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2020_03 is use HAT, Interfaces; i_max : constant := 323; -- 1-based j_max : constant := 30; -- 0-based -- -- n : VString := +"example_03.txt"; -- i_max : constant := 11; -- j_max : constant := 10; -- map : array (1 .. i_max, 0 .. j_max) of Character; -- -- Count trees on a trajectory with a rational slope (y / x). -- function Trees (y, x : Positive) return Natural is ii : Positive := 1; jj, t : Natural := 0; begin for i in 1 .. i_max loop if map (ii, jj) = '#' then t := t + 1; end if; jj := (jj + x) mod (j_max + 1); -- Map is periodic horizontally. ii := ii + y; exit when ii > i_max; end loop; return t; end Trees; -- test_mode : constant Boolean := Argument_Count >= 2; f : File_Type; prod : Integer_64; begin Open (f, "aoc_2020_03.txt"); for i in 1 .. i_max loop for j in 0 .. j_max loop Get (f, map (i, j)); end loop; end loop; Close (f); -- prod := Integer_64 (Trees (1, 1)) * Integer_64 (Trees (1, 3)) * Integer_64 (Trees (1, 5)) * Integer_64 (Trees (1, 7)) * Integer_64 (Trees (2, 1)); if test_mode then if Trees (1, 3) /= Integer_Value (Argument (1)) or prod /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+" a) Trees met with slope 1/3: " & Trees (1, 3)); Put_Line (+" b) Product of total met trees with different slopes:" & Integer_64'Image (prod)); -- Part 1: validated by AoC: 218 -- Part 2: validated by AoC: 3847183340 end if; end AoC_2020_03; ================================================ FILE: exm/aoc/2020/aoc_2020_03.txt ================================================ ....#...##......##..#..#.#...#. ..######...#......#....#..#.##. ..#.#...##......#.#..#..#....#. ..#.....#..#.#........#.#..#..# #......##..###...#.#..#.....#.. #.......##...###...#....#...... .....##...#......##.#.#..#.##.. .........#......#.....#......#. ..#.#..#....#....#......##.#.## .#...#..#.............#.#..#.#. ....#..#.#.##.#....#..#..#....# ...#..#.....#.......#...#..#..# .....#.....#.......#..#...#.... .##.......#...#..#........#...# ...#.......#.#.#...#.#.#......# #....#..#.....#......##....#..# ###.#......#.#.#.#..#....#....# ......##......#.#...#...#..#... .....#......#.#.#......#.#..... ...##...#..#........#..#.##.... ..##.#.#..#...###..........#.#. .#..#..#.....#.........#.###.#. ....##.....#...#...##..#.##...# ....#.##....#.....##......#.... ........#.#.........#.#.......# #....##.#....#..#...#.......... #..###......#....##..........## ....##.#.....#..#.##......#.... #..#......#......#............. ...##.....##.......#.......#... #...#.#.....#..........#...###. #.....#..#.#.###...#......###.. ...##.#......#........#..#..... ......#.....###.#...##........# .#......##......##....#....#... ..#.#..#.....##....#....#..#... ..#.#.....#.##.#.....#.....#... ....#.......#...#.........##... .#....#..#.......##.......#.... ..#..##.....#...##.##.#.#...... .##.#....#............#.......# .......#...#..#.#.##.....##..## ..###....#..#.##........##.#... ....#.#..#.....#..#.#.....#.... ..#..#.#..............#..#..... .......#.#.#.........#......#.. ...##..#.#...#......##.#....... #....#.#.........#...#....#..## .#..#.#...#.......#.#.#....#.## .#..###.#..#.#.....#..#........ #.#..##.###.....##.........#..# #...##...#..##..#..#..........# .#...#..#...................... ...##..###...........#.#...##.. ..........#.#....#.#........... ..#....#....#..#....#.#.#...... .#..#.....###......#...#...#... #.##..#..#.........#..#....#... ........#......#...#.........#. ..#.....#.#..##...#.#.#...##... ..#...........#.##..#.#..#.##.. ..............##...#.#......#.. #.#..#....#...##.###........#.. .#...#..#........#........##..# .....##..#...#.....#.#......... .#...#...#....###...#.#.#..##.. ....#.........#....###..##....# .#....#...####...##....####.#.. ..#..#.......#..#......#.#.#... ....#....#.......##..#.#....... ..#....#...........##.#.##..... #..#..#...##.##....#.#.#.###.## ...#...#....#.#...##...#....### ......##........#.........#.#.. ....#####..#..##.......#.#....# ....##..#...###....#..#.....#.. ..#........#..#.#.....#....#... ..#....#......#..#...#......#.. ...#.....##...#.#..##.....#..#. ...#..#.......####.##...#...... .....#..#..#.##..##....#..#.#.. ..#..#..##.#.#.##..#..#...#.... ...#..........#.........#....## .##.....###...............#.##. ...##...........#.#.#......#..# .#...#.#.##....#....#..#....... .#...###.#....#..#..#..#......# #..#........###...........#..#. ..#...#......#.#.#......####.#. ...#.#....##.#.....#.....##.... ...###..#.#.#...#.....#.###..#. .#.#..#...##......#..........#. ##.....#.......#.#..###...#.#.. ##.###....#.....#.....###.#.... #...#..##....#.#...#...#......# .....##.#........#.###......... .#..#..#.#......##.#...#.#..... #..#.#........##...........##.# #...###..#..####..#.#.......... ..#...#....#...##.#....#....##. ......#.#........#.....#..#.... #.........#...#.....#...#..##.. #....#.........#...#.##..###.#. #...###...#.##.#.#............. #.#....#....#......#....#.#...# ##...#.##......#..#.#....#..... ....#...#.##....#.............. .........##..........#..##..#.. ......##....#.#......#......... ..#.#..............#......#..## ...........##.......#.#.#...... ##...#........##.......#.#..... ....#...#...#....#.#......##... ...#..#.#.#.........#..#.#....# .##.#...#.#.........#.....##.#. #.#.....#.#.....#.............. ..#.#..#....#..........#..##... ...#..#....................#..# ...........#...........#...#..# ............#...#............## ..#....##......##...........#.. ..#..#..#....#....##......##.## ##..........#..##.##.#...#..... ............#..#........###.#.. ###...##.#.#....#....#.#....#.. ...#......##...#.......####.... .......#..#..#.#.....#......... ........##.......##.....#...... #.#...#.###....#..#...##....... ...#.#....#..#####.#..##.#..... ..#.#..##.......###...#.....#.. ..#.......#..#...#...#..#.##... ......#..#.......#.....#....#.. .......#........#.#.......##..# .#.#.....#.......#.......##..#. ..#.#....#.#.#####.....#...#... #..#............###.......#..#. ........##.........#..#...###.. .#............##...#.....#..... .#..##..#....#....#.......#.... ....##..........##............. .##..........#..#..#....#...#.. ...#..#..#............####..... .............#..#.##..#.#.##... .....#........#....#.#.......#. ###.#..#.#...#....##........... ....#......#...#....##.......#. .......#.#...#.#...#........##. ..........#........#..#.##..... ##..#.#.....##.#............... .....#....#................#... ...##....#........##.#....#.... .....##...###....#.#..#.......# .....#.#.........##....###..... .#.....##......#..##..##...##.# .#..............#.....#.#...... .##......#..#..#......##....... .......#..................#.... ...#.#...##......####.........# #....#####.#.#..#..#..#...#...# ##.#...#.......#....#...#...### ...#........#.....#...#.##..... ..##....#.......#....#.......## #......#..##...#..##.#.....#.#. ..###........#.#..#........#.#. ...#.###..........#.....#.#.#.. #.###.....#...#...#..##..###... #....#.#.....#.#........#...... ........#.......##.......#..... ...........#...#......##....... ............#...#....#..#.....# #.#.#.#....#.....#.#..........# #.##...#...#..#....##.#.......# ...#..#......#..#...##..##..#.. #....#......#.#.....##.#..#.... #....#..##.#......#.#.....#..## .#..##....##....#.#...#...#.... #.#.###....#.#............#...# .#.#....#..#..........#....#.#. ......#..#.#...............##.. ..#......###.#..........#.###.. ....#.##.#..#...##..#.#...#.... ..............#...##.......#.## .#...........#....#....#.##.... #..#....#.....#...#.....##...#. .........#...#.##.......#...#.# .....#......#.........#.#..#... ##..........#.#..##...#.#.#.... ##..##.#..#..#.....#.##....#... ........##....#.#.#....#......# .#.##...#.###....#.........#..# ..........#....###..#.........# #.#..#.#...#.......#..##....... ..#....#...###..............##. #..###.....####...#..#..#...#.. ......#..#...###........###.... ..#.....#...#.......#....###..# .#.........#.#.#....#.#.......# #.#.###.#.#...........#........ ......#..#.........#........#.. ...........##.#........#.#...#. .....#.#......##.......#.....## ...##...#............#..#.....# .....#..##....##...##.#..#.#... ...#...#........#.#......##.... ........#..##..#..#......##.#.. .#.#.....#.....#...........#.## .#...#.#............#......#... .....#...#........#....#..#.#.. ...##....#..#...#.............. #....##.#.#............#....... #..#..#.....##..#........##.#.# ##..#.#....#....##.......###..# .#.#.#.....###.....#.#......### .....#..#...###...#....#.#...#. .##.....................##....# .#.....#.........#....#.....##. #...#....#.#...###.......#.#..# ...#.................#.#....#.# .##...#.#...................... .##.#........#...##............ .#....#.....#.........#.##..##. #......#...##..#.........##.##. ......#......#...####..#.##.... .###....#..##......#.##......#. ..#...#....#..#.......#.#...... #....#...#.................#.#. ....#.#.#..#...#..#.......#.#.# #.#...##.......#.....##.#...... #.........#.....##..##..#...... ....#..##..#.....#..#..#.#..#.. ......#.#..#.#.#....#.#.......# .##......#..#....##...##..#.... ..#..#......#...##..#.##.....#. ..#..#.......#.#....#.....#...# ....#.#.....###...#.......#.#.. ..#....##.....##.#........##... #...............##....#.....##. .#.........#....#...##.###.##.# .#.##..#.............#.#.#..#.. .#.....#.................##.... ..####.........#.#......#.#..#. #.......#..........#.#........# .#.#...##.....#.#.......#....#. ..#.##.#.......###....#....#... .#....##.............##.#.#.#.. #.#.....#.#.#.#..#......##..#.. .............#..........#.#.#.. ...#.#.............#.#...##.... .......#..#.#.......#..#.#....# .............#.........###..#.. .#.#..#....#.....#..#.....#...# #.....#....##..##.#..#........# ..##..###.....##....#.#..#..... ..#...##....#...#.#..........#. ...##..##.#.....#....#......... ..#...#........##.#..#........# #.............#.###......#.##.. .#...#........#...........#...# ..##.......#.#..##.##......#... ...#.#...##....##..#........... .#......##........#....##....#. .........#..#....#...#..##.##.. ....#..#.#...#.......#.#.##.... ...#.#......#.#..#..#.#....#..# .......#........#.........###.. #.#..#.#.........##............ ##..##..#.##..###...#.#...#.... .#....#.#..#...#....#.##.....#. .#.#.#.#........##...#..#.#.##. .#..#.#..#...........#..#...... ..#.##.#...#....#.........#...# .....##...#.#...#...#....#..... ..#..........#.#.#.......##.#.. #.#............#..#.....#..#... ..#...........##.#.##.#....#..# #..####.....#............#..... .##......#####.#..#.....#....#. ...##..#.#......#.#..#..#...##. #....................#.##...#.# ...#............#.............# ....#.##..........#.....#...... ....##..##....#.#.............. ...........#....##.#.....#..... ....#.....#....#....#......#... #...##........#...#........#.#. ........#.....##..#.##.#..#.#.# ....##......##....#.....##....# ...#.#........##.......#...##.. #......##..#.#.#....##......#.. ..#.......#.......##..#.##..... .#...#...#.#.............##.... ......#.#.#.........##...#..#.# .....#..####....#.##..........# ...#...#.#....#.....#..#.....## .........#.......#......###.... ........##..##..#.#.#...###...# .#..##.#....#...##.....#.#.#... ........##...#...##..#......... .........#.......#.##..#...#### #......#.....#..............#.# ##..##.#.##.....##...........#. #.............#.........#...... ...####.#.##..#.#.#.##.#......# ..#.....##....#...#............ #..............#......#...###.. ..#..#.#...#.##.........##..... ..#...##..#........#..#.##..##. ......###...#..#....#..#.###... ...##.##.###.....##.#.......#.. #....#..###..#.......#.#.#..#.. ..##.............##..##...###.# .#.#..#.........#..........#... .........#.#.....##...#..#...## ....#..#....#####..#...#..#.... ...#.....#.....#...#.#..#.#.... .#..#.............#.......##.#. ...##.......#.#.....##......#.. ...........##..#.##..###...#.#. ...........#...........#...#..# ..#....#.##.#..#..#...........# ..#.....##...#......#...#...... ...###.###.....##..........#..# ================================================ FILE: exm/aoc/2020/aoc_2020_04.adb ================================================ -- Solution to Advent of Code 2020, Day 4 ------------------------------------------ -- Passport Processing -- -- https://adventofcode.com/2020/day/4 -- ------------------------------------------------------------------------- -- -- HAC 0.084 "nice to have"'s detected in this exercise: -- * exception handling to catch invalid values -- * Index with From parameter -- * 'Image attribute for enumerated types -- -- Solved in HAC 0.098: -- * "and then", "or else" -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src procedure AoC_2020_04 is use HAT; -- function Val_Num (s : VString; hexa : Boolean) return Integer is c : Character; begin if Length (s) = 0 then return -1; end if; for i in 1 .. Length (s) loop c := Element (s, i); if not (c in '0' .. '9' or else (hexa and then c in 'a' .. 'f')) then return -1; end if; end loop; if hexa then return Integer_Value (+"16#" & s & '#'); else return Integer_Value (s); end if; end Val_Num; -- function Val (s : VString) return Integer is begin return Val_Num (s, False); end Val; function Val_Hexa (s : VString) return Integer is begin return Val_Num (s, True); end Val_Hexa; -- cats, total, cat_idx, tok_begin, tok_end, nb : Integer; s, tok, cat, un : VString; compiler_test_mode : constant Boolean := Argument_Count >= 2; f : File_Type; begin for criteria in 1 .. 2 loop Open (f, "aoc_2020_04.txt"); cats := 0; total := 0; while not End_Of_File (f) loop Get_Line (f, s); if s = "" then cats := 0; end if; if criteria = 1 then if Index (s, "ecl:") > 0 then cats := cats + 1; end if; if Index (s, "pid:") > 0 then cats := cats + 1; end if; if Index (s, "eyr:") > 0 then cats := cats + 1; end if; if Index (s, "hcl:") > 0 then cats := cats + 1; end if; if Index (s, "byr:") > 0 then cats := cats + 1; end if; if Index (s, "iyr:") > 0 then cats := cats + 1; end if; if Index (s, "hgt:") > 0 then cats := cats + 1; end if; else cat_idx := 0; loop s := Slice (s, cat_idx + 1, Length (s)); cat_idx := Index (s, ":"); exit when cat_idx <= 3; tok_begin := cat_idx + 1; tok_end := tok_begin - 1 + Index (Slice (s, tok_begin, Length (s)), " "); if tok_end >= tok_begin then tok_end := tok_end - 1; else tok_end := Length (s); end if; tok := Slice (s, tok_begin, tok_end); cat := Slice (s, cat_idx - 3, cat_idx - 1); if cat = "byr" and then Val (tok) in 1920 .. 2002 then cats := cats + 1; end if; if cat = "iyr" and then Val (tok) in 2010 .. 2020 then cats := cats + 1; end if; if cat = "eyr" and then Val (tok) in 2020 .. 2030 then cats := cats + 1; end if; if cat = "hcl" and then Element (s, tok_begin) = '#' and then Val_Hexa (Slice (s, tok_begin + 1, tok_end)) > 0 then cats := cats + 1; end if; if cat = "pid" and then Length (tok) = 9 and then Val (tok) >= 0 then cats := cats + 1; end if; if cat = "ecl" and then Index (+"amb blu brn gry grn hzl oth", tok) > 0 -- ^ Idea: Maxim Reznik, replaces checking each value then cats := cats + 1; end if; if cat = "hgt" then nb := Val (Slice (s, tok_begin, tok_end - 2)); un := Slice (s, tok_end - 1, tok_end); if (un = "cm" and then nb in 150 .. 193) or else (un = "in" and then nb in 59 .. 76) then cats := cats + 1; end if; end if; end loop; end if; 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 loop; Close (f); if compiler_test_mode then if total /= Integer_Value (Argument (criteria)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Valid passports (criteria set #" & criteria & "): " & total); -- Part 1: validated by AoC: 228 -- Part 2: validated by AoC: 175 end if; end loop; end AoC_2020_04; ================================================ FILE: exm/aoc/2020/aoc_2020_04.txt ================================================ pid:827837505 byr:1976 hgt:187cm iyr:2016 hcl:#fffffd eyr:2024 hgt:189cm byr:1987 pid:572028668 iyr:2014 hcl:#623a2f eyr:2028 ecl:amb pid:#e9bf38 hcl:z iyr:2029 byr:2028 ecl:#18f71a hgt:174in eyr:2036 hcl:#cfa07d byr:1982 pid:573165334 ecl:gry eyr:2022 iyr:2012 hgt:180cm cid:151 hcl:#c0946f ecl:brn hgt:66cm iyr:2013 pid:694421369 byr:1980 eyr:2029 ecl:brn pid:9337568136 eyr:2026 hcl:#6b5442 hgt:69cm iyr:2019 byr:2025 cid:66 hcl:#efcc98 pid:791118269 iyr:2013 eyr:2020 ecl:grn hgt:183cm byr:1993 eyr:2022 hgt:160cm iyr:2016 byr:1969 pid:767606888 ecl:gry hcl:#6b5442 hgt:157cm eyr:2026 ecl:oth hcl:#efcc98 byr:1938 iyr:2014 byr:1931 iyr:2015 ecl:gry hgt:76in cid:227 hcl:#09592c eyr:2024 pid:276365391 ecl:gry hgt:170cm iyr:2014 cid:285 pid:870052514 hcl:#866857 byr:1925 eyr:2025 eyr:2021 byr:1960 pid:569950896 iyr:2010 hgt:179cm hcl:#888785 cid:167 hgt:154in cid:194 pid:8142023665 byr:2010 hcl:7d22ff ecl:utc iyr:2026 eyr:1976 ecl:blu eyr:2030 hgt:192cm pid:363860866 iyr:2019 hcl:#ceb3a1 byr:1963 byr:1947 hgt:167cm hcl:#7d3b0c ecl:amb cid:70 eyr:2022 iyr:2019 pid:756932371 hgt:185cm pid:871945454 iyr:2020 hcl:#866857 ecl:amb byr:1989 cid:184 eyr:2030 byr:1935 pid:322117407 hgt:153cm iyr:2011 cid:244 eyr:2022 hcl:#efcc98 ecl:hzl ecl:blu hcl:#5e6c12 eyr:2029 iyr:2011 hgt:191cm byr:1992 hcl:#7d3b0c eyr:2029 hgt:163cm pid:625292172 byr:1932 ecl:brn iyr:2020 hgt:158cm eyr:2030 iyr:2016 byr:1969 cid:173 pid:092921211 hcl:#602927 ecl:grn hcl:#733820 iyr:2016 eyr:2029 ecl:hzl hgt:180cm pid:292904469 byr:1984 ecl:amb pid:901224456 hgt:190cm iyr:2013 hcl:#733820 byr:1922 pid:262285164 iyr:2010 byr:2018 eyr:2026 hcl:#602927 hgt:179cm ecl:gmt cid:349 byr:1956 eyr:2027 pid:351551997 hgt:71in cid:277 hcl:#cfa07d iyr:2010 ecl:grn eyr:2027 hcl:#602927 hgt:157cm ecl:gry cid:128 byr:1953 pid:231551549 iyr:2012 iyr:2011 pid:771266976 cid:264 byr:1955 hcl:#b6652a hgt:189cm ecl:blu eyr:2030 eyr:2026 pid:698455242 byr:1949 ecl:gry hgt:190cm iyr:2013 hcl:#efcc98 cid:139 ecl:blu hgt:181cm byr:1977 iyr:2011 eyr:2022 pid:454163967 hcl:#b6652a pid:534506872 hgt:155cm iyr:2012 byr:1968 cid:333 eyr:2024 hcl:#623a2f ecl:amb hgt:162cm iyr:2020 hcl:#733820 eyr:2027 byr:1995 ecl:gry pid:084994685 iyr:2016 byr:1990 ecl:amb pid:185689022 eyr:2025 hgt:184cm hcl:#866857 byr:2016 hcl:z iyr:2022 hgt:166in eyr:2040 byr:1943 hgt:152cm hcl:#cfa07d ecl:hzl iyr:2016 cid:300 pid:376088014 iyr:2020 eyr:2026 hcl:#602927 ecl:gry byr:1962 pid:453907789 hgt:172cm eyr:2023 hgt:185cm hcl:#623a2f pid:963767258 byr:1977 iyr:2019 ecl:oth hgt:159cm byr:1965 cid:349 ecl:blu pid:962908167 iyr:2013 eyr:2024 hcl:#fffffd eyr:2026 pid:912822238 hgt:66in byr:1985 iyr:2018 hcl:#c0946f ecl:hzl hgt:167cm hcl:#ceb3a1 byr:1990 eyr:2027 ecl:grn iyr:2011 pid:642877667 hcl:#7d3b0c byr:1921 pid:976412756 hgt:192cm iyr:2013 ecl:gry iyr:2030 pid:283599139 eyr:2039 cid:203 hcl:f943cb hgt:111 hgt:190cm iyr:2027 ecl:blu hcl:z byr:2004 eyr:2039 pid:734570034 hcl:#6b5442 hgt:191cm ecl:oth byr:1989 pid:669414669 cid:196 iyr:2016 eyr:2023 ecl:brn eyr:2028 byr:1965 pid:630674502 hcl:#602927 iyr:2020 hgt:61in iyr:2016 eyr:2022 cid:225 hcl:#733820 ecl:hzl hgt:166cm byr:1934 pid:232742206 ecl:amb hcl:#602927 eyr:2029 pid:897535300 hgt:189cm byr:1952 iyr:2017 pid:853604345 hgt:161cm cid:269 hcl:#fffffd eyr:2030 iyr:2011 ecl:grn byr:1966 hgt:151cm hcl:#18171d eyr:2026 ecl:grn iyr:2016 pid:176cm byr:2000 hcl:#341e13 eyr:2022 pid:536989527 cid:73 byr:1971 ecl:hzl pid:739005658 hcl:#b6652a eyr:2026 hgt:154cm ecl:hzl iyr:2019 byr:1935 pid:373465835 ecl:oth byr:1932 cid:333 hgt:165cm hcl:#b6652a eyr:2021 iyr:2014 byr:1967 pid:486658617 hcl:#18171d hgt:174cm eyr:2021 iyr:2015 ecl:gry cid:53 eyr:2024 cid:124 iyr:2017 hgt:152cm pid:095649305 hcl:#341e13 byr:1920 ecl:oth hcl:#623a2f byr:1951 pid:993284548 cid:106 hgt:186cm ecl:amb iyr:2017 eyr:2029 cid:308 pid:080673934 hgt:193cm byr:1967 hcl:#623a2f iyr:2016 ecl:hzl eyr:2021 iyr:2010 eyr:2024 byr:1946 hgt:156cm cid:199 ecl:blu hcl:#866857 ecl:blu byr:1955 eyr:2022 cid:95 pid:139391569 iyr:2019 hgt:180cm hcl:#efcc98 ecl:brn pid:579889368 eyr:2023 hgt:158cm byr:1935 iyr:2018 hcl:#cfa07d byr:1920 pid:90919899 hcl:#18171d hgt:152cm eyr:2029 ecl:oth iyr:2014 byr:1961 eyr:2024 ecl:#d401e3 iyr:2011 hgt:172cm pid:919145070 cid:100 hcl:#efcc98 ecl:gry hgt:168cm hcl:#888785 byr:1942 pid:731032830 iyr:2014 eyr:2028 hcl:#6b5442 pid:265747619 hgt:191cm cid:217 eyr:2028 iyr:2019 ecl:amb byr:1948 iyr:2011 ecl:brn hgt:183cm hcl:#fffffd cid:258 byr:1983 pid:835909246 byr:2030 iyr:2024 ecl:#f66808 hcl:fd548d cid:183 pid:#fced33 hgt:160in ecl:utc hgt:183in hcl:a92c31 pid:0394222041 iyr:2008 eyr:1976 byr:2020 pid:126195650 iyr:2019 hcl:#341e13 ecl:blu hgt:150cm eyr:2025 byr:1964 cid:71 iyr:2016 hgt:157 ecl:grt hcl:#18171d pid:#1ab5ea eyr:2027 eyr:2026 hcl:#b5266f byr:1971 cid:269 hgt:192cm iyr:2012 pid:736578840 ecl:amb pid:152109472 hcl:#ceb3a1 ecl:grn hgt:188cm eyr:2027 byr:1923 hcl:#341e13 pid:535175953 hgt:63in eyr:2028 iyr:2015 byr:1999 ecl:gry hgt:183cm pid:611738968 byr:2001 eyr:2020 hcl:#a97842 iyr:2014 ecl:gry eyr:2038 ecl:gmt pid:113210210 iyr:2012 byr:2011 hcl:z hgt:157cm hgt:157cm pid:699449127 iyr:2014 ecl:gry byr:1980 hcl:#fffffd eyr:2029 iyr:2028 hcl:z pid:152cm eyr:2039 ecl:#4760fb hgt:177in byr:2017 eyr:2026 hcl:#efcc98 iyr:2020 hgt:180cm ecl:hzl pid:747449965 byr:2016 byr:1974 iyr:2019 cid:89 eyr:2023 pid:421418405 hcl:#fffffd hgt:192cm ecl:gry hcl:26c2ef eyr:2029 cid:309 byr:1931 ecl:grn pid:#4eb099 iyr:2024 hgt:174cm ecl:gry hgt:183cm cid:281 eyr:2022 pid:050492569 byr:1968 hcl:c88145 iyr:2015 eyr:2028 iyr:2014 pid:712984515 hgt:187cm cid:206 hcl:#866857 byr:1927 ecl:brn byr:1936 hgt:61in ecl:oth iyr:2012 pid:447813841 hcl:#c0946f cid:126 eyr:2021 ecl:gry pid:791970272 eyr:2020 byr:1932 hcl:#623a2f hgt:161cm iyr:2015 hcl:#c0946f byr:1935 pid:721144576 eyr:2025 hgt:162cm iyr:2017 ecl:oth byr:1959 pid:551109135 ecl:hzl hgt:68in eyr:1977 hcl:#888785 iyr:1955 cid:100 hgt:190in eyr:1993 pid:8358180772 iyr:1975 ecl:oth byr:2024 hcl:3de172 eyr:2030 hgt:190cm hcl:#a40ef3 byr:1935 pid:484932501 ecl:amb iyr:2016 iyr:2015 byr:1964 hgt:176cm pid:819552732 hcl:#c0946f ecl:amb cid:263 eyr:2024 hgt:65cm cid:59 eyr:2027 pid:074880819 ecl:utc iyr:2023 byr:1954 hcl:#623a2f byr:1954 hgt:167cm iyr:2020 eyr:2023 hcl:#602927 pid:280295309 ecl:hzl cid:168 hgt:168cm pid:311043701 iyr:2017 byr:1965 ecl:hzl eyr:2026 hcl:#fffffd hcl:#fffffd ecl:grn pid:672987232 iyr:2012 eyr:2022 hgt:66in iyr:2012 ecl:#6f4f9f hgt:133 byr:1937 eyr:1953 pid:7177768428 hcl:#602927 iyr:2010 byr:1922 hcl:#c0946f eyr:2029 ecl:gry hgt:165cm pid:893045052 iyr:2013 eyr:2028 hcl:#866857 pid:137143403 ecl:brn hgt:170cm byr:1940 cid:194 hgt:161cm eyr:2027 pid:3966920279 ecl:gry iyr:2015 byr:1997 hcl:#cfa07d ecl:amb hgt:157cm byr:1971 pid:562746894 cid:305 hcl:#0b0e1a eyr:2021 iyr:2016 hcl:8b821d hgt:157cm pid:187cm cid:298 eyr:1926 iyr:2019 ecl:amb byr:2030 hgt:155cm hcl:#341e13 byr:1924 pid:779847670 ecl:hzl iyr:2015 eyr:2024 pid:768590475 hcl:#a97842 iyr:2014 cid:128 eyr:2029 ecl:oth hgt:164cm byr:1990 iyr:2019 hgt:181cm cid:342 eyr:2020 ecl:gry byr:2001 hcl:#623a2f pid:473165431 byr:1928 eyr:2026 hcl:#42a9cb iyr:2010 ecl:grn hgt:157cm pid:638074984 eyr:2028 byr:1951 pid:239781647 iyr:2020 hgt:156cm ecl:hzl cid:215 hcl:#efcc98 pid:636605355 ecl:hzl iyr:2017 cid:323 eyr:2025 byr:1995 hcl:#18171d hgt:187cm byr:1933 hcl:#866857 hgt:152cm ecl:oth iyr:2014 pid:900790914 eyr:2030 cid:267 ecl:brn byr:1999 eyr:2027 hcl:#623a2f iyr:2017 pid:853165955 hgt:152cm eyr:2030 pid:316704688 hcl:#c0946f ecl:brn iyr:2014 hgt:193cm iyr:2012 byr:1928 hgt:154cm pid:570535769 hcl:#623a2f eyr:2026 ecl:hzl iyr:2016 cid:252 eyr:2030 hcl:#888785 hgt:177cm ecl:grn byr:2002 pid:568715162 pid:570999226 iyr:2012 hgt:150cm byr:2024 ecl:brn hcl:z eyr:2029 pid:174002299 iyr:2019 hcl:#cfa07d ecl:brn byr:1927 cid:77 hgt:159cm eyr:2027 ecl:#d16191 eyr:2022 pid:166cm hgt:165cm hcl:#18171d iyr:2015 pid:112585759 hcl:#341e13 eyr:2025 byr:1962 hgt:164cm ecl:hzl iyr:2018 pid:478415905 eyr:2025 cid:315 ecl:amb hgt:91 iyr:2014 hcl:#cc9d80 byr:1985 pid:561885837 hcl:#7d3b0c hgt:169cm byr:1921 iyr:2014 cid:178 eyr:2022 ecl:gry ecl:#c87497 hcl:5321a2 eyr:2020 hgt:74in pid:#7a62c6 iyr:1976 eyr:2037 pid:858202391 hgt:162cm ecl:grn byr:2003 cid:278 iyr:2010 hcl:cbf662 ecl:blu iyr:2012 hgt:183cm hcl:#623a2f pid:848200472 byr:1997 eyr:2027 byr:1942 hgt:164cm pid:464257339 iyr:2016 hcl:#7d3b0c ecl:gry iyr:2012 hcl:#ceb3a1 hgt:193cm ecl:amb pid:667987561 eyr:2024 byr:1960 hgt:187cm pid:222340640 iyr:2018 eyr:2022 ecl:oth byr:1957 hcl:#336667 cid:83 eyr:2025 iyr:2015 hcl:#733820 ecl:brn pid:131195653 hgt:185cm eyr:2026 ecl:amb byr:1998 pid:938587659 hcl:#733820 iyr:2016 ecl:oth pid:300949722 eyr:2028 iyr:2016 byr:1933 hgt:179cm hcl:#cfa07d byr:1974 iyr:2019 ecl:hzl hcl:#c0946f eyr:2024 pid:484547079 cid:112 hgt:185cm eyr:2022 iyr:2018 hcl:#fffffd pid:118568279 hgt:153cm ecl:gry byr:1941 cid:341 iyr:2018 eyr:2027 hcl:#888785 byr:1970 hgt:165cm pid:773715893 ecl:amb hcl:#623a2f hgt:156cm byr:1938 iyr:2012 pid:745046822 ecl:amb eyr:2030 iyr:2012 pid:097961857 eyr:2023 hgt:66in hcl:#fffffd byr:1962 ecl:utc byr:1943 hgt:150cm iyr:2012 pid:740693353 eyr:2023 hcl:#18171d cid:101 ecl:blu iyr:2018 pid:183728523 byr:1924 hgt:154cm eyr:2030 cid:167 ecl:blu hcl:#ceb3a1 hgt:69cm eyr:2025 hcl:z ecl:brn byr:1982 pid:250782159 iyr:2011 byr:1998 iyr:2018 hcl:#341e13 eyr:2022 hgt:157cm pid:497100444 cid:266 ecl:gry eyr:2027 iyr:2011 hcl:#6b5442 hgt:156cm pid:494073085 byr:1998 ecl:hzl byr:1947 hcl:#b6652a iyr:2011 pid:228986686 eyr:2030 hgt:175cm cid:70 ecl:brn eyr:2026 hgt:159cm byr:1946 pid:534291476 iyr:2018 ecl:gry cid:225 hcl:#18171d pid:439665905 cid:311 ecl:amb iyr:2018 eyr:2030 hgt:186cm byr:1950 hcl:#cfa07d pid:250175056 hcl:#efcc98 byr:1981 cid:262 hgt:154cm ecl:gry iyr:2020 eyr:2027 pid:461335515 iyr:2014 hcl:#f1cf00 hgt:180cm ecl:amb eyr:2027 byr:1956 iyr:2014 eyr:2030 cid:194 pid:234623720 hcl:#733820 hgt:164cm byr:1929 ecl:blu byr:1992 eyr:2024 hcl:#ef8161 cid:216 ecl:brn hgt:177cm iyr:2018 pid:101726770 hcl:#341e13 hgt:178cm iyr:2016 eyr:2029 byr:1945 pid:045325957 ecl:grn cid:99 ecl:gry iyr:2012 cid:52 hgt:168cm byr:1943 hcl:#cfa07d pid:899608935 eyr:2030 cid:241 byr:1934 hgt:161cm eyr:2027 iyr:2011 hcl:#c0946f ecl:amb pid:346857644 iyr:2019 hgt:178cm hcl:#c0946f byr:1957 eyr:2026 ecl:brn pid:222885240 ecl:blu eyr:2021 cid:312 hcl:#733820 hgt:186cm iyr:2012 byr:1969 pid:821704316 hcl:#6b5442 cid:159 hgt:180cm iyr:2018 eyr:2028 ecl:hzl byr:1966 pid:#e0238e pid:622400994 eyr:2022 hcl:#5b6635 iyr:2012 byr:1980 hgt:190cm ecl:oth byr:1976 ecl:gry eyr:2020 iyr:2020 hgt:171cm pid:219878671 hcl:#6b5442 hgt:163cm byr:1968 pid:003521394 ecl:oth iyr:2010 cid:61 hcl:#888785 cid:115 pid:810722029 hgt:166cm byr:1955 ecl:blu eyr:2030 iyr:2018 hgt:176cm eyr:2025 pid:617393532 hcl:#733820 byr:1975 iyr:2018 ecl:grn hcl:#733820 byr:1979 pid:838168666 hgt:190cm ecl:oth cid:330 eyr:2029 iyr:2018 eyr:1940 hgt:67cm iyr:2009 ecl:gry pid:#e76a62 byr:2020 hcl:z hgt:190cm ecl:brn pid:396113351 byr:1956 iyr:2010 hcl:#6b5442 eyr:2024 cid:256 hcl:#efcc98 hgt:178cm byr:1984 iyr:2013 pid:752620212 eyr:2021 ecl:gry iyr:2014 hcl:#a97842 hgt:166cm ecl:blu eyr:2024 byr:1935 pid:836748873 cid:236 ecl:amb hgt:168cm iyr:2010 hcl:#602927 byr:1950 eyr:2026 pid:404810674 eyr:2030 ecl:grn byr:1975 pid:064596263 hgt:193cm iyr:2019 cid:71 hcl:#a97842 iyr:2014 pid:298386733 hcl:#c0946f hgt:180cm ecl:hzl cid:115 byr:1940 eyr:2023 iyr:1960 hgt:139 ecl:#9db7b8 byr:1980 pid:#ef597b cid:54 eyr:2028 hcl:fdcda3 iyr:2015 byr:1954 ecl:blu hgt:62in hcl:#ceb3a1 pid:253593755 eyr:2028 eyr:2025 ecl:blu pid:216388098 iyr:2017 byr:1968 hgt:151cm hcl:#602927 eyr:2022 hcl:#a97842 pid:606979543 iyr:2013 ecl:grn cid:63 hgt:186cm byr:1992 ecl:gry hgt:168cm hcl:#18171d iyr:2017 pid:670898814 byr:1983 eyr:2022 hgt:155cm ecl:grn iyr:2012 pid:837979074 eyr:2024 hcl:#888785 byr:1972 iyr:2015 pid:970743533 hcl:#866857 eyr:2027 byr:1921 ecl:brn eyr:2022 hgt:160cm byr:1964 hcl:#efcc98 iyr:2019 ecl:oth pid:141923637 byr:2029 pid:3313111652 ecl:brn eyr:2034 iyr:2013 hgt:193cm hcl:z pid:853890227 eyr:2029 hcl:#efcc98 iyr:2021 byr:2003 ecl:#037c39 hgt:160cm iyr:1927 byr:1992 eyr:2030 hcl:#efcc98 ecl:amb hgt:152cm pid:436765906 iyr:2014 hcl:#c0946f pid:207052381 eyr:2024 ecl:hzl hgt:177cm byr:1923 ecl:blu iyr:2014 eyr:2025 hgt:165cm hcl:#733820 pid:343011857 byr:1967 ecl:xry eyr:2028 iyr:2011 hgt:166in hcl:#c0946f pid:805297331 cid:167 byr:1926 byr:1947 pid:468012954 eyr:2026 ecl:oth iyr:2018 hgt:170cm hcl:#b6652a hcl:#6b5442 ecl:brn hgt:180cm cid:233 pid:029789713 byr:1920 iyr:2010 eyr:2024 iyr:2010 eyr:2027 hgt:156cm hcl:#c0946f byr:1960 pid:312723130 ecl:hzl eyr:2023 byr:1959 iyr:2010 hgt:186cm pid:066768932 ecl:grn hcl:#602927 cid:310 eyr:2030 pid:460535178 hgt:171cm ecl:gry iyr:2020 byr:1934 hcl:#888785 hgt:64cm eyr:2021 byr:1995 cid:336 ecl:gmt pid:926714223 iyr:2017 hcl:#18171d eyr:2022 iyr:2010 ecl:grn pid:285994301 cid:215 hgt:186cm byr:1978 hgt:63in hcl:#866857 pid:386128445 iyr:2020 byr:1971 eyr:2021 ecl:gry hgt:183cm hcl:#733820 iyr:2015 ecl:blu pid:216205626 eyr:2022 byr:1941 cid:150 ecl:amb pid:872515243 byr:1926 eyr:1996 hcl:#dedc39 hgt:67in iyr:2020 byr:1927 ecl:brn cid:153 iyr:2011 pid:165190810 hcl:#fffffd eyr:2028 hgt:64in pid:502603734 byr:1966 iyr:2015 hgt:176cm cid:205 ecl:brn hcl:#fffffd eyr:2021 hcl:#18171d hgt:158cm byr:1943 iyr:2019 pid:058840094 eyr:2023 byr:1962 hcl:#b6652a ecl:grn cid:297 iyr:2010 pid:990422650 hgt:154cm eyr:2020 eyr:1934 iyr:2011 ecl:gry hcl:z byr:2004 hgt:63cm pid:6173356201 pid:329432364 eyr:2029 ecl:grn hcl:#18171d iyr:2013 hgt:158cm byr:1960 hcl:#efcc98 iyr:2016 hgt:186cm cid:215 pid:852781253 eyr:2027 ecl:blu byr:1937 hcl:#623a2f ecl:gry iyr:2020 byr:1972 hgt:182cm pid:073426952 eyr:2027 hcl:#3317b9 byr:1950 pid:304511418 hgt:177cm cid:124 eyr:2020 ecl:hzl iyr:2014 eyr:2029 pid:034754507 byr:1936 cid:265 ecl:#b50997 hgt:183cm hcl:#623a2f iyr:1924 eyr:2024 byr:1927 cid:243 ecl:gry hcl:#6b5442 pid:714355627 hgt:160cm iyr:2016 hgt:152cm ecl:gry hcl:#a97842 eyr:2029 byr:1952 pid:555308923 iyr:2010 byr:2008 pid:19681314 hgt:180in iyr:2030 ecl:gry cid:272 eyr:2023 hcl:#b6652a cid:234 iyr:2014 byr:1940 ecl:hzl pid:042231105 hcl:#3bf69c hgt:172cm eyr:2029 hcl:#efcc98 pid:831567586 hgt:190cm iyr:2017 byr:1966 eyr:2024 ecl:blu hcl:#341e13 ecl:blu eyr:2022 cid:161 pid:197839646 iyr:2014 hcl:#cfa07d byr:1957 iyr:2019 hgt:181cm pid:543775141 ecl:oth eyr:2021 hcl:z pid:#596c41 eyr:2035 byr:2008 iyr:1975 ecl:#c66ee6 hgt:150in ecl:grn hcl:#7d3b0c iyr:2016 pid:804255369 eyr:2028 byr:1983 hgt:69in cid:82 eyr:2022 iyr:2013 hgt:191cm ecl:gry hcl:#a97842 pid:186827268 byr:1969 pid:871672398 eyr:2026 byr:1946 ecl:oth iyr:2015 hcl:#866857 hgt:185cm byr:1973 hgt:150cm pid:905076707 iyr:2017 hcl:#2edf01 ecl:oth cid:221 eyr:2026 eyr:2024 ecl:grn pid:955444191 hcl:z iyr:2015 byr:2008 hgt:151cm byr:1958 hcl:#fffffd pid:218986541 cid:203 ecl:brn hgt:154cm iyr:2014 eyr:2026 hcl:#623a2f byr:1964 ecl:oth iyr:2010 pid:525843363 hgt:164cm eyr:2025 ecl:blu iyr:2013 hgt:193cm byr:1990 pid:612387132 hcl:#18171d cid:280 eyr:2028 ecl:oth eyr:2022 pid:110447037 hgt:187cm byr:1967 hcl:#efcc98 byr:1930 eyr:2026 hgt:159cm iyr:2011 ecl:hzl hcl:#6b5442 pid:923471212 cid:350 eyr:2029 pid:823592758 iyr:2018 ecl:grn byr:1972 hgt:167cm hcl:#18171d cid:76 eyr:2027 hcl:#6b5442 pid:099579798 byr:1930 iyr:2020 ecl:gry hgt:153cm byr:1957 ecl:brn hcl:z iyr:2016 pid:352677969 hgt:189cm eyr:2029 cid:143 eyr:2035 pid:602952079 ecl:#9b73f0 hcl:#602927 iyr:2022 byr:1975 hgt:174cm byr:1971 pid:741305897 hgt:192cm ecl:amb hcl:#888785 eyr:2028 iyr:2011 ecl:oth iyr:2016 byr:1942 hgt:189cm hcl:#888785 eyr:2024 pid:054290182 hcl:#a97842 byr:1945 ecl:amb pid:370849304 eyr:2028 iyr:2016 hgt:168cm hgt:154cm iyr:2015 eyr:2030 byr:1952 ecl:hzl hcl:#341e13 pid:996518075 byr:1941 ecl:amb iyr:2014 hcl:#fffffd pid:560990286 eyr:2022 hgt:173cm ecl:blu byr:1974 hgt:150cm hcl:#ceb3a1 eyr:2020 iyr:2013 pid:827415351 hcl:#623a2f eyr:2027 iyr:2011 pid:913199234 ecl:oth byr:1990 hgt:178cm ecl:blu byr:1989 hcl:#b6652a eyr:2026 pid:724881482 hgt:185cm iyr:2014 cid:115 pid:255002731 eyr:2025 ecl:amb byr:1934 iyr:2020 hcl:#7d3b0c hgt:150cm byr:1969 ecl:blu iyr:2023 hcl:#866857 pid:754288625 eyr:2029 iyr:2011 hcl:#7d3b0c ecl:hzl byr:1930 hgt:188cm eyr:2023 pid:256556076 cid:136 iyr:2025 byr:1978 ecl:#fe30a9 hcl:#efcc98 eyr:2029 pid:392032459 hgt:178cm eyr:2027 iyr:2017 hgt:160in byr:1990 pid:131099122 hcl:#623a2f ecl:amb ecl:grn byr:1978 eyr:2029 hcl:#18171d hgt:165cm pid:172369888 cid:93 iyr:2011 ecl:hzl hcl:#733820 iyr:2010 eyr:2029 pid:127253449 hgt:156cm byr:1963 hcl:#6c8530 iyr:2020 byr:1929 eyr:2021 hgt:177cm ecl:oth pid:347925482 eyr:2037 iyr:2026 pid:163cm hgt:174in byr:2007 hcl:c1305f cid:134 ecl:#0cf85c iyr:2011 pid:033811215 hcl:#a97842 byr:2002 eyr:2021 hgt:186cm ecl:brn hcl:#a97842 iyr:2020 eyr:2029 byr:1972 pid:535511110 hgt:160cm ecl:oth ecl:grn cid:89 hgt:193cm pid:73793987 iyr:2021 eyr:2027 byr:1939 hcl:z hcl:#623a2f hgt:182cm cid:154 pid:873863966 iyr:2018 byr:1999 ecl:brn eyr:2031 iyr:2014 eyr:2029 cid:71 hcl:#fffffd byr:1924 hgt:63in ecl:gry pid:897972798 hgt:76cm hcl:z eyr:1955 iyr:2012 byr:2001 pid:9425090 ecl:hzl eyr:2021 pid:501861442 ecl:grn hcl:#d71ae9 byr:1977 hgt:167cm iyr:2015 iyr:2014 hgt:170cm ecl:gry byr:1928 cid:314 hcl:#602927 eyr:2029 pid:836710987 eyr:2027 hcl:#efcc98 ecl:amb iyr:2016 byr:1995 pid:603705616 hgt:179cm eyr:2030 hcl:#602927 cid:105 byr:1943 ecl:hzl pid:381601507 hgt:188cm iyr:2020 iyr:2011 byr:1993 hcl:#c0946f pid:292649640 hgt:139 ecl:hzl cid:268 eyr:1999 cid:339 byr:1928 ecl:brn eyr:2022 hcl:#733820 hgt:191cm pid:282733347 iyr:2019 hgt:176cm byr:1935 ecl:brn cid:252 eyr:2023 pid:105060622 iyr:2020 hcl:#18171d ecl:hzl eyr:2029 hgt:193cm pid:770254253 hcl:#efcc98 iyr:2020 byr:1926 pid:977785261 eyr:2022 iyr:2015 byr:1978 hcl:#733820 hgt:172cm ecl:brn byr:2021 hgt:160in ecl:gmt eyr:2032 cid:345 pid:179cm hcl:8f5c13 iyr:2029 iyr:2018 hgt:182cm ecl:gry pid:897076789 eyr:2023 hcl:#866857 byr:1980 hgt:88 eyr:2039 cid:99 byr:2007 hcl:a1bb42 ecl:#a2f6bb pid:2264966188 iyr:2022 iyr:2012 cid:59 ecl:gry eyr:2021 byr:1931 hgt:172cm hcl:#7d3b0c pid:862416147 byr:1962 eyr:2025 ecl:grn hcl:#866857 hgt:180cm iyr:2014 pid:313647071 eyr:2030 hgt:157cm byr:1985 iyr:2020 hcl:#7d3b0c pid:911544768 ecl:grn hgt:175cm byr:1938 iyr:2020 ecl:amb hcl:#602927 eyr:2026 pid:144411560 iyr:2019 ecl:amb hcl:#888785 eyr:2025 hgt:187cm pid:942054361 byr:1939 cid:168 pid:722146139 byr:1952 ecl:grn iyr:2014 hgt:97 hcl:z eyr:2023 eyr:2024 pid:567528498 ecl:gry iyr:2012 byr:1990 hcl:#733820 hgt:193cm cid:293 hcl:#bc352c pid:321838059 byr:1930 hgt:178cm cid:213 eyr:2023 ecl:amb iyr:2017 hgt:173cm byr:1925 pid:070222017 iyr:2013 hcl:#ceb3a1 ecl:gry eyr:2024 ================================================ FILE: exm/aoc/2020/aoc_2020_04_b_full_ada.adb ================================================ -- 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; ================================================ FILE: exm/aoc/2020/aoc_2020_05.adb ================================================ -- Solution to Advent of Code 2020, Day 5 ------------------------------------------- -- Binary Boarding -- -- https://adventofcode.com/2020/day/5 -- -- Binary space partition in the plane for -- locating seats. -- F means "front", B means "back", -- L means "left", and R means "right". -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_05 is f : File_Type; x : Character; max, id, r, c, b : Integer; test_mode : constant Boolean := Argument_Count >= 1; begin max := 0; Open (f, "aoc_2020_05.txt"); while not End_Of_File (f) loop r := 0; b := 64; for i in 1 .. 7 loop Get (f, x); if x = 'B' then r := r + b; end if; b := b / 2; end loop; c := 0; b := 4; for i in 1 .. 3 loop Get (f, x); if x = 'R' then c := c + b; end if; b := b / 2; end loop; id := r * 8 + c; if id > max then max := id; end if; exit when End_Of_File (f); Skip_Line (f); end loop; Close (f); if test_mode then if max /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Maximum seat Id in the plane = " & max); end if; -- Part 1: validated by AoC: 835 -- Part 2: validated by AoC: 649 end AoC_2020_05; ================================================ FILE: exm/aoc/2020/aoc_2020_05.txt ================================================ FFFFBFBLLR BFBFFBBLLR BBFFFFBLRR FBFBFFFRLL BFFBFFFRRR BFBFBFFRLR FFFBBBBLRL BFFFFBFLLL FFFFBBFLLR BBFFBFFRRR FBBFBBFLRL BFBFFBFLRR FBFFBFFLLL FFFBFFFRLR FFFBFBBLLR BBFFBFFLRL FFFFFBBRLR BFFBFBBLLR FFBBBBBLRR FBBFFBBLLR FFFFFBBLLR FBBFFFBRLR FFBFBBFRRR FBBFFFFLRL FFBFBBFLLR BFBBBBFRRL FFFFBBBLLR FFBFFFFRLL FFBBFFBLRL BBFFFBBRLR FBBFBBFRLL FBBBFBFRRR FBBBBBBRLR BFBBFBBRRL FBBBBFFRLR FBFBFBBLLL FBBFFFBLRL BFFBBBFRLL FFBFFBBLLL FFFFFFBRLL BFFBFBFRLR FBBFBBBRRL BFBFBFFLLR BFBFBFBRLL FBFBBBFLRL FBFFFBFRLR FBBBBBBRRL BFBBFFBLLL BFFFFFBLRR BFFBFFFLRL FBBBFFBLLL BFBFBFFLRR BFBFBFFRRL FBBBFFFLRR FFBBFFBRLL BFBFFFFLRR FFFFBBFRRL FFFFBBFLRL BFFBBFBRRR FBFBBFBRRR FFBFFBFLLR BFFFFBBLRL FBBFBFFLRR BFFBFBFLLL BFFBFBFRRR FBBBFFBRLL FBFFFBBRRL BBFFBFFRRL BBFFBBFLLR BBFFFBBRLL FFFBFFBLRL BBFFFFBRRR FBFBBFBRLR BFBBFBFLLR FFBFFFFRLR FBBFFFBRRR FFFBFFFLLL FFBBFFFRLL FBBBBFBLRR BFFFBFFRLR FFFBBFBRRL FBFFBBBLLL FBFFBBFLRR BFFBFFBRLR FBBBBFBRLR BFBBBBFRRR FBBFBBFLLR FBBBFBBLRR BFFFBFFLRR FFBBBBFLRR FBFBFFFRRR FBBFFBFLRL FBBFFFFLLL BFFFBBBRRL FFBBBFFLLL FFFBBBFLRL FBBFFBBLRL BFFFFFFRLL BFBBFBBRRR FBBBBBFLRL FFBFFFFLRR FBFFBBFRRR FFBBFBBRLL FBFFBFBLLR FFBBFFBLLL FBFFFBBLLL FBFBBFBLLR BFFBFBFLLR FBFBBFFLLR BFBFBFBRRL BFBFFBBRRL FFBFFBFLRL FBBFBFFLRL FBFFFBBRRR BFBFFFFRLR BBFBFFFLRR BFBBFFFLRL FFBFBFBLRR BFFFBBBLRL FBBFBFBLRR FBBFFBBRLR BFBBBFBRRL FBBBFBBRRL BFBFBBFLLL FFBBFBBLRL FBBBFBFLLL BFFBFFBLLR FFFBFBBRLR FBFBFBFLRR BBFFBBBRLL BFBBFBBLRR BFBFFBFRLL FBBBBBFRLL FBFFFFBRRR FFFBFFBLLL FFFBFFBLLR BFFFFBBRLL FBBFBBBLRR BFFFBBBLRR BFBBFBBRLL FBFBBFBLLL FFBBFBBRRR BBFFBFBRRL FBFFFFFLRR FFBBFBFRRL BFBFFBFRRR FFBFBBFRLR BFBBBFBLLL FBBFBFBRLL BFBFFBBRRR BFFBBFBLLL BBFFFBFRRR FFFBFFFRRL FFFBBFFRLL BFFFFBFRLR BFFBFBFRRL FBFFFFFLLR FFFFFFBRRR BBFFFFFLRR FBFBFFBRLL FFBFBFBLLL FBFFBFFRRL FBBBFFFRLL BFFFFBBRRL BFFFFBBRLR FFFFBFFRLL BBFFFFBLRL BBFFBFFLLL FBFFBBFLLL FFFBFBFLLL BFBFFFBLRL BFFFFFFRLR BFBBBBBLLR FBBBBFBRRR FFFFFBBLRR FBFFFBBRLR FBFFBBBRRR BFBFFBFLRL BBFFFFBRRL FFFBBBBLLR BFFFFFBLLL BFFBFFFLRR FBFFFFFLRL FFFBBFFLLR BFBBBFFLRR FFBBFFBRRR FFFFBFBRRL FBBFBBBLLL BFBFFBBLRL BFBFBBFRLL BFFBBBFRRR BFFFBBFRRL FFFFBBBLLL BFFFFFFLLR FFBBFFBLRR BFBFFBBLRR FBFBFBBLRR BFBFFFBLRR FBBBFBFLRR FFBBFFBRLR BFFBBBBRRR FFFFBBBLRR BBFFBBBLRL FBBBFBFRRL FFBFBBFLRL FFBBBFBRRR FFFBFBFRLL FBFFFFBLLL FBFFBBBLLR FFBFBBFLLL BFFBBFFRLL FFFFFBFRRL FBBFBBBLRL FBBBFFBLRR BFFFBBBRLL FBFFFFFRLR BFBBBFFLLR BBFFBBBRRR BFBFFFFRLL BBFFBBFLRR BBFFBFBLLR FBBFFFFRRL BFBBFBFRRL FBFFBBBLRR BFBBFFBRLL BBFFBBFRRL BBFFBFBRRR FFFBFBFLRL FBFFFFFRLL BFFFBBFLLL FBBFFBFLRR FBFBBBBRRR FBFFBBFRLR FBBBFFFRRR BFFFBBFRRR FFBFBFBRLL BFBFBFBLRR BBFFBBBLLL BFFBBBBRLL FBFBFBFLLR FBBBBBBLLR BFBFFBBRLL FBFBFFBLLR BFFBBFBLRR BFFBFFFLLL FBBFBBFRLR FFFBFBFLLR BFFBBFBLRL FFFFBBBRLR FFBFFFBRLR BBFFFFFRLL BFFBBBFLRR BBFFBBFRLR FBFFFFFRRR FBBFBFBRLR FFFBFFFRLL BFBBFFFRRR FFFFFBBRRL FBBFFFBRLL FBBBBBFRLR BFBBBBFLLL FBFFFFBRRL BBFFFFFRLR FFFBFBBRRR BFBBBFFRRR BFBFBFBLLL FFFFBFBLLL FBFBFFBLRR BFFFBFFLRL FFFFBFFLRR FBBFBBBRRR BFBFBBBLRR BFFBFBBRLR BFBFBBFLRR FFFBBFFRLR BFFBBBBRLR FBFBFFBLRL FFFBBBFRLL BFBFBBBRRR FFFBFBBRRL FFBFBBBRLL FBFBBBBLRL BFFBBFFRLR BFFFBFBLLR BFFBBBBLRR FFBFFBFLLL FFBFBBBLRR BFFFBBFLRR BBFFBBFLRL FBBFFFBLRR FFFBBBFLLL FBBFBBBLLR BFFFFBFLRL BFFBFBFLRR FBBFFFBLLL BFBFBBFRRR FFFBBFFLRL FBBFFBBRRL FBFBFFFRRL FBFFBFFLLR BFBBFBBRLR BFBFBFFRLL FFBFFBBLRR FBFFBBFRRL FBFBFFFRLR FBFBFBBRLL FFBBBFBLRL FBFFFBFRRL BFFBFFBRRL FFBBBBBRLL FFFBBBBLRR FFFFBFFRRR FBBBBFBRLL BBFFFBFLRR FBFBFFBRRR FFBBBFFRRR FBBFFBFRRR BFBFBFFRRR FFFBBFBRRR FBBFBFFLLL FFBBFFFLLL FFFBFFBLRR FFFBBBBRRR FBFFBFFRLL FBFBFFBLLL FFFBFFFRRR FBBBBFFLRL BFBBFFFRRL BFBBBFFLLL BFBBFFFLLR BFFFBFBRRR FFFFBBFRLR BFFFFFBRRR BFFBBBFLLL FBFFFBFRRR FBFFFFBLRL FFBFFFFLLL BFBFBBFLLR FBBBBFFLRR FFBBBFBRLL BBFFFFBRLL BFBBFBFLRR BBFFBFBLRR BBFFBBFRRR BFFFBBFLLR FFBBBFFRLL FFBFBFFLLR FFBFFFBRLL FFFBBFFLLL BFBBBFBRRR FFFBFFBRLR BBFFFBBRRR FFBFBBBRRL FFBFFBBRLL FFFBBBFLRR BFBBBBFLLR BFBFFFBLLL BBFFBBBLLR BFFBBFFLRR FBFFBFBLRR FFBFBFFLLL FFFBBBBLLL FFFFBBBLRL BBFFBFFLLR BFBFBBFRLR BFFFFBFRLL BFFFFBBRRR FBFFFBFLLR BFFFBBFRLR FBBFFBBRLL FBBBBBBRRR FFBFBFFLRR FFBFFFBLLR FFFFBBBRLL FFFBBBFRLR FBFBBBFRRL BFFFBFBRLR FFFFBBBRRR FFFBFFFLLR FBBFFBFRRL FBBBBBBRLL FBBBFFBLRL BFFBFFFRRL FBFBBBBLLR FBFBBFBLRL BFFFFFBLLR BFBBBFBRLR BFFBFFBRRR FBFFBFBRRR BBFFBBFLLL FBFBBBFLLL FFBBBBBLRL FBBFBBFLLL FBBBFFFRLR FBFBFFBRRL FBBFFBBLRR FBBBFBBLRL BFFBBBFRLR FFFFBBFRLL BFFFBFBLRR FBBBBBFRRL FBFBFFFLLR FFBBBFFLLR BFBBBBBRLR BFBBFBBLRL FBBBFBBRLL FBFFBBBRLR FBFFBBFRLL BFBFFFBRLL FBBBFBBLLL BBFFFBFLRL FBFFBFBRLR FBFBFBFRLL FFBBBFBRRL FFBFFFBRRL BFBFBFFLLL FFBFFBBRRL BFBBFBBLLR BFBBFFBRLR BFFFFFFLLL FBFBBBBRRL BFBBFFFLLL FFFFFBFLRR BBFFFBFLLR FFBFFFBLRR FFBBBBBRLR BFBFBBBLRL BFFFFFBRRL FFBBFFFLRR BBFFFFBLLR FBBBFFFLLR FBBFFBFLLR FBBFFBFRLL FBFFFBBRLL FFBFFFFRRR BBFFBFFLRR BFFBFBBLRR FFBBBFBLLL BFBBBBFLRL BBFFFBFLLL FBBFBBFRRR FFBBFFFLRL FBBFBBFLRR BFFBFFFRLR FFBBFBFRLL FBFBFBFLRL BFBFBBFRRL FFFFBFFRLR BFFFFFFRRL FFFFFBBRLL FBFBFFBRLR FBFBBFFRLR FFFFBBFRRR FBFBBBBRLL FFFBBBBRLR FBBFBFFLLR FFFBBBFRRL BFBFFFFLRL FFBBBFFRLR BFBFBFBLLR FFFFBFBLRL FBFBFFFLRL BFBBFBFRLL FBBBBFBLLR FBFBBBBRLR FFFBBFBLRL FBFFFBBLRL FBFFFFFRRL FFBBBBFLLR FFFBBFBRLL FBFBFBFRLR FFFBBFFRRR BBFFFBBLRL BFFBBBBLLL BBFBFFFLRL FBFFBBFLRL BFFFFFFLRR FFBBFFFRRL FFFFFBBRRR BFFFBFFRRR BBFFFFFRRR BBFFFBFRRL FBBBFBFLLR BFFBBBBLLR FFFFFFBRLR FBBBFBBRRR FFBFFFBRRR BFFBFFBLRL BFBFFBFRRL FBFBFBBRLR FFFBFBBLRL BFBBBFFRLR FBFFBFBRLL FFFFFBBLLL FFFFBFFRRL FFBBBBFRLL FBBBFFBRRR BBFFFFBLLL BFBBFFFRLL BFBFFFBRRL FBBFBBBRLL FFBBFBFRLR FFFBFBFRRR BFFBBFFLLL BFFBBBFRRL BFBFFFFRRL FBFBFBBLRL FBFBBFFRRR FBFBBBFRLR FFBFBBBLLL FFFBBBFLLR FFBFBFBRLR FBFBBFBRLL FBBFBFBRRL FBBBBBFRRR FBBBBFBRRL BFFFBFBRRL FFFFBFFLLL BFBBFBFLLL BBFFFBBLLL FBFBBBBLRR BFFBBBBRRL FBFFFFBRLR FBFFBBBRRL FFFBFFFLRR FBBFFFFLRR BFFBFFBLRR FFBFBFBRRR FBFBBFBLRR BFFFFBFLRR BFBBFFBLRL FFBBBBBLLR FBBBFBBLLR FFFBBFFLRR FFBFFFFLRL FFBBFBFLRR FBFBBBBLLL FBBFFFBRRL FFFBFBFLRR BFFFBFFLLR BFBFFBFLLL BFBFFFFRRR FFFFFFBLRR FBFFBFBLRL FBBFBFFRRR FBFFBBBLRL FBFFBFBLLL FFBFBFFRLR FFBFBBBRRR BFBBBFBLLR FFBBBFFLRR FBBBBBFLLR BFFBFBFLRL BFFBBBFLRL FFBFFFBLRL BBFBFFFLLL FBBBBBFLRR FFBFBFFRLL FFFFBFBRLR FBBFBBBRLR FFFBBBBRLL BFBFBBBRLR FFFFBBFLLL FBBFBFFRLL FFBFBFFRRR FBBFFBBRRR BFBBFFBRRL BFBBBFFRLL BFFFFFBRLR FBFFBFFRLR FFBFBFBRRL BBFFBBBRLR FFBFBFFLRL FFFBFBFRLR BBFBFFFLLR FBBFFBBLLL BFFFBFBLLL BFFBBFFLLR BFFBBFFRRL BFBBBBBRLL BFBBBBFRLR BFFFFFBLRL FBBFBBFRRL FBBFBFBLLL BFFBFBBRRR FFBBBFFLRL BBFFBFFRLR FBBFFFBLLR FBBFFFFRLR FBBBBFBLRL BFFFFBBLLL FFBFFBBLLR FBFBBFBRRL BFFFBBBRRR FBBFFFFLLR FBFBBFFLRL FFBBBBFLRL FFFFFBFLLR BFFFFFFLRL BFFFBFFRRL FBBFBFFRRL BBFFFFFLLL FFFFFBFRRR FBBBFFBLLR BFFBFFBRLL FBFFFBFRLL FFFBFBBLLL BFBFBBBLLR FBBBBFBLLL BFBFBFBLRL BFFBFFFRLL BFBBFBFLRL FBBFFFFRRR FFBBBBFRLR FFBBFBBRRL BFBFBFFLRL FBBBBFFLLR FBFBFBBRRR FFBFBFBLLR BFFBFFBLLL FFBFBBFLRR FFBFFBBLRL FFBBFFFLLR BBFFBFBLLL FBFBFBFRRL FFBFFBBRRR BFFFFFFRRR BFBFBBBRRL FFBFBBBLLR FFBFBBFRRL FFBBBFBRLR FBFFFBBLLR FFBBFBFRRR FBFFFFFLLL FFFFFFBRRL FFBBBBFRRL FBFFBBBRLL BFBBBBBLRL FFBBFBFLRL BBFFBFBRLL FFFBBFBLLR BBFFFFFRRL FFBFFBFRLR BFFBFBFRLL BFBBBBBLRR FFBFFBBRLR BFFFBFFLLL BFBBBFBRLL FBBFFBFRLR FFBFBBBLRL BBFFFBFRLR BFFFFBFRRL BBFFFFFLRL BFBFFBBLLL FFFFBFFLLR FBFFBFFLRL BFFFBBFLRL BFBBFFBLRR FFFFBFFLRL FFFFFBBLRL BFBBBBFLRR BFBBBBBRRL BFFFBFFRLL BFBFBBBRLL BFBFFBFRLR FFFFBFBRRR BFFBFBBLLL BFBBFBFRRR FBFBFBBRRL FFBFFBFRRL FBBFBFBLRL FFBFFFFLLR BFFFFBFRRR BFFFFFBRLL FFBBBFBLLR FFBFFBFLRR FFBFBFFRRL BFFBFBBRRL BBFFFFBRLR FBBBFFFLRL FBFBFFFLRR BFFFBBBLLL FFFFFBFLLL BFBBBFFRRL FBFBFFFLLL BFBFBBBLLL BFBBBBBLLL FFBBFFBLLR FBBFFFFRLL BFBFFFBRRR BFFBFFFLLR FBFBBBFLRR FBBBFFFLLL FBBBFFBRLR FBBBBBBLLL BFBFFFFLLL BFFBBFBRLR BBFFFBBLLR BFBBFFBRRR BFFBFBBRLL BFBBBFBLRR BFFFFBFLLR FBBBBFFRRR FBFFFFBLRR BFBBFBBLLL FBFBFBFRRR FFFBBBFRRR FFBBFFFRLR FBBBBBBLRL FFFBFFBRRR BFFFFBBLRR FBFBFBBLLR FFBBFBBLLR FBBBFFBRRL FBFFFFBLLR BFFBFBBLRL FFFBFBBLRR BFBFBBFLRL BFFBBFBLLR BFBFBFBRLR BFFFBBBLLR FFFFBBFLRR FBBFBFBRRR FBFFBBFLLR BBFFFBBRRL FBFBFBFLLL FFFBBBBRRL FBBBFBFRLR BFFBBBFLLR BFBBBFBLRL BFBBBFFLRL BFFBBFBRRL FFFBFBBRLL BFFBBBBLRL FFFBBFBRLR FFBFBFBLRL BFFFFBBLLR FFFFFBFRLR FFFFBFBRLL FBFFFBBLRR FBBBBFFRRL BFFBBFFRRR BFBBBBBRRR FFBFFBFRLL BBFFBFBLRL FFFFFBFLRL BFBBFFBLLR FBBBFBFLRL BFFFBBFRLL BFBFFBFLLR FFBFBBBRLR BFFBBFFLRL FFFBFBFRRL BFBBFFFRLR BFBFFFFLLR FFBFFFFRRL BBFFBBFRLL BBFFBBBLRR FFFBFFFLRL FBFBBFFRLL FBBBFBBRLR FBBFBFBLLR FFBFFFBLLL FBFFFBFLRL FBBBBBBLRR FFBBBBFRRR BFBFBFBRRR FBFFBFFLRR BFBBFFFLRR BBFFBFBRLR FFBBBBFLLL BBFFBBBRRL FFFBFFBRRL BFFFBBBRLR FFBBFBFLLR FBFFBFFRRR FFFFFBFRLL FBFBBFFRRL FFBBFBBLRR BBFFFFFLLR FFBBFFFRRR FFFBBFBLLL FBFBBBFLLR FFFFBBBRRL BFBFFBBRLR FBFBBBFRRR FFBBBFFRRL FFFBBFFRRL FBFBBFFLRR FBFFBFBRRL BBFFFBBLRR FFBBBBBRRL FBFBBBFRLL BFBFFFBRLR FBFBBFFLLL BFBBBBFRLL FBBBBFFLLL FBFFFFBRLL FFBBFBFLLL FBFFFBFLRR FFFBFFBRLL FFBBBFBLRR FFBBFFBRRL FFBBFBBLLL FFBBFBBRLR FFFFBFBLRR BFBBFBFRLR BFFFBFBRLL BBFFFBFRLL FFFBBFBLRR FBBFBFFRLR FBBBFFFRRL FFBBBBBRRR FBBBFBFRLL FBBBBFFRLL FFBFBBFRLL BFFBBFBRLL FFBFFBFRRR FFBBBBBLLL BFFFBFBLRL FBBBBBFLLL FBBFFBFLLL BBFFBFFRLL FBFFFBFLLL ================================================ FILE: exm/aoc/2020/aoc_2020_06.adb ================================================ -- Solution to Advent of Code 2020, Day 6 ------------------------------------------ -- Custom Customs -- -- https://adventofcode.com/2020/day/6 -- ------------------------------------------------------------------------- -- -- HAC 0.084 "nice to have"'s detected in this exercise: -- -- * ` clear := (others => False); ` -- * ` rg := rg and r ` for arrays of Boolean (i.e., sets) -- * ` aaa : constant Character := 'a';` -- HAC should detect an expression as a -- static (compile-time-known) value -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_06 is total : Integer; new_group : Boolean; subtype Answer_Range is Character range 'a' .. 'z'; type Yes_Answer is array (Answer_Range) of Boolean; r, rg : Yes_Answer; -- procedure Collect_Group_Total is g : Natural := 0; begin for c in Answer_Range loop if rg (c) then g := g + 1; end if; end loop; total := total + g; new_group := True; end Collect_Group_Total; -- f : File_Type; s : VString; test_mode : constant Boolean := Argument_Count >= 2; begin for part in 1 .. 2 loop Open (f, "aoc_2020_06.txt"); total := 0; new_group := True; while not End_Of_File (f) loop -- Collect answers from every group on the plane. Get_Line (f, s); if s = "" then -- Blank line: group separator. Collect_Group_Total; else for c in Answer_Range loop r (c) := Index (s, c) > 0; end loop; if new_group then rg := r; new_group := False; elsif part = 1 then -- Count the number of questions to which anyone answered "yes" for c in Answer_Range loop rg (c) := rg (c) or r (c); end loop; else -- Count the number of questions to which *everyone* answered "yes" for c in Answer_Range loop rg (c) := rg (c) and r (c); end loop; end if; end if; end loop; Collect_Group_Total; if test_mode then if total /= Integer_Value (Argument (part)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part " & part & ". Total customs answers: " & total); -- Part 1: officially validated by AoC: 6532 -- Part 2: officially validated by AoC: 3427 end if; Close (f); end loop; end AoC_2020_06; ================================================ FILE: exm/aoc/2020/aoc_2020_06.txt ================================================ qtmdwspah sqwdamhpt phwdaqsmt stmdqwhap pqawdhtms bgsickuztovfwa yiozauvgfsbtkwc zygijavmtfkcuwobs fvsuwtiadzrncboklg dxgieku dihnxkgf mqybtd yqbtd btydq rgpbcfxtzoewy otbyrfgwxzpec yocrwtebzxgfp qcpngeodrszaky ocaqrngsyuz xwenu nwsxuye xapwvhsktlmr twpslarxhvkm vhlwmrapxkts pmkxraswvlth ksrxpvtmwahl xhcepbdsltvk khcdptsixbg spbjtdchxk cbkxspqtdrh kaishmtdl jcnprqigt pjqtekodlmwcaginxfzrushbv iuyzsfaxcvrotdmklgebpnjwqh dirxeqbswlonhzumgafvckptj zqpitfrjnmhvuxbcdlwkogase khncmsfdzlgwpvriotxujbaeq motb twm mvt nomt euwhdnlaxbtjiqz dquxjznhtlwebia atzdwxqiunhlebj jnwlzxdiuaheqbt jnktcwaovpbqzei qcrljzskbvo tangojspuvlwbryeicz eujvkaporgwdilbyfscztn pjrisxqwdoyze cvyzmjlqxsgpeirw xieqwcajzslryp xjpzerwqyamis rftxglbkpqnchvajs cnsvqgpurtjfeb m mcx wramgjy mv meacfoiqpbzy zmvqpaibegoyfc oiyzmaengcfbpq uiaqprbycmzfoe qjdnecvmsr sdmecpqn gt tg bndhmeupwszlqiycofkt fcrptkulhixjnazvmdg nrcytwdaozvbmhsjuk owarihdekqzslvnxmubyfpj suzlnmxvkwjyodhbrag fz zf zefpk fz fz zfnqcdhvjwxa hxfazjcwd xzhtajkfwcd weusntyxblcdqpvgfzoam oxiyslgabqvdhnwzm jneuovbpgfxlsmkwd kjbwonlspfdumcegthv omvfbgejaiwnkdulsp orfgdlbqjkvhumpewns mhb hb dhjxb boh af tzlbugdkq j qhgnav ngvahqp gvnqha hoer oufeq u gmy td naguhdzsmcxlye pglwjsvxzduc uosgxqzldct xugcszld qcxsgtlzoud uoxacitdkeh kypudjgbsefi bjywqhgcps uaybelqkjpiwc yblwqpjec jwvyrcpbqzt qjgywbocp cuvwxkmrnliodphaj rvuzcdxknphol hprvkucdonsxl qtgjunkhaovbw wkgvotljhbq blfvtr vrtfby mbtvjdfnr xbftpvrh svbrhptf rijakd kadnijer kqdwjifar jdrihkmaz ejnirkfda ysukmtloxgjhvnwp qjxlwnvpyzsgbutomd gxpdqomijnhkyws vyqgxmjpowhsnik mnxqhgykwiopjs fm u fc zd yplnbikosxj welcjifhgnzupo izfpwljnodctheg dtlhgznwepcojif hzwvgpcifnjleo wgpqvtcnjofhlezi azhipsvbx xwbip ixpb xbip bpxi yxhpltiuvzorefqnwm azwiylnohxmejqurftvp hvuzwfxmnqyeltpro kwxghtdyfreqmplvzuon n f a f xfoaj ofsqb eqfo canrzup znarcpu pzcnrua czaupnr puchnzra hwxtaqvsci rhxylbskwcjmoid svqexwhaic whxisc xfamongdyrhjpizqbtswl tsnermfbvidyqcwhlxuzg jz zj zj mohrs rom mro orm rnwbshdkxv vkrjwsdthnxb kjwrxhsvnb rnbhvxowas lbdahrf ralbfhd lhfadbr radhflb wztomybdgaqhu rmuohgyqbdz dgzqrumoayhb hgqdmyubjpeoz mgdquhzoyb xiy yix bixoy xyi xiy xvzqjwfkhctgeayu kdjmlrow vnlu ulnvg wluvn lvun btmcqewifuh gqvakfzrmyuicsjpdbo npfy yznfx ynf b b b b b zuhkqwfpm mqpzwkhf pnwfqchkzm kfumpqzhw qzwhkmpfu pcevtdhgylnmsxaqiuzkr pxanvcgiquethzksmylrd vdszgiqyautrpxhcnmlek bhru ubhr uhvopbr trbizhud omnpx yp cpf p fuhokrpewbyvlnjcdmqi pcijvmskndtwohxylqeurf cdvfhebukmjrqnolwpiy qpwhymlcfjrndoeuivk xwehzfud wupfdexz xbdh jxdhb hmkbuyl rtcefpsaui jlfsy oknuy kvpy hcgzs hegzs sapzhd vnhjbqk bkvqnhjd vhnkqjb jhnkqvb bnhjkvq myjnp wkyjamn kmyjna rupvd pvrud rpdvu kvnlmhgizwdbjsxf nmfdkzgjxlbvsiwh zmsphibqwglkejfxrvn ge eg g g ga eivbk vikeb bkiyve puvf fvup uvfp pvuf fvup rydhgfbmpktzvlewjusn wqgfnovcerskjad ekrfsjgvowndcxq muco ouse pxoihbg bogpxhi aik k k qa aq aq aq snezvhbkwa nvzuaksbh zbvalskhn xposdbmhnavgzk thvfcbznkulas jaxdfucymsghp hfxaqcwunsjgmkpyd glfdjpuzxacyhm sp ps cesof vsu s svu sv s t te t epnq oeyqn nqe qen qne taxpglnzkejswbo zekwtongjpbxas gasokxnzbejpwty wanzsfbgpxjeotk wzxaengjkbptfso imftvao vtmif pbjelcf prnhgwqem xopmzg zfoxg xzgo ozxg gmcybniqevotjda ytiebavgdqojcnm mr m f n mnhpxfircz cihmvrxzyf ygibvxud ykubiqxgvd xydibeuv buvqdyxi budxiyv zjpqlmftionbgu tzbfgjiqoumapn nzcjuftibompqg aztbmoiqnjfgup chpnjmvlw hlbrdvqemcnwp pnkvcmlwh lmcyfwpvhn ynlmcjvipawh kzhxeqfa feaxqzkh hzxkaeqf zfqhexka fqxahkze blwqdpy yqdaniplwbe jhxbrwdylngqs qwtdylukzvbm asobzdl jahzxpdy daksz zadufl ahunxksgp sakhpun nukathps uzhnsapk pmusknahz yzmogwp tbqcp bnpcr xhp dhyxojbvrqnml nkr rnc wngra kmdynhutpjlvxaroce pbwohkjtmyfnzg tjoikmhypnsq zduqkfivgjo oizvjfuqbd zvjuqrfigdo vudqiozjf oidvqyzuftj usmo sm sm ms njf f glft auh hwiavfug xevqipr gwxdmlsuakcyf iltoavmycurph luhcarivtomxy yihcratumoevxl louhcvmiytra miqzdtolhrcayuvwg xwtcmqso xdnimfbyr okimydfr uhgzfyjqat evjdtmcoxiklhpgwq qgnxbkftmhiy ixqrakuhngytm hfzpe uefphkb afmwhqpek fvpoygjinlhexds oly byoal yol koly oyl k k k k k ofhrz xhpruzq zrh hwgrbedykvsmzin ginxcsjevrwyqz egysvqncxzrij syvgzcnreqijx zcvxgsjrqenyi qyfvzirnjcgxes eyxfutwoqjbrvkgds xsfjoutrbeqwkvgyd vqwtjgdbrsfoyukxe vfurtykqgebjwosdx eypubrkojqvdsgtfwx odwmeztifrjxn nrgmwlxc vgkxwrlnm tz tz rtz daze ezyad ujqdozgh goujdmqkzh jghuqdzo gjozdqhu erdnakojyfzchvxg hfekdrnctgvzpyjaxom hwi wih hiw hiw krqdscaoiwhnyz rwjaknoxyidzsqhpc rnyqdawcoskifghz wahrqznyvdcskiuo swlakrxjmtpv inaylxhdjwkmsvur qbxavfrlewkcsjm ucxvtw ue u lu oztxeqjvgb tpdbjgoqe spyqunh uypnhqs fdw safw wfjh wfomxi lwfsdn daibtezjo qtxeaizjmdb aoejitbkzd etadizjb jkeynazqvobiflrushcwtgdmxp wnrjequcdxlkmtfobihsvy iksvuebxtjwmhfrdqyocln gkxq pkw kw swy ywsn jzqurhixawto gaojpfrzciq izoxrtqawj asoihjqzutr wijlermdyzhstf zjlrwfsdhmtiey elymwztijfrdhs qatxy tyq nja yha a gfsav kha uebolhvntdkfsxap fpnlskhdeuobva oahteupksbvdlnf oeulbvhdpfksna ansgphkrfdlovebu vpe vedp pev pev pev zacfpshmrequykt tuzarfpmknwc pzuimacvfktr cjeqourh eouqcljr rojueqc ykoi koyi koyi kiyo fvkhuntrmpz ckngmxirpuzvat rfuvksnozpath bntdrlyvkzupj rukwpvtzcn wczery eczwrby wrzcey xjndayl hnlyaxdj lndayxj ynjdlaxt j j j tj awhrfvjbzduistx gnyhcmteop ym y sy my zkai ajiz aiz aiz ikaz irgsokuwy lnxtcqsiwmf busyvhzidw qxhpynjewsfmkd hwpqenfkydm aedbfmx fwexa jgckhspy zpusakfeb izpev sdepzu znpwe pqjgehtxzr vqmlkjznbeiofahucdtsgw utmvhgqedbocfwkszjlain yfbqzaspnlgotrdjxuhvkemiwc idglcasthofkuemnbjwqzv uqhdebp chdbquepl qedzphbu hupdqbe qbedhpu ehnv t aksmbzu wvlhktdqpjmsirz fznykbsem ksgmz kzxsymc vnoetrhlgkcmqxdp nvdqtkolcrhxep pxcedrnhoiltqvk elrxnhitcpqdokv ymuxitzqsagrkofcvbj tauxskfigjymro cnfdjwbxkisp cpydkbjxwsifn cipnkbufswdjrx ybkxihfwejnscdp yueaplwitfdvkoxnbjcmrqgz jvlfmxoakzwiegpbdnrquct manwikovgbpuhrcfesjlzxtqd lptzwxfn fpnxtlz nxtflegzpj dkpuyaefsijvlrhgqxmnt bshiwokugpflvtmzeqxnyja in n xzou ng gn epqbvmi vqembi bvmeqizu mbeqiv cjapgriulbzeq ugiqdzcvpobjlrek zqleircpubjg cirjuqbzgepl nhpsreikdjzo hkjsnodipzer znoidphekjrs dezf edfz efdz rdfze nzitsqrfp qiznrfspt rfqizspnt nsqizrptf xntrkogqfapj nioagqtmrfkjyp is sgdi qsity pe ep ep ep uhvpiwdgsfr uwlpcqrezykovni aevu ae ea ae djzfhxmas msdxhz zexhdsymt dxzshktm dzemshxg msqiuvncoltxejg cqxfmsonlvute wmfblsrogvjinpc rplfngicojbkvwms cfbolhnjvrsimwgk gmisflrwnkcjbov vmwrcbosjngfuil kbxitoqvzajudfnsgmyc ikfwcxzgvtjedmsyouqnab aqknmufjiypcvxbgodstz eshyzxbqncuomfpwgk gzcxqpmhljeoyuikbfrn bzhxveutpfyaqmkcong evqyuicpfhl yquckvlpiejf anf szydm qt qt qt mfyovqgpnlbcxidauzh cqniopdhfgxlauvzbmy idxofbaylmcznuvqhpg qbcpihzogydlfvmnwuxa qgvcumyizpnabxdfhol btwjlohyfaq ydlwprkj rhisamcj csirha srcaih icshar mejydkgtnfovuzix enuvirjogdmkyxztf xefomztvkungysdijc jxdginfktapovyzueqhm fioktdsnemgjuzyxv hrztvexlkob lwekirhbxdzqtmo etxv arxtvue exvft fwdnqsomhtryxvcgzej eczwytuhfsgmdqnxoj ycdsqwznhftgjmkoxe tsjnexcafwmhygzbvqod xovcfts cfsopxvdt xoscfvt osfxtvc w rc t zs ik lzm zpl romqvb mvo uy y y y govwliuabszqp goiabwfusvzlpnq qpiwgbvaosulz apvguizblwsqo s m s s ozpiljymxhswnfuevt emvbwshnylzxpjti nveblmzchtwjiypsx nldfsb sfblndt sdblfn bnflds ndslbf ieg idew wonxsab wbsaoxn nobaxws wasbnox alscukjbf lsbjakfc jxcduqioabwpyhlzef ialdxwfzycqjhbepuo jfzypowishadclxbueq riydchjfnwqvtmbpsaloxe dsbwfintzelormhvxcaqpyj ejomaiyqsxcthfvpdlwbnr lrycvtunboifgxawqemhpjd xvtiafqrdwnoymclepbhj jsydqempfvntrhui miyefthpuqsrvnj zsvyrmhbtuelpqinfja nuphytvreqmfsji cltvanwuh tulachoyvwn tuwclvanh bixkgozashw hakibzoswmx poxkblmhqjftwsdcn bhtykpvzjxuiengao j j j cqodguxrzles loxqcrgeszudw ocsdqruxglze rugqoyxesdzlcf ulzdorxgsqec yvz vyz mfq sztdnk py zawgmj jawgz gwapjz sgzajw ekoadscpwhg jsuchbxmfyzlnwq wlkrqcjux xuqjclr gjrqlcxu afcosnhvprzblxtwd abszvxoglnctfhpwr bjhlvzfwceayksxtun tzvnxrhwlmsfacbd igreocyhquzjmvlx liowjethfkqszvmxdyu ljeqkvwpdazgocf cqgdyvmjuwpeotainsr mhoylsckuzxbiaevq vyczxkjeoapsbifu kxbdosyzavujiec mwsfxbkjqazpiohgnyldc xqgnadblfkwpcomshiy wgvsalrhqbmieyxodpfnkc eurqfmtkvjbosh vyqrhkotfblmseu brtfqkvoheums rvtksmehoubqf uwftdoarkmvqgehbcps ctyalrqdxskjuoh dlathrokujqxs hxsqukdoaltjr osrqkautljxdh zfdlxtr sburlzxd zlrdx ocfb cbfo uykhxqrtmnc ahigrcuptnxdqmk tckz ktzc vzgtxhkums kvzmhtgus sgthkzumv vzxsgmkuht znqmuhvkswgt jtdwk ydkti kdt dkjt mwxehozbnqpad ryjdeblzwxnpoucqahmtg liumaz izulam zauloim miludzaqr rzkjguslxohwnfdivm ofulwkhisgvjmnrxzd dikwvojugxzfrmnlsh sxjdzkcuworbnvgflmih vlmxrzikndhwjofgus fzqnodmx a v lfoeh leovfh hofsle djku kjud dukj qtiwbxfhlzjnokvpadruymgse onurjdisvgzwaqkybftlhpmex fnmqwuhtyjrkepbgildovxasz marndljbkegqxtupviscywfhzo fdbqehtxkavjimzwporsugyln aqkonbhvfdljigp phaqrlkbjdin phldcbkaumjvinq iplbjxeykqhdazn zsl sz xsyzh zs xdhlq ndlkxjyu xlde xdl blwmairvkofcuq tedokrvbqm pw p iqrbnglofs grwuylifvkbq yl yl xaizpuhlqo kiloxm ilkox puaorhzmtvfg mutoegrhzafv lrzmpt dpqyihnsa jfiodcs spi swni isn ohdmyvlpbxjnqzfrswiuaeg ceafhrujqtndivbxpwzsmg mvoxyd tvdoymx xdymov py y nutogsehiczykpmdvf ngmueistpxkfodhvzrcy yuhczioegpvmnfktsd zp z zbc z z creyt uisfmova er dltugzhniyjro lizndhrutojyg jhgnzytuordli lhgotuznirjydc xtrckznswlueia ivnwstaeulrkzjc kcwaleiuznqrts rkwiunqzatsecl y pqnae ofm fl y czoi smvbnd tzi tzanvx azgnjx ingjzyuae anrhzkq eqhafrbmw rjscmwxz lrgnyfeukdvmiqwpt tarsmxwveqdhjbk xrajvebtdmwkh taojykmefwbdzrxuvnp wbdtmjrevakx ctilgkbmaredjwvx wp p p zprwtogmdu orwdmtzuxpg omwputzdgr umgrtpwozd wgzdrtpmou xtkjsm ylqptfjmk pzgyknr kyorpngz pnzykgra rtsiypahgecuvj rsudtcgjiheyvp rpyehvtijcgsu cyprhvestgjui uvigershtyjpc jlmhtfbsoq gbtohjsqm mbstojqh mhkecsqtabjox xrhinjamvo hproxvnma mzscorhnx utwprfqjyhsvzaomcb yesrijzcagmhbwoutvpnqk porcxwmyutzajbhqsv uvrcpyzsmhajowtqb ycpwuzovatbsmjqhr fbkgycqutlmw wuybgqmlcfk xycgbkqmulwf bgcfwyuqklm vntsimju boegqz edotgsi dgoism iogds gdstio sogdixz fdi ifd rx v x qibkwyvmtxargjldc bykzitxevgrwsnqflcdjm dborhtpxjsflciveyq xbuijhdqafnsrvepozytcl qhlopsdtebcjyfrixv hlvdyqxtcroegfjbisp ormifqdhyvxjpclebst qtzumogwrclaiex iburltzgexdocwapq ixuwtoqlegnrzc xizeklwrugtqhoj iynjbsahtvfeurqkgd rtnwjgeukyadicflq deytfqknlpjuairgc oy to po wyj q vatgy xegndfrv smgv sgzbacv ifmepunrdszgh mvgdesianluzpfrh eypfughdnmszitr nepugsfimzrdh fzuiqesnjcdwoxmhkpbrg goycuvjqnpix ytwnigvcjq bsiczfhkne gwxp ojdl a uvgm kaxzjpmwutcqnv isadmolbtrfugxyhcj vxqhfryiakbn txhqbavyknri ptbqifxcwyjgordls dbpvkeauyc kovpawxf ovwxkpfa xbknwjpcoaftq oxapvfkw ybjvaftkzheqgiuposnmxc ungfezmiskqvyjaphobxtc yjqimsvbktaonpeucfzhgrx nepvgsifuqytahxzmjkocb qmaexzipshcvjkfyonutgb u u u u tpgqyvjaedlkbhwr nytwkpqlvmgrbehxjad vsruxht rdmb rfb khqyd ycj aidrbmzkxvt yzvbkiorxamdt mzwvhblrxtn vqalzwcbrxjmtnd wlvnrtxmzcbg ow ow ewuob wo gl mnacgl lg gul kdflg oqvd qodvy qdvo qvoda rd fus thoi rtnz tqagrnlb wemlvjbhuqcfrtodkxzn pjbtruvdmhowfznlxekq eoyadnxbuktqshgwfmvzirlj kumotnwel lmezwoutkn nuemkwlot efnlduohmtkw mhaubleozw zwulbhmo mhbzouwl hmwulbzo hvjpdoiswzbenma ojndsepwhiq dwsjnhiope tsohjdpwien joipwhesnd edbhi fisdhbe r v v v ezlc czei azlcei czie eynczs ngfuhekmzxvopy twogyeknxvmhbjzpuf zxpfnygeomukvh ktxduimz vtgmurjiqk mtkbuia uykwh kuyhnw dzjqnwbrouh qfncpvszdeg cydmlqnz dzqtn xga hmxpdg fnxgeu nxeogu nsxrgu xngurs jvmudzscnalhwktry lrvucmjkwztsyna wyruzcjxlbtemsknva yzwvklpcqustojrmnai zyjntswcuarkmvl zq qz qz qz zqt gbpnqrxu dqnxyvwhbtgi csqmbfjeaokxlz rdtuqpxnbzj yzsnpu fcnrzpou penzu nvukhlmizwpag tdvfgahbiw gtbpsdo ucdprxmznhbw rcumdzpwnx dxnpzrmcuw drpxcmnzuw zxwcnpmrdu dhouqlfvsakg uaofqkdsvhgl uoalfhvqsgkd klgvfudqosah auhslqfkgvdo qkwfimrogubyhljda shuprevacxlndiqfjwy crpsetajviwmqhl szqdpfvimaekgbj geyqpl gzqlei qleg kcfipzjwyugsrtahboneqxdm uwkcmtdfopayenqbshxi eudhcyfpwamoxvkqlistnb yfqbtnwuzsdl lszfnquwbtyd fsjznbdwytulq bfgldzqyutwsn n uv vjfzuhqgaypbmcd hqmbpsjyugrvfzatndc ovfazbdipqxeclykjgum vmbzptjwydaguncfrq k w k k eipruzqndlys elrysidnzqu pzlgeciqys wjvrdxmunfsb kdy kd kd dlk kd yretjs g kahzubo rjd r hlxpawm xmyeltpqw gmpxicbv burmxc ozxmsfjdn dtskziwy qxzycupgs iflherjytpxg thienjgrfxly heyftrgjlix igyfjurphtexl gtyxrjleihf nuswkhz xosqihvwfrez hgszyw ukphojt hotkpzju htupjbko mjpkouhd luhsi shliu lihqsu iqr ybndlhzrgwtmkf rxcuq j j j j rwqsbyoe fweujxcoliya mpowrey wvn wv frbuexwg xmqgdwfeb rbyjsiqxtfcvlup vqpuyrifcsjxtlb yvtqirslxpjfbcu vsribxjcufylqpt ikcvoguphqtyjdswzexa ptjocgxiuhwavydsqzek ipcuohvqdwyxsetkagjz vpgdhzqckoywxaijuest erhdoyugavcq doqsvahugec cnhezgfavbuixdo lhgvknmequsctapxzbjdorf fodnxkrlqthcubmzvpjaeg fcvqmordxhklpybujgenatz nlmbxvpcokearhdzjtqufg uthcdpbvojlqewrknafgxzmi hwjpevzgrtmoqknydfs jvzstyfdhgkoqpmw ncw gwivun wnl nxw najwbzdrke ckyowhxblrt flabyrdwctk lbwripvjtykcs pn eonwtzp yxsirvqhcm fapu njwb lsjdymwpz zmrhuajxvewysp lyisuvcbdqxotkmh bkmrldugxsycohqitv xlhcvtmyqibdosuk hscubvoelkyqdximt mb mjbf rbm zvqlg gnlvjbz zvdgl dslgvzt vczwgl bem yqpgj dxflhwokatuvnzs irqc jqp gqolch hnozqgcl dnhwl hdo fduc lug lug gurkal lgu ulg uahmzdyxbr htkmwpcxbqy cbhyxmp ajv mjt j ji bfpygmtxajnk kpnmfbxtgayj pcynamktgbjxf tfympjvqxgnkab x x x mxf vqx wlzsgdhixr hgcoaiwpbluv wyhlig iwfnlhqgs jfgqihmxwlr cqrdbpoehiwfuzvgalxm ularwipqxcfedozmbvg vurqezjkoysgpalbfimxwcdt mcvfzqplaxwrgoebiud mydhxfvgzcleojiq ixcozgyvjdfl njxuwiaovpycslrzgdf gfwtnr mojdinwkf rfnwqhcg wfn lwise arl trzbvl bal y y y y sayqdimthfrpjvgn crdphnmayqbgf sfgtqwbzej pnmlcyitj yvtng tyn nyutg ytgenh onpty bleicngomsqhwfdy mrbnfygxpiwucoldqshke cqdeimynwhsfoblg gqesldbcijmwhonfy enblgcmfwdhyqois ufmsgkbcxz xfsckzmub umbkoxzhrsvcnf kzmcsbfxgu tuiwqd hbtdou t t t t t ureltqfji ohzkrul oievpqgs sqdvopigle easvqpkgio upkr urpk wrbipknheldxjfm rhjexfldkwpb lhrpejxfwbdk drybxszfetlnwjigk fngbltzjywsroixk hodteualp dtrpuile tqrbsjni sbcirnqt rsbaitqv qbsrit gbtsriq ovjmetdznlw dtjvlmonze zdjntemolvw mlouvjngzkdter ckrnly rclkyn cyjlkrnh crynkl ylckrn zjk zkj djkz jzk jzk xoj mjro kjuxro ybsjeahf zhwvtialqegufxmrcj hwljxrecaqmztgifv vgibmzlxwrdeacfqhjt nxicerwtzolfgky hogmsvdplbweja w clq i gi cilrkspgjqmw xhvadtlyfjobnzue ckytg nqtyg gyxbt kygtc fwcd wfc oebwhmil fdwxr lomdtfsihk sfyitokldmh dimyotfkls iovdstlmkfj smulideqtfok frazxb ahfbxz bafzx aftbxpz ubdarimsqvgtlhfjze eqfrvhsguzjamtidl hjidpgrc vrp zpxwsulqrona drhpftvi kbrdhype xidcskygjwmbzr bsqexaypghjkv tgxmy atxym txym qjrbmxtluews ulbrwtjsxqop fzbksturwmxlqj tbxvnsjqriuwcl edhvzwqxojuplbkyf wfphdjyczxvlkbqo jhxbpkvyfzdloqw yhmlfwoqkjpvdxbz qfmxikhozbvwydplj seyq yogxm jzbgatxhrplowqsyecvdn nzjvohtguxpydsrlcewab apzf zanwg pza az sapxfnyhbowujlcdveqiztkm tzskjxqcoebdunyfphi caruks rhlwsv cnswqfaztmdh uxszromtanqdfb cjnmstxqvdik qmjdcksitxvn cjktvxqmdnis cjnrsqdkxptivm oq qaion omq qo kzymeqtbasgn cuktvbsorim lpjxwhdf knflw ezvkn yuhakrnc vidhwxfrmnsyuct rzumskdfeqx p p duicxvgnbeopfzlqyrks skdetoclpbmzqfghwixr gfozcdskprxeaiqbml plkhqcifedxbgosrz ydtjolrxzefiaschwng tdoerngfhzwxjcylia zrawdytxhcojlgenfi ghvjqlifws sfiqklwjehrgv q q s a s et tme a a a a a qng g wg nvmlaui audrigo atnjdu hybxcpszkwuq fnu zmngdceqikxyuapwv ciwyqekgamdzvp ikcpavfgbwmerqyz mcvyjezqxrpkiu wlfatnmghs awkqenuiorcd lkuowsracdtzqgei joxhucpqrmfyvikawe cdn ndc fybj bjfy byjucsf flybjx zfcphgxqno zhmxyncpqr iqhwaclzupsne oscpyvdebfhz pbonsjyrelkfxvz wfpvyigbmaeztoqus ypbfhaivmkx xpjfhikyoca wkzvxlebarsmcdpi xidcbpswmazekr zsxwidpmekacrb pwczxsedakirbm vfupqwdshxygkmrzol wslmypfkogrxzqdvh qwlxsrfzpgdomvyhk cmkdiapszuyb bkpyduimascz vjpxmdzfwkuq eycbgsnhltmapxo xmnklfpugdewtj okzerxjuihqcptdmysf yajvhbtowixds dvynabxjiwhs asydoixzbh ihjdxbasyk lifxrbspedahyumcg snragze gmszrnae egrazsn ensragz odi odi ido odi mvogdzfker veongkrpzmdf vgekmrzdfo ombjdfqykergvz hzsormkdgfve l l l ly kgnpliuwmsebhjfrcyqxotvazd mzqryvgsftauxpcknehbiwojld vczkrabfmhpyjteui merjtikybvaugz aieydktjrmzvubg yeslqoibauvtkmrjz vi vip eigv vix iv mcuknbexfowszpvtyi ztmfwonvcsapqxyieb etowynxzcpirmbvsf wjfnyvopzetkmiusbcx ywhqemsx banksxwemy ymsexw smyewx szxeywm yvqtnsahzpwebgr zgtjnevyapwbhrs jzynhrpvwgsbat obtynrfwslcahvzgpm eytrpagzwsjvbkhn ynwutpmvhj mvwjpuyt wupzyjvmt kwnyatozcmdqbpsvejfrxug vkzjaogfmqsxhnyctpu cozypjmtvlxquakgfnsi qrwtgecs daley emh qmbjwe qebfwjm qewjm qjiwem dqc tad qdcs zrvjnfpe zpefunyvqc fzpvern pnefvz envpfz nduhkvstxqmbfyr ufmhbtkqvxdnpy hdntqxuvmbkfy ot o yv xp evkrifstpzgbahl vzkmdtchgseajyfub bgtnkxvheoaqifsz wxec wfuie awmj ghsnkvwbqor mcexwf teosna tnkb ptm t r na ykx jdl mzjtp xbpj tzrkxba xnbjmgosv mhxbw j j j j xn lrvt htg mr hafkb fkab afbk zlyxomawvuib vxwzbaymolui tcdfzgx ql luo uh ixtbluahoeqgsv eovsiglhuqanxtb ntychjig chyijtgn hcnjtiyg tgjnhiyc tgjiychn khomqatzscydwunfe ygoazrdukh zokbrlyaudjh uojynifthzvcgqp phnvryfbtucl sbeizdtjopxu nouqbeykmszd cga gca cag hiogxbslyptfc pilwxcthogysb holsibtcypfgx oahyr pkjro qgfkj gjzk jgvk kw wk kw wk bxvmnks sfmbva fsocn ygfopn wbarmxtfyjzenicvlhps aefdirlyvzjpwtcmnh rqymwfzjpevchiaotnl lietnypmcrvhowfjaz ztjcehympnavirlwf gqsnyhtafdcbki yncbhxiakgpqt mikyzoxflndetbp ebqdwiopkhyfxnl jbscverlgfyauo bkewpj n solnxmfr ybxa ybxa xyba byax abxy sgbo sg unvqlyhzdaxrcwg dxvhaugicrzqnlw mrplcqatdxzbuvgnwh vzaurnhdgqlxwc ucdwavqhylxrngz frhdaek fpuwosv qm m smg ================================================ FILE: exm/aoc/2020/aoc_2020_06_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 6 ------------------------------------------ -- Custom Customs -- -- https://adventofcode.com/2020/day/6 -- -- Full Ada version. -- with Ada.Strings.Fixed, Ada.Text_IO; procedure AoC_2020_06_Full_Ada is total : Integer; new_group : Boolean; subtype Answer_Range is Character range 'a' .. 'z'; type Yes_Answer is array (Answer_Range) of Boolean; r, rg : Yes_Answer; -- procedure Collect_Group_Total is g : Natural := 0; begin for c in Answer_Range loop if rg (c) then g := g + 1; end if; end loop; total := total + g; new_group := True; end Collect_Group_Total; -- use Ada.Strings.Fixed, Ada.Text_IO; f : File_Type; begin for part in 1 .. 2 loop Open (f, In_File, "aoc_2020_06.txt"); total := 0; new_group := True; while not End_Of_File (f) loop declare s : constant String := Get_Line (f); begin if s = "" then Collect_Group_Total; else for c in Answer_Range loop r (c) := Index (s, (1 => c)) > 0; end loop; if new_group then rg := r; new_group := False; elsif part = 1 then rg := rg or r; else rg := rg and r; end if; end if; end; end loop; Collect_Group_Total; Put_Line ("Part" & Integer'Image (part) & ' ' & Integer'Image (total)); Close (f); end loop; end AoC_2020_06_Full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_06_full_ada_using_hat.adb ================================================ -- Solution to Advent of Code 2020, Day 6 ------------------------------------------ -- Custom Customs -- -- https://adventofcode.com/2020/day/6 -- -- Full Ada version, using the HAT package. -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_06_Full_Ada_using_HAT is total : Integer; new_group : Boolean; subtype Answer_Range is Character range 'a' .. 'z'; type Yes_Answer is array (Answer_Range) of Boolean; r, rg : Yes_Answer; -- procedure Collect_Group_Total is g : Natural := 0; begin for c in Answer_Range loop if rg (c) then g := g + 1; end if; end loop; total := total + g; new_group := True; end Collect_Group_Total; -- f : File_Type; s : VString; begin for part in 1 .. 2 loop Open (f, "aoc_2020_06.txt"); total := 0; new_group := True; while not End_Of_File (f) loop Get_Line (f, s); if s = "" then Collect_Group_Total; else for c in Answer_Range loop r (c) := Index (s, c) > 0; end loop; if new_group then rg := r; new_group := False; elsif part = 1 then rg := rg or r; else rg := rg and r; end if; end if; end loop; Collect_Group_Total; Put_Line (+"Part " & part & ". Total customs answers: " & total); -- Part 1: officially validated by AoC: 6532 -- Part 2: officially validated by AoC: 3427 Close (f); end loop; end AoC_2020_06_Full_Ada_using_HAT; ================================================ FILE: exm/aoc/2020/aoc_2020_07.adb ================================================ -- Solution to Advent of Code 2020, Day 7 ------------------------------------------ -- Handy Haversacks -- -- https://adventofcode.com/2020/day/7 -- -- HAC 0.081 "nice to have"'s detected in this exercise: -- * "=" for composite types ( ` rules (ri).contains (cti).col = c `) -- -- Solved in HAC 0.099: -- * I/O with enums, at least 'Image and 'Value. -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_07 is type Base_Colour is (aqua, beige, black, blue, bronze, brown, chartreuse, coral, crimson, cyan, fuchsia, gold, gray, green, indigo, lavender, lime, magenta, maroon, olive, orange, plum, purple, red, salmon, silver, tan, teal, tomato, turquoise, violet, white, yellow); type Colour_Qualifier is (bright, clear, dark, dim, dotted, drab, dull, faded, light, mirrored, muted, other, pale, plaid, posh, shiny, striped, vibrant, wavy); -- Emulate full Ada's Enumeration_IO's Get (ouch!) ... procedure Get_CQ (f : in out File_Type; cq : out Colour_Qualifier) is c : Character; s : VString; begin loop Get (f, c); exit when c < 'a' or c > 'z'; s := s & c; end loop; cq := Colour_Qualifier'Value (To_String (s)); -- We don't treat the invalid cases... end Get_CQ; procedure Get_BC (f : in out File_Type; bc : out Base_Colour) is c : Character; s : VString; begin loop Get (f, c); exit when c < 'a' or c > 'z'; s := s & c; end loop; bc := Base_Colour'Value (To_String (s)); -- We don't treat the invalid cases... end Get_BC; procedure Get_Nat (f : in out File_Type; n : out Natural) is c : Character; begin n := 0; Get (f, c); while c = ' ' loop -- Skip heading blanks. Get (f, c); end loop; loop exit when c < '0' or c > '9'; n := n * 10 + Ord (c) - Ord ('0'); Get (f, c); end loop; -- Result 0 when invalid... end Get_Nat; type Colour is record cq : Colour_Qualifier; bc : Base_Colour; end record; type Contained_Spec is record col : Colour; num : Natural; end record; subtype Contains_Range is Integer range 1 .. 4; type Contains_List is array (Contains_Range) of Contained_Spec; type Rule is record container : Colour; num_contain : Natural; contains : Contains_List; can_contain : Boolean; -- Used for marking container bag rule without double-counting. end record; subtype Rules_Range is Integer range 1 .. 1000; rules : array (Rules_Range) of Rule; -- Cheap version of Vectors... rules_count : Natural := 0; details : constant Boolean := False; procedure Put_Colour (c : Colour) is begin Put (Colour_Qualifier'Image (c.cq)); Put ("~"); Put (Base_Colour'Image (c.bc)); end Put_Colour; function Equal (c1, c2 : Colour) return Boolean is begin return c1.cq = c2.cq and c1.bc = c2.bc; end Equal; function Containing_Bags (c : Colour) return Natural is -- procedure Scan_Containing_Bags (c : Colour) is is_top : Boolean := True; begin for ri in 1 .. rules_count loop for cti in 1 .. rules (ri).num_contain loop if Equal (rules (ri).contains (cti).col, c) then -- Colour c is contained in bag described by rule #ri. is_top := False; rules (ri).can_contain := True; if details then Put (" container of "); Put_Colour (c); Put (" is "); Put_Colour (rules (ri).container); New_Line; end if; Scan_Containing_Bags (rules (ri).container); end if; end loop; end loop; if is_top and details then Put ("Top: "); Put_Colour (c); New_Line; end if; end Scan_Containing_Bags; -- can_contain_count : Natural := 0; begin for ri in 1 .. rules_count loop rules (ri).can_contain := False; end loop; Scan_Containing_Bags (c); for ri in 1 .. rules_count loop if rules (ri).can_contain then can_contain_count := can_contain_count + 1; end if; end loop; return can_contain_count; end Containing_Bags; function Contained_Bags (c : Colour) return Natural is contained : Natural := 0; begin for ri in 1 .. rules_count loop if Equal (rules (ri).container, c) then if details then Put ("Container "); Put_Colour (c); New_Line; end if; for cti in 1 .. rules (ri).num_contain loop contained := contained + rules (ri).contains (cti).num * (1 + Contained_Bags (rules (ri).contains (cti).col)); end loop; exit; end if; end loop; return contained; end Contained_Bags; procedure Get_Rules is f : File_Type; sep : Character; new_rule : Rule; new_spec : Contained_Spec; begin Open (f, "aoc_2020_07.txt"); while not End_Of_File (f) loop Get_CQ (f, new_rule.container.cq); Get_BC (f, new_rule.container.bc); if details then Put_Colour (new_rule.container); end if; for i in 1 .. 13 loop Get (f, sep); end loop; -- " bags contain" if details then Put (" bags contain: "); end if; new_rule.num_contain := 0; loop Get_Nat (f, new_spec.num); if new_spec.num = 0 then Skip_Line (f); exit; end if; Get_CQ (f, new_spec.col.cq); Get_BC (f, new_spec.col.bc); if details then Put (new_spec.num, 2); Put (" "); Put_Colour (new_spec.col); Put (" "); end if; new_rule.num_contain := new_rule.num_contain + 1; new_rule.contains (new_rule.num_contain) := new_spec; loop Get (f, sep); exit when sep = ',' or sep = '.'; end loop; exit when End_Of_Line (f); end loop; if details then New_Line; end if; rules_count := rules_count + 1; rules (rules_count) := new_rule; end loop; Close (f); end Get_Rules; -- shiny_gold : Colour; test_mode : constant Boolean := Argument_Count >= 2; begin shiny_gold.cq := shiny; shiny_gold.bc := gold; Get_Rules; if test_mode then if (Containing_Bags (shiny_gold) /= Integer_Value (Argument (1))) or (Contained_Bags (shiny_gold) /= Integer_Value (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Rules about bag contents: " & rules_count); Put_Line (+"Part 1: all possible direct or indirect containers of shiny gold: " & Containing_Bags (shiny_gold)); Put_Line (+"Part 2: all bags contained by shiny gold: " & Contained_Bags (shiny_gold)); end if; -- Rules: 594 -- Part 1: all possible direct or indirect containers of shiny gold: 169 -- Part 2: all bags contained by shiny gold: 82372 end AoC_2020_07; ================================================ FILE: exm/aoc/2020/aoc_2020_07.txt ================================================ wavy green bags contain 1 posh black bag, 1 faded green bag, 4 wavy red bags. dotted chartreuse bags contain 1 light beige bag. dark white bags contain 2 dotted white bags. clear aqua bags contain 4 posh orange bags, 4 pale blue bags. faded green bags contain 2 plaid orange bags, 4 drab green bags, 4 pale aqua bags, 4 drab coral bags. drab lavender bags contain 2 shiny white bags, 2 muted orange bags, 1 mirrored crimson bag, 1 dotted aqua bag. dull maroon bags contain 1 plaid plum bag, 5 plaid orange bags, 4 posh maroon bags. pale lavender bags contain no other bags. plaid cyan bags contain 2 posh violet bags, 5 dim turquoise bags, 2 dark tomato bags. dull plum bags contain 5 muted red bags, 4 dotted salmon bags, 1 dull maroon bag. bright turquoise bags contain 2 dotted chartreuse bags, 3 dull tan bags, 4 light gray bags, 3 mirrored red bags. posh violet bags contain no other bags. faded coral bags contain 1 wavy teal bag, 4 wavy cyan bags. striped turquoise bags contain 3 bright gray bags, 4 bright bronze bags. muted magenta bags contain 5 light teal bags. dull lavender bags contain 3 clear orange bags, 3 pale cyan bags, 4 vibrant orange bags, 1 dim chartreuse bag. pale silver bags contain 3 faded olive bags. dull turquoise bags contain 4 light gray bags, 4 clear green bags, 2 dull aqua bags, 5 dim white bags. dim cyan bags contain 4 pale cyan bags, 2 dotted beige bags, 4 drab lime bags, 2 muted silver bags. wavy plum bags contain 2 drab bronze bags, 3 mirrored yellow bags, 3 vibrant beige bags. drab lime bags contain 5 muted plum bags. striped yellow bags contain 3 dark fuchsia bags, 1 clear lime bag, 5 faded turquoise bags. shiny cyan bags contain 4 clear maroon bags, 1 dim yellow bag, 5 drab red bags. bright maroon bags contain 2 shiny gray bags, 2 faded indigo bags, 5 muted tan bags. striped crimson bags contain 5 posh brown bags. pale green bags contain 1 pale red bag. shiny blue bags contain 2 clear red bags, 2 dark black bags, 3 dotted silver bags. mirrored lime bags contain 2 drab violet bags. mirrored maroon bags contain 4 faded salmon bags, 2 shiny blue bags, 1 pale coral bag. light bronze bags contain 2 clear red bags, 3 posh lavender bags, 1 clear purple bag, 5 plaid lavender bags. bright salmon bags contain 2 faded cyan bags, 1 striped blue bag, 1 faded crimson bag. faded red bags contain 4 dotted purple bags, 1 bright brown bag, 1 pale tan bag, 1 drab teal bag. pale indigo bags contain 3 pale orange bags, 5 muted bronze bags, 2 pale tan bags, 3 posh fuchsia bags. pale orange bags contain 2 dotted magenta bags, 5 clear plum bags, 3 dim olive bags, 1 mirrored yellow bag. drab gold bags contain 4 dotted cyan bags, 4 muted plum bags, 1 vibrant white bag, 4 dull green bags. mirrored teal bags contain 5 posh turquoise bags, 4 striped purple bags, 5 mirrored blue bags. dark chartreuse bags contain 1 striped crimson bag, 3 dull purple bags. posh olive bags contain 2 clear brown bags, 1 faded lavender bag. muted tan bags contain 1 striped red bag. drab olive bags contain 2 dim plum bags, 4 mirrored violet bags. faded lime bags contain 3 dark tomato bags. dim black bags contain 2 wavy purple bags, 5 mirrored fuchsia bags, 5 drab beige bags. dotted plum bags contain 2 shiny gold bags, 4 shiny beige bags, 1 clear red bag. striped red bags contain 5 pale tan bags, 5 pale lavender bags. drab green bags contain 1 faded silver bag, 3 vibrant plum bags, 2 wavy purple bags, 1 plaid blue bag. dull orange bags contain no other bags. posh tomato bags contain 5 dim gold bags, 2 drab coral bags, 4 drab maroon bags, 2 pale indigo bags. light turquoise bags contain 2 shiny violet bags, 1 dull violet bag. muted salmon bags contain 2 mirrored teal bags, 1 mirrored bronze bag. bright red bags contain 1 dotted orange bag, 2 faded gray bags, 2 dim white bags, 4 plaid tomato bags. dotted tan bags contain 3 clear red bags, 5 pale coral bags, 3 clear turquoise bags, 2 muted beige bags. muted gold bags contain 2 drab turquoise bags. pale magenta bags contain 3 dotted cyan bags, 4 mirrored lime bags, 2 shiny cyan bags. pale brown bags contain 2 dull silver bags, 3 wavy tomato bags. shiny lime bags contain 1 mirrored gold bag, 5 dull magenta bags, 5 shiny fuchsia bags. dark bronze bags contain 2 light green bags. light magenta bags contain 4 pale crimson bags, 3 drab plum bags. dark gray bags contain 5 light maroon bags. plaid orange bags contain 5 plaid gray bags, 1 dark tomato bag, 2 drab chartreuse bags, 4 clear red bags. posh purple bags contain 2 posh blue bags. drab turquoise bags contain 3 clear brown bags, 2 mirrored red bags, 2 muted green bags. dark fuchsia bags contain 4 light orange bags. dim lime bags contain 1 dotted olive bag, 5 posh blue bags, 3 dim gold bags, 2 drab lime bags. drab tan bags contain 4 clear violet bags. posh fuchsia bags contain 5 drab black bags, 4 plaid purple bags, 3 dim white bags. clear orange bags contain 5 muted tomato bags, 1 dotted white bag, 5 bright fuchsia bags. posh crimson bags contain 1 mirrored chartreuse bag, 4 pale gray bags. plaid tan bags contain 1 light orange bag. posh brown bags contain 1 clear lavender bag, 4 clear yellow bags. mirrored salmon bags contain 2 dotted plum bags, 5 plaid lavender bags, 4 drab olive bags, 5 shiny violet bags. striped bronze bags contain 5 light blue bags. dotted black bags contain 4 plaid coral bags, 2 drab maroon bags, 4 dotted red bags. light gray bags contain 3 posh magenta bags, 5 wavy coral bags, 2 vibrant red bags, 2 wavy olive bags. pale turquoise bags contain 2 light olive bags, 1 dark silver bag, 5 plaid yellow bags. striped fuchsia bags contain 3 wavy aqua bags. light teal bags contain 5 dotted turquoise bags, 5 muted tomato bags, 1 dotted gray bag, 1 pale lavender bag. wavy beige bags contain 5 dim gray bags, 4 bright aqua bags. light salmon bags contain 2 clear plum bags. shiny magenta bags contain 4 dim fuchsia bags. clear white bags contain 4 dim white bags. wavy gray bags contain 1 vibrant beige bag. plaid bronze bags contain 5 plaid plum bags, 3 drab olive bags, 2 drab green bags. drab plum bags contain 5 drab chartreuse bags, 5 plaid purple bags, 2 drab teal bags, 1 drab coral bag. dotted salmon bags contain 4 dim fuchsia bags, 4 striped cyan bags, 3 dotted white bags, 4 mirrored violet bags. striped magenta bags contain 1 faded teal bag, 1 drab red bag. posh magenta bags contain 4 faded green bags, 2 dull magenta bags. striped lavender bags contain 1 striped black bag, 4 wavy turquoise bags, 5 dull purple bags, 4 posh violet bags. mirrored lavender bags contain 1 wavy turquoise bag. dim violet bags contain 3 muted green bags, 1 striped plum bag, 4 dull coral bags, 4 wavy chartreuse bags. shiny tomato bags contain 3 bright red bags, 5 wavy beige bags, 5 faded blue bags, 3 muted black bags. wavy indigo bags contain 2 dull brown bags. dark tomato bags contain 2 drab olive bags. vibrant red bags contain 1 plaid tomato bag, 1 muted tomato bag. vibrant brown bags contain 4 shiny violet bags, 2 mirrored violet bags, 2 dark salmon bags, 5 faded turquoise bags. dim lavender bags contain 4 dim plum bags, 5 drab maroon bags, 3 dark black bags. dull lime bags contain 5 bright turquoise bags, 3 vibrant chartreuse bags, 1 pale gray bag. muted plum bags contain 4 plaid plum bags, 3 dim beige bags, 5 wavy magenta bags. wavy tan bags contain 3 wavy chartreuse bags, 5 clear orange bags, 2 light blue bags, 2 pale yellow bags. dim maroon bags contain 2 dull yellow bags, 4 shiny orange bags. clear violet bags contain 2 clear red bags, 1 plaid blue bag. dim orange bags contain 4 posh red bags, 3 posh plum bags. plaid crimson bags contain 5 posh brown bags, 4 vibrant indigo bags, 5 drab teal bags, 1 dotted gray bag. clear yellow bags contain 1 plaid gray bag. dotted fuchsia bags contain 2 plaid plum bags, 1 drab chartreuse bag. dim brown bags contain 1 faded silver bag, 1 faded brown bag, 2 striped cyan bags. striped aqua bags contain 2 faded purple bags. striped gold bags contain 3 dotted lime bags. bright yellow bags contain 2 drab bronze bags, 2 dotted gray bags. wavy blue bags contain 5 drab olive bags. wavy turquoise bags contain 3 dotted indigo bags, 2 vibrant plum bags. dotted purple bags contain 4 light blue bags, 4 wavy gray bags, 5 pale lavender bags. mirrored gold bags contain 5 wavy silver bags, 3 clear white bags. dull purple bags contain 3 dim fuchsia bags, 3 clear indigo bags, 4 dotted purple bags. bright gold bags contain 5 shiny silver bags, 5 dark olive bags, 2 muted yellow bags, 3 vibrant magenta bags. faded gray bags contain 3 dotted magenta bags, 5 clear lavender bags, 2 faded tomato bags. dark olive bags contain 1 drab tan bag, 2 striped crimson bags. light silver bags contain 3 dark teal bags, 4 posh crimson bags, 2 wavy olive bags, 2 dotted fuchsia bags. light yellow bags contain 3 wavy silver bags. dotted teal bags contain 3 vibrant orange bags, 2 clear maroon bags. drab coral bags contain 5 mirrored violet bags. dim salmon bags contain 4 faded silver bags, 2 plaid cyan bags. dotted coral bags contain 3 faded gray bags. vibrant bronze bags contain 4 faded tomato bags, 3 light brown bags, 5 posh lavender bags. light blue bags contain 3 clear brown bags, 3 posh violet bags, 3 bright brown bags. plaid fuchsia bags contain 4 striped white bags, 1 mirrored cyan bag. plaid indigo bags contain 5 bright cyan bags. dull magenta bags contain 5 muted tomato bags, 4 plaid tomato bags, 1 faded silver bag. shiny orange bags contain 3 dark coral bags. wavy white bags contain 2 striped indigo bags, 1 faded orange bag, 2 dull fuchsia bags, 2 vibrant silver bags. dotted bronze bags contain 5 shiny fuchsia bags, 5 dotted aqua bags, 1 faded aqua bag. light chartreuse bags contain 3 dull chartreuse bags. dull salmon bags contain 2 vibrant plum bags. clear bronze bags contain 1 shiny tomato bag. faded lavender bags contain 5 pale lavender bags, 2 dull maroon bags, 3 drab beige bags. dark black bags contain 2 dim fuchsia bags, 3 plaid tomato bags, 3 dull orange bags. dull violet bags contain 1 striped red bag. mirrored indigo bags contain 3 mirrored violet bags, 4 faded plum bags, 1 pale tan bag, 2 dotted white bags. shiny crimson bags contain 2 dim purple bags, 2 dotted purple bags, 2 bright bronze bags. plaid aqua bags contain 1 plaid tan bag, 1 mirrored orange bag. drab beige bags contain 1 dull yellow bag. clear purple bags contain 1 vibrant cyan bag, 2 dim brown bags, 1 dark lavender bag. dim olive bags contain 5 light blue bags, 1 dull gold bag, 5 faded red bags, 1 dotted purple bag. mirrored green bags contain 4 wavy beige bags. dotted silver bags contain 5 wavy fuchsia bags. dotted blue bags contain 5 pale blue bags. pale crimson bags contain 1 dim tan bag. plaid gold bags contain 5 wavy magenta bags, 2 dotted gray bags. dim crimson bags contain 4 dark lavender bags. pale tomato bags contain 3 muted red bags, 1 clear lavender bag, 1 clear orange bag, 3 pale red bags. drab fuchsia bags contain 3 faded red bags, 1 muted silver bag, 2 drab aqua bags. pale maroon bags contain 5 vibrant lime bags, 1 light crimson bag, 1 posh white bag. wavy lavender bags contain 3 muted red bags, 2 posh violet bags. vibrant salmon bags contain 1 dark beige bag. dark blue bags contain 5 dim brown bags, 3 dark red bags, 1 light fuchsia bag, 5 shiny gold bags. dark plum bags contain 1 muted aqua bag. drab crimson bags contain 2 drab turquoise bags, 3 shiny violet bags. vibrant tomato bags contain 1 light tomato bag, 5 vibrant gold bags. drab maroon bags contain 2 faded tomato bags, 5 clear olive bags, 3 plaid gray bags. clear green bags contain 5 striped lavender bags, 4 dim gray bags. plaid green bags contain 2 shiny blue bags, 1 drab fuchsia bag, 5 dotted black bags, 1 dim plum bag. mirrored yellow bags contain 2 mirrored violet bags, 5 clear brown bags. dull aqua bags contain 2 faded tomato bags. shiny olive bags contain 4 light teal bags, 2 bright white bags. plaid lime bags contain 3 drab red bags, 2 light crimson bags. dull green bags contain 5 drab green bags, 4 dotted red bags, 4 shiny olive bags, 4 plaid plum bags. dull beige bags contain 2 faded tan bags. light indigo bags contain 3 dotted white bags. shiny silver bags contain 3 vibrant cyan bags, 1 dim teal bag, 1 striped beige bag, 5 wavy chartreuse bags. plaid yellow bags contain 3 light beige bags. striped orange bags contain 1 dotted maroon bag, 5 bright red bags, 3 shiny red bags. posh indigo bags contain 2 dotted bronze bags. drab orange bags contain 1 striped crimson bag, 3 dark yellow bags, 3 light turquoise bags, 3 light silver bags. mirrored chartreuse bags contain 2 dotted magenta bags. plaid silver bags contain 5 wavy aqua bags, 3 vibrant plum bags, 1 dark black bag. striped indigo bags contain 2 dotted salmon bags, 1 vibrant beige bag, 1 wavy cyan bag, 5 striped salmon bags. muted coral bags contain 5 vibrant brown bags, 4 light fuchsia bags. shiny brown bags contain 2 vibrant violet bags, 3 drab gray bags. shiny indigo bags contain 5 muted bronze bags. striped cyan bags contain 3 dim fuchsia bags, 3 dark coral bags, 1 faded red bag, 5 plaid brown bags. shiny tan bags contain 5 plaid white bags. clear gold bags contain 3 plaid purple bags, 4 striped black bags, 5 dim turquoise bags, 1 plaid plum bag. vibrant violet bags contain 2 posh violet bags, 2 pale tomato bags. muted olive bags contain 2 dark tomato bags. mirrored tomato bags contain 5 pale black bags. clear crimson bags contain 1 dim crimson bag, 5 striped blue bags. drab blue bags contain 1 bright indigo bag. drab teal bags contain 1 plaid brown bag. striped brown bags contain 4 dotted orange bags, 4 wavy blue bags. posh lavender bags contain 4 bright indigo bags, 4 faded bronze bags. light fuchsia bags contain 1 shiny crimson bag, 2 clear brown bags, 2 striped crimson bags. dotted violet bags contain 4 dull crimson bags. vibrant lavender bags contain 2 faded olive bags, 5 shiny tomato bags. wavy gold bags contain 5 dotted black bags, 2 drab beige bags, 3 dull gold bags. faded brown bags contain 1 wavy gray bag, 3 plaid teal bags. bright purple bags contain 1 faded tomato bag. shiny plum bags contain 2 dim silver bags. posh beige bags contain 3 bright crimson bags. posh coral bags contain 4 light chartreuse bags, 5 drab bronze bags, 2 striped aqua bags. shiny black bags contain 2 posh black bags, 5 clear white bags. posh white bags contain 1 plaid violet bag. vibrant chartreuse bags contain 5 clear aqua bags, 4 dotted magenta bags. faded olive bags contain 2 mirrored fuchsia bags, 5 plaid brown bags. drab purple bags contain 1 dim olive bag, 5 drab lime bags. dull yellow bags contain 2 dark coral bags, 3 clear brown bags. vibrant turquoise bags contain 5 plaid orange bags. wavy tomato bags contain 3 faded olive bags, 3 bright white bags, 5 dull gray bags. pale plum bags contain 4 pale coral bags, 4 bright cyan bags, 3 dim brown bags. faded indigo bags contain 1 clear beige bag, 2 vibrant beige bags. shiny violet bags contain 4 shiny tomato bags, 2 striped lavender bags. mirrored purple bags contain 5 dotted red bags, 1 mirrored fuchsia bag, 2 mirrored yellow bags. faded cyan bags contain 4 drab red bags, 5 wavy purple bags, 2 dim beige bags, 5 faded red bags. shiny salmon bags contain 5 muted tomato bags, 5 striped olive bags. clear maroon bags contain 1 dotted magenta bag. faded black bags contain 5 wavy fuchsia bags, 2 dim olive bags, 1 dark lavender bag. posh green bags contain 3 mirrored coral bags, 2 drab aqua bags, 4 wavy orange bags. faded crimson bags contain 1 mirrored cyan bag, 2 dim gray bags, 5 light blue bags, 5 posh maroon bags. striped tomato bags contain 4 drab lime bags, 2 wavy teal bags, 4 plaid cyan bags, 2 muted fuchsia bags. light olive bags contain 2 dotted red bags, 2 pale coral bags. faded gold bags contain 4 shiny green bags, 1 clear beige bag, 2 wavy brown bags, 2 dull tomato bags. pale bronze bags contain 1 dim lime bag. dotted gray bags contain 5 mirrored yellow bags. dark beige bags contain 4 clear turquoise bags, 3 vibrant plum bags, 5 drab maroon bags, 5 clear red bags. drab magenta bags contain 1 drab maroon bag, 1 clear magenta bag. vibrant beige bags contain 3 bright fuchsia bags, 1 dull gold bag. dark teal bags contain 5 clear turquoise bags, 5 dark maroon bags, 4 dotted magenta bags, 3 shiny crimson bags. mirrored blue bags contain 5 dark black bags, 5 vibrant brown bags, 5 dark aqua bags. wavy cyan bags contain 4 clear aqua bags, 4 dark aqua bags. dark turquoise bags contain 1 striped gold bag. drab silver bags contain 3 plaid bronze bags. faded beige bags contain 5 wavy cyan bags, 3 dull white bags, 5 dim purple bags, 4 faded brown bags. faded purple bags contain 3 light white bags, 4 faded brown bags, 4 posh maroon bags. dotted magenta bags contain 3 posh violet bags. muted green bags contain 2 dim gray bags, 1 vibrant indigo bag, 4 dotted indigo bags. bright beige bags contain 1 wavy teal bag, 4 bright cyan bags, 1 clear green bag, 1 posh brown bag. bright violet bags contain 2 plaid indigo bags. dim purple bags contain 1 posh maroon bag, 2 drab beige bags, 5 clear brown bags. clear magenta bags contain 4 pale white bags, 5 dotted chartreuse bags, 2 bright turquoise bags, 4 mirrored red bags. faded magenta bags contain 1 dull gray bag. mirrored white bags contain 4 dotted purple bags, 2 plaid purple bags, 2 pale tan bags. clear salmon bags contain 2 mirrored lavender bags. light maroon bags contain 1 plaid tomato bag, 5 pale aqua bags. vibrant tan bags contain 3 bright coral bags, 4 striped turquoise bags, 3 wavy aqua bags, 2 shiny gold bags. shiny lavender bags contain 2 drab tomato bags, 1 drab plum bag. dark crimson bags contain 2 pale purple bags, 2 dotted white bags, 3 shiny orange bags, 1 dotted bronze bag. faded aqua bags contain 3 wavy purple bags. striped blue bags contain 3 plaid bronze bags, 1 clear yellow bag, 2 clear white bags, 3 wavy teal bags. mirrored silver bags contain 5 striped salmon bags, 4 drab blue bags, 1 vibrant green bag, 1 muted cyan bag. drab white bags contain 2 wavy salmon bags. dull brown bags contain 5 pale plum bags, 3 plaid tomato bags. bright cyan bags contain 2 clear lavender bags. faded chartreuse bags contain 4 wavy aqua bags, 5 plaid orange bags, 5 dotted indigo bags, 4 clear yellow bags. dotted tomato bags contain 4 muted purple bags, 4 dotted black bags. dim white bags contain 5 mirrored cyan bags, 2 dim fuchsia bags, 2 dark tomato bags, 1 dotted purple bag. posh orange bags contain 5 drab olive bags, 5 vibrant beige bags. light coral bags contain 5 light purple bags, 2 wavy tomato bags. wavy lime bags contain 4 clear brown bags. mirrored magenta bags contain 2 faded silver bags, 2 dark coral bags. wavy coral bags contain 4 dull purple bags, 1 dark white bag, 4 posh orange bags. vibrant gray bags contain 5 dotted aqua bags, 2 dark salmon bags, 2 bright blue bags, 1 dotted white bag. mirrored olive bags contain 3 dark coral bags, 3 wavy gray bags. light gold bags contain 2 striped lime bags, 2 dark orange bags. light cyan bags contain 2 dim turquoise bags, 3 dotted tan bags, 4 shiny crimson bags. shiny gray bags contain 5 plaid cyan bags, 1 wavy purple bag. bright plum bags contain 3 muted tomato bags, 1 dim chartreuse bag, 3 dotted indigo bags, 4 shiny olive bags. vibrant blue bags contain 2 shiny orange bags. clear lavender bags contain 5 faded red bags, 2 wavy gray bags. dim yellow bags contain 2 drab aqua bags, 3 dim lavender bags, 1 bright plum bag. posh gray bags contain 3 light lavender bags. dull tan bags contain 1 dim gold bag, 2 bright bronze bags, 5 dim plum bags. plaid brown bags contain 3 dull orange bags, 3 dim plum bags. muted purple bags contain 5 dark black bags, 1 vibrant lime bag. shiny coral bags contain 4 dim green bags, 4 dim maroon bags, 2 dim chartreuse bags. pale gold bags contain 2 dim beige bags. dim beige bags contain 2 mirrored yellow bags, 5 clear brown bags. dull chartreuse bags contain 2 faded red bags, 5 posh maroon bags, 5 clear lavender bags. muted bronze bags contain 5 dim plum bags. vibrant coral bags contain 1 faded black bag, 3 light green bags, 1 wavy chartreuse bag. clear turquoise bags contain 2 shiny beige bags, 5 mirrored fuchsia bags. wavy silver bags contain 5 dim tan bags. muted red bags contain 4 dull gold bags, 1 plaid brown bag, 1 wavy gray bag. light tan bags contain 4 dotted yellow bags, 1 dull maroon bag, 1 light beige bag. bright tomato bags contain 1 muted beige bag. striped coral bags contain 3 bright coral bags. dotted lime bags contain 2 dull salmon bags. mirrored plum bags contain 1 bright fuchsia bag, 1 drab yellow bag, 2 dark plum bags, 2 posh purple bags. plaid blue bags contain 5 dull gold bags, 4 wavy gray bags, 5 mirrored violet bags. plaid salmon bags contain 4 dim salmon bags, 1 dotted lavender bag. clear chartreuse bags contain 5 muted teal bags, 4 clear gold bags, 2 plaid tomato bags. muted blue bags contain 3 faded tomato bags, 5 striped chartreuse bags. dim tan bags contain 4 clear lavender bags, 2 clear violet bags, 1 wavy plum bag, 4 pale gold bags. bright chartreuse bags contain 2 posh silver bags, 1 vibrant plum bag. plaid white bags contain 1 striped red bag, 3 dim beige bags, 3 plaid bronze bags, 2 dim turquoise bags. bright coral bags contain 3 shiny gold bags, 2 striped chartreuse bags, 4 light salmon bags, 2 vibrant aqua bags. clear indigo bags contain 4 posh orange bags, 4 dull gold bags. bright aqua bags contain 1 shiny orange bag. faded bronze bags contain 2 pale gray bags, 3 dull gold bags. shiny green bags contain 1 drab chartreuse bag, 4 light salmon bags, 4 striped gold bags. drab black bags contain 4 dark black bags, 1 dotted turquoise bag, 3 wavy gray bags, 3 shiny fuchsia bags. pale yellow bags contain 2 dim green bags, 3 vibrant aqua bags. dull indigo bags contain 2 striped aqua bags, 4 clear chartreuse bags, 4 dark orange bags, 3 posh magenta bags. mirrored cyan bags contain 2 dotted purple bags, 5 mirrored violet bags, 2 dotted white bags, 3 bright brown bags. dark yellow bags contain 4 faded tan bags, 3 dim turquoise bags, 5 muted fuchsia bags, 5 clear salmon bags. wavy yellow bags contain 2 dim bronze bags, 4 drab bronze bags. muted white bags contain 1 dotted black bag, 5 bright plum bags, 1 striped cyan bag, 2 clear turquoise bags. dotted gold bags contain 3 shiny fuchsia bags, 5 muted tan bags, 2 clear fuchsia bags. light aqua bags contain 5 faded brown bags, 3 pale blue bags, 2 mirrored green bags. plaid violet bags contain 3 bright yellow bags. bright silver bags contain 1 drab violet bag, 4 light teal bags. wavy red bags contain 3 dotted gray bags, 5 drab fuchsia bags, 1 posh blue bag. mirrored tan bags contain 5 light green bags, 2 plaid gray bags, 4 pale orange bags, 1 shiny violet bag. muted tomato bags contain 1 wavy purple bag. faded blue bags contain 3 shiny crimson bags, 1 clear indigo bag. shiny purple bags contain 5 clear blue bags, 1 vibrant red bag. posh aqua bags contain 4 striped olive bags, 3 pale maroon bags, 1 dim yellow bag, 1 clear red bag. striped white bags contain 1 bright cyan bag, 3 dotted orange bags. striped lime bags contain 1 striped brown bag, 3 dotted chartreuse bags, 3 wavy fuchsia bags, 4 faded magenta bags. striped tan bags contain 1 pale gray bag, 1 light indigo bag, 2 dark coral bags. shiny red bags contain 4 dotted gray bags, 1 drab bronze bag, 4 shiny fuchsia bags. shiny beige bags contain 3 vibrant beige bags, 2 vibrant indigo bags, 3 plaid blue bags. dim fuchsia bags contain 5 pale tan bags. plaid tomato bags contain 4 clear red bags. dull blue bags contain 4 pale turquoise bags. dull red bags contain 5 posh brown bags, 2 dotted tomato bags, 2 striped gold bags. pale red bags contain 3 plaid brown bags. striped maroon bags contain 3 pale cyan bags, 1 dotted cyan bag, 1 dim tomato bag. light lime bags contain 3 light cyan bags, 4 light olive bags, 4 bright salmon bags, 3 shiny orange bags. drab brown bags contain 3 dim tomato bags, 2 dark gray bags. faded yellow bags contain 3 dotted beige bags, 2 muted blue bags, 2 wavy fuchsia bags, 1 dark magenta bag. bright green bags contain 2 pale cyan bags, 5 plaid bronze bags, 5 wavy orange bags. wavy bronze bags contain 3 wavy red bags. dull gold bags contain no other bags. plaid olive bags contain 4 muted white bags, 4 plaid red bags, 5 wavy red bags, 3 posh indigo bags. dotted aqua bags contain 3 dim indigo bags, 3 drab coral bags. pale purple bags contain 1 dotted magenta bag, 3 clear indigo bags, 1 dim turquoise bag, 3 pale blue bags. faded teal bags contain 3 drab maroon bags, 3 clear tan bags, 1 pale gray bag, 4 bright tomato bags. drab chartreuse bags contain 2 drab aqua bags, 4 clear indigo bags. light lavender bags contain 4 faded bronze bags, 1 plaid chartreuse bag. dim tomato bags contain 2 dull orange bags, 5 shiny cyan bags, 2 muted purple bags, 2 dotted black bags. faded maroon bags contain 2 faded white bags, 3 dim maroon bags. pale cyan bags contain 2 plaid brown bags. muted indigo bags contain 4 mirrored red bags, 1 dotted indigo bag, 4 mirrored maroon bags. wavy orange bags contain 3 plaid bronze bags. dull teal bags contain 5 drab red bags, 4 dim green bags, 3 dotted olive bags, 5 pale maroon bags. dull gray bags contain 5 dark tomato bags, 4 dull magenta bags, 4 dotted red bags, 5 faded brown bags. vibrant gold bags contain 3 striped beige bags, 5 clear bronze bags. posh bronze bags contain 3 pale turquoise bags, 4 posh blue bags. striped plum bags contain 3 pale orange bags, 5 clear tomato bags, 1 light salmon bag. shiny chartreuse bags contain 4 dim yellow bags, 4 mirrored yellow bags, 2 clear orange bags, 2 bright red bags. vibrant yellow bags contain 4 clear yellow bags, 2 vibrant olive bags, 5 drab salmon bags, 5 light tomato bags. dark coral bags contain 1 pale tan bag, 3 dull orange bags, 4 clear brown bags. dotted cyan bags contain 5 faded aqua bags, 2 dotted lime bags, 1 dim gray bag. light purple bags contain 5 dotted indigo bags, 2 pale violet bags. bright bronze bags contain 1 dim turquoise bag. wavy brown bags contain 5 dotted silver bags. plaid black bags contain 1 clear magenta bag, 2 faded plum bags. posh cyan bags contain 5 muted beige bags, 1 clear brown bag, 3 wavy beige bags. dotted green bags contain 4 faded lavender bags, 2 muted blue bags. vibrant orange bags contain 1 dark aqua bag. dark violet bags contain 1 striped fuchsia bag. dark green bags contain 2 dark white bags, 3 vibrant chartreuse bags, 3 mirrored maroon bags. shiny aqua bags contain 2 light salmon bags, 5 pale turquoise bags, 1 pale silver bag. mirrored gray bags contain 2 dim salmon bags, 4 striped chartreuse bags, 5 dull gray bags, 2 bright white bags. bright black bags contain 1 dark aqua bag, 5 dark red bags, 4 faded tomato bags. dark purple bags contain 3 striped brown bags. vibrant plum bags contain 5 dim fuchsia bags, 1 posh orange bag, 1 dotted purple bag, 1 light blue bag. pale gray bags contain 1 plaid cyan bag, 2 dim white bags, 1 dotted magenta bag, 4 shiny gold bags. striped green bags contain 2 pale crimson bags, 3 dotted lime bags, 5 posh turquoise bags. shiny bronze bags contain 5 dark olive bags, 2 vibrant magenta bags, 4 striped silver bags. muted fuchsia bags contain 5 drab fuchsia bags. bright olive bags contain 4 pale blue bags, 5 shiny crimson bags. posh lime bags contain 1 dim plum bag, 3 dim magenta bags, 1 mirrored tomato bag, 2 light lavender bags. light crimson bags contain 3 clear turquoise bags, 5 dim brown bags, 3 bright cyan bags, 4 plaid tomato bags. dull silver bags contain 5 wavy silver bags. clear coral bags contain 5 muted aqua bags. pale salmon bags contain 3 dark gold bags, 5 wavy orange bags. pale lime bags contain 3 dim cyan bags, 4 striped turquoise bags, 2 muted aqua bags. wavy fuchsia bags contain 2 drab beige bags, 1 faded olive bag, 1 dim beige bag, 3 pale orange bags. clear blue bags contain 1 pale black bag, 2 plaid fuchsia bags, 2 mirrored chartreuse bags, 2 bright brown bags. muted teal bags contain 5 pale black bags. muted orange bags contain 4 dim olive bags. dotted indigo bags contain 3 drab lime bags. drab yellow bags contain 1 dim beige bag. muted brown bags contain 2 striped red bags, 4 muted green bags, 3 drab chartreuse bags, 4 dark aqua bags. posh red bags contain 1 wavy beige bag, 1 wavy tomato bag, 1 faded bronze bag, 1 clear coral bag. posh gold bags contain 1 dim chartreuse bag, 1 clear lavender bag, 1 bright fuchsia bag, 3 bright magenta bags. posh salmon bags contain 5 plaid red bags, 1 dim purple bag, 1 bright yellow bag. wavy black bags contain 5 faded white bags, 3 faded chartreuse bags. mirrored crimson bags contain 2 plaid gray bags, 2 vibrant tomato bags, 1 dim bronze bag. light white bags contain 4 dim turquoise bags. pale violet bags contain 5 dim beige bags. dim magenta bags contain 4 striped teal bags. striped teal bags contain 5 drab lime bags, 5 mirrored yellow bags. dotted brown bags contain 4 shiny gold bags, 3 wavy brown bags, 4 clear brown bags, 1 clear teal bag. bright orange bags contain 2 plaid violet bags, 3 posh aqua bags, 1 clear tan bag. shiny gold bags contain 3 dotted magenta bags, 2 shiny beige bags, 3 plaid brown bags, 5 clear indigo bags. clear olive bags contain 4 drab red bags. plaid purple bags contain 3 plaid gray bags, 3 dim olive bags, 4 dotted purple bags. pale teal bags contain 4 wavy cyan bags, 4 posh bronze bags. muted cyan bags contain 2 light blue bags, 3 shiny purple bags, 3 dotted white bags. plaid chartreuse bags contain 4 clear lime bags, 4 pale red bags. wavy crimson bags contain 1 pale gray bag, 3 striped tan bags, 5 muted purple bags. bright tan bags contain 1 posh purple bag, 1 light chartreuse bag, 3 dark white bags. dark lavender bags contain 1 dotted beige bag, 2 dark tomato bags. plaid coral bags contain 5 dotted red bags, 1 dim white bag. faded plum bags contain no other bags. dark indigo bags contain 4 drab beige bags, 5 clear red bags, 5 pale red bags, 4 pale blue bags. striped gray bags contain 5 drab teal bags, 4 muted red bags. light red bags contain 2 light gray bags, 3 vibrant aqua bags, 1 dotted aqua bag. clear tan bags contain 5 dull gold bags, 3 dim gray bags, 3 dim white bags, 2 light green bags. pale aqua bags contain 5 dotted purple bags, 1 drab lime bag, 2 clear orange bags. vibrant fuchsia bags contain 5 clear turquoise bags, 3 clear red bags, 5 faded green bags. clear lime bags contain 3 striped red bags, 1 dull maroon bag. muted gray bags contain 4 muted yellow bags, 4 dotted silver bags, 4 clear orange bags, 5 faded turquoise bags. dull fuchsia bags contain 1 dark aqua bag. wavy purple bags contain 4 drab teal bags, 3 light blue bags, 3 mirrored violet bags. vibrant teal bags contain 2 striped white bags, 4 dull red bags, 3 plaid chartreuse bags, 5 dotted salmon bags. dotted lavender bags contain 4 dim purple bags, 4 clear orange bags, 4 vibrant beige bags. clear gray bags contain 4 dotted tan bags, 1 dull gold bag, 4 dull gray bags. wavy violet bags contain 3 bright blue bags, 3 shiny purple bags, 2 bright fuchsia bags. dull cyan bags contain 4 clear green bags. dim blue bags contain 1 light brown bag, 3 faded indigo bags. bright magenta bags contain 1 dim brown bag, 4 wavy purple bags, 3 dotted red bags. dark cyan bags contain 4 vibrant maroon bags, 2 wavy salmon bags. vibrant magenta bags contain 4 plaid orange bags, 1 faded red bag. bright gray bags contain 5 dotted magenta bags, 3 clear olive bags, 1 bright fuchsia bag, 2 muted silver bags. wavy maroon bags contain 5 mirrored violet bags, 4 clear orange bags, 5 drab olive bags. dotted maroon bags contain 5 pale purple bags, 5 faded silver bags, 5 dotted lime bags. drab indigo bags contain 5 light chartreuse bags. dark brown bags contain 4 bright red bags. bright blue bags contain 2 shiny cyan bags. bright brown bags contain 5 dark coral bags, 5 dim fuchsia bags. dotted orange bags contain 5 bright fuchsia bags, 2 dull gold bags. mirrored red bags contain 4 dotted salmon bags, 3 dark red bags, 3 drab teal bags, 4 pale blue bags. plaid red bags contain 2 light maroon bags, 3 drab tomato bags. drab violet bags contain 2 vibrant cyan bags. vibrant olive bags contain 1 clear maroon bag, 3 clear green bags, 5 drab aqua bags. plaid plum bags contain 3 vibrant plum bags. dim coral bags contain 2 dull aqua bags, 3 vibrant tan bags, 5 muted fuchsia bags, 1 plaid silver bag. vibrant green bags contain 4 pale gray bags, 4 posh fuchsia bags, 3 bright lime bags, 5 faded blue bags. muted beige bags contain 5 drab fuchsia bags. vibrant maroon bags contain 1 faded aqua bag. muted yellow bags contain 3 clear maroon bags, 2 striped crimson bags, 4 mirrored maroon bags, 3 vibrant olive bags. faded salmon bags contain 4 faded olive bags, 1 muted purple bag, 3 dotted yellow bags, 3 dim silver bags. pale beige bags contain 3 mirrored tan bags. plaid lavender bags contain 2 bright magenta bags, 4 bright indigo bags, 1 posh tomato bag. drab aqua bags contain 4 wavy magenta bags, 3 mirrored olive bags, 1 muted tomato bag, 3 posh orange bags. bright indigo bags contain 3 pale violet bags, 3 dark lavender bags, 4 muted plum bags, 3 striped crimson bags. clear black bags contain 4 wavy aqua bags, 3 light yellow bags. drab gray bags contain 1 muted aqua bag, 3 plaid fuchsia bags. striped beige bags contain 1 vibrant blue bag, 5 dotted tomato bags. faded orange bags contain 2 mirrored maroon bags. dark orange bags contain 1 muted maroon bag, 5 drab indigo bags. mirrored coral bags contain 3 faded aqua bags, 2 drab lime bags. dim red bags contain 5 muted fuchsia bags. dark aqua bags contain 3 shiny gold bags, 4 pale blue bags, 3 dull magenta bags. dim gold bags contain 1 plaid blue bag, 1 posh fuchsia bag. striped black bags contain 2 shiny gold bags. shiny turquoise bags contain 4 pale purple bags, 5 faded blue bags. dim chartreuse bags contain 2 pale coral bags. drab red bags contain 5 mirrored olive bags, 5 vibrant beige bags. posh chartreuse bags contain 3 pale violet bags, 3 muted beige bags. light black bags contain 3 mirrored maroon bags, 5 dull tan bags, 5 posh crimson bags, 3 dark gray bags. vibrant aqua bags contain 2 plaid coral bags. pale olive bags contain 5 wavy lavender bags, 2 posh olive bags, 4 dim black bags, 3 drab cyan bags. mirrored aqua bags contain 3 mirrored violet bags. muted lime bags contain 4 mirrored cyan bags, 1 drab turquoise bag, 5 wavy fuchsia bags. dull coral bags contain 4 muted lime bags, 4 dim white bags. faded tomato bags contain 3 pale violet bags, 4 faded brown bags. mirrored fuchsia bags contain 3 dotted purple bags, 4 pale lavender bags. plaid magenta bags contain 3 light plum bags, 3 striped orange bags. clear teal bags contain 4 plaid blue bags. faded fuchsia bags contain 1 dull purple bag, 2 bright brown bags. mirrored brown bags contain 4 faded bronze bags, 5 faded beige bags. muted silver bags contain 2 dull gold bags, 4 clear orange bags, 2 dotted purple bags, 5 dim olive bags. dull bronze bags contain 4 shiny cyan bags, 1 posh cyan bag. dark silver bags contain 1 shiny olive bag, 2 drab aqua bags, 2 striped fuchsia bags, 4 mirrored tan bags. bright white bags contain 4 dark aqua bags, 5 plaid tomato bags, 5 drab green bags, 4 muted red bags. dark gold bags contain 2 dim teal bags, 4 shiny fuchsia bags. dull olive bags contain 5 mirrored orange bags, 3 drab gray bags, 1 shiny turquoise bag, 5 dull cyan bags. wavy olive bags contain 1 wavy cyan bag. dotted white bags contain no other bags. plaid gray bags contain 3 dim beige bags, 2 dotted magenta bags, 5 vibrant indigo bags. dim bronze bags contain 5 dark aqua bags. dotted yellow bags contain 2 wavy blue bags. muted lavender bags contain 2 faded aqua bags. dim teal bags contain 5 pale gold bags. posh teal bags contain 1 muted plum bag, 5 clear tomato bags, 1 clear white bag. faded turquoise bags contain 1 wavy teal bag, 1 plaid red bag. vibrant lime bags contain 4 vibrant beige bags, 5 drab lime bags. clear plum bags contain 1 vibrant beige bag. mirrored black bags contain 5 wavy white bags. mirrored orange bags contain 1 wavy turquoise bag. vibrant purple bags contain 2 faded crimson bags, 2 dull red bags, 3 plaid blue bags. posh maroon bags contain 5 clear orange bags, 5 vibrant indigo bags, 2 drab lime bags, 5 posh orange bags. plaid maroon bags contain 2 pale silver bags, 5 dotted salmon bags, 1 dotted plum bag, 3 bright olive bags. posh blue bags contain 1 dark coral bag, 2 vibrant lime bags, 4 pale orange bags, 1 plaid blue bag. muted black bags contain 2 dim gold bags. clear red bags contain 5 pale lavender bags, 1 bright brown bag, 5 muted red bags, 4 dull orange bags. plaid teal bags contain 1 dark coral bag, 3 dull orange bags. light tomato bags contain 4 dotted white bags, 1 pale blue bag, 1 dull coral bag. mirrored turquoise bags contain 1 shiny green bag, 1 wavy plum bag, 1 dull orange bag. pale coral bags contain 2 shiny fuchsia bags, 1 dull gold bag, 5 dim plum bags, 5 dark black bags. muted aqua bags contain 5 posh maroon bags, 4 dim gray bags, 3 pale aqua bags, 1 light crimson bag. shiny yellow bags contain 2 faded plum bags. faded tan bags contain 2 dark maroon bags. clear fuchsia bags contain 4 light white bags, 5 posh maroon bags. light brown bags contain 4 dim olive bags, 5 drab chartreuse bags, 5 posh maroon bags, 3 pale violet bags. muted maroon bags contain 2 wavy silver bags. wavy aqua bags contain 4 pale purple bags. mirrored beige bags contain 4 posh brown bags. drab salmon bags contain 3 striped red bags, 1 dull gray bag, 3 posh white bags. dotted crimson bags contain 2 light teal bags, 4 bright black bags, 3 drab teal bags. muted violet bags contain 3 bright coral bags. dim green bags contain 1 drab violet bag, 5 dotted beige bags. striped salmon bags contain 4 dull chartreuse bags, 2 dark indigo bags. dull black bags contain 3 dotted silver bags. shiny maroon bags contain 3 vibrant lavender bags, 3 clear lavender bags, 4 dull teal bags, 5 wavy maroon bags. faded white bags contain 1 plaid silver bag, 3 pale gold bags. light orange bags contain 3 pale red bags, 3 dull purple bags, 3 bright cyan bags, 4 dim lavender bags. posh plum bags contain 1 clear silver bag, 2 clear maroon bags. vibrant indigo bags contain 3 pale lavender bags, 5 dotted purple bags, 5 dotted white bags, 2 wavy magenta bags. dotted beige bags contain 3 muted tomato bags, 3 clear brown bags, 1 plaid gray bag, 2 faded olive bags. dim plum bags contain no other bags. pale white bags contain 3 vibrant beige bags. wavy salmon bags contain 1 dim black bag, 4 faded gray bags, 5 dim maroon bags. pale chartreuse bags contain 5 mirrored white bags, 4 posh teal bags, 2 muted plum bags. pale tan bags contain no other bags. vibrant black bags contain 4 vibrant tan bags. mirrored bronze bags contain 5 pale aqua bags, 2 wavy olive bags, 1 posh olive bag. bright teal bags contain 2 dark lavender bags, 5 muted fuchsia bags. striped silver bags contain 5 dull cyan bags, 5 striped teal bags, 2 posh blue bags. shiny white bags contain 3 shiny violet bags, 3 dotted cyan bags, 3 dotted purple bags. dark salmon bags contain 5 dotted lime bags, 1 pale orange bag, 1 vibrant red bag, 5 wavy purple bags. vibrant crimson bags contain 4 clear red bags, 4 faded gray bags. pale blue bags contain 5 striped cyan bags. drab bronze bags contain 1 drab teal bag. wavy magenta bags contain 4 vibrant beige bags, 4 bright fuchsia bags, 1 mirrored yellow bag, 4 dim fuchsia bags. faded violet bags contain 4 wavy gray bags. drab cyan bags contain 1 light gray bag, 5 plaid bronze bags, 5 dull aqua bags, 2 vibrant gray bags. dotted turquoise bags contain 2 mirrored indigo bags, 4 plaid plum bags, 4 faded red bags, 3 dim gray bags. dotted olive bags contain 4 vibrant beige bags. posh turquoise bags contain 1 light fuchsia bag, 5 plaid red bags, 5 bright coral bags. dull tomato bags contain 5 light blue bags, 2 plaid plum bags, 3 dotted lime bags. pale fuchsia bags contain 3 drab orange bags, 4 bright lime bags, 3 pale tan bags. drab tomato bags contain 2 posh magenta bags, 3 vibrant fuchsia bags, 3 dim fuchsia bags. vibrant silver bags contain 1 posh turquoise bag. pale black bags contain 3 dark coral bags, 3 dim plum bags, 4 shiny beige bags. wavy chartreuse bags contain 3 drab violet bags, 1 vibrant orange bag, 2 dim gray bags. dull crimson bags contain 3 mirrored plum bags, 2 dotted orange bags, 3 faded brown bags. clear beige bags contain 4 wavy tomato bags, 1 muted lavender bag, 5 bright magenta bags, 3 dotted indigo bags. shiny teal bags contain 3 drab red bags. bright lavender bags contain 4 drab fuchsia bags, 4 vibrant olive bags, 2 clear olive bags. posh tan bags contain 5 drab crimson bags, 5 bright lavender bags. dim turquoise bags contain 2 dim fuchsia bags. light violet bags contain 4 wavy tomato bags, 5 dark green bags, 1 vibrant violet bag. bright crimson bags contain 2 posh white bags. striped olive bags contain 3 light indigo bags. muted crimson bags contain 1 wavy magenta bag, 1 mirrored fuchsia bag. muted chartreuse bags contain 5 faded tan bags. dull white bags contain 5 faded red bags, 5 dim plum bags. bright lime bags contain 5 posh blue bags, 2 pale aqua bags, 3 light red bags. shiny fuchsia bags contain 4 faded olive bags, 2 dim turquoise bags, 1 plaid blue bag. faded silver bags contain 2 muted red bags, 5 pale purple bags. light plum bags contain 1 vibrant aqua bag. dark magenta bags contain 4 striped purple bags, 5 bright lime bags, 2 dull magenta bags, 2 dim black bags. clear cyan bags contain 3 bright brown bags, 3 mirrored gold bags, 2 faded plum bags, 5 shiny purple bags. plaid turquoise bags contain 5 posh orange bags, 4 light gray bags. clear brown bags contain 1 plaid brown bag, 5 posh violet bags. posh black bags contain 3 dark coral bags, 1 pale cyan bag, 2 faded gray bags. mirrored violet bags contain no other bags. bright fuchsia bags contain no other bags. striped chartreuse bags contain 4 pale lavender bags, 2 wavy gray bags, 2 pale violet bags. dark tan bags contain 3 dotted white bags. dim gray bags contain 5 dim beige bags. plaid beige bags contain 4 wavy lavender bags, 4 clear lime bags, 3 posh magenta bags, 3 dotted crimson bags. dim aqua bags contain 3 wavy cyan bags. wavy teal bags contain 5 drab aqua bags, 5 vibrant beige bags, 1 plaid tomato bag. dark red bags contain 1 drab fuchsia bag, 1 pale gold bag, 5 dark tomato bags, 5 shiny beige bags. vibrant white bags contain 5 wavy aqua bags, 2 muted cyan bags. muted turquoise bags contain 2 faded crimson bags. dark maroon bags contain 4 vibrant orange bags. dotted red bags contain 4 dark coral bags. striped violet bags contain 4 drab teal bags, 1 pale gray bag. light green bags contain 1 pale orange bag, 3 dim fuchsia bags. striped purple bags contain 4 pale black bags. clear tomato bags contain 4 dark white bags. dim indigo bags contain 3 pale tan bags, 2 mirrored cyan bags, 5 dotted crimson bags, 4 wavy lavender bags. posh silver bags contain 4 mirrored orange bags, 5 dotted lavender bags. dim silver bags contain 5 faded purple bags, 5 striped olive bags, 5 striped tan bags. light beige bags contain 2 bright plum bags, 2 dull salmon bags. posh yellow bags contain 4 dotted crimson bags, 5 dark salmon bags, 4 pale yellow bags. dark lime bags contain 3 posh crimson bags, 5 posh purple bags, 1 light black bag. clear silver bags contain 3 faded olive bags, 3 drab turquoise bags, 4 drab purple bags. vibrant cyan bags contain 5 vibrant plum bags. ================================================ FILE: exm/aoc/2020/aoc_2020_07_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 7 ------------------------------------------ -- Handy Haversacks -- -- https://adventofcode.com/2020/day/7 -- -- Full Ada version. -- Rules as Vector's, small arrays within each rule. -- with Ada.Containers.Vectors, Ada.Text_IO; procedure AoC_2020_07_full_Ada is use Ada.Text_IO; type Base_Colour is (aqua, beige, black, blue, bronze, brown, chartreuse, coral, crimson, cyan, fuchsia, gold, gray, green, indigo, lavender, lime, magenta, maroon, olive, orange, plum, purple, red, salmon, silver, tan, teal, tomato, turquoise, violet, white, yellow); type Colour_Qualifier is (bright, clear, dark, dim, dotted, drab, dull, faded, light, mirrored, muted, other, pale, plaid, posh, shiny, striped, vibrant, wavy); package BCIO is new Enumeration_IO (Base_Colour); package CQIO is new Enumeration_IO (Colour_Qualifier); package IIO is new Integer_IO (Integer); use BCIO, CQIO, IIO; type Colour is record cq : Colour_Qualifier; bc : Base_Colour; end record; type Contained_Spec is record col : Colour; num : Natural; end record; subtype Contains_Range is Integer range 1 .. 4; type Contains_List is array (Contains_Range) of Contained_Spec; type Rule is record container : Colour; num_contain : Natural := 0; contains : Contains_List; can_contain : Boolean; -- Used for marking container bag rule without double-counting. end record; package Rules_Pkg is new Ada.Containers.Vectors (Positive, Rule); rules : Rules_Pkg.Vector; details : constant Boolean := False; procedure Put (c : Colour) is begin Put (c.cq); Put ("~"); Put (c.bc); end Put; function Containing_Bags (c : Colour) return Natural is -- procedure Scan_Containing_Bags (c : Colour) is is_top : Boolean := True; begin for r of rules loop for cti in 1 .. r.num_contain loop if r.contains (cti).col = c then is_top := False; r.can_contain := True; if details then Put (" container of "); Put (c); Put (" is "); Put (r.container); New_Line; end if; Scan_Containing_Bags (r.container); end if; end loop; end loop; if is_top and details then Put ("Top: "); Put (c); New_Line; end if; end Scan_Containing_Bags; -- can_contain_count : Natural := 0; begin for r of rules loop r.can_contain := False; end loop; Scan_Containing_Bags (c); for r of rules loop if r.can_contain then can_contain_count := can_contain_count + 1; end if; end loop; return can_contain_count; end Containing_Bags; function Contained_Bags (c : Colour) return Natural is contained : Natural := 0; begin for r of rules loop if r.container = c then if details then Put ("Container "); Put (c); New_Line; end if; for cti in 1 .. r.num_contain loop contained := contained + r.contains (cti).num * (1 + Contained_Bags (r.contains (cti).col)); end loop; exit; end if; end loop; return contained; end Contained_Bags; procedure Get_Rules is f : File_Type; sep : Character; new_rule : Rule; new_spec : Contained_Spec; bags_contain : String := " bags contain"; begin Open (f, In_File, "aoc_2020_07.txt"); while not End_Of_File (f) loop Get (f, new_rule.container.cq); Get (f, new_rule.container.bc); if details then Put (new_rule.container); end if; Get (f, bags_contain); if details then Put (bags_contain & ": "); end if; new_rule.num_contain := 0; loop begin Get (f, new_spec.num); exception when Data_Error => -- "no other bags" Skip_Line (f); exit; end; Get (f, new_spec.col.cq); Get (f, new_spec.col.bc); if details then Put (new_spec.num, 2); Put (" "); Put (new_spec.col); Put (" "); end if; new_rule.num_contain := new_rule.num_contain + 1; new_rule.contains (new_rule.num_contain) := new_spec; loop Get (f, sep); exit when sep = ',' or sep = '.'; end loop; exit when End_Of_Line (f); end loop; if details then New_Line; end if; rules.Append (new_rule); end loop; Close (f); end Get_Rules; -- begin Get_Rules; Put_Line ("Rules about bag contents:" & rules.Length'Image); Put_Line ("Part 1: all possible direct or indirect containers of shiny gold:" & Containing_Bags ((shiny, gold))'Image); Put_Line ("Part 2: all bags contained by shiny gold:" & Contained_Bags ((shiny, gold))'Image); -- Rules: 594 -- Part 1: all possible direct or indirect containers of shiny gold: 169 -- Part 2: all bags contained by shiny gold: 82372 end AoC_2020_07_full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_07_full_ada_vectors_2x.adb ================================================ -- Solution to Advent of Code 2020, Day 7 ------------------------------------------ -- Handy Haversacks -- -- https://adventofcode.com/2020/day/7 -- -- Full Ada version. -- Rules as Vector's, Vector of Contained_Spec each rule. -- with Ada.Containers.Vectors, Ada.Text_IO; procedure AoC_2020_07_full_Ada_Vectors_2x is use Ada.Text_IO; type Base_Colour is (aqua, beige, black, blue, bronze, brown, chartreuse, coral, crimson, cyan, fuchsia, gold, gray, green, indigo, lavender, lime, magenta, maroon, olive, orange, plum, purple, red, salmon, silver, tan, teal, tomato, turquoise, violet, white, yellow); type Colour_Qualifier is (bright, clear, dark, dim, dotted, drab, dull, faded, light, mirrored, muted, other, pale, plaid, posh, shiny, striped, vibrant, wavy); package BCIO is new Enumeration_IO (Base_Colour); package CQIO is new Enumeration_IO (Colour_Qualifier); package IIO is new Integer_IO (Integer); use BCIO, CQIO, IIO; type Colour is record cq : Colour_Qualifier; bc : Base_Colour; end record; type Contained_Spec is record col : Colour; num : Natural; end record; package Contains_Pkg is new Ada.Containers.Vectors (Positive, Contained_Spec); type Rule is record container : Colour; contains : Contains_Pkg.Vector; can_contain : Boolean; -- Used for marking container bag rule without double-counting. end record; package Rules_Pkg is new Ada.Containers.Vectors (Positive, Rule); rules : Rules_Pkg.Vector; details : constant Boolean := False; procedure Put (c : Colour) is begin Put (c.cq); Put ("~"); Put (c.bc); end Put; function Containing_Bags (c : Colour) return Natural is -- procedure Scan_Containing_Bags (c : Colour) is is_top : Boolean := True; begin for r of rules loop for ct of r.contains loop if ct.col = c then is_top := False; r.can_contain := True; if details then Put (" container of "); Put (c); Put (" is "); Put (r.container); New_Line; end if; Scan_Containing_Bags (r.container); end if; end loop; end loop; if is_top and details then Put ("Top: "); Put (c); New_Line; end if; end Scan_Containing_Bags; -- can_contain_count : Natural := 0; begin for r of rules loop r.can_contain := False; end loop; Scan_Containing_Bags (c); for r of rules loop if r.can_contain then can_contain_count := can_contain_count + 1; end if; end loop; return can_contain_count; end Containing_Bags; function Contained_Bags (c : Colour) return Natural is contained : Natural := 0; begin for r of rules loop if r.container = c then if details then Put ("Container "); Put (c); New_Line; end if; for ct of r.contains loop contained := contained + ct.num * (1 + Contained_Bags (ct.col)); end loop; exit; end if; end loop; return contained; end Contained_Bags; procedure Get_Rules is f : File_Type; sep : Character; new_rule : Rule; new_spec : Contained_Spec; bags_contain : String := " bags contain"; begin Open (f, In_File, "aoc_2020_07.txt"); while not End_Of_File (f) loop Get (f, new_rule.container.cq); Get (f, new_rule.container.bc); if details then Put (new_rule.container); end if; Get (f, bags_contain); if details then Put (bags_contain & ": "); end if; -- If you forget the following, the executable built by -- GNAT for Win64, Win32 breaks without STORAGE_ERROR. new_rule.contains.Clear; loop begin Get (f, new_spec.num); exception when Data_Error => -- "no other bags" Skip_Line (f); exit; end; Get (f, new_spec.col.cq); Get (f, new_spec.col.bc); if details then Put (new_spec.num, 2); Put (" "); Put (new_spec.col); Put (" "); end if; new_rule.contains.Append (new_spec); loop Get (f, sep); exit when sep = ',' or sep = '.'; end loop; exit when End_Of_Line (f); end loop; if details then New_Line; end if; rules.Append (new_rule); end loop; Close (f); end Get_Rules; -- begin Get_Rules; Put_Line ("Rules about bag contents:" & rules.Length'Image); Put_Line ("Part 1: all possible direct or indirect containers of shiny gold:" & Containing_Bags ((shiny, gold))'Image); Put_Line ("Part 2: all bags contained by shiny gold:" & Contained_Bags ((shiny, gold))'Image); -- Rules: 594 -- Part 1: all possible direct or indirect containers of shiny gold: 169 -- Part 2: all bags contained by shiny gold: 82372 end AoC_2020_07_full_Ada_Vectors_2x; ================================================ FILE: exm/aoc/2020/aoc_2020_08.adb ================================================ -- Solution to Advent of Code 2020, Day 8 ------------------------------------------ -- Handheld Halting -- -- https://adventofcode.com/2020/day/8 -- -- HAC 0.085 "nice to have"'s detected in this exercise: -- * ` seen := (others => False); ` -- -- Solved in HAC 0.099: -- * I/O with enums, at least 'Image and 'Value. -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_08 is subtype Machine_Code_Range is Positive range 1 .. 1000; type Instr is (acc, jmp, nop); code : array (Machine_Code_Range) of Instr; oper : array (Machine_Code_Range) of Integer; last : Natural := 0; -- procedure Run (result : out Integer; ok : out Boolean) is seen : array (Machine_Code_Range) of Boolean; a : Integer := 0; c : Integer := 1; begin -- for x in 1 .. last loop seen (x) := False; end loop; while c <= last loop seen (c) := True; case code (c) is when nop => c := c + 1; when acc => a := a + oper (c); c := c + 1; when jmp => c := c + oper (c); end case; exit when seen (c); end loop; ok := c > last; -- Went past the last instruction: program terminated. result := a; end Run; -- procedure Swap (c : Integer) is begin case code (c) is when nop => code (c) := jmp; when acc => null; when jmp => code (c) := nop; end case; end Swap; -- function Exit_Diagnostic (x : Boolean) return VString is begin if x then return +"correct exit!"; else return +"infinite loop detected."; end if; end Exit_Diagnostic; -- asm : String (1 .. 3); i : Instr := nop; v, a1, a2 : Integer; f : File_Type; done_1, done_2 : Boolean; test_mode : constant Boolean := Argument_Count >= 2; begin Open (f, "aoc_2020_08.txt"); while not End_Of_File (f) loop Get (f, asm); if asm = "acc" then i := acc; end if; if asm = "jmp" then i := jmp; end if; if asm = "nop" then i := nop; end if; Get (f, v); last := last + 1; code (last) := i; oper (last) := v; end loop; Close (f); if not test_mode then Put_Line (+"Instructions: " & last); end if; -- Run (a1, done_1); -- -- Try fixing the machine code by swapping "nop" and "jmp" instructions: -- for c in 1 .. last loop Swap (c); Run (a2, done_2); exit when done_2; Swap (c); end loop; -- if test_mode then if a1 /= Integer_Value (Argument (1)) or a2 /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Accumulator = " & a1 & "; " & Exit_Diagnostic (done_1)); Put_Line (+"Accumulator = " & a2 & "; " & Exit_Diagnostic (done_2)); -- Part 1: validated by AoC: 1394 -- Part 2: validated by AoC: 1626 end if; end AoC_2020_08; ================================================ FILE: exm/aoc/2020/aoc_2020_08.txt ================================================ acc -17 nop +318 jmp +1 acc -10 jmp +394 acc +43 acc +47 nop +570 jmp +176 acc -9 jmp +322 jmp +73 acc +4 acc -4 jmp +460 jmp +228 acc +25 acc +39 jmp +50 acc -12 acc -14 nop +275 jmp +489 acc -11 jmp +338 acc +21 acc +10 jmp +1 acc +20 jmp +445 acc +7 jmp +419 acc -8 acc +32 jmp +181 acc +19 acc +5 acc +46 jmp +417 acc +28 acc +23 acc +16 jmp +225 jmp +317 jmp +309 jmp +69 acc -6 acc -6 jmp +127 acc +49 nop -38 jmp +467 acc +0 acc -12 acc -14 jmp -46 acc +14 acc +2 acc +2 jmp +311 acc +33 jmp +364 nop +234 acc +24 acc +37 acc +18 jmp +22 jmp +303 jmp +414 jmp +318 acc +22 acc +27 jmp +1 jmp +150 acc +34 acc +15 nop +200 acc +6 jmp +320 nop +534 acc +29 jmp +147 nop -20 jmp +255 jmp +10 acc -15 acc +3 jmp +338 nop +362 acc -4 jmp +1 jmp +286 acc -1 jmp +497 acc -4 acc +23 acc +4 jmp +400 acc +35 acc +50 jmp +133 acc -17 jmp -90 jmp +7 acc -17 jmp +472 acc +20 jmp +280 jmp +133 jmp -15 jmp +16 acc -19 acc -2 jmp -64 acc -17 jmp +1 jmp +385 acc -5 acc +34 jmp +382 acc +24 acc -17 acc +0 acc +15 jmp +466 jmp +300 acc +16 jmp +302 nop +479 acc +16 jmp +71 acc +23 jmp +1 acc +8 jmp +154 jmp +410 acc -8 jmp +402 acc +48 acc +42 acc +22 acc +35 jmp +50 jmp -7 acc -13 acc +37 acc +24 jmp +243 jmp +410 acc -3 acc +45 jmp +416 acc +2 acc +25 jmp -109 jmp -41 jmp +318 acc -8 acc -12 jmp +169 nop +393 acc +7 acc -12 acc +35 jmp +381 acc +41 nop -98 acc +15 acc -19 jmp +218 acc +24 acc +47 jmp +65 acc +29 jmp -129 acc +23 acc -13 nop +60 jmp -26 nop -4 acc -5 acc +13 nop -12 jmp -13 jmp -53 acc +21 jmp +276 nop -27 jmp +165 acc +42 nop +43 jmp +1 acc +26 acc +22 acc -3 jmp +405 acc +29 nop -118 acc +21 nop -190 jmp +217 acc -1 nop +223 acc -8 acc +45 jmp +49 acc +8 acc +22 jmp +209 acc +44 jmp +66 acc +7 acc -7 acc +48 jmp +318 nop +398 acc +2 jmp +16 nop +207 nop +358 acc +45 acc +48 jmp +267 nop +248 acc +26 jmp +307 acc +27 jmp -197 jmp -68 acc +34 acc +25 acc -13 jmp +133 jmp -77 acc -13 acc +10 jmp -193 jmp -62 acc +4 acc -14 jmp +261 jmp +151 jmp +208 acc -10 jmp +40 acc +31 jmp -216 acc +23 acc +34 jmp +364 nop +205 acc -3 acc +14 jmp +59 nop +359 acc -4 jmp +1 jmp -248 acc +47 acc +35 jmp +184 acc +16 nop -92 acc -12 jmp +354 acc +27 jmp -152 acc -14 acc -16 acc +43 jmp +147 acc +45 acc +24 acc +6 nop -46 jmp +21 acc +26 jmp +1 jmp +293 acc -8 acc +12 acc -19 acc -9 jmp +94 jmp +299 acc +10 acc -2 jmp +75 acc -7 acc +3 acc +47 jmp +171 acc +16 acc +44 acc -3 jmp +14 acc +30 acc +34 jmp -178 acc +35 nop -238 acc +39 jmp +1 jmp -133 acc +34 acc -6 jmp -276 acc +1 jmp -207 acc +10 jmp -43 jmp -302 acc -1 nop -29 jmp +1 acc +17 jmp -281 acc +17 jmp -109 jmp +1 acc +13 nop -9 jmp +245 acc +5 nop -15 acc +3 acc +7 jmp +65 acc -11 jmp -313 acc +47 jmp +29 jmp -289 acc +18 acc -17 nop +73 acc -12 jmp +80 acc +32 acc -4 acc +3 jmp -126 acc +16 jmp -275 nop -188 acc -3 acc +14 jmp -155 acc +33 acc -19 nop -166 acc +20 jmp +30 nop -169 acc +49 nop +168 jmp -24 nop -345 acc +34 jmp -40 jmp -56 jmp +29 jmp +191 acc +24 jmp +219 acc +34 acc +27 acc +11 jmp -260 jmp -339 acc +15 nop +16 jmp +1 jmp +138 jmp +1 jmp +1 jmp +14 acc -11 acc +45 jmp -19 acc +0 jmp +27 acc +0 nop +128 jmp -65 nop -23 jmp -318 jmp -325 jmp +1 jmp -229 jmp -270 jmp -137 acc +34 acc +7 jmp +1 jmp -346 acc +18 jmp +37 acc +40 acc -16 nop -146 acc +35 jmp -12 acc +1 acc +27 acc +44 acc +8 jmp -276 acc +16 acc +42 nop -342 acc +13 jmp -165 acc -11 acc -17 acc -10 jmp -26 acc +10 acc +43 jmp -276 acc +5 acc +34 acc +17 acc -9 jmp +99 acc +29 jmp -370 acc -11 jmp -412 acc +47 acc +21 acc -12 jmp -136 jmp -124 acc +12 acc +0 acc +25 acc +27 jmp -290 acc +5 acc +49 acc +32 nop +29 jmp -202 nop -296 acc -12 acc +9 acc +21 jmp +23 jmp -345 acc +26 nop -123 jmp -373 nop +118 jmp +43 acc -15 jmp -386 jmp +1 nop -370 acc +47 nop -141 jmp -426 acc +42 acc +12 acc +4 nop -103 jmp -122 acc +23 acc -4 acc +11 jmp -314 jmp -73 nop -1 jmp -411 acc +13 acc +9 nop -372 jmp -293 acc +46 acc +3 acc -1 jmp +86 acc +36 jmp +100 acc +27 acc +49 nop -4 acc +47 jmp -445 acc +31 acc +47 acc -11 acc +14 jmp -181 nop -438 acc +31 jmp -428 nop -115 nop -244 jmp -464 jmp -29 nop -240 jmp -241 acc -12 jmp -329 nop +78 acc +6 jmp +1 acc +49 jmp -322 jmp -133 acc +20 nop -83 acc +35 acc +29 jmp -41 acc +15 jmp -46 jmp -29 acc +45 acc -14 acc +21 jmp -366 nop +84 acc -6 acc +25 acc -17 jmp -326 acc -5 nop -159 acc +5 jmp -171 acc +42 jmp -28 acc +42 acc -11 acc +45 acc +19 jmp -305 acc +38 acc -13 acc -16 jmp -134 acc +45 jmp -256 acc -15 acc -18 acc +28 jmp -114 acc -11 acc +47 nop -420 jmp -90 nop -330 jmp +13 acc -15 acc +9 jmp -159 acc -12 acc +0 acc +0 jmp -538 acc +31 acc +24 acc +32 acc -16 jmp -95 jmp -466 acc +19 acc +2 jmp -172 acc -12 jmp -207 acc +39 acc +18 acc +5 jmp -211 nop -507 jmp +1 jmp -197 nop -227 acc +28 jmp -494 acc +22 acc +2 acc -14 jmp -377 acc +8 acc +29 jmp -573 acc -17 acc +14 acc +29 acc +11 jmp -351 acc +9 nop -540 acc +30 nop -344 jmp -564 acc -4 nop -465 jmp -293 acc -18 acc +5 acc +29 jmp -302 acc -17 acc +14 acc +2 acc -11 jmp -527 jmp -563 acc +14 acc +10 jmp -505 acc +43 jmp -188 nop -448 acc +44 acc +3 acc +16 jmp +1 ================================================ FILE: exm/aoc/2020/aoc_2020_09.adb ================================================ -- Solution to Advent of Code 2020, Day 9 ------------------------------------------ -- Encoding Error -- -- https://adventofcode.com/2020/day/9 -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_09 is contig_max, last_data, n, min, max, x, t : Integer; res_no_pair, weakness : Integer := 0; f : File_Type; mem_max : constant := 24; subtype Mem_Range is Integer range 0 .. mem_max; mem : array (Mem_Range) of Integer; found : Boolean; test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin for part in 1 .. 2 loop Open (f, "aoc_2020_09.txt"); for i in Mem_Range loop Get (f, mem (i)); end loop; n := 0; File_Read : while not End_Of_File (f) loop Get (f, last_data); found := False; if part = 1 then -- Find a pair of numbers in the recent data whose -- sum is the number read just now (last_data). Scan_Mem : for j in Mem_Range loop for k in j + 1 .. mem_max loop if last_data = mem (j) + mem (k) then found := True; exit Scan_Mem; end if; end loop; end loop Scan_Mem; if not found then res_no_pair := last_data; exit File_Read; end if; else -- Find a contiguous set of at least two numbers in the list -- which sum to the invalid number from part 1. contig_max := n + mem_max; Contig_Scan : for j in n .. contig_max loop for k in j + 1 .. contig_max loop t := 0; min := mem (j mod (mem_max + 1)); max := min; for i in j .. k loop x := mem (i mod (mem_max + 1)); t := t + x; if min > x then min := x; end if; if max < x then max := x; end if; end loop; if t = res_no_pair then weakness := min + max; exit File_Read; end if; end loop; end loop Contig_Scan; end if; mem (n) := last_data; n := (n + 1) mod (mem_max + 1); end loop File_Read; Close (f); end loop; if test_mode then if res_no_pair /= Integer_Value (Argument (1)) or weakness /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: Not a sum of a pair: " & res_no_pair); Put_Line (+"Part 2: Encryption weakness: " & weakness); -- Part 1: officially validated by AoC: 138879426 -- Part 2: officially validated by AoC: 23761694 end if; end AoC_2020_09; ================================================ FILE: exm/aoc/2020/aoc_2020_09.txt ================================================ 42 27 23 19 4 26 31 29 11 49 38 9 45 1 40 46 39 28 44 16 13 5 32 17 50 12 20 6 7 10 22 14 18 60 59 8 19 9 11 15 21 23 39 24 25 16 26 13 29 17 27 28 20 35 30 31 22 32 44 33 38 47 34 36 37 41 55 64 40 42 43 46 39 45 61 48 50 52 65 62 53 67 72 69 70 74 73 98 86 76 79 81 108 84 82 91 160 153 93 253 100 102 105 115 175 166 151 149 142 218 147 152 162 155 161 163 165 173 255 184 191 193 293 195 357 252 295 220 257 404 289 291 322 294 314 415 343 316 318 324 328 512 364 517 379 384 511 636 615 574 472 477 509 644 1021 605 585 608 610 800 634 640 1122 642 1255 692 841 893 981 763 1313 1586 1046 949 986 1057 1062 1094 1444 1300 2393 1193 1250 1244 1274 1475 1282 1405 1334 1533 1585 1604 1744 2467 1712 2986 2043 2193 2255 2048 3250 2338 2287 2437 3711 2443 2526 2494 2518 2556 3382 2938 2990 3527 4149 5876 4660 4993 4050 4724 4091 4236 4241 4303 4781 4625 4730 4805 4880 4937 5432 7280 9717 5074 5494 9027 5928 9505 7577 8966 8141 8286 8291 13021 12377 10162 9535 8544 13907 14235 14459 9610 9685 19222 17294 10506 18637 18683 14040 33262 22526 21882 15718 17751 16427 16432 16835 35110 28293 18079 19050 28322 34586 30339 40277 19295 26520 20191 24546 26224 26933 29758 33090 47837 34506 34914 32553 64269 34178 52868 62471 35885 37374 37129 38270 38345 96649 39486 43841 57636 70898 44737 46415 68387 66887 74155 71307 85211 66731 67059 67467 68438 110684 82300 73014 80622 74230 76615 75399 106217 77831 152678 126074 116044 91152 111624 113474 141117 133618 133790 138366 134198 173276 142668 157699 135905 158453 206696 212520 147244 157237 365198 152014 239548 168983 191305 224942 202776 254591 276458 272564 247092 267408 267816 402014 301121 292651 278573 506956 283149 293142 304481 309251 494139 565215 320997 343319 441547 371759 785529 449868 692756 457367 537740 592400 514500 761848 546389 711265 561722 1157615 585793 571715 846991 1100293 597623 874466 715078 778364 881059 784866 793187 813306 821627 907235 1452774 971867 995107 1157508 1060889 1076222 1118104 1108111 1340086 1370659 1169338 1183416 1375987 1634933 1508265 1419250 1493442 1499944 2407179 1665925 1578053 1889528 1720541 1728862 1879102 1966974 2400975 3213983 2230227 2137111 3457155 2448197 3379046 2352754 2539997 3306915 2993386 5013979 2912692 2919194 3085175 3071495 3165869 3243978 3545027 3298594 5846912 3449403 3607964 3846076 4104085 4940972 4367338 4489865 6764070 4800951 4892751 5265446 5271948 6362095 5831886 6291980 6237364 5984187 6615272 6156670 6315473 6409847 6542572 7144670 11945621 8593950 9606073 7454040 7950161 8471423 9382616 17777507 9290816 11103834 10537394 10158197 17211067 12654075 11816073 18200023 17719106 12140857 12299660 14106831 12472143 16148645 12952419 13687242 15094831 15404201 15925463 16744856 23009537 17240977 26306842 20695591 19828210 20394650 21641228 21974270 39754393 23956930 36543295 24115733 24440517 24771803 37045429 25252079 25424562 29216999 33515452 41177542 28782073 30499032 42169418 54455962 33985833 37069187 37936568 44600013 40523801 40222860 42035878 59019699 53988802 57631185 54206635 48556250 54034152 50196365 50023882 50676641 54469078 58940014 57999072 104652327 69305874 59281105 64484865 71055020 105132603 82536581 80746661 78159428 155328968 82258738 88779110 104665443 159121405 98580132 130814988 98752615 99232891 100220247 123424879 100700523 169617468 112468150 213328040 117280177 135539885 217798623 123765970 142644293 149214448 163283242 158906089 160418166 166938538 171037848 255112443 138879426 197332747 197813023 197985506 231035235 241046147 388836471 340655316 213168673 277698343 282085618 236234120 252820062 278184178 266410263 262645396 272980418 288093874 364271285 297785515 299297592 305817964 550739270 503150711 336212173 700483458 395145770 570179492 411154179 444203908 449402793 465988735 822999554 524327994 637251703 489054182 498879516 515465458 551164596 585879389 535625814 700963734 587391466 597083107 785614966 635509765 893209430 1004519640 900208361 959669366 806299949 1137043985 1229818874 1897729070 893606701 1059953808 955042917 987933698 1013382176 1014344974 1024679996 1034505330 1121505203 1336473499 1621763103 1810294962 1601602747 1497291468 1953163238 2428063052 1441809714 1959562557 1706508310 1699906650 2922409066 1819682125 1881540399 1907951675 1848649618 1906988877 1942976615 1968425093 2001315874 3927987650 2048850304 2734411980 2156010533 2618796671 2778283213 2939101182 3043412461 3148318024 4436392650 3141716364 7069704014 3555157928 3406414960 3519588775 3817074711 4098987148 5821695674 3730190017 3755638495 7572713206 6878508041 3911401708 6548131324 4779599087 5353208651 4204860837 4774807204 5095111715 7317816668 5919999577 7578109014 6191730485 10966537689 6958791075 6661305139 6926003735 6961572888 9299972552 7249778792 7485828512 10459533032 13150521560 10396591322 8979668041 9558069488 8116262545 8686208912 10128015855 13461016116 11130864572 11286842200 9869918919 11015111292 12111730062 16465496553 20419807191 20573180780 13920363963 15077835433 13587308874 14211351680 25537368465 28059009292 14735607304 15602091057 19973051112 17674332033 16802471457 17095930586 17986181464 18244278400 18556127831 19997934774 23126841354 20885030211 24605526223 21981648981 38975935022 28577226615 27507672837 27798660554 28131715643 28322916178 54053770455 35340208986 29813442737 30337698361 31831537890 41979583755 32404562514 36230459864 33898402043 41113022818 37980960797 39441158042 45108490335 79093983615 42866679192 44011871565 45490556434 46587175204 53813186871 56084899452 69435938996 55306333391 63138869540 69238611029 58660614539 70385523311 60151141098 62742260875 62169236251 65729939933 66302964557 68635022378 70128861907 73339560085 86603579252 77422118839 164025698091 86878550757 88357235626 100400362075 89502427999 233461637087 101893508595 109119520262 129587080094 113966947930 115457474489 118811755637 120829850790 121402875414 199715942001 122320377349 127899176184 128472200808 175422484819 134937986935 141974582463 143468421992 164300669596 165779354465 166924546838 187278912832 216465630851 214367310005 235369823344 191395936594 211013028857 246710931821 223086468192 232778703567 326333923529 236860349903 287182229879 242232726204 366640488839 306275252059 257258364284 522740882910 357835731997 276912569398 278406408927 332703901303 739206513761 355696606190 380146664470 354203459670 642878836069 402408965451 405763246599 414482404786 760244697448 599419192406 919791405467 459946818095 632609175588 479093076107 660478711729 499491090488 690539633300 534170933682 535664773211 679321534849 555318978325 609616470701 756612425121 812577342609 932123093709 734350124140 1140391361918 1150486451395 1851914499176 1096302879899 808172212050 820245651385 874429222881 939039894202 959437908583 1632822993994 1089489912007 1394828835869 978584166595 2611407160589 1033662024170 1069835706893 1695710340243 1687006565490 1164935449026 1289669102465 1343966594841 1490962549261 2524624573431 1972701918372 1542522336190 1628417863435 1682601434931 1694674874266 1897662124057 1747212106252 2717907775442 1813469117083 2103975343228 2661185601526 2012246190765 2048419873488 2103497731063 2859610323292 2729372364413 2198597473196 2234771155919 3338088975953 2454604551491 2508902043867 3091178701093 3868591168272 4466850742256 3170940199625 3237197210456 3225123771121 3311019298366 3377276309197 3441886980518 3560681223335 3759458297017 6921455293747 4048240273002 5490306854006 4060666064253 4871856514057 4689375707410 5536686449149 4927969837609 4433368629115 4707499517063 5325949857012 4963506595358 10092395493372 7502553044771 7878439716688 6396063970746 6536143069487 6408137410081 7820124361270 10727676815892 7070477595383 8249132823254 8268180740398 7621347287588 11115636927144 8481608902117 8108906337255 8494034693368 8750041771663 9122744336525 9140868146178 9361338466724 9396875224473 11103563487809 9671006112421 10289456452370 11359570566104 12804201380827 14414582786175 14890098664114 12932207040233 12944280479568 13478615005464 15179383932638 14691824882971 20226307824334 16115381980956 15730253624843 16102956189705 16590515239372 17231650673780 16602941030623 26282816386291 18502206612902 24030966810292 18537743370651 18758213691197 19067881336894 19960462564791 29535148070856 21649027018474 24163771946931 27983585313465 25876487519801 27834379143682 26410822045697 26422895485032 28170439888435 41102646928668 30422078507814 32705897220328 42141075670540 31833209814548 35733857286682 37192113238571 33834591704403 35105147643525 37039949983553 37295957061848 37605624707545 37826095028091 38718676255988 39028343901685 41609489583265 45812798965405 65266418875599 50040259466732 66702261569453 52287309565498 56004819032117 52833717530729 54593335373467 58592518396249 66155935794496 62255288322362 64539107034876 65667801518951 84666927345277 ================================================ FILE: exm/aoc/2020/aoc_2020_10.adb ================================================ -- Solution to Advent of Code 2020, Day 10 ------------------------------------------- -- Adapter Array -- -- https://adventofcode.com/2020/day/10 -- with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2020_10 is use HAT, Interfaces; subtype Jolt is Natural; -- ^ Full Ada: it's better to define an incompatible -- type for Jolts: ` type Jolt is new Natural; `. Max_Adapters : constant := 1000; subtype Adapter_Range is Integer range 1 .. Max_Adapters; j : array (Adapter_Range) of Jolt; top : Natural := 0; jmax : Jolt := 0; verbose : constant Boolean := False; procedure Search (result : out Integer) is c : Jolt := 0; diff_1, diff_3 : Natural := 0; seen : array (Adapter_Range) of Boolean; -- function Check_all_used return Boolean is ok : Boolean := True; begin for i in 1 .. top loop ok := ok and seen (i); end loop; return ok; end Check_all_used; -- begin for i in 1 .. top loop seen (i) := False; end loop; while c < jmax loop Steps : for step in 1 .. 3 loop for i in 1 .. top loop if not seen (i) then if j (i) = c + step then if step = 1 then diff_1 := diff_1 + 1; end if; if step = 3 then diff_3 := diff_3 + 1; end if; seen (i) := True; if verbose then Put_Line ( +"current " & c & " step " & step & " found adapter " & i & " rated " & j (i) & " Jolts" ); end if; c := j (i); exit Steps; end if; end if; end loop; end loop Steps; end loop; if not Check_all_used then Put_Line ("Nooo - some adapters are not used!"); end if; diff_3 := diff_3 + 1; -- 3 jolts from the last adapter to the device. result := diff_1 * diff_3; end Search; procedure Count_Possibilities (result : out Integer_64) is cache : array (Adapter_Range) of Integer_64; -- function Count (from : Jolt) return Integer_64 is sum : Integer_64 := 0; begin if from = jmax then return 1; end if; for step in 1 .. 3 loop for i in 1 .. top loop if j (i) = from + step then if cache (i) = 0 then -- We compute only once the number of combinations -- for a given joltage level. Without cache, the -- computation would take an insane amount of time. cache (i) := Count (j (i)); end if; sum := sum + cache (i); end if; end loop; end loop; return sum; end Count; begin for i in 1 .. top loop cache (i) := 0; end loop; result := Count (0); end Count_Possibilities; compiler_test_mode : constant Boolean := Argument_Count >= 2; puzzle_1 : Jolt; puzzle_2 : Integer_64; f : File_Type; begin Open (f, "aoc_2020_10.txt"); while not End_Of_File (f) loop top := top + 1; Get (f, j (top)); if j (top) > jmax then jmax := j (top); end if; end loop; Close (f); -- Search (puzzle_1); Count_Possibilities (puzzle_2); if compiler_test_mode then if puzzle_1 /= Integer_Value (Argument (1)) or puzzle_2 /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Number of adapters: " & top); Put_Line (+"Max jolts: " & jmax); Put_Line (+"Result of puzzle 1 (diff_1 * diff_3 when using all adapters): " & puzzle_1); Put_Line (+"Result of puzzle 2 (number of ways adapters can be arranged):" & Integer_64'Image (puzzle_2)); -- Part 1: validated by AoC: 2277 -- Part 2: validated by AoC: 37024595836928 end if; end AoC_2020_10; ================================================ FILE: exm/aoc/2020/aoc_2020_10.txt ================================================ 99 104 120 108 67 136 80 44 129 113 158 157 89 60 138 63 35 57 61 153 116 54 7 22 133 130 5 72 2 28 131 123 55 145 151 42 98 34 140 146 100 79 117 154 9 83 132 45 43 107 91 163 86 115 39 76 36 82 162 6 27 101 150 30 110 139 109 1 64 56 161 92 62 69 144 21 147 12 114 18 137 75 164 33 152 23 68 51 8 95 90 48 29 26 165 81 13 126 14 143 15 ================================================ FILE: exm/aoc/2020/aoc_2020_11.adb ================================================ -- Solution to Advent of Code 2020, Day 11 ------------------------------------------- -- Seating System -- -- https://adventofcode.com/2020/day/11 -- ------------------------------------------------------------------------- -- -- HAC 0.084 version. -- -- NB: when run from HAC with the full-size data ("aoc_2020_11.txt"), -- the HAC virtual machine shows its capacity of slowing down your computer ;-) . -- For performance, better use your preferred full Ada compiler... -- -- HAC 0.084 "nice to have"'s detected in this exercise: -- -- * ` aaa : constant Character := 'a';` -- HAC should detect an expression as a static (compile-time-known) value -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_11 is w : constant := 10; h : constant := 10; name : constant VString := +"aoc_2020_11_mini.txt"; -- w : constant := 93; h : constant := 98; name : constant VString := +"aoc_2020_11.txt"; -- type Map_Type is array (1 .. h, 1 .. w) of Character; -- -- empty : constant Character := 'L'; -- Not used. See remarks above. -- occupied : constant Character := '#'; -- Not used. See remarks above. -- procedure Move ( current_map : in Map_Type; new_map : out Map_Type; simple_rule : in Boolean; change : out Boolean ) is function Count_Visible_Occupied (i, j : Positive) return Natural is occ : Natural := 0; -- procedure Scan_Direction (di, dj : Integer) is ii : Integer := i + di; jj : Integer := j + dj; begin loop exit when ii not in 1 .. h; exit when jj not in 1 .. w; case current_map (ii, jj) is when '#' => occ := occ + 1; exit; when 'L' => exit; when others => exit when simple_rule; end case; ii := ii + di; jj := jj + dj; end loop; end Scan_Direction; begin for di in -1 .. 1 loop for dj in -1 .. 1 loop if di /= 0 or dj /= 0 then Scan_Direction (di, dj); end if; end loop; end loop; return occ; end Count_Visible_Occupied; -- threshold : Positive; begin if simple_rule then threshold := 4; else threshold := 5; end if; change := False; for i in 1 .. h loop for j in 1 .. w loop new_map (i, j) := current_map (i, j); case current_map (i, j) is when 'L' => if Count_Visible_Occupied (i, j) = 0 then new_map (i, j) := '#'; change := True; end if; when '#' => if Count_Visible_Occupied (i, j) >= threshold then new_map (i, j) := 'L'; change := True; end if; when others => null; end case; end loop; end loop; end Move; -- procedure Show (map : Map_Type) is begin for i in 1 .. h loop for j in 1 .. w loop Put (map (i, j)); end loop; New_Line; end loop; Skip_Line; end Show; -- function Count_Occupied (map : Map_Type) return Natural is occ : Natural := 0; begin for i in 1 .. h loop for j in 1 .. w loop if map (i, j) = '#' then occ := occ + 1; end if; end loop; end loop; return occ; end Count_Occupied; -- f : File_Type; map_start : Map_Type; map : array (0 .. 1) of Map_Type; c : Natural := 0; changed : Boolean; verbose : constant Boolean := False; part : Positive := 1; compiler_test_mode : constant Boolean := Argument_Count >= 2; begin Open (f, name); for i in 1 .. h loop for j in 1 .. w loop Get (f, map_start (i, j)); end loop; end loop; Close (f); -- for simple_rule in reverse Boolean loop map (c) := map_start; loop if verbose then Show (map (c)); end if; Move (map (c), map (1 - c), simple_rule, changed); exit when not changed; c := 1 - c; end loop; if compiler_test_mode then if Count_Occupied (map (c)) /= Integer_Value (Argument (part)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line ( +"Part " & part & ": stabilized at " & Count_Occupied (map (c)) & " occupied seats." ); end if; part := part + 1; end loop; -- Part 1: Example: 37. Input (aoc_2020_11.txt): validated by AoC: 2386 -- Part 2: Example: 26. Input (aoc_2020_11.txt): validated by AoC: 2091 end AoC_2020_11; ================================================ FILE: exm/aoc/2020/aoc_2020_11.txt ================================================ LLLLL.LLLL.LLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLL.LL.LLLLLLLLL.LLL LLLLLLLL.L.LLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLL.LLL.LLLLL.LLLL.L..LLLLLL.LLLLLLLL LLLLLLLLLLLLLLLLLLLLLLLLLLL.LL.LLLLLLLLLLLLLL..LLLLLLLL.L.LLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLL LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLL.LLLLL.LL LLLLLLLLLL.LLLLL.LLL.LLLLLL.LLLLLLL..LLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLL..LLLLLL.LLLLLLLL LLLLLLLLLL..LLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LL.LLLL.LLLLLLLLLLLL.LLLLLLL.LLLLLL.L L.LL.L...LL......LLL........LL...L.L.L...L...L....L........LL......L.............LL..LL.L...L LLLLLLLLL..LL.LLLL.L.LL.LLL.LLLLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLL LLLLLL.LLL.LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLL.LL.LLLLLLLLL.L.LLLLL.LLLLL.L.LLLL.LLLLLLLLLLLLLLLL LLLLLLLLLL.L.LLLLLLLLL.LLL..LLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLL.LLLLLLL.LLLLLLLL LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.L.LLLL.LLLLLLL.LLLLLLLL LLLLLLLL.L.LLLLLLL.LLLL.LLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLLLL.L.LLLLLLLLLL.LLLLLLLLLLLLLL.L ...L..L..L..L...L..L...L............L......L.....L...LLL.........L..L.LL.LL.LL.LLLL.......... LLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLL.LLL.LLL.LLLLLLLL LL.LLLLLL..LLLLLLL.LLL.LLLL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLLLLLL.LLLLLLLL LLLLLLLLLLLLLLLLLL.LLLLLLLL.L.LLLLL.LLLLLLLLLLLLLL.LLLLLLLLLLLL.LL.LL.LLLLLLLLLLLLLLLLLL.LLLL LLLLLLLLLL.LLLLLLL.LLLLLLLL..LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.L.LL.LLLLL LLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLLL.LL.LLLLLLLLL.LLLLLLL.LL.LL.LLL.LLLLLLLLLL.LLLLLLLL LLLL.LLLLLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLL.LL.LLLLL.LLLLLL.LLLLLLL.LLL.LLLL LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LL.LLLLLLL.LL.LLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLL LLLLLL.LLL..LL.LLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLL.LLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLL LLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLL.LLLLLLLL..LLLLLLLLLLLLLLLLLL.LLLLLLLLL .LL...L......LLL.....L..LL..L.....L.LLLL.L......L.......L...L....L.L..L..LL.L.L.....L.L...... LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LL.LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLL.LLL.LL.LLLLL LLLLLLLLLL.LL.LLLL.LLLLLLLLLLLLL.LL.LLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLL..LLLLLLLL.LL.LL.LLLLLLLL LLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLL.L..LLLLLLLLL.LLLLLLLLLLLLLLLL LLLLLLLLLL.LL.LLLL.LLLLLLLLLLLLLLLL.LLLLLL.LL.LLLLLLLLLLLLLLLLL.LLLLL.LLLLLL.LLLLLLLLLLLLLLLL LLLLLLLLLLLLLLLLLL.LLLLLLLL.LLL.LLL.LLLL.LLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLL..LLLLLLL LLLLLLLLLL.LLLLLLLLLLLL.LLL.LLLLLLLLLLLLLLLLLLLLLLL.LLL.LLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLL.L LLLLLL.LLLLLLLLLLLLLLLLLLLL.LLL.LLLLLLLLLLLLL.LLLLLLLLL.L.L.LLL.LLLLL..LLLLLLLLLLLLL.LLLLLLLL LLLLLL.LLLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLL..LLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLL.LLL.LLLLLLLL LLLLL...L..L.L..L.L..LL..L..L...L.LL.LLLLL.L...........L....LLLLLL..L..L..L.LL.LL...LL.L..... LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.L.LLLLLLLLLLL.LLLL LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL..LLLLL.LLLLLLLLLL.LLLLL.LLLLLL.LLLLLLL.LLLLLLLL L.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL..LLLLL.LL.LLLLLLLLLL.LLLLLLL.LLLLL.LLLLLL.LLLLLL..LLLLLLLL LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL..LLLLLLLL.LLLLLLL.LLLLL.LL.LLL.LLLL.LL.LL.LLLLL .L....L.L.L...LL..L.L.LL..L.LL..LL..LLL.LL..L..L.LL..L.......L.....L...LL......LLLL...L.....L LLLLLLLLLL.LLLLLLLLLLLL.L.L.LLL.LLL.LLLL..LLL.LLLLL.LLL.LLLLLLLLLLLL..LLLLLLLLLLLLLL..LLLLLLL LLLLLLLLLL.LLLLLLL.LLLLLLLL.LL.LLLL.LLLL.LLLLLLLLL.LLLL.LLLLLLL.LLLLL.LLLLL..LLLLLL.LLLLLLLLL LLLLLLLLLL.LLL.LLLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLL LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLL.LLLLLL.LLLLLLL.LLLLLLLL LLLLLLLLL..LLLLLLL.LLLLLLLL.LLLLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLLL.L.LLL.LLLLLLLLLLLLLLLLLLLLLLL LLLLLLLLLLLLLL.LLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLL..LLLLLLLL L......LLLL...LLL.L..L.LL...LL.L.....L.LL...L...LL..LL..LLL..L.L.LLL..L..L...L.LLL..L....L... LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLL..LLLLLLLL.LLLLLLLLL.LL..LLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLL LLLLLLLLLL..LLLLLL..LLLLLLL..LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLL.L.LLLLLL LLLLLLLLLLLLLLLLLL.LLLLLLLLLLL..LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLL.LLLLLLL.LLLLLLLL LLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLL.LLLLL LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.L.LLL.LLLLLL.LLL.LLL.LL.LLLLL ..LL.LLLLL.L...L...LL.......L.........LL..L.LLL.....LL..L.L.LL..L..L.L..L.L..L...L.L.......LL LLLLLLLLLL.LLL.L.L.LLLLLLLLLLL.LL.L.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLLLLLLLLLLLLLLL LLLLLLLLLL.LLLL.LLLLLL..LLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLL.LLLLLLLLLLLL.LLLLLLL.L..LLLLL LLLLLLLLLLLLLLLLLLL..LLLLLLLL.LL.LL.LL.LLLLLL.LLLL.LLLLLLLL..LL.LLLLLLLLLLLL.LLLLLLL.L.LLLLLL LLLLLLLLL..LLLLLLL.LLLLLL.LLLLLLLLLLLLLLL.L.LLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLL.LLLLLLL.LLLLLLLL LLLLLLLLLL.LLLLLLL.LLLLL..LLLLLLLLLLLL.LLLLLL.LLLLL.LLL.LLLLLLL.LLLLL.LLLLL..LLLLLLL.LLLLLLLL LLLLLLLL..LLLLLLLL.LLLLLLLL.LLLLLLLLLLL.LLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLL.LLLLLLL.LLLLLLLL LLLLLLLLLL.LLLL.LL.LLLL.LLL.LLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLL.LLLLLL.LLLLLLL..LLLLL.L LL...LL........L.L....L..L....LLL.L...LL.L......L.LL..L...L.L.L.L....L..L.L...L.L.L....L.L..L LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.L.LLLLLLLL.LLLLLLLL.LLLLLL..LLLLLLL.LLLL.LLLLLLL.LLLLLLLL LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLL.LL.LLLLLLLLLLLLL LLLLLLLLL..LLLLLLL.LLLLL.LLLLLLL.LL.LLLLLLLLL.LLLLL.LLL.LLLLLLL..LLLL.LLL.LL.LLLLLLL.LLLLLLLL LL.LLLLLLL.LLLLLLL.LLLLL.LL.LLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL L.LL.LLLLLLLLLLLLL.LLLLLLLL.LL.L.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLL..LLLLLLL.LLLLLLLL LLLLL.LLLL.LLLLLLL.LLLLLLLL.L.L.LL.LLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLL.LLLLLLLLLLLLLLLL LLLLLLLLLL.LLLLLLLLLLLLL.LL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLLL.L.LLLL.LL.LL.LLLLL ...L.....L............L...L.LL.L.L.L.L...LLL.L.LL.......LL.L.LLLL..LL......L...LLL..L....L... LLLLLLLL.L.LLLLLLLLLLLLLLLL.LLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLL..LLLLLLLLLLL.L.LLLLLLLLLLLLLLLL LLLLLLL..LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLL.LLLLLLL.LLLLLLLL .LL.LLLL.L.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLL.LLLLL..LL.LL.L.LLLLL.LLLLLLLLLLLLLL.LLLLLLLL LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLL..LLLLLLLL.LLL.LLLLLLLLLLLLL.L.LLL.LLLLLL.L.LLLLL.LLLLLLL. LLLLLLLLLLLL.L.LLL.LLLLLLLL.LL.LLLL.LLLLLLLLL.LLL.L.LLL.LLLLLLL.LLLLLLLLLLLL.LLLLLL..LLLLL..L .L..LL.......L..L..L.L........LL...LL.LLLLL........L.LLL......L..L.....L.LL....LLL.....LLL.L. .LLLLLLL.L.LLLLL.L.LLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL..LLLLLLLLLLL.LLLLLLL.LLLLLLLL LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LL.LLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.L.LLLLLLLLLLLL.LLLLLLLL LLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLL.LLL.LLLLLLLLLLLL LLLLLLLLLLLLLLLLLL.LL.LL.LL.LLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL LLL.LLLLLL.LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLL..LLLLLLLLLLL.LLLLLLL.LLLLLLLL LLLLL.LLLLLLLLLLLL.LL.LLLLL.LLLLL.L.LLLLLL.L..LLLLLLLL..LLLL.LLL.LLLLLLLLLLL.LLLLLLLLLLLL.LLL LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLLLLLL LL..L....L...L.L........L.L....L..L..L...L..L..L........L...LLL..L.LL..L........LL..........L LLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLL.L.LLLLLLLLL.LLLL.LL.LLLLL.LLLLLLLLLLL.LL.LLLLLLL. LLLLLLLLLL.LLLLLLL.LLLLLL.L.LL.L.LL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLL LLLLLLLLLL.LLLLLLL.LLLLLL.LLL.LLL.L.LLLLLLLLL.LLLLLL.LL.LLLLLL..LLLLL.LLLLLL.LLL.LLLLLLLLLLLL LLLLLLL.LL.LLLL.LL.LLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLL.LLLLLLLL .LL.LLLLLLL.LLLLLLLLLLL.LLL.LLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL LL.LLLLLLLLLLLLLLL.LLLLLLL..LLLLLLLLLLLLLLLLL.LLLLLLLLL..LLLL.L.LLLLLLLLLLLLLL.LLLLL.LLLLLLLL .....L.....LLLL......LL.L...LL...L..L........L...L..LL..LL.LL.LL..LL...L.......L..LLL..L...LL LLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLL.L.LLL.LLLLLL.LLLLLL..LLLLLLLL .LLLLLLL.L.LL.LL.L.LLLLL.L..LLLLLLLLLLLLLLLLLLLLLLLL.LL.LLLLLLLLLLLLL.LLLLLL.LLLL.LL.LLLLLLLL LLLLLLLLLL..LLLLLL.LLLLLLLL.LLLLLLL..LLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLL.LL.LLL.LL.LLLL. LLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLL.LLL.LL.LL.LLLLL.LLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLL LLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLLLL.LLLL.LL.LLL.L.LLL.LLLLLLL.LLL.L.LLLL.LLLLLLLLL.LLLLLLLL ..L...LLL..LL...L.L.LLLL..L.L...L..LLL...L...LLL.....L.....LL.L....L....L.L..L.L.L....L..L..L LLLLLLLLLLLLLLLLLL.LLL.LLLL.LLLLLLL.LLLLLLLLL.LL.LLLL.LLLLL.L.L.LLLLL.LLLLLL.LLL.LLL.LLLLLL.L LLLLLLLLLL.LLLLLLLLLLLLLLLL.LL.LL.L.LLLLLLLLL..LL.LLLLL.LLLLLLLLLLL.L.L.L.LL.LLLLLLL.LLLLLLLL LLLLLLLLLL.LLLLLLL.LLLLLL.LLLLLL.LL.LLLLLLLLLLLLLLLLLLL.LL.LL.L.LLLLL.LLLLLLLLL.LLLL.LLLLLLLL LLLLLLLLLL..LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.L.LLLLLLL.LLLLLLLLLLLL.LLLLLLL..LLLLLLL LL.LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLLLL.LLL..LL.LLLLLLLL ================================================ FILE: exm/aoc/2020/aoc_2020_11_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 11 ------------------------------------------- -- Seating System -- -- https://adventofcode.com/2020/day/11 -- -- Full Ada version. -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_11_full_Ada is procedure Solve (w, h : Positive; file_name : String) is -- type Map_Type is array (1 .. h, 1 .. w) of Character; -- empty : constant Character := 'L'; occupied : constant Character := '#'; -- procedure Move ( current_map : in Map_Type; new_map : out Map_Type; simple_rule : in Boolean; change : out Boolean ) is function Count_Visible_Occupied (i, j : Positive) return Natural is occ : Natural := 0; -- procedure Scan_Direction (di, dj : Integer) is ii : Integer := i + di; jj : Integer := j + dj; begin loop exit when ii not in 1 .. h; exit when jj not in 1 .. w; case current_map (ii, jj) is when occupied => occ := occ + 1; exit; when empty => exit; when others => exit when simple_rule; end case; ii := ii + di; jj := jj + dj; end loop; end Scan_Direction; -- begin for di in -1 .. 1 loop for dj in -1 .. 1 loop if di /= 0 or else dj /= 0 then Scan_Direction (di, dj); end if; end loop; end loop; return occ; end Count_Visible_Occupied; -- threshold : Positive; begin if simple_rule then threshold := 4; else threshold := 5; end if; change := False; for i in 1 .. h loop for j in 1 .. w loop new_map (i, j) := current_map (i, j); case current_map (i, j) is when empty => if Count_Visible_Occupied (i, j) = 0 then new_map (i, j) := occupied; change := True; end if; when occupied => if Count_Visible_Occupied (i, j) >= threshold then new_map (i, j) := empty; change := True; end if; when others => null; end case; end loop; end loop; end Move; -- procedure Show (map : Map_Type) is begin for i in 1 .. h loop for j in 1 .. w loop Put (map (i, j)); end loop; New_Line; end loop; Skip_Line; end Show; -- function Count_Occupied (map : Map_Type) return Natural is occ : Natural := 0; begin for i in 1 .. h loop for j in 1 .. w loop if map (i, j) = occupied then occ := occ + 1; end if; end loop; end loop; return occ; end Count_Occupied; -- f : File_Type; map_start : Map_Type; map : array (0 .. 1) of Map_Type; c : Natural := 0; changed : Boolean; verbose : constant Boolean := False; part : Positive := 1; begin Put_Line (file_name); Open (f, file_name); for i in 1 .. h loop for j in 1 .. w loop Get (f, map_start (i, j)); end loop; end loop; Close (f); -- for simple_rule in reverse Boolean loop map (c) := map_start; loop if verbose then Show (map (c)); end if; Move (map (c), map (1 - c), simple_rule, changed); exit when not changed; c := 1 - c; end loop; Put_Line ( +" Part " & part & ": stabilized at " & Count_Occupied (map (c)) & " occupied seats." ); part := part + 1; end loop; New_Line; end Solve; -- begin Solve (10, 10, "aoc_2020_11_mini.txt"); Solve (93, 98, "aoc_2020_11.txt"); end AoC_2020_11_full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_11_mini.txt ================================================ L.LL.LL.LL LLLLLLL.LL L.L.L..L.. LLLL.LL.LL L.LL.LL.LL L.LLLLL.LL ..L.L..... LLLLLLLLLL L.LLLLLL.L L.LLLLL.LL ================================================ FILE: exm/aoc/2020/aoc_2020_12.adb ================================================ -- Solution to Advent of Code 2020, Day 12 ------------------------------------------- -- Rain Risk -- -- https://adventofcode.com/2020/day/12 -- -- Compute destination of a ship following navigation -- instructions (interpreted in two different ways). -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src procedure AoC_2020_12 is use HAT; -- function D2R (a : Real) return Real is begin return (Pi / 180.0) * a; end D2R; -- procedure Rotate (x, y : in out Real; a : Real) is nx : Real; begin nx := Cos (a) * x - Sin (a) * y; y := Sin (a) * x + Cos (a) * y; x := nx; end Rotate; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; c : Character; i, res : Integer; wx, wy, a, x, y, d, res_r : Real; f : File_Type; begin for part in 1 .. 2 loop Open (f, "aoc_2020_12.txt"); x := 0.0; y := 0.0; a := 0.0; wx := 10.0; wy := 1.0; while not End_Of_File (f) loop Get (f, c); Get (f, i); d := Real (i); if part = 1 then case c is -- Move the ship directly. when 'N' => y := y + d; when 'S' => y := y - d; when 'E' => x := x + d; when 'W' => x := x - d; when 'L' => a := a + D2R (d); when 'R' => a := a - D2R (d); when 'F' => x := x + d * Cos (a); y := y + d * Sin (a); when others => null; end case; else case c is -- Move a waypoint which is relative to the ship's position. when 'N' => wy := wy + d; when 'S' => wy := wy - d; when 'E' => wx := wx + d; when 'W' => wx := wx - d; when 'L' => Rotate (wx, wy, +D2R (d)); when 'R' => Rotate (wx, wy, -D2R (d)); when 'F' => -- Move the ship forward to the waypoint. x := x + d * wx; y := y + d * wy; when others => null; end case; end if; end loop; Close (f); res_r := abs x + abs y; res := Integer (res_r); if compiler_test_mode then if res /= Integer_Value (Argument (part)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line ( +"Part " & part & ": Manhattan distance of the ship to (0,0): " & res & " (" & res_r & ')'); end if; end loop; -- Part 1: validated by AoC: 1631 -- Part 2: validated by AoC: 58606 end AoC_2020_12; ================================================ FILE: exm/aoc/2020/aoc_2020_12.txt ================================================ N1 R90 S5 R180 N3 W1 L180 F92 R270 E4 F4 W4 W4 L180 S2 W2 F90 E1 S5 W3 F78 S5 R180 F100 N1 W3 L90 L90 N1 F94 W2 R90 F49 W2 F26 R180 W1 S5 R180 W4 S3 R90 W3 S4 E5 S1 F13 N5 R270 E2 R270 S5 F3 E3 F4 S3 R270 S1 W4 R90 S4 L180 N4 F81 W2 R90 F61 R90 F13 N3 R180 W1 F98 S5 F50 W5 S3 W5 R90 F17 S5 F70 F7 E2 F87 E1 L270 F59 E2 R180 N5 F59 L90 N5 W5 F10 N3 E1 R90 W1 S2 R90 N5 F25 R90 E2 F57 R180 E1 N3 W2 F85 L90 F50 W2 R90 S3 R90 F27 E1 S1 L90 F32 L90 W3 R90 E1 F39 S5 E4 F50 W4 L90 F63 N2 F67 W3 R90 F4 N2 R90 F90 N5 L180 F24 E5 N3 L180 F67 E3 L90 S3 F49 R90 E5 F89 W5 F62 F39 F33 W1 R90 F18 S3 R90 N4 F47 N5 N3 W2 S5 L90 E4 L90 W2 R90 W5 L90 W5 N4 F64 R90 S2 W4 R90 N3 F18 L90 S4 L90 F31 S4 L90 F79 R90 F69 N3 E4 F64 N2 E4 R90 F20 R180 E1 F85 W1 S5 S2 F21 R90 F43 N1 F18 S5 R180 F52 L180 W4 F5 L90 F70 S4 N3 R180 F64 R90 F17 R90 E5 F85 N1 F74 E5 F21 N1 F35 N1 F65 W2 F67 N1 E5 F79 S4 R90 F20 R180 W5 L180 S4 F56 S4 L90 E5 F13 S5 F38 W1 S2 L90 N4 E3 R180 W3 N1 R90 F52 N5 F23 E5 F82 E5 S2 E3 N3 S2 L90 N1 R90 S5 F60 W1 N2 W1 N3 E4 F2 E2 L90 S1 L90 E4 N1 R180 E2 R180 F93 F94 L90 S4 E5 R90 F5 S2 E2 S3 E4 R180 F56 E2 N2 F3 R90 W2 F94 W5 F47 L180 F68 E5 F63 S3 E4 F93 L90 S5 L180 W5 S5 W3 L180 F34 R90 F87 W4 S1 W3 R270 S1 E1 F78 E4 R90 F91 W4 S3 W1 F41 N4 E1 F66 S1 W5 F62 N2 W2 L90 W1 F23 L270 N2 W2 S3 F9 R90 F2 E4 F61 L90 W5 N4 F97 L90 F93 N5 L270 R90 W1 R90 R90 N4 E1 F72 N4 R270 F24 W1 F79 S1 E3 N4 E3 L90 W2 S1 R270 W5 F24 E5 S4 F22 L180 F57 S5 R90 N4 W3 F18 N2 R90 E3 F55 N2 R90 S5 F4 W3 L90 N2 W3 L270 E4 R90 F46 S5 N1 F16 N1 R90 F8 L180 N2 W3 N4 E1 S3 L90 F4 E5 N5 E3 R90 F35 N2 F68 F33 E5 F38 E4 F27 R180 S5 F47 R90 F43 R90 S1 F84 L180 F47 R90 N4 E4 F77 R180 N1 E2 S4 F45 S1 L90 E5 F40 L90 W5 F25 W4 R90 F80 N5 E2 F74 W3 N3 E4 F48 N3 R90 N2 W1 L90 S2 F35 L90 E5 R180 W5 N2 E1 L90 N2 F78 S5 R270 S5 R90 N5 E3 L90 S5 F13 S5 F52 L90 N2 R180 E1 F41 S1 F20 N4 F34 N2 F45 E5 L90 W3 L270 N5 F52 R90 N5 E5 N2 W2 W5 R270 W5 F10 N3 F63 N4 F53 L90 E5 L270 F17 N1 L90 F26 F93 R90 S5 R270 S5 R180 N4 F58 L180 F40 S2 F54 N5 F70 W1 N4 W1 L90 W5 R90 N2 R90 S5 F95 W4 L180 E3 F68 S1 F56 R90 W1 L180 F66 R90 S2 F57 L90 E1 F42 S4 F44 L90 F42 E4 R90 S4 W5 R90 E4 S4 E5 F27 R90 N1 R90 E5 R90 W4 S1 F81 N5 R180 S4 E4 F68 S3 L90 E4 E4 L180 E3 F8 W2 L90 S4 L180 N2 L180 E1 R90 W5 N4 W4 R90 F1 S5 E2 L90 F49 N4 W3 R90 E5 F33 R180 S4 E5 S2 F79 W4 F38 R90 F1 L90 F56 L270 N2 L90 E2 L90 F25 W1 S4 L270 W3 R90 N2 F68 E1 R180 W3 R90 W3 R90 S3 F4 W3 N3 R90 W3 N1 F54 W2 S5 E4 F76 F47 N1 F32 L180 L90 F19 N2 E5 L90 E1 L90 E3 R90 F48 R270 S3 R180 S4 F53 R90 F90 E4 F100 L90 F49 N1 W1 F56 E2 N5 L90 F39 R90 W2 F26 E4 N4 L90 F9 L90 F41 W5 N4 S1 W4 N3 R90 N5 L270 F82 L90 F75 S5 F25 S4 F67 N4 F57 E4 N4 F73 W5 L90 E2 R180 N5 L270 W3 F95 W2 S4 E1 R180 N3 W2 N1 F28 N2 R90 E3 S1 F41 E4 N1 R90 F12 L90 N2 S2 E3 F31 W1 L90 E5 S1 F12 R180 W5 R90 F26 ================================================ FILE: exm/aoc/2020/aoc_2020_13.adb ================================================ -- Solution to Advent of Code 2020, Day 13 ------------------------------------------- -- Shuttle Search -- -- https://adventofcode.com/2020/day/13 -- with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2020_13 is use HAT, Interfaces; -- Taken from MathPaqs (Euclidean_Ring_Tools, de-generic-ized for HAC): procedure GCD_and_Bezout (a, b : in Integer_64; s, t, the_gcd : out Integer_64) is -- Finds the GCD and s, t for the -- ` GCD (a, b) = a * s + b * t ` factorization (Bezout theorem). -- Program 1.8, Introduction to number theory, RBJT Allenby & EJ Redfern ta, tb : array (1 .. 3) of Integer_64; q, r : Integer_64; begin ta (1) := 1; tb (1) := 0; ta (2) := 0; tb (2) := 1; ta (3) := a; tb (3) := b; while tb (3) /= 0 loop q := ta (3) / tb (3); for i in 1 .. 3 loop r := ta (i) - q * tb (i); ta (i) := tb (i); tb (i) := r; end loop; end loop; s := ta (1); t := ta (2); the_gcd := ta (3); end GCD_and_Bezout; answer_1, answer_2, d, earliest, sk, tk, sum, prod, gcd : Integer_64; freq_inp, earliest_inp, n : Integer; dmin, idmin : Integer_64 := 0; f : File_Type; freq : array (1 .. 1000) of Integer_64; sep : Character; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := False; begin Open (f, "aoc_2020_13.txt"); Get (f, earliest_inp); earliest := Integer_64 (earliest_inp); n := 0; loop n := n + 1; Get (f, freq_inp); freq (n) := Integer_64 (freq_inp); exit when End_Of_File (f); Get (f, sep); end loop; Close (f); prod := 1; for k in 1 .. n loop if freq (k) > 0 then d := freq (k) * (1 + earliest / freq (k)); -- Next departure after earliest if k = 1 then dmin := d; idmin := 1; elsif d < dmin then dmin := d; idmin := freq (k); end if; prod := prod * freq (k); if verbose then Put_Line ( +" frequency:" & Integer_64'Image (freq (k)) & ", first departure:" & Integer_64'Image (d) & ", delta time: " & (k - 1) ); end if; end if; end loop; if verbose then Put_Line ("First bus for you : ID " & Integer_64'Image (idmin)); end if; answer_1 := (dmin - earliest) * idmin; -- Chinese remainder theorem (the frequencies are assumed to be coprime) sum := 0; for k in 2 .. n loop if freq (k) > 0 then GCD_and_Bezout (prod / freq (k), freq (k), sk, tk, gcd); if gcd > 1 then Put_Line ("Not coprime, Chinese remainder theorem cannot be used."); return; end if; sum := sum + (freq (k) - Integer_64 (k) + 1) * sk * (prod / freq (k)); end if; end loop; sum := sum mod prod; answer_2 := sum; -- if compiler_test_mode then if answer_1 /= Integer_64'Value (To_String (Argument (1))) or answer_2 /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line ("Part 1: first bus for you (encoded answer):" & Integer_64'Image (answer_1)); Put_Line ("Part 2: earliest timestamp for first bus in correct sequence:" & Integer_64'Image (answer_2)); -- Part 1: validated by AoC: 222 -- Part 2: validated by AoC: 408270049879073 end if; end AoC_2020_13; ================================================ FILE: exm/aoc/2020/aoc_2020_13.txt ================================================ 1000511 29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,0,0,0,0,0,409,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,13,19,0,0,0,23,0,0,0,0,0,0,0,353,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41 ================================================ FILE: exm/aoc/2020/aoc_2020_14.txt ================================================ mask = 00101X10011X0X111110010X010011X10101 mem[41248] = 4595332 mem[26450] = 60 mem[32210] = 982366 mem[1060] = 234632920 mem[20694] = 38159 mem[45046] = 58906955 mask = 010110010X1101XX11X0100001X0000X00X1 mem[16069] = 7758 mem[55864] = 2473265 mem[37095] = 103513009 mem[4911] = 1002 mem[63231] = 6932274 mem[21265] = 72322159 mem[43724] = 16591353 mask = 01001X01X101011101010101011X1X000000 mem[63470] = 30339812 mem[16920] = 471738 mem[1014] = 29735753 mem[61061] = 6866 mem[8437] = 9138168 mem[46487] = 1819945 mem[2985] = 15040783 mask = 0X10X1101111001X1X100X1X00011100XX11 mem[32836] = 12902 mem[60365] = 24782 mem[29953] = 10085 mem[18214] = 1160 mask = 001011X10X11100000100X0X0X0X01011001 mem[39434] = 37383633 mem[278] = 670174555 mem[34062] = 20749996 mem[2583] = 6222093 mask = 01X111X1001101X11110100XX001X1000XX1 mem[6075] = 49890 mem[9363] = 2392780 mem[24967] = 218861 mask = X110111X1XX1010101111X01XX1000X001X1 mem[41334] = 11836 mem[24242] = 7263066 mem[17289] = 64986060 mem[2583] = 4702503 mem[21650] = 103905 mem[134] = 486675 mask = 00X010100110XXXX111000XXX1000011000X mem[45307] = 37940 mem[16597] = 224911 mem[17943] = 392744 mem[55001] = 622484 mem[35954] = 470 mask = 11X01011X11000X1X1100X100X011101X011 mem[1005] = 56755 mem[16146] = 4333571 mem[32347] = 10486693 mem[11452] = 377363 mem[25158] = 328161913 mem[51956] = 250388 mem[10044] = 34078606 mask = 011011X1X111010111110000X001X1X00110 mem[8773] = 10575925 mem[33116] = 175 mem[36101] = 14593 mask = 0100010X110X0101010XX10X011111XX1101 mem[21083] = 1922 mem[3653] = 912 mem[26768] = 7321934 mem[49134] = 17616 mem[62950] = 41565481 mem[12957] = 2136786 mem[10324] = 17788 mask = X11X0X0X11010101110X01111010X1100X11 mem[5462] = 18755 mem[39408] = 2435211 mem[49271] = 6589 mask = X1X011XX01X100010110001X0X0X111X1100 mem[52570] = 2166 mem[28731] = 16573421 mem[18265] = 1192 mem[22435] = 10856992 mem[19263] = 7550 mem[30541] = 434738 mem[36101] = 869138 mask = 010001X001010001XX010100000010110X01 mem[52893] = 125505223 mem[22919] = 597 mem[62950] = 54107 mem[52797] = 7649588 mem[30421] = 3968 mem[30429] = 614720 mask = 01X0X10001X100010X1011XX00000X111X00 mem[44718] = 11141064 mem[42713] = 206218234 mem[51781] = 527553473 mem[1967] = 27527823 mem[6386] = 5404 mask = 00101X10XX11X0XX1110001000001110X11X mem[62339] = 72046594 mem[14657] = 3243652 mem[750] = 40239 mem[134] = 1936539 mem[5775] = 266384125 mask = 011X111XXX110X01X11X000X00010100011X mem[2956] = 438895 mem[41520] = 7282 mem[42192] = 34769 mem[8837] = 2587 mask = 01XX11100101000X0X10011XX01010011101 mem[12515] = 450388 mem[62175] = 649233 mem[54743] = 129273 mem[10284] = 159823 mem[31311] = 16983 mem[56137] = 852771967 mask = 11010X1X01010101X1010X11101111X00010 mem[47190] = 526627409 mem[34299] = 540572 mem[61226] = 61426238 mem[12892] = 61446 mem[33421] = 4192 mask = 0110111111X10101111010100XX01XX10100 mem[41685] = 258 mem[26983] = 60795579 mem[28064] = 10483 mem[33070] = 66557269 mem[12624] = 448724 mem[38125] = 141175913 mask = 010X1X00X101000X0111010101XX01011000 mem[12957] = 7693971 mem[45285] = 4628 mem[48546] = 799 mem[17857] = 7578026 mask = 00101X100101X0010110000000XX1010X110 mem[41841] = 234511 mem[27387] = 2990 mem[24636] = 1269957 mem[15638] = 428392 mem[22064] = 272 mask = 0XXX10X01011X011111000000XX0X100X010 mem[26764] = 482715793 mem[8422] = 70439 mem[17857] = 28381730 mem[4524] = 750659820 mask = 11101100010100X1011000111000XX00X010 mem[52570] = 517468200 mem[25263] = 11113122 mem[33421] = 32762600 mask = 11101X01XX1000010X10111000X1101X0X00 mem[16577] = 910 mem[32450] = 16924479 mem[4421] = 24801362 mem[46638] = 8546454 mask = 01X11X1101110101X1X1X010000XX101X001 mem[34209] = 24703796 mem[30481] = 831 mem[46487] = 147322 mem[38619] = 11686 mem[26615] = 1174 mask = 010X0X00110100X1XX000010110XX100X001 mem[53587] = 198046 mem[38420] = 22334 mem[20181] = 962 mask = XX101101X01000010XX01111001111010100 mem[33812] = 107321 mem[8613] = 7395 mem[1117] = 149990 mem[22919] = 23596 mask = 1X01110110010X01X100000001111011X010 mem[57800] = 254591077 mem[6633] = 60308580 mem[8980] = 104196938 mem[5936] = 289911936 mem[44806] = 297364592 mask = 11X10XX0X1010X01010110XXX01111100X00 mem[49271] = 177794 mem[15368] = 259266583 mem[19327] = 590 mem[40243] = 24245 mem[57130] = 1201404 mem[22545] = 1831196 mem[59161] = 25210381 mask = 0X101X11111X010111100X110XX11000X10X mem[38749] = 2091454 mem[45138] = 621877 mem[52107] = 3430339 mask = 0010X110X11X00101X100011XX111X000100 mem[17228] = 252642 mem[23892] = 13721 mem[43787] = 2786942 mem[55481] = 58875 mem[513] = 892 mem[62445] = 40312 mask = 0010X11XXX11001011X01010X0111110X100 mem[17415] = 7415167 mem[9048] = 46059 mem[2159] = 636711036 mask = X010111X111X010X1110X10100XX1000X00X mem[38420] = 104527 mem[24790] = 85 mem[58634] = 127952377 mem[8958] = 11672057 mask = X01X111X00X110XX0X10000000000X0X0100 mem[283] = 241 mem[8898] = 36719 mem[49134] = 217820 mem[31884] = 419937 mask = 0XX11110X1110X0101111000000100110X00 mem[27694] = 6848 mem[25843] = 331711 mem[6688] = 581239 mem[41591] = 171 mask = 0100X100X1010X01010X001XX01XX1010101 mem[30429] = 1103121 mem[42192] = 7844667 mem[21668] = 51727200 mask = 001X1X10001X101XX1100X1000101100X010 mem[4322] = 157863993 mem[49962] = 9140 mem[16964] = 1599 mem[14443] = 2038 mem[3767] = 16636129 mem[13476] = 485497191 mem[1663] = 163345 mask = X101110111010101X1X10011001X10110000 mem[13172] = 195 mem[33921] = 5684133 mem[1337] = 51317 mask = X1XXX101110101X1010X0100XX111X101001 mem[63928] = 4636 mem[56436] = 3887978 mem[6185] = 3037 mem[7095] = 11521156 mem[1663] = 121401 mem[7218] = 20750 mask = 010001001X0101010X00001XXX100XX10100 mem[24149] = 309519 mem[16287] = 12731276 mem[29772] = 65227 mem[37172] = 2824 mem[17508] = 59271 mem[22133] = 3806 mask = 01X0X101011X000X0X101000100011111101 mem[14401] = 158547520 mem[37172] = 16841 mem[40439] = 461272566 mem[60909] = 478018315 mem[43219] = 2154608 mem[25369] = 46117 mem[54852] = 79656 mask = XX10111001X100X1X1100X1X0001110001X1 mem[4213] = 900609324 mem[19327] = 28071 mem[30421] = 782 mem[4804] = 17293 mask = 0100X1000101X0010X010101X01000011001 mem[18139] = 1546181 mem[14021] = 33793814 mem[46699] = 2014 mem[51956] = 171606030 mem[29702] = 475302805 mem[18265] = 198549 mask = 0101X0110X1X0101X1X1X01101001X001XX1 mem[38962] = 132592128 mem[9436] = 7464578 mem[12650] = 49333 mem[8837] = 3234578 mask = 011X11101011X101111000XX001110001110 mem[61694] = 1206 mem[32263] = 20761769 mem[2116] = 193628 mem[13505] = 123039 mem[62164] = 14323289 mask = 1X101010100X0101X1110X01000101X00100 mem[21385] = 1022949 mem[51318] = 5667643 mem[17420] = 36980027 mem[29202] = 801 mask = 0101X01XX11X0101X10110X1010001001001 mem[15338] = 23103863 mem[10488] = 4521 mem[13172] = 17055515 mask = X10111X11X01X111X100000000111011X111 mem[36577] = 397263 mem[8992] = 11944917 mem[22064] = 738796 mem[17310] = 1562710 mem[30068] = 4950154 mask = 011111X10111X10X010X00X1X100X0010001 mem[31166] = 6551 mem[62218] = 1528 mem[11467] = 35999360 mem[39578] = 11530695 mem[30855] = 27864 mem[18369] = 1610323 mem[58953] = 12938251 mask = 01X111010X1111X0010X0XX010000X000111 mem[15411] = 1096 mem[49541] = 3181 mem[23568] = 276408 mem[45168] = 1721 mem[11394] = 155136 mask = 1111X1X011010001X101010X100XX11001X1 mem[61945] = 26647548 mem[63262] = 110741 mem[33783] = 158 mem[12753] = 200460 mem[43229] = 7579 mem[37084] = 26507 mask = 0100110011X10101010X00X01X11X1X10101 mem[65089] = 636807464 mem[5775] = 4440830 mem[52107] = 69328099 mem[38420] = 859060126 mem[21272] = 1700 mem[12062] = 176162 mem[12094] = 8733 mask = X100010111XX01X1X1010100X01101001X1X mem[44718] = 33650499 mem[26507] = 165784650 mem[12622] = 2023 mem[5651] = 120398699 mask = 110001011X010X0111X10X00011110001X00 mem[44975] = 666498 mem[11614] = 751 mem[61354] = 5063 mem[4396] = 1131 mem[25418] = 882 mem[49245] = 64151 mask = 011X1X110111X1XX11X1100X01000X101001 mem[59013] = 1141214 mem[18016] = 95668408 mem[30067] = 18132964 mem[38900] = 286972459 mem[42265] = 13529062 mem[59369] = 6028326 mask = 0110110X010100010XXX0X00X0011X101X1X mem[6479] = 8816055 mem[28451] = 29446 mem[61417] = 59156 mem[6694] = 15597 mem[29264] = 115437 mask = 11110100110101011101XX0001X1X1110101 mem[46886] = 114630 mem[17383] = 452299 mask = 010X110X11X10101000X001X011010000100 mem[19215] = 487176198 mem[59629] = 2120284 mem[27009] = 3064 mem[42335] = 22072 mem[514] = 2010 mask = 0100X1001101010X010000X0001000X00100 mem[37232] = 2564 mem[20561] = 29506163 mem[27396] = 380700410 mem[34075] = 868 mem[24967] = 1882926 mask = 010X1X01XX110111111X0XX0000X010X0101 mem[61084] = 3068852 mem[33028] = 188720342 mem[17375] = 62850 mask = X10X1X0X110101010X01001001101000X000 mem[24149] = 1815 mem[51489] = 197928369 mem[27694] = 231814 mem[11813] = 1002177793 mem[526] = 104755102 mem[22216] = 8396 mask = 0110111101010001X1X0X11100X010001111 mem[21083] = 2509191 mem[13215] = 172339241 mem[12386] = 106305632 mask = X1X101X11101010101000X010X11101101X1 mem[35709] = 64980388 mem[51838] = 62510 mem[48641] = 1174272 mem[42157] = 149 mask = 0X101100010100010X0X00X1100101111111 mem[35807] = 1100541 mem[10044] = 69616152 mem[3047] = 142725213 mask = 11101X1X10X101010111X001XX10X0X00100 mem[38049] = 110 mem[43097] = 14955394 mem[61810] = 3545867 mem[61238] = 5370 mem[20585] = 191903 mem[26133] = 24248 mask = 010X110X011X00010110010100X0XXX1X011 mem[15950] = 140910 mem[12062] = 424527462 mem[11876] = 236 mem[5182] = 4776 mem[50278] = 490 mask = 010XX011011101X1110101110111110110X0 mem[53736] = 2314 mem[12633] = 5053 mem[66] = 49557761 mask = 01X01101X10101010101000X00111110100X mem[18849] = 911 mem[20666] = 12891678 mem[5609] = 10432 mem[59720] = 22145720 mem[17508] = 42631 mem[8585] = 3448 mask = 11X1X10X110101X101010X01X0011011X001 mem[30601] = 9140827 mem[30361] = 4166366 mem[46057] = 16057 mem[26983] = 251682577 mem[63197] = 1603252 mem[52893] = 462048575 mask = 011011100111X00X11100X00100010001XXX mem[17534] = 25807901 mem[4932] = 106350673 mem[42192] = 735653575 mem[10874] = 59007 mask = 01000101110001X1XX001000001X1X011111 mem[48049] = 386 mem[1538] = 138451275 mem[50333] = 15707 mask = 0101100X01110111XX1X0000001011001X01 mem[18139] = 102960 mem[41277] = 5837 mem[44484] = 29937 mask = 11101XX10X1X0001011000100X010010X00X mem[30615] = 95201946 mem[719] = 3697022 mem[27391] = 150969140 mem[62680] = 427952 mem[7349] = 46922 mem[17375] = 41348888 mem[57800] = 1901 mask = 0010X11X1X11X011111X0011001X01001111 mem[46994] = 118757653 mem[32947] = 23571 mem[8653] = 1364 mem[3767] = 6954112 mask = 01001X0011010X000111X0X0X1X011011XXX mem[37908] = 88438829 mem[20630] = 618075182 mem[21520] = 101250753 mem[10703] = 475904 mask = 001001101XX10010111X1X10100111XX11X1 mem[17310] = 2889476 mem[2725] = 463419 mem[65001] = 910330085 mask = X1011011X111010101X110X1X1X0010110X0 mem[15999] = 18586203 mem[12825] = 51333145 mem[29966] = 596120517 mem[26866] = 141039 mem[24223] = 415414 mem[24403] = 16110598 mask = 0XX00X01111X01110X011010101X01101010 mem[43382] = 150995 mem[28011] = 1021785 mem[60339] = 7805893 mem[37197] = 268431 mem[17792] = 253366088 mem[21437] = 24057926 mask = XX1011X111100X00111X1100010111010011 mem[18006] = 265940517 mem[55921] = 1634 mem[27656] = 17058 mem[4911] = 3686 mem[33243] = 8125794 mem[47537] = 146165365 mask = 110111011X01X1X10100X000010110111X0X mem[5775] = 176470 mem[63017] = 24003454 mask = 00011X001X11XX11111X01101010X0000010 mem[1604] = 174349 mem[42888] = 7159712 mem[26615] = 1487 mask = 01X11101100111111X000X1001110001011X mem[5344] = 8563500 mem[21234] = 166162105 mem[48935] = 10849963 mask = 01000101XX0001111000XX0000X010010X00 mem[24149] = 127627213 mem[27338] = 43164114 mem[47215] = 252815 mem[47431] = 32732410 mask = 01011100000100011X0X0XX101X111111100 mem[13412] = 4193068 mem[45046] = 148 mem[63535] = 11659 mem[6518] = 471308933 mask = 111X111011X1X1X101111X000100001101X1 mem[31114] = 118512878 mem[41334] = 1604 mem[7338] = 571 mem[6001] = 4126415 mem[5215] = 4392 mem[47836] = 1862 mem[22064] = 30804845 mask = 0111010X11X1010X0101X1110011101X0111 mem[13321] = 22426593 mem[37095] = 5357 mem[44281] = 467020 mem[62680] = 2721559 mask = 010001X0010100XX10010000011000101X00 mem[30615] = 261491 mem[31097] = 46202501 mem[27880] = 6002395 mem[51385] = 2780 mem[51435] = 43181943 mem[42192] = 107728750 mask = 101011100X1100110X1X00X0101X10X11101 mem[48366] = 859523 mem[14111] = 859 mem[21668] = 292390073 mem[8073] = 858 mem[12920] = 662378 mask = X111X10011X10101X10101XX01111011X101 mem[20630] = 4051571 mem[55963] = 367 mem[379] = 10962356 mem[33028] = 37 mem[24035] = 9459 mem[50949] = 2030 mask = 001011100X110X111X10101100011X010X11 mem[8437] = 47226 mem[41248] = 319 mem[9624] = 3503 mem[6875] = 5282 mask = 11X111XX100101010100X01XX1X1001X1000 mem[21292] = 1673693 mem[51132] = 10346473 mem[7504] = 4325 mask = 111X010X1101011101X100010XX1X0111100 mem[35415] = 6296 mem[19215] = 1263591 mem[49977] = 379136185 mem[62950] = 28156510 mem[8265] = 28662942 mask = 01X110X01X1X0X11X1X00110000X01000100 mem[54672] = 131784041 mem[11394] = 24602 mem[24646] = 10584 mem[44349] = 4883 mem[54743] = 2940969 mem[8265] = 14841530 mask = 0X10111X11100X0011X011XX00X011011010 mem[49374] = 45910 mem[25923] = 368017518 mem[25114] = 8076340 mem[62690] = 904875563 mask = 010X11X0X1X1010X01010X01101001110101 mem[39408] = 3080 mem[6918] = 125955053 mem[27880] = 29186 mask = 01001101X101010X0101X1001111100010X1 mem[11813] = 153838914 mem[20585] = 1917 mem[21385] = 1881773 mem[8556] = 25758757 mem[22435] = 802061 mem[27631] = 13285866 mask = 01101110111X0001011X10100X0100X10101 mem[23441] = 186656612 mem[2186] = 189388742 mem[12866] = 874882 mem[12947] = 23895 mem[20630] = 77211 mem[42083] = 63015239 mem[51838] = 4984972 mask = 00101110X111001X1X10001XX0X111XXX101 mem[14789] = 244532376 mem[21292] = 736136092 mem[10874] = 513949 mem[16755] = 12361 mem[5416] = 22987 mem[39578] = 106587 mask = 010X11000X010001X1XXX0110011X1X1110X mem[43479] = 61 mem[47199] = 15617564 mem[18265] = 6027808 ================================================ FILE: exm/aoc/2020/aoc_2020_14_exm_1.txt ================================================ mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X mem[8] = 11 mem[7] = 101 mem[8] = 0 ================================================ FILE: exm/aoc/2020/aoc_2020_14_exm_2.txt ================================================ mask = 000000000000000000000000000000X1001X mem[42] = 100 mask = 00000000000000000000000000000000X0XX mem[26] = 1 ================================================ FILE: exm/aoc/2020/aoc_2020_14_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 14 ------------------------------------------- -- -- https://adventofcode.com/2020/day/14 -- -- Full Ada version only. -- This problem is too complicated for HAC 0.08x... -- with Ada.Calendar, Ada.Containers.Hashed_Maps, Ada.Text_IO, Ada.Integer_Text_IO; with Interfaces; procedure AoC_2020_14_full_Ada is -- Based on algorithm at https://gist.github.com/badboy/6267743 -- function Hash_64_32_shift (key : in Interfaces.Unsigned_64) return Ada.Containers.Hash_Type is use Interfaces; k : Unsigned_64 := key; begin k := (not k) + Shift_Left (k, 18); -- key = (key << 18) - key - 1; k := k xor Shift_Right (k, 31); k := k * 21; -- key = (key + (key << 2)) + (key << 4); k := k xor Shift_Right (k, 11); k := k + Shift_Left (k, 6); k := k xor Shift_Right (k, 22); return Ada.Containers.Hash_Type (k and (2**32 - 1)); end Hash_64_32_shift; procedure Process_Data ( file_name : String; verbose : Boolean := False; exit_part : Positive := 2 ) is use Ada.Calendar, Ada.Text_IO, Ada.Integer_Text_IO, Interfaces; package Addr_Map_Pkg is new Ada.Containers.Hashed_Maps (Unsigned_64, Unsigned_64, Hash_64_32_shift, "="); package MIO is new Modular_IO (Unsigned_64); use MIO; package IIO is new Integer_IO (Integer_64); use IIO; addr, addr_f, addr_base, b, m_or, m_float, m_and, sum, v : Unsigned_64; mame_s : String := "ma"; mask_s : String := "sk = "; mem_s : String := "m["; mem_s2 : String := "] = "; c : Character; f : File_Type; mem : Addr_Map_Pkg.Map; use Addr_Map_Pkg; cu : Cursor; single_bit_mask : array (1 .. 36) of Unsigned_64; last_X_bit : Natural; -- Some post-game statistics: written_addresses : Integer_64; T1, T2 : Time; begin Put_Line ("Processing data file: " & file_name); T1 := Clock; for part in 1 .. 2 loop mem.Clear; Open (f, In_File, file_name); while not End_Of_File (f) loop Get (f, mame_s); if mame_s (2) = 'a' then -- "mask" Get (f, mask_s); m_or := 0; m_and := 0; b := 2 ** 35; if verbose then Put (" Masks: ------["); end if; last_X_bit := 0; for i in 1 .. 36 loop Get (f, c); if verbose then Put (c); end if; case c is when 'X' => last_X_bit := last_X_bit + 1; single_bit_mask (last_X_bit) := b; m_and := m_and + b; when '1' => m_or := m_or + b; when others => null; end case; b := b / 2; end loop; if verbose then Put (']'); New_Line; Put (" Masks: and: "); Put (m_and, 39, Base => 2); New_Line; Put (" Masks: or: "); Put (m_or, 39, Base => 2); New_Line; if part = 2 then Put_Line (" Single ""X"" bit mask list:"); for i in 1 .. last_X_bit loop Put (" "); Put (i, 0); Put (" "); Put (single_bit_mask (i), 39, Base => 2); New_Line; end loop; end if; end if; else -- "mem" Get (f, mem_s); Get (f, addr); Get (f, mem_s2); Get (f, v); if part = 1 then -- Value is changed. v := (v and m_and) or m_or; mem.Include (addr, v); else addr_base := (addr or m_or) and not m_and; if verbose then Put (" Base address : "); Put (addr_base, 0); New_Line; end if; -- Bit flipping m_float := 0; -- Get as much combinations of 0's and 1's as there are 'X'es: for i in Unsigned_64'(0) .. 2 ** last_X_bit - 1 loop m_float := 0; for j in 1 .. last_X_bit loop if (Shift_Left (Unsigned_64'(1), j - 1) and i) /= 0 then -- Flip the bit of the corresponding 'X': m_float := m_float + single_bit_mask (j); end if; end loop; if verbose then Put (" Compact ""Floating"" representation: "); Put (i, 0, Base => 2); Put (", expanded : "); Put (m_float, 0, Base => 2); end if; addr_f := addr_base or m_float; if verbose then Put (" Setting @ "); Put (addr_f, 0); Put (" value "); Put (v, 0); New_Line; end if; mem.Include (addr_f, v); end loop; end if; end if; end loop; Close (f); sum := 0; written_addresses := 0; if verbose then Put_Line ("----- Summary of memory dump (overwritten addresses only) -----"); end if; cu := mem.First; while Has_Element (cu) loop sum := sum + Element (cu); written_addresses := written_addresses + 1; if verbose or Key (cu) = 0 then Put (Key (cu)); Put (":"); Put (Element (cu)); New_Line; end if; Next (cu); end loop; Put (" Part "); Put (part, 0); Put (" rules. Sum of all values left in memory: "); Put (sum, 15); T2 := Clock; Put (". Total of memory addresses written: "); Put (written_addresses, 5); Put_Line (". Computation time: " & Duration'Image (T2 - T1) & '.'); exit when part = exit_part; end loop; New_Line; end Process_Data; begin Process_Data ("aoc_2020_14_exm_1.txt", True, 1); Process_Data ("aoc_2020_14_exm_2.txt", True); Process_Data ("aoc_2020_14.txt"); Process_Data ("aoc_2020_14_jc.txt"); -- -- aoc_2020_14.txt : -- Sum of all values left in memory: 10717676595607 -- Sum of all values left in memory: 3974538275659 end AoC_2020_14_full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_14_jc.txt ================================================ mask = 00X1011010111X01X1X010X01X1111X11100 mem[13879] = 56974 mem[26072] = 842 mem[47322] = 62104110 mem[31450] = 372784 mem[54364] = 2818920 mask = 01000X10101XX0011000X00XXX00101X0101 mem[13358] = 73976240 mem[41121] = 3647124 mask = 010000X01111X0011000X01010X1001100X0 mem[49893] = 63539 mem[63669] = 79316429 mem[19136] = 256 mem[1117] = 1244 mem[56655] = 267815 mem[22811] = 142 mask = 0101011010111X0111X010110000XXX1010X mem[40297] = 21028792 mem[16007] = 950419537 mem[40907] = 2010 mem[27377] = 525 mem[0] = 209 mem[41317] = 2312973 mem[4641] = 1227100 mask = X0X000101X111001110X011X1X1010X10100 mem[24322] = 103589922 mem[2572] = 1231 mem[53327] = 814998856 mem[30460] = 25015 mask = 00000010XX101X11X0110100X0X001X010X1 mem[50914] = 37339 mem[50218] = 5021282 mask = 0X0X00X01XX0110X1101X0X010000110X101 mem[3780] = 51750101 mem[8561] = 638 mem[64747] = 215 mem[51358] = 194347939 mem[29912] = 9717 mem[44684] = 418165 mask = 0X0X00101011XXX11100001X0101X01101XX mem[1418] = 81827528 mem[38228] = 399582 mem[57488] = 7003 mem[22080] = 112130 mem[29467] = 2198074 mem[32800] = 35048851 mask = 010X00001011100111X0001X0100011010X1 mem[16589] = 1922920 mem[31011] = 88738170 mem[35178] = 4791 mem[17792] = 5560 mem[50656] = 1695 mem[22720] = 1584409 mem[54364] = 1486 mask = 01XX011010X110XXX1X001010X01000X1011 mem[19230] = 13477 mem[41397] = 781359 mem[11599] = 7687201 mem[2817] = 26775 mask = X10001XX1000100X1X00001X01X100011100 mem[288] = 1886 mem[32911] = 326403 mem[48084] = 66681 mask = 00001000X011110X11011000X0X000XX10X1 mem[41020] = 3202 mem[21434] = 5634478 mask = 00X0XX001011X0X1X10X100001110111X011 mem[33545] = 1876 mem[28976] = 581977039 mask = 0X11011010111101011000X1101X000X1110 mem[19071] = 770610413 mem[20064] = 1694 mem[43482] = 2871 mem[46365] = 3148234 mem[52059] = 3513 mem[18760] = 1548 mem[61977] = 605 mask = 010X01XX1X11100X11001X10X10110000001 mem[53801] = 111695 mem[11683] = 168184 mem[20469] = 1949 mask = X1010110X01111011100X010000XX0000000 mem[55872] = 2261951 mem[13140] = 15964 mem[45204] = 22572 mask = X10X0000XX111X01100011X11X1100101101 mem[56655] = 124863920 mem[32800] = 20227 mem[58864] = 42605725 mem[59474] = 859 mem[59729] = 141193 mem[18342] = 1631 mask = 01100XX01011100111X00010XX01X0XX010X mem[13572] = 3383121 mem[32800] = 25726954 mem[54193] = 54397 mem[3305] = 251510 mem[52294] = 33972 mask = 0100X0XX10XX11X11101001010X1X110X100 mem[3991] = 3201095 mem[19248] = 1173 mem[17507] = 684436 mem[37324] = 694 mem[11150] = 44468495 mem[16853] = 3978967 mem[10293] = 3552 mask = X0X00000X01010011011011X1000X01XX001 mem[54689] = 1224 mem[36536] = 33407636 mem[22811] = 296513 mem[58491] = 109654 mask = 010XX1111011000X1000X1000100X00011X0 mem[20982] = 1468 mem[15854] = 13972 mem[55563] = 121451 mem[28871] = 732 mask = 00100X100001000001001101XX100X10XX10 mem[37549] = 11144610 mem[58939] = 280786876 mem[38833] = 1473210 mem[44075] = 571 mem[21698] = 5427778 mem[35937] = 544693 mask = 0100011010111XX10X00011011X010110110 mem[63719] = 36151477 mem[43205] = 79985 mem[9431] = 23613381 mem[38228] = 93679 mem[45544] = 946568 mask = 0X000000101010011101110X11001000XX00 mem[2730] = 8086855 mem[50422] = 3607 mem[9544] = 3738 mask = 0X0XXXX010X1100111100010000001010010 mem[17216] = 2231300 mem[40965] = 30453 mem[43536] = 1780 mem[26440] = 712936 mem[26845] = 445304638 mask = 01X000X1X0101001101111X1000X0001X0XX mem[34736] = 35 mem[23584] = 62941351 mask = 01X000XX1110XX11XX10010000010X00X110 mem[35014] = 2725 mem[31317] = 3 mask = 000XX0XX101010X1X0X111X0100001100001 mem[372] = 21946096 mem[10488] = 41777407 mem[23528] = 1708407 mem[60206] = 182569990 mem[44075] = 816675 mem[43028] = 618865 mask = 0X00X000101X1X01110XX01XX0000011X001 mem[955] = 17506 mem[41317] = 3162029 mem[37] = 9168685 mem[24435] = 33494 mem[10291] = 901681 mem[26688] = 23163 mask = 0100100110X111011XX10010101101101X00 mem[53694] = 184478 mem[38156] = 140154654 mem[3645] = 99833620 mem[5194] = 7438 mem[13132] = 187583 mem[10626] = 213169401 mask = 0X00X11X1011000X100000XXX0001010XX11 mem[58468] = 3932 mem[47108] = 13422709 mem[20791] = 25670347 mask = 0100010010111000110000X1X11111X0X100 mem[64332] = 58063181 mem[20791] = 97103200 mem[21178] = 704 mask = 010X000010101X0X11X111001100X1X011XX mem[29912] = 96861 mem[11661] = 15933204 mem[31973] = 1597059 mask = 010X0010001XX001110011X0000X00101110 mem[54377] = 929 mem[1578] = 1628469 mem[9066] = 1039223 mem[54819] = 131459054 mem[59746] = 97979749 mem[21742] = 919 mask = 010X000010111X011110X100X00X0000X00X mem[25877] = 1030474 mem[40848] = 441 mem[19136] = 40 mem[41305] = 509818516 mask = 11010011XX111011110X111011X11X00X100 mem[56916] = 23553145 mem[43067] = 120593523 mem[41993] = 121958 mem[16589] = 469 mask = 00000XX0101111011101X1011XX1001XXXX0 mem[44363] = 1739 mem[15915] = 49544 mem[5729] = 173493396 mem[29213] = 41122 mem[50656] = 1531 mask = 0X010X1010111X0111000X1XX10100X101XX mem[58111] = 1227 mem[45142] = 3293 mem[30952] = 2965075 mem[25181] = 578696 mem[50656] = 60702685 mask = 0111011010111XX10100X100110101000X1X mem[59881] = 82070 mem[60524] = 62394 mem[35663] = 1981 mem[27322] = 216531615 mem[8965] = 14469 mem[13388] = 1148662 mem[13342] = 92607190 mask = X1000XX110X0111XXX010010X00101110101 mem[2228] = 40376 mem[64755] = 1327525 mask = 11010010X0XX10X11X0X1X011001101X110X mem[15280] = 2364003 mem[19478] = 72063090 mem[8497] = 28240 mem[45678] = 2811 mem[52231] = 39955 mask = 0X001111X011000010X01011X1000XX00X11 mem[24827] = 1639 mem[13879] = 119218 mem[17610] = 6101768 mem[48448] = 3972 mask = XX0000X0X11110X110001111011X00010101 mem[65388] = 9968 mem[26462] = 45065510 mem[27496] = 70270 mask = 01010X1X111X1001101X101X0XX000000001 mem[10134] = 755 mem[34940] = 3959699 mem[26321] = 156 mem[63789] = 36543477 mask = X10X001010111001X1000100001XX00X101X mem[59095] = 888920 mem[26072] = 189525541 mem[41506] = 78022 mask = 01X000101X1X10X11010X1X010X1010X011X mem[19618] = 43629 mem[16853] = 176218496 mem[27558] = 9383 mask = 000000X01011101111001XX00000X0000110 mem[47738] = 782 mem[9654] = 14755 mask = 01X0X0001X01X101110X00000000000X0101 mem[21742] = 34626297 mem[10621] = 1418350 mem[45805] = 3784031 mask = 01XX01001011101X010X001001X1010X0100 mem[18511] = 458 mem[4597] = 8053 mem[34914] = 902 mem[11895] = 2319205 mem[54291] = 7059674 mem[60178] = 1495 mem[64432] = 22061 mask = 1X110010001110011X0X01100X1XX0X01XX0 mem[9055] = 462699 mem[35882] = 554265333 mem[50939] = 52443722 mem[20552] = 160408413 mask = 0100010010111001X100000X01X1001001X1 mem[28976] = 404 mem[64843] = 813 mem[57066] = 899 mem[16179] = 3033125 mask = X101X01X101110X1110011X0X00010X01001 mem[63922] = 122921015 mem[47325] = 66631 mem[34914] = 122827 mem[41369] = 723416 mem[26321] = 350572 mem[10260] = 11917171 mem[20396] = 112670 mask = 00X100101011100111XX010X011X0XX001XX mem[11150] = 875126074 mem[28760] = 25307778 mem[14951] = 445519 mem[54291] = 394307 mem[19109] = 15584261 mem[8221] = 524 mask = 01000XX011111001100000001101X111X101 mem[58015] = 18497 mem[63992] = 530980167 mem[26915] = 14357281 mem[42401] = 12123838 mem[65275] = 14601815 mask = 010X00X0100011X011010010X00XX100010X mem[49005] = 39006890 mem[121] = 119847895 mem[16179] = 737050 mem[52215] = 11770 mask = 010XX0001X10X101110XX10X00000X100111 mem[40066] = 1188 mem[27727] = 10855 mem[47207] = 113852179 mask = 0X10011XX01X1011110000011X11X0XX101X mem[27558] = 1280 mem[18441] = 312 mem[22675] = 2746277 mem[54987] = 120268 mask = 1101XX1010111X011XX01XX0110000001110 mem[8285] = 6819893 mem[56655] = 10287 mem[39027] = 158 mem[25922] = 2798 mem[22261] = 36850389 mem[46394] = 48894888 mask = X1X10010X011100111001000XX100X1X1X00 mem[24614] = 1802 mem[13232] = 499261 mask = 01XX0X1010111XX11100X011010100X0X101 mem[63992] = 12600674 mem[56655] = 99142656 mem[9273] = 302251593 mask = XX000XXX1011101111XX0010000100111X00 mem[18088] = 20379649 mem[47508] = 111520085 mem[38545] = 90881967 mem[21514] = 16333 mem[35731] = 816238944 mask = 110111101X11X1011010X10010000111101X mem[13890] = 4842901 mem[23610] = 19829 mem[21900] = 31928769 mem[10595] = 228191 mem[13375] = 24467 mem[45544] = 149815 mask = 010XX1X0101X100X110X1111010X1100X10X mem[13358] = 7851 mem[18277] = 1322 mem[24517] = 6165 mem[19856] = 93677767 mask = 010X0110101XX0011100X000X00000100111 mem[60820] = 549270 mem[42355] = 609632 mem[35546] = 241510 mem[59340] = 57067 mask = 010X00X0X0101X001X01111011X00XX01010 mem[58491] = 456443643 mem[49058] = 86242 mem[24702] = 25105 mem[35001] = 88082598 mem[36988] = 23981732 mem[54815] = 19064841 mem[52231] = 329 mask = 0XX0001X11101XX011X1X1000000110111X1 mem[7504] = 475530227 mem[29138] = 11235 mem[56376] = 76699622 mask = 0011XXX01011100X1110X111011XX1110X00 mem[52184] = 60066 mem[64705] = 2343316 mem[43172] = 28305258 mem[5362] = 2133 mem[38763] = 2754100 mem[52032] = 7390 mem[2572] = 19579691 mask = 010XX00010101001101X111X000101110011 mem[29623] = 24098 mem[8946] = 24951998 mem[11382] = 184167 mem[47522] = 6393093 mask = XX01001010X11X011110X000XX000100X0X1 mem[10260] = 661 mem[25012] = 11390 mask = 0100001010001101110101100XX110X01XX1 mem[9055] = 297216 mem[49887] = 26800 mem[18511] = 3731 mem[26845] = 42990 mask = 00X0X00010101X1X1001100011X001100001 mem[19591] = 197388201 mem[51460] = 1032 mem[9600] = 934060 mem[58791] = 1646732 mem[50283] = 1235563 mem[26455] = 5018620 mem[288] = 481559 mask = 010X001010110X0X1X001111000XX010011X mem[13491] = 1626583 mem[36536] = 239 mem[56224] = 9125 mem[28105] = 22015873 mem[44531] = 8125 mem[18760] = 25964 mask = X101000011111X011110100011000X010X0X mem[58864] = 709865577 mem[32976] = 303129 mem[44109] = 8025520 mem[51706] = 3030478 mask = 00X01X0010101X0X1X011X110000X10101X1 mem[53349] = 146801393 mem[372] = 27164788 mask = 0X00000010101X011XX11110X000XX1X0001 mem[27091] = 1227 mem[3194] = 234 mem[37] = 4066397 mem[43559] = 17240 mem[36904] = 23282 mem[9186] = 622901569 mem[58468] = 208767 mask = 00XX00X010X11101X101111001110100101X mem[9251] = 230 mem[61367] = 78432672 mem[37478] = 2594 mem[64797] = 71052818 mem[30018] = 11711518 mem[20324] = 64836 mem[61185] = 1433 mask = 010000X0101X11001101011001100XXX0010 mem[31581] = 232228 mem[51766] = 13503 mem[46129] = 1071 mem[27845] = 3969749 mem[17643] = 282089 mem[60524] = 10654 mask = 010X00X01X1110011XX01010XX00X0X10101 mem[41317] = 20899132 mem[17792] = 1949 mem[1117] = 4931 mem[21452] = 423952 mem[29912] = 36667871 mem[10260] = 15401611 mem[28642] = 2840753 mask = 000000X0101111011101XXXX000X001X01X1 mem[57488] = 297477423 mem[8228] = 240002 mem[45051] = 1209316 mem[65123] = 1339 mask = 0100000010101X001111X1011X0001X0X00X mem[25750] = 10538421 mem[59160] = 13024648 mem[7581] = 521295867 mem[44127] = 10349 mem[20791] = 263486916 mem[58844] = 37364 mem[44165] = 213775351 mask = 010X0X0010XX10011100001X0X0X1X0001X1 mem[20221] = 7207 mem[2326] = 247233 mem[54001] = 1782454 mem[41112] = 61297 mem[45994] = 12285 mask = 00X00010X0X1001111000010X0X1001XX10X mem[22080] = 50449 mem[32446] = 69686 mem[46129] = 6052251 mem[45810] = 6931 mem[2730] = 17348930 mem[25557] = 22866081 mem[53007] = 2662 mask = 00000X1010111X0111011X01000X10X0XX01 mem[26747] = 237030337 mem[47589] = 912076 mem[7333] = 105514 mem[62613] = 1442076 mem[293] = 1883 mask = X1001X1010101111110XX010100000100X01 mem[64864] = 522211793 mem[381] = 395572639 mem[39482] = 641 mem[47108] = 37814 mask = 00X00111101110111X001101001110XXX00X mem[16554] = 1304638 mem[56666] = 189089562 mem[12934] = 138931 mem[63122] = 607569 mem[37147] = 131399848 mask = 0X1X11101XX11X0X11100111X100001111X0 mem[24256] = 156773 mem[14436] = 485469048 mem[20781] = 376 mem[23284] = 879110 mem[2582] = 42478 mem[39002] = 3578 mask = 0000XX0X101010011XX000X0000X01100X01 mem[40945] = 11048 mem[36114] = 13782606 mem[2325] = 185202507 mem[33715] = 4806448 mem[61649] = 3756998 mem[55852] = 117 mask = 01000000101X1011110010010XXX0XX11110 mem[5881] = 13440134 mem[22720] = 962895873 mem[25142] = 11785 mask = 0101011010111001010011100XX0011111XX mem[586] = 209 mem[51207] = 145606 mem[21220] = 62604 mem[45100] = 34084913 mem[30986] = 310031 mem[56443] = 483530965 mask = 0000100000X1X10X11X1100010100X011001 mem[41487] = 38587945 mem[21434] = 249215427 mem[7230] = 111149021 mask = X101X010XXX1100101X0X10100100111111X mem[40840] = 2606 mem[63190] = 2447 mem[60328] = 40915 mem[45620] = 13499 mask = 001X0010101110X1X1X0X11X0010X0X001X0 mem[62719] = 785 mem[19974] = 42859172 mem[51864] = 44741 mem[63056] = 27482866 mask = X0X1X0101011X001X100101100101XX1X000 mem[39205] = 10997188 mem[14100] = 29987320 mem[616] = 278639655 mask = 0100000X10101X011X1111000X00X0111000 mem[49278] = 610 mem[9321] = 333537 mem[22656] = 4066 mem[8228] = 2791399 mem[9251] = 3866 mask = X00100X01011100X1X0XX000111011X00011 mem[58260] = 459 mem[18311] = 40779317 mem[10291] = 3362 mem[16865] = 1236 mask = X100X000X010110111X0001100000001X011 mem[1826] = 108687499 mem[4087] = 243589 mem[47489] = 474492676 mem[4129] = 16244 mem[29617] = 819406 mem[43545] = 108512190 mask = 010X0XX0101110X1X100X01X000X0X110100 mem[57918] = 102433847 mem[33825] = 9 mem[372] = 230834 mem[19591] = 7380 mem[65409] = 98189 mem[36391] = 3033 mask = X101X000101111011000X10X100100100000 mem[54029] = 347451 mem[28001] = 82660784 mask = 01X0000010101001X1000000X0X000110101 mem[37266] = 1643 mem[52294] = 242323894 mem[40965] = 11451 mem[52532] = 1191041 mem[1994] = 1830445 mem[16066] = 694 mask = 0X100010X0X1XX0X01001X10X1100X110000 mem[60293] = 92656839 mem[8228] = 24889387 mem[13951] = 25158 ================================================ FILE: exm/aoc/2020/aoc_2020_15.adb ================================================ -- Solution to Advent of Code 2020, Day 15 ------------------------------------------- -- Rambunctious Recitation -- -- https://adventofcode.com/2020/day/15 -- -- Part 1 only. -- If we increase HAC's stack a bit, we can do both parts. -- with HAT; use HAT; -- in ../../../src procedure AoC_2020_15 is type Preamble is array (1 .. 6) of Natural; -- procedure Play (pre : Preamble; start : Positive; puzzle_id : Positive) is compiler_test_mode : constant Boolean := Argument_Count >= 8; stop : constant := 2020; -- We memorize turn of spoken number (if any), indexed by spoken number. mem : array (0 .. stop) of Natural; not_seen : constant := 0; prev, curr : Natural; T1, T2 : Time; begin T1 := Clock; for i in 0 .. stop loop mem (i) := not_seen; end loop; for i in 1 .. start - 2 loop mem (pre (i)) := i; end loop; prev := pre (start - 1); for i in start .. stop loop if mem (prev) = not_seen then curr := 0; else curr := (i - 1) - mem (prev); -- "Age" end if; if compiler_test_mode then if i = 2020 then if curr /= Integer_Value (Argument (puzzle_id)) then Set_Exit_Status (1); -- Compiler test failed. end if; end if; else if i = 2020 or i = stop then Put (i); Put (" : "); Put (curr, 0); New_Line; end if; end if; mem (prev) := i - 1; prev := curr; end loop; T2 := Clock; if not compiler_test_mode then Put_Line (+"---- Computation time: " & (T2 - T1)); New_Line; end if; end Play; -- example : array (1 .. 7) of Preamble; puzzle : Preamble; begin -- No aggregates in HAC 0.083, we need to fill arrays element by element ... example (1) (1) := 0; example (1) (2) := 3; example (1) (3) := 6; -- 2020th number is 436 example (2) (1) := 1; example (2) (2) := 3; example (2) (3) := 2; -- 2020th number is 1 example (3) (1) := 2; example (3) (2) := 1; example (3) (3) := 3; -- 2020th number is 10 example (4) (1) := 1; example (4) (2) := 2; example (4) (3) := 3; -- 2020th number is 27 example (5) (1) := 2; example (5) (2) := 3; example (5) (3) := 1; -- 2020th number is 78 example (6) (1) := 3; example (6) (2) := 2; example (6) (3) := 1; -- 2020th number is 438 example (7) (1) := 3; example (7) (2) := 1; example (7) (3) := 2; -- 2020th number is 1836 -- puzzle (1) := 15; puzzle (2) := 12; puzzle (3) := 0; puzzle (4) := 14; puzzle (5) := 3; puzzle (6) := 1; -- for i in 1 .. 7 loop Play (example (i), 4, i); end loop; Play (puzzle, 7, 8); end AoC_2020_15; ================================================ FILE: exm/aoc/2020/aoc_2020_15_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 15 ------------------------------------------- -- Rambunctious Recitation -- -- https://adventofcode.com/2020/day/15 -- -- Full Ada version. -- Total run time: 0.42 seconds (i5-9400 @ 2.9 GHz). -- with Ada.Calendar, Ada.Text_IO, Ada.Integer_Text_IO; procedure AoC_2020_15_full_Ada is type Preamble is array (Positive range <>) of Natural; -- procedure Play (pre : Preamble) is use Ada.Calendar, Ada.Text_IO, Ada.Integer_Text_IO; stop : constant := 30_000_000; -- We memorize turn of spoken number (if any), indexed by spoken number. type Big_Mem is array (0 .. stop) of Natural; type P is access Big_Mem; mem : constant P := new Big_Mem; -- Heap allocation in case of small default stack size... not_seen : constant := 0; prev, curr : Natural; T1, T2 : Time; begin T1 := Clock; for m of mem.all loop m := not_seen; end loop; for i in 1 .. pre'Last - 1 loop mem (pre (i)) := i; end loop; prev := pre (pre'Last); -- for i in pre'Last + 1 .. stop loop if mem (prev) = not_seen then curr := 0; else curr := (i - 1) - mem (prev); -- "Age" end if; if i = 2020 or i = stop then Put (i); Put (" : "); Put (curr, 0); New_Line; end if; mem (prev) := i - 1; prev := curr; end loop; T2 := Clock; Put_Line ("---- Computation time: " & Duration'Image (T2 - T1)); New_Line; end Play; begin -- Examples shown on https://adventofcode.com/2020/day/15 : Play ((0, 3, 6)); -- 2020th number is 436; 30m-th number is 175594 Play ((1, 3, 2)); -- 2020th number is 1; 30m-th number is 2578 Play ((2, 1, 3)); -- 2020th number is 10; 30m-th number is 3544142 Play ((1, 2, 3)); -- 2020th number is 27; 30m-th number is 261214 Play ((2, 3, 1)); -- 2020th number is 78; 30m-th number is 6895259 Play ((3, 2, 1)); -- 2020th number is 438; 30m-th number is 18 Play ((3, 1, 2)); -- 2020th number is 1836; 30m-th number is 362 -- The "real" puzzle: Play ((15, 12, 0, 14, 3, 1)); -- ^ 2020th number is 249; 30m-th number is 41687 end AoC_2020_15_full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_15_full_ada_hashed_maps.adb ================================================ -- Solution to Advent of Code 2020, Day 15 ------------------------------------------- -- Rambunctious Recitation -- -- https://adventofcode.com/2020/day/15 -- -- Full Ada version with hashed maps. -- Total run time: 2.46 seconds (i5-9400 @ 2.9 GHz). -- -- *But* actually, in this context, a hashed map is overkill -- since the keys (the numbers) are in the range [0 .. stop] ... -- with Ada.Calendar, Ada.Containers.Hashed_Maps, Ada.Text_IO, Ada.Integer_Text_IO; procedure AoC_2020_15_full_Ada_hashed_Maps is type Preamble is array (Positive range <>) of Natural; -- procedure Play (pre : Preamble) is use Ada.Calendar, Ada.Text_IO, Ada.Integer_Text_IO; function Identity_Hash (key : in Natural) return Ada.Containers.Hash_Type is (Ada.Containers.Hash_Type (key)) with Inline; function Simple_Hash (key : in Natural) return Ada.Containers.Hash_Type with Inline is use Ada.Containers; begin return 2654435761 * Hash_Type (key); end Simple_Hash; pragma Unreferenced (Simple_Hash); package Number_Map_Pkg is new Ada.Containers.Hashed_Maps ( Natural, -- Key is the number spoken Positive, -- Element is the turn (the index in a simple array) Identity_Hash, "="); mem : Number_Map_Pkg.Map; stop : constant := 30_000_000; prev, curr : Natural; T1, T2 : Time; begin T1 := Clock; for i in 1 .. pre'Last - 1 loop mem.Include (pre (i), i); end loop; prev := pre (pre'Last); -- for i in pre'Last + 1 .. stop loop if mem.Contains (prev) then curr := (i - 1) - mem.Element (prev); -- "Age" else curr := 0; end if; if i = 2020 or else i = stop then Put (i); Put (" : "); Put (curr, 0); New_Line; end if; mem.Include (prev, i - 1); prev := curr; end loop; T2 := Clock; Put_Line ("---- Computation time: " & Duration'Image (T2 - T1)); New_Line; end Play; begin -- Examples shown on https://adventofcode.com/2020/day/15 : Play ((0, 3, 6)); -- 2020th number is 436; 30m-th number is 175594 Play ((1, 3, 2)); -- 2020th number is 1; 30m-th number is 2578 Play ((2, 1, 3)); -- 2020th number is 10; 30m-th number is 3544142 Play ((1, 2, 3)); -- 2020th number is 27; 30m-th number is 261214 Play ((2, 3, 1)); -- 2020th number is 78; 30m-th number is 6895259 Play ((3, 2, 1)); -- 2020th number is 438; 30m-th number is 18 Play ((3, 1, 2)); -- 2020th number is 1836; 30m-th number is 362 -- The "real" puzzle: Play ((15, 12, 0, 14, 3, 1)); -- ^ 2020th number is 249; 30m-th number is 41687 end AoC_2020_15_full_Ada_hashed_Maps; ================================================ FILE: exm/aoc/2020/aoc_2020_16.adb ================================================ -- Solution to Advent of Code 2020, Day 16 ------------------------------------------- -- Ticket Translation -- -- https://adventofcode.com/2020/day/16 -- -- Run-time with HAC: -- * 1.08 seconds for a Celeron N3350 @ max 1.1 GHz -- * 0.35 seconds for a i5-9400 @ 2.9 GHz -- Run-time with GNAT, AoC_Build_Mode = "Fast": -- * 0.009 seconds for a i5-9400 @ 2.9 GHz -- -- HAC 0.084 "nice to have"'s detected in this exercise: -- -- * ` cc_match := (others => (others => True)); ` -- with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2020_16 is use HAT, Interfaces; criteria : constant := 20; subtype Criteria_Range is Positive range 1 .. criteria; val_11, val_12, val_21, val_22 : array (Criteria_Range) of Integer; -- function Is_Valid (value : Integer; c : Criteria_Range) return Boolean is begin return value in val_11 (c) .. val_12 (c) or else value in val_21 (c) .. val_22 (c); end Is_Valid; -- -- In this problem we have as many columns as criteria: subtype Column_Range is Criteria_Range; ticket, my_ticket : array (Column_Range) of Integer; -- or_str : String (1 .. 4); -- " or "; ok, possible_row, single_match_only : Boolean; cc_match : array (Column_Range, Criteria_Range) of Boolean; unlinked : array (Column_Range) of Boolean; cc, matching : Integer; err : Natural := 0; prod : Integer_64; c, sep1, sep2, sep3 : Character; f : File_Type; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant := 0; begin Open (f, "aoc_2020_16.txt"); for crit in 1 .. criteria loop loop Get (f, c); exit when c = ':'; end loop; Get (f, val_11 (crit)); Get (f, sep1); Get (f, val_12 (crit)); Get (f, or_str); Get (f, val_21 (crit)); Get (f, sep2); Get (f, val_22 (crit)); if verbose > 0 then Put (val_11 (crit), 0); Put (" - "); Put (val_12 (crit), 0); Put (or_str); Put (val_21 (crit), 0); Put (" - "); Put (val_22 (crit), 0); New_Line; end if; end loop; Skip_Line (f, 3); -- -- Read my ticket. -- if verbose > 0 then Put_Line ("my ticket:"); end if; for col in Column_Range loop Get (f, my_ticket (col)); if col < criteria then Get (f, sep3); end if; if verbose > 0 then Put (my_ticket (col), 0); Put (' '); end if; end loop; Skip_Line (f, 3); if verbose > 0 then New_Line; end if; -- for col in Column_Range loop unlinked (col) := True; for crit in Criteria_Range loop cc_match (col, crit) := True; end loop; end loop; -- -- Read the nearby tickets. -- while not End_Of_File (f) loop possible_row := True; for col in Column_Range loop Get (f, ticket (col)); if col < criteria then Get (f, sep3); end if; if verbose > 1 then Put (ticket (col)); end if; ok := False; for crit in Criteria_Range loop if Is_Valid (ticket (col), crit) then ok := True; exit; end if; end loop; if not ok then if verbose > 0 then Put ("Invalid value: "); Put (ticket (col), 0); New_Line; end if; err := err + ticket (col); possible_row := False; end if; end loop; if possible_row then -- Each column in this row fits one or the other criterium. -- We switch off possible combinations that don't match for this data row. for col in Column_Range loop for crit in Criteria_Range loop if not Is_Valid (ticket (col), crit) then -- This column is invalid for this criterium: cc_match (col, crit) := False; end if; end loop; end loop; end if; if verbose > 1 then New_Line; end if; end loop; Close (f); -- -- Part 2 only: for each column, find THE matching criterium. -- for round in Column_Range loop single_match_only := True; -- Find a column that fits only one criterium. -- (Q: is this problem symmetric? Can we find a -- criterium matching only one column?) for col in Column_Range loop if unlinked (col) then cc := 0; for crit in Criteria_Range loop if cc_match (col, crit) then cc := cc + 1; matching := crit; if cc > 1 then single_match_only := False; exit; end if; end if; end loop; if cc = 1 then -- Column col is valid for only one criterium. if verbose > 0 then Put (" Column "); Put (col, 0); Put (" fits only criterium: "); Put (matching, 0); New_Line; end if; unlinked (col) := False; for other_col in Column_Range loop if other_col /= col then -- Cancel the matching criterium for other columns. cc_match (other_col, matching) := False; end if; end loop; end if; end if; end loop; if verbose > 0 then Put ("Round "); Put (round, 0); Put_Line (" done."); end if; exit when single_match_only; end loop; -- -- Columns for my ticket, for criteria "destination" (1 to 6). -- prod := 1; for crit in Criteria_Range loop if verbose > 0 then Put ("Criterium: "); Put (crit, 0); end if; for col in Column_Range loop -- Find THE matching criterium. if cc_match (col, crit) then if verbose > 0 then Put (" column: "); Put (col, 0); end if; prod := prod * Integer_64 (my_ticket (col)); end if; end loop; if verbose > 0 then New_Line; end if; exit when crit = 6; end loop; if compiler_test_mode then if err /= Integer_Value (Argument (1)) or prod /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put ("Part 1: ticket scanning error rate . . . . . . . . : "); Put (err, 0); -- Validated by AoC: 23954 New_Line; Put ("Part 2: product of column numbers for ""destination"" :"); Put (Integer_64'Image (prod)); -- Validated by AoC: 453459307723 New_Line; end if; end AoC_2020_16; ================================================ FILE: exm/aoc/2020/aoc_2020_16.txt ================================================ departure location: 28-787 or 804-964 departure station: 41-578 or 594-962 departure platform: 50-718 or 733-949 departure track: 27-846 or 862-949 departure date: 50-241 or 249-957 departure time: 44-81 or 104-972 arrival location: 45-292 or 299-954 arrival station: 46-650 or 657-974 arrival platform: 42-396 or 405-953 arrival track: 42-871 or 886-973 class: 31-808 or 829-964 duration: 39-909 or 935-969 price: 49-350 or 364-970 route: 44-251 or 264-959 row: 50-539 or 556-952 seat: 45-624 or 630-951 train: 28-283 or 290-960 type: 44-334 or 340-951 wagon: 43-699 or 716-961 zone: 42-668 or 688-958 your ticket: 131,67,137,61,149,107,109,79,71,127,173,157,167,139,151,163,59,53,113,73 nearby tickets: 436,66,560,233,594,569,437,864,15,350,199,146,265,166,666,490,494,689,170,869 744,207,488,829,776,123,949,327,308,219,624,600,337,197,941,502,305,659,77,63 941,201,228,759,490,232,469,631,660,305,562,339,237,185,290,123,411,536,64,772 155,204,699,517,689,940,520,700,756,329,459,690,843,901,534,662,416,212,483,868 715,465,463,519,304,133,561,309,216,367,440,239,899,78,602,566,453,535,487,482 898,250,181,392,176,977,666,160,603,754,941,524,304,501,107,640,495,649,309,899 936,143,507,778,162,652,134,520,316,523,316,393,769,405,458,195,620,832,161,611 843,500,66,657,278,414,313,676,280,483,431,841,442,868,204,632,159,427,690,445 764,303,208,865,127,832,533,758,508,518,14,173,473,227,194,424,344,835,325,606 540,487,392,468,309,632,905,425,534,274,634,866,749,174,734,642,125,600,529,366 640,57,896,574,646,170,688,597,384,312,193,273,724,315,938,440,207,63,425,201 212,468,410,429,232,867,527,875,386,185,199,871,78,487,310,465,506,786,693,241 161,863,209,420,904,771,864,227,761,220,537,623,287,366,161,507,443,251,832,693 202,446,491,835,222,377,377,603,578,787,376,441,342,891,67,628,862,160,129,717 521,208,909,490,806,492,733,750,507,472,314,353,212,473,571,81,50,612,304,157 178,708,525,140,438,772,165,560,158,365,64,382,783,321,514,186,251,568,439,658 319,697,507,238,316,55,668,629,667,80,663,368,772,214,76,439,949,133,311,452 51,190,433,337,370,830,450,344,72,178,227,899,649,889,690,178,638,769,613,598 895,460,557,769,936,386,743,418,528,845,661,791,737,863,507,129,179,532,935,737 464,269,472,426,617,169,613,179,189,113,457,564,120,287,843,347,835,274,305,741 181,528,250,907,189,498,599,309,155,840,198,741,769,132,159,336,210,223,164,537 288,434,171,643,80,577,606,513,61,329,459,631,113,594,193,618,430,909,617,409 189,178,281,329,300,612,613,566,532,434,79,887,322,935,518,427,487,5,907,904 177,311,995,775,535,695,371,162,504,948,753,370,776,182,267,407,136,765,948,342 737,420,898,875,118,764,574,374,233,52,612,186,534,462,836,272,172,193,471,160 797,227,198,237,203,182,481,320,765,600,558,439,428,78,364,382,235,69,835,454 447,385,322,132,299,429,829,484,865,529,519,845,938,340,201,65,886,471,785,288 942,448,611,434,479,280,841,537,894,427,237,656,889,665,661,662,907,525,221,768 303,437,386,276,867,559,71,114,347,185,572,578,881,196,595,366,279,465,762,225 51,114,176,557,692,466,54,779,234,435,130,535,637,654,480,614,179,468,557,70 535,717,599,490,632,371,178,458,138,499,207,574,507,115,656,741,636,434,370,845 388,573,617,440,218,564,862,532,764,377,691,499,126,728,140,438,616,668,50,431 440,519,944,6,516,524,137,76,496,272,307,611,906,782,946,127,735,482,567,376 738,149,775,769,529,748,759,536,694,447,443,126,852,105,139,312,830,345,434,79 184,689,766,273,51,547,758,607,772,531,380,149,349,318,232,184,408,387,485,323 130,694,234,184,184,493,901,343,17,637,634,646,318,110,161,219,512,696,738,510 659,939,577,158,291,136,560,291,279,642,182,489,121,183,869,705,151,750,733,274 485,470,412,644,514,866,462,381,277,267,132,488,419,625,607,196,639,771,528,782 558,844,893,653,137,234,406,535,145,429,516,388,473,748,509,314,451,420,334,806 830,203,407,482,768,319,476,886,327,378,439,173,81,601,214,743,60,57,398,494 132,171,67,240,74,908,770,621,318,52,562,201,920,190,312,942,478,120,221,461 404,233,623,475,220,498,140,187,344,184,127,232,78,841,696,195,538,138,597,225 485,308,624,840,944,641,773,517,526,388,775,184,842,290,617,788,465,475,597,772 127,76,125,462,837,616,391,348,208,648,512,510,176,180,338,761,347,488,742,642 668,235,183,186,745,836,718,624,239,224,228,757,56,801,634,217,787,343,63,762 566,62,367,789,79,664,660,500,155,309,742,236,808,600,428,936,280,190,216,313 561,694,449,280,662,609,513,566,769,185,57,429,655,300,148,903,452,64,900,536 172,159,434,142,191,212,868,604,344,367,495,392,126,167,181,676,534,169,487,863 770,61,942,159,427,334,908,233,626,470,736,302,466,516,568,611,897,320,301,657 133,234,161,388,564,866,531,458,136,438,111,778,320,634,323,113,223,505,331,548 376,648,236,322,871,516,304,405,209,121,641,868,375,385,537,572,274,510,284,773 171,984,445,427,494,596,471,862,281,942,455,949,940,350,907,53,909,342,79,282 196,742,223,221,142,389,175,392,594,135,653,130,198,199,571,108,416,698,897,893 191,321,749,886,493,753,377,560,711,221,311,218,55,158,319,233,718,226,382,301 58,72,159,69,111,371,71,461,334,124,104,663,624,312,410,247,477,834,835,119 762,65,76,595,949,1,55,600,374,210,512,428,613,832,167,643,383,737,442,453 470,611,780,888,472,373,611,270,126,433,227,188,434,497,647,529,488,908,267,653 213,610,449,423,639,215,761,891,568,416,412,350,161,381,185,436,446,896,189,789 474,51,347,840,846,376,421,330,539,559,535,980,56,188,177,576,194,307,189,105 621,838,488,325,395,286,331,742,569,840,612,193,479,393,894,615,466,237,104,509 457,197,300,683,783,322,633,328,372,892,566,439,659,521,163,909,617,561,348,634 743,132,563,559,617,447,456,80,152,829,80,278,249,246,422,329,272,426,613,642 479,736,894,484,776,518,110,221,320,429,299,834,864,468,994,840,345,770,465,760 717,272,203,833,214,208,461,185,59,838,864,702,221,182,318,345,751,431,316,735 371,178,333,374,558,337,865,842,225,405,372,63,277,563,381,446,787,518,749,114 199,534,534,142,630,151,349,597,504,461,454,254,197,451,213,153,746,114,186,575 639,431,938,241,904,760,834,479,464,151,67,693,716,101,170,509,438,570,104,601 470,429,303,184,139,136,888,789,267,182,562,311,660,898,119,573,115,501,272,694 939,832,492,943,61,615,526,423,560,769,718,998,160,76,504,141,136,771,445,739 290,905,292,509,568,513,506,467,498,120,395,59,640,373,192,787,939,195,116,673 638,862,697,235,374,567,405,643,906,421,447,111,427,335,777,605,406,903,866,409 489,553,504,863,524,462,657,807,214,193,562,445,133,333,511,435,215,619,744,193 475,612,240,458,845,694,522,438,793,735,173,618,521,200,441,610,396,238,282,278 186,465,633,128,196,236,507,129,767,497,302,110,300,62,647,872,752,566,516,117 199,136,485,167,250,769,937,4,181,694,777,174,421,595,70,869,601,143,392,647 842,733,227,437,491,344,443,750,552,556,662,693,236,417,78,374,224,424,134,379 868,430,202,553,429,515,935,465,174,391,167,134,158,138,190,905,771,499,394,562 326,785,182,782,74,752,81,147,641,51,199,403,393,182,448,381,434,942,759,455 869,846,430,197,452,747,899,668,86,268,268,333,276,563,773,497,742,394,209,410 190,699,744,384,110,417,435,231,278,432,500,80,736,939,767,993,608,668,776,697 125,152,612,215,666,138,831,468,754,132,64,691,105,661,884,938,461,104,845,640 559,366,418,422,17,219,319,638,277,139,368,888,635,600,439,494,537,389,179,180 949,435,908,442,53,104,314,693,270,210,413,614,516,202,166,436,565,595,936,398 349,485,119,840,190,158,240,327,171,345,291,75,169,837,421,305,781,757,631,99 898,302,373,845,559,198,412,530,68,453,662,941,54,574,540,71,570,350,299,165 502,220,147,471,568,624,935,454,806,453,776,639,410,706,222,495,659,196,636,59 425,469,18,131,331,535,346,500,438,783,268,71,786,57,115,573,622,764,452,159 618,395,658,219,595,426,471,220,388,208,73,77,609,662,427,618,698,457,463,993 528,451,215,232,390,56,201,718,485,668,432,477,536,331,155,137,649,540,276,739 613,637,717,422,763,76,514,641,676,718,210,234,112,637,699,68,154,464,218,449 768,557,945,695,265,900,197,864,318,139,179,906,751,869,757,224,312,629,478,218 481,756,840,345,651,566,316,279,140,694,137,561,748,446,277,311,117,743,418,557 292,246,502,212,268,564,196,368,151,785,122,166,172,645,459,183,316,185,224,537 370,314,299,556,452,805,179,369,909,513,577,694,502,178,10,210,512,634,758,435 482,401,109,396,249,156,304,197,350,373,61,405,939,829,645,749,556,745,831,59 522,781,837,108,753,785,435,234,575,224,525,456,506,558,829,725,829,218,317,763 430,568,830,979,199,331,317,515,426,130,65,120,838,948,647,560,154,371,768,752 407,165,181,413,613,395,841,227,310,428,383,633,193,664,698,776,339,409,233,782 481,275,630,776,343,766,688,630,228,892,631,626,446,896,594,63,431,935,782,750 340,493,746,371,426,752,489,537,529,634,112,884,755,420,783,346,163,148,631,68 417,379,504,138,733,163,147,869,112,613,274,270,301,374,833,142,541,890,784,518 787,472,566,504,568,890,595,657,388,434,292,103,272,428,74,408,201,310,155,190 350,280,418,410,482,466,473,62,304,317,743,316,122,684,749,898,520,774,573,642 235,787,495,275,140,422,768,944,463,249,129,307,108,779,436,524,157,643,507,14 230,646,390,649,867,829,609,100,133,186,690,831,415,381,376,645,393,615,716,634 68,112,62,754,833,778,239,663,267,110,806,914,762,868,168,200,602,350,663,198 625,347,513,513,842,507,330,160,489,532,226,193,130,423,444,567,307,222,63,111 836,140,661,871,169,664,312,745,742,646,998,322,450,214,939,503,161,274,636,224 344,603,649,492,478,772,377,281,250,411,497,719,517,758,643,183,600,464,315,559 119,442,4,105,179,365,425,145,61,535,637,640,434,304,194,562,175,233,539,211 477,337,374,215,778,68,830,141,272,196,483,347,460,118,165,326,693,443,164,867 886,501,607,617,202,222,436,992,577,319,501,745,805,949,232,309,887,533,445,498 471,783,436,899,561,396,431,379,906,407,942,208,611,840,449,304,286,519,163,274 113,494,448,508,889,576,159,271,51,831,597,844,535,736,900,478,328,457,552,107 603,905,104,906,898,871,435,318,327,158,381,536,458,854,178,347,455,606,106,897 223,517,205,658,643,661,522,273,892,250,736,849,532,65,186,689,733,376,521,763 232,166,699,128,378,626,478,534,937,81,617,81,529,333,441,502,903,170,756,603 386,301,123,435,461,830,694,455,519,606,480,245,425,691,214,751,895,415,65,196 203,418,776,525,935,833,171,394,194,180,745,140,981,608,614,775,833,630,193,457 415,944,138,399,563,229,486,268,121,839,697,228,771,739,717,76,250,143,650,164 454,808,116,72,214,458,292,485,634,746,326,754,238,69,72,647,348,487,166,996 153,158,634,314,776,535,326,384,248,510,178,234,274,415,517,104,650,558,454,435 864,805,184,109,895,76,210,114,904,597,751,277,504,649,612,618,164,178,12,749 737,203,403,751,616,868,135,70,202,330,346,59,383,275,442,842,716,381,742,692 652,846,312,130,456,406,207,182,444,650,62,182,304,212,485,69,782,187,132,892 133,783,325,578,893,393,527,620,890,648,560,286,945,845,497,376,269,152,779,179 507,698,459,661,251,835,976,603,165,233,222,365,643,665,531,649,744,519,126,326 508,781,456,657,648,223,291,104,327,556,845,585,690,785,110,536,112,868,574,516 539,612,197,394,188,936,642,440,664,349,231,414,249,445,304,548,457,443,944,145 273,433,434,831,525,213,208,390,213,903,419,418,326,659,525,399,738,143,265,532 896,269,870,376,434,114,113,338,498,898,866,290,395,72,428,831,135,324,176,947 225,556,841,718,304,770,415,888,453,528,644,490,478,106,163,396,733,440,693,295 384,627,842,476,396,774,169,562,129,373,177,51,430,205,130,316,660,624,128,56 383,215,559,449,143,867,505,649,649,182,206,528,398,126,596,561,459,212,577,570 831,128,519,536,395,644,526,119,336,836,837,619,646,774,619,109,473,843,185,349 897,239,486,288,115,432,273,560,453,322,661,453,753,617,144,375,333,140,482,224 528,224,561,382,643,523,219,518,134,5,641,538,753,836,161,417,341,562,607,537 437,406,552,419,558,466,187,947,428,717,190,643,169,943,620,829,482,699,437,525 382,318,630,318,223,495,520,105,514,737,148,421,627,695,374,808,210,196,147,160 380,320,889,902,131,525,176,838,516,642,597,266,686,530,150,154,221,638,368,756 196,273,155,190,534,488,231,641,475,865,742,807,698,204,240,427,272,396,654,333 887,227,176,753,830,899,107,59,623,886,740,319,409,77,375,904,654,524,428,334 754,441,229,483,162,494,226,888,477,322,114,834,790,151,477,837,64,126,751,364 533,217,737,575,11,888,904,566,426,441,748,346,275,762,893,302,609,603,558,533 558,194,717,752,388,53,664,765,854,445,903,599,118,645,70,372,773,347,557,745 900,557,390,326,768,126,143,206,503,169,303,474,694,209,364,185,736,149,664,850 682,891,442,863,474,830,119,746,662,155,781,214,421,308,461,274,365,524,153,889 446,133,603,526,309,716,779,588,204,193,208,778,505,907,188,185,465,240,649,888 153,144,324,248,498,889,772,433,61,843,331,486,380,840,498,116,576,237,786,127 778,201,708,738,485,414,104,314,209,937,122,266,378,842,756,193,842,743,660,214 68,141,763,380,642,180,733,837,741,457,450,534,451,941,534,630,436,469,706,188 280,321,658,383,147,485,613,174,486,622,452,317,711,433,621,452,938,190,693,271 481,668,239,459,308,533,442,319,154,844,422,50,517,193,837,894,621,343,230,243 300,527,206,425,123,393,194,568,191,194,278,622,328,468,170,652,520,234,475,153 209,142,5,51,408,370,57,754,115,214,571,511,201,716,134,223,866,474,408,697 885,277,513,513,106,410,753,866,56,906,426,478,949,328,439,64,378,197,765,762 557,576,230,323,227,484,608,404,455,343,570,947,163,321,155,738,349,277,172,495 302,636,617,623,649,421,70,115,497,303,601,782,216,499,479,297,173,151,604,632 844,442,307,142,54,459,601,510,754,327,219,750,114,935,739,86,636,804,236,181 385,895,761,840,144,787,349,134,122,347,55,836,202,386,131,176,807,227,808,921 414,326,457,781,946,787,224,517,426,307,597,185,444,241,196,903,211,240,445,363 435,644,227,640,937,409,527,936,395,157,846,688,611,166,148,484,890,837,625,163 411,62,612,448,154,276,117,243,66,304,657,571,805,396,606,469,429,280,150,322 106,608,786,320,521,229,227,780,188,599,273,425,389,153,410,804,330,412,128,721 54,935,207,830,697,985,596,120,200,143,564,340,375,841,831,894,842,521,531,691 570,8,646,342,890,939,451,312,805,624,292,908,772,462,454,698,313,568,898,638 138,241,61,124,524,436,109,559,586,411,642,310,386,81,639,170,220,320,862,389 462,472,504,909,689,428,449,633,438,755,576,698,519,404,774,506,365,310,898,179 621,173,315,321,299,174,444,379,619,311,197,431,422,940,179,10,539,206,619,630 773,688,665,323,366,323,785,368,438,329,157,217,600,657,365,286,907,166,534,165 565,393,431,864,288,775,63,528,72,760,142,598,161,465,389,241,210,489,535,231 846,148,153,345,306,747,422,831,560,380,938,460,758,839,130,847,108,783,537,612 246,122,767,806,424,769,314,522,273,166,839,575,182,194,760,617,480,168,604,487 562,878,786,217,271,772,137,63,267,177,408,427,116,215,176,862,787,432,775,395 867,534,55,741,234,689,419,416,639,603,566,684,606,947,221,140,162,568,435,865 481,166,382,489,364,187,612,469,807,159,491,221,18,71,558,599,266,445,189,373 839,535,338,787,68,269,142,649,415,666,604,189,303,521,396,167,320,65,780,232 787,381,210,146,406,387,119,1,946,631,635,67,495,846,641,125,747,418,559,126 396,396,311,418,434,695,844,427,388,629,304,140,228,496,239,465,449,59,130,459 210,762,161,745,829,690,169,976,237,105,532,427,576,889,341,695,375,890,230,622 205,346,438,870,894,601,761,412,455,613,936,324,456,178,492,279,14,409,236,328 487,463,842,750,840,186,222,461,289,280,72,699,538,521,224,419,780,191,367,898 139,187,389,643,349,502,300,367,561,130,186,345,143,137,739,756,77,129,601,628 349,678,188,752,156,225,463,188,278,949,457,375,808,67,905,497,328,488,782,769 77,418,829,134,532,445,276,535,650,698,322,181,496,393,139,931,865,458,148,453 772,224,886,597,752,778,330,525,652,157,290,946,62,773,608,490,179,124,249,164 901,213,286,411,305,392,909,158,139,642,392,304,175,529,125,473,578,569,740,315 147,464,371,159,508,154,571,523,518,534,210,456,77,864,710,717,893,172,424,81 782,125,55,182,631,523,481,556,174,107,369,130,53,328,530,580,104,180,135,451 829,284,330,739,659,81,148,508,179,699,467,372,414,945,527,472,72,633,467,159 218,563,469,976,306,320,838,604,241,769,940,317,383,443,805,455,618,128,645,488 112,213,147,870,743,397,118,616,666,717,453,557,73,174,522,69,556,869,558,317 893,323,841,333,109,638,140,527,665,493,210,295,390,199,328,346,408,610,150,126 597,462,312,704,180,429,482,479,374,534,409,773,505,527,186,348,764,115,688,280 900,943,941,470,484,385,532,618,224,523,753,594,621,602,681,528,455,229,448,898 109,808,741,275,606,744,634,459,474,10,108,383,425,845,739,52,484,124,938,183 165,488,740,429,503,113,620,60,304,514,834,73,76,324,168,141,532,718,318,713 515,761,560,561,371,505,188,617,833,420,753,177,869,884,183,527,165,130,518,909 619,77,573,306,515,306,157,945,239,305,665,836,428,442,394,440,201,866,684,116 808,763,568,507,149,434,503,164,112,75,939,775,145,448,844,21,468,444,496,889 980,524,175,500,233,416,151,864,110,203,936,415,74,616,479,691,617,470,842,639 483,308,315,20,577,209,864,567,569,780,201,716,892,766,869,557,602,907,224,632 585,212,382,778,605,846,602,364,220,251,113,745,511,767,522,146,237,105,750,528 977,180,597,938,81,668,171,778,436,304,199,197,718,864,466,609,716,347,605,348 576,938,215,381,483,350,160,772,131,182,126,831,248,306,622,599,520,416,504,201 648,754,640,159,76,396,753,56,111,690,644,108,588,372,439,665,635,509,80,203 203,807,844,190,317,949,639,654,735,603,603,490,413,604,377,315,370,327,779,127 573,482,656,492,241,417,325,126,806,165,407,890,753,617,347,372,165,236,869,596 907,64,218,516,366,840,233,291,892,122,575,6,424,187,482,665,616,510,232,531 325,806,514,395,475,532,209,412,483,391,480,554,939,607,224,153,602,124,894,119 832,234,384,318,449,980,374,330,221,659,598,235,408,74,906,50,436,718,647,569 179,749,599,150,759,350,75,59,405,568,476,866,757,505,689,230,600,285,641,668 389,510,565,75,264,452,463,537,53,650,526,54,450,59,629,377,81,62,466,746 235,764,889,230,148,935,517,893,717,832,808,754,346,444,907,648,450,890,407,984 427,377,486,453,71,115,567,524,777,529,279,762,544,667,623,290,207,688,571,181 334,388,472,470,277,217,485,549,894,945,612,573,597,768,438,774,435,128,500,305 986,141,211,116,213,302,534,300,598,777,171,841,444,128,183,76,122,131,325,447 904,807,782,62,215,119,442,395,229,52,160,641,185,249,602,772,627,236,482,448 18,69,835,599,760,111,784,109,660,782,937,328,125,126,281,198,766,128,417,176 226,59,511,514,665,643,120,689,517,331,556,411,424,427,935,164,426,275,194,584 300,140,127,746,595,390,502,512,274,69,520,463,170,207,742,188,375,944,127,339 657,479,173,329,126,112,266,808,575,203,176,316,947,270,218,481,978,768,423,563 202,429,520,643,471,778,369,211,125,285,292,207,736,606,774,162,396,696,427,693 320,233,870,887,501,168,13,299,778,110,646,533,477,154,457,474,317,457,128,751 338,783,162,199,755,420,436,838,890,223,378,603,290,907,181,506,301,635,889,205 846,129,187,232,313,756,524,63,610,393,431,60,196,638,539,482,617,805,782,882 449,774,650,625,484,471,806,304,456,443,70,907,904,394,716,267,619,603,236,641 835,300,278,444,54,783,450,144,516,390,718,777,84,528,61,200,766,348,662,173 79,652,480,558,210,649,421,212,736,232,350,329,444,624,768,835,111,146,770,602 778,892,327,612,213,909,458,697,402,127,163,846,488,892,735,459,889,769,482,869 596,223,62,412,396,319,533,745,473,321,642,563,576,543,694,78,188,374,290,279 868,557,782,570,870,463,433,659,785,567,630,441,862,659,446,348,201,65,336,341 463,835,138,829,940,474,473,344,210,568,436,113,834,316,427,124,620,656,313,578 60,414,625,415,608,106,453,620,408,598,832,690,331,63,607,457,364,182,539,838 667,438,458,81,202,487,80,288,413,494,452,609,326,565,409,283,907,467,514,647 893,319,561,225,490,943,658,394,129,465,417,459,563,579,836,164,265,323,312,942 264,308,375,833,539,411,561,66,292,564,121,383,203,870,403,405,207,774,832,442 438,71,218,766,454,505,504,116,890,619,995,316,771,763,364,373,767,480,439,660 475,322,522,173,215,485,311,151,532,655,735,59,173,689,434,106,425,478,139,189 269,382,107,487,233,532,58,471,787,69,216,895,596,314,284,194,662,842,52,839 192,506,574,77,64,575,275,445,885,315,643,223,380,59,770,232,574,376,127,381 198,890,449,749,80,275,114,305,131,754,943,150,211,140,561,761,58,4,158,210 ================================================ FILE: exm/aoc/2020/aoc_2020_17.adb ================================================ -- Solution to Advent of Code 2020, Day 17 ------------------------------------------- -- Conway Cubes -- -- https://adventofcode.com/2020/day/17 -- -- NB: Was able to recycle parts from another "Game of Life" -- puzzle: Seating System (Day 11). -- -- Run time with GNAT (use the aoc_2020.gpr project file, -- AoC_Build_Mode = "Fast", or compile with -- gnatmake -O3 -gnatpn -I../../../src aoc_2020_17): -- * 0.18 seconds on a i5-9400 @ 2.9 GHz -- -- Run time with HAC (Virtual Machine + no compilation optimization: -- we expect a big slowdown with this problem (many nested loops): -- * (too many) seconds, on a i5-9400 @ 2.9 GHz -- -- HAC 0.084 "nice to have"'s detected in this exercise: -- -- * ` map (0) := (others => (others => (others => (others => False)); ` -- with HAT; use HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src procedure AoC_2020_17 is -- max : constant := 10; min : constant := -max; subtype R is Integer range min .. max; type State is (Inactive, Active); type Map_Type is array (R, R, R, R) of State; -- procedure Move ( current_map : in Map_Type; new_map : out Map_Type; wmin, wmax : in Integer -- Relative and absolute range in 4th dimension ) is dl_max : Natural; function Count_Visible_Occupied (i, j, k, l : Integer) return Natural is occ : Natural := 0; -- procedure Scan_Direction (di, dj, dk, dl : Integer) is ii : constant Integer := i + di; jj : constant Integer := j + dj; kk : constant Integer := k + dk; ll : constant Integer := l + dl; begin loop exit when ii not in R; exit when jj not in R; exit when kk not in R; exit when ll not in R; case current_map (ii, jj, kk, ll) is when Active => occ := occ + 1; exit; when Inactive => exit; end case; end loop; end Scan_Direction; -- begin for di in -1 .. 1 loop for dj in -1 .. 1 loop for dk in -1 .. 1 loop for dl in -dl_max .. dl_max loop if di /= 0 or else dj /= 0 or else dk /= 0 or else dl /= 0 then Scan_Direction (di, dj, dk, dl); end if; end loop; end loop; end loop; end loop; return occ; end Count_Visible_Occupied; -- occ : Natural; begin if wmax = 0 then dl_max := 0; else dl_max := 1; end if; for i in R loop for j in R loop for k in R loop for l in wmin .. wmax loop new_map (i, j, k, l) := current_map (i, j, k, l); occ := Count_Visible_Occupied (i, j, k, l); case current_map (i, j, k, l) is when Active => if occ < 2 or else occ > 3 then new_map (i, j, k, l) := Inactive; end if; when Inactive => if occ = 3 then new_map (i, j, k, l) := Active; end if; end case; end loop; end loop; end loop; end loop; end Move; -- function Count_Occupied (map : Map_Type; wmin, wmax : Integer) return Natural is occ : Natural := 0; begin for i in R loop for j in R loop for k in R loop for l in wmin .. wmax loop if map (i, j, k, l) = Active then occ := occ + 1; end if; end loop; end loop; end loop; end loop; return occ; end Count_Occupied; -- map : array (0 .. 1) of Map_Type; c : Natural := 0; cc : Character; f : File_Type; size : Integer; cycles : constant := 6; low, high : Integer; compiler_test_mode : constant Boolean := Argument_Count >= 1; wmin, wmax : Integer; begin for dim_4 in Boolean loop if dim_4 then wmin := min; wmax := max; else wmin := 0; wmax := 0; end if; -- for x in R loop for y in R loop for z in R loop for w in wmin .. wmax loop map (0)(x, y, z, w) := Inactive; end loop; end loop; end loop; end loop; -- Open (f, "aoc_2020_17.txt"); size := 8; low := -size / 2; high := low + size - 1; if low - cycles < min or high + cycles > max then Put_Line ("Test (hyper)space is too small"); return; end if; for x in low .. high loop for y in low .. high loop Get (f, cc); if cc = '#' then map (0)(x, y, 0, 0) := Active; end if; end loop; end loop; Close (f); for cy in 1 .. cycles loop Move (map (c), map (1 - c), wmin, wmax); c := 1 - c; end loop; -- if compiler_test_mode then if Count_Occupied (map (c), wmin, wmax) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; exit; -- ^ This is for HAC & compiler testing: we skip part 2, takes too long. else if dim_4 then Put ("Part 2, 4"); else Put ("Part 1, 3"); end if; Put ( +"-dimensional: number of active cells is " & Count_Occupied (map (c), wmin, wmax)); New_Line; end if; end loop; end AoC_2020_17; ================================================ FILE: exm/aoc/2020/aoc_2020_17.txt ================================================ ###..#.. .####### #####... #..##.#. ###..##. ##...#.. ..#...#. .#....## ================================================ FILE: exm/aoc/2020/aoc_2020_18.txt ================================================ 2 * 9 + 5 + ((8 + 6 + 5) * (2 + 3 * 9 + 3) + 5) * (7 + 9 + 7 + 3 * 7) * 5 7 + (2 + 8 * 8 * 2 + (4 * 3 * 9 + 4 * 4)) + 4 * 3 6 + 9 * 2 * 2 + (2 + (7 * 6 * 6) + 4 * (7 * 8 * 2 + 4) * 7) + 7 2 + ((3 * 6 * 5 * 4 + 7 * 7) + 5 * 4 * 5 * (8 * 7 + 9) + 8) * (4 + 6 * 5) (7 * 6 * 3 + 4 * 3 * 9) + (6 * 6 * (4 + 6 + 4) + 7 + 2 + (9 * 8 * 9 + 9 * 7 * 4)) + (3 * 4 + 3 + 2) * 8 (3 + (7 * 7 + 9 * 9 * 6)) * 3 * 5 + 4 * 8 8 + 9 * (2 + 2 * 5 + 9 * 2) * 2 + ((6 + 4) * 4 + (4 * 7 + 3 * 3 + 7) * (4 * 5 + 8 + 8 + 7 * 6) + (6 + 2) + 5) (2 + 2 * 9 * 7) * ((9 + 8) * 3 * 6 + 6 + (5 * 4 * 4 * 3)) + 9 + (3 + 2) 2 + 7 * 3 + ((7 + 7 * 3) * 6 + 8) 2 + 7 + 6 + (4 + 7 * 7) + 9 * 2 (9 * 2 * 4 * 4) + 4 8 + (8 + 8 + 7) * (5 * 4 + 4 + 5 * 5) * 9 + 8 (6 * (4 * 2 + 4 + 7 + 4) + 4 * 7 + (7 + 5 + 3 + 3 * 7) * 6) * 6 + 3 + 6 + 5 5 + ((7 * 3 * 2) + 9 * (9 + 2) * 6) (3 * (2 * 2 * 3 * 7 * 2) * 8) * 8 ((3 + 2) + 5 + 7 + 3 * (8 + 4 + 5 * 8 * 9)) + 7 * 3 * 6 7 * 6 + 8 * 4 + ((7 + 5 + 2 + 4 * 9 + 9) * 7 + 5) 6 * (6 * (4 + 8 + 6) * 6) 4 + 3 + (6 * (2 * 8)) (2 * 8 * (3 + 8 + 3 + 2) * (8 * 4 + 2 + 8) * 9 + 7) * 8 4 * (3 + 9) + 9 + 4 + 8 + 4 ((6 + 3 + 5 + 6 + 6) * 9 * (2 + 7 * 4 * 9 + 3 * 7) + 6) * (3 * 9 + 2 + 7 * 3) * 6 8 * (5 + 4 * 3) + 3 * 7 + 6 * 4 4 + 6 + 6 + (4 + 9 + 3 + 3 + 3) + (2 + 6 * 2 + 3 + 4) * (2 * 4 + 9 + 3) 7 + (3 + 2 * 4 + 4 * 9 + 2) * 2 * ((8 * 6 + 6 * 2 + 7 + 7) + (2 + 8 * 7 + 6 * 9) + 7 * 6) * 7 + 8 3 * (8 * 7 * (5 + 2 + 8 * 9)) 6 * 9 + 2 + 8 + (4 * 3 * 4 + 6) (2 * 6) + 7 * 9 + (3 * 9 + 8 * 4 * 3 * 5) * (9 * 7) 5 * 2 + (3 + 5 * (5 + 7 + 7 + 4) * 2) 9 + 4 * (8 + 3 * 2 + 9 * 6 * 4) * 9 * 6 6 + (6 * (2 * 5 * 4 * 7 * 3) * 9 + 4 + 6 * 3) + 4 * 8 (6 + (4 * 7) + 6 * 5) + 4 + 7 + 2 3 + 4 * 9 + 9 * 8 + (3 * 4 + (9 * 6 * 9 * 2) * 5 + 8) 8 + (3 + (9 * 3) + (6 * 4) + 8 * 6 + 8) + 5 (7 + 6 * 3) * 2 + 5 6 + 6 + ((6 + 7) * 9 + 5) * 2 (3 * 3 * 2 * 5) + 9 * 9 + 3 (8 * (6 + 2) + 4) * 9 (4 * 6 * 6 * 3) * 9 * 4 + 4 * 4 * 9 5 * 5 + ((8 * 9 * 2 + 5) + (3 + 7 * 5 + 2) + 2 + 8 + 5) 9 + 8 * (6 + 2 * 2) + 7 + 4 * 9 7 * 8 + (9 + (9 + 4 + 6 * 6 * 9 * 6)) * 8 * 5 9 * 7 + 8 + 7 * (4 * 2 + (6 + 3 * 4 + 6 * 6 + 6) * 2) + 9 8 + 2 + (4 * 3) + (2 + 8) * 5 * 7 2 * 7 * 7 * 8 + (3 * 4 * (7 * 4) + 5 * 8) 2 * ((6 + 7 + 6 + 2) * 4 + (9 + 4 * 5) + 8 + 6 * 7) (6 + 4 * 4 + 9 * (4 + 9 * 5 + 9 + 9 * 9) + 7) * 2 8 + 9 * (4 + (6 + 4 * 3 * 6 * 6) + 7 + (6 * 2 * 8) + (9 + 5 * 3 + 3 * 3) * 9) * 9 * 4 (8 + 8 * 9 + 9 + (7 + 8 * 3)) * (6 + 4 * 7) 2 + (6 * 3 * 5 * 5) + 4 + 9 + (4 + 9 + 9) + 4 8 + 3 + 8 + (4 + 6 * 6 * 2 * 5) + 5 * 5 2 * 4 + (7 + 6 + 9 + 5 + 9 + 2) (5 * 5 + (5 + 7 + 4 + 3 + 7) * 4) + ((6 * 4) + 2 * (8 + 8 + 4 * 4) * (7 * 7 * 2 + 3) + (8 + 6 + 8 * 2 * 8 + 8)) * 7 3 * 4 * (7 + 6 * 4 + 6 * 3) * 4 + 4 + ((8 * 6 + 2 + 5 + 7 + 6) + 6) 9 + (9 * 7 + 2 * 9) + 8 + 6 4 + 6 + 7 + 6 * 3 5 * ((4 + 4) + 4 + 7 * 9) * 6 9 * 6 + 6 + (4 + (5 + 9 + 2 + 9 * 5 + 8) * 4 * 8 * (3 * 4 + 7 * 6 * 3) + 7) * (4 + 4 * (6 + 7 * 6 * 7 * 9)) * 5 6 + (2 + 4 + 6 + 6 + (8 * 7 * 2 + 6)) + 5 + 9 + 2 + (8 * 7 * (9 + 8 * 6 * 6 * 7 * 3)) 6 + 9 + 7 + 8 + (8 * 6 * (5 + 5 * 7 + 3) * 8 * (4 + 8 * 2 + 9)) (9 + 3 + 8 + 4 + 8 + 4) * 6 * 3 * 6 5 * ((5 + 7 + 2 * 3 + 4 + 3) + 3) + 6 + 4 2 * (8 * 4 + (9 * 3) * (7 + 2 + 3 * 4) * 7) * (6 + 9 + 7) + 5 + 4 + 7 9 * (9 * (8 * 9 + 5 * 3 * 2) + (9 + 7 + 8 * 8) * (9 * 7 + 6)) * 3 * 3 + 8 * 6 5 * ((2 + 5) * (8 + 2 * 6 + 6 + 3) + 9 + 3 + 9) * (7 * 4) + (3 * 7 + 8 + 5 + 2 + (7 * 7 + 6)) + 4 * 7 (2 + 8 + 6 + 6 + 8 + 3) + 5 + (5 + 7 * 8 * 5 + 5 * (2 * 4 * 2 + 2 + 6)) 5 + 6 + (9 * 7 * (6 * 8 * 4 + 7 * 2 * 4) + 3 * 5) + 4 + (2 * 4 * 6 * (9 + 6 + 7)) 5 + 6 * (7 + 5 * (4 * 3 * 9)) 6 * 8 + 4 + (2 + 8 * 6 * 2 + (5 + 9) * 3) + 6 (7 + 5) * 7 + 5 * (6 + 4 * 9 + 6 * 2) 9 * (9 + (5 + 9 * 7 + 7 * 2 + 2) * 9 + 8 + 5 * 6) + (5 + 5 * (2 + 4 + 7 + 9 + 6) + 2) * 9 * (3 + 5 + (8 + 2 * 2 + 7 * 7 * 6)) 7 * (7 + 3 * 8 * 9 * 9 + (5 * 2)) + 5 9 * 9 * (8 + 3 + (2 + 9 + 6 + 6)) * 4 + 2 + (2 + 9 + 6) ((9 * 4 * 9 * 3 + 2 * 5) + (7 + 2 * 4 * 3 * 6 * 8) * 7) * 3 * 9 (3 + (8 + 6 * 6 * 5) + (3 * 5 + 8 * 5) + 7 * (2 + 3 * 7)) + (8 * (6 * 8 * 5 + 8 * 2)) + 8 4 * 4 + 5 * 8 * (2 * 2 + 8) * 8 7 * 8 + (5 * 4) * 7 + 2 + 9 ((4 * 9) * 4 * 8 * (4 * 6 * 5 * 2) * 5 + 9) + 7 * 2 + 8 ((4 * 3 * 9 + 7 * 7) * (7 + 3 + 7) + 9 + 6 + 8 + (3 + 2 * 6 * 2 * 9)) * 2 + (7 + (9 * 9) + 6) * 3 + 6 8 + (9 * 8 + (2 + 3 * 3) + 4 + 4 + 4) + 4 * (5 * 4 + 4 * 6) * 7 + 8 9 + 8 * ((2 * 5 + 7 * 2) + 3 * 4 * 3 * 8 * (2 * 6 + 6 + 3 * 5 + 6)) + (8 + 9 * 8 * 2 * 3 * 9) 8 + (9 * (8 * 5)) (5 * 4 * 9 * 3) + 7 + (3 + 7) 3 * (2 * 8 + 2 * (8 * 3 * 8 + 8)) * 7 + (6 + 7) 3 + 4 2 * 8 + ((8 + 9 + 6 * 7 * 4 + 5) + 2 + (5 * 2 + 8)) * 4 + 2 2 + 5 * 7 * 4 * (3 + 9 * (4 + 5 * 7) + 4) + 5 5 + 7 * (6 * 9 + 9 + 5 * 3) + 8 4 + (8 + 6 + 5 + 5 * (2 + 6) * 5) 5 * 4 + 3 + ((4 * 5 * 7 * 6) + (7 * 7 + 6 + 8 * 9 + 4) + 5 + 2 * 7 * 5) 9 * (8 + (4 + 9 * 8 + 7 * 3) + 3 * 9) + (7 * 7 + 5 * (5 + 7 + 3 * 9)) 4 * 6 + (2 + 6) 6 + 2 * 2 + 4 4 + 9 * 7 * (2 + 5 * 4) * 9 (2 + 4 * (2 * 9 * 4 * 8 + 5 + 4)) + 4 + (8 * 7) + 7 + (3 + 5 * 7) 9 * 8 * 8 * (6 + 6 * 2 + 5 * 7 + 3) + 6 + 8 (3 + 9 + (7 * 2 + 2 + 3 + 2)) + (4 * 6) ((6 + 3) + 3 * 8 + 7 * 7 + 8) + (9 + (8 * 6 + 7) + 2 + 5 * 4) + 5 + 3 8 * ((5 + 2 * 9 + 2 + 7) * 7 * 7 + 7) * 4 + 8 + (4 * (3 * 9 + 3) + (2 * 9 * 4 * 9 * 7 + 6) + 6) * (8 + (2 + 5 * 3 + 8) + 4 + 8) 5 + 4 + 7 * (4 + (5 * 5 + 3 * 3 + 8 + 7) + 3 + 8 * 6) ((9 + 5 * 5 * 6 + 4) + (2 + 2) * 2) * (9 * 9 + 7 * 7 * 6) + 9 + 6 + 2 + (9 * (5 * 9) + 3 * 5 * (5 * 2 * 4 * 7)) 2 * (9 * (5 + 9 * 2 * 9) * 9 + 6) * (2 * 6) * 5 + (3 + 9 + 4 + 6 + (4 * 5 * 7 + 6) + (6 + 7)) * 7 3 * 8 * 8 * 9 * 2 + 3 6 * 8 * 6 + (2 + 7) + 5 (6 * (3 * 4 + 6 + 9) * (2 + 8 + 3 * 8 + 3 * 2)) * 7 * 9 * 7 8 + (4 + 9 + 2 + 9 * 2 + 9) 5 + 7 + 6 + ((2 * 2 + 7 + 3 + 9) + 2 + 8) * 7 (3 * 2) * 2 * 7 * 5 9 + ((4 * 3 + 3 * 6 * 2 * 9) * 5 * 7 * 3) * 4 * 7 * 2 (2 * 2 + 9 + 7) + (6 + 4 * 9 * 5) + 6 * 8 * 3 + 8 8 * 8 + (7 * 9 + 6 * 7 * (2 * 2) * (4 + 2 + 8 * 2 * 3)) + 4 (3 * (7 * 9 * 6) + 2 + (2 * 6)) * (4 * 3 * 7) 2 + (2 * (6 + 9 + 9 * 6)) * (7 + 7 * 3 + 8) + 7 + 3 9 + (5 * 2 + (8 * 4) * 7 * 5) + 9 + 4 2 + 4 * 4 + 8 * 3 + 5 8 * 2 * (8 * (7 * 3 * 5 + 7) * 5 + 6 * 4 + 9) * 8 * 2 * 8 ((7 + 4) + 7 * 3 + 6 * (3 + 6 + 8) * (5 + 4)) * 2 * (7 + (2 + 3 * 5) * 5 + 3 + 6) * ((6 + 3 + 4 + 2 + 3) + 4 * (3 * 7 + 2)) (2 + (3 * 8 * 2)) + 2 * ((3 + 6 + 3 + 7) * 5 * (9 * 2 + 6 + 7 + 3)) (6 + (7 * 2 + 4 * 9 + 5 * 2) + 4 + 8 * (4 * 8 * 5 + 7) + 9) * 7 + 2 * 9 2 + (6 + 4 * 2 + (7 * 2)) * (8 * 6 + 6 * 4 + 5 * (5 * 4 + 9)) (6 * 3 + (5 * 8 * 4 + 7)) + 7 * 7 + 9 + 9 + 7 (2 * 9 * 7 * 5 * 7 + 5) * 8 + (8 * (9 + 9 * 8) * 7) * 4 + 5 6 + (3 + 8 + 4 + 9 * 7) 4 * 8 + 2 ((8 * 8 + 4 + 9) + 9 * 7 + 8) * 8 * (5 + 7 * 5) * 2 + ((3 * 2 + 6 + 6 * 3) * 8 + 9 * 9 * (9 * 6)) + (4 * 8 * (5 + 8 * 5 * 8) * 6 * 9 + 8) (3 * 6 * 7) * (4 + 8) + 9 6 * ((9 * 3 * 4 + 9 * 2) + 7 + 2 * 6) 6 + (7 + 8 + 2 * 5 * 2) * 7 + (5 + 3) * 7 7 + ((6 * 8 * 6 * 3) * 9 * 3) + 9 + ((3 + 4 * 2 * 6) * 4 * 3) + 5 + 3 (4 + 3 * (5 * 2 * 2)) + 5 4 * 3 * (6 * (4 + 3 + 9 * 3)) + (4 * 2 * 5 + (9 * 2) * (6 + 8 + 9 + 6 * 8 + 8) + 2) + 6 + 8 7 * 5 * 9 + 7 + (5 * (9 + 8 + 3 * 6 * 3)) * ((3 + 5) * (7 + 9 + 3 + 6 * 2) * 3 + 9) ((3 + 3 * 9 + 4 * 8 * 2) + 6) + 2 * (5 * (2 * 5 * 7 + 8 + 6) * 2 + 8 + 3 + 6) + (4 + 6 + 4) (2 * 8 + 8 + 4 + 3 + 5) + 7 6 + (6 * 5 * 9 * 6) 8 + 2 + 6 + 3 + (9 + 6 + (7 * 3) + 5 + 4 + 8) 6 + 7 * (3 * 7 * 5 + (9 + 6 + 6) * 7) * (3 + 4 + 7 * 4 + 6) * 4 * 4 9 * 9 * (4 * 4 * (3 * 2 * 2 + 4 + 7 * 3) * 7 * 5 + (7 * 4)) + 5 9 * ((6 + 3 * 6 + 2) + 4 * (9 * 8 + 8)) + 5 * 6 * 4 + 4 (8 * 9 + (8 + 5 + 8 + 5 + 3)) + 3 + 6 * 4 * 2 * 4 8 + (3 * 6 * 7) * 4 * 4 * 3 (6 * 8 + (2 * 2 + 3 * 8) + 6 * (4 * 9)) * 6 * (2 * 8 + 7 * (8 + 9 + 6 * 9 + 3 + 3)) 3 + 8 * 2 + (8 * 3) 4 + 3 * 2 * (5 + 3 + 5 + (6 * 5 * 3 * 6 * 6)) + 9 + 7 (3 + 5 + (3 + 9 + 9 + 7) * 7 * 6) + 7 * 5 * (5 + 3) 2 + ((7 + 2 + 9 + 2 + 6) * 3 * 2 * 5 * 5 + 2) + 2 6 * 8 * (2 + 4 * 9 * 5) + 9 + 3 4 * (6 + 9) 5 * 2 + 3 * 2 * (5 * 3 * 9 * 7 + (6 + 4 * 5 + 6) * (6 * 2 * 2)) * (9 + 6 + 9 + (8 + 9 + 9)) 5 + (4 * 4 * 5 * (4 * 2 * 4 * 2) * 7) * 2 3 * 2 + ((4 * 6 * 8) + 9 * (3 * 9 * 8 * 2)) (3 * 5 + 6 * 8) + 5 + ((2 + 9) + (3 + 4 * 2 * 5 * 3) + 4 + (3 * 7)) * 6 6 + 3 + 2 + 4 + (6 * 2 + 6 + 4) * 2 (5 + (5 + 6 + 7 * 2) + 7 + 4 * 5) + 5 * 6 * 9 4 * 7 * (3 * 2) + 4 (5 + 4 + (8 + 3 + 7 * 2)) * (6 + (5 + 7 + 3 * 8 + 4) * 5 + 6 * 6 * 5) + 7 2 * 5 + (5 + 4 + 3) + (9 * 3 + (7 * 6 * 9 * 4 * 3 * 2)) * 3 + 2 (8 * 2 + 3) + 5 * 2 * 9 + 9 + (3 + 4) 9 + 6 * ((4 * 7 * 9 * 5 * 4 * 5) + 8 * 8 * 7) * 7 5 * 4 + ((3 + 2 * 5 * 6 + 7) + 7) + 2 3 * 9 + 4 * 9 9 + 7 + (7 + 5 + 3 * (5 + 7 * 8 * 7 + 5 + 7)) + (7 * 6 + 5 * 8) + (8 + (2 + 3 * 3 + 4) + (6 * 9 * 9) * 8) * 6 8 * (2 * 7 * 3 * 4) + 9 * 3 + 7 6 + (8 + (7 + 5 * 8 * 5) + 5 * 6 + (8 * 6) + 6) * 3 7 + 3 * 4 * 6 + 9 8 + 8 + ((8 * 9 + 6 + 3 * 9) + 3 + 4 * 8) 9 + 4 + 6 + 3 + 2 + (2 * 6 + 8 + 3) (5 * 2) + 4 + 7 * 9 + (5 + 5 + 3 * 5) 5 * 5 * 2 * 5 + (9 + 7 + 5) (2 * 5) + 7 5 + 7 * 9 + 3 * 5 (8 * 7 + 9 * 5) + 3 * (6 * 5 + (2 * 7 * 2 * 7 + 7 * 2) + 4) + 3 (6 + 6 + 6 + 9) + 9 + (3 * 5 + 4 + (6 * 3) * 4) * 3 + (8 + 7 * 5 * (3 * 3) + 6) * 3 ((2 * 8 * 3 + 2 * 6 * 5) * 5 + (7 * 3 + 5 + 6 * 9 * 4) * (5 * 6 + 8 + 4 * 7 * 5)) + 6 + (9 * (9 + 7 * 8 * 3) + 7 * (5 * 9 + 6 + 5 + 4 + 8) * 8 + 8) * 5 2 * (5 + 2 * 2 * 3 + (4 + 3)) * (6 + 6 + 2 * 9 + 9 * 3) * 8 * 8 9 * (9 + 3 + 8 + 5) * (2 * 5 * (6 + 8) * 9) * (4 + 3 * 8 * 9 * 4 + 4) * (3 * 9 * 8 + (6 * 6 + 9 + 5) + 2 * (8 + 2 * 7)) 2 * 5 * 9 * 8 * ((7 * 2 * 3) + 3) 2 * (6 * 7 * 2 * 4 + (5 * 4 + 7 + 3 + 7) + 5) * (7 + (6 + 3) * (8 + 8) * 3 * (5 + 2)) * 3 * 8 * 7 2 * 5 * (4 * 9 + 2 + 5 * 2) + 6 * 5 + (6 * 6 * 4 * 8 * 4) 4 + 8 * 4 + 4 * 3 + (7 + 2 * 2 * 5 * 2 + 8) (8 * (4 + 5 + 9 * 9 + 8) * 4 + (8 + 7 + 9 * 4 * 4 + 3)) * 7 * 8 * 3 8 * 9 + ((2 + 5 + 8 * 9 + 5) + 2) * 7 * 4 + 5 3 + (5 * 8 * 6 * (7 + 4 * 2 + 2 * 4 * 2) + (9 + 6) * 9) + 4 9 * 7 + 4 + (7 + 9 + (9 * 9 + 8 * 4 * 5 * 8) + 5) + 3 2 * 2 + 6 + (3 * 9 + 6 + (4 * 4 * 6 + 2 * 5)) * 5 6 * 3 * (3 + 8 * 7) + 9 7 * 2 * 6 * (3 * 3 * 8 * (2 + 7 * 9 + 8)) 9 * 7 + 6 * (7 * (3 + 6 + 7) + 3) + (9 * 6 + (2 + 9 * 3) + (7 * 8 * 8 + 6 * 3 * 5) * 9) 3 * 4 * 4 * 6 + 2 + (6 * 3) 4 * (5 + 7) + 8 5 * 3 * 9 + 9 + 9 * 2 8 + (8 * 9) * 7 + 6 * 9 9 + 9 * (3 * 8) * 3 + 2 6 + (8 + 6 + 2) * (9 * 9 * 8) 5 + 4 * 3 + (2 * 2 * (2 + 3 + 4 + 7 * 3) + 5 + 3) + 6 9 * 2 + 3 * 8 * 9 5 * 2 * 7 * ((5 + 6 * 4 + 6 + 3 + 5) * 7 + 9 + 4) * (7 + 3 * 7) 2 + ((5 + 3 * 4 + 2) * 2 * 6 + (8 * 8 + 8) * 3 * (3 * 8 * 5 * 6 + 5)) 5 + (6 + 9 + 4 + (3 * 7)) * (4 + 6 * 5 * (7 + 8 * 3 + 3 * 9) + (9 + 8 + 3)) 4 * 2 + 9 + (9 * 6 * 9 * (9 * 4 + 3 * 2 * 6 + 8) + 7 + 9) * (5 + 7 * 9 * 5) + (8 + 9 + 4 * 5 * 8) 7 + 8 * 3 + (5 + 2 * 2 + 6 * 8) + 7 8 + ((9 * 7 + 5 * 8 + 3 + 6) * 4) + 6 * 4 + 4 + 3 (6 + 2 + 4 + 7) * (2 + 6 * 7 * (4 * 3 + 9 + 5 * 5) + 5 + (2 + 3 * 5 * 5 * 6)) * 2 (6 + 9) + 4 * 9 4 * (4 * 5 + 9 * (9 + 5 * 7 * 6 * 7 + 9)) 2 * 5 + ((7 + 3 * 3 * 9 + 8 + 4) * 4 * 6) + 3 + 6 + (4 + (2 * 7) + 5) (7 + (4 * 5 + 2 + 2 * 2 + 8)) * 5 + 5 + (3 + 8 + 6 * 6) * 9 5 + 4 + 4 + 7 * (2 + 6 + (3 + 6 + 7) + 6 * 9) * (2 + 8) 8 + ((4 * 3 * 2) + 4) + 5 * 7 * 3 * 5 4 * 4 + 9 + (8 + (6 * 5 * 2 + 8 * 3 + 8) + 4 * (2 + 6 * 2 + 4 + 3 + 2) * (4 + 5)) (9 + 8 * 8 + (5 * 8 * 7 * 8 + 9 * 6)) * 9 + 5 * 2 7 + 8 * (2 + (5 + 7 + 3 + 9 * 8 + 8) * (2 * 9 * 7) + 3 + 4) * 8 + 5 + 2 5 + 2 * (5 * 7 * 6 * 4 * 2 + (7 + 2 + 7 + 9 + 4)) 6 * 8 * 7 * 8 * 9 + 9 5 + 8 + 7 * 5 * (8 * 8 * 5 + 7 + 9) + 6 9 + 2 * 3 * 5 8 * 5 + (2 + (4 + 9 + 5 * 6 + 8) + 9 * (4 + 4 * 5 * 3) * (5 * 7 * 8 + 3 * 3 + 3) + 5) 7 + 3 + (2 * 2 + 5 * 8 + 3) + (8 + 3 + (6 * 5 + 4 * 5)) 6 * ((2 * 6 + 6 * 2 + 5 + 4) * 8 + 8 * 9) * (5 * 2 + 4 + 6 * 3) + ((6 + 8 + 8 + 6 + 7 * 6) + 8 * 9 * 2 * 2 * (8 + 3 + 7 * 5 * 3)) * ((5 + 9) * 4) + 4 (3 * 8 * 5) + 8 + (3 + 7 + 2 * 3 * 8) * 5 7 + 3 * 9 + (2 * (2 + 9 + 9 + 8 + 9) * (8 * 6)) * 4 * 9 7 + 9 + (3 + 7 + 2 + 6) 4 * (6 + (3 + 6 + 3) * (9 * 7 * 4 + 3 + 4) + 8 * 7 + 4) ((9 + 6) * 3 + 2 * 5) + (6 * 5 + 4 + 3) 3 + (4 * (2 + 4 + 4 + 2)) * 4 * 7 + 5 + 5 (5 * 9 * 2 * (7 * 9 * 8) + 2) + 6 + 2 + 8 + 9 5 + 4 * 4 + (2 * 3 + 8 + 8) * 6 * (9 * 8 + (8 * 9 * 5) + 9) 3 * 5 * (8 + 3 + 7) + 4 + 6 6 + 7 * (9 + (2 + 7 + 2 * 2)) * 3 (9 * (4 * 3)) + 9 * 4 + (9 * 5 + 5 * (6 * 2 + 8 * 8) + 2) + 9 + 8 6 * 7 + 7 7 + (9 * 6 * 8 + 9 * 2) * 4 * (9 * 4 * 6 + (8 * 5 * 8)) * 7 8 + 5 + ((8 + 2 * 6) + (9 * 3 * 8)) + 7 4 * 8 * (6 + (4 + 5) + 5 * 3) (3 * 2 + 6) + 3 + 3 + 8 * 6 * 7 9 * 3 * 3 + (4 * (6 + 3) * 4) + 2 * 9 5 + 9 + 7 + 4 * (9 * 3) ((8 * 9) + (7 + 5 + 6) + 3 * (5 + 7 + 6)) + 5 + (3 * 8 * 3) * 2 9 + 6 * 5 * ((4 * 4) + 7 * 3) + (3 * 6) 7 + (8 + 7) + 4 * (3 + 3) * 7 * 9 ((6 + 7 + 4 + 7) * 7 + 9 + (9 * 7 + 5 + 7 + 7) + 9 + (7 + 3 + 2 * 6 + 9)) + 2 + (4 * 7 + 9 * 3 * 2 * (5 + 9 + 3)) * 5 9 * (3 + (9 * 9)) + 9 * 8 + 4 * 2 (8 * 8 + 6 + 9 + 8 + 2) + 6 * 5 + 5 * 4 3 + 3 + 4 * (6 * 6) + 2 * 8 (5 * 9) * (8 * (2 + 6 * 9) * 7 + 7) 8 * 5 + (8 + 8 + 8 * 4) + 3 * 8 * (8 + 6 * 3 + 4) 4 * 9 + (5 * (8 * 3) + 4) * 5 + (3 * 3) (2 + 2 * 4 * 3) + 8 * ((2 * 6 + 5 + 6 * 2) * 3) + 2 ((5 * 4 + 2 + 7 * 6) + (7 * 5 + 4) + 9 + 7 + 7) + 3 2 + 3 + 9 * 9 + (9 * (2 + 8 + 7) * 3) 3 * 7 (4 + 2 * 5) + 2 5 * 5 * (5 + (8 + 8 + 8) + 3 * 2 * 4) * 9 * 2 + 8 4 + 5 * 3 * 5 + (4 + (3 + 8 + 4) + 7) + 7 (4 + 7 + 6 + 2 * 7) + 7 4 * 2 * 4 (4 * 4 + (6 * 6 * 7 * 2) * 4 * 6 * 7) * ((9 + 5 + 9) + 8) * (5 + 8 + 2 + (9 + 8 * 2 + 9 * 8) * 8 + 3) * 6 5 + 8 * 9 + ((7 * 9 * 3 * 7) * 2 + (2 + 2 + 3 * 6 + 6) + 5 + 4) 3 * 8 + 2 + (7 + 8 + (8 + 7 + 7 * 6 + 2) + (3 + 2) + 5) 4 + 4 * 6 * 5 4 * 9 * ((9 + 2) + 4 + 2 * 5) * ((6 * 9 * 5 + 8) * (7 + 7)) * (8 * 7 + 9 + 7 * (2 + 9 + 9 + 4 + 8) + 9) * 6 (8 * (2 + 3 + 7 * 3 + 2) * 2 * 4 + 7) + 4 + 3 * 2 (6 + (2 * 5 + 3 * 2 * 4 * 7)) * 6 + 4 + 6 + 9 + 9 (8 + 8 * 6 * (4 + 3 + 4 + 8 * 2 * 4) + 7) + 2 8 + 9 8 + 8 * 4 + 4 * ((9 * 2) + 2) (3 + 3 + 9 * 9 + 5 * 2) + 5 + 7 2 + (7 * 5 * 2) 8 + (5 + 3 + 8 * (3 + 2) * 6) + 9 * 9 * 8 * 9 8 + (2 * 5 + (9 * 7 * 4 * 2) * (7 * 4) * 4 * 6) * 9 + 3 4 * 7 + 4 * 4 * (2 + (2 * 8 + 2 * 5 + 2) * 7) 8 * 5 + 8 + (6 * 9 * 8 * 2 + 5 + (4 * 5 + 4 + 3 + 3)) + 4 9 + 9 * 2 * 9 + (5 + 2 + 6 + 3 * (5 * 2 + 8 * 9 + 6 + 7)) 4 * 9 + 2 4 + 4 * (3 + (4 + 9 * 8 * 7 * 3 * 3) * 2 + 9) + (2 * 7) + 8 ((5 + 8 + 5 * 2 * 5 * 3) * 5 * 6 + 2) + (5 * 9 * 6 + 2 * (4 + 8 + 9 * 9 * 8 * 3) * 2) + (8 * 6 + 2) 3 + 7 + (9 * (2 * 6 + 3) + 4) * (3 + 4 * 8) ((2 * 2 + 5 * 6 + 7 * 2) * 5 + 9 + 6) * 5 (8 * 6 * (3 + 8) + 9 + 7 * 5) * 3 * 2 * 3 * 5 * 5 ((2 + 9 * 4 + 8) * (5 + 5 + 6) * 6 + 9 * 8 + (6 + 9)) * (9 + 8) * 6 * 6 + 9 + 7 (6 * 5 * 6 * 5 * 3) * 6 * 9 * 9 (5 * 4 * (5 * 3 * 3) * (5 + 6 + 2 + 2 * 9 * 3)) + (3 + 6 * 3 * 3 + 3 * (8 * 5 + 3)) * (9 + 3 * 9) + (7 + 4 + 3 * 8 * 8) (4 + (9 + 2 * 3 + 9 + 6) + 2) + 2 * 7 * 5 9 + 8 + (3 + (7 * 7 + 2 * 8 + 6 * 2) * 8 * 6 * (9 + 7 + 4)) (7 + 3) * 7 * (4 + 4 * (2 + 3 + 4 + 6) + 7) + 6 + 2 (8 * (5 * 9 * 6) * 3 * (7 * 5)) + 5 + 3 (2 * 6 + (7 + 5) * 7 + 3) * 5 + 3 * 2 ((9 + 4) * 6 * 2 * 3 + 6) * ((2 + 6 + 4 * 7 + 4 * 7) * (7 + 9 + 2) * 2) + 7 * 2 3 * (9 + 9 + 5 + (9 + 7 * 7 + 8 + 2 + 6) + (9 * 8 + 8 * 8 * 7) * 3) + (7 + 9 * 4 + (6 + 4) + 2) + 9 9 + (2 * 5 + 9) + 9 + 7 3 * 9 + ((2 + 4 * 4) * 3 + 5 * 3 * 5 + (4 + 8 * 3 * 4)) + 6 * 5 3 + (7 * 2 + (4 + 6 * 6)) * 2 + (4 * 5 + 2 + 6 + (7 * 6 + 6 + 7)) * 6 + 9 6 + 5 * (3 + 5 + 2 + (9 + 6 * 3) + 3 + 7) * 3 4 * ((4 + 4 * 8 + 7 + 2 + 4) * (4 + 4 + 8 * 4 + 4 + 3) + 9 * (6 * 4 * 9 * 9) * 2 * (6 + 6 * 9 * 3 + 4)) + 7 9 + 8 7 + (9 + (5 * 6 * 5 * 3 * 3)) 7 * 9 + 4 + 6 + ((9 * 2 + 9) * 7 * 9) + 6 ((8 + 7 * 8 * 6 * 9 + 2) + 4 + 6 * 9 * (5 * 6 * 9 * 8) * 7) * 5 + 5 2 + 2 * (4 + 3 + 6 + 4 + 5) * (7 * 5 * 5 * 6 + 4 + (6 * 8 * 4 + 7)) (3 + (9 + 2 * 3)) + 2 * 7 (5 + 8 * 5 * (9 * 6 + 4 * 6 + 5)) + 5 * ((3 * 9 + 7) + 9 + (2 * 6 * 4 * 3 + 4 * 4) + 7 + (5 * 4 * 9 + 9 * 7) * 5) ((7 + 2 * 5 * 3) + 4) * 8 6 * (3 + 7 * (2 + 6) + 6 + (9 * 8 * 7) * (5 * 4 + 7 + 8 * 8)) + 6 * 6 (6 + 9 * (2 + 2 * 2 * 3 * 7 + 8) * 3 * 5 * 4) + 2 5 + 2 + (9 + 4 * 7 + 3 + 8) * (4 + 8 * (3 + 2 * 7 * 4)) + 8 + (4 + 5) (8 * 9 + 9 + 4 * 5) + 2 * 2 * 9 + (3 + 9) + 5 4 * 7 + ((5 + 7) * 3) * 9 * 9 6 + 6 * 4 * ((8 + 9 * 7 * 3 + 9 * 8) + 4) * 3 * 4 4 * (6 * (9 * 9 + 4 * 2 * 3) * 2) + 8 * 5 * 3 7 + 4 * (8 * 2 * 2 * 3 * 8 * 8) * 7 + 2 + 5 8 * ((2 * 3 * 5 * 9 * 2 + 6) * 4 * (7 + 3 * 4 + 7 * 5 + 5) * 3) * 7 + ((9 + 8 + 5) * 8 * (5 * 8 * 9 + 3 + 9) * 5) 5 * (7 + 2 + 9) + 9 * (5 + 8) + 3 * 6 6 * ((9 * 5 + 7) * (8 + 9 + 9 * 7 + 3 + 4)) ((7 + 2 * 6 * 5) * 7 + 2) * 8 * 7 9 + ((7 + 8 * 9 * 4 * 4 + 6) + 8) * (9 + (7 + 2 + 6 * 3)) (3 + 6 * (6 * 9 * 4)) + 6 + 5 * 9 + (4 * 6 * 8) * ((7 + 2 * 9 * 4 + 4) + 9 + (6 + 2) + 5) 2 + 4 + 6 + 2 * ((8 * 3 * 2 + 7 * 6 + 3) + 4 + 5 + 5 * 5) 6 + ((6 * 5 * 3 + 9) + (7 + 7 * 8 + 9 * 7 + 6)) (9 + 3 * 3 + (6 * 4 * 2 * 9 + 7 + 4) * 2) * 9 * 2 4 * ((8 + 4) * 2) * (7 + 6 + 3) 9 * 2 + (9 + (7 * 4) * 9 + 8 + (4 + 4) + 7) + (6 * 6 * 3 * 3) * ((9 * 4) * 5 * (6 + 3 + 8) + 5 * 7) + 2 5 + ((9 + 3 + 4 + 2) + (5 + 3) + (4 * 2)) * 7 (8 * 7) + 9 + 6 + 7 * 9 * ((5 + 8 + 5 * 5 + 7 + 2) * 2 + 6) (9 * 3 * 6) * 4 + 5 * 4 * 3 5 * ((7 + 4 * 5 + 8) + 2) * 9 + 3 2 * 2 + ((2 * 2) * (7 * 5 * 6 + 9)) * 2 4 + ((5 * 5 + 2 + 2) * 3 * 6 + (4 * 3 * 3 + 4 + 7)) * 3 + 3 + (4 + (6 + 9) + 4 + 6 * (2 * 3) * (5 + 8 * 2 * 8)) + 9 2 * 9 + 5 2 + ((6 + 7 + 9) * 9 + 9) + 9 * 5 2 + 7 * (9 * 7 + (6 + 5 + 2)) + 8 + 5 3 * (7 * 4 + 8 * 8 * 6 * 8) + 5 + 2 8 + (5 * 2 * 3 + 5 + 8 * 3) * 3 * (9 * (2 + 8) * (7 + 3 + 5 + 4 * 9) * 6 + 5 + (8 + 9)) + 4 + 3 4 + 7 * ((8 * 5 * 2) + 3) + 2 4 + 6 (5 * (7 * 6 + 3 + 4) + 9 + (8 + 9) + (5 * 6) * 4) * 8 6 + ((7 + 5 + 7 * 3 + 8 + 3) * 5 * 2 * 4 + 5 + 4) 5 + 4 + ((6 + 6 + 5 + 7 * 8) * (2 + 4 * 3 * 8 + 3) + (4 + 3) + 2) + 9 7 * 3 + 6 + 6 * 4 * 6 (4 * 9 + 2 + 4 + 9) * 6 + 6 * (4 * 9 * (6 * 9 * 3 * 6 * 2 * 7) + 5 + 3 * 3) + 3 * 8 (5 + (4 * 8) + (5 * 5)) + (2 + 5 * 8) 9 + 3 * 3 * 8 + (3 + 4 * 2 + (6 * 7 * 2 + 4 + 6 * 9) * 4) * 3 3 * 6 + 2 + (8 * 6 * 6 + 8 + 8) * ((7 + 3 * 4 * 5) * 4 + 9 * (7 + 4 + 5 * 9 + 8 + 3) * (7 * 8 * 5 + 5 + 7 + 6)) + 4 6 + 4 + (5 + 7 * 6) 5 + 3 * 8 + 6 + 3 6 + 2 + 9 + 8 + (7 + (8 + 2 * 8 + 3 + 8) * 8) * (8 * 8 * (7 + 9 * 2 + 7 * 4) * 4 + (7 + 6 + 7 * 4 + 5)) 3 + 8 + 4 + (8 + 7) * ((7 + 5) + 8 + 4 + (9 * 7 * 8 * 6) + (7 + 6 + 8 * 3)) + 5 4 + 2 + 6 * (8 + 2 * 2 * 7) * 2 * 8 2 + 6 * 4 + 6 + (8 + 4 + 6 * 8 + (6 + 4 * 9 * 8 * 3 + 6) * (3 * 5 * 2 + 2 + 7 * 2)) * 3 6 + 6 * 4 + ((9 * 8 * 5) * 4 * 9 * (2 + 9 * 4 + 8 * 8) * 7) 3 * 3 + (2 + 9 * 6 + 3) * ((3 + 2 * 2 + 8 * 8 * 3) + 8 * 9) * 4 + 9 (2 * 7 + 2 * 2) * 8 + 6 5 + (3 + 9 + 3 + 9 * 4 + 6) + 3 * 7 * 5 * 5 ((9 + 7 * 4 * 5 + 6 * 8) + 5 * 3 * (2 * 7 + 3 + 5 * 4 + 9)) * 5 * 8 7 + 2 + (5 + (8 + 2 * 2 * 9 + 6) * 4 + 2 * 5) * 3 + 5 7 + (8 + 6 * (9 + 6 * 3 * 9 * 8 + 7)) 7 + 2 + 7 * (9 + 4 + 3 * 3 + 9) 7 + ((5 + 7 * 4 * 3) + 4 * (9 * 5 + 2 * 5 * 6 + 2)) * 3 * ((3 + 3 + 4 + 8) * (4 * 5 * 7 * 4 + 9) + 8 + 3) * 7 (3 * 9 * 8 + 8 + (5 * 3 + 6 * 3 + 2) + (8 + 9 + 3)) * 5 * 4 * 4 * 3 9 * 6 + (9 * 6 + 3 * (7 * 4 * 2 + 9) + 3) (3 + 6 * (6 * 5 * 8 * 9) + (7 + 5 * 5 + 5 + 8 * 8)) * 6 + (9 + 8 + 7 * 5 + (8 + 3 * 4 + 8 * 9) * 7) * 8 + 6 (9 * 7 + (4 * 8 + 9 + 6) * 3 * 7 * (9 * 7)) + (5 * 9 * (3 * 4 * 7 + 6) * (8 * 9 + 5 + 2 + 9)) 5 * (8 * 3) + 9 * ((8 * 3 * 4) * (6 * 2) * 3 + 6 * 6 * 8) * ((2 * 3 * 6 + 4 * 2 + 5) * 8 * 6 * 2) 3 + (4 * (6 + 5 * 3 + 9 + 3) * 2 * (8 + 7 * 8 * 7 + 5) * (8 + 8)) + (8 * 5 + 8 + 6 * 9 * 4) + 8 * 4 + 3 (3 * 6 * 7 * (3 + 7 * 4) * 8 * 8) * 5 + 6 * 6 + (4 * (9 + 5 * 8 * 9 * 6 * 6) * 3) + ((7 * 8 * 6 + 2 + 5 * 6) * 2 + 3 + 5 * (3 * 8) + 6) (2 + 4 * 9) + (7 + 2 + 7 * 7 * (3 + 8 * 4 + 2) * (7 + 5)) * 9 * 7 4 + (8 + 2 + 5 + 2 + 9 + 4) + 7 + 6 * 4 3 * 8 + (8 + 5) * (7 + 5 + 6) 5 + (5 + (7 + 5)) * 8 * 6 * ((9 + 3 * 2 * 5 + 2 + 9) * 2 + 5 + 3 * 6) * ((2 + 2 * 9) * 6 * 8 * 7 * (4 * 5) * 6) 7 + 3 * 6 + ((5 + 2 + 6 + 5 + 5 * 4) * 4 * 9) 5 * 4 + 8 * 3 (8 + 6 * 6 + 5) + 9 + (6 + 3) + 7 + 6 ================================================ FILE: exm/aoc/2020/aoc_2020_18_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 18 ------------------------------------------- -- Operation Order -- -- https://adventofcode.com/2020/day/18 -- with Ada.Text_IO, Interfaces; with AoC_2020_18_Weird_Formulas; -- Variant of MathPaqs' Formulas. procedure AoC_2020_18_full_Ada is use Ada.Text_IO, Interfaces; -- Set `*` as a fake `-`, in parsing and in evaluation. package WF_1 is new AoC_2020_18_Weird_Formulas (Long_Float, Plus => "+", Minus => "*", Times => "*", plus_char => '+', minus_char => '*', times_char => '_' ); -- Swap `+` and `*`, in parsing and in evaluation. package WF_2 is new AoC_2020_18_Weird_Formulas (Long_Float, Plus => "*", Minus => "-", Times => "+", plus_char => '*', minus_char => '-', times_char => '+' ); -- sum : Integer_64; f : File_Type; begin for part in 1 .. 2 loop Open (f, In_File, "aoc_2020_18.txt"); sum := 0; while not End_Of_File (f) loop sum := sum + Integer_64 ( (if part = 1 then WF_1.Evaluate (WF_1.Parse (Get_Line (f))) else WF_2.Evaluate (WF_2.Parse (Get_Line (f))))); end loop; Close (f); Put_Line ("Part" & part'Image & ": sum is" & sum'Image); -- Validated by AoC: 14006719520523 -- Validated by AoC: 545115449981968 end loop; end AoC_2020_18_full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_18_weird_formulas.adb ================================================ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Exceptions; use Ada.Exceptions; with Ada.Numerics.Generic_Elementary_Functions; with Ada.Strings.Fixed; use Ada.Strings.Fixed, Ada.Strings; with Ada.Unchecked_Deallocation; package body AoC_2020_18_Weird_Formulas is package REF is new Ada.Numerics.Generic_Elementary_Functions (Real); package RIO is new Ada.Text_IO.Float_IO (Real); subtype Leaf is S_Form range nb .. var; subtype Neutral is Unary range plus_una .. accol; subtype Built_in_function is S_Form range abso .. max; subtype Binary_operator is Binary range moins .. puiss; type S_Form_Set is array (S_Form) of Boolean; par_or_terminal : constant S_Form_Set := (par | croch | accol | nb | var => True, others => False); symmetric : constant S_Form_Set := (min | max | plus | fois => True, others => False); function Conv_strg (s : S_Form) return String is begin case s is when plus_una => return "+"; when moins_una => return "-"; when abso => return "Abs"; when sign => return "Sign"; when step => return "Step"; when round => return "Round"; when trunc => return "Trunc"; when floor => return "Floor"; when ceiling => return "Ceiling"; when expn => return "Exp"; when logn => return "Log"; when sqrt => return "Sqrt"; when sinus => return "Sin"; when arcsin => return "Arcsin"; when cosinus => return "Cos"; when arccos => return "Arccos"; when tg => return "Tan"; when arctg => return "Arctan"; when sh => return "Sinh"; when arcsinh => return "Arcsinh"; when ch => return "Cosh"; when arccosh => return "Arccosh"; when th => return "Tanh"; when arctanh => return "Arctanh"; when min => return "Min"; when max => return "Max"; when par => return "("; when croch => return "["; when accol => return "{"; when fois => return "*"; when plus => return "+"; when moins => return "-"; when sur => return "/"; when puiss => return "^"; when Leaf => return ""; end case; end Conv_strg; function conv_symb_una (c : Character) return S_Form is begin if c = plus_char then return plus_una; elsif c = minus_char then return moins_una; else return nb; end if; end conv_symb_una; function conv_symb (c : Character) return S_Form is begin return ( if c = plus_char then plus elsif c = minus_char then moins elsif c = times_char then fois elsif c = '/' then sur elsif c = '^' then puiss elsif c = '(' then par elsif c = '[' then croch elsif c = '{' then accol else nb); end conv_symb; function Conv_mstr (s : S_Form) return String is begin return To_Upper (Conv_strg (s)); end Conv_mstr; procedure Put (f : Formula; style : Output_style := normal) is begin Put (Ada.Text_IO.Current_Output, f, style); end Put; procedure Put (t : in Ada.Text_IO.File_Type; f : Formula; style : Output_style := normal) is begin Ada.Text_IO.Put (t, Image (f, style)); end Put; function Almost_zero (x : Real) return Boolean is begin return abs x <= Real'Base'Model_Small; end Almost_zero; function Image (f : p_Formula_Rec; style : Output_style) return String; function Image_simple (f : p_Formula_Rec; style : Output_style) return String is x : Real; use Ada.Text_IO, RIO; s : String (1 .. 40); begin if f = null then return ""; end if; case f.s is when nb => x := f.n; if Almost_zero (x - Real'Floor (x)) and then abs x < Real (Long_Integer'Last) then return Trim (Long_Integer'Image (Long_Integer (x)), Left); else begin Put (s, x, 5, 0); exception when Layout_Error => Put (s, x); end; return Trim (s, Left); end if; when pi => return "pi"; when var => return To_String (f.v); when moins_una => return minus_char & Image (f.left, style); when plus_una => return plus_char & Image (f.left, style); when Binary_operator => return Image (f.left, style) & Conv_strg (f.s) & Image (f.right, style); when Built_in_function => if f.s in Binary then return Conv_strg (f.s) & '(' & Image (f.left, style) & ',' & Image (f.right, style) & ')'; else return Conv_strg (f.s) & '(' & Image (f.left, style) & ')'; end if; when par => return '(' & Image (f.left, style) & ')'; when croch => return '[' & Image (f.left, style) & ']'; when accol => return '{' & Image (f.left, style) & '}'; end case; end Image_simple; function Image (f : p_Formula_Rec; style : Output_style) return String is begin if f = null then return ""; end if; if style = bracketed and then f.s not in Leaf then return '{' & Image_simple (f, style) & '}'; else return Image_simple (f, style); end if; end Image; function Image (f : Formula; style : Output_style := normal) return String is begin return Image (f.root, style); end Image; function Deep_copy (f : p_Formula_Rec) return p_Formula_Rec is g : p_Formula_Rec; begin if f = null then return null; end if; g := new Formula_Rec (f.s); case f.s is when nb => g.n := f.n; when pi => null; when var => g.v := f.v; when Unary => g.left := Deep_copy (f.left); when Binary => g.left := Deep_copy (f.left); g.right := Deep_copy (f.right); end case; return g; end Deep_copy; procedure Dispose is new Ada.Unchecked_Deallocation (Formula_Rec, p_Formula_Rec); procedure Deep_delete (f : in out p_Formula_Rec) is begin if f /= null then case f.s is when Unary => Deep_delete (f.left); when Binary => Deep_delete (f.left); Deep_delete (f.right); when others => null; end case; Dispose (f); f := null; end if; end Deep_delete; Closing : constant array (Character) of Character := ('(' => ')', '[' => ']', '{' => '}', others => 'X'); c_fin : constant Character := Character'Val (0); procedure Check (expected, found : Character) is begin if expected = found then return; end if; if found = c_fin then Raise_Exception ( Parse_Error'Identity, "End of formula reached, '" & expected & "' is missing"); else Raise_Exception ( Parse_Error'Identity, "'" & expected & "' was expected, found '" & found & '''); end if; end Check; procedure Check_brackets (open, close : Character) is begin Check (expected => Closing (open), found => close); end Check_brackets; function No_Spaces (s : String) return String is t : String (s'Range); j : Integer := s'First - 1; begin for i in s'Range loop case s (i) is when ' ' | ASCII.HT | ASCII.CR | ASCII.LF => null; when others => j := j + 1; t (j) := s (i); end case; end loop; return t (t'First .. j); end No_Spaces; digit : constant Character_Set := ('0' .. '9' | '.' => True, others => False); expo : constant Character_Set := ('e' | 'E' => True, others => False); digit_or_expo : constant Character_Set := digit or expo; first_symbol_after_expo : constant Character_Set := ('0' .. '9' | '+' | '-' => True, others => False); procedure Parse (f : out Formula; s : String) is str : constant String := No_Spaces (s) & c_fin; i : Integer; -- function Expression return p_Formula_Rec is -- function Term return p_Formula_Rec is -- function Factor return p_Formula_Rec is -- function Number return p_Formula_Rec is n : constant p_Formula_Rec := new Formula_Rec (nb); j : constant Integer := i; begin while digit_or_expo (str (i)) or else (expo (str (i - 1)) and then first_symbol_after_expo (str (i))) loop i := i + 1; end loop; n.n := Real'Value (str (j .. i - 1)); return n; end Number; function Variable_or_function return p_Formula_Rec is n : p_Formula_Rec; j : constant Integer := i; begin loop i := i + 1; exit when not following_character (str (i)); end loop; declare chj : constant String := str (j .. i - 1); mch : constant String := To_Upper (chj); begin if str (i) = '(' then for s in Built_in_function loop if mch = Conv_mstr (s) then -- Found a built-in function n := new Formula_Rec (s); exit; end if; end loop; i := i + 1; if n = null then Raise_Exception (Parse_Error'Identity, "User functions not yet supported"); else n.left := Expression; if n.s in Binary then -- Function with two arguments: read 2nd argument Check (',', str (i)); i := i + 1; n.right := Expression; end if; Check_brackets ('(', str (i)); i := i + 1; end if; elsif mch = "PI" then n := new Formula_Rec (pi); else n := new Formula_Rec (var); n.v := To_Unbounded_String (chj); end if; end; return n; end Variable_or_function; -- Factor n, n1 : p_Formula_Rec; c : Character := str (i); begin n := null; if digit (c) then n := Number; elsif letters (c) then n := Variable_or_function; elsif c = minus_char or c = plus_char then n := new Formula_Rec (conv_symb_una (c)); i := i + 1; n.left := Factor; end if; c := str (i); case c is when '^' => -- NB: right-associative in this parser. -- x^y^z means x^(y^z) like in R and unlike -- in Excel where x^y^z means (x^y)^z. -- Ada asks for parenthesization. n1 := n; n := new Formula_Rec (puiss); i := i + 1; n.left := n1; n.right := Factor; when '(' | '[' | '{' => if n = null then n := new Formula_Rec (conv_symb (c)); i := i + 1; n.left := Expression; Check_brackets (c, str (i)); i := i + 1; end if; when others => null; -- [P2Ada]: no otherwise / else in Pascal end case; if n = null then Raise_Exception (Parse_Error'Identity, "Unexpected end in factor"); end if; return n; end Factor; -- Term n, left_factor : p_Formula_Rec; c : Character; begin left_factor := Factor; c := str (i); if c = times_char or c = '/' then i := i + 1; n := new Formula_Rec (conv_symb (c)); n.left := left_factor; n.right := Term; return n; else return left_factor; end if; end Term; -- Expression n, left_term : p_Formula_Rec; c : Character; begin left_term := Term; c := str (i); if c = plus_char or c = minus_char then i := i + 1; n := new Formula_Rec (conv_symb (c)); n.left := left_term; n.right := Expression; return n; else return left_term; end if; end Expression; generic oper : S_Form; -- - or / : these operators are left-associative only ! ivrs : S_Form; -- + or * procedure Left_Assoc (n : in out p_Formula_Rec); procedure Left_Assoc (n : in out p_Formula_Rec) is left_part : p_Formula_Rec; begin if n = null then -- Should not happen, but who knows... return; end if; -- -- Recursion -- case n.s is when Leaf => null; when Unary => Left_Assoc (n.left); when Binary => Left_Assoc (n.left); Left_Assoc (n.right); end case; if n.s = oper then if n.right /= null and then (n.right.s = oper or n.right.s = ivrs) then -- This has been parsed as X - {Y + Z} or X - {Y - Z}, -- should be {X - Y} + Z or {X - Y} - Z. left_part := n.right.left; -- Remember Y n.right.left := n; n := n.right; n.left.right := left_part; -- -- Redo on children. See 9-4-3-2 example... -- Left_Assoc (n.left); Left_Assoc (n.right); end if; end if; end Left_Assoc; procedure Left_Assoc_Plus is new Left_Assoc (plus, moins); -- !!! procedure Left_Assoc_Minus is new Left_Assoc (moins, plus); procedure Left_Assoc_Divide is new Left_Assoc (sur, fois); begin i := 1; Deep_delete (f.root); f.root := Expression; Left_Assoc_Plus (f.root); Left_Assoc_Minus (f.root); Left_Assoc_Divide (f.root); if str (i) /= c_fin then Deep_delete (f.root); Raise_Exception (Parse_Error'Identity, "Unexpected end in formula (extra symbols)"); end if; exception when E : Parse_Error => Deep_delete (f.root); Raise_Exception (Parse_Error'Identity, Exception_Message (E)); end Parse; function Parse (s : String) return Formula is f : Formula; begin Parse (f, s); return f; end Parse; procedure Parse (f : out Formula; u : Unbounded_String) is begin Parse (f, To_String (u)); end Parse; function Parse (u : Unbounded_String) return Formula is f : Formula; begin Parse (f, u); return f; end Parse; ---------------------------------- Evaluate --------------------------------- function Sign (x : Real) return Real is begin if x < 0.0 then return -1.0; elsif x > 0.0 then return +1.0; else return 0.0; end if; end Sign; function Step (x : Real) return Real is begin if x < 0.0 then return 0.0; else return 1.0; end if; end Step; function Evaluate (f : p_Formula_Rec) return Real is aux : Real; use REF; begin if f = null then return 0.0; end if; case f.s is when nb => return f.n; when pi => return Ada.Numerics.Pi; when var => return 0.0; -- Hacked. when moins_una => return -Evaluate (f.left); when plus_una | par | croch | accol => return Evaluate (f.left); when plus => return Plus (Evaluate (f.left), Evaluate (f.right)); when moins => return Minus (Evaluate (f.left), Evaluate (f.right)); when fois => return Times (Evaluate (f.left), Evaluate (f.right)); when sur => aux := Evaluate (f.right); if Almost_zero (aux) then raise Div_By_0; elsif Almost_zero (aux - 1.0) then -- X/1 -> X return Evaluate (f.left); else return Evaluate (f.left) / aux; end if; when puiss => aux := Evaluate (f.right); if Almost_zero (aux - Real'Floor (aux)) then return Evaluate (f.left) ** Integer (aux); -- Negative arguments are possible in this case else return Evaluate (f.left) ** aux; end if; when abso => return abs Evaluate (f.left); when sign => return Sign (Evaluate (f.left)); when step => return Step (Evaluate (f.left)); when round => return Real'Rounding (Evaluate (f.left)); when trunc => return Real'Truncation (Evaluate (f.left)); when floor => return Real'Floor (Evaluate (f.left)); when ceiling => return Real'Ceiling (Evaluate (f.left)); when logn => return Log (Evaluate (f.left)); when expn => return Exp (Evaluate (f.left)); when sqrt => return Sqrt (Evaluate (f.left)); when sinus => return Sin (Evaluate (f.left)); when arcsin => return Arcsin (Evaluate (f.left)); when cosinus => return Cos (Evaluate (f.left)); when arccos => return Arccos (Evaluate (f.left)); when tg => return Tan (Evaluate (f.left)); when arctg => return Arctan (Evaluate (f.left)); when sh => return Sinh (Evaluate (f.left)); when arcsinh => return Arcsinh (Evaluate (f.left)); when ch => return Cosh (Evaluate (f.left)); when arccosh => return Arccosh (Evaluate (f.left)); when th => return Tanh (Evaluate (f.left)); when arctanh => return Arctanh (Evaluate (f.left)); when min => return Real'Min (Evaluate (f.left), Evaluate (f.right)); when max => return Real'Max (Evaluate (f.left), Evaluate (f.right)); end case; end Evaluate; function Evaluate (f : Formula) return Real is begin return Evaluate (f.root); end Evaluate; ------------------------------- Compare ----------------------------------- function Equivalent (fa, fb : p_Formula_Rec) return Boolean; -- Special cases. -- We check these equivalences because the concerned formula -- parts are unlikely to be changed by the Simplify procedure. -- E.g. we don't want to change x/2 into x*0.5; then, we check -- the equivalence. -- X * cst, or cst * X, equivalent to X / (1/cst) function Equivalent_Times_Div (fa, fb : p_Formula_Rec) return Boolean is begin return fa /= null and then fb /= null and then (fa.s = fois and fb.s = sur) and then fb.right /= null and then fb.right.s = nb and then ( ( -- check X * cst Equivalent (fa.left, fb.left) and then fa.right /= null and then fa.right.s = nb and then Almost_zero (fa.right.n * fb.right.n - 1.0) ) or else ( -- check cst * X Equivalent (fa.right, fb.left) and then fa.left /= null and then fa.left.s = nb and then Almost_zero (fa.left.n * fb.right.n - 1.0) ) ); end Equivalent_Times_Div; -- General case: function Equivalent (fa, fb : p_Formula_Rec) return Boolean is ga, gb : S_Form; begin if fa = null then return fb = null; end if; if fb = null then return False; end if; -- fa and fb are not null, at this point ga := fa.s; gb := fb.s; if ga in Neutral then return Equivalent (fa.left, fb); -- +A, (A), [A], {A} -> A elsif gb in Neutral then return Equivalent (fa, fb.left); -- +B, (B), [B], {B} -> B elsif ga = gb then -- Formulas' nodes a and b are of the same kind case ga is when nb => return Almost_zero (fa.n - fb.n); when pi => return True; when var => return fa.v = fb.v; -- same names when Unary => return Equivalent (fa.left, fb.left); when Binary => return (Equivalent (fa.left, fb.left) and then Equivalent (fa.right, fb.right)) or else -- Detect that X * Y is equivalent to Y * X (symmetric (ga) and then Equivalent (fa.left, fb.right) and then Equivalent (fa.right, fb.left)); end case; else -- Formulas' nodes a and b are not of the same kind, but... return Equivalent_Times_Div (fa, fb) or else Equivalent_Times_Div (fa => fb, fb => fa); end if; end Equivalent; function Equivalent (fa, fb : Formula) return Boolean is begin return Equivalent (fa.root, fb.root); end Equivalent; function Identical (fa, fb : p_Formula_Rec) return Boolean is begin if fa = null then return fb = null; end if; if fb = null then return False; end if; -- fa and fb are not null, at this point if fa.s /= fb.s then return False; end if; -- Formulas' nodes a and b are of the same kind case fa.s is when nb => return Almost_zero (fa.n - fb.n); when pi => return True; when var => return fa.v = fb.v; -- same names when Unary => return Identical (fa.left, fb.left); when Binary => return Identical (fa.left, fb.left) and then Identical (fa.right, fb.right); end case; end Identical; function Identical (fa, fb : Formula) return Boolean is begin return Identical (fa.root, fb.root); end Identical; ------------------------------- Simplify ---------------------------------- function Is_constant (a : p_Formula_Rec; cst : Real) return Boolean is begin return a /= null and then a.s = nb and then a.n = cst; end Is_constant; function Is_constant_pair (a : p_Formula_Rec) return Boolean is begin return a.s in Binary and then a.left /= null and then a.right /= null and then a.left.s = nb and then a.right.s = nb; end Is_constant_pair; function Build_2X (X : p_Formula_Rec) return p_Formula_Rec is -- returns 2*X aux : constant p_Formula_Rec := new Formula_Rec (fois); begin aux.left := new Formula_Rec (nb); aux.left.n := 2.0; aux.right := X; return aux; end Build_2X; function Build_X_pow_2 (X : p_Formula_Rec) return p_Formula_Rec is -- returns X^2 aux : constant p_Formula_Rec := new Formula_Rec (puiss); begin aux.left := X; aux.right := new Formula_Rec (nb); aux.right.n := 2.0; return aux; end Build_X_pow_2; procedure Simplify (f : in out p_Formula_Rec) is aux, nexp : p_Formula_Rec; procedure left_replaces_f is begin aux := f.left; f.left := null; -- empeche destruction Deep_delete (f); f := aux; end left_replaces_f; procedure right_replaces_f is begin aux := f.right; f.right := null; -- empeche destruction Deep_delete (f); f := aux; end right_replaces_f; procedure cst_replaces_f (cst : Real) is begin Deep_delete (f); f := new Formula_Rec (nb); f.n := cst; end cst_replaces_f; use REF; procedure Simplify_functions is x, y : Real; -- Assumes: f.s in Built_in_function begin if f.left = null then return; end if; if f.s in Binary then if f.right = null then return; end if; if f.right.s = nb then y := f.right.n; end if; end if; -- -- Arguments are constants, we can evaluate the function and put the result as constant. -- Actually we could use the "Evaluate" function (for operators as well), but we then would -- need a fake payload. We also choose not to simplify cases where evaluation would fail. -- if f.left.s = nb then -- Evaluate "f(cst)" into f(cst) x := f.left.n; case Built_in_function (f.s) is when abso => cst_replaces_f (abs x); when sign => cst_replaces_f (Sign (x)); when step => cst_replaces_f (Step (x)); when round => cst_replaces_f (Real'Rounding (x)); when trunc => cst_replaces_f (Real'Truncation (x)); when floor => cst_replaces_f (Real'Floor (x)); when ceiling => cst_replaces_f (Real'Ceiling (x)); when sinus => cst_replaces_f (Sin (x)); when arcsin => cst_replaces_f (Arcsin (x)); when cosinus => cst_replaces_f (Cos (x)); when arccos => cst_replaces_f (Arccos (x)); when expn => cst_replaces_f (Exp (x)); when logn => if x > 0.0 then cst_replaces_f (Log (x)); end if; when sqrt => cst_replaces_f (Sqrt (x)); when tg => cst_replaces_f (Tan (x)); when arctg => cst_replaces_f (Arctan (x)); when sh => cst_replaces_f (Sinh (x)); when arcsinh => cst_replaces_f (Arcsinh (x)); when ch => cst_replaces_f (Cosh (x)); when arccosh => cst_replaces_f (Arccosh (x)); when th => cst_replaces_f (Tanh (x)); when arctanh => cst_replaces_f (Arctanh (x)); when min => if f.right.s = nb then cst_replaces_f (Real'Min (x, y)); end if; when max => if f.right.s = nb then cst_replaces_f (Real'Max (x, y)); end if; end case; end if; if f.s = cosinus and then f.left /= null and then f.left.s = moins_una then aux := f.left.left; -- Cos(-X) -> Cos(X) Dispose (f.left); f.left := aux; end if; end Simplify_functions; begin if f = null then return; end if; -- Simplify arguments first, before the formula itself case f.s is when Unary => Simplify (f.left); when Binary => Simplify (f.left); Simplify (f.right); when others => null; end case; if f = null or else (f.s in Unary and then f.left = null) or else (f.s in Binary and then (f.left = null or else f.right = null)) then return; end if; case f.s is when moins_una => if f.left.s = moins_una then aux := f.left.left; -- --X -> X Dispose (f.left); Dispose (f); f := aux; elsif f.left.s = nb then cst_replaces_f (-f.left.n); -- -cst -> cst end if; when plus_una => left_replaces_f; -- +X -> X when par | croch | accol => if par_or_terminal (f.left.s) then left_replaces_f; -- ((...)) -> (...), (c) -> c, (v) -> v end if; when plus => if f.right.s = moins_una then aux := new Formula_Rec (moins); -- X + -Y -> X - Y aux.left := f.left; aux.right := f.right.left; Dispose (f.right); Dispose (f); f := aux; elsif Equivalent (f.left, f.right) then aux := Build_2X (f.left); -- X + X -> 2*X Deep_delete (f.right); Dispose (f); f := aux; elsif f.right.s = plus and then Equivalent (f.left, f.right.left) then f.left := Build_2X (f.left); -- X + {X + Y} -> 2*X + Y Deep_delete (f.right.left); -- destroy 2nd occurence of X aux := f.right.right; -- keep Y Dispose (f.right); f.right := aux; elsif f.right.s = plus and then Equivalent (f.left, f.right.right) then f.left := Build_2X (f.left); -- X + {Y + X} -> 2*X + Y Deep_delete (f.right.right); -- destroy 2nd occurence of X aux := f.right.left; -- keep Y Dispose (f.right); f.right := aux; elsif f.left.s = nb and then f.right.s = plus and then f.right.left.s = nb then aux := f.right.right; -- cst + {cst + X} -> cst + X f.left.n := f.left.n + f.right.left.n; Dispose (f.right); f.right := aux; elsif f.right.s = nb and then f.right.n < 0.0 then aux := new Formula_Rec (moins); -- X + neg_cst -> X - {abs neg_cst} aux.left := f.left; aux.right := f.right; aux.right.n := abs aux.right.n; Dispose (f); f := aux; elsif Is_constant_pair (f) then cst_replaces_f (f.left.n + f.right.n); -- cst + cst -> cst elsif Is_constant (f.left, 0.0) then right_replaces_f; -- 0 + X -> X elsif Is_constant (f.right, 0.0) then left_replaces_f; -- X + 0 -> X end if; when moins => if f.right.s = moins_una then aux := new Formula_Rec (plus); -- X - -Y -> X + Y aux.left := f.left; aux.right := f.right.left; Dispose (f.right); Dispose (f); f := aux; elsif Equivalent (f.left, f.right) then cst_replaces_f (0.0); -- X - X -> 0 elsif f.right.s = nb and then f.right.n < 0.0 then aux := new Formula_Rec (plus); -- X - neg_cst -> X + {abs neg_cst} aux.left := f.left; aux.right := f.right; aux.right.n := abs aux.right.n; Dispose (f); f := aux; elsif Is_constant_pair (f) then cst_replaces_f (f.left.n - f.right.n); -- cst - cst -> cst elsif Is_constant (f.left, 0.0) then aux := new Formula_Rec (moins_una); -- 0 - X -> -X aux.left := f.right; Deep_delete (f.left); Dispose (f); f := aux; elsif Is_constant (f.right, 0.0) then left_replaces_f; -- X - 0 -> X end if; when fois => if Equivalent (f.left, f.right) then -- X*X -> X^2 aux := Build_X_pow_2 (f.left); Deep_delete (f.right); -- destroy 2nd occurence of X Dispose (f); f := aux; elsif f.right.s = fois and then Equivalent (f.left, f.right.left) then f.left := Build_X_pow_2 (f.left); -- X * {X * Y} -> X^2 * Y Deep_delete (f.right.left); -- destroy 2nd occurence of X aux := f.right.right; -- keep Y Dispose (f.right); f.right := aux; elsif f.right.s = fois and then Equivalent (f.left, f.right.right) then f.left := Build_X_pow_2 (f.left); -- X * {Y * X} -> X^2 * Y Deep_delete (f.right.right); -- destroy 2nd occurence of X aux := f.right.left; -- keep Y Dispose (f.right); f.right := aux; elsif Is_constant_pair (f) then cst_replaces_f (f.left.n * f.right.n); -- cst*cst -> cst elsif f.left.s = puiss and then f.right.s = puiss and then Equivalent (f.left.left, f.right.left) then aux := new Formula_Rec (par); -- X^m * X^n -> X^(m+n) aux.left := new Formula_Rec (plus); aux.left.left := f.left.right; aux.left.right := f.right.right; -- aux= "(m+n)" nexp := new Formula_Rec (puiss); nexp.left := f.left.left; nexp.right := aux; -- nexp= "X^(m+n)" Deep_delete (f.right.left); Dispose (f.left); Dispose (f.right); Dispose (f); -- dissoudre ancienne expr f := nexp; elsif f.right.s = puiss and then Equivalent (f.left, f.right.left) then aux := f.right; -- X * X^n -> X^(n+1) Deep_delete (f.left); Dispose (f); f := aux; -- got rid of * aux := new Formula_Rec (par); aux.left := new Formula_Rec (plus); aux.left.left := f.right; aux.left.right := new Formula_Rec (nb); aux.left.right.n := 1.0; -- (n+1) prepared f.right := aux; elsif f.left.s = puiss and then Equivalent (f.left.left, f.right) then aux := f.left; -- X^n * X -> X^(n+1) Deep_delete (f.right); Dispose (f); f := aux; -- got rid of * aux := new Formula_Rec (par); aux.left := new Formula_Rec (plus); aux.left.left := f.right; aux.left.right := new Formula_Rec (nb); aux.left.right.n := 1.0; -- (n+1) prepared f.right := aux; elsif Is_constant (f.left, 0.0) or else Is_constant (f.right, 0.0) then cst_replaces_f (0.0); -- 0*X or X*0 -> 0 elsif Is_constant (f.left, 1.0) then right_replaces_f; -- 1*X -> X elsif Is_constant (f.right, 1.0) then left_replaces_f; -- X*1 -> X end if; when sur => if Is_constant (f.right, 1.0) then left_replaces_f; -- X/1 -> X elsif Equivalent (f.left, f.right) then cst_replaces_f (1.0); -- X/X -> 1 elsif Is_constant_pair (f) and then not Almost_zero (f.right.n) then cst_replaces_f (f.left.n / f.right.n); -- cst/cst -> cst end if; when puiss => if Is_constant (f.right, 0.0) then cst_replaces_f (1.0); -- X^0 -> 1 elsif Is_constant (f.right, 1.0) then left_replaces_f; -- X^1 -> X elsif f.left.s = nb and f.right.s = nb then -- cst^cst -> cst cst_replaces_f (Exp (Log (f.left.n) * f.right.n)); end if; when Built_in_function => Simplify_functions; when pi => cst_replaces_f (Ada.Numerics.Pi); when nb | var => null; end case; end Simplify; procedure Simplify (f : in out Formula) is begin Simplify (f.root); end Simplify; procedure Enumerate_custom (f : Formula; lp : List_proc) is procedure EC (f : p_Formula_Rec) is begin if f /= null then case f.s is when var => lp (To_String (f.v), 0); when Unary => EC (f.left); when Binary => EC (f.left); EC (f.right); when others => null; end case; end if; end EC; -- begin if lp /= null then EC (f.root); end if; end Enumerate_custom; overriding procedure Adjust (f : in out Formula) is begin f.root := Deep_copy (f.root); end Adjust; overriding procedure Finalize (f : in out Formula) is begin Deep_delete (f.root); end Finalize; end AoC_2020_18_Weird_Formulas; ================================================ FILE: exm/aoc/2020/aoc_2020_18_weird_formulas.ads ================================================ -- Variant of the Formulas package (see the open-source MathPaqs project), -- with "alternative" arithmetics... with Ada.Finalization; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO; generic type Real is digits <>; with function Plus (a, b : Real) return Real; with function Minus (a, b : Real) return Real; with function Times (a, b : Real) return Real; plus_char : Character; minus_char : Character; times_char : Character; package AoC_2020_18_Weird_Formulas is type Formula is tagged private; --------------------------------------------------- -- The parsing of the formula is done once -- -- The evaluation is quick and done many times -- --------------------------------------------------- procedure Parse (f : out Formula; s : String); function Parse (s : String) return Formula; -- NB: a bit slower than the procedure procedure Parse (f : out Formula; u : Unbounded_String); function Parse (u : Unbounded_String) return Formula; -- NB: a bit slower than the procedure function Evaluate (f : Formula) return Real; Parse_Error, Div_By_0 : exception; ----------------------------------- -- Comparison / simplification -- ----------------------------------- function Equivalent (fa, fb : Formula) return Boolean; -- Strict form of formula equivalence: function Identical (fa, fb : Formula) return Boolean; procedure Simplify (f : in out Formula); -- Deep_copy and Deep_delete are no more needed and -- were removed, it is done now automatically. ---------------------------------------------------------------- -- Display. Caution: the displayed constants may be rounded -- ---------------------------------------------------------------- type Output_style is ( normal, -- Normal is infix, should be the closest to the parsed formula bracketed -- Like normal, but displays a {} around every parse tree node ); procedure Put (f : Formula; style : Output_style := normal); procedure Put (t : in Ada.Text_IO.File_Type; f : Formula; style : Output_style := normal); function Image (f : Formula; style : Output_style := normal) return String; ----------------- -- Utilities -- ----------------- type List_proc is access procedure (name : String; parameters : Natural); procedure Enumerate_custom (f : Formula; lp : List_proc); -- This will find all custom variables or functions appearing -- in a formula and list it through List_proc. -- A name will be listed as many times as it appears in the formula. --------------------------------------------------- -- Character set used for defining identifiers -- --------------------------------------------------- type Character_Set is array (Character) of Boolean; -- Custom variables or functions always begin with a letter: letters : constant Character_Set := ('a' .. 'z' | 'A' .. 'Z' => True, others => False); -- Set of following characters in custom variables or functions names is defined here: following_character : constant Character_Set := ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' | '.' => True, others => False); private type S_Form is ( -- 0 argument (leaf, terminal nodes): nb, pi, var, -- 1 argument: moins_una, plus_una, par, croch, accol, -- vvv begin of built-in functions abso, sign, step, round, trunc, floor, ceiling, expn, logn, sqrt, sinus, arcsin, cosinus, arccos, tg, arctg, sh, arcsinh, ch, arccosh, th, arctanh, -- 2 arguments: min, max, -- ^^^ end of built-in functions moins, plus, sur, fois, puiss); subtype Unary is S_Form range moins_una .. arctanh; subtype Binary is S_Form range min .. puiss; type Formula_Rec (s : S_Form); type p_Formula_Rec is access Formula_Rec; type Formula_Rec (s : S_Form) is record case s is when nb => n : Real; when pi => null; when var => v : Unbounded_String; when Unary | Binary => left, right : p_Formula_Rec; end case; end record; type Formula is new Ada.Finalization.Controlled with record root : p_Formula_Rec := null; end record; overriding procedure Adjust (f : in out Formula); overriding procedure Finalize (f : in out Formula); end AoC_2020_18_Weird_Formulas; ================================================ FILE: exm/aoc/2020/aoc_2020_19.txt ================================================ 108: 117 50 | 63 64 124: 50 64 | 64 64 123: 64 119 | 50 85 45: 60 64 32: 20 50 | 79 64 36: 97 64 | 70 50 97: 50 64 | 64 50 21: 50 104 | 64 83 59: 50 124 | 64 83 10: 115 64 | 34 50 118: 50 124 | 64 4 60: 12 50 | 4 64 84: 29 64 | 99 50 111: 64 27 | 50 14 18: 64 101 | 50 29 13: 64 45 | 50 1 62: 64 97 | 50 83 117: 124 64 | 70 50 98: 50 4 | 64 124 15: 64 114 | 50 12 7: 100 64 | 56 50 78: 99 50 | 52 64 82: 114 64 | 97 50 22: 6 64 | 4 50 63: 12 50 | 114 64 16: 64 52 | 50 70 76: 50 46 | 64 13 31: 64 69 | 50 67 37: 21 50 | 128 64 95: 68 64 | 16 50 12: 64 50 | 50 30 26: 50 12 | 64 83 112: 113 50 | 72 64 33: 104 64 | 52 50 25: 70 64 | 114 50 96: 51 64 | 105 50 51: 50 47 | 64 26 91: 103 50 | 9 64 65: 66 64 | 23 50 116: 64 114 | 50 97 42: 64 54 | 50 40 4: 50 64 79: 50 97 | 64 29 110: 64 116 | 50 118 0: 8 11 73: 50 12 | 64 101 70: 50 50 | 64 50 74: 61 50 | 65 64 27: 50 107 | 64 90 101: 30 30 105: 17 50 | 24 64 61: 58 64 | 102 50 17: 50 83 | 64 29 72: 30 97 88: 64 38 | 50 2 14: 50 36 | 64 2 125: 64 50 | 64 64 127: 95 64 | 28 50 83: 64 64 80: 64 107 | 50 81 106: 50 101 | 64 29 56: 88 64 | 49 50 52: 50 50 | 64 64 46: 80 50 | 120 64 94: 68 64 | 33 50 47: 50 114 | 64 6 69: 44 64 | 57 50 54: 74 64 | 3 50 89: 50 83 48: 106 64 | 59 50 87: 86 50 | 37 64 35: 64 73 | 50 55 115: 50 99 | 64 70 44: 111 50 | 109 64 75: 78 50 | 22 64 20: 64 101 | 50 6 41: 50 4 | 64 101 6: 64 50 66: 50 93 | 64 115 90: 64 101 | 50 124 23: 50 82 | 64 77 81: 50 114 | 64 101 30: 50 | 64 100: 122 50 | 75 64 86: 50 73 | 64 18 92: 64 48 | 50 71 68: 6 50 | 114 64 121: 50 70 8: 42 85: 64 112 | 50 110 38: 64 104 | 50 4 120: 84 50 | 55 64 67: 64 7 | 50 53 64: "a" 55: 50 52 | 64 125 28: 89 50 | 84 64 71: 50 39 | 64 16 109: 43 64 | 94 50 99: 50 50 43: 41 64 | 77 50 119: 64 108 | 50 35 57: 87 50 | 96 64 39: 64 97 | 50 6 104: 50 64 | 64 30 29: 50 64 | 50 50 34: 83 50 | 125 64 2: 99 64 | 124 50 11: 42 31 114: 64 64 | 30 50 93: 50 97 | 64 101 58: 50 33 | 64 121 113: 64 99 | 50 70 128: 64 4 | 50 125 40: 123 64 | 76 50 107: 50 52 | 64 83 102: 126 50 | 25 64 126: 50 125 | 64 97 19: 50 124 | 64 114 24: 114 64 | 29 50 49: 20 30 1: 64 19 | 50 15 103: 26 50 | 18 64 9: 64 117 | 50 62 50: "b" 53: 91 64 | 5 50 77: 6 64 | 99 50 5: 32 64 | 10 50 3: 64 92 | 50 127 122: 115 64 | 98 50 bbabbaaabbabbaaaabbbbbbb bbaabaaaaabbbaaaabaaabba baabababbbbaaaaabbabaaba baaabbbabaabbaaababaabbaaaaabbbb bbbbaabbbabaabbabaabaaaa aabaaaabaababbbbababaabb bbabbbaaabbbbabbbbabbabbbbbbbbabaabaaaabaabaabbabbabbbbbaabaaaba baaaaaaabaabbbaaaaaababb aaabbabaaabbabbbabaaabba abbbbbabbababaabbaaabbbaababbbbaababbabb bababbaabbbbbbaababaaabaaabababbabababba babbaabbbabaabbbbbaaabba abbbbbabbbbaababbababaaa aaabaaababbaaabbbbbabbaaaabbbbba bbaabaaaabbbaaaabbabbbab baabaabababbaaababbababa abbbbbabababaaabbbbbbbba aababbbababbababaaababababbbbbbabaaabaaa bbbbabaabbabaabbbbabbbaa aabaabbbbbbababbbabbbaba abbababaabbbaabbbabaaaababbbaabababbaaaaababbaabbbaabbabbbabaaabbaabaabbbbaaabaa baababaaabababaabaaabbabbbaaaabbabbabaab bbbaaaaabaababaaaaabbaaabbbababbaaabaaba bbababbabbbbbbabbbbabbbbbaabbbabaabbbbababbabaab abbbbbabbbabaabbbabbaabaaababaab bbbbabbbbaababaaaaabbbbabbabbbbbbabbbbaaabaabbabaabbabbb abbaabbabaaabaaaaabbbbaaaaabbbbb aabaababababbbabbbabbbaabaaaabaaaaabbbbbaabbbabbaaabbbab abaabaaabababbaababbabab aabaaaabbbaababbbbabaaab bbbababbabbbbabaaaabababbbabbbabbbbaaaabaaabbbbbaabababbbbababbbbbabaabb aabbaababaabaaaaabbbbbabbbaaabaaaabaabab baabbaaaaaaabbabbbababab abbbabaabaabbbabbabaaaabaabaaaababaabbbb aabbbabaaabababaabbababb abababbbabaaabbaaaaaaababbabaabbbabbaaaabbbbbaab abbabbaabbbaabbbabbaabaa baabababbaabbaaabaaababb aababaabbbabbababbaabababaaaabbabaabbaab bbaaaabbbbbbababaabbbaaaabaabaaabbbbbbba abbaabbbbaababaaaabaabaa aaaaaabbabbaabbbbaabbabb bababababababaabaaabbaabbababaababaabaabababbaba ababbbbabbbbabaaabbbbbba babaaabaaabbababbabbbbaa bbabbbbabbbbbbabaaababbbaaabbabbbabbabbababbabbbbaabbbaabbababaa bbaabaaaaabbbabaabbabbba babababababbaabaaabbbbbb baabbbabaabaabbabaabbbbb babbbbababbaaabbbaaabbaabababbaabababaabbbbbaaabaaaaaaaa aabbbabbababbbbaaaaaabaa bbbababbababbbbabbaaabba aabbabbaababaabbbbaababa abbabaaabbbaaaaabbbababaaabbababbabbbaab babaaaaaaababababbbabbbbbbbbbbaa abaaababbabbbbbabaabaabb babbbabbabbbbbabababbbbaaababbab aaabbbbabababaabababbbbaabababab baaabaabbabaaaabbababbaabbbabbbaabbbabbb babaaabbabbabbabbabbbaba bbaabbbababbbbabaaaabaaaaabbabababaabaab abaaabaaabaabababbaaaabbbabbabab bbbaaaababbabbabaaaaabab bbbbababbaaabbaaabaabbbb abbbbabbbaaaaababbbbbbba bababbabaababbbbbababaaa bbababbabbbbabbbbbababaabbbbbbbbabbbbabbbbaababa baaaaababaabababaabaaabb baabaababaaabbaaabababab baaaaaaabbbababbbbbaabbbaababaaa ababaaabbabaabbbabababba baaabbbaabbabaaabbaaaaabaaaabbabbabbbbbbbbbaabaa bbbababbabbbaaabaababaab aaaaaabbaabbbaaabaaaaabb babaaabbbbabbaaabbabbaab aaabbaabbbababaaabaabaababababab aaabaabbbabbaaaaababaaabababaabb bbaaaabbbaaabbbaaababaaa bbabbbbabbbaababbabbabba baabababaaababaababaaaaaaababbab baabbaaaaaabaaabbbbbaaaa babbaaababaabaaaaaaabbbb babaaaaaaaaabbabaabbababaabbabbaababaaabbbaabbaaaaabbbbb abababaabbabaabbbaabbaaabbaaaaaa bbbbbbaaaaabbabbbabbaaaabaabbbaababbbbbbbaabbbbaabbbababaabbaaababaababbabbbbaaaaabaaaaaaabaabab bbababaabbbbaabbbbaabbbbbbbbbbbabbbaabbabbbbbabbabaaabaaaaabaaaa abbbaabbbbbaabbbbabaabaabababbbbabaabbab babaababaaababaabbaabbbbaaabaaabaaababbbabbbaaaabbabbbbbbbaababaabaabbbbbbbbbaaaaaababaa babaabaababaabaabbaabbbb bbbbbaaabbababaaabaabbaaaaaaabbbabbabaabbaaaabba babbbbbbaaabbbabbbbabaaa abaabaaababbbbabaababbab bbaaabaabaaaaaaaaaabbbabaabbbbbb aaabbbabaaaaaabbaabbaabbbaabaabaaabbababaaabaaababbbabab aaabbaabaabbabaabbbbabbabaaabaabbaabbabb babababaabaabaaababbaaba babbbbbbabababaabaabbaba baabbbabbbaaaaabababbaabaabbbbaaababaabaabbaabaaaaaabbaabbaaabba abbbabaaabbbaabbbbaaabba baabbbabaabbbbaaaabbbbbb bababbabaaaabaaaaabbbbaaababaaaaaaababbaaaabbbbbabaabbab abbaabbbbbabbbbbaabbbaab ababbbabababbbaaaabbbabbbbaabaabbbbaaabbbaababbaaaaabbbbbaabbabb aaababaaabbaabbbabbbbaaa bbbababbbabbbaaaaabbbbaabaaabbaabbabababaaaaabaa babaabaaabbaabbbbbbbabaaabbaaabbbaababbaabbbbbbbbaabaaaa bababaabaabaaaabbaaaabba baabbbbabaabababbaaabbabbbaabbbaabbbbabaababaaaaababbabaaabaabaaaaaababb aabbbabbbbabbaaaaaaaabba bbbaaabbaabbababbaabaaaa abbbbbababbaabbbbaaabaaabbbbbabbbaaababaaabbaaababaabaaabbbabbaabbbbbbababaababb babbbbbbababbbaabbabbbab abbaabbaaababbbabbaababa aaabbbabbabaabaaabbaabbbabbaabbbaaaaaaaa abbbbabbbbbbabababbaabab bbbbababaaabababbbbbbbba bbbabaabababbbabbaaaabbbbababbabbabababa aababababbbababbbbaabaaaababbababbbbaaaaabbbbabaabaababbabbbaaabbabbaaaabbbbababbabaabab aabbaaabababbbaaabbaabaabababaaaaaaabababbabaaab bbaaaaabbabbbbbabbabbbab babbaababbbbabbbbbabaaab aabababaaabbababbbbbaaba babbaaaabbbaabbbbbbbabaaabbbbbba bbaabaabbbabbbbaabaaababbaabababaabaaaaa abaaababbababbaaabbbbbbb bbaaaabbabbabaaaababbabb aaabababaababababaaabbbb ababbaaaabbbaabbbaabababbaaabbababbabbbabbaaabbb aababbbaabababbabbabbbabbbaabababbbaababbabaabbabaababaa baaabbbababbbabbbbaabaababbbbabbbabababbaabbbbba aabababbaababbbbabbbaaaababbbbabbbbaaabbbabbbabaabaababb baaabbabababbaaabaaaabab aababbbaaabaabbaababbabb aaabbaaaaababbbbbaabbbbbbaaaabaa bbbbbaaababaabaaabbaabbbbbabbbabaaaaabab aababbbbaabaabbabbabbaab bbbaaaabaaaabaababbbbbbb abbabaaaaaaabaaababaaabaaaababbbabaaabbb abbbaaabbabababaabbbbbaa baababaaaaababababababaabaaabbbaabaabaaa bbbbbbbbababbbbabbabbaab ababbaabaabaabbbabbbbbbb babaaababaabbaaaabbabbaaababbababbabbbaaababbbabbbabbbabbabbbabb babaabbabbbaaababbaaaaaa bababbbaabababaabababaabaaaaaabbbbbababa bbbbaabbababaababaaaaaab ababbabbbabbbbaabaabbbbb aabababbabababbaababaabbbbbaabaaabbbbbababbbbbabbbbbabbbbababbabbaababaa ababbbababbabbaabaaaaabb babaabbbbabbabbbaaabbaabbaabbbababbbabba abbbaaabbaababaabbabaaba bbbabaabbabaabbbaabaabab ababbaaaaabaaaabbbaaabab baababababbabbaabbababab abbbbbabbbbbaabbaaaaaaab baaaabbbaababaaaaabaaabbababbababaaaaabbbaaaabaa bbbaaabbabbbaaaababaaaaa bbbbaabbbbabbaaabbaaaaba aaaabbabaaabbabbaaaabbba abaabaaabbbaaaababbaaabaabbbaaabbbababaaaabbaabbabbabaababbabbbb aaabaabbbbaabaababbbaaababbbaaba baaabbbbbabbababbabaabab babbbabbabbabaaaaaaaaabbbbaaaaaa ababbaaaabaababaaaabbbbb bbbaaabbbaabaababaaabbaabbbbbbaaabbbbbaa ababaaaabbbbbbbbabaabbaa bababaababbbabaaaabbabaa babbabaababbaaabbabbbbaababaababbbbaaaaaaaabaabaaaaaababbbabbbbaaaabbbaa baaabaaaabbbabbabaababbb babaaaaabababababaabbaabbaabbbbabbabbabbbbaaaabababbabbbaabbbaaa baabaababbaabbbaaababbab aabaabababaabbbabbbabaaaabaaabaababbabbbaaabbbbbbaabbbaabaaabbbbaababbbbaabbaabb aabbbabbbbaabaaabbbbbabb aaabbaabaabbabbabaaaabba baaabbbaaaabbaaababbabba abaabbbababbbbababbaaaaa bbaaabaaabbbbababbbaababbbbbbaaaabbaababaaabbbbb ababaaaabbbbbaabbababaabbbabbaaabbbbaaba aabbabaaaabbbabbbaabbbbaababaababbbabbbbabaaabaabbaaaabbaabaaaaa bbbabbababbaaabbbaabbaaabaabbbaaaabbbbaabbababaaaabababb babaaababbbbbaaaaabaaabb abbbabbabbbbaabbbbabbbaa bbbbabbbababbaabbbabaaaa abbbaabbbbbbbaaaabbababa bababaabbbbbbbbbaaaaabbb babaaaababaabababbaabbaa abbbaabbabaababaabaaabaaabbbabaabbaababa bababbababbabbaabbaaaaaa babbaaaababbaaabbbabaaaa bbbbbaaaaabbababaaaaabaa abaababaabaaabaaabaababb baabbbbababbaabbbbbbbaba bbabbbbbbbaaaaabbbaaaaabbaabbbaabbbbaaabaaaabbaa aaabbbaaaaaaabbbaaabaabbaaaaaaaabbbaaabbbbbbbaba aabbbababbababbaaaaaabbb bbaabaaaabbaaabbabbabbababaaabbabbaaabba babbaabbabbbbabbbabbbaaabbbaabbbbabbbaababaabbabbabbbbaa bbbaabbbaababababaaaaaab bbaaabaababaaabbaabbabbb aaabaabbbbabbbbbababaabb babaabbbbbbaababaabbbabbabbbabaabbabbaaababbabba babbbbbabaaabbbaaaaaabab aaabbbbabbababaaababbbbb abbbaaaabaaaaababbabbaba baabaaabbbbabbbbaabbbbaababaaabbabaaabba ababaababaababaaaaabbbaa baaabbabaaabbaabbbbbabaaaaaabbaaaaaabaaabaabaabaabaaabbaaabbababaaabbababbaaaaba baabaabaaaaaaabbabbabaaabbabaabbbbabbbbabbabbaabbbabbbabbaabaabb aabbbaaabbbabbbbbbbbbbba aaabaabbaababbbabbabaaaa aaabbabbabbbbbbaaabbbbbbabbbbaaa aabbbbaaaabababaaababbbaaaabaaaa bbaabaabbbbbbabababaababbbbbabaabbbbabaaabbabaab aaabaabbaabbabbabaaaaaab baaaaabaababbbabbbbaaaaa ababbaabaaabaabbabaaaaba baabaabaabababaababaaabbbbabbabb baabbbabbbababbaaababaaa aabaaaabaabaaaabbabababb babbaababaabaaabaaaabbba abbaabbbaabbbaaabaaababa aabbbabbaababbbbbbaababbbbbbbbaaabaaaabb babbabbaababababbaaaabbbbaaaaaabbaaabbbbababbbabaabababa baabaaabbababbabbbaababa babbbabbbbabbbbbabbababa aabbababbbbbbbbbabbaabab bbbbbaabaabbabbaabaaaabb babbbbbbbabaaaabaabbbabbbabaabbbbbababaabbbbaabbabaaabbb bbabbbbaaaababbabaaaaaab abaaaabababaabbaababaabb aaabbbabababbaaaaabaabbaababbbaabaaabbab aaaabbabbababbbabaabbaab bbaaaaabbbaabaababbabbba baaabaaabaabbbbaaabaaabb aababbbbbbbababbbaaabbbbbbaaabba aaaabaaabbbbbbbaabaabbab aabaabbabbbaabbbaabbabbababaabbababbaaabaabaabaaabaaabba baababaabababababbbbbaba bbaabaaabaaabbababbababa abbbaaaaaaababaabaaabbaabaaabbaaaabbaaba abbabbabbbbaaabaabaababb babbabbbaabbbaaaaaaababb bbbabababbaabaabaaabaaaa bbbabaaabaababbabbaaabbaabaabbaa baaaaababbbbbaabbbabbabb baabababbaaabbbabababbaaababbabbabbbbbbb abbbaabbabaaaaaaabaaaaaaaaabbbbababbaaaaababbababaabbbbbbabbbaababbbbaaa aaabbabbbaaaaaaabababaababaaaaab babaaaaaaabbbababbbbabbbabbaabbbaaabbaaaaaaaaaab aabbbabbbababbaabbbababaabbaabbabaaaaabb babbaaabbaabbbaabaabbabb abbaabbaaabababbababbaba abbbbbabbbbbbbbbbaabbabb bbbaabbbbabaabaababaababbabbbabaaabaaabb baabbbbabbbbbbbbbbbbaabbababbabb aaabbbbaabbabbaaaaaababa aabaabbabbbaaabababbbbbaaaaaaababaabbaba abbabbabbaabbbabaaaabbaabaabbabbababbbbbbbaaaaaaaaaababbbbbaaabaaabaaaaabaaaabaa aaababaaaabbababbaabbbaabaababaaaabaaabaaaaabbaa baabaaabaaaaaaaaaabaaabbbbbbaaab abaaabaaaaaaaabbbbaaaaba babbaaabbbaaabaababbbaba babbbbbabbaabaababbababbbabbabbabbbbbaba aaaaaabbbaaaaaaaabaaaabaabbaabbaabbabbbbbbababbbaaaabbbb bbbaababababbaabbbbabaaa aaaaabbabbaaaaabaaabbaabbbabbabaababaabbababbaaababbabaabbbaaabbabbbbabb babaabaaaabbbaaaaabbaaab bbbbabbbbaaabbbabbbaababaaabbaabbabbbaba aabaabaaabaaaabbabbabababaaabbabbbaaaabbbbbbaaaaababbaabaaabaabaabbababb ababbaaaababbaabbaaaabbabababaababbaaabb abababababbbabbbaabbbaababbabaab babbbbabbbbababbbbbbbbabbbababbb aababbbbabaaaabaaabaabab bbbaaababababbababaababb bbbabbbbbabbbabbaabaabab baaababbaaabbbaaabbbabaaabaabaaaaaaabaaaabaababa bbbbbbbbbbabbbbbbbbbbbabaaabbbaaabbbbaab babbabbbbbbbabbbbbaaabba babaaababbbbabaaaaabaaabaababababbabaaab abaababaababbaaabbabbbbbabbabbab bbbabbbbaabaaaabbbabaabbaaababbaaababbbbabaaaabbbbbabbbabaaaabab babbbbbbaaabaabbbbbabbbbbabaabaaabaaabaabaaababa abbabbababbbbababbabaaab ababbaaaabaaabaabbaababb aabaaaabababaaaabbbbaabbabbbaaaaabbaaaab babaaaaaabbbaaaabababaababbbabbababaabaababbbbaaaabaabab abaaaaaababbaabaabbaaaaababbaabbbabbbbbbbaaaabbbabaabbabbbabababaaababba aabbbabababbaabbababbabb aaabbaaaabaabbbaababaabb bbaabbbabbbbababaaabbbabbbbbabbabaaaaaabaabbbbaaaaabbaabbaaaaaaa babaaaabaaabbabbaaabbaba aabbbbaabbbabbaabbbbbbba bbaaaaaaabaabbaaaabaaaba abbbaaabbabbbbbbbbbbabaababaaabbbbaabaaaabbbbbbaabaabbaaabbbababbbbabbba abbaabbbaabbabababaaaabaabbababbabbbabbb abbaaabbbbaabaaabbbbabbbbabbbbbbbaababbb bbabbbbaabbbaaaabbbaababbbababbababbabba abaaabaaabaabaaabbabbbaa aaabbbabbbbbababaaabaaba aabaabbabbbaaaabbabbabba abbaaabbbbaabaabbababaaa aabbabababbaaaaaaaaaabbbabababaabbbaaabbbbbaaaaa aaaabbabbaababaabaaabaab bababbaaaaabbaaaabbabbbb abbaabbbabaaababbbbaababbabbaaaaabbbaaababbaaabaabbbbbba aabbbabaaaabaaabbaaaabaa bababbaabababbaabaabbaba bbaabbbbbbbbaaaaabaabbbb bbbbbbabbabbbbbaabbbbaaa bababbbabaaabaaabbbabaab baaaabaaaabbbbabbabbabbaaaaabbaa bbbbbbabbaabbbabaabbbaab baabaabaabbbaabbaababbab aaabbaaabbbbababaabbababbabaabbaabaabbbabbbabaab baaaaaababbbbbbabbabababbbaaabbbaabaaaababbbabbbaababaabbbaaaaabbaabbbbbabbababb abbbabbabbaaabaabaaabaab abaabbbabababbabababaabaabbabbabaabbaaaabbbbaaaa bbabbabbbbbbaaabaabaababababaabbabababba abaabbabbababaaabbabbababbabaaaababaaaaaaaaaabaabbbbaabbbbbbabaaaaaababbbbabaabaaababbba bbaabbaabbbbbbabbabaaaabababaabbabbabbabbabaaabb abbbaabbbbbaabbaabbbabab bbbbbaabaaaabaabbaaababbabaaaabbabababbb aabbbbbabaabaababaaabbaaaabaabbaabababbbaaabbbbb aaaabaaabbbabababaaabbaaaabbabababbaababaababbaaabaaabba bbbbabaaababbaaabbabaabbbabbaaaaaaaaaaab babbaaaababbbbbabbbabababaabaabb baabababbbbbabbbabbabbba babaabaaaaabbaaaaaaaaaaa bbbaaaabbabbaabbbabbbaba abbaaabababbbaaabbaababb aaababaabbabaabbbababaaa baaabbaaababbabbbabaaaaaabaabbbbaaabaabaababbbbbbbaaaabbaabbbaabababbabbababbaaa bbaabaabbbbababaaabbaabbaaabababbbbabaaaaaaaaaabbaaaaabbababbbbb aaababbaabababaabbbaaabbbbabbaab aabbbabaabbbabaabaabaaaa ababbaaababbaababbabbaba babbabaabbaaabbbabbbaaaaaabaabababaabaaaabaaabbbabbaabbbbabbabbbabbbaaab ababbaaaababbaaabbbbaaba bababbaabaabaaababbaabab babaabbaaabaabbaabbbbabbaababbbabaaaabaaaababaab babbbaaaabbbbbabaabaaaabbbabaaaa abaabaaabababbabbbabaaab babaabbabbbbabaaabaaaabaabbabbabaaaabbab aaabaabbaabbbababbabbbbbaaabaaaa ababaababbbaabababbaaaaabababbbbaabbaaba aabbbabbabbabaaaabaabbab bbabbaaabababbaabbababbb baabbababbababbaaaaabbbbaabbbabaabaabbbbbabaabaabbbbbaaa aababbbabaaaaaabbaaabaab bbbbabbbaaaabaaaababaaaabbaaaaaaababbabb baababbbaabaababbbababbbbbbaababbbbbaaabaaabbababbabaaaaababaaabaaaaabbabbbababb baababaabbbabbbbbaaaabab abbaaababbbaaabbbabababb bbaaaaabbabbaabbababbabb aabaabbaababaabaaaabbaba bbbaababaaabbbbaabbaabbbbaaabababbbbbaba bbaabbbabbaabaabaaaaabaa aabaaaabbaaabbababaabbbabbbaaabbaabaaabaaaaabbba babbaaabbaaabbaabbabbabb bbbaababaaabbbabbabaabab aaababaabbaaabaaaabaabbaabaabbab aaababbaabaabaabbaaaaabbbbabbaaaaaaabbababbbaaaabaabbaabaabbaabbbbbabbab aaaaaaaaabbaabaababbbbbababaababbabbaabbababbbabaaaaaabaabbbabab baaaaabbabaaaabbaaababbabaabbaababbbbbabaaababbbbbbbbaaaabaaabababbababbabbabaababababab abaaaaabbaabababbabaaaababbbaaaabbaaaaaa ababaaaabbbbbaaaababaababaabbabbbbaaabab bbaaaabbaabbbabbabbaabab baabaabaababaabaaaabaaba baabbbabbbaabbaabbababaabbbaaabbbaaaabaabaabbbbbaabbabaaabbababbbbbbbaabbabbaaabababaabb aaaabaaaabbaaababbabbaba aabababbaaabbbababaababb ababaaabababbbabbbabbbab abbbabbaaaababaabaaabbaaababbbbaaabbabbaaaaaabaabaaabbbbbbaaabbaaaaaabba baaaabbbbaabbababbabbbabbabaaaba baabaabaaaaabbabaabaabbbbaaaabbaabaaabbb abbaabbbababbaaababaaababbbaaababaaaaaabbbababab aabbbbaaaaaabaababbaaaababaaabbbaabbbaaaabbbbbababbbaabaaaaabbabaaaaaaaa baaaaaaabababaabababbaba bababbbaaabbababbbaaaaba aaababbaaabbabbaababbbbb aabababbabbbbabaabbabaaaabaabbbabbababbabababbabaaaaabba abbababbbaabaabbbaabbaaaabaaabbaababbbbbbbbbbabbaababbaabaabaababbbabbabaabbabbbbbaaaabbbbbababb aabbabbaabaababaaaaaabba aabbababaaababbaabaabbab abbbbbaababbaababbababaabbaaaaaabaaabababaaaabbbbbaaabbb aaaaabbabaababbaaabaabaa babbbaaabaabbbbababaabbaabaaaaabbbabbbaaabbbabbbbabbbbaa aaaabaabbabaaaababababba abbbabbbaaaaabbbbbaabbaa bbbaaaabbbaabbbababaaabbbbababaabbaaaaaa aaaabaabbbbaaaabbbbabbab aababbbbbaabababbbaaabba baabbbbababbbabbaabbabbabbbababbaaaaabab bbabbbbabaabbaaabaabbbbb ababbaabbbababbabbababab aaabababbbbababbabaaababbbabaaba aaabababbaaabbbabbabbabb bbbbbbabaabaaaabbbaaabab abbabbaabbbabbaaabbaabbbaabaababaababbab abbaabbababbaaaaabbaabbaaabaabbaaabbaaba ababbbabbaababbbbabbbbaaaabbaaabaaaaaaab baabbbbaaaababbbaabbbbbaaabaaaaa bbbababababbaabaaaaaabaa baabababbbbaabbababbbbbaaaababbaabaabbbaaabbabaabbaabbbb aabbbaaabbbbbaabaaabbaba babbbabbaabbaabbbaabbaab bbbabaabbbbaabbaaaabbabbaaabababbbabbaaaabbbaabbbaaabaaababababb bbbaaaabbbabbbbabbbabbba aabbbabababaaaaabbbabbaaaabaaaba bababbaababababaabaaaabb bbbaaabbbbbaabbabbbbbbaabbaabbbb abbbaabbbababaabbbaaaaba abababaabaaabbbabaaabbabbabaaaabbbaaabab bbbabbbbbbbaaaaabbbbababbbabaaabababbbbb abaaaaaaababbaababbaaabaabbaaaab bababaababbbabbabbabaaba babbaababababaabbbbbbbbbabbababbbababbbb bbbaaabbbbababaababbbaba aaabbbbaabbbababbababaaaaaabbbbaababbbbbabaaababbbabbbaaaaaaaabaaaaaabaa bbaabbbabbbbbbaaaaaaaaab baaabbbabbbaaaaaaabbaaaa aaaabaaaaabaabbaabbabbbb abbbbabbbaababaaabababbbbaaabaabaaaaabaabbbbabbaabbabbbb aaaabaabbbababbababbaabbbbabaabbbbbbaaab bbbbbaaabbbaababbbbababbbbabaabbaabbbbba aaabbbbababbbabbbbbaababbbbbbbbbbbabaabbaaaaabaa aabbbabaababaaabbabbbaba bbbaababbbbbbbbbabaabbaa ababaaababbbbbabaaaaabab bbbababbbababbbaabbababa bababbbaabbbabbababbabaa bbbababaabaaaabaaaaabbbb ababaaabbbbaaaabbbabaaba aaababaabbbaaabbbbbaaaababbabbbb babbbbabbababbaaababaaaaabaababbabbbabbb bababbabbabbabbbaabbababbaabbaaaaabbbaabaabbaabbbbaaabbaabbabbbabbbbbaab babbaababaaabbaaababaaaabbbaabaa bbabbbbabaabababbaaabaab abbbaaabaaababbaabaabbab bbbababbbbbabbbbbbabbabb bbbbbaababaaaabaababaabb abbabaaaabbbaaaababbbbab ababbbabaaabbbabaabbbbaaaaabbbbbaabaaaba bbaaabaaaaababaaabaabbbb abaaabaababaaabbbaaabbaabbbbabaabbabbaab bbbbbababbabaababaababbbaabbaabaaabaaaaaaabbbbba aabbbabbabbaaababbababaabbbabababaaaaaaaaabaabaabaababba abaaaababbbbbbababaabbbabbbaaaaaababbabb babbbbbaaaaabbabbaaaaabb aaabaababbaabbaaabbbbbabbbbababbaabbbbbababbbaab abbabaaabbbabbaababbaabbaabbbbba babaaabaabbbabbaaaaabbaa baabbbbabaaaaababbbaabbbaaaabbbb aabbaabbbbbaaaabbbbabbaaabbabbababbbbaababaababb abaaaabbbbaaababbbbbbabb abaaaabaababbbabaabaaabb abaababbaabaababbaaabbbb bbabbabbabababbaaaabbabaabababab aaaaaabbbabaaaabbbbbbbaabaaaaabbaababbabbabbbababaaaabba bbababbabaaababbababbbbbbabbabab bbabbaaababbbbaababbaaab baaaaaaaaabababbaabaabaa abbaaabbabbbaaaababaaabaababaabaababaabb abaaaaabaaababbaaaabaaab abaaaaaabbaabaaaaaabbaabababbbaaabbbabbbbaabbaab abbaaabbbbaabbaaaabbbaaabaabaaaa aabaaaabbbbaaaabaaababbb abbaabaabbbbababbabbaaababaaabbaaabaaaabbabababababababb ================================================ FILE: exm/aoc/2020/aoc_2020_19_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 19 ------------------------------------------- -- Monster Messages -- -- https://adventofcode.com/2020/day/19 -- with Ada.Text_IO; with HAT; use HAT; -- in ../../../src procedure AoC_2020_19_full_Ada is -- n : constant := 6; fn : constant String := "mini.txt"; n : constant := 129; fn : constant String := "aoc_2020_19.txt"; type Rule_Index_List is array (Positive range <>) of Integer; submax : constant := 5; subtype Rule_Index_List_Fixed is Rule_Index_List (1 .. submax); type Rule_Type (is_terminal : Boolean := False) is record case is_terminal is when True => leaf : Character; when False => max : Integer; sub : Rule_Index_List_Fixed; alt : Natural; -- alternative subrule list starts at `alt` end case; end record; max_rule_id : constant := 500; rule : array (0 .. max_rule_id) of Rule_Type; verbose : constant Boolean := False; -- function Is_Valid (s : String) return Boolean is -- -- We verify the string (s) against the rules (list), -- in a LISP-esque fashion ( https://en.wikipedia.org/wiki/CAR_and_CDR ). -- The nice thing in this problem is the tail recursion -- on the string AND on the rule list. -- function Verify (s : String; list : Rule_Index_List) return Boolean is -- function Verify_First_Rule return Boolean is rule_1 : Rule_Type renames rule (list (list'First)); tail_rule_list : Rule_Index_List renames list (list'First + 1 .. list'Last); begin if rule_1.is_terminal then return s (s'First) = rule_1.leaf and then -- Test the rest of the string against the other rules. Verify (s (s'First + 1 .. s'Last), tail_rule_list); elsif rule_1.alt = 0 then -- Test the sub-rules, appended with the tail of the rules, and -- verify all that on the local string. return Verify (s, rule_1.sub (1 .. rule_1.max) & tail_rule_list); else -- Test separately both subrule lists: return Verify (s, rule_1.sub (1 .. rule_1.alt - 1) & tail_rule_list) or else Verify (s, rule_1.sub (rule_1.alt .. rule_1.max) & tail_rule_list); end if; end Verify_First_Rule; -- begin if list'Length = 0 then -- Rule list is empty. OK if the string is empty as well. return s'Length = 0; end if; if s'Length = 0 then -- String is too short: there are unprocessed rules. return False; end if; return Verify_First_Rule; end Verify; -- -- Test rule 0 (and all the rest...): is_test_ok : constant Boolean := Verify (s, (1 => 0)); begin if verbose then Put_Line ("Tested: " & s & " : " & (if is_test_ok then "OK" else "invald")); end if; return is_test_ok; end Is_Valid; -- procedure Parse_Rules (f : in out File_Type) is procedure Get_Nat (n : out Natural) is c : Character; begin n := 0; Get (f, c); while c = ' ' loop -- Skip heading blanks. Get (f, c); end loop; loop exit when (c < '0') or (c > '9'); n := n * 10 + Ord (c) - Ord ('0'); Get (f, c); end loop; end Get_Nat; -- c, sep : Character; i, j, k : Integer; begin for count in 1 .. n loop Get_Nat (i); Get (f, sep); Get (f, c); if c = '"' then Get (f, c); rule (i) := (is_terminal => True, leaf => c); Get (f, sep); if verbose then Put_Line (+"Terminal " & i & " -> " & rule (i).leaf); end if; else k := 0; rule (i).alt := 0; loop if (c >= '0') and (c <= '9') then j := Ord (c) - Ord ('0'); else j := 0; end if; k := k + 1; while not End_Of_Line (f) loop Get (f, c); exit when (c < '0') or (c > '9'); j := j * 10 + Ord (c) - Ord ('0'); end loop; rule (i).sub (k) := j; exit when End_Of_Line (f); Get (f, c); if c = '|' then rule (i).alt := k + 1; Get (f, c); end if; end loop; rule (i).max := k; if verbose then Put (+" List " & i & ": "); for l in 1 .. k loop if rule (i).alt = l then Put ("| "); end if; Put (+"" & rule (i).sub (l) & " "); end loop; New_Line; end if; end if; end loop; end Parse_Rules; -- total : Natural; f : File_Type; begin for part in 1 .. 2 loop total := 0; Open (f, fn); Parse_Rules (f); if part = 2 then rule (8) := (is_terminal => False, max => 3, alt => 2, sub => (42, 42, 8, -1, -1)); rule (11) := (is_terminal => False, max => 5, alt => 3, sub => (42, 31, 42, 11, 31)); end if; Ada.Text_IO.Skip_Line (f, 2); while not End_Of_File (f) loop if Is_Valid (Ada.Text_IO.Get_Line (f)) then total := total + 1; end if; end loop; Close (f); Put_Line (total); -- Part 1: Validated by AoC: 226 -- Part 2: Validated by AoC: 355 end loop; end AoC_2020_19_full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_20.adb ================================================ -- Solution to Advent of Code 2020, Day 20 ------------------------------------------- -- Jurassic Jigsaw -- -- https://adventofcode.com/2020/day/20 -- -- Part 1 only -- with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2020_20 is use HAT, Interfaces; size : constant := 144; name : constant VString := +"aoc_2020_20.txt"; type Side is (up, down, swup, swdown, left, right, swleft, swright); subtype Tile_Range is Positive range 1 .. size; label : array (Tile_Range) of Natural; side_code : array (Side, Tile_Range) of Natural; -- subtype Edge_Value_Range is Natural range 0 .. 1023; edge_count : array (Edge_Value_Range) of Natural; -- compiler_test_mode : constant Boolean := Argument_Count >= 1; -- procedure Get_Nat (f : in out File_Type; n : out Natural) is c : Character; begin n := 0; Get (f, c); while c = ' ' loop -- Skip heading blanks. Get (f, c); end loop; loop exit when c < '0' or c > '9'; n := n * 10 + Ord (c) - Ord ('0'); Get (f, c); end loop; end Get_Nat; -- procedure Read_Data is t_s : String (1 .. 5); -- "Tile " f : File_Type; c : Character; bit : Integer; begin Open (f, name); for n in Tile_Range loop Get (f, t_s); Get_Nat (f, label (n)); for s in Side loop side_code (s, n) := 0; end loop; for i in 0 .. 9 loop for j in 0 .. 9 loop Get (f, c); if c = '#' then bit := 1; else bit := 0; end if; if i = 0 then -- top-down (0 = top) side_code (up, n) := side_code (up, n) + bit * (2 ** j); side_code (swup, n) := side_code (swup, n) + bit * (2 ** (9 - j)); end if; if i = 9 then side_code (down, n) := side_code (down, n) + bit * (2 ** j); side_code (swdown, n) := side_code (swdown, n) + bit * (2 ** (9 - j)); end if; if j = 0 then side_code (left, n) := side_code (left, n) + bit * (2 ** i); side_code (swleft, n) := side_code (swleft, n) + bit * (2 ** (9 - i)); end if; if j = 9 then side_code (right, n) := side_code (right, n) + bit * (2 ** i); side_code (swright, n) := side_code (swright, n) + bit * (2 ** (9 - i)); end if; end loop; end loop; end loop; Close (f); end Read_Data; -- procedure Count_Edges is procedure Increment (value : Natural) is begin edge_count (value) := edge_count (value) + 1; end Increment; begin for i in Edge_Value_Range loop edge_count (i) := 0; end loop; for m in Tile_Range loop for s in Side loop Increment (side_code (s, m)); end loop; end loop; for i in Edge_Value_Range loop if edge_count (i) > 2 then Put_Line ("Though puzzle case (luckily, our data isn't)"); Put_Line (+"" & i & " : " & edge_count (i)); end if; end loop; end Count_Edges; -- function Is_Corner (n : Positive) return Boolean is begin return (edge_count (side_code (left, n)) = 1 and edge_count (side_code (up, n)) = 1) or (edge_count (side_code (right, n)) = 1 and edge_count (side_code (up, n)) = 1) or (edge_count (side_code (left, n)) = 1 and edge_count (side_code (down, n)) = 1) or (edge_count (side_code (right, n)) = 1 and edge_count (side_code (down, n)) = 1); end Is_Corner; -- function Spot_Corners return Integer_64 is prod : Integer_64 := 1; begin for n in Tile_Range loop if Is_Corner (n) then prod := prod * Integer_64 (label (n)); end if; end loop; return prod; end Spot_Corners; -- begin Read_Data; Count_Edges; if compiler_test_mode then if Spot_Corners /= Integer_64'Value (To_String (Argument (1))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line ("Product of corner labels:" & Integer_64'Image (Spot_Corners)); end if; -- 20899048083289 (example) -- 83775126454273 (input) end AoC_2020_20; ================================================ FILE: exm/aoc/2020/aoc_2020_20.txt ================================================ Tile 2647: #....##### .##......# ##......## .....#..#. .........# .....#..## #.#....#.. #......#.# #....##..# ...##..... Tile 1283: ######..#. #.#..#.#.. ..#..#...# .#.##..#.. #......#.. #.#....##. .#.....#.# #.#..#.#.# .#......## ...##..... Tile 3547: #.#.#.###. #......... #....##... #.....#..# #.....#.#. ##..##...# #...##.... ......#..# #...##.... .....###.# Tile 1451: ##..#.#... #.#....... ##.#.....# ....#..... ...#...##. ......#.#. #...##.##. ........#. .#.##.#... ..##..#... Tile 3137: ....#.##.# #....#...# ..#.#..... ...####..# .#.###...# .......#.. ##.##.#..# .#.##....# #...#....# ..##.##..# Tile 2897: ###..#.##. ..#......# .....#.... ###.#....# #.#..#...# .#...##..# ##..##.##. #.....#..# .#......## #.#.#.##.# Tile 1093: ..#.#.#.#. #.#....... ..##....#. .#.....#.# #........# .#....#..# ##....#..# #.##..#..# ..###...## .######.## Tile 1217: #..#....## #.....#... ##...##..# #.....#... ..#.#..#.. #..#....## .##.#..... ......#... .#........ .#..###.#. Tile 2801: ###..##.#. .........# ##.#...### #......#.. #........# ......#... ##.####... .....##... ..#..#.##. ...###.##. Tile 1361: ...#.##..# ....#..... ###....... #......#.. .......##. #...#..#.. #.....##.# ##........ #.#....... ###.#..### Tile 2063: ...#....## ##...#..## #........# ........## #.......## #......... ##.....##. .....##..# .#.##.#... .#..#####. Tile 3797: ##..#...#. .###.#.##. .....#.##. ..#....... ...#.#.... ........## #.#.#.##.# #.....#.## #.......#. .....#.##. Tile 1289: ####.##.#. .....#.... #..#.#.... ####...#.. #.#..#..#. .#.##..#.. #........# ....#..#.. ........#. ###.#.#### Tile 1427: ##.##..##. ###..#.##. #..##...#. #..#.#...# #........# #...##.... #........# .....#..#. .####....# ##.#.##.#. Tile 1951: ....##.#.# .........# #........# .#..#...#. .....##### #......#.# ...##....# ......#... ..#...#..# ....####.# Tile 1483: ....####.. .......#.# ###..#..## ...#.#...# #..##...## ##.#...... #...#..#.. ..#...#.## .........# .#...#.... Tile 1789: ##..#####. ....#....# ........#. ..#.#..#.# ..##.#..## .........# .........# #..#.#..## ....##.... #.#....... Tile 2129: #.###.#..# ....##...# .#..#..##. ...###.##. ..#..#...# ....##...# #......... #...#..### #...#..... ...#....## Tile 2137: ..#.####.# ##...#.#.. .......### .#.....#.# .#....##.# #.......#. #....#...# #.....#### ......##.# ..#####.## Tile 3761: .####.#... ####..#..# #...##..## .#.....#.# ....#....# #.......#. ...#..#..# #.##...##. ...###...# ...##.#..# Tile 1327: ..####.#.# #..#...... ......#.## #..##..... ..##.##..# #.#.#..... ####.....# ..#....... #.#...##.. #.##....#. Tile 2741: .#..#...#. #....#..#. ......##.# ....#.#..# ........## ...#..#... ......##.. #...#..#.# ......##.. ..#..#..#. Tile 1699: .###..#### ##.....#.# .....##.## #.#...##.. .#........ .#....#..# #..#....#. .#...#...# #.......#. ##.#..#..# Tile 1151: ..#.##.... ##....#... ###.#..#.# #.......## ....#.#..# #...###... .#..#.#..# #.#..##..# .#.#.#.#.. .###..#### Tile 2273: #.#.#.#.## .......... #......#.. #.....#... #.#...#... ##....##.. ##..##.#.. #.#####.## ##.##...## #...##..## Tile 1999: ##.##...## #......#.. ##..#..... #........# #.#...#### ..#....#.# #..#...#.. .........# #...##.... ##.##.##.. Tile 1721: ....##...# ###.#....# .##..#.... .#.#.#.... ...##....# ##..#....# #....#.### #.....##.. ....#...## ..#.#.#..# Tile 2521: ..#######. #.#..##.#. .#....##.# ..#...#### .......##. ##...###.. ...##....# .##.#..... ###..##..# ####.##.#. Tile 2111: ..#.#..#.. ...#.....# ..####...# .#.#..##.# .##..#.##. ........## ........## #..#.#.... ...#.###.. .#.#...#.. Tile 2767: .#######.. ##.......# #...#.##.. ....#...## #........# ..#.###... ....#..#.# ##....#.## ..##....## .#####.#.. Tile 2141: ####.#.... #..#.#...# ...#..#..# .......#.. .....###.# #....#.... .......#.# .#...#..## ...#...... .###.####. Tile 2557: .#.##..#.. ..##.....# #.#.#....# ..##...#.. ...#..##.# .......... ##......## #..#...... #.#..#...# ##.#####.. Tile 2269: .#.#...##. #.......## #.....##.. ##.#...... #.##..###. .#.....##. ....#....# ....#...## #..##..... #.#.#.#.## Tile 3511: .#.#.##... .#.....##. .#....#..# #.#......# #.#.#..... #........# ..#....... .##.#..... ##.#.....# ..####..## Tile 2789: #......#.. #...#..... #......... .......#.# ...#....## #.##..###. #...##...# .........# .........# .###..##.. Tile 2971: #.##.#.... ...#.....# .#....#... #.#..##... #.....#... ####.....# #..###..## #....#.... #..#.##... #.#..###.. Tile 3719: #.###..... ...#.....# ...##...## .#..#.#..# #..#.#..#. #.#..#..## #...###..# .#.#..#.## ........#. #....###.. Tile 1901: .#...##.## #......... .#.#.....# #.##.....# #........# #....#...# .....##.## ##.###..## ....#....# ....##..## Tile 3191: #.#..###.# #...#..##. #.....#... .#.#.#.... .#..##.... #.....#.#. .##....... ....#....# #..##.#... ####....## Tile 3709: ..#......# #..#...#.# #.##....#. .#..#.##.. ..#......# #....##... ##........ ....#....# .........# .#.#..###. Tile 1613: ...##..##. #......#.. ..##.#..## ......##.. .#..#..##. .......##. .......#.# ...#.#.... #......#.# ###..#.... Tile 2441: ..#.###### #.#....... #..#.#.... ....#...## #...#...## #.##...#.# ........## #.#...#... #..####.## #.##.####. Tile 1409: ..####.#.# ..##....#. ..#.#...#. ..##.##... .#.##....# #.....##.# ####.....# ###....#.. ####..#.#. #..##.##.# Tile 1523: .#.##..##. #..#.#.... ##.#.#...# ....#.##.# #........# #.#....... #...##...# ...#..##.# #.##...#.. .####..#.. Tile 1367: #..#...#.# #.#....... ..#..#.... .###..###. ###..#.##. ##...#..#. #..#...#.# ......##.. ##.....#.# .#####..## Tile 1783: ...#.####. .####..#.. #....#.### #.#..#.#.# #.#.#.#..# #.......## #.##.#.#.. .#.#....#. #..#.#...# .###..##.# Tile 1871: .##..#.##. #........# #...#....# ##.#..##.. ##.....##. #.....#.## ........## ....#....# #......... ....#.#..# Tile 3217: #.#...#.## .........# .........# #...#..... #....#.#.# .........# ...#.##.## #...#..... .#..#....# #..###.#.# Tile 3163: ...##.#.## #.#......# ....#...## #.......## ###..#.#.. .#....#### ##....#.## #.......#. .....#..#. .##.#.#.## Tile 3271: ##.#.#.##. ##....##.# #.#.##..## #.#...##.# .##......# #.....#.#. #........# ##..##.... #.#..##..# #..#.####. Tile 2707: ..###.#... #...#..... #.#..#.... #..##...## .###...... .#..##...# #...#..... ....#..... #..#.#.... .##....#.# Tile 3083: ##..#.#.## #..#....## .........# ..#.#...## ..#....... .#.#.....# ..#..#.#.. #...#.#..# #..#.#.... #.###..##. Tile 1051: ####...##. ...#.#...# .......... ..#....... #......#.. .#.##.##.. #....#.#.# #..#.#...# #.#..##..# ......###. Tile 3767: .#..##.### ...#.#.... ..#.....#. #.#....... .#.....#.# ##..#....# #...#..#.# ........## #........# ..#....##. Tile 2267: .#..#..#.. .#.#.#.... .#......#. #...#....# .###..#... .##.#...## ..#.##.##. ...#.#.##. ##.#.##..# .#.##..... Tile 1973: #.#####..# .#.......# #..#.#..#. #.#.#.#.#. .##....... #.#.....#. .#.......# #...##.#.# ##.......# .##...#### Tile 3671: #..##.#.## ....##...# .###.##... .........# #..#.....# ..##...#.. ......#... ..#..#..## ..#....... ##..###..# Tile 3221: #.#..###.# #..#....## #..#...... #...#...## ..#..#..#. #..##...#. ...#....#. .....#..#. ##..#..#.. .....#...# Tile 1549: .###.##..# #.#.##...# #....#.... .......... #.#......# ##.#.#..## ...#.#..## ........#. #.#....### #....#...# Tile 3461: .######..# #.......## .......#.. .#...#.... ..##....#. #.....##.. ##.#.#..#. .........# ##.##.#... ....#...## Tile 2459: ..##.##.#. ...#..#... .........# #.#..#..## #.###.#... ##.#...... .......#.. .........# ........## #.##...#.. Tile 3203: .#...####. ..##..#.#. #..#..##.. #.#....##. ...#.#.... .......### #.....##.. ....#....# #......#.. ###....... Tile 2203: #.#..##.## .......#.. ......#.## #.......## #..##.##.# ..#.....## #.##.....# #.#....#.. .##.....## ......#... Tile 3637: #...###.#. #......... ..#....... ...#.....# #..##....# #........# .......#.. #....#.#.. #.#..##..# ..#.#..##. Tile 2467: ..##.##... ##....#### ...#.#.#.# #.##...#.# ...##.##.. #.....#... ##........ ..#...#.#. #...####.# #......### Tile 2411: ...##....# ...##..### ...##.#### #.#..##.#. ..##.#.### .#..#.###. ....####.# .....##.#. #......... .#..#..### Tile 2221: ####.....# #.#.....## .#....#... .#.#...... .##..#..#. ....#..... .........# ##.......# #....#.... .##.###### Tile 1487: ..#..##... .........# #..#...### ....#...#. .#...##.#. .....#.#.# .....##... #.##...... #.#....... #.#####.#. Tile 1481: #.###.##.. ....##...# ....#..... ...#...... ##.###.#.# #.##..#### ..#......# .#....##.# ..##.##.#. .#####.#.# Tile 1669: #...##.##. ...#..#... .##..#.#.# #..#..#..# #......#.# .#......## ........#. ......#..# .##..#.#.# ##.##....# Tile 3167: .#.####... .........# #......##. .....#.... ..#.#...## #.#.####.# ...#....#. .........# #...#.#..# #.#.#.#.#. Tile 3347: ###...##.. #.#......# ...#.....# .......... #.#.....#. ..####..## ..#.#.#..# ##...#..#. ..##.....# #..#....#. Tile 2213: #..#####.# .......... #..#.##.#. ...###.#.# ......##.. ......#..# .##.....## ..#....### ...####..# .####.#.## Tile 3329: ..##...#.. #.#....#.# #...#..#.. ......#.## #...####.# .......... ##....##.# #......##. ....##...# ..####.##. Tile 3851: #.#....##. .........# #.....#... ##.##..... ...#.###.. #....##... .....#.##. .#........ #......#.# ...#..#..# Tile 2659: #.#...#.#. .....#.##. #..##.#### #.#.##.... #....#..#. ...#...#.. ...#....#. #....#.#.. .##.#....# .....#..#. Tile 1933: .####.##.. #..####... .#..####.. .#.#.##... ......#.#. ##........ .#.#.....# #..#...... ....#..... ...#...##. Tile 3299: ###.##..#. .......#.. ...#...##. ###...#.## ......##.. ....#.#..# .###...... .#.#####.. #..#.#..#. .....#.#.# Tile 3691: ...###...# #......... #.#.....## #.#....#.. #..#...#.. .......... ##...##..# .#...#...# #.....#.## .###..#... Tile 3733: #..#.##### .....#.... ....###..# #..#.#.... #.#..#.### ..###...## ......#.## ...###.... ...#....#. ..##...... Tile 2131: ##.#..#.#. .#...#..## #.......#. ....##...# .###..#... ...#####.. .....#...# ##..#..##. ..##....#. .#...####. Tile 1723: .....##### .#.#..#... ##......#. #.......## .###...#.. #..#...... #......... ......#..# .........# .###.##.## Tile 3463: ##.#....## #....##..# ..#.#..... #.#...#..# #....#.... ..#....#.# #...#..### ##....#.## ..#.#..... .#..#.##.. Tile 2549: #.####.#.. ...##....# ##..#.##.# ..###.#..# #.#......# #........# ....#..... #......#.# #....####. ...##.#.## Tile 1031: #..#.#.#.# ......##.. #........# .###...... ..#..#..#. ##....##.. ......#... ...#...### .###...#.. .##.#.###. Tile 1979: #.######.. .#.#.....# #........# #..##..... ##........ ##.....#.. ......#... .........# .#........ ..#.#####. Tile 2939: #.#...#.## .#..#....# .#.....#.# ##......## ...#..##.. #....#.##. #...##.#.# ..#...#... ##.....#.. .....##.#. Tile 2381: ..##.###.# ..##...#.. .#...#.... #......#.# ##.......# #..####... ...#.#.#.# #.##.....# ..#......# #..#.##... Tile 3943: #.#.###..# .......### #.#...###. #..##.#..# #......#.. #.##...#.# #......... ##....##.# ....#.#... .###.#.... Tile 1553: #####.#### #...#..... #.#.....#. ##......#. #....#.#.. .#.....#.# ##....#.#. #........# .........# .#.....##. Tile 2351: .###.###.. #.....#... ##.##....# ..#..##.#. #.#....... #....#.... ......##.# ##...##..# .#.....#.. .#.###..#. Tile 2311: #.#.#..##. #..###.#.. ...##..#.# ###....... ##........ #.#....... ..##.....# .#.####... ..#.#.#... ###..##.#. Tile 1567: ..###.#.## .#.....### #...#..##. #.......#. .......#.. #....#.... ...#.##.#. ....#...## ....#....# #.#...##.. Tile 2579: #.##..##.. #......#.. #..#..#..# ##.......# ....##.#.# #.####..#. #..#..#.## #...#..#.# ...##...#. #..#.###.. Tile 3593: .#.##.#.## #...#....# .......... ##....#..# ##......## #......... ......#..# ...#.....# ....#....# ##..###..# Tile 2281: ##....###. ...#...... #......#.# ##.#..#..# ###.#..##. .#...#...# .......... .#.###.#.. #..#...... #..#.##.#. Tile 1193: .......### ##..#..#.. .###...### ....#.###. ..#...#..# #.#....#.. ...####..# #....#..## .#.......# .#.#...##. Tile 3833: ...#####.. #..####... #.#....### ...##.#.## ..#...#..# .##.#####. #..#..#..# #...##.... .....#.#.. .##.##.#.# Tile 2003: .#.###.#.. .........# ..#..#.... #......... #..##....# .......#.# ......#... #....##..# .#......## ..#..##.#. Tile 2731: #.#..#..## ....#..#.# ..#...#... ..#..#.... #.#..#...# #....##... #......... #..##..#.# #......... .###.#.... Tile 3881: ..##...... #...#..#.# ##...#.... ....#..... ##.......# .....##### ...#....## .........# .......... #..##.#### Tile 3673: ##..###.#. ...##....# ###.....## #..#...#.# #.##...... ..#.#..... ..#.#....# .###.....# .###.##... ###.#..#.# Tile 1021: #..###.#.. ###..##.#. #..##....# .....###.. ....##...# ....#..... #.##..#..# .......... .......#.# ..#.##..#. Tile 2423: #.....#### .##.#....# .#........ ##.....#.. #.....###. #...#...#. #...#..#.# .#..#..##. ##.......# .#####.### Tile 3923: ..#....### #.....#..# #...#.#.#. .#.......# #..#.#.... .......#.# ##....##.# .#..#...#. #...##..#. ..#.#.#..# Tile 2753: ..####..#. #.......#. #.##.#..## #.#.#..... #..#...... ....#.#... .#.#..#..# #.....#..# ##.#..#... #####....# Tile 3929: ....#####. ##..#.##.. ##.#.#.##. ##...#.#.. #........# .##.#..#.. #..#.##... ##..#...#. .....#...# ###..####. Tile 3041: .##.#..#.# #..#...#.. ###..#..#. .#.#....## ...##..... #....#..## #........# ##.#...#.. ##....#..# ...#..#..# Tile 3433: ..#.#.#... #.#....... .....#.... ..#......# #..#.....# ........## ##..##.##. ##........ #.#.##..## ###.###..# Tile 2719: ..##..#..# #.##..##.. #......#.. #...##..## ..#..#.#.# #......### ..###..#.. ....#.#..# ....##...# ##..#..### Tile 1201: .#...##.## #........# ##...##... .......... .....#.#.. #.##.....# ...#.##..# .........# .#.#.....# .##...#... Tile 1129: ...####..# ......##.. #.....##.. #.......#. #......#.. ...##....# ........## ##.#.#.#.. ...#..##.# ...##....# Tile 3019: ..#...###. .....#.##. #.##.....# .#.##..#.. .#..###..# ..#.####.# #..#.#...# .......#.# #..##.#..# #.##....## Tile 1747: ##.###.#.. #.......#. #...#..#.# ##...##.#. ..###.#..# #..#..##.. #...#..... ..#....... ...#..#.#. .##..##.## Tile 1741: .##.#..#.# #...##..## #....#.#.# ##...##..# ##.......# #...#..##. ...#.##.## ...#..#.#. .......#.# .#####.### Tile 1867: #..##..... .......### #..##....# ##...#.... ...###.... ##..#..... .##....... #.....###. #...#..#.# ...###.... Tile 2803: .#.##....# #.####..#. #......... #.#......# .......#.# ........#. ..#..#.#.# ....###... #...##.... ...###.... Tile 3643: #..#..#.## ####.#..#. #.#...#.## .#..#..... ##....#..# .##....... .......#.# ...##.#... .....#.##. #...####.# Tile 2437: ..###..### ....#..... .......... #.#..#.### ##...####. ....##.... ...##..... ##..#.##.. #......#.. #.#.....#. Tile 1069: ..####.... ##..##...# .#..#..##. .#....##.# ###.#.#.## ...##..#.# ##....#... #.#....#.# .#.....#.# #.#.#..... Tile 1381: .###.#.##. ....#..#.. #.......## #...#..... .#...#..## ...#....## #..#.###.. ..######.# #....#...# #######.#. Tile 2617: ..##..#.#. #.....##.# ..#.#..#.. .##.#..#.. ###...#.#. .###.##... #.#....... #..##.#..# ##.....#.. .##..#..## Tile 2393: .##..#.#.# ..#.#..### ..##..#.## ....#..... #...#..... ##.#.....# .#.#..#.#. ##.....#.. .......#.# ####..#... Tile 3529: #.#...##.# ......#..# .........# #.....#... .......#.. .....#.#.# .....#.... #....#.#.# ....#.##.# .####.#..# Tile 2953: ...##...#. ##.#.#..## #...#..... ##.#...### ...#...... #.#.#..#.# .#...#...# ##....#.## .......#.. .#.#..#... Tile 3617: #..##...## ......#... #....#.... .......... .######.## ##..#.#.## #.#...#... ........#. .######.## ##...###.# Tile 3863: .##.#...## #...#..... ..#.#....# #....#..## .....###.. #.#......# #.......#. ...#.....# #......... ..###....# Tile 3727: #.###.##.# .......... ...##..... ..#..#..## #......### #....##... ###.##.... .....#.... ##.####.#. #..#.#.### Tile 3803: ###..#.##. .##......# .........# ###.....## ....###..# .......#.# ........## #..#...... ##......## #.###..#.. Tile 1579: #...##.### .....#.### .##...#... #.#..#..#. ..##.....# .........# .......... #.....#.## .....#.... .###..#... Tile 1049: #..#.##.## ##......## ..#.##...# #.......#. ###.....#. .....#.#.# ...#...... ..##...... #.#....#.. ##..#.#... Tile 2687: ##..#.##.. .#........ ##..#...#. .#.#.....# .#..#.#..# #.###..#.. ..#......# #.......## #..#.....# #.##.#..## Tile 1637: #..##...## ##..#....# ...#....#. #....#.... .....#...# #...#...## .#....#... #......... ..#....#.. .#.####... Tile 3527: .#....#.#. #.......#. ..#....#.# ####.#.#.# ...#..#... ###..#.### ##..#....# #.##....## ..#......# .....#.#.. Tile 2963: #.#.#.#.#. #.....#... ##.#.....# ..##...... ..#....... .#...#.##. ###......# ##....#..# .#...#..## ..##..##.# Tile 2287: ##.######. .#.##.##.. #..#....## ##.#.#...# .......##. #...##...# ...##..#.. ##....#.#. ....#.##.. ..#.#..### Tile 3677: ###.....## #..#.#..#. #.#....... .....#..## .......... ......#.## .....#..#. #..#...#.. .##......# #...##.##. Tile 3559: ..#..#.##. ###......# ..#.##.... #.#..#.... ##..##..## ..#...#.#. #.....#.## ....#....# ...#.#...# ...#.###.. Tile 2837: ..#...#... .....##... #.#..#...# ....#....# ...####.## #......... ...#...##. .#..###.#. ....#..... .###.##.#. Tile 3539: ..##....#. ........#. ......#..# ...#..#... ###....### #...#..... .#........ #.....#... ..##.#..#. ..###..#.# Tile 1667: .#..####.. .....#.... ......#... #.#...##.# #...#.#..# ##.#.#...# ##..#..#.. #...##...# .#..###... ..#..####. Tile 2791: #.##.###.# ...#..#... ##.....### ...#.#..## .........# .###...#.. ...#.....# ##.....##. ###....... #..#.#.... Tile 2609: ..##.#.... ##.#.#...# #.#..#.... #......... ...#..#..# #...#.#... ##.##....# .###...... ##.....##. #.#...#.#. Tile 3061: ####..#.## #.....##.. .......... ......#... ..#.#..### .#.#..#..# .#...#...# #........# .....#.#.. #..#....## ================================================ FILE: exm/aoc/2020/aoc_2020_21.txt ================================================ mxc ssdszsn phc llj nhnd fqqcnm njrcfg mrczqmj zfnttf tqkfx zvq rftbr jgbk kmlkx tzdks czvphx qpbl fzlrf zmsdzh qfslcb psqc rfx vnjxs lkgln sqhvzg qzjrtl hfzqf qhtvsr zdthsvl cgflg nggbtk mxq rdkrtr djdhrn nkzqj lcrs mhrlx hpbnj blvfz djhj ssrgt lpvfv fslqkg rzcps njdb jbtlfv cncpbssj lsgqf hbdv gbhjv drtdz flndv gpjr xqgb xvjk zjbgp rjc bfnnnrn gcptp prksl xdcp pdt xtgjslz fgptl kdm njqrhcc nqvnn lxldx spnd nlqhlsn tcclbr gpqgkt jfrlp hddd bmqzgvr rfxgl fgsr hjvzcp mxzb hqd (contains eggs, fish, peanuts) zcphr pcslhrg strpjp hbbgk nqvnn rtq jqzklv fnlk mhrlx fgsr bvlb gpqgkt fqqcnm dhsssf pdhlzg dchvb njdb rms zppxp pdt nfgr th jbz tktj rtpff xvjk fqtc ldrgj jbtlfv hzmk tqkfx nppxr qzjrtl nlqhlsn qfslcb xbvrx jhv ssrgt xqgb nbgv kmlkx chgjqc nthsf vhjgg mcl fzlrf lzvh pmhhqrk hjzkg lpvfv jgbk xsk blvfz thtlt nfck lftqn mxq flndv lsgqf njqrhcc mrczqmj nnskqnmn rjc zfnttf sqhvzg rfxgl zmsdzh rxd zbxj phc rtmfg bfnnnrn kdm dfcgd (contains peanuts) vhjpjdr nxrgp pdj njdb fgsr zmsdzh fctmvrs dfcgd nnskqnmn cvbc rxd th fgptl fqqcnm xqgb nkzqj dkg phc qpbl dgxnc fnlk llj tktj nlqhlsn bkzbrm lzvh rfgf fgcd nppxr vxmrk mhrlx pcslhrg czvphx hfzqf dxrsgs jbz dxdrk chgjqc tqkfx nfgr snzxr frxmq hjzkg mgv lsgqf jhbnm rjc xtgjslz sxsxm gvdstsc pdt lpvfv zbxj (contains wheat, dairy) xdcp njrcfg blvfz kdbxxzv tcclbr jhbnm rlgr njqrhcc nggbtk rntk phc zmsdzh lxldx qfslcb psqc mzrx ggrc hqd mrczqmj jp mxq sqhvzg bggmsj mcl gcptp jgbk tzdks hbbgk llj smdlg tqkfx pdt jqgm jhv vnjxs gcpks cqqcd hrnvd rjc rfgf jlrt bvlb njdb rdkrtr dxrsgs czvphx flndv nppxr gvdstsc nlqhlsn hdtr gpqgkt fgcd lzvh bvcxfp dchvb spnd jsh gbhjv vhjgg bjcvpc prbk rng zvq nthsf kjjst pdj zdthsvl pdhlzg lsgqf mgv vbkb ssrgt jxvx (contains nuts, dairy) jqgm prksl psqc lftqn jlrt jqzklv fppgp ldrgj cgflg xsk gpqgkt rjc sfkcp zmsdzh njqrhcc nppxr tcclbr snzxr hbdv npftghk phc hbmvpmt bjcvpc czmml bkzbrm ggrc pdt blvfz spnd smdlg mbmtz gcptp hpbnj jbz lsgqf czkfv gqnxlr nhnd chgjqc rzcps jhv fnlk gcpks nlqhlsn fslqkg rsr hjvzcp cvbc rdkrtr zdthsvl nxrgp hjzkg vbkb nfgr fgcd tktj czvphx qhtvsr hcjkd qfslcb hqd fqqcnm nhzthvn sxsxm (contains fish, sesame, soy) zmsdzh dxrsgs qrpzt tzdks bggmsj chgjqc cgflg sxsxm zppxp jbtlfv bvcxfp pdj hbmvpmt fzlrf lxldx llj dgxnc hfzqf hqzcncv gbhjv spnd phc hjzkg dhsssf fqtc xtgjslz nfck thtlt tcclbr xdcp djdhrn zjbgp nhnd kdm ksrjn mxq rng pdt dxdrk rtpff sqhvzg ldrgj kjjst rjc jp lsgqf flndv ggrc njqrhcc gpqgkt mrczqmj mxc rftbr psqc lzvh nmps (contains soy) jfrlp hqd mxq fnlk cncpbssj nnskqnmn rzcps hbmvpmt pdt zmsdzh pfrqf zfnttf zjbgp dchvb jp mzbgp phc qpbl qdkk nqvnn rsr xbvrx sfkcp cqqcd cgflg dhsssf rlgr vnbfvkp hrnvd lsgqf ldrgj nxrgp qzjrtl czmml nthsf fqqcnm kmlkx lpm xvjk nbgv rfx fctmvrs qjhq njdb pdhlzg xsk rbjmdn tzdks spnd chgjqc bvlb jqzklv lzvh jxvx rxd kjjst jvhsj vxmrk (contains dairy, peanuts) njqrhcc mxc mgv phc fzlrf spnd jvhsj kmlkx cldgd fgsr vnjxs ksrjn fqtc qjhq nfgr bmqzgvr pdhlzg frxmq gcptp rdjdq vbkb fgptl npftghk dxrsgs fgcd qdkk qzjrtl lpvfv hfzqf fqqcnm lzvh hpbnj hzmk jqzklv ktnlk tktj vhjpjdr llj fppgp zmsdzh hjzkg jbz cqqcd rtq hbdv njrcfg fslqkg jfrlp smdlg dhsssf qhtvsr rjc lsgqf jhv rftbr xgpdnz (contains wheat, dairy, eggs) zmsdzh sjpzc tkhzz kdbxxzv tqkfx fslqkg rtpff nbgv prksl nxrgp pdt zfnttf qdkk rjc vnbfvkp nppxr fppgp spnd bkzbrm rftbr mzbgp llj nfgr xtgjslz lpvfv zjbgp fctmvrs zgvtn xfn nvmm rntk jhbnm frxmq strpjp cqqcd phc dfcgd nggbtk kdm sxsxm gbhjv cldgd qjhq th jlrt rdjdq mzrx hqd jsh vhjgg nlqhlsn vxmrk zcphr lzvh mcl dhsssf bggmsj kjjst fqqcnm (contains nuts, dairy) zbxj jlrt lxldx jqgm zfnttf rdkrtr smdlg mcl fctmvrs vhjgg vbkb fqtc nlqhlsn czmml bxqpgx hpbnj fzlrf spnd pdj flndv phc pdt rzcps mzbgp gcpks ldrgj rtmfg zjbgp lzvh hjvzcp rfxgl czkfv gpqgkt bkzbrm jhbnm dxrsgs xdcp hbdv xvjk lpm lkgln gqnxlr kmlkx nfgr jbtlfv fgsr prksl jfrlp nthsf drtdz dfcgd dgxnc dhsssf rjc tkhzz tktj xgpdnz zmsdzh nhzthvn fslqkg bmqzgvr hrnvd lsgqf bjcvpc mbmtz mxc nbgv th bggmsj nqvnn nnskqnmn mxq rlgr rtpff kjjst pfrqf (contains nuts, soy) tktj jbz rbjmdn zcphr fqqcnm djdhrn smdlg nkzqj qdkk vnbfvkp rtmfg fnlk jqgm tkhzz rdkrtr hpbnj nhzthvn rjc czkfv lftqn cldgd fgsr rfxgl lkgln bvpxc lsgqf kdm blvfz spnd nlqhlsn xvjk nmps lzvh nvmm snzxr psqc vnjxs sfkcp pdt rfgf gcptp zdthsvl mrczqmj hqzcncv pcslhrg djhj hqd bggmsj nfck hdtr bxqpgx jsh rtpff jqzklv qlkfvk phc jfrlp strpjp (contains dairy, wheat, peanuts) hbmvpmt psqc pfrqf gvdstsc chgjqc cgflg pdhlzg gcptp nmps tktj frxmq mzbgp pdt mcl fppgp jqzklv mhrlx ssrgt tcclbr rzcps nhzthvn rjc rfxgl fqqcnm gqnxlr gpqgkt fgsr hqzcncv spnd nbgv nhnd mxc xtgjslz nfgr vbkb zjbgp jgbk nppxr rfgf dxrsgs nqvnn hfzqf gcpks jlrt rdkrtr rntk rlgr rxd kjjst flndv lxldx phc jqgm zmsdzh hrnvd zdthsvl drtdz rfx qpbl lzvh xbvrx gpjr hbdv tzdks blvfz smdlg gbhjv pmhhqrk nnskqnmn rtq prksl qfslcb ggrc nthsf bggmsj zppxp (contains eggs, fish) nthsf pmhhqrk gpjr zmsdzh jhv zfnttf vhjpjdr rtmfg cvbc nvmm vbkb bmqzgvr lftqn prksl rjc bfnnnrn qzjrtl pdj hrnvd jbtlfv mgv kdm xtgjslz nkzqj mhrlx fgcd kmlkx qrpzt xfn rntk fppgp fqqcnm dgxnc nggbtk bjcvpc nppxr qfslcb fctmvrs pdt njqrhcc rdkrtr ldrgj rfxgl jgbk spnd phc rfx lkgln rtq xdcp jhbnm prbk jqhn hfzqf mxc rms mxzb rtpff tqkfx fslqkg jbz hbmvpmt hbdv rfgf lzvh (contains fish) gcpks mrczqmj rtq gpjr npftghk hbbgk lxldx xtgjslz njrcfg hjvzcp kdm jp sfkcp bvcxfp xdcp nqvnn tkhzz czvphx ssdszsn xvjk zmsdzh chgjqc rdkrtr hqd qrpzt mbmtz frxmq pdt zppxp nmps hdtr dfcgd nbgv gbhjv th rsr lsgqf fqqcnm rjc cldgd flndv bjcvpc zfnttf zgvtn rms fslqkg phc rtpff hjzkg rlgr dxrsgs nvmm zcphr rxd nxrgp zdthsvl jhbnm jqhn qfslcb lftqn psqc czkfv pcslhrg fqtc xsk nnskqnmn mxq qdkk spnd lcrs ksrjn kmlkx ldrgj nfgr nlqhlsn cvbc djhj thtlt bmqzgvr lpvfv qpbl xqgb (contains dairy, soy, peanuts) prbk thtlt fqqcnm rjc tkhzz hcjkd blvfz xvjk njrcfg nnskqnmn xfn xdcp czkxlg hzmk bvlb ssdszsn xsk mbmtz spnd zjbgp lzvh lsgqf rtq kjjst xgpdnz bxqpgx czmml gpjr ggrc ktnlk jbtlfv pmhhqrk nkzqj phc zbxj fzlrf dgxnc lcrs xbvrx rdkrtr rfxgl hqd gbhjv vbkb pdt nfck qdkk jlrt (contains soy, nuts) qhtvsr mxc prksl jhv cvbc dkg drtdz gpqgkt jbtlfv rdkrtr qfslcb phc ssdszsn dchvb fppgp djdhrn tktj tkhzz jbz njqrhcc dhsssf lftqn mrczqmj jgbk lcrs hrnvd fqqcnm jqzklv rfx hjvzcp czkxlg pcslhrg kdbxxzv zvq spnd qzjrtl lzvh vxmrk hbmvpmt bxqpgx zmsdzh qdkk pfrqf jsh strpjp th njdb pdt sjpzc bfnnnrn lxldx nbgv hbbgk rjc (contains fish) sfkcp njqrhcc xvjk lpm rfgf fctmvrs spnd djdhrn nhnd zmsdzh njrcfg gvdstsc zjbgp nthsf prbk njdb jqzklv hdtr dxrsgs phc thtlt nppxr mxc fqqcnm gbhjv lcrs mzrx pdhlzg frxmq hbmvpmt nggbtk rdkrtr zdthsvl smdlg nfck nhzthvn pdt dkg xqgb bmqzgvr sjpzc qfslcb hjzkg llj nqvnn rjc lzvh rtq kmlkx hzmk rfx xbvrx fgptl (contains nuts, fish, peanuts) xgpdnz hqzcncv tkhzz lpvfv hpbnj fgsr zbxj rjc rms rntk ssdszsn tktj bvlb snzxr hrnvd xbvrx rxd rfxgl spnd mrczqmj gcpks cgflg lzvh zjbgp hzmk rng lpm rdjdq hdtr fqqcnm zmsdzh fctmvrs qzjrtl gbhjv nvmm zdthsvl blvfz xvjk lsgqf jvhsj cvbc phc jqgm jqzklv gpjr nbgv gqnxlr xfn zcphr (contains fish, eggs, sesame) pmhhqrk vhjpjdr rjc lcrs xvjk lpm dxdrk rtq vhjgg gbhjv lzvh vbkb pdt njdb fgcd bxqpgx npftghk ktnlk sqhvzg rlgr bvpxc ssrgt jbtlfv gpjr hfzqf fgsr xqgb bggmsj nmps lxldx djhj nppxr jhbnm pcslhrg mgv jgbk nlqhlsn fqtc qrpzt jfrlp mzbgp fnlk nvmm cgflg ggrc kdm zppxp nnskqnmn jqgm fctmvrs hrnvd vnbfvkp rtmfg nxrgp phc ssdszsn xbvrx rzcps rftbr ldrgj hdtr mrczqmj rtpff lkgln zgvtn hbdv czvphx spnd qpbl zvq zmsdzh rbjmdn tqkfx rdjdq tkhzz dchvb rfxgl fqqcnm (contains soy, nuts, eggs) bvpxc chgjqc bggmsj rfgf qpbl fgcd bmqzgvr frxmq tktj lsgqf mxzb mzbgp bxqpgx gvdstsc rzcps hbbgk drtdz vhjgg fqqcnm rntk mbmtz spnd vxmrk thtlt nhzthvn mgv jp cncpbssj sqhvzg lftqn nmps lpm nggbtk hdtr xvjk pdt kdbxxzv qlkfvk zmsdzh fzlrf cldgd jqhn ktnlk npftghk prbk qhtvsr smdlg hqzcncv gqnxlr nthsf nvmm zvq nnskqnmn mhrlx rtq phc xtgjslz qrpzt gcptp rfx mxq hjvzcp rjc lkgln zgvtn xqgb (contains nuts) mcl xvjk xsk sjpzc rsr zmsdzh zjbgp drtdz zcphr zvq jhv qfslcb fzlrf lcrs tqkfx rfgf prbk xqgb rjc spnd dchvb tcclbr strpjp flndv njqrhcc hfzqf pdt dkg lzvh gcpks hjvzcp lsgqf fgptl mzbgp sxsxm nvmm phc rng frxmq dxrsgs nnskqnmn nhnd bvcxfp (contains nuts, eggs) rtq jfrlp dchvb fppgp jp xtgjslz sfkcp zppxp rzcps spnd mbmtz llj rbjmdn rsr nbgv lsgqf jqzklv mxc lxldx hdtr njrcfg phc gbhjv nthsf dkg nhnd lcrs fqqcnm hcjkd fgptl dfcgd dxdrk pdt nlqhlsn zmsdzh hbbgk pmhhqrk rjc pdhlzg dgxnc zfnttf jbtlfv nmps bmqzgvr fgcd jhbnm flndv hzmk chgjqc dhsssf nnskqnmn cldgd (contains nuts, peanuts) sjpzc cvbc zcphr gpqgkt lsgqf ggrc rtmfg hrnvd cldgd ssdszsn tktj chgjqc zjbgp spnd njqrhcc hjvzcp mkxbf dgxnc ldrgj dxdrk nqvnn mzbgp ssrgt mbmtz nfgr jp pdhlzg hbdv gcpks xtgjslz sqhvzg ksrjn mcl zmsdzh fppgp dxrsgs blvfz lftqn jhv czvphx jlrt lpm bjcvpc jvhsj pdt zppxp bvlb zvq djdhrn nggbtk phc qfslcb tqkfx nmps nppxr jxvx rzcps vhjpjdr bvpxc snzxr lzvh fqqcnm qrpzt sxsxm (contains wheat, fish) strpjp dxrsgs qlkfvk cgflg sxsxm hpbnj lsgqf mgv prbk prksl zmsdzh rtpff xfn czkfv dgxnc nfck ldrgj cncpbssj pfrqf zppxp bggmsj qzjrtl xvjk kjjst mbmtz sjpzc lftqn lkgln mxc rtmfg rdjdq hqzcncv jqgm psqc nxrgp hzmk rntk rms th kdm nthsf hjzkg dkg sqhvzg zvq gpqgkt qrpzt pdt zcphr rfxgl mrczqmj jbtlfv ssdszsn blvfz bvlb dfcgd nmps thtlt fqqcnm jp zfnttf fnlk frxmq rlgr hbbgk vbkb xgpdnz vhjgg czvphx vxmrk fgptl cldgd lpvfv lcrs pdhlzg hddd spnd phc pcslhrg rjc (contains eggs, peanuts, dairy) zfnttf spnd rfx vbkb sfkcp tkhzz zmsdzh rfxgl dgxnc lsgqf sqhvzg phc bvpxc rlgr dxrsgs pdt vnbfvkp lftqn rfgf hcjkd fgsr nkzqj xgpdnz pmhhqrk tqkfx dfcgd cncpbssj rdkrtr qlkfvk blvfz xsk nfgr rsr czmml rtq bvcxfp kmlkx zdthsvl hzmk rjc xvjk gcpks tktj xfn prbk kdbxxzv fqqcnm mxc hjvzcp jp (contains peanuts) nfck nnskqnmn rtpff sqhvzg lsgqf dfcgd hcjkd cvbc fzlrf bvpxc rftbr dgxnc jlrt cncpbssj cgflg fslqkg pdt nbgv xdcp nqvnn rsr jxvx hqzcncv mrczqmj gpjr fqqcnm zmsdzh cldgd qfslcb czkfv bfnnnrn prbk fqtc zjbgp qhtvsr rdkrtr bvcxfp tkhzz rfx smdlg nggbtk mzbgp qpbl nvmm th snzxr gbhjv rng vxmrk mbmtz mhrlx blvfz rzcps qrpzt nhnd lxldx gcptp zgvtn njdb kjjst mcl npftghk rjc jqhn cqqcd prksl lzvh phc vnbfvkp psqc jgbk zvq hfzqf (contains nuts, fish) hcjkd rzcps fnlk fzlrf dgxnc cqqcd hbdv jvhsj lsgqf rxd bvcxfp lpvfv qpbl mrczqmj jqgm mxq jqhn hfzqf zmsdzh rjc lzvh nfgr vhjgg rntk rbjmdn ssdszsn tktj pdhlzg sqhvzg tqkfx czkxlg rfxgl gpqgkt njdb dkg strpjp zdthsvl nbgv lkgln vnbfvkp rfgf pcslhrg fppgp bmqzgvr hqzcncv rng dfcgd xbvrx qdkk hzmk vhjpjdr qlkfvk rms gqnxlr hdtr jlrt kdm sjpzc qhtvsr bvlb nppxr pdt vxmrk fqqcnm jxvx qrpzt thtlt zgvtn phc ksrjn fslqkg (contains soy, peanuts, fish) rsr hfzqf fctmvrs zjbgp qdkk qjhq rfx hqzcncv nfgr nhzthvn xbvrx jhbnm pdt rng rdjdq pdj nnskqnmn jhv bfnnnrn kdm cldgd nppxr nthsf lzvh czvphx vhjgg hdtr mbmtz mgv jbz mhrlx fppgp rlgr ssrgt jvhsj tktj fqqcnm zbxj nvmm qzjrtl czmml ggrc zmsdzh tkhzz dxdrk jp mrczqmj phc kmlkx jqzklv nhnd rftbr thtlt pcslhrg hbmvpmt jsh nmps nggbtk rtq nqvnn lkgln snzxr xdcp fqtc lsgqf spnd mxzb llj gbhjv (contains fish) spnd rng lsgqf nkzqj gbhjv mhrlx mcl hzmk sfkcp bfnnnrn qpbl dkg dxdrk nmps kdm djdhrn xbvrx rlgr tcclbr drtdz fqqcnm dhsssf gcptp kdbxxzv zcphr vnjxs mrczqmj rms kjjst bvlb fgsr bkzbrm jhv gpqgkt ssdszsn qjhq th zmsdzh kmlkx rjc hqzcncv rxd mxc jhbnm nggbtk bjcvpc njrcfg lftqn jbz jqhn jbtlfv hbmvpmt rsr nqvnn pdhlzg rzcps hdtr nnskqnmn rntk ssrgt qrpzt llj thtlt mbmtz mxzb pdt hfzqf nxrgp zdthsvl lxldx lzvh (contains peanuts) rfgf hddd rng ssrgt tzdks zjbgp blvfz spnd lzvh ldrgj fqqcnm fnlk bvcxfp gcptp dkg bfnnnrn zfnttf kdbxxzv gpjr rntk jsh nxrgp njdb xtgjslz dhsssf dxdrk lpm nnskqnmn lcrs mzrx nvmm jp prksl rzcps xgpdnz czmml rbjmdn mxq qhtvsr dgxnc bxqpgx mbmtz nmps bmqzgvr dfcgd pdt xbvrx njrcfg rfx fppgp fgptl fzlrf qrpzt zmsdzh cncpbssj tkhzz phc mkxbf rjc njqrhcc cqqcd tqkfx mxc nhzthvn hzmk pdj (contains fish) rms qrpzt hbbgk sxsxm dchvb jqhn gcptp xqgb psqc fctmvrs nlqhlsn tktj rntk qfslcb xdcp rfxgl fqqcnm jlrt zgvtn fgcd bvlb cvbc xbvrx rdkrtr rlgr prbk zmsdzh ssrgt phc tcclbr lpvfv djhj rsr rfx blvfz lzvh gpqgkt hpbnj bfnnnrn dxdrk nmps cncpbssj hjzkg hrnvd hbdv dgxnc hdtr rjc rdjdq jxvx qpbl zvq rtmfg jhbnm vhjpjdr nvmm lsgqf czkxlg pdt prksl xgpdnz rbjmdn gcpks fgsr zjbgp frxmq (contains soy, fish, peanuts) drtdz nbgv hcjkd mxq sqhvzg xfn nfck phc gcptp hdtr nnskqnmn tqkfx rfxgl jqhn lpvfv blvfz czkxlg djhj lsgqf bggmsj flndv kmlkx mxzb czmml vnjxs spnd dchvb lzvh fzlrf bkzbrm xbvrx prbk ksrjn rxd fqqcnm xgpdnz pdt jfrlp bvpxc fgptl ktnlk njdb zmsdzh (contains nuts, wheat, fish) vxmrk fqqcnm rlgr prbk fgsr tktj gqnxlr ssrgt phc rng gcpks mzrx dxdrk njqrhcc czmml cgflg qjhq vnjxs prksl ktnlk tcclbr qhtvsr sjpzc bggmsj nhzthvn zmsdzh ggrc jp rfgf rtpff zcphr lsgqf spnd blvfz rjc tkhzz sxsxm xfn pdt xqgb mrczqmj zdthsvl jhbnm bvcxfp ssdszsn djhj npftghk (contains nuts, eggs, sesame) sfkcp bvpxc rfgf bjcvpc bggmsj jbz zppxp gpqgkt mgv lzvh qjhq hbbgk mrczqmj zmsdzh rlgr cvbc qzjrtl rbjmdn mxc czmml fqqcnm hfzqf jfrlp nhzthvn fctmvrs lftqn tcclbr djdhrn rjc cgflg spnd sjpzc phc pmhhqrk fslqkg flndv hzmk nvmm jp prksl dkg gcptp pdt (contains fish) dchvb nppxr njdb fqqcnm hbbgk strpjp bvcxfp nhnd rjc hpbnj tkhzz jqzklv spnd vbkb jqgm phc pdt bxqpgx kdbxxzv zmsdzh xgpdnz rfxgl kdm drtdz nhzthvn ldrgj rdkrtr thtlt cvbc mhrlx bggmsj hjvzcp sjpzc nbgv gcptp hqd lcrs hddd djhj ssdszsn tqkfx xtgjslz mzbgp rdjdq nnskqnmn hqzcncv hjzkg jfrlp mxq nmps pmhhqrk pdj th fgcd psqc lsgqf gcpks xfn fgptl nfck mkxbf mbmtz rxd blvfz ggrc zppxp mcl ksrjn zbxj nkzqj hbdv lpm dxdrk zcphr qhtvsr pcslhrg tktj (contains sesame) lzvh psqc rjc nhzthvn tqkfx lcrs pfrqf lkgln spnd nhnd pmhhqrk lxldx hqd dchvb zvq vnbfvkp mcl rsr rdkrtr hpbnj rfgf fzlrf ssrgt phc djdhrn fppgp rftbr xqgb hbdv vbkb tktj jqgm sfkcp pdt bggmsj bmqzgvr zfnttf jbtlfv nxrgp flndv sxsxm lsgqf zbxj dfcgd nmps mxc bvpxc rbjmdn gbhjv dxrsgs sjpzc jp fgcd zmsdzh jhbnm vxmrk bjcvpc zcphr gqnxlr njdb nvmm jqzklv kdbxxzv jsh xtgjslz gcpks rntk qpbl djhj lftqn ldrgj xfn hdtr tzdks tcclbr gcptp nnskqnmn (contains eggs, soy) gpqgkt lftqn frxmq dchvb hbdv gvdstsc djdhrn ssrgt drtdz rjc gpjr jvhsj rfxgl hqd spnd rtpff mzrx qfslcb cgflg jqhn strpjp zcphr xtgjslz lsgqf pcslhrg smdlg czmml nqvnn fqtc qpbl dkg phc xfn fgsr fppgp dgxnc cqqcd qzjrtl ggrc lkgln ksrjn nvmm qdkk rxd jlrt jhbnm nhnd lpm hjvzcp bfnnnrn pmhhqrk rdjdq hcjkd czvphx xbvrx zgvtn dxrsgs fqqcnm zmsdzh njqrhcc lzvh rzcps fzlrf (contains sesame, soy) jgbk gvdstsc spnd rtmfg psqc njdb drtdz thtlt dxrsgs cldgd hjvzcp nggbtk dfcgd nppxr mbmtz gcpks rdjdq lzvh czvphx rjc vnbfvkp mhrlx frxmq bfnnnrn kmlkx qpbl lsgqf ldrgj qrpzt jp bvpxc phc zmsdzh jbtlfv nhzthvn rsr jxvx th rzcps kdbxxzv xgpdnz nqvnn rdkrtr pmhhqrk pdt prbk rbjmdn fgptl gpjr zbxj czmml tqkfx xdcp njqrhcc cncpbssj chgjqc fgcd (contains nuts, dairy, eggs) ================================================ FILE: exm/aoc/2020/aoc_2020_21_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 21 ------------------------------------------- -- Allergen Assessment -- -- https://adventofcode.com/2020/day/21 -- -- Full Ada version. -- -- Main obstacles for using HAC: -- - lack of 'Value (or at least 'Image) attribute -- - lack of logical operators on arrays of Boolean -- with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . procedure AoC_2020_21_full_Ada is -- Enumerated types created by removing duplicates from data. -- See: AoC_2020_21_full_Ada_Preproc. type Ingredient is (bfnnnrn, bggmsj, bjcvpc, bkzbrm, blvfz, bmqzgvr, bvcxfp, bvlb, bvpxc, bxqpgx, cgflg, chgjqc, cldgd, cncpbssj, cqqcd, cvbc, czkfv, czkxlg, czmml, czvphx, dchvb, dfcgd, dgxnc, dhsssf, djdhrn, djhj, dkg, drtdz, dxdrk, dxrsgs, fctmvrs, fgcd, fgptl, fgsr, flndv, fnlk, fppgp, fqqcnm, fqtc, frxmq, fslqkg, fzlrf, gbhjv, gcpks, gcptp, ggrc, gpjr, gpqgkt, gqnxlr, gvdstsc, hbbgk, hbdv, hbmvpmt, hcjkd, hddd, hdtr, hfzqf, hjvzcp, hjzkg, hpbnj, hqd, hqzcncv, hrnvd, hzmk, jbtlfv, jbz, jfrlp, jgbk, jhbnm, jhv, jlrt, jp, jqgm, jqhn, jqzklv, jsh, jvhsj, jxvx, kdbxxzv, kdm, kjjst, kmlkx, ksrjn, ktnlk, lcrs, ldrgj, lftqn, lkgln, llj, lpm, lpvfv, lsgqf, lxldx, lzvh, mbmtz, mcl, mgv, mhrlx, mkxbf, mrczqmj, mxc, mxq, mxzb, mzbgp, mzrx, nbgv, nfck, nfgr, nggbtk, nhnd, nhzthvn, njdb, njqrhcc, njrcfg, nkzqj, nlqhlsn, nmps, nnskqnmn, npftghk, nppxr, nqvnn, nthsf, nvmm, nxrgp, pcslhrg, pdhlzg, pdj, pdt, pfrqf, phc, pmhhqrk, prbk, prksl, psqc, qdkk, qfslcb, qhtvsr, qjhq, qlkfvk, qpbl, qrpzt, qzjrtl, rbjmdn, rdjdq, rdkrtr, rfgf, rftbr, rfx, rfxgl, rjc, rlgr, rms, rng, rntk, rsr, rtmfg, rtpff, rtq, rxd, rzcps, sfkcp, sjpzc, smdlg, snzxr, spnd, sqhvzg, ssdszsn, ssrgt, strpjp, sxsxm, tcclbr, th, thtlt, tkhzz, tktj, tqkfx, tzdks, vbkb, vhjgg, vhjpjdr, vnbfvkp, vnjxs, vxmrk, xbvrx, xdcp, xfn, xgpdnz, xqgb, xsk, xtgjslz, xvjk, zbxj, zcphr, zdthsvl, zfnttf, zgvtn, zjbgp, zmsdzh, zppxp, zvq); type Allergen is (dairy, eggs, fish, nuts, peanuts, sesame, soy, wheat); use HAT; name : constant VString := +"aoc_2020_21.txt"; -- type Ingredient is (fvjkl, kfcds, mxmxvkd, nhms, sbzzf, sqjhc, trh); -- type Allergen is (dairy, fish, soy); -- name : constant VString := +"mini.txt"; type Ingredient_Set is array (Ingredient) of Boolean; type Allergen_Set is array (Allergen) of Boolean; type Food is record ingr : Ingredient_Set; allr : Allergen_Set; end record; food_list_max : constant := 100; foods : Natural := 0; type Food_List_Type is array (1 .. food_list_max) of Food; food_list : Food_List_Type; verbose : constant Boolean := True; generic type Enum is (<>); type Enum_Set is array (Enum) of Boolean; procedure Gen_Count (set : Enum_Set; total : out Natural; last : out Enum; verb : Boolean); procedure Gen_Count (set : Enum_Set; total : out Natural; last : out Enum; verb : Boolean) is begin total := 0; for e in set'Range loop if set (e) then if verb then Put (" " & e'Image); end if; last := e; total := total + 1; end if; end loop; if verb then Put (total'Image & " "); end if; end Gen_Count; procedure Count is new Gen_Count (Ingredient, Ingredient_Set); i_of_a : array (Allergen) of Ingredient; procedure Find_Allergens_Ingredients (total_1 : out Natural) is -- In a food ingrendient list, not all allergen are listed. -- But when an allergen is listed, its associated ingredient IS listed, among others. i_for_a : array (Allergen) of Ingredient_Set := (others => (others => True)); -- An allergen is done when the set of possible ingredients is reduced to 1. done : array (Allergen) of Boolean := (others => False); total : Natural; i : Ingredient; scrap : Food_List_Type := food_list; to_solve : Natural := Allergen'Pos (Allergen'Last) + 1; begin loop for f in 1 .. foods loop for a in Allergen loop if scrap (f).allr (a) then -- Allergen a is in the food #f. -- Then we can narrow the set of possible ingredients for a. i_for_a (a) := i_for_a (a) and scrap (f).ingr; end if; end loop; end loop; -- for a in Allergen loop if not done (a) then if verbose then Put (" " & a'Image & " can only be in ingredients: "); end if; Count (i_for_a (a), total, i, verbose); if verbose then New_Line; end if; if total = 1 then -- Hurra, allergen a is ONLY in ONE ingredient, i. -- We apply now the rule "Each allergen is found in exactly ONE ingredient." for f in 1 .. foods loop -- Remove allergenic a and ingredient i everywhere. scrap (f).allr (a) := False; scrap (f).ingr (i) := False; end loop; if verbose then Put_Line (" -> allergen " & a'Image & " associated to ingredient " & i'Image); end if; to_solve := to_solve - 1; done (a) := True; i_of_a (a) := i; end if; end if; end loop; exit when to_solve = 0; end loop; -- total_1 := 0; for f in 1 .. foods loop for i in Ingredient loop if scrap (f).ingr (i) then -- Unassociated ingredient. total_1 := total_1 + 1; end if; end loop; end loop; end Find_Allergens_Ingredients; procedure Read_Data is f : File_Type; s, s1, s2, key : VString; i, paren : Integer; begin Open (f, name); while not End_Of_File (f) loop foods := foods + 1; food_list (foods).ingr := (others => False); food_list (foods).allr := (others => False); Get_Line (f, s); paren := Index (s, "(contains "); s1 := Slice (s, 1, paren - 1); s2 := Slice (s, paren + 10, Length (s)); loop i := Index (s1, " "); exit when i = 0; key := Slice (s1, 1, i - 1); food_list (foods).ingr (Ingredient'Value (VStr_Pkg.To_String (key))) := True; s1 := Slice (s1, i + 1, Length (s1)); end loop; loop i := Index (s2, ", "); exit when i = 0; key := Slice (s2, 1, i - 1); food_list (foods).allr (Allergen'Value (VStr_Pkg.To_String (key))) := True; s2 := Slice (s2, i + 2, Length (s2)); end loop; key := Slice (s2, 1, Length (s2) - 1); food_list (foods).allr (Allergen'Value (VStr_Pkg.To_String (key))) := True; end loop; Close (f); end Read_Data; total_n : Natural; begin Read_Data; Find_Allergens_Ingredients (total_n); Put_Line (+"Part 1: ingredients without known allergens: " & total_n); Put ("Part 2: list of ingredients sorted by allergen's name: "); for i of i_of_a loop Put (To_Lower (+i'Image) & ','); end loop; New_Line; end AoC_2020_21_full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_21_full_ada_preproc.adb ================================================ -- Preparation of Advent of Code 2020, Day 21 ---------------------------------------------- -- -- https://adventofcode.com/2020/day/21 -- with Ada.Containers.Ordered_Maps, Ada.Text_IO; with HAT; -- in ../../../src procedure AoC_2020_21_full_Ada_Preproc is use HAT; package Name_Mapping is new Ada.Containers.Ordered_Maps (VString, VString); ingredient_map, allergen_map : Name_Mapping.Map; i : Integer; f : File_Type; s, s1, s2, key : VString; paren : Integer; begin Open (f, "aoc_2020_21.txt"); while not End_Of_File (f) loop Get_Line (f, s); paren := Index (s, "(contains "); s1 := Slice (s, 1, paren - 1); s2 := Slice (s, paren + 10, Length (s)); loop i := Index (s1, " "); exit when i = 0; key := Slice (s1, 1, i - 1); ingredient_map.Include (key, key); s1 := Slice (s1, i + 1, Length (s1)); end loop; loop i := Index (s2, ", "); exit when i = 0; key := Slice (s2, 1, i - 1); allergen_map.Include (key, key); s2 := Slice (s2, i + 2, Length (s2)); end loop; key := Slice (s2, 1, Length (s2) - 1); allergen_map.Include (key, key); end loop; Close (f); Put (" type Ingredient is ("); for ingr of ingredient_map loop Put (ingr & ", "); if Integer (Ada.Text_IO.Col) > 70 then New_Line; Put (" "); end if; end loop; New_Line; Put (" type Allergen is ("); for aller of allergen_map loop Put (aller & ", "); end loop; New_Line; end AoC_2020_21_full_Ada_Preproc; ================================================ FILE: exm/aoc/2020/aoc_2020_22.adb ================================================ -- Solution to Advent of Code 2020, Day 22 ------------------------------------------- -- Crab Combat -- -- https://adventofcode.com/2020/day/22 -- -- HAC 0.083 "nice to have"'s detected in this exercise: -- -- * comparison (equality operators) "=", "/=" of composite types (arrays and records) with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . procedure AoC_2020_22 is use HAT; max_deck : constant := 50; type Cards is array (1 .. max_deck) of Natural; type Deck is record top : Natural; card : Cards; end record; type Deck_Pair is array (1 .. 2) of Deck; verbosity : constant := 0; procedure Play ( g : in out Deck_Pair; winner : out Positive; is_recursive : in Boolean; recursion_level : in Positive -- For information only ) is -- "The winner keeps both cards, placing them on the bottom -- of their own deck so that the winner's card is above -- the other card." procedure Move_Top_Cards (winner, loser : in out Deck) is top_card_winner, top_card_loser : Positive; begin top_card_winner := winner.card (winner.top); top_card_loser := loser.card (loser.top); loser.top := loser.top - 1; winner.top := winner.top + 1; for i in reverse 3 .. winner.top loop winner.card (i) := winner.card (i - 2); end loop; winner.card (1) := top_card_loser; winner.card (2) := top_card_winner; end Move_Top_Cards; -- sub : Deck_Pair; top_card : array (1 .. 2) of Positive; round_win : Positive; round : Natural := 0; type Game_Mem is array (1 .. 1000) of Deck_Pair; -- A size 100_000 is needed for the "real" data, otherwise -- we would not be able to memorize enough the past decks. -- But the needed stack for HAC would be huge and would -- slow down the initialization part of the interpreter. -- Better to switch to "full Ada" at this point. -- See AoC_2020_22_full_Ada (file: aoc_2020_22_full_ada.adb). mem : Game_Mem; -- function Equal (g, h : Deck_Pair) return Boolean is begin for player in 1 .. 2 loop if g (player).top /= h (player).top then return False; end if; for i in 1 .. g (player).top loop if g (player).card (i) /= h (player).card (i) then return False; end if; end loop; end loop; return True; end Equal; -- begin if verbosity > 1 and recursion_level > 6 then Put_Line (+"level=" & recursion_level); end if; loop round := round + 1; mem (round) := g; -- -- Recursion breaker (first rule of Recursive Combat). -- if is_recursive then for i in 1 .. round - 1 loop if Equal (mem (i), g) then winner := 1; return; end if; end loop; end if; -- -- Draw cards. -- for p in 1 .. 2 loop top_card (p) := g (p).card (g (p).top); end loop; if is_recursive and g (1).top - 1 >= top_card (1) and g (2).top - 1 >= top_card (2) then -- Copy parts of the decks for the sub-game. -- -- "To play a sub-game of Recursive Combat, each player creates -- a new deck by making a copy of the next cards in their deck -- (the quantity of cards copied is equal to the number on the -- card they drew to trigger the sub-game)." for p in 1 .. 2 loop for i in 1 .. top_card (p) loop sub (p).card (i) := g (p).card (g (p).top - 1 + i - top_card (p)); end loop; sub (p).top := top_card (p); end loop; Play (sub, round_win, is_recursive, recursion_level + 1); elsif top_card (1) > top_card (2) then round_win := 1; else round_win := 2; end if; if round_win = 1 then Move_Top_Cards (g (1), g (2)); else Move_Top_Cards (g (2), g (1)); end if; exit when g (1).top = 0 or g (2).top = 0; end loop; if g (1).top > 0 then winner := 1; else winner := 2; end if; end Play; -- procedure Show (a : Deck) is begin for i in 1 .. a.top loop Put_Line (+" card " & i & ": " & a.card (i)); end loop; end Show; -- function Score (a : Deck) return Natural is res : Natural := 0; begin for i in 1 .. a.top loop res := res + i * a.card (i); end loop; return res; end Score; -- procedure Read_Data (g : out Deck_Pair) is data : Deck_Pair; f : File_Type; s : VString; p : Natural := 0; begin Open (f, "aoc_2020_22.txt"); while not End_Of_File (f) loop Get_Line (f, s); if Head (s, 6) = "Player" then p := p + 1; data (p).top := 0; elsif s = "" then null; else data (p).top := data (p).top + 1; data (p).card (data (p).top) := Integer_Value (s); end if; end loop; Close (f); -- Invert the deck: top <-> bottom for p in 1 .. 2 loop g (p).top := data (p).top; for i in 1 .. g (p).top loop g (p).card (i) := data (p).card (1 + data (p).top - i); end loop; end loop; end Read_Data; -- winner : Positive; g, g_start : Deck_Pair; compiler_test_mode : constant Boolean := Argument_Count >= 1; begin Read_Data (g_start); g := g_start; Play (g, winner, False, 1); if verbosity > 0 then Put_Line (+"Winner is: " & winner); Show (g (winner)); end if; if compiler_test_mode then if Score (g (winner)) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Score: " & Score (g (winner))); end if; -- Part 1: validated by AoC: 31957 -- Part 2: validated by AoC: 33212. Part skipped (see remarks around Game_Mem). end AoC_2020_22; ================================================ FILE: exm/aoc/2020/aoc_2020_22.txt ================================================ Player 1: 26 16 33 8 5 46 12 47 39 27 50 10 34 20 23 11 43 14 18 1 48 28 31 38 41 Player 2: 45 7 9 4 15 19 49 3 36 25 24 2 21 37 35 44 29 13 32 22 17 30 42 40 6 ================================================ FILE: exm/aoc/2020/aoc_2020_22_full_ada.adb ================================================ -- Solution to Advent of Code 2020, Day 22 ------------------------------------------- -- Crab Combat -- -- https://adventofcode.com/2020/day/22 -- -- Full Ada version -- -- Run-time with GNAT, AoC_Build_Mode = "Fast": -- * 4.45 seconds for a i5-9400 @ 2.9 GHz using a heap-allocated -- fixed (100,000) size array for memorizing the previous decks -- * 1.25 seconds for a i5-9400 @ 2.9 GHz using a vector -- * 0.36 seconds for a i5-9400 @ 2.9 GHz using a hashed set with Ada.Containers.Hashed_Sets, Ada.Containers.Vectors; with HAT; -- ^ Files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . procedure AoC_2020_22_full_Ada is max_deck : constant := 50; type Cards is array (1 .. max_deck) of Natural; type Deck is record top : Natural; card : Cards; end record; type Deck_Pair is array (1 .. 2) of Deck; verbosity : constant := 0; use HAT; procedure Play ( g : in out Deck_Pair; winner : out Positive; is_recursive : in Boolean; recursion_level : in Positive -- For information only ) is -- "The winner keeps both cards, placing them on the bottom -- of their own deck so that the winner's card is above -- the other card." procedure Move_Top_Cards (winner, loser : in out Deck) is top_card_winner, top_card_loser : Positive; begin top_card_winner := winner.card (winner.top); top_card_loser := loser.card (loser.top); loser.top := loser.top - 1; winner.top := winner.top + 1; for i in reverse 3 .. winner.top loop winner.card (i) := winner.card (i - 2); end loop; winner.card (1) := top_card_loser; winner.card (2) := top_card_winner; end Move_Top_Cards; -- sub : Deck_Pair; top_card : array (1 .. 2) of Positive; round_win : Positive; round : Natural := 0; -- function Equal (g, h : Deck_Pair) return Boolean with Inline is begin for player in 1 .. 2 loop if g (player).top /= h (player).top then return False; end if; for i in 1 .. g (player).top loop if g (player).card (i) /= h (player).card (i) then return False; end if; end loop; end loop; return True; end Equal; -- function Hash (g : Deck_Pair) return Ada.Containers.Hash_Type with Inline is use Ada.Containers; knuth : constant := 2654435761; res : Hash_Type := 1; begin for player in 1 .. 2 loop res := knuth * res + Hash_Type (g (player).top); for i in 1 .. g (player).top loop res := knuth * res + Hash_Type (g (player).card (i)); end loop; end loop; return res; end Hash; -- -- We benchmark Vectors (linear search) vs. Hashed_Sets. -- type Memory_Type is (use_vectors, use_sets); mem_type_choice : constant Memory_Type := use_sets; -- package Game_Mem_Vectors is new Ada.Containers.Vectors (Positive, Deck_Pair); mem_vec : Game_Mem_Vectors.Vector; -- package Game_Mem_Sets is new Ada.Containers.Hashed_Sets (Deck_Pair, Hash, Equal, Equal); mem_set : Game_Mem_Sets.Set; -- begin if verbosity > 1 and recursion_level > 6 then Put_Line (+"level=" & recursion_level); end if; loop round := round + 1; -- -- Recursion breaker (first rule of Recursive Combat). -- if is_recursive then case mem_type_choice is when use_vectors => for mem of mem_vec loop if Equal (mem, g) then -- NB: the test `mem (i) = g` happens to work but is incorrect -- (compares cards above top) winner := 1; return; end if; end loop; mem_vec.Append (g); when use_sets => if mem_set.Contains (g) then winner := 1; return; end if; mem_set.Include (g); end case; end if; -- -- Draw cards. -- for p in 1 .. 2 loop top_card (p) := g (p).card (g (p).top); end loop; if is_recursive and g (1).top - 1 >= top_card (1) and g (2).top - 1 >= top_card (2) then -- Copy parts of the decks for the sub-game. -- -- "To play a sub-game of Recursive Combat, each player creates -- a new deck by making a copy of the next cards in their deck -- (the quantity of cards copied is equal to the number on the -- card they drew to trigger the sub-game)." for p in 1 .. 2 loop for i in 1 .. top_card (p) loop sub (p).card (i) := g (p).card (g (p).top - 1 + i - top_card (p)); end loop; sub (p).top := top_card (p); end loop; Play (sub, round_win, is_recursive, recursion_level + 1); elsif top_card (1) > top_card (2) then round_win := 1; else round_win := 2; end if; if round_win = 1 then Move_Top_Cards (g (1), g (2)); else Move_Top_Cards (g (2), g (1)); end if; exit when g (1).top = 0 or g (2).top = 0; end loop; if g (1).top > 0 then winner := 1; else winner := 2; end if; end Play; -- procedure Show (a : Deck) is begin for i in 1 .. a.top loop Put_Line (+" card " & i & ": " & a.card (i)); end loop; end Show; -- function Score (a : Deck) return Natural is res : Natural := 0; begin for i in 1 .. a.top loop res := res + i * a.card (i); end loop; return res; end Score; -- procedure Read_Data (g : out Deck_Pair) is data : Deck_Pair; f : File_Type; s : VString; p : Natural := 0; begin Open (f, "aoc_2020_22.txt"); while not End_Of_File (f) loop Get_Line (f, s); if Head (s, 6) = "Player" then p := p + 1; data (p).top := 0; elsif s = "" then null; else data (p).top := data (p).top + 1; data (p).card (data (p).top) := Integer_Value (s); end if; end loop; Close (f); -- Invert the deck: top <-> bottom for p in 1 .. 2 loop g (p).top := data (p).top; for i in 1 .. g (p).top loop g (p).card (i) := data (p).card (1 + data (p).top - i); end loop; end loop; end Read_Data; -- winner : Positive; g, g_start : Deck_Pair; begin Read_Data (g_start); for is_recursive in Boolean loop g := g_start; Play (g, winner, is_recursive, 1); if verbosity > 0 then Put_Line (+"Winner is: " & winner); Show (g (winner)); end if; Put_Line (+"Score: " & Score (g (winner))); end loop; -- Part 1: Validated by AoC: 31957 -- Part 2: Validated by AoC: 33212 end AoC_2020_22_full_Ada; ================================================ FILE: exm/aoc/2020/aoc_2020_23.adb ================================================ -- Solution to Advent of Code 2020, Day 23 ------------------------------------------- -- Crab Cups -- -- https://adventofcode.com/2020/day/23 -- -- In this version, we don't move the cups at all. -- We redefine which one is the next. -- -- Total run time for both parts, example & input: -- 0.58 second (GNAT AoC_Build_Mode_Type = "Fast", i5-9400 @ 2.9 GHz). -- 324.75 seconds (HAC, fastest build, same machine...). -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . with HAT; -- Interfaces is needed for compiling on both -- HAC and GNAT (64-bit integer: Integer_64): with Interfaces; procedure AoC_2020_23 is use HAT, Interfaces; max_cup_pos : constant := 9; subtype Cup_Range is Positive range 1 .. max_cup_pos; type Cup_Array is array (Cup_Range) of Cup_Range; function Play (c_init : Cup_Array; part : Positive) return Integer_64 is big_max : constant := 1_000_000; subtype Big_Cup_Range is Positive range 1 .. big_max; type Cup_Info is record label : Big_Cup_Range; next : Big_Cup_Range; end record; index_from_label : array (Cup_Range) of Big_Cup_Range; c : array (Big_Cup_Range) of Cup_Info; pick_label : array (1 .. 3) of Big_Cup_Range; current_index, cursor, pick_index, last_pick_index, after_pick_index, dest_index, dest_next_index : Big_Cup_Range := 1; -- ^ Initialization is just for removing a -- warning issued by the ObjectAda compiler. dest_label : Integer; found : Boolean; part_max, rounds : Positive; res : Integer_64 := 0; begin if part = 1 then part_max := max_cup_pos; rounds := 100; else part_max := big_max; rounds := 10_000_000; end if; for i in 1 .. part_max loop if i <= max_cup_pos then c (i).label := c_init (i); index_from_label (c (i).label) := i; else c (i).label := i; end if; c (i).next := 1 + i mod part_max; end loop; -- current_index := 1; Game : for round in 1 .. rounds loop -- The crab picks up the three cups that are immediately -- clockwise of the current cup. pick_index := c (current_index).next; cursor := pick_index; for j in 1 .. 3 loop pick_label (j) := c (cursor).label; last_pick_index := cursor; cursor := c (cursor).next; end loop; after_pick_index := cursor; -- They are removed from the circle; cup spacing is adjusted as -- necessary to maintain the circle. c (current_index).next := after_pick_index; -- The crab selects a destination cup: the cup with a label equal -- to the current cup's label minus one. dest_label := c (current_index).label - 1; -- loop -- If at any point in this process the value goes below the -- lowest value on any cup's label, it wraps around to the -- highest value on any cup's label instead. if dest_label < 1 then dest_label := part_max; end if; found := False; for i in 1 .. 3 loop if dest_label = pick_label (i) then found := True; exit; end if; end loop; exit when not found; -- If this would select one of the cups that was just picked up, -- the crab will keep subtracting one until it finds a cup that -- wasn't just picked up. dest_label := dest_label - 1; end loop; -- if dest_label <= max_cup_pos then dest_index := index_from_label (dest_label); else dest_index := dest_label; end if; -- The crab places the cups it just picked up so that they are -- immediately clockwise of the destination cup. They keep the -- same order as when they were picked up. dest_next_index := c (dest_index).next; c (dest_index).next := pick_index; c (last_pick_index).next := dest_next_index; -- current_index := c (current_index).next; end loop Game; -- if part = 1 then for i in 1 .. max_cup_pos loop if c (i).label = 1 then cursor := i; for count in 1 .. max_cup_pos - 1 loop cursor := c (cursor).next; res := 10 * res + Integer_64 (c (cursor).label); end loop; end if; end loop; else for i in 1 .. big_max loop if c (i).label = 1 then cursor := i; cursor := c (cursor).next; res := Integer_64 (c (cursor).label); Put (c (cursor).label, 0); Put (", "); cursor := c (cursor).next; Put (c (cursor).label, 0); res := res * Integer_64 (c (cursor).label); exit; end if; end loop; end if; return res; end Play; exm, inp : Cup_Array; res : Integer_64; compiler_test_mode : constant Boolean := Argument_Count >= 2; begin -- example 389125467 -- input 523764819 -- -- With full Ada we can write ` exm := (3,8,9,1,2,5,4,6,7); ` -- exm (1) := 3; exm (2) := 8; exm (3) := 9; exm (4) := 1; exm (5) := 2; exm (6) := 5; exm (7) := 4; exm (8) := 6; exm (9) := 7; -- inp (1) := 5; inp (2) := 2; inp (3) := 3; inp (4) := 7; inp (5) := 6; inp (6) := 4; inp (7) := 8; inp (8) := 1; inp (9) := 9; -- for part in 1 .. 2 loop if compiler_test_mode then if Play (exm, part) /= Integer_64'Value (To_String (Argument (1))) or Play (inp, part) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; exit; -- ^ This is for HAC & compiler testing: we skip part 2, takes too long. else Put (+"Part: " & part & ": labels on the "); if part = 1 then Put_Line ("cups after cup 1"); else Put_Line ("two cups that will end up immediately clockwise of cup 1"); end if; Put (" From example : "); res := Play (exm, part); if res > 0 then Put (Integer_64'Image (res)); end if; New_Line; -- Example, part 1: from AoC site: 67384529 -- Example, part 2: from AoC site: 149245887792 = 934001 * 159792 Put (" From input : "); res := Play (inp, part); if res > 0 then Put (Integer_64'Image (res)); end if; New_Line; -- Input, part 1: validated by AoC: 49576328 -- Input, part 2: validated by AoC: 511780369955 = 760147 * 673265 end if; end loop; end AoC_2020_23; ================================================ FILE: exm/aoc/2020/aoc_2020_23_simple_array.adb ================================================ -- Solution to Advent of Code 2020, Day 23 ------------------------------------------- -- Crab Cups -- -- https://adventofcode.com/2020/day/23 -- -- Moving the cups to fill the gaps is very time-consuming -- on large sizes (part 2 of the game). -- See AoC_2020_23 for a much more efficient solution. -- -- Total run time for both parts, example & input: -- 169 minutes (almost 3 hours) with -- GNAT, AoC_Build_Mode_Type = "Fast", i5-9400 @ 2.9 GHz. -- -- The linked list version takes 0.58 second on the same configuration. -- Then, the linked list version is more than 17,000 times faster! with HAT; use HAT; -- in ../../../src procedure AoC_2020_23_Simple_Array is max : constant := 9; subtype Cup_Range is Positive range 1 .. max; type Cup_Array is array (Cup_Range) of Cup_Range; procedure Play (c_init : Cup_Array; part : Positive) is big_max : constant := 1_000_000; subtype Big_Cup_Range is Positive range 1 .. big_max; c : array (Big_Cup_Range) of Big_Cup_Range; c_cur : Big_Cup_Range; pick : array (1 .. 3) of Big_Cup_Range; dest, gap : Integer; found : Boolean; part_max, rounds : Positive; begin if part = 1 then part_max := max; rounds := 100; else part_max := big_max; rounds := 10_000_000; end if; for i in 1 .. max loop c (i) := c_init (i); end loop; for i in max + 1 .. part_max loop c (i) := i; end loop; -- Game : for round in 1 .. rounds loop -- The crab picks up the three cups that are immediately -- clockwise of the current cup. for j in 1 .. 3 loop pick (j) := c (j + 1); end loop; -- They are removed from the circle; cup spacing is adjusted as -- necessary to maintain the circle. null; -- The crab selects a destination cup: the cup with a label equal -- to the current cup's label minus one. dest := c (1) - 1; loop -- If at any point in this process the value goes below the -- lowest value on any cup's label, it wraps around to the -- highest value on any cup's label instead. if dest < 1 then dest := part_max; end if; found := False; for i in 1 .. 3 loop if dest = pick (i) then found := True; exit; end if; end loop; exit when not found; -- If this would select one of the cups that was just picked up, -- the crab will keep subtracting one until it finds a cup that -- wasn't just picked up. dest := dest - 1; end loop; -- Remove & shift current focus by one (current slot is always 1) gap := 3; c_cur := c (1); for i in 1 .. part_max - 4 loop c (i + 3 - gap) := c (i + 4); if c (i) = dest then -- The crab places the cups it just picked up so that they are -- immediately clockwise of the destination cup. They keep the -- same order as when they were picked up. for j in 1 .. 3 loop c (i + j) := pick (j); end loop; gap := 0; end if; end loop; c (part_max) := c_cur; end loop Game; -- if part = 1 then for i in 1 .. max loop if c (i) = 1 then for j in 1 .. max - 1 loop Put (c (1 + (i + j - 1) mod max), 0); end loop; end if; end loop; else for i in 1 .. big_max loop if c (i) = 1 then Put (c (1 + i mod big_max), 0); Put (", "); Put (c (1 + (i + 1) mod big_max), 0); exit; end if; end loop; end if; New_Line; end Play; exm, inp : Cup_Array; begin -- example 389125467 -- input 523764819 -- -- With full Ada we can write ` exm := (3,8,9,1,2,5,4,6,7); ` -- exm (1) := 3; exm (2) := 8; exm (3) := 9; exm (4) := 1; exm (5) := 2; exm (6) := 5; exm (7) := 4; exm (8) := 6; exm (9) := 7; -- inp (1) := 5; inp (2) := 2; inp (3) := 3; inp (4) := 7; inp (5) := 6; inp (6) := 4; inp (7) := 8; inp (8) := 1; inp (9) := 9; -- for part in 1 .. 2 loop Put_Line (+"Part: " & part); Put (" From example : "); Play (exm, part); -- Part 1: from AoC site: 67384529 -- Part 2: from AoC site: 149245887792 Put (" From input : "); Play (inp, part); -- Part 1: validated by AoC: 49576328 -- Part 2: validated by AoC: 511780369955 end loop; end AoC_2020_23_Simple_Array; ================================================ FILE: exm/aoc/2020/aoc_2020_24.adb ================================================ -- Solution to Advent of Code 2020, Day 24 ------------------------------------------- -- Lobby Layout -- -- https://adventofcode.com/2020/day/24 -- -- NB: Was able to recycle parts from another "Game of Life" -- puzzle: Seating System (Day 11). -- As an hommage to John Conway, there are three -- "Game of Life" puzzles: Day 11, 17, 24. -- with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . procedure AoC_2020_24 is type Colour is (black, white); function Flip (c : Colour) return Colour is begin if c = white then return black; else return white; end if; end Flip; type Direction is (e, se, sw, w, nw, ne); type Position is record x, y : Integer; end record; move : array (Direction) of Position; -- (0, 1) (1, 1) -- nw ne -- \ / -- (-1, 0) w--(0, 0)--e (1, 0) -- / \ -- sw se -- (-1,-1) (0,-1) -- Full Ada: we define `move` in a single expression: -- move : constant array (Direction) of Position := -- ( -- nw => (0, 1), ne => (1, 1), -- -- w => (-1, 0), e => (1, 0), -- -- sw => (-1, -1), se => (0, -1) -- ); max : constant := 70; subtype Tile_Range is Integer range -max .. max; type Map_Type is array (Tile_Range, Tile_Range) of Colour; procedure Change (current_map : in Map_Type; new_map : out Map_Type) is function Count_Black (x, y : Tile_Range) return Natural is occ : Natural := 0; -- procedure Scan_Direction (dx, dy : Integer) is xx : constant Integer := x + dx; yy : constant Integer := y + dy; begin loop exit when xx not in Tile_Range; exit when yy not in Tile_Range; case current_map (xx, yy) is when black => occ := occ + 1; exit; when white => exit; end case; -- Adjacent only in this problem. -- xx := xx + dx; -- yy := yy + dx; end loop; end Scan_Direction; begin for d in Direction loop Scan_Direction (move (d).x, move (d).y); end loop; return occ; end Count_Black; -- count : Natural; begin for x in Tile_Range loop for y in Tile_Range loop new_map (x, y) := current_map (x, y); count := Count_Black (x, y); case current_map (x, y) is when black => if count = 0 or else count > 2 then new_map (x, y) := white; end if; when white => if count = 2 then new_map (x, y) := black; end if; end case; end loop; end loop; end Change; function Is_large_enough (m : Map_Type) return Boolean is begin for y in Tile_Range loop if m (-max, y) = black or else m (max, y) = black then return False; end if; end loop; for x in Tile_Range loop if m (x, -max) = black or else m (x, max) = black then return False; end if; end loop; return True; end Is_large_enough; function Count (m : Map_Type) return Natural is c : Natural := 0; begin for x in Tile_Range loop for y in Tile_Range loop if m (x, y) = black then c := c + 1; end if; end loop; end loop; return c; end Count; procedure Init_Move is -- This way of doing initialization is needed for HAC. begin move (e).x := 1; move (e).y := 0; move (se).x := 0; move (se).y := -1; move (sw).x := -1; move (sw).y := -1; move (w).x := -1; move (w).y := 0; move (nw).x := 0; move (nw).y := 1; move (ne).x := 1; move (ne).y := 1; end Init_Move; use HAT; procedure Read_Data (m : out Map_Type) is -- Initializations are just for removing warnings -- issued by the ObjectAda compiler. c, c2 : Character := ' '; i : Integer; f : File_Type; s : VString; d : Direction := e; p : Position; begin for x in Tile_Range loop for y in Tile_Range loop m (x, y) := white; end loop; end loop; -- Open (f, "aoc_2020_24.txt"); -- "input.txt" while not End_Of_File (f) loop Get_Line (f, s); p.x := 0; p.y := 0; i := 1; while i <= Length (s) loop c := Element (s, i); if c = 'n' or c = 's' then i := i + 1; c2 := Element (s, i); end if; i := i + 1; case c is when 'e' => d := e; when 'w' => d := w; when 'n' => if c2 = 'e' then d := ne; else d := nw; end if; when 's' => if c2 = 'e' then d := se; else d := sw; end if; when others => null; end case; p.x := p.x + move (d).x; p.y := p.y + move (d).y; end loop; m (p.x, p.y) := Flip (m (p.x, p.y)); end loop; Close (f); end Read_Data; rounds, count_1, count_2 : Natural; paving : array (Boolean) of Map_Type; state : Boolean := False; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := False; begin Init_Move; Read_Data (paving (state)); -- -- Part 1, count black tiles -- count_1 := Count (paving (state)); -- -- Part 2, hexagonal game of life -- if compiler_test_mode then rounds := 2; else rounds := 100; end if; -- for round in 1 .. rounds loop if Is_large_enough (paving (state)) then Change (paving (state), paving (not state)); else Put (+" Too small! max=" & max); return; end if; state := not state; if verbose then Put_Line (+"Round " & round & ": " & Count (paving (state))); end if; end loop; -- count_2 := Count (paving (state)); -- if compiler_test_mode then if count_1 /= Integer_Value (Argument (1)) or count_2 /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1 : number of black tiles at startup: " & count_1); Put_Line (+"Part 2 : number of black tiles after " & rounds & " rounds: " & count_2); -- Part 1: validated by AoC: 341 -- Part 2: validated by AoC: 3700 end if; end AoC_2020_24; ================================================ FILE: exm/aoc/2020/aoc_2020_24.txt ================================================ nenwswenweswweenesweeenenwee nwnwnwnwswenenenwneswneenwnenenwnenwsw weweeeeneneseswesesweeesenwnw wnwwwwwnwwnewsewnwenwwnww enwnwsenwnenwnwseenwswnweseswenwswnwsw nwseseswsenwseswseseswsenweseeeenwnwsese senwwwwnweeswewwwewwnenenwswse swnwneswnweneneneswneneeneswne ewsenwweneeeenwnwneneswnewwswesene sesenwsweseseswnenenwnweenwseenewee seswwwswwnwnwsewneenenenwnwneneseww nenenenenenenenenwsenewne swwnwswswswwswswswswswswswe nenwswnesesesesesesesesesesenwsenwsesesew wswwneswswswweeswswwwswnwswswseswnew wwwwwnwwewenwwwwswnwwew neenwnwnwnenenenenwenenwnwwwnwswswse swwneswswswswnwseswswswswswsw seseseenesewnwseseeswwseseeseneesesw nesenwswseswnwwseswwwseswwnenewswwwse wwwwwwswewww seenewewenwneswneneneneneneswnenee sesewnwsenwnwesesweneswseseseswnwsee nenwnenenwnwnwswnenwnwsenenwnenwwnwnwne seseswneeneeseeewwnwseesenwsenwsee seseeeeseseweesesesewnesesesenwsene swwswswseswwwswnewe swwswswswwseneswswseswswwnewswwwsw neeswneneneenenenene neeswseseswswnwwseswnwwswswseseseseseswne ewneneneenewewnenewseneenwneeesw enwnenwneeeeseeeeswenweeneseese nwwnwnwnwnwnwnenenenenenenenenwsenwsene nwseenwnwnwnenwnwwsenwnwne seseswsenwswseswswswseeseswse seswneswswswswswswswswwwswsw enesenenwesesweeweeswseseeseseew wwswnwweneswneenwsesesenwnwsenwwnw swnwwnwswwewsenewenwnewseswnwwww wswewnwwswwnwswswswswswwswsweswesww swesenwnweeneseseseswswwnwsewwenwswne wwwswwsewwwwswwwwwnw neeenwwwswnewnenwnwsenwsewwwww seneswswsewswneswswseswswseseseseewnwsese nenenenewneneneneneneneneeseneweese wswsweeswswwswswswswwswswwswwnwsw wwwseswnewswswswwwwwwsw wnwnwnwwnwnwnwnenwenenweneswsewenwnwnw wwweswewnewwnwswsewwwwwnwnenw nwnwsweneeeseeseeeseesesesenwseswese nwwswswswwswwswewwwwsenwswsenwsww senwnenwnwnwnwnwnwnwnwnwnwnwsw neswnwseswswswswswswswswswsweswwswe eeeeeeeseenwnweeseesweeeenw swseseseswswwnwneswewwnwnwseeswnwswwne neesenwseesesewwnwseeseseenwnesw neswswswwwswswsesweswswsw eeneeewsenweseeeweeeneswee nwnenweneewnwnwnwwnwwwswnwsenwnwnwnw newneeneseneneswnenwnenenesenewnwsw seseneeewsweneneeeneseneeeswwwene swswswswseswswwsesesesweswswswneneswsww eeeeswneneeewseewneeseeee neeeneneneeeneneewneewwwnesenene eneswnwnenwneeswwswneeeenenwenese seenwseseseeneeseseeseseseweseswsese seswnwswswenewnewnwswsw wwwwwwwwwwwneswswwwnewswse seeseswseseseswwsesese nenenewenenewesenesewesenwewnewne nwneseneeneseneswneneneewneewnee nenenwneneewewneeseneeneeneeese eswnwswwswsewweswwnwneswwwswww neseswnweeeeseeeswee wwwwnwswwwswswswnwsese wseseswswwswswswnweswswsesweseesw nwneneneeewewwneneneeeeeswese eesesesewnwseenweeeeesenweseswse neneneneenenwneswneneneneeeneee wswswsweeseswswswswwnwnwwsw wseewesenwnwneswnenweewneneswwnw nwneeswswseswwseseneswesenenwsenesww nwsewwwwswswwsenw swswswewswnwswwswswnwewswwseswww swswwwsewwnenesewwswswswwwwww nenwnwnwwnwnwnwnwnwnwenwswnwnwnwnwsenwnw neneneneneneneneneneneneneneswe nwwwswenwwneenwnwwswewnwwnwsww eseswseswwnwneswneswsesewswnenesesw wwwwwnwnwwwe senwenenewwnewswneewnesewsenenenesene sewewneewnwneenenenenweneese swswswewwwewneswswwswswswswwww swwnwneneenenenenwnwnenewnwseswnwsenenw swnenwneenenwnwnwnwsenwnwnwnwnwnwnwnwnw neswsesewswseeeneseswnwwswswsw ewwwwswwwswwneswwwewnwnewwsene nwnwnenwnwnwsewnweneswwswnwnwsenewnee ewneseeeeeeewenweseeeeeee nwseswwswseewwnwwwnwwnwwwseswene swswwswweswswewswswswsw nwnwneswnwneenwnwnwneswnenwnwnwnenenwne eswweeeeswseenewenwsenwesesese seswnwneswnenenwnwnwesenesenwswnenenwnene nenwnenenwwnenwnwnenwnwsenwnwswse newwwweswswswwswseenewwseseswnwsw nwwnwsesenwnwnesenwnwswnwewnwnenenwnwnw nwneneneneneneneeswnwnenenwne wnwnwsenwnesenenenenenwnenwne nenenwnenewnesenenewseneneeneneseenenesw wneneswnwnenwnwswneeseenwseswnesesenww swseswseseswseswneswseswsewseswsese weeesweeesenwseeee nenwswswnenwweswseseseewseneneseswe neweewneswneenweeneesweewnenene nesesweenenewneenenenewesenesenew swswswswseseswseswswswswswnw neneswwwwwwwwwwsewsenewwswww nenenenwnenenenewsenenesenenewnenwnwne neeneeswneeseeseenenwnwwseswewee swswswswnwseseswneseswseseswswswwnenesw neeswnenwneeeeweswswsweneneenwe wsenweswseenwsewsesenwsenesesesesesenesw seseswseseseswneswswse swnewswwwsesewswnewwwswwswswswww senewneneneseneenenenwewenwwnwswsw weseneneseseseeeweeseswsweenesese swnewwswnwseswswswseswswwwswswswswne neneeenenweneneswenenesenwewneenesw seseseseneseswseseswswsewsenwseseesesese nenenwnwnwnenwnenenesenenwwneneneene nwnwnwsenenenwneswwnwnwnesenwnenenenew neeeeeweneseeweweeneeneenee wneneeneneenewneneeeeseeneneseeswe eswwwnwwnwwnwwwwwwwenwswneswe eseswwsweseeeneenewe sesesweseseswsesesenwseseseseweseswne sewseseseseseseseeseseseneseesenesw swwneewswwwnwwswswwenwewnwnwnww eneneeeenwsenwnwesesweeeeswee wwwwwwswwswwnew swswwwswwnwewwnwneswwnwseneneww swnewnwnewnwwsweseeseswwswnenenwsee swewswswwswswswswseswswswswesweswswnw neswswseswswswswswswswneswswwnweswswe seeseseneseswswwsewseseenwsesenwseswsw esewneswnewwesewneswneneneneeenwe nesewnenesweneeeneneenenenenwnenenese nwnenwnwwnwnenwnenwnwneeeneswnwnwenww eeeeeeswwwwnesenenwenwsenewsw nwswweswsweswsenwneswewswwswnesenwsw sesenwseseseseesesesesesesesesesesw nenesenenwnenwnwwnenwneneswnewesenene swnwwswswwwnenwwseswwwwnewewsee esesewswswsenwswswswnenewsw nwnwnwwnwnwnwnwnwse eeneenenewsenenewwnenenenenenesenwe sweseswswseneseswswswnwswnwswswseswswse eeseneeneneneeenenweeeeswnwee swswwewswwwnenwseswwswswswswswswsww neswswswnwwswnwseswweswswwswsww nwswnenwnewnweseneneeswswneswnwnwnesene ewnenwswwwnwnwnwnwnwwswwwwwwne wswseseseeseswnwwenenwneswsenesenwse nwnenenwseneswswsee nenenenenenwnewswnwnenwswnwnwenenwnwe neweweweswesenweesesenw eenwneeeeenwwneeseseseseswwsese seeseneswseeseeeee nwneswswnwwweswnenewwnwneseseswwwse newwwswwnwwnwnww neneeneseswnwenenesweneeneneweeew wswswnwneswenesenwnwnewnwsenenwnenesenenw wneneeneseswnweseseneewswenwnenwsese nwsweswswswwsweswswsenwwenweswneenw seneswswswswswseswswswswswswneswswswnwswse wswswneneneswswswswwsewswwnew enwsenwsenwswswewnewewnwweseww wswswseswsewwswwwwwswwwwnwnew swneswswswewswswswwwseswswswswswwswnw seeneweseeseeeswseeneseneswnwweswse eeeseweswseweeeeeswsenwneewe swnweneneeneeeneeenenewneneeene eeeeneseeeseneeswsenenweewnwnw swswswnewwseswseswswswseseneswewnwswe nwswswneeseswneswnwnwswsesw wwnwwswwwsewwswwwww sweeneeeneenwesweseeeneenweee nwwswsenwnwswnwnwnwswseeseseneenenwse nwwnenwnwnwswwwwwnwnwww wwwswnwnesenesewwseneesenwneseewsw nwnweenwnwnwswnwwnenwwsweswnweswene nenwnwnwnwneenenewwneswnenese nenenwnewnwsenwnewsweenene nwneenwneswsweswneseeswswsenenenenwnw swswseswseseneseseseseseswswswsenenweswse senwswwsenwswsenwswswswswswswswswswww nwnwenwneswnwnwnwnwnenwnwnwnwnwnwnw nwnwwenewnwnwswswwe swsweseswseswnwnesesesenesewseswseswne swseneswswneswwswnenwwswseseswneswswseswsw swswseswswswswwwseswswneswswwnewswsw seswseswseneswseeswsenwswseswsesewswswse nenenenenewnenwnenenesenenesenenenenene wnwnwsenenwwnwnwnwwnwwnwswnwwwee nesesesesesesesenwsewseesesesewnesesese seesesesesenenwsesesesweesesesesese nwseeesweneswnenweswwwwnwnwnwnwswene wswwswnenwnenesweswneswswseswswswsesenenw eesweeeeeeeenw wnwwwnwsewwnwnwwnwwsenwnenwwewnw nwswnwsewswnwnewswwneenwnenwsewnenwnw nenweenwneneneneswswneswsenwnenenenenenwse nwnenenenenwnenesenewnesenenenenenenwne seeeeeeseswnweeee swswwwnwwwwewswwwwwswwewnw wswwwswswnwwneseswseswwnewwswwnwse sesesenewseeeseseswe wswwsewwwwneswswwwwwnewswsew eneeenweneneswnwneneeeneeeeese neenenwneeeneeeneneneneneeswnenesw nwswenwseeseesenenwneswseeesewesw sewwneswswwsewnwswnwswsewnenewwsww wseswwsenwnwnewsesenwwsenwneeswwnee nwswseeeseeesesew nwwsewnwnenwnwenwswswnwsewwesewe ewneeeeeeweeeeeesweeenwe neswswswwswswnwswnwseswswswwswseeseswsw seseneeseeseneseeeewseseswseseenwse nwnwnwnwsenwwnwnenwwnenwnwwnwnwswnww nwseweseseswnwweneseswseneswswswswswnw swwswwwswswnwwweswswwwewswww nwnwnwswsenenenwwwseswnwnwnwesenwnwwnww eeeseeeeseswenwnwee enewneneeneseeeneeneeeeseeeew nwwnwnwswseswwnwnewnesewwneswnwesenw neeseswwwnwswwneeseswnewenwswswswsw seseswseswnwnwenwsesenwneewwneseee seseswswswesesenwseswnwswsene nenwewneswneeeneneneseeeneneneee sesesesesenwseseswseswsesesewnwsenesesw nwnwswneswnwseenwnwswneswnwesesenwnwe nwnwenewsweswnwsesenenewwnwnweswnw nenwneneswseenenewsenwnwswnwwnwnwnenenew sewseseseseswseswnesesesesesesese neweeneeneneeeesenenwswswneneneneee eneneeswwseneneswnenweeweswnenwswnw senwswnenwnwnenenenwnewnwnenwsenwwnwnene neswneswsenwswsewseenweseeeewsesese seseseswseesewnweseeesenwseseswseenwse sewwsesewwwwwwwnewwwnwwnwnw nweneswnenwenwnenenenwnwnenwneswwnwnw neneeneneneswenwneswnwnenwnwnwnwwswnene nwwnwnwnwnenwnwnwnwnwswnwnwnwsenw swwnwewwwsewswsww eeseeseeeeseseseseswnwwseesesese enwsenwseswwnwnwnenwnwwnwnwnwsenwnenew ewneeneseneeseneneenwneneeneenenesw seseseswnwsenenwseese wswswwwwwneseww neewneeswsenwnwnwnenenwnenwswnwnenwnw neneseseswneswnwnwesenwnweenwnwnwswsenww wwwnwnwwseenwsewwwwewwnenwnwsw nwnenwnwwwwnwnwenwnwwnwswwnwenw swseswwneesesesewseseseesesesenwswsese swswseeseseseseswswswswswwswswseneswnwsw senenesweewnweesewweneneseneeene wwwwnewwwwwsewwsewswwwwnew ewsesesesesesesenwswsese swswwswswneeswnwswwseswswsee sewnwwnewnwnewwwwwnenwsesewwnwww nenwneneneneneneneneseneeneneneswnw nwneseseeeswweee swwnwswwewswwseeswenwswswswswswsw swswneseswswswswnwswswswseeswswswswnwne wnwnewneenenesesenesweswneeswenene nwseseseseseswnwwseeseseeseseseesese eswnwswwnwwewwwnwnwsewenenwwse ewwswwwnenwewewwesewewww swseneseswswswswwswswswnwswswswsweswswnw swwwswnwwweewnwsew eeeeseseewnweewsweeeeeee nwnwnwnwnenwsenwnenwewnenwewnwsewnwnwnw nwsewnwnwnwneswnenwnenwnenwnwnenwswesw swnwnwwwewwnwwewwwewwswnwnw eneeeesweewnenwnenesewewnee nwnwnwswwnwnwnwwwsenwwwne eeeseeeseeweseeseseweeesenwse eswsewswswswswswswswwswswnwswsw seseeeseeeeeeesenwsw esweeswsesewseeneseseseneeswnwsenesew swswswswnweneseeseswseswwswswswswswsw wwwwswwswwneswswwwsww swswwsweswnwswswswsw nenenwsewsenewnenewnenwnwswneseneseswe seseswseseswswswswswswneswwswsenenwsesw swsewsenesesenwseseseseenwseesenesesw enwwwswwnwesweswsenesewwswswwnw nwswnwnwnwnwnenwnwnwnwnwnwnwnesenweneswnww swswswewwswseseswswwnwnwnwswneeswnww wswneenwewnweneswneneneesw seeeseswwseeneseweeswnenweswsenew nwnwnewnewnwwwwwsewwnwwswnwwese eeswnenwswswswswwswswswsw nwnenwneneneneneswneenenenwnwnwnenwnwsw seseseeeeseeseseseeswswnenwwe swwnewnwsewnwwnenenwwnwwsesewwnwnew nwnwsewnwneenwnwnwnwnenwnwneswsenenwnw wwwwwswwewwwwewnewwweww wnwsenwwsewnwwwnwnwnesenewnwswnew swsenesesenesesesesesesesewswesesesese seseneswswwseseseseseswneswseswseseesese enesenenwseneseseswweseeseneswwwsese sesesesenesewseseesesesewwswneseseesw eeeseeeeweesenenweeseseswese swnwnwswnweswenesenwsenwseewneneswsesw sewswseenesesesenwnwsenenwseesesewnesw swswswswswsweswnewswswsesenenwswswnwsw enesweeeneseeseswwseeeenweese esenwwnwswseneneseswneseesenesewse swswsesewswnesewsewneseneseswswnesese eseweeswseeeeseesenenee newneswswwwswswwwwwwswnewwwwsesw nenenewswnwswnesenwnwnenenenwnwnwnenwne wseswnewsewswwnwswnewwwwwswwww wwwswwwnwwwwenwwnwwnww weeeeeesweenweswwneeeeeeee wneswswswnwswswsewswwsewsw seenwewseseseseseeseeesesesenweesw neswnenenwwnwenwnwnwnwwenenene wnewwseeswwnewneswnenwswwwwsww swswnwneswnweswseswswswswwwwsweswwsw wswsenwwswswwswwweneswswwswswswnew nwnwwwenwesenwseswnwnw seneneeeneenewe nwwnweenenwwnwnwsenwswnwnweswnenwswnwne nwnwnwnwsenwnwnwnenenwnwsenwnenwnwenwnww seswnwseswswseeneswwseseswseswswswseswsw swswneswwswswnewswwwnweswswnesesenw seswswseseswswsesenesw seseneswseseseseseesenesesesewsenenwsw neneneenenwswnwnwneneswnewnwnewnenwee seseswsewswnwseseswsesweseseeseswnesesw wwnenenwswsenwnwneneeswseeswew swwswnwnwseseseswnwseenenwseswnweswenw nwswwswswswswswswsweswnewsweseswswnesw sewwswwwnwwenwwnesenewnwswwswsene swseswsesesesenwseweseswseseswswsenwseese seseeseseesesenweeesweweesee wewswnwnwswenwnwswewseneneswsewwne esesenwseseenwswnewswenwseseseswnwswnw neswswseseseseseswseswswwnenwseseseswese seeeesesesesenwsenesewseesenwsesww swswseswsweswwswswswseswseswswnwswsw neeneeeneseeenwsweeeseeenwwne swwesesesenesenenewsesenewseesewsese nenwnwnwwwnwswnwnwsenwwwwnewwnwnw eweneeenweewsweeeeeeseneese newneswneneneeeseswneneswneneneswnwsw nweeeeeeeeweweeeeeesese sewnwwwwwewenwnwnwwwwwwwww nenewneenenenenwwnenwnenenenenenwe eswswnesesewneseseswnwwswne eeseesweeewseseeeneeese wneswsewwseesesenwneeseseswneswnwsesw swwswseswsesesweseswseswsw swswswwswswswsenwswswswswwswseswnenwswsw seneswweeneswnwneeneeeseweeew swswsweswnewnenesenwseseswswseseswsww nwnesewsweswwwsenewwnewwwwww ewneseseeeenewnenenweeneeswnene wwwwwwnwwwewseewnenwwwnwwsw wwwseswwsewswneswwneswwwwwwnw nenwnesenwnenwneenwnwnwnwnwnenwnwnwwsesw swneenwwswenwenweseeweeese nwwnwenwnweseswneewnwenwswnwwnwswnw nwwnwsenenwnwseneswnwneswnwnwnenwnenenenw nenenwnwsenenenenenenenwnenwnwnw nenwwseeneneswwsesenesenwnenenwsenenee nwwswswenwwnwsenwweneenwnenwnwwwww wnwswnewwwwwswnwnwwwnewwnwwswne nwsenwnwswnwnwswnenwnenenwnenwnwnwnwnenw ewnenenewneneneneenenenenwnenene nwsesesenwnwseeseseseseeseseesweesesw seeswnenesewnenwnenenwnenwneneneswenene seeeswenwseswneeese swenwenwswswseneswsenw wnwnwwnwnwsewnwnwnwnenwnwnwnwsewnenw nwwsenwnwsenenwnwnwnwnwnwnwwnwnenenwnenw sesesesenenwseeseseswseseseseswe swwwneseswswnewswwwswswswwnewswswww wwnwwnwnewnwnwswwnwwnwnw wsenwswesenwneswswseswswswewsweswswnw eeseneeeeesweeewwneeseeneesw ewnenwnwnwswnwnwwsewwwnwnwewsenwnww nwesewsesesweeseesenenesesewseseesese seesweewneseseseenwseswneswenwsesenwse weeneswnesweswenwwnwnewswsenwene nwnwnwwwnwwwsenwneweswswwenwnwsene nwnwnwnwwnwnwwnwnwwwswwwnwsewnwe swneneeswseenwseneswnweenewnweenenw eweeneswenweneenwsweeeene nwnwnenwewseseneseneswwnenwnenwnwnwsenew ================================================ FILE: exm/aoc/2020/aoc_2020_25.adb ================================================ -- Solution to Advent of Code 2020, Day 25 ------------------------------------------- -- Combo Breaker -- -- https://adventofcode.com/2020/day/25 -- with HAT; -- ^ For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2020.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2020_25 is N : constant := 20201227; -- A prime number. use HAT, Interfaces; function Transform (subjet_number : Integer_64; loop_size : Positive) return Integer_64 is value : Integer_64 := 1; begin for i in 1 .. loop_size loop value := value * subjet_number; value := value rem N; end loop; return value; end Transform; procedure Solve (seed, card_public_key, door_public_key : Integer_64) is function Find_Loop_Size (key : Integer_64) return Natural is value : Integer_64 := 1; max_loop_size : constant := 10_000_000; begin for i in 1 .. max_loop_size loop value := value * seed; value := value rem N; if key = value then return i; end if; end loop; return 0; end Find_Loop_Size; card_loop_size : constant Natural := Find_Loop_Size (card_public_key); begin Put_Line (+" Card's reverse-engineered loop size : " & card_loop_size); Put_Line (+" Door's reverse-engineered loop size : " & Find_Loop_Size (door_public_key)); -- Put_Line (" Encryption key :" & Integer_64'Image (Transform (door_public_key, card_loop_size))); -- -- NB: -- -- card_public_key ** door_loop_size = -- (seed ** card_loop_size) ** door_loop_size = -- seed ** (card_loop_size * door_loop_size) = -- (seed ** door_loop_size) ** card_loop_size = -- door_public_key ** card_loop_size -- end Solve; procedure Test_Example is card_public_key : constant Integer_64 := Transform (7, 8); door_public_key : constant Integer_64 := Transform (7, 11); begin Put_Line ("Example"); Put_Line (" Card's public key :" & Integer_64'Image (card_public_key)); Put_Line (" Door's public key :" & Integer_64'Image (door_public_key)); -- Solve (7, card_public_key, door_public_key); end Test_Example; procedure Input is begin Put_Line ("Input"); Solve (7, 18356117, 5909654); -- Officially validated by AoC: 16902792 end Input; begin Test_Example; Input; end AoC_2020_25; ================================================ FILE: exm/aoc/2021/aoc_2021.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the Advent of Code 2021 examples. -- Some work with both HAC and "full Ada" compilers, -- some (titled *_full_ada.adb) work only with "full Ada". -- project AoC_2021 is for Source_Dirs use ( ".", "../../../src" -- GNAT's access to the HAT package. ); for Exec_Dir use "."; for Create_Missing_Dirs use "True"; type AoC_Build_Mode_Type is ("Debug", "Fast" ); AoC_Build_Mode : AoC_Build_Mode_Type := external ("AoC_Build_Mode", "Debug"); for Main use ( "aoc_2021_22.adb", "aoc_2021_21.adb", "aoc_2021_20.adb", "aoc_2021_19.adb", "aoc_2021_18_full_ada.adb", "aoc_2021_17.adb", "aoc_2021_16.adb", "aoc_2021_15.adb", "aoc_2021_14.adb", "aoc_2021_13.adb", "aoc_2021_12.adb", "aoc_2021_11.adb", "aoc_2021_10.adb", "aoc_2021_09.adb", "aoc_2021_08.adb", "aoc_2021_07.adb", "aoc_2021_06.adb", "aoc_2021_05.adb", "aoc_2021_04.adb", "aoc_2021_03.adb", "aoc_2021_02.adb", "aoc_2021_01.adb" ); case AoC_Build_Mode is when "Debug" => for Object_Dir use "obj_debug"; when "Fast" => for Object_Dir use "obj_fast"; end case; Common_Options := ("-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatwCijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ", -- Don't quit, write ali/tree file even if compile errors -- "-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens "-gnatye", -- Style: check e:end/exit labels present "-gnaty2", -- Style: check indentation "-gnatytc"); -- Style: check t:token separation rules, c:comment format (two spaces) Fast_Options := ( "-O3", "-funroll-loops", "-fpeel-loops", "-funswitch-loops", "-ftracer", "-fweb", "-frename-registers", "-ftree-vectorize", "-fipa-cp-clone", "-fgcse-after-reload" ); Debug_Options := ( -- "-gnateV", -- Validity check for parameters, GNAT > 4.6, redundant with -gnatVim ? "-gnatVa", -- Turn on all validity checking options "-gnato", -- Enable overflow checking in STRICT (-gnato1) mode "-g", "-fno-inline", "-fstack-check" ); package Compiler is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Options & Debug_Options ; when "Fast" => for Default_Switches ("ada") use Common_Options & Fast_Options & ("-gnatpn", "-ffunction-sections"); end case; end Compiler; package Linker is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use ("-g"); when "Fast" => for Default_Switches ("ada") use ("-g", "-s", "-Wl,--gc-sections"); end case; end Linker; package Binder is -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks for Default_Switches ("ada") use ("-Es"); end Binder; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-j0"); end Builder; end AoC_2021; ================================================ FILE: exm/aoc/2021/aoc_2021_01.adb ================================================ -- Solution to Advent of Code 2021, Day 1 ------------------------------------------ -- Sonar Sweep -- -- https://adventofcode.com/2021/day/1 -- Copy of questions in: aoc_2021_01_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_01 is use HAT; f : File_Type; depth, depth_p1, depth_p2, inc_a, inc_b, row, sum, sum_p1 : Integer; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; begin Open (f, "aoc_2021_01.txt"); depth_p1 := -1; depth_p2 := -1; inc_a := 0; inc_b := 0; row := 0; sum := -1; while not End_Of_File (f) loop Get (f, depth); row := row + 1; if row > 1 and then depth > depth_p1 then inc_a := inc_a + 1; end if; sum_p1 := sum; sum := depth + depth_p1 + depth_p2; if row > 3 and then sum > sum_p1 then inc_b := inc_b + 1; end if; depth_p2 := depth_p1; depth_p1 := depth; end loop; Close (f); if compiler_test_mode then if inc_a /= Integer_Value (Argument (1)) or inc_b /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1: Depth increases: " & inc_a); Put_Line (+"Part 2: Depth increases: " & inc_b); -- Part 1: validated by AoC: 1154 -- Part 2: validated by AoC: 1127 end if; end AoC_2021_01; ================================================ FILE: exm/aoc/2021/aoc_2021_01.txt ================================================ 199 203 200 201 196 195 196 214 227 225 229 260 246 253 271 281 280 295 310 293 295 297 298 297 306 299 290 292 289 287 291 296 294 287 286 287 289 290 281 283 282 275 256 265 242 231 226 216 227 226 249 238 237 247 245 250 264 267 259 258 264 261 249 246 239 240 259 258 280 279 278 281 272 256 255 271 286 290 286 288 290 294 292 294 292 293 294 291 298 303 301 330 331 336 362 371 374 368 367 368 366 364 371 377 378 384 386 388 393 409 423 422 411 412 426 430 441 460 462 464 469 461 483 452 455 457 468 506 509 514 525 512 524 523 522 531 549 548 549 548 524 525 528 526 537 544 549 546 525 532 535 543 544 545 525 536 538 541 524 534 542 538 539 544 543 539 538 527 553 552 562 560 561 573 574 570 571 568 569 571 573 566 567 584 591 607 605 604 605 617 615 617 606 608 609 613 616 635 634 637 635 634 655 639 646 637 628 622 648 645 640 652 653 659 661 658 650 667 670 668 680 682 673 668 678 677 675 676 677 675 688 681 676 684 675 664 665 654 660 664 663 667 658 661 676 675 680 681 690 693 697 721 733 739 740 739 751 765 766 752 748 763 772 771 782 784 797 799 817 812 811 795 783 785 790 785 784 782 771 756 759 783 772 774 779 783 786 780 783 779 777 778 777 762 778 777 770 773 769 770 771 764 765 761 745 754 758 759 746 738 740 742 767 765 754 755 758 762 760 761 757 761 770 773 777 776 777 769 767 793 805 798 793 803 809 808 817 804 809 805 804 806 808 812 830 831 832 831 819 820 823 822 812 814 812 842 858 855 856 862 860 855 839 840 841 840 846 850 859 861 852 846 848 845 833 843 846 849 889 890 894 904 907 904 905 906 907 910 902 906 900 907 906 899 887 867 866 873 878 885 880 890 863 860 859 885 856 853 854 852 864 855 874 875 874 875 871 872 867 870 873 874 860 862 879 878 879 880 881 882 878 882 885 890 902 903 905 906 909 917 916 934 932 935 937 935 910 911 907 902 904 910 917 918 943 945 959 973 972 969 973 972 958 957 959 963 968 961 960 973 971 970 977 1002 1012 1011 1007 1017 1024 1014 1013 1019 1005 984 983 980 993 999 982 988 989 990 992 988 989 988 981 958 973 966 965 942 926 933 928 932 940 927 930 920 930 897 905 907 889 882 888 889 872 873 885 884 886 887 898 901 902 895 880 894 886 882 885 890 896 880 881 866 872 875 903 901 907 899 920 921 934 935 937 928 929 927 928 935 906 908 906 882 883 887 891 892 898 903 907 909 916 917 945 935 937 928 918 927 916 929 919 931 954 953 954 956 953 947 937 941 960 968 951 955 954 938 939 946 945 947 948 951 943 949 946 954 952 949 943 936 944 941 950 952 948 947 971 970 969 974 971 1000 1005 1007 1009 1008 1000 998 999 1001 1008 1001 1024 1005 998 1016 1018 1019 1020 1021 1057 1056 1052 1044 1045 1057 1058 1074 1075 1069 1056 1055 1056 1052 1059 1070 1043 1039 1035 1025 1015 1018 1029 1033 1042 1038 1031 1033 1023 1016 1019 1018 1016 1018 1020 1009 1008 997 973 983 990 996 1002 1001 1000 1002 1001 1015 1016 1015 1019 1020 1016 1010 1009 1008 1016 1018 1015 1011 1004 999 1000 1027 1035 1050 1051 1068 1058 1072 1086 1089 1060 1043 1028 1026 1028 1052 1050 1042 1040 1036 1055 1050 1051 1049 1053 1054 1059 1058 1066 1059 1061 1070 1071 1068 1059 1060 1065 1066 1068 1060 1059 1070 1069 1068 1067 1068 1070 1069 1066 1073 1065 1066 1050 1052 1050 1056 1055 1063 1062 1057 1054 1048 1047 1051 1049 1043 1017 1016 1002 1005 992 994 999 1001 1017 1026 1024 1028 1040 1039 1046 1022 1023 992 995 1019 1022 1023 1011 1004 1005 993 991 992 995 996 997 1009 1011 1012 1017 1030 1029 1031 1024 1033 1008 1006 1018 1020 1015 1020 1031 1029 1026 1030 1042 1039 1029 1027 1008 1003 1019 1000 1001 995 996 994 988 989 988 987 994 997 1000 994 997 989 991 985 975 982 981 986 980 979 973 984 985 983 981 956 925 924 919 913 915 917 914 916 895 910 924 919 914 928 935 927 930 932 936 939 944 948 947 946 945 948 944 942 944 958 956 947 955 990 995 996 1007 1009 1013 1012 1011 1020 1019 1021 1016 1038 1050 1043 1046 1047 1043 1040 1039 1045 1046 1030 1031 1034 1035 1045 1066 1085 1092 1101 1100 1101 1099 1084 1085 1086 1090 1091 1087 1100 1099 1092 1095 1101 1102 1118 1117 1138 1139 1132 1127 1131 1132 1130 1128 1130 1150 1149 1157 1158 1156 1157 1155 1170 1175 1167 1166 1177 1174 1186 1187 1186 1185 1189 1193 1204 1191 1196 1198 1186 1198 1215 1210 1211 1212 1211 1207 1206 1198 1202 1190 1185 1190 1199 1222 1225 1222 1234 1236 1260 1261 1262 1272 1289 1286 1290 1297 1295 1270 1291 1299 1303 1318 1342 1356 1361 1362 1326 1325 1333 1329 1349 1353 1367 1368 1371 1369 1353 1351 1349 1352 1354 1353 1356 1355 1362 1366 1368 1370 1349 1354 1357 1356 1360 1357 1361 1363 1364 1345 1338 1335 1334 1322 1329 1333 1334 1331 1330 1337 1348 1347 1348 1317 1307 1313 1330 1323 1324 1327 1334 1336 1334 1332 1338 1341 1342 1373 1375 1374 1372 1373 1371 1370 1375 1363 1361 1366 1389 1390 1366 1380 1381 1379 1383 1400 1402 1404 1409 1410 1434 1439 1443 1448 1434 1462 1463 1462 1464 1465 1471 1465 1464 1469 1473 1480 1486 1488 1492 1494 1495 1496 1504 1496 1495 1472 1469 1465 1466 1455 1464 1465 1474 1475 1490 1499 1490 1492 1489 1500 1504 1500 1499 1500 1510 1511 1516 1511 1515 1512 1499 1506 1509 1493 1495 1496 1485 1486 1476 1475 1484 1485 1469 1477 1478 1467 1468 1469 1477 1478 1475 1473 1461 1468 1470 1496 1491 1506 1505 1526 1530 1528 1529 1533 1555 1558 1557 1554 1557 1559 1560 1562 1561 1563 1564 1550 1559 1558 1559 1554 1535 1538 1541 1540 1529 1528 1519 1527 1535 1518 1523 1519 1536 1562 1561 1566 1568 1583 1584 1599 1585 1581 1588 1559 1561 1574 1587 1574 1576 1589 1588 1582 1581 1584 1604 1563 1555 1561 1564 1548 1541 1542 1546 1548 1550 1566 1544 1523 1525 1521 1541 1550 1551 1548 1558 1561 1560 1550 1563 1578 1582 1563 1557 1558 1557 1559 1574 1569 1577 1576 1577 1571 1573 1572 1574 1577 1581 1566 1535 1539 1540 1536 1545 1544 1513 1511 1509 1502 1489 1490 1495 1488 1492 1513 1519 1520 1521 1530 1512 1514 1512 1517 1518 1520 1519 1527 1526 1527 1528 1529 1522 1525 1529 1525 1524 1525 1527 1529 1524 1523 1525 1533 1535 1536 1555 1557 1573 1572 1571 1590 1593 1594 1593 1565 1566 1554 1572 1567 1569 1566 1597 1616 1630 1641 1638 1634 1647 1651 1649 1652 1659 1660 1651 1656 1653 1654 1653 1658 1643 1642 1641 1654 1655 1656 1666 1673 1682 1665 1663 1670 1654 1668 1667 1656 1646 1655 1662 1680 1683 1682 1683 1684 1722 1702 1710 1711 1715 1728 1730 1735 1736 1750 1755 1756 1755 1752 1761 1768 1767 1760 1751 1747 1764 1763 1762 1748 1753 1745 1752 1754 1746 1747 1748 1756 1761 1756 1734 1711 1712 1721 1727 1726 1731 1729 1715 1716 1733 1738 1740 1756 1755 1748 1744 1751 1756 1774 1775 1755 1746 1754 1758 1767 1785 1786 1787 1788 1766 1787 1786 1788 1762 1757 1752 1760 1781 1750 1757 1762 1767 1770 1744 1743 1747 1756 1763 1775 1769 1760 1759 1766 1768 1764 1759 1761 1792 1798 1800 1802 1813 1810 1822 1824 1816 1842 1843 1835 1833 1834 1837 1826 1830 1850 1855 1857 1862 1856 1877 1878 1875 1850 1847 1846 1847 1846 1826 1829 1825 1817 1818 1815 1834 1833 1822 1825 1815 1817 1815 1816 1810 1822 1815 1817 1821 1820 1814 1802 1799 1814 1834 1830 1842 1828 1836 1849 1851 1849 1848 1849 1865 1885 1895 1904 1910 1921 1937 1941 1970 1968 1975 1982 2003 2012 2011 2008 2006 1997 1994 1991 1989 1988 1995 1976 2006 2018 2015 2023 2022 2023 2048 2038 2039 2041 2057 2058 2059 2060 2059 2061 2031 2032 2033 2020 2019 2023 2032 2034 2027 2029 2027 2018 2028 2055 2054 2043 2047 2046 2055 2047 2056 2037 2032 2003 2002 1999 2001 1996 2000 2002 2004 1988 1990 1999 1986 1988 1986 1985 1977 1978 1977 1973 1977 1978 1985 1988 1964 1967 1989 1984 1980 1979 1980 1999 2006 2004 2018 2051 2024 2023 2025 2026 2012 2000 2017 2018 2017 2019 2017 2025 2030 2038 2016 2001 2020 2018 2010 2013 2028 2031 2018 2019 2009 2015 2011 2012 2024 2027 2028 2018 2007 2009 2011 2009 2008 2006 2008 2013 2017 2027 2030 2031 2029 2045 2064 2065 2064 2077 2075 2066 2037 2038 2043 2047 2049 2055 2090 2092 2101 2115 2117 2130 2131 2130 2136 2141 2145 2151 2150 2149 2150 2143 2150 2139 2142 2140 2146 2147 2148 2146 2141 2158 2176 2195 2194 2190 2187 2188 2205 2206 2208 2207 2208 2200 2199 2193 2169 2188 2189 2183 2202 2170 2164 2165 2166 2177 2181 2198 2197 2207 2201 2206 2203 2209 2213 2214 2216 2218 2219 2214 2235 2239 2235 2253 2246 2247 2246 2247 2246 2251 2249 2275 2285 2293 2294 2295 2299 2303 2302 2303 2276 2282 2287 2294 2299 2301 2300 2306 2294 2301 2296 2289 2291 2300 2301 2287 2286 2307 2305 2315 2305 2309 2334 2337 2348 2349 2350 2332 2342 2341 2338 2310 2316 2333 2335 2330 2342 2349 2341 2363 2368 2374 2360 2359 2350 2348 2359 2365 2364 2355 2341 2339 2345 2338 2335 2323 2324 2318 2294 2296 2297 2286 2282 2278 2276 2272 2267 2269 2270 2269 2266 2268 2264 2268 2260 2263 2297 2311 2319 2301 2292 2302 2309 2307 2303 2306 2311 2293 2278 2284 2288 2271 2273 2275 2278 2279 2283 2318 2315 2312 2325 2346 2339 2314 2303 2304 2279 2278 2269 2267 2270 2277 2287 2285 2288 2289 2288 2284 2283 2281 2289 2288 2275 2278 2265 2267 2262 2259 2260 2261 2251 2250 2254 2253 2242 2240 2241 2226 2232 2236 2201 2182 2183 2191 2185 2192 2197 2211 2210 2208 2218 2219 2228 2227 2225 2226 2225 2226 2229 2233 2237 2236 2211 2215 2216 2236 2227 2228 2227 2226 2244 2260 2258 2257 2258 2250 2248 2229 2225 2223 2222 2221 2220 2219 2213 2214 2212 2216 2217 2220 2216 2217 2223 2227 2231 2225 2228 2230 2233 2226 2224 2241 2221 2220 2224 2221 2220 2223 2221 2246 2247 2246 2222 2226 2237 2250 2251 2276 2288 2309 2304 2330 2323 2327 2350 2349 2348 2346 2354 2350 2323 2320 2313 2315 2314 2316 2332 2338 2341 ================================================ FILE: exm/aoc/2021/aoc_2021_01_questions.txt ================================================ --- Day 1: Sonar Sweep --- You're minding your own business on a ship at sea when the overboard alarm goes off! You rush to see if you can help. Apparently, one of the Elves tripped and accidentally sent the sleigh keys flying into the ocean! Before you know it, you're inside a submarine the Elves keep ready for situations like this. It's covered in Christmas lights (because of course it is), and it even has an experimental antenna that should be able to track the keys if you can boost its signal strength high enough; there's a little meter that indicates the antenna's signal strength by displaying 0-50 stars. Your instincts tell you that in order to save Christmas, you'll need to get all fifty stars by December 25th. Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck! As the submarine drops below the surface of the ocean, it automatically performs a sonar sweep of the nearby sea floor. On a small screen, the sonar sweep report (your puzzle input) appears: each line is a measurement of the sea floor depth as the sweep looks further and further away from the submarine. For example, suppose you had the following report: 199 200 208 210 200 207 240 269 260 263 This report indicates that, scanning outward from the submarine, the sonar sweep found depths of 199, 200, 208, 210, and so on. The first order of business is to figure out how quickly the depth increases, just so you know what you're dealing with - you never know if the keys will get carried into deeper water by an ocean current or a fish or something. To do this, count the number of times a depth measurement increases from the previous measurement. (There is no measurement before the first measurement.) In the example above, the changes are as follows: 199 (N/A - no previous measurement) 200 (increased) 208 (increased) 210 (increased) 200 (decreased) 207 (increased) 240 (increased) 269 (increased) 260 (decreased) 263 (increased) In this example, there are 7 measurements that are larger than the previous measurement. How many measurements are larger than the previous measurement? --- Part Two --- Considering every single measurement isn't as useful as you expected: there's just too much noise in the data. Instead, consider sums of a three-measurement sliding window. Again considering the above example: 199 A 200 A B 208 A B C 210 B C D 200 E C D 207 E F D 240 E F G 269 F G H 260 G H 263 H Start by comparing the first and second three-measurement windows. The measurements in the first window are marked A (199, 200, 208); their sum is 199 + 200 + 208 = 607. The second window is marked B (200, 208, 210); its sum is 618. The sum of measurements in the second window is larger than the sum of the first, so this first comparison increased. Your goal now is to count the number of times the sum of measurements in this sliding window increases from the previous sum. So, compare A with B, then compare B with C, then C with D, and so on. Stop when there aren't enough measurements left to create a new three-measurement sum. In the above example, the sum of each three-measurement window is as follows: A: 607 (N/A - no previous sum) B: 618 (increased) C: 618 (no change) D: 617 (decreased) E: 647 (increased) F: 716 (increased) G: 769 (increased) H: 792 (increased) In this example, there are 5 sums that are larger than the previous sum. Consider sums of a three-measurement sliding window. How many sums are larger than the previous sum? ================================================ FILE: exm/aoc/2021/aoc_2021_02.adb ================================================ -- Solution to Advent of Code 2021, Day 2 ------------------------------------------ -- Dive! -- -- https://adventofcode.com/2021/day/2 -- Copy of questions in: aoc_2021_02_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_02 is use HAT; c, sep : Character; i, x, d, aim : Integer; f : File_Type; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; begin for part in 1 .. 2 loop x := 0; d := 0; aim := 0; Open (f, "aoc_2021_02.txt"); while not End_Of_File (f) loop Get (f, c); loop Get (f, sep); exit when sep = ' '; end loop; Get (f, i); case part is when 1 => case c is when 'f' => x := x + i; -- Forward when 'u' => d := d - i; -- Up when 'd' => d := d + i; -- Down when others => null; end case; when 2 => case c is when 'f' => x := x + i; -- Forward d := d + i * aim; when 'u' => aim := aim - i; -- Up when 'd' => aim := aim + i; -- Down when others => null; end case; end case; end loop; Close (f); if compiler_test_mode then if x * d /= Integer_Value (Argument (part)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part " & part & ": x = " & x & ", d = " & d & ", solution = x * d = " & x * d); -- Part 1: validated by AoC: 2187380 -- Part 2: validated by AoC: 2086357770 end if; end loop; end AoC_2021_02; ================================================ FILE: exm/aoc/2021/aoc_2021_02.txt ================================================ forward 1 down 6 down 6 forward 2 forward 2 down 2 down 1 down 5 down 7 down 3 forward 1 forward 6 up 2 forward 2 forward 7 forward 4 down 2 forward 6 forward 6 down 3 up 7 down 6 forward 2 up 5 down 7 forward 8 down 8 forward 8 down 5 down 5 down 8 forward 9 down 7 forward 9 forward 9 forward 8 down 6 down 9 down 1 forward 8 down 6 down 7 up 3 forward 5 down 1 down 7 up 8 forward 6 down 2 down 9 down 9 forward 1 down 2 down 9 forward 1 forward 3 down 6 up 7 down 7 forward 3 down 4 down 3 up 7 up 7 forward 2 down 7 forward 2 down 3 up 7 down 7 forward 6 down 2 down 7 forward 5 down 9 down 2 up 7 down 1 forward 5 down 5 forward 9 down 6 down 3 down 7 down 8 down 3 up 4 down 6 forward 6 up 7 up 2 forward 3 up 1 down 5 forward 9 up 3 forward 8 up 4 down 7 down 8 down 3 down 7 forward 5 up 6 down 4 down 8 down 8 forward 7 down 5 forward 3 forward 1 down 1 forward 1 up 1 forward 4 forward 9 up 8 down 7 down 9 down 1 down 2 down 1 down 4 forward 4 forward 8 forward 6 forward 1 forward 6 forward 9 down 1 up 9 down 9 forward 2 down 6 down 8 down 6 up 7 forward 2 up 2 forward 5 down 2 up 2 up 9 forward 7 down 6 forward 3 down 5 up 4 down 1 down 5 down 6 up 7 down 3 down 9 up 8 down 2 up 8 down 1 down 2 down 4 forward 6 up 7 up 3 forward 8 down 9 down 8 forward 3 up 5 forward 1 down 5 up 2 down 5 up 4 down 6 forward 9 down 1 down 1 forward 1 down 2 forward 9 up 5 down 7 forward 7 down 9 down 5 down 3 forward 4 down 2 forward 7 forward 3 up 4 down 9 forward 9 forward 3 forward 1 forward 6 down 1 down 5 down 3 forward 9 down 2 forward 9 up 7 forward 7 forward 7 forward 8 forward 6 forward 5 down 7 up 4 forward 7 up 2 forward 6 down 2 down 9 down 3 forward 5 down 3 down 9 forward 2 up 4 forward 7 forward 3 forward 8 down 4 forward 4 down 3 up 7 up 1 up 4 down 3 down 5 down 3 down 7 down 3 down 7 down 5 down 1 forward 5 forward 6 down 1 forward 9 down 4 up 1 forward 5 up 6 down 4 up 7 down 4 down 9 forward 7 up 8 forward 3 forward 5 down 9 down 1 down 7 forward 9 down 9 down 5 forward 6 forward 4 forward 3 down 1 down 2 up 4 up 7 down 8 forward 4 forward 1 forward 8 down 8 down 8 forward 1 forward 5 up 8 forward 2 down 6 forward 6 down 6 forward 7 down 9 down 4 up 4 up 5 down 7 forward 4 down 7 down 5 forward 7 down 3 down 2 forward 5 forward 1 down 5 down 4 down 8 up 8 forward 3 down 7 down 8 down 5 forward 1 down 6 forward 8 forward 2 forward 3 down 4 up 3 down 4 forward 3 forward 9 up 5 up 9 down 3 up 4 forward 4 down 9 forward 8 down 2 down 2 forward 9 down 5 down 2 up 1 forward 6 forward 4 up 5 up 3 up 8 down 7 forward 5 up 7 forward 9 down 6 down 7 forward 4 down 9 up 2 forward 8 down 1 forward 6 forward 1 forward 4 down 9 down 6 up 1 forward 1 down 5 up 1 forward 3 down 1 down 4 forward 3 down 4 up 9 down 6 up 6 forward 1 forward 8 up 1 down 7 up 8 up 3 up 7 down 9 forward 8 down 3 up 2 forward 3 up 4 up 3 down 5 forward 3 forward 2 down 3 forward 5 up 4 down 9 down 8 down 3 down 5 down 7 forward 2 forward 8 up 9 forward 9 down 4 down 8 forward 5 down 2 up 4 down 7 forward 6 up 9 forward 6 down 9 down 5 forward 9 down 5 down 3 up 6 up 6 down 7 up 1 forward 7 forward 4 down 5 forward 8 down 5 down 8 forward 4 forward 8 forward 1 down 7 forward 4 down 6 down 4 up 8 down 4 up 5 up 7 up 2 down 5 down 9 forward 6 down 7 down 9 down 3 up 4 down 8 forward 3 forward 5 forward 8 down 9 forward 9 down 1 up 1 down 9 forward 3 up 9 forward 5 forward 2 down 1 down 5 down 6 forward 5 forward 4 up 5 forward 5 up 4 up 9 up 4 forward 8 down 7 down 6 down 9 down 3 down 2 down 6 up 6 forward 6 up 3 down 3 forward 3 down 2 down 9 down 3 forward 1 forward 8 down 2 down 9 down 6 up 3 down 6 forward 1 forward 1 forward 2 down 9 down 8 forward 9 down 2 up 3 forward 2 up 5 up 8 down 4 up 3 forward 3 forward 5 forward 1 down 5 up 4 forward 4 down 7 forward 8 up 7 forward 5 down 2 forward 4 forward 6 down 7 down 9 forward 2 forward 2 down 4 down 5 up 5 forward 5 forward 2 down 8 forward 6 down 1 down 6 forward 1 down 8 up 6 down 8 forward 4 down 4 down 4 forward 3 up 8 down 1 forward 7 down 5 forward 1 down 9 down 9 down 5 forward 1 down 4 up 6 forward 4 forward 5 forward 1 down 4 down 2 down 5 forward 6 forward 1 forward 6 down 2 down 6 forward 3 down 9 up 6 forward 2 up 7 forward 8 down 7 up 1 forward 1 down 8 forward 8 down 9 forward 4 down 4 down 5 down 8 up 3 forward 1 forward 9 down 9 up 2 down 1 down 8 down 6 forward 3 down 8 down 3 forward 5 forward 2 forward 5 forward 5 forward 2 forward 4 down 9 down 3 forward 7 forward 3 up 3 up 1 forward 2 down 5 forward 3 up 3 forward 2 forward 9 forward 5 down 3 forward 9 up 2 forward 7 up 3 down 8 forward 7 up 5 forward 3 forward 4 up 5 down 6 up 2 forward 8 up 3 down 5 down 4 forward 9 up 2 down 5 forward 4 up 7 down 9 up 8 down 4 up 5 forward 4 down 8 forward 3 down 5 down 5 down 8 up 9 forward 3 forward 9 down 2 forward 4 down 1 up 3 down 9 up 6 down 1 down 1 down 5 down 1 down 7 forward 4 down 4 down 9 up 1 up 7 up 2 down 8 up 5 down 6 forward 6 forward 6 down 4 forward 9 forward 4 forward 9 forward 4 up 5 forward 9 up 7 up 1 forward 5 forward 9 down 7 forward 7 forward 6 down 5 forward 9 up 9 down 4 down 9 down 2 forward 3 down 3 down 3 forward 9 down 8 down 4 down 8 down 6 down 6 down 9 up 5 down 3 down 4 up 6 up 2 forward 1 up 9 up 9 forward 9 forward 7 down 3 forward 2 up 5 down 2 forward 2 forward 8 down 8 forward 4 forward 2 up 3 up 8 down 5 forward 5 forward 8 down 1 down 8 forward 3 forward 9 down 7 forward 5 forward 8 forward 1 up 6 forward 9 up 5 forward 8 forward 3 down 2 up 9 up 7 forward 5 down 8 down 3 forward 8 down 3 down 9 down 9 forward 7 down 9 forward 5 forward 1 forward 5 down 2 down 7 forward 4 down 4 up 8 down 2 up 1 down 1 up 5 up 6 down 5 up 9 up 6 down 6 down 4 down 3 forward 9 forward 2 forward 2 up 6 forward 9 down 3 forward 4 forward 6 forward 8 forward 2 forward 8 forward 4 down 1 forward 3 up 1 up 9 forward 9 up 6 up 5 forward 2 down 6 up 8 up 9 forward 3 forward 9 down 7 down 6 forward 2 down 7 forward 4 down 5 down 2 down 6 down 2 down 5 down 3 forward 3 down 7 down 6 down 5 up 2 forward 4 up 9 forward 2 forward 4 down 5 up 9 up 2 forward 9 forward 6 down 6 down 3 down 5 down 1 up 4 up 1 down 4 down 1 forward 5 forward 3 down 7 down 9 forward 2 down 3 up 7 down 2 down 6 forward 3 forward 3 down 3 up 1 forward 6 forward 3 down 6 down 2 up 4 up 3 down 5 down 9 down 3 forward 7 forward 2 forward 9 down 6 forward 4 up 9 forward 1 down 4 down 6 down 2 forward 3 down 2 up 8 forward 1 forward 9 down 9 up 7 forward 6 up 8 down 9 down 4 forward 8 down 6 down 1 down 9 down 1 up 7 forward 9 up 3 forward 7 up 7 down 2 forward 1 down 4 down 7 forward 7 forward 9 down 6 down 5 down 8 down 9 up 3 down 7 up 3 down 1 forward 1 forward 6 forward 2 down 6 forward 9 forward 1 up 2 forward 1 forward 3 forward 4 forward 7 forward 4 down 3 up 8 forward 9 down 7 forward 6 forward 3 down 6 forward 4 up 1 forward 3 down 3 forward 9 forward 2 forward 1 forward 4 up 6 forward 3 down 6 down 8 up 4 forward 8 forward 4 down 8 up 4 up 3 forward 9 forward 3 down 5 forward 7 forward 1 up 8 up 4 down 1 down 3 down 9 down 7 up 5 forward 6 down 1 forward 3 down 2 down 2 down 6 forward 2 down 5 forward 2 forward 1 up 9 down 1 forward 3 down 3 forward 6 down 1 forward 5 forward 7 down 6 forward 7 down 4 up 7 forward 1 down 7 down 8 down 9 down 6 down 1 forward 6 down 7 forward 2 down 2 up 1 up 2 down 3 down 4 up 2 forward 3 down 5 down 4 down 9 down 6 down 9 down 7 down 2 forward 7 forward 3 up 3 down 1 down 5 down 1 down 3 down 3 forward 9 down 1 down 7 up 4 down 1 down 6 up 9 down 9 forward 6 down 9 forward 3 forward 8 up 1 forward 3 down 8 forward 2 down 6 down 1 up 7 down 1 forward 3 down 2 forward 1 up 8 forward 8 forward 7 down 9 forward 3 ================================================ FILE: exm/aoc/2021/aoc_2021_02_questions.txt ================================================ --- Day 2: Dive! --- Now, you need to figure out how to pilot this thing. It seems like the submarine can take a series of commands like forward 1, down 2, or up 3: forward X increases the horizontal position by X units. down X increases the depth by X units. up X decreases the depth by X units. Note that since you're on a submarine, down and up affect your depth, and so they have the opposite result of what you might expect. The submarine seems to already have a planned course (your puzzle input). You should probably figure out where it's going. For example: forward 5 down 5 forward 8 up 3 down 8 forward 2 Your horizontal position and depth both start at 0. The steps above would then modify them as follows: forward 5 adds 5 to your horizontal position, a total of 5. down 5 adds 5 to your depth, resulting in a value of 5. forward 8 adds 8 to your horizontal position, a total of 13. up 3 decreases your depth by 3, resulting in a value of 2. down 8 adds 8 to your depth, resulting in a value of 10. forward 2 adds 2 to your horizontal position, a total of 15. After following these instructions, you would have a horizontal position of 15 and a depth of 10. (Multiplying these together produces 150.) Calculate the horizontal position and depth you would have after following the planned course. What do you get if you multiply your final horizontal position by your final depth? --- Part Two --- Based on your calculations, the planned course doesn't seem to make any sense. You find the submarine manual and discover that the process is actually slightly more complicated. In addition to horizontal position and depth, you'll also need to track a third value, aim, which also starts at 0. The commands also mean something entirely different than you first thought: down X increases your aim by X units. up X decreases your aim by X units. forward X does two things: It increases your horizontal position by X units. It increases your depth by your aim multiplied by X. Again note that since you're on a submarine, down and up do the opposite of what you might expect: "down" means aiming in the positive direction. Now, the above example does something different: forward 5 adds 5 to your horizontal position, a total of 5. Because your aim is 0, your depth does not change. down 5 adds 5 to your aim, resulting in a value of 5. forward 8 adds 8 to your horizontal position, a total of 13. Because your aim is 5, your depth increases by 8*5=40. up 3 decreases your aim by 3, resulting in a value of 2. down 8 adds 8 to your aim, resulting in a value of 10. forward 2 adds 2 to your horizontal position, a total of 15. Because your aim is 10, your depth increases by 2*10=20 to a total of 60. After following these new instructions, you would have a horizontal position of 15 and a depth of 60. (Multiplying these produces 900.) Using this new interpretation of the commands, calculate the horizontal position and depth you would have after following the planned course. What do you get if you multiply your final horizontal position by your final depth? ================================================ FILE: exm/aoc/2021/aoc_2021_03.adb ================================================ -- Solution to Advent of Code 2021, Day 3 ------------------------------------------ -- Binary Diagnostic -- -- https://adventofcode.com/2021/day/3 -- Copy of questions in: aoc_2021_03_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_03 is use HAT; c : Character; f : File_Type; -- input : constant VString := +"aoc_2021_03.txt"; bits : constant := 12; subtype Bit_Pos_Range is Integer range 1 .. bits; stat_ones : array (Bit_Pos_Range) of Natural; type Criterium is (most, least); stat_ones_selected_pos : Natural; -- subtype Bit_Type is Integer range 0 .. 1; type Word is array (Bit_Pos_Range) of Bit_Type; keep, bit_value, mem_valid : Word; -- consider : Boolean; rows, gamma, epsilon, res_1, res_2 : Natural; gas : array (Criterium) of Natural; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := False; begin for pos in Bit_Pos_Range loop stat_ones (pos) := 0; end loop; rows := 0; Open (f, input); while not End_Of_File (f) loop rows := rows + 1; for pos in Bit_Pos_Range loop Get (f, c); if c = '1' then stat_ones (pos) := stat_ones (pos) + 1; end if; end loop; end loop; Close (f); gamma := 0; for pos in Bit_Pos_Range loop gamma := gamma * 2; if stat_ones (pos) > rows / 2 then gamma := gamma + 1; end if; end loop; epsilon := 2 ** bits - 1 - gamma; if verbose then Put_Line (+"Part 1: gamma: " & gamma & "; epsilon: " & epsilon); end if; res_1 := gamma * epsilon; -- -- Part Two -- if verbose then Put_Line (+"Part 2:"); end if; for pos in Bit_Pos_Range loop keep (pos) := 0; -- Just to remove a compiler warning. end loop; for crit in Criterium loop for main_pos in Bit_Pos_Range loop stat_ones_selected_pos := 0; rows := 0; Open (f, input); while not End_Of_File (f) loop consider := True; for pos in Bit_Pos_Range loop Get (f, c); bit_value (pos) := Ord (c) - Ord ('0'); if pos < main_pos then consider := consider and keep (pos) = bit_value (pos); elsif pos = main_pos then if consider then rows := rows + 1; if bit_value (pos) = 1 then stat_ones_selected_pos := stat_ones_selected_pos + 1; end if; end if; end if; end loop; if consider then mem_valid := bit_value; -- Remember the number on the last considered row. end if; end loop; Close (f); if verbose then Put ("Bit pos: "); Put (main_pos, 2); Put (+"/" & bits & "; rows: "); Put (rows, 5); end if; if rows = 1 then keep := mem_valid; if verbose then Put_Line (". Only one row left, stop!"); end if; exit; else case crit is when most => if stat_ones_selected_pos >= rows - stat_ones_selected_pos then keep (main_pos) := 1; else keep (main_pos) := 0; end if; when least => if stat_ones_selected_pos >= rows - stat_ones_selected_pos then keep (main_pos) := 0; else keep (main_pos) := 1; end if; end case; if verbose then Put ("; ones: "); Put (stat_ones_selected_pos, 5); Put (keep (main_pos)); New_Line; end if; end if; end loop; if verbose then for main_pos in Bit_Pos_Range loop Put (keep (main_pos), 0); end loop; New_Line; end if; gas (crit) := 0; for pos in Bit_Pos_Range loop gas (crit) := gas (crit) * 2; if keep (pos) = 1 then gas (crit) := gas (crit) + 1; end if; end loop; end loop; if verbose then Put_Line (+"Oxygen: " & gas (most)); Put_Line (+"CO2: " & gas (least)); end if; res_2 := gas (most) * gas (least); -- if compiler_test_mode then if res_1 /= Integer_Value (Argument (1)) or res_2 /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Result Part 1: " & res_1); Put_Line (+"Result Part 2: " & res_2); -- Part 1: validated by AoC: 3549854 -- Part 2: validated by AoC: 3765399 end if; end AoC_2021_03; ================================================ FILE: exm/aoc/2021/aoc_2021_03.txt ================================================ 000000011010 011001111011 100101011101 000110000110 101010001010 010010000011 011001111001 100111000000 011101011010 000000110001 101110111100 111110100001 000000001111 001011111111 101011001111 101000101010 110111010001 000010011111 000101001011 101111001001 100000000100 010100010100 100110001110 101011101110 111100101101 000101000001 001110000011 111010110001 101000101000 011011000101 000001100100 101001011101 001111111111 101001001101 100100100001 101111000100 000110101000 001100011001 101111101000 101010110000 110100010001 101110101100 010101100100 011101100110 101000011011 101110101011 110100001100 100111000001 010000100000 111010110010 111110100111 001101110111 001001100100 000110100100 011100110010 100110001100 011011110110 110001011100 101111001111 110011011101 111001100110 110110011001 111011000000 000101101011 111110101110 000100011000 000001000001 010110000011 000100011100 011000110000 101011010101 100101110101 110001010010 101111001101 101110011010 101110000010 010001111010 100000111111 000000010011 100010111011 000110100000 101111000101 001110011101 100011010010 100001011101 011100101100 111100010010 111011011110 010010000110 010100001011 011000100010 100011001000 011001101001 110110010001 111110001001 000111101100 100111000011 111011110100 101000000010 011000110101 101010110101 110110000011 111101000110 010000100110 000110101010 111100110110 111000011101 010001011101 101011011000 101000101110 110101010001 000001110011 110010001110 110110000101 110111111001 110001000101 001101010011 010100011100 111011100100 101010001011 001011101011 101100010001 010100000000 110100000100 010011111111 101010010100 111101000101 000011000011 001111100000 010110101110 001010110010 000111100001 101000101101 111101110010 000000101011 110010000111 001111100110 000100001110 110101101000 000010100001 000111010011 010110001101 111110011001 011011111001 000011010011 001111000000 011000010001 000100011011 110011111011 001011101101 010111011111 001001110111 100110100011 000001110100 000010011000 110001101000 000001100111 011110100000 110000001000 110000001110 000010001100 000011100010 101100111101 101000000011 110011001010 110100110000 100101001010 111000111011 100011001010 111111111110 111100000011 011101110101 010100001111 010110010000 000011010100 011111010001 111011000010 111110000110 101100101101 010111011001 001001111100 001101010000 011000100000 001011111110 100010101111 001100010101 001000001111 110001010011 000000011100 011100010001 000111100101 010000010110 000001111100 010010110111 110101001100 001011001100 111111011100 111001100101 001010010000 101100101001 101100110011 011100111100 110001110100 101000101111 110011111001 011101000010 100001111001 010101111101 101101010010 110001011010 110100100001 011011110111 101110110000 110111001001 000011110100 101000110001 011110110111 011011101001 101011101001 100001111011 101001010011 110000010010 001011110110 110001011011 101100100001 001010000101 101011000100 000111110100 011010000010 110000011001 010001011110 001000100011 010000111010 011010111000 000001110010 010010011111 100100010000 001000000110 100001110111 000100010000 000010110000 010100111101 100001100111 100101101011 000010111010 010110111100 100101010110 001000101000 011101101011 000111101001 001000010101 101011010001 001110101100 010010100100 101101101100 000010111101 000100111000 100010110000 001100101111 111110000011 001101101100 110101001111 110010101010 011111000101 111001111101 000011001101 000000011001 010001110001 001001010011 110101110101 011011110010 111010110111 011000011110 111110011110 110001001101 010110100100 011100000101 000111110111 101110100010 000000011000 011101010011 001111100001 110010010101 101001001100 000111100011 101111100011 001100010001 110001100101 011001101100 000011000010 000001111000 110010001100 110011010011 010111100001 101101101101 010010100110 010001101100 111100100001 001000001001 110110101000 000011000001 001001001011 001101100100 100011111110 100101110110 001100010000 100111100111 010111100111 110011101111 010001101010 011010011111 001011000110 010001100000 111001010011 010011100111 101000111110 110110110110 000011111001 101011100110 000010011110 010001111101 100111010101 100111001001 100000010011 000011111010 110010100010 101101000001 111000001010 011111101100 001100001101 000100010011 010110011110 001110001011 101110011111 011111000010 110101001000 000000110100 110110101101 010111110100 110000000001 100011100001 100000010110 010100100110 100111111001 000110111110 000000110000 110001110101 101110110110 101011110101 110100110010 010000001010 110001111111 000110101101 111100010110 110011100011 110000000111 110011011011 111111001110 111110111001 110001110110 001101000000 001011111001 110001001010 001000010100 001011110001 000000010000 111111000001 110010000110 111010011111 100100100100 000000000101 100001010000 110101110111 001011111100 100111101100 100011110110 110110111100 001001010001 011100111101 110110001101 111100001011 000000100100 111101101010 111001111100 010101110011 101010100110 100001000101 100110011101 101101000100 100000011011 001001101000 001010011110 100010011011 011100010111 011101000111 111100101110 100100000111 100101110001 100000011101 001000011001 010101100110 101001101010 100011110000 101010100000 111000101100 111000101110 101000100001 100110000100 010010110011 111001101011 011000000100 010100001000 010001101001 001111101001 010010110010 101110010011 011000101001 111000111001 110010011011 110011010100 100010110110 110000011011 111100100100 101001111011 110100010011 101110100100 000011111000 001110101011 101000001111 111100000100 010110001110 010111011010 100100101011 110010111111 011001011011 000101100001 010011001001 000111111010 000000011111 011011000011 111011110001 110110010101 111100010000 011101100001 001110000010 110101011010 000101011100 011110000011 100010010011 011100100000 001111111101 000101000111 001001011010 101111111001 110000111011 000001100001 101000100111 111111101100 110001100111 101110010110 100110000111 000110000010 100001110100 101111011011 110110000010 111000001101 110100010010 100011010011 110000111110 110100000000 101110000001 001001011111 101000000101 000100110111 111010000101 010111100101 010011100011 100110100001 110101011101 100011000101 001001111101 100111000110 001001110101 111110010110 011000000111 010011101110 111010011000 001101100010 111101100101 101011100000 101100100011 100010101101 010000101101 111000000010 000010001010 000110101110 000110110001 111110111101 001111110100 101101110011 011110011011 100010110111 001110000101 101010001000 110000110101 000110000011 101101111001 101100001011 010000001101 101110110010 101001111001 000100110100 111100001000 101010100010 010100011111 011110001101 001100100001 110100011101 000001001101 000001001111 110000010000 110010111011 100001111100 110100000010 010111100100 111011001110 100101000100 111011010010 011101000011 011100010100 010101000010 010110100001 010011001100 011100100100 100000111010 011001000111 011101011101 100010101001 011001111110 011101110001 001110100010 011100010110 100111110001 000101001100 001101110001 110101110000 000110011001 100000111000 111101010001 000001110001 110111001000 110110110111 110111101100 001110010110 100001111101 110101101111 000110010101 100010001010 001110110000 111000110100 010101111100 001000101010 011010111101 110001110111 000010001000 100100011100 001000100110 100000100110 101001110100 100111001011 000011010010 010111001010 111000000011 110110110000 010110101010 110011010110 101101001010 011110110001 100011011101 001110010011 011100000100 111100100101 111011110010 010110011101 111101000100 000110111011 000001011000 101111110000 101000100110 100100100000 001010001110 000111011110 101000100100 011111110111 111100011001 101010010001 101100011101 011000011000 011111100100 001100101000 110001100001 000010010111 110100001111 010010011001 010100100100 110110101111 001010110000 110011010111 000010010101 100111001110 001100101011 001111111100 010111111100 101101000010 000001001110 011111111110 001010000111 111011010110 110110100011 010001101000 010011010111 000100001010 010000100010 000111100100 011000010011 001011000001 001101001111 100111010111 100010100001 010000110110 111010101011 010111011100 011111011010 001110100101 010100110010 100001000010 011111110011 100011011010 110100011100 011101111011 101011011100 111110001011 101011010010 111010101101 011110010111 011101100111 000110100010 110011100110 100000010101 111111100111 101000110101 110011001101 100010011111 111000011011 101010000000 111100110010 001000011101 001001100110 101011001011 010011111010 110000110100 100010000000 100111111111 101011100010 011000100100 111101010100 100011111101 010001110100 100100101110 111111000000 001101111101 011100101011 111011110111 001001101101 110110000100 101100111110 000000001100 110100011010 001011010010 111000110101 011111100001 000000101110 110000010111 100011111011 111111000101 110011101110 000011000111 001011101100 100000000000 011001010011 111001010010 000110101111 111111111000 000101110100 111000010000 100011011100 111001111000 101001011010 011101111000 111111110101 100110101110 100100010001 100000101100 001000001101 000010110010 110001000011 111111011011 010100010111 101010001001 000111011011 001011111101 110111110011 011001100010 011101111010 001000000001 101001100100 110101110100 111110011111 111011111011 111011111010 101010000001 001011010110 111001011111 100011110001 011100101101 010010010100 001001100010 110110000110 011111011011 001100100110 011110111010 010101011101 110101100011 001101110110 011110101111 001101110101 001100001111 100101111110 101111001011 001000110000 001110000001 100110101111 111001000011 101101111000 000010000101 010011001101 111110000001 001111101011 111010001100 101001101001 001011101010 101001100101 011100001001 000100011111 101101001101 111110111011 000100011101 100101101000 101110011011 001111100010 101110011110 110001000100 110101010100 011101000101 011110001010 110100011000 001000100100 111000011100 000111110101 011010101011 000011110111 100111110100 100110100101 011100100110 000111111001 010001110010 001110111001 010011111100 100111011010 001001000110 111010010100 110101000011 100001111111 111001001011 001100100101 110001001111 011011010010 110110000000 010101111110 011011010000 110100101010 100001100001 010100110011 101000011101 111100000111 010100111010 101000001001 101110010000 010100010010 100110011110 010011111101 011011000000 101011100100 101100110100 111001101110 001101101111 101000010011 000101001111 001011101001 001011111000 001001010000 111110101001 110101100001 011100001010 100111010100 010001001111 001110100011 100101111100 010101011110 000110111010 111010101110 001110001110 011101001000 010001000000 011100110101 111111001100 011110101011 010111011000 100100111111 110111111000 001010100101 001110011001 010101001001 101111101010 011110001110 100001000110 110100001010 000011001011 101011000111 000010001001 011010100000 011101011100 110100000111 101000111000 011100011110 111101110001 001010010100 011111110101 111101000000 111000010111 001111010100 000110000000 001100010010 010000111000 111101101000 101001011001 010011100100 111101111000 101110001010 101101110111 010011000111 100000011100 100001100010 100011011111 010110001010 100011111100 110110011100 011111101101 111111101000 100101110000 100010100011 100000010000 100000100010 001111011110 000101111101 111111111111 111101100110 010111110110 101111100101 000010110111 010000011000 000010111000 010011111001 010011001010 101011101000 001010111000 010000110100 100011011011 100100000010 001011000011 001110011111 010000110010 010110110110 110100110110 000010101011 010101000101 001011010011 100011001101 001100000110 101010100101 111110011000 101110111111 111011101010 010000010011 101101110010 010110110101 000011111111 111111001010 000101000011 000100000110 111101110011 000010101010 100111011110 101110001001 100000000111 111000011001 101101101111 101110010111 111010011001 011010110001 010011101100 110110010011 010000001011 001010100001 110111011101 111110111000 110110101010 100011000111 101010111010 101101111110 100110101101 101111101101 111101100000 010110000101 101010001101 011110101010 000100001011 001001011001 000011000101 011110000010 111110001010 111101010111 011111000000 010000000011 101010100001 011101101110 110111110000 111111101001 100101111101 011011011001 101101000110 000101101000 110001011111 011100010011 111111111101 001010000100 111010001001 101110110011 111001010001 110011100100 000101100111 011000001000 011010101111 000101000010 111001000110 101101100001 101100010010 101000010000 001001111000 001100101100 100101010010 101000010110 111001100100 111001110010 100000010100 011011111111 100100001101 011010100110 101010010101 011101110111 110101011111 010101010110 011010000011 000010000100 011001100100 101011011111 110000100111 001011001001 000000101001 011000111010 100110001001 111011100101 000100101111 100001001001 101110000000 100001001110 111101100111 111011111100 000011011001 000000100001 ================================================ FILE: exm/aoc/2021/aoc_2021_03_questions.txt ================================================ --- Day 3: Binary Diagnostic --- The submarine has been making some odd creaking noises, so you ask it to produce a diagnostic report just in case. The diagnostic report (your puzzle input) consists of a list of binary numbers which, when decoded properly, can tell you many useful things about the conditions of the submarine. The first parameter to check is the power consumption. You need to use the binary numbers in the diagnostic report to generate two new binary numbers (called the gamma rate and the epsilon rate). The power consumption can then be found by multiplying the gamma rate by the epsilon rate. Each bit in the gamma rate can be determined by finding the most common bit in the corresponding position of all numbers in the diagnostic report. For example, given the following diagnostic report: 00100 11110 10110 10111 10101 01111 00111 11100 10000 11001 00010 01010 Considering only the first bit of each number, there are five 0 bits and seven 1 bits. Since the most common bit is 1, the first bit of the gamma rate is 1. The most common second bit of the numbers in the diagnostic report is 0, so the second bit of the gamma rate is 0. The most common value of the third, fourth, and fifth bits are 1, 1, and 0, respectively, and so the final three bits of the gamma rate are 110. So, the gamma rate is the binary number 10110, or 22 in decimal. The epsilon rate is calculated in a similar way; rather than use the most common bit, the least common bit from each position is used. So, the epsilon rate is 01001, or 9 in decimal. Multiplying the gamma rate (22) by the epsilon rate (9) produces the power consumption, 198. Use the binary numbers in your diagnostic report to calculate the gamma rate and epsilon rate, then multiply them together. What is the power consumption of the submarine? (Be sure to represent your answer in decimal, not binary.) --- Part Two --- Next, you should verify the life support rating, which can be determined by multiplying the oxygen generator rating by the CO2 scrubber rating. Both the oxygen generator rating and the CO2 scrubber rating are values that can be found in your diagnostic report - finding them is the tricky part. Both values are located using a similar process that involves filtering out values until only one remains. Before searching for either rating value, start with the full list of binary numbers from your diagnostic report and consider just the first bit of those numbers. Then: Keep only numbers selected by the bit criteria for the type of rating value for which you are searching. Discard numbers which do not match the bit criteria. If you only have one number left, stop; this is the rating value for which you are searching. Otherwise, repeat the process, considering the next bit to the right. The bit criteria depends on which type of rating value you want to find: To find oxygen generator rating, determine the most common value (0 or 1) in the current bit position, and keep only numbers with that bit in that position. If 0 and 1 are equally common, keep values with a 1 in the position being considered. To find CO2 scrubber rating, determine the least common value (0 or 1) in the current bit position, and keep only numbers with that bit in that position. If 0 and 1 are equally common, keep values with a 0 in the position being considered. For example, to determine the oxygen generator rating value using the same example diagnostic report from above: Start with all 12 numbers and consider only the first bit of each number. There are more 1 bits (7) than 0 bits (5), so keep only the 7 numbers with a 1 in the first position: 11110, 10110, 10111, 10101, 11100, 10000, and 11001. Then, consider the second bit of the 7 remaining numbers: there are more 0 bits (4) than 1 bits (3), so keep only the 4 numbers with a 0 in the second position: 10110, 10111, 10101, and 10000. In the third position, three of the four numbers have a 1, so keep those three: 10110, 10111, and 10101. In the fourth position, two of the three numbers have a 1, so keep those two: 10110 and 10111. In the fifth position, there are an equal number of 0 bits and 1 bits (one each). So, to find the oxygen generator rating, keep the number with a 1 in that position: 10111. As there is only one number left, stop; the oxygen generator rating is 10111, or 23 in decimal. Then, to determine the CO2 scrubber rating value from the same example above: Start again with all 12 numbers and consider only the first bit of each number. There are fewer 0 bits (5) than 1 bits (7), so keep only the 5 numbers with a 0 in the first position: 00100, 01111, 00111, 00010, and 01010. Then, consider the second bit of the 5 remaining numbers: there are fewer 1 bits (2) than 0 bits (3), so keep only the 2 numbers with a 1 in the second position: 01111 and 01010. In the third position, there are an equal number of 0 bits and 1 bits (one each). So, to find the CO2 scrubber rating, keep the number with a 0 in that position: 01010. As there is only one number left, stop; the CO2 scrubber rating is 01010, or 10 in decimal. Finally, to find the life support rating, multiply the oxygen generator rating (23) by the CO2 scrubber rating (10) to get 230. Use the binary numbers in your diagnostic report to calculate the oxygen generator rating and CO2 scrubber rating, then multiply them together. What is the life support rating of the submarine? (Be sure to represent your answer in decimal, not binary.) ================================================ FILE: exm/aoc/2021/aoc_2021_04.adb ================================================ -- Solution to Advent of Code 2021, Day 04 ------------------------------------------- -- Giant Squid -- -- https://adventofcode.com/2021/day/4 -- Copy of questions in: aoc_2021_04_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_04 is use HAT; res_1, res_2 : Integer; sep : Character; f : File_Type; -- input : constant VString := +"aoc_2021_04.txt"; number_of_boards : constant := 100; subtype Boards_Range is Integer range 1 .. number_of_boards; first_winner, last_winner : Boards_Range; any_winner_yet : Boolean := False; -- list_max : constant := 2500; list : array (1 .. list_max) of Natural; top : Natural := 0; number_last_bingo, number_first_winner : Natural; board_size : constant := 5; subtype Board_Side_Range is Integer range 1 .. board_size; type Cell is record value : Natural; marked : Boolean; end record; type Board_Type is array (Board_Side_Range, Board_Side_Range) of Cell; board : array (Boards_Range) of Board_Type; won : array (Boards_Range) of Boolean; bingo : Boolean; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := False; begin -- -- Get and prepare data. -- Open (f, input); loop top := top + 1; Get (f, list (top)); exit when End_Of_Line (f); Get (f, sep); -- Absorb the ',' separator end loop; for b in Boards_Range loop won (b) := False; for i in Board_Side_Range loop for j in Board_Side_Range loop Get (f, board (b)(i, j).value); board (b)(i, j).marked := False; end loop; end loop; end loop; Close (f); -- numbers_loop : for n in 1 .. top loop -- Mark all boards with the number in list (n). boards_loop : for b in 1 .. number_of_boards loop if not won (b) then -- Mark and check rows: for i in Board_Side_Range loop bingo := True; for j in Board_Side_Range loop if list (n) = board (b)(i, j).value then board (b)(i, j).marked := True; else bingo := bingo and then board (b)(i, j).marked; end if; end loop; exit when bingo; end loop; if not bingo then -- Check columns: for j in Board_Side_Range loop bingo := True; for i in Board_Side_Range loop if not board (b)(i, j).marked then bingo := False; exit; end if; end loop; exit when bingo; end loop; end if; -- Process Bingo case: if bingo then won (b) := True; last_winner := b; number_last_bingo := list (n); if not any_winner_yet then any_winner_yet := True; first_winner := b; number_first_winner := number_last_bingo; end if; end if; end if; end loop boards_loop; end loop numbers_loop; -- if any_winner_yet then res_1 := 0; res_2 := 0; for i in Board_Side_Range loop for j in Board_Side_Range loop if not board (first_winner)(i, j).marked then res_1 := res_1 + board (first_winner)(i, j).value; end if; if not board (last_winner)(i, j).marked then res_2 := res_2 + board (last_winner)(i, j).value; end if; end loop; end loop; if verbose then Put_Line (+"First winner " & first_winner & "; score 1: " & res_1 & " * " & number_first_winner); Put_Line (+"Last winner " & last_winner & "; score 2: " & res_2 & " * " & number_last_bingo); end if; res_1 := res_1 * number_first_winner; res_2 := res_2 * number_last_bingo; else Put_Line ("Uh? No Bingo?"); end if; -- if compiler_test_mode then if res_1 /= Integer_Value (Argument (1)) or res_2 /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1: " & res_1); Put_Line (+"Part 2: " & res_2); -- Part 1: validated by AoC: 39984 -- Part 2: validated by AoC: 8486 end if; end AoC_2021_04; ================================================ FILE: exm/aoc/2021/aoc_2021_04.txt ================================================ 10,80,6,69,22,99,63,92,30,67,28,93,0,50,65,87,38,7,91,60,57,40,84,51,27,12,44,88,64,35,39,74,61,55,31,48,81,89,62,37,94,43,29,14,95,8,78,49,90,97,66,70,25,68,75,45,42,23,9,96,56,72,59,32,85,3,71,79,18,24,33,19,15,20,82,26,21,13,4,98,83,34,86,5,2,73,17,54,1,77,52,58,76,36,16,46,41,47,11,53 3 82 18 50 90 16 37 52 67 28 30 54 80 11 10 60 79 7 65 58 76 83 38 51 1 83 63 60 88 98 70 87 5 99 14 85 3 11 16 33 72 69 97 36 49 26 17 58 13 2 30 80 64 53 69 36 0 32 46 70 13 31 22 95 15 12 35 5 84 21 39 60 68 83 47 77 93 26 62 88 87 76 80 10 63 32 7 28 82 44 43 30 31 16 74 33 86 42 45 47 95 86 93 45 67 20 58 63 35 97 84 79 10 54 49 48 66 75 23 61 5 30 6 56 71 75 8 85 12 98 37 51 91 24 23 50 54 81 53 33 72 57 52 25 6 56 40 95 87 22 52 19 53 9 32 23 99 48 26 73 10 8 54 20 79 49 45 34 74 90 27 72 30 13 57 1 60 72 85 64 62 39 56 93 78 90 17 87 48 7 9 13 45 23 69 44 80 86 55 21 86 57 25 98 18 42 75 38 9 66 54 19 99 87 49 33 32 53 8 6 17 68 24 58 95 2 5 80 10 61 27 16 40 67 78 66 13 24 42 75 25 7 35 11 85 93 38 4 31 77 52 81 68 88 95 82 50 46 87 20 3 54 59 75 51 92 93 38 72 4 8 77 61 31 56 45 16 8 44 62 92 23 42 20 74 73 83 65 9 84 55 13 21 70 59 34 2 98 47 37 3 54 85 79 76 42 29 45 12 46 60 59 24 67 80 89 15 99 68 48 40 7 95 44 70 75 31 99 16 32 80 56 43 30 36 66 73 35 20 61 67 28 89 23 54 47 26 69 70 50 35 91 81 13 15 73 1 37 68 28 98 29 9 22 56 12 59 82 67 31 77 47 32 79 52 22 73 39 14 46 99 0 27 34 40 4 5 38 23 18 64 26 89 59 79 71 76 53 49 62 14 37 27 67 94 76 16 79 61 83 8 43 36 28 75 10 4 24 56 44 26 1 88 9 86 14 78 43 10 30 56 29 1 61 9 7 95 39 35 25 33 87 71 97 21 72 0 4 2 24 88 0 72 42 6 53 79 58 80 20 57 84 15 21 64 98 17 43 8 95 2 22 59 63 78 78 21 33 57 72 10 69 85 73 16 92 60 87 39 63 40 15 77 80 56 6 62 99 50 3 38 72 34 41 74 90 29 9 6 91 94 39 56 71 67 53 21 22 32 10 73 48 79 47 85 5 49 73 24 8 75 12 11 47 69 66 70 89 62 48 99 3 29 88 30 10 40 32 33 43 61 93 2 58 84 47 62 51 16 82 80 22 50 31 65 76 85 83 4 40 86 59 68 14 69 52 5 74 9 72 84 69 38 1 27 78 90 46 97 95 57 21 32 93 29 11 66 20 51 48 2 3 58 18 53 11 96 63 33 13 55 47 30 9 46 98 85 79 19 65 87 94 77 27 75 54 97 46 33 90 99 93 22 0 51 83 53 34 29 38 35 65 80 82 9 56 30 19 49 15 43 40 51 67 37 4 30 85 24 21 83 94 69 91 99 13 32 82 86 12 66 9 60 65 97 71 96 55 92 6 83 8 63 56 18 4 0 74 70 34 15 87 44 80 29 68 33 99 14 47 76 86 46 6 8 90 80 77 30 62 97 66 55 59 36 1 43 27 15 57 54 70 38 21 89 75 96 97 54 29 62 43 69 57 88 36 46 73 84 28 18 98 38 63 4 59 35 99 90 58 66 29 60 25 95 91 4 87 76 41 26 19 45 96 74 7 82 3 81 31 17 64 51 93 71 41 51 14 70 26 35 38 50 25 13 95 60 88 36 24 66 94 62 97 83 21 10 37 1 96 38 90 81 96 14 40 82 71 18 83 78 17 65 46 84 7 92 63 79 49 55 21 89 95 72 60 35 26 67 42 59 77 15 6 75 18 16 21 55 4 98 49 38 43 30 0 85 69 96 19 93 22 87 66 94 7 43 98 18 57 29 20 91 60 21 28 51 17 10 14 96 12 15 25 37 12 69 27 41 36 58 11 42 44 9 8 56 33 7 30 70 64 78 17 61 22 28 94 0 99 16 64 88 22 48 65 42 23 7 26 97 12 63 57 45 29 94 91 21 54 95 43 0 85 46 9 50 54 98 35 45 37 84 87 5 40 23 14 17 18 73 43 86 41 59 69 77 78 15 60 79 9 45 59 85 38 56 64 95 60 39 22 14 57 66 98 53 83 76 16 62 94 72 54 82 77 44 6 66 46 9 89 11 84 63 81 94 87 83 21 22 90 1 93 92 24 65 34 45 99 36 93 59 5 43 76 49 51 0 68 71 34 55 7 73 14 10 45 63 95 30 94 79 67 11 93 98 82 96 91 3 79 55 70 24 68 56 87 12 76 19 31 67 1 54 49 62 23 15 10 10 74 98 15 6 14 31 66 38 86 68 84 60 80 26 34 72 87 92 61 81 56 73 12 53 11 69 4 6 23 38 47 16 99 96 7 13 40 41 78 12 5 1 18 88 20 42 10 82 73 66 97 72 55 99 26 59 6 79 53 74 80 98 28 69 25 95 17 29 34 85 64 84 90 42 95 50 58 51 66 48 27 81 94 0 35 82 57 71 16 32 93 70 40 25 31 73 46 12 90 39 94 52 9 88 3 23 59 77 29 2 40 93 85 38 74 97 12 50 1 22 36 68 65 37 70 15 44 90 55 42 20 82 0 78 10 49 62 3 22 91 73 84 40 28 72 13 11 60 19 58 95 66 36 22 91 99 77 94 44 70 14 85 13 52 49 6 2 50 35 47 42 15 98 63 35 1 99 21 68 93 32 30 76 5 79 96 10 85 16 19 69 81 78 70 66 36 26 94 39 78 51 55 4 97 21 36 53 1 26 77 42 20 12 65 17 52 6 40 16 19 85 2 24 23 95 68 76 14 30 19 11 64 99 60 63 55 8 40 65 41 75 62 53 83 26 34 46 72 79 68 6 35 62 77 43 14 88 7 11 40 45 98 86 64 3 53 56 87 30 28 37 48 10 72 13 69 72 93 17 1 46 8 56 37 78 27 49 64 59 81 99 33 76 79 84 98 51 82 31 57 41 45 15 10 65 72 79 17 29 67 0 33 32 69 56 96 92 46 53 88 3 18 87 51 97 52 58 67 17 51 69 43 20 63 1 26 27 47 99 53 23 14 90 86 4 56 13 36 11 88 11 57 73 89 43 34 91 15 58 9 39 18 12 14 1 98 29 77 52 84 97 96 68 10 99 5 69 53 45 10 43 24 60 55 64 57 30 3 0 22 65 68 32 83 52 38 74 97 20 27 25 33 41 67 54 42 3 1 55 66 92 44 98 35 14 82 5 10 39 52 79 69 76 48 64 58 60 91 42 45 55 35 9 72 36 74 99 33 26 67 4 25 50 14 15 2 96 82 11 34 84 90 95 26 8 66 52 43 63 79 98 36 85 41 47 24 33 88 71 86 91 83 40 18 79 68 49 64 35 23 57 27 77 71 95 39 43 19 98 78 62 65 58 60 52 73 82 4 32 22 54 57 45 3 43 85 30 60 94 35 46 28 55 6 82 42 13 83 59 76 70 41 61 1 76 89 34 96 1 95 60 55 23 88 37 13 61 92 62 98 77 32 82 31 33 74 71 58 86 73 91 92 49 44 53 6 29 8 95 4 31 54 20 97 98 57 2 65 75 43 88 1 58 0 49 91 70 1 79 17 90 33 65 54 56 47 63 83 52 8 45 72 84 39 43 37 71 97 59 90 93 20 31 96 98 84 2 87 73 97 16 19 24 38 14 11 94 92 36 4 10 27 44 30 20 77 81 80 28 35 51 93 24 62 54 56 41 68 79 29 67 89 60 12 63 91 18 90 99 28 48 94 50 73 20 27 34 59 43 66 55 35 98 57 40 53 21 99 4 17 74 80 5 12 76 22 6 61 23 70 67 69 33 9 87 2 12 68 27 13 52 82 15 84 24 51 89 53 38 96 23 91 97 10 50 8 68 67 0 65 3 92 4 70 53 77 59 86 66 41 78 44 52 71 62 19 17 63 75 43 88 15 84 13 41 7 47 16 23 12 71 8 83 50 36 31 22 5 79 71 95 17 90 63 64 52 32 3 93 70 13 99 40 5 22 18 83 11 55 47 59 78 45 29 9 98 73 46 79 5 51 84 26 40 64 62 0 66 18 33 83 47 1 63 89 31 99 54 36 98 15 86 9 50 67 7 75 85 17 96 27 64 81 19 80 30 29 54 52 49 25 36 5 90 39 29 40 16 69 38 55 67 71 59 42 72 51 10 45 94 75 21 27 0 84 6 22 33 30 33 64 82 97 39 79 7 62 49 99 26 3 13 66 10 37 98 15 80 47 1 35 30 50 43 56 92 41 82 34 68 79 11 0 65 70 84 26 76 96 1 72 31 80 8 9 38 98 17 7 12 19 6 29 89 96 87 70 75 77 84 74 64 54 13 16 68 44 79 43 61 47 69 26 50 43 20 45 21 87 80 50 83 26 49 64 99 71 75 9 18 96 6 94 88 76 97 51 11 74 85 47 25 72 93 96 36 81 55 27 63 18 57 1 29 9 35 83 88 98 90 21 3 67 82 58 94 55 10 98 2 24 71 93 57 74 34 21 35 73 89 88 6 16 8 76 81 38 28 83 36 53 63 67 18 51 74 60 69 85 32 22 80 58 98 34 92 13 12 26 46 61 31 96 47 90 1 5 10 48 12 76 95 83 17 24 84 65 44 28 81 80 41 79 15 29 61 75 94 40 65 22 40 75 86 93 77 46 35 87 88 5 91 48 74 92 28 66 47 30 69 2 29 67 94 78 38 1 53 68 84 70 26 7 72 92 87 55 47 6 51 82 36 73 28 75 58 35 49 56 61 85 60 19 24 16 23 71 74 33 42 7 57 82 70 14 97 59 99 49 46 30 89 79 41 5 24 92 19 65 0 80 33 78 23 4 37 31 16 41 79 73 88 36 67 86 29 62 61 71 40 51 27 57 85 53 68 31 60 83 48 69 24 17 96 54 89 22 77 64 95 26 21 65 41 48 7 20 68 21 31 22 1 99 96 82 63 78 2 70 18 83 58 92 51 81 64 98 44 89 23 74 99 75 6 81 14 37 8 85 12 36 55 20 47 88 7 90 87 43 3 44 83 15 2 97 15 69 76 95 13 44 31 10 14 40 83 49 11 65 43 98 55 92 89 90 33 73 32 53 25 79 77 83 68 5 10 23 15 19 18 4 92 51 76 17 90 70 49 39 74 63 75 42 67 46 66 18 17 28 75 76 78 72 44 57 39 97 27 99 36 58 62 90 82 14 45 48 64 1 51 90 58 6 37 28 30 57 54 10 45 80 39 4 0 29 17 66 18 55 96 44 36 76 34 94 50 0 71 99 11 67 96 87 64 48 30 31 68 40 89 55 23 92 42 16 62 37 83 33 66 42 91 70 72 28 69 96 17 71 99 5 2 26 19 60 87 51 83 76 77 33 64 61 54 61 93 90 82 88 80 11 25 40 28 60 29 34 39 21 24 13 72 77 2 19 95 47 17 0 86 97 50 42 87 7 18 80 23 30 41 6 96 92 98 36 45 77 71 38 19 40 47 39 53 83 7 80 86 65 37 22 19 84 92 29 17 76 4 33 97 50 1 12 21 15 58 39 38 74 ================================================ FILE: exm/aoc/2021/aoc_2021_04_questions.txt ================================================ --- Day 4: Giant Squid --- You're already almost 1.5km (almost a mile) below the surface of the ocean, already so deep that you can't see any sunlight. What you can see, however, is a giant squid that has attached itself to the outside of your submarine. Maybe it wants to play bingo? Bingo is played on a set of boards each consisting of a 5x5 grid of numbers. Numbers are chosen at random, and the chosen number is marked on all boards on which it appears. (Numbers may not appear on all boards.) If all numbers in any row or any column of a board are marked, that board wins. (Diagonals don't count.) The submarine has a bingo subsystem to help passengers (currently, you and the giant squid) pass the time. It automatically generates a random order in which to draw numbers and a random set of boards (your puzzle input). For example: 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 22 13 17 11 0 8 2 23 4 24 21 9 14 16 7 6 10 3 18 5 1 12 20 15 19 3 15 0 2 22 9 18 13 17 5 19 8 7 25 23 20 11 10 24 4 14 21 16 12 6 14 21 17 24 4 10 16 15 9 19 18 8 23 26 20 22 11 13 6 5 2 0 12 3 7 After the first five numbers are drawn (7, 4, 9, 5, and 11), there are no winners, but the boards are marked as follows (shown here adjacent to each other to save space): 22 13 17 11 0 3 15 0 2 22 14 21 17 24 4 8 2 23 4 24 9 18 13 17 5 10 16 15 9 19 21 9 14 16 7 19 8 7 25 23 18 8 23 26 20 6 10 3 18 5 20 11 10 24 4 22 11 13 6 5 1 12 20 15 19 14 21 16 12 6 2 0 12 3 7 After the next six numbers are drawn (17, 23, 2, 0, 14, and 21), there are still no winners: 22 13 17 11 0 3 15 0 2 22 14 21 17 24 4 8 2 23 4 24 9 18 13 17 5 10 16 15 9 19 21 9 14 16 7 19 8 7 25 23 18 8 23 26 20 6 10 3 18 5 20 11 10 24 4 22 11 13 6 5 1 12 20 15 19 14 21 16 12 6 2 0 12 3 7 Finally, 24 is drawn: 22 13 17 11 0 3 15 0 2 22 14 21 17 24 4 8 2 23 4 24 9 18 13 17 5 10 16 15 9 19 21 9 14 16 7 19 8 7 25 23 18 8 23 26 20 6 10 3 18 5 20 11 10 24 4 22 11 13 6 5 1 12 20 15 19 14 21 16 12 6 2 0 12 3 7 At this point, the third board wins because it has at least one complete row or column of marked numbers (in this case, the entire top row is marked: 14 21 17 24 4). The score of the winning board can now be calculated. Start by finding the sum of all unmarked numbers on that board; in this case, the sum is 188. Then, multiply that sum by the number that was just called when the board won, 24, to get the final score, 188 * 24 = 4512. To guarantee victory against the giant squid, figure out which board will win first. What will your final score be if you choose that board? --- Part Two --- On the other hand, it might be wise to try a different strategy: let the giant squid win. You aren't sure how many bingo boards a giant squid could play at once, so rather than waste time counting its arms, the safe thing to do is to figure out which board will win last and choose that one. That way, no matter which boards it picks, it will win for sure. In the above example, the second board is the last to win, which happens after 13 is eventually called and its middle column is completely marked. If you were to keep playing until this point, the second board would have a sum of unmarked numbers equal to 148 for a final score of 148 * 13 = 1924. Figure out which board will win last. Once it wins, what would its final score be? ================================================ FILE: exm/aoc/2021/aoc_2021_05.adb ================================================ -- Solution to Advent of Code 2021, Day 05 ------------------------------------------- -- Hydrothermal Venture -- -- https://adventofcode.com/2021/day/5 -- Copy of questions in: aoc_2021_05_questions.txt -- -- HAC 0.098 "nice to have"'s detected in this exercise: -- -- * ` hits := (others => (others => 0)); ` -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_05 is use HAT; sep_1, sep_3 : Character; sep_2 : String (1 .. 3); res : array (1 .. 2) of Integer; f : File_Type; -- input : constant VString := +"aoc_2021_05.txt"; subtype X_Range is Integer range 0 .. 1000; subtype Y_Range is Integer range 0 .. 1000; x1, x2, xx : X_Range; y1, y2, yy : Y_Range; len : Natural; dx, dy : Integer; hits : array (X_Range, Y_Range) of Natural; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; begin for x in X_Range loop for y in Y_Range loop hits (x, y) := 0; end loop; end loop; -- for part in 1 .. 2 loop Open (f, input); while not End_Of_File (f) loop Get (f, x1); Get (f, sep_1); Get (f, y1); Get (f, sep_2); Get (f, x2); Get (f, sep_3); Get (f, y2); case part is when 1 => if x1 = x2 then for y in Min (y1, y2) .. Max (y1, y2) loop hits (x1, y) := hits (x1, y) + 1; end loop; elsif y1 = y2 then for x in Min (x1, x2) .. Max (x1, x2) loop hits (x, y1) := hits (x, y1) + 1; end loop; end if; when 2 => if x1 /= x2 and then y1 /= y2 then -- The hydrothermal vent mapping systems assumes a diagonal. xx := x1; yy := y1; dx := (x2 - x1) / abs (x2 - x1); dy := (y2 - y1) / abs (y2 - y1); len := abs (x2 - x1); for draw in 0 .. len loop hits (xx, yy) := hits (xx, yy) + 1; if draw < len then xx := xx + dx; yy := yy + dy; end if; end loop; end if; end case; end loop; Close (f); -- res (part) := 0; for x in X_Range loop for y in Y_Range loop if hits (x, y) >= 2 then res (part) := res (part) + 1; end if; end loop; end loop; end loop; -- if compiler_test_mode then if res (1) /= Integer_Value (Argument (1)) or res (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1: crossings of horizontal and vertical lines: " & res (1)); Put_Line (+"Part 2: crossings, including diagonals: " & res (2)); -- Part 1: validated by AoC: 6225 -- Part 2: validated by AoC: 22116 end if; end AoC_2021_05; ================================================ FILE: exm/aoc/2021/aoc_2021_05.txt ================================================ 955,125 -> 151,929 830,251 -> 526,555 182,185 -> 13,16 73,871 -> 73,951 169,968 -> 626,968 471,180 -> 471,746 725,478 -> 791,544 577,413 -> 577,753 636,937 -> 181,937 46,601 -> 714,601 400,905 -> 400,972 911,773 -> 883,801 818,684 -> 818,705 71,846 -> 151,846 737,489 -> 626,378 634,800 -> 634,482 401,209 -> 401,469 676,688 -> 384,396 247,819 -> 680,819 944,343 -> 196,343 57,689 -> 586,160 13,54 -> 918,959 736,490 -> 520,706 331,20 -> 208,20 639,865 -> 322,548 914,227 -> 914,980 163,411 -> 163,825 344,58 -> 344,199 274,153 -> 989,153 15,14 -> 983,982 784,269 -> 332,721 206,921 -> 206,331 219,944 -> 260,903 81,92 -> 976,987 325,633 -> 502,810 887,850 -> 887,83 203,756 -> 203,627 447,33 -> 748,33 87,245 -> 87,932 817,324 -> 881,324 922,227 -> 167,982 626,867 -> 155,396 743,689 -> 743,779 516,433 -> 133,433 444,407 -> 614,407 42,140 -> 475,140 311,422 -> 311,514 526,59 -> 643,59 709,69 -> 455,69 136,46 -> 159,46 300,113 -> 763,576 979,977 -> 18,16 380,490 -> 380,556 134,726 -> 134,287 317,717 -> 383,717 726,712 -> 211,197 703,952 -> 165,952 806,575 -> 122,575 589,691 -> 589,716 965,337 -> 879,337 938,23 -> 57,904 186,141 -> 385,141 864,744 -> 959,744 276,957 -> 636,957 98,846 -> 98,349 559,261 -> 559,63 564,808 -> 564,429 491,362 -> 491,746 513,250 -> 897,250 939,442 -> 249,442 366,678 -> 916,678 325,79 -> 604,358 513,890 -> 133,890 360,88 -> 427,88 777,266 -> 522,266 371,859 -> 776,859 111,600 -> 111,980 366,471 -> 646,191 849,407 -> 933,407 867,681 -> 570,384 467,707 -> 797,377 624,304 -> 852,76 341,149 -> 575,383 34,499 -> 736,499 13,312 -> 927,312 897,188 -> 897,639 372,665 -> 372,501 651,22 -> 173,22 450,394 -> 450,798 140,584 -> 140,960 223,919 -> 980,919 893,645 -> 429,181 284,488 -> 207,411 823,868 -> 622,667 426,881 -> 868,881 49,63 -> 974,988 921,475 -> 81,475 166,653 -> 166,913 40,191 -> 767,918 911,499 -> 911,363 966,960 -> 84,78 193,522 -> 193,379 208,255 -> 673,255 684,837 -> 684,192 921,758 -> 921,841 756,244 -> 756,277 866,533 -> 866,186 97,747 -> 798,46 415,287 -> 415,759 570,824 -> 902,824 341,792 -> 44,792 849,787 -> 161,99 501,621 -> 565,685 409,62 -> 215,256 591,780 -> 855,780 901,67 -> 901,223 662,212 -> 578,212 196,924 -> 196,94 404,492 -> 300,492 10,984 -> 984,10 722,739 -> 722,775 805,637 -> 805,299 848,722 -> 707,722 444,597 -> 158,597 402,57 -> 509,57 490,353 -> 273,353 868,208 -> 421,655 102,930 -> 903,129 557,877 -> 557,529 27,69 -> 843,885 549,695 -> 468,695 767,701 -> 104,701 415,141 -> 415,809 205,767 -> 205,427 264,723 -> 952,35 357,279 -> 390,279 529,436 -> 250,715 390,472 -> 889,971 983,11 -> 21,973 732,307 -> 112,927 412,801 -> 252,801 738,338 -> 738,94 80,135 -> 952,135 623,269 -> 870,516 216,507 -> 32,507 927,10 -> 927,946 389,955 -> 389,399 683,825 -> 629,879 163,450 -> 208,495 303,217 -> 831,217 827,632 -> 827,736 629,880 -> 629,533 368,67 -> 111,67 625,268 -> 397,268 737,335 -> 299,773 666,767 -> 494,939 144,238 -> 757,238 511,211 -> 270,211 312,901 -> 548,665 550,763 -> 47,763 942,403 -> 464,881 969,18 -> 15,972 963,831 -> 187,55 933,831 -> 933,408 733,658 -> 876,658 599,392 -> 980,11 44,406 -> 900,406 645,169 -> 577,237 731,41 -> 731,265 574,397 -> 574,249 316,279 -> 316,657 826,116 -> 18,924 611,892 -> 824,892 607,168 -> 607,85 371,914 -> 113,656 145,201 -> 458,514 813,952 -> 189,328 633,15 -> 239,409 832,278 -> 202,908 234,698 -> 509,423 635,27 -> 635,18 701,147 -> 701,577 777,722 -> 777,835 519,298 -> 497,298 80,71 -> 875,866 872,350 -> 58,350 128,711 -> 131,711 591,709 -> 362,480 129,647 -> 54,572 980,731 -> 282,33 245,813 -> 682,813 867,238 -> 463,642 511,888 -> 511,391 727,38 -> 289,38 311,888 -> 311,801 261,915 -> 926,250 855,835 -> 145,125 78,688 -> 826,688 989,40 -> 66,963 956,30 -> 101,885 665,826 -> 406,826 97,981 -> 985,93 971,847 -> 357,233 725,531 -> 725,556 63,570 -> 403,570 41,430 -> 577,430 40,54 -> 796,810 417,232 -> 417,392 214,800 -> 936,78 542,955 -> 146,955 76,263 -> 471,263 784,507 -> 784,858 443,222 -> 443,881 317,157 -> 317,956 245,599 -> 166,520 307,649 -> 307,313 399,782 -> 538,782 483,731 -> 294,731 950,903 -> 281,234 283,522 -> 866,522 472,505 -> 278,505 435,693 -> 845,283 881,751 -> 294,164 40,840 -> 179,979 481,398 -> 481,661 509,687 -> 509,875 976,866 -> 684,574 133,130 -> 158,130 268,81 -> 641,454 613,754 -> 393,974 980,984 -> 14,18 55,909 -> 952,12 865,132 -> 986,132 147,773 -> 147,414 135,62 -> 934,861 298,293 -> 298,978 583,990 -> 424,990 760,189 -> 516,189 286,292 -> 286,648 60,352 -> 60,830 335,241 -> 420,156 360,571 -> 360,354 361,233 -> 714,233 21,78 -> 922,979 35,748 -> 449,748 859,26 -> 73,812 277,827 -> 277,708 160,633 -> 515,278 673,422 -> 568,317 620,235 -> 620,645 538,698 -> 156,698 47,543 -> 439,543 65,975 -> 945,95 259,644 -> 242,644 777,216 -> 794,216 100,191 -> 835,926 450,581 -> 450,433 475,784 -> 475,118 840,584 -> 580,844 191,283 -> 191,58 170,650 -> 130,690 478,269 -> 478,781 44,981 -> 839,186 270,744 -> 270,902 941,960 -> 102,121 303,690 -> 303,467 150,18 -> 150,601 470,523 -> 240,523 166,575 -> 621,575 197,765 -> 691,271 164,798 -> 369,798 544,319 -> 677,319 31,212 -> 777,958 894,774 -> 894,752 567,225 -> 67,225 884,201 -> 184,201 675,961 -> 187,473 203,78 -> 203,690 52,945 -> 957,40 987,214 -> 987,762 792,975 -> 792,673 358,782 -> 598,542 105,716 -> 777,44 736,643 -> 245,643 507,940 -> 275,940 231,936 -> 231,209 204,545 -> 186,563 881,426 -> 881,460 315,867 -> 96,867 793,324 -> 642,324 276,709 -> 540,973 834,401 -> 834,701 616,874 -> 616,606 892,596 -> 892,570 255,919 -> 850,324 764,62 -> 82,744 682,374 -> 978,374 218,353 -> 218,787 140,289 -> 720,869 811,20 -> 811,203 165,291 -> 284,291 137,382 -> 137,767 15,14 -> 989,988 947,682 -> 499,234 751,356 -> 862,356 398,362 -> 398,494 260,32 -> 780,552 839,484 -> 584,484 198,865 -> 198,327 600,461 -> 418,279 346,439 -> 495,588 854,661 -> 775,661 119,575 -> 119,415 349,849 -> 349,421 13,401 -> 21,393 169,511 -> 169,61 848,678 -> 213,678 42,25 -> 729,712 903,740 -> 816,740 398,862 -> 398,116 443,624 -> 101,624 135,158 -> 223,158 440,742 -> 388,742 903,963 -> 49,109 131,198 -> 208,198 147,289 -> 147,663 684,307 -> 684,299 453,864 -> 453,404 361,982 -> 978,365 840,64 -> 563,64 377,301 -> 613,301 32,366 -> 609,366 867,240 -> 867,188 798,714 -> 956,714 617,792 -> 617,354 309,357 -> 309,797 824,888 -> 824,598 947,958 -> 305,316 505,934 -> 461,890 45,685 -> 597,133 875,170 -> 66,979 239,959 -> 985,213 769,423 -> 769,39 62,750 -> 764,48 749,798 -> 749,307 110,646 -> 241,777 93,804 -> 867,30 361,663 -> 856,663 494,788 -> 187,788 696,379 -> 696,823 664,935 -> 146,417 895,804 -> 895,144 200,240 -> 805,240 347,794 -> 487,934 978,920 -> 978,408 730,480 -> 390,140 933,810 -> 933,513 429,864 -> 134,864 476,339 -> 183,632 677,878 -> 677,417 980,261 -> 757,261 452,569 -> 452,280 535,223 -> 867,223 159,466 -> 983,466 332,155 -> 334,153 887,478 -> 887,179 173,245 -> 773,845 441,274 -> 632,465 987,389 -> 987,440 830,806 -> 747,806 103,82 -> 796,775 945,14 -> 129,14 110,873 -> 520,873 393,391 -> 291,391 598,125 -> 129,594 378,546 -> 175,546 302,558 -> 617,243 943,752 -> 244,53 972,943 -> 41,12 16,164 -> 124,164 270,815 -> 27,815 146,729 -> 146,317 153,255 -> 166,255 511,505 -> 270,505 404,568 -> 388,568 485,751 -> 485,785 752,686 -> 160,686 523,676 -> 385,676 854,437 -> 618,437 578,212 -> 875,509 800,115 -> 815,130 439,554 -> 868,983 225,803 -> 244,822 494,735 -> 655,574 932,191 -> 932,41 842,325 -> 630,325 201,288 -> 518,288 255,332 -> 53,332 385,959 -> 329,903 757,447 -> 276,447 884,957 -> 884,449 686,354 -> 195,354 384,677 -> 951,110 173,77 -> 164,77 767,840 -> 248,321 81,180 -> 81,371 517,838 -> 517,461 950,559 -> 221,559 934,826 -> 329,221 311,329 -> 311,146 140,459 -> 280,459 200,195 -> 24,19 517,270 -> 865,618 43,54 -> 939,950 853,339 -> 853,388 297,795 -> 240,795 358,890 -> 275,973 26,70 -> 931,975 781,141 -> 318,604 17,794 -> 204,794 87,534 -> 763,534 590,968 -> 590,613 358,836 -> 758,836 598,635 -> 764,635 313,670 -> 313,478 832,330 -> 832,629 973,36 -> 21,988 131,814 -> 709,236 261,163 -> 261,906 720,48 -> 659,48 988,152 -> 326,814 937,761 -> 690,761 988,784 -> 988,879 807,445 -> 336,916 933,978 -> 51,96 305,966 -> 305,402 184,687 -> 437,687 256,172 -> 186,172 508,162 -> 421,162 689,52 -> 740,52 545,807 -> 545,630 676,924 -> 620,924 976,68 -> 139,905 322,96 -> 45,96 663,407 -> 199,871 562,636 -> 224,974 172,439 -> 126,439 740,628 -> 852,628 252,28 -> 596,372 129,850 -> 571,408 75,446 -> 399,446 67,460 -> 704,460 932,531 -> 932,60 520,229 -> 255,494 462,756 -> 462,614 158,117 -> 592,551 203,722 -> 203,892 93,822 -> 207,822 634,172 -> 634,457 272,365 -> 272,377 989,23 -> 25,987 739,776 -> 40,776 843,708 -> 24,708 665,10 -> 665,728 271,858 -> 11,598 947,642 -> 629,960 230,760 -> 938,52 291,552 -> 291,388 689,400 -> 260,829 610,194 -> 470,194 628,824 -> 45,241 935,940 -> 51,56 90,871 -> 90,933 973,934 -> 104,65 435,245 -> 768,245 43,666 -> 625,666 770,563 -> 724,563 363,816 -> 363,889 25,725 -> 701,49 784,846 -> 484,846 989,293 -> 989,502 572,135 -> 485,135 683,807 -> 370,494 982,182 -> 225,939 838,522 -> 520,522 253,942 -> 970,225 442,963 -> 577,963 867,193 -> 307,753 269,204 -> 771,204 941,925 -> 136,120 329,488 -> 728,89 37,424 -> 254,424 179,864 -> 895,148 359,473 -> 359,675 976,933 -> 129,86 220,101 -> 376,101 988,667 -> 946,667 667,22 -> 308,22 831,782 -> 245,196 759,813 -> 225,279 ================================================ FILE: exm/aoc/2021/aoc_2021_05_questions.txt ================================================ --- Day 5: Hydrothermal Venture --- You come across a field of hydrothermal vents on the ocean floor! These vents constantly produce large, opaque clouds, so it would be best to avoid them if possible. They tend to form in lines; the submarine helpfully produces a list of nearby lines of vents (your puzzle input) for you to review. For example: 0,9 -> 5,9 8,0 -> 0,8 9,4 -> 3,4 2,2 -> 2,1 7,0 -> 7,4 6,4 -> 2,0 0,9 -> 2,9 3,4 -> 1,4 0,0 -> 8,8 5,5 -> 8,2 Each line of vents is given as a line segment in the format x1,y1 -> x2,y2 where x1,y1 are the coordinates of one end the line segment and x2,y2 are the coordinates of the other end. These line segments include the points at both ends. In other words: An entry like 1,1 -> 1,3 covers points 1,1, 1,2, and 1,3. An entry like 9,7 -> 7,7 covers points 9,7, 8,7, and 7,7. For now, only consider horizontal and vertical lines: lines where either x1 = x2 or y1 = y2. So, the horizontal and vertical lines from the above list would produce the following diagram: .......1.. ..1....1.. ..1....1.. .......1.. .112111211 .......... .......... .......... .......... 222111.... In this diagram, the top left corner is 0,0 and the bottom right corner is 9,9. Each position is shown as the number of lines which cover that point or . if no line covers that point. The top-left pair of 1s, for example, comes from 2,2 -> 2,1; the very bottom row is formed by the overlapping lines 0,9 -> 5,9 and 0,9 -> 2,9. To avoid the most dangerous areas, you need to determine the number of points where at least two lines overlap. In the above example, this is anywhere in the diagram with a 2 or larger - a total of 5 points. Consider only horizontal and vertical lines. At how many points do at least two lines overlap? ================================================ FILE: exm/aoc/2021/aoc_2021_06.adb ================================================ -- Solution to Advent of Code 2021, Day 6 ------------------------------------------ -- Lanternfish -- -- https://adventofcode.com/2021/day/6 -- Copy of questions in: aoc_2021_06_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2021_06 is timer_max : constant := 8; subtype Timer_Range is Integer range 0 .. timer_max; use HAT, Interfaces; type Lanternfish_Population is array (Timer_Range) of Integer_64; pop_init, pop : Lanternfish_Population; pop_0 : Integer_64; days : array (1 .. 2) of Positive; -- input : constant VString := +"aoc_2021_06.txt"; sep : Character; i : Integer; f : File_Type; r : array (1 .. 2) of Integer_64; compiler_test_mode : constant Boolean := Argument_Count >= 2; begin for j in Timer_Range loop pop_init (j) := 0; end loop; Open (f, input); loop Get (f, i); pop_init (i) := pop_init (i) + 1; exit when End_Of_File (f); Get (f, sep); end loop; Close (f); -- days (1) := 80; days (2) := 256; for part in 1 .. 2 loop pop := pop_init; for d in 1 .. days (part) loop pop_0 := pop (0); for j in 0 .. timer_max - 1 loop pop (j) := pop (j + 1); end loop; pop (6) := pop (6) + pop_0; -- Life cycle pop (timer_max) := pop_0; -- New fishes end loop; r (part) := 0; for j in Timer_Range loop r (part) := r (part) + pop (j); end loop; end loop; -- if compiler_test_mode then if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else for part in 1 .. 2 loop Put_Line ( +"Part " & part & ": population after " & days (part) & " days:" & Integer_64'Image (r (part))); end loop; -- Part 1: validated by AoC: 388419 -- Part 2: validated by AoC: 1740449478328 end if; end AoC_2021_06; ================================================ FILE: exm/aoc/2021/aoc_2021_06.txt ================================================ 1,1,1,1,3,1,4,1,4,1,1,2,5,2,5,1,1,1,4,3,1,4,1,1,1,1,1,1,1,2,1,2,4,1,1,1,1,1,1,1,3,1,1,5,1,1,2,1,5,1,1,1,1,1,1,1,1,4,3,1,1,1,2,1,1,5,2,1,1,1,1,4,5,1,1,2,4,1,1,1,5,1,1,1,1,5,1,3,1,1,4,2,1,5,1,2,1,1,1,1,1,3,3,1,5,1,1,1,1,3,1,1,1,4,1,1,1,4,1,4,3,1,1,1,4,1,2,1,1,1,2,1,1,1,1,5,1,1,3,5,1,1,5,2,1,1,1,1,1,4,4,1,1,2,1,1,1,4,1,1,1,1,5,3,1,1,1,5,1,1,1,4,1,4,1,1,1,5,1,1,3,2,2,1,1,1,4,1,3,1,1,1,2,1,3,1,1,1,1,4,1,1,1,1,2,1,4,1,1,1,1,1,4,1,1,2,4,2,1,2,3,1,3,1,1,2,1,1,1,3,1,1,3,1,1,4,1,3,1,1,2,1,1,1,4,1,1,3,1,1,5,1,1,3,1,1,1,1,5,1,1,1,1,1,2,3,4,1,1,1,1,1,2,1,1,1,1,1,1,1,3,2,2,1,3,5,1,1,4,4,1,3,4,1,2,4,1,1,3,1 ================================================ FILE: exm/aoc/2021/aoc_2021_06_questions.txt ================================================ --- Day 6: Lanternfish --- The sea floor is getting steeper. Maybe the sleigh keys got carried this way? A massive school of glowing lanternfish swims past. They must spawn quickly to reach such large numbers - maybe exponentially quickly? You should model their growth rate to be sure. Although you know nothing about this specific species of lanternfish, you make some guesses about their attributes. Surely, each lanternfish creates a new lanternfish once every 7 days. However, this process isn't necessarily synchronized between every lanternfish - one lanternfish might have 2 days left until it creates another lanternfish, while another might have 4. So, you can model each fish as a single number that represents the number of days until it creates a new lanternfish. Furthermore, you reason, a new lanternfish would surely need slightly longer before it's capable of producing more lanternfish: two more days for its first cycle. So, suppose you have a lanternfish with an internal timer value of 3: After one day, its internal timer would become 2. After another day, its internal timer would become 1. After another day, its internal timer would become 0. After another day, its internal timer would reset to 6, and it would create a new lanternfish with an internal timer of 8. After another day, the first lanternfish would have an internal timer of 5, and the second lanternfish would have an internal timer of 7. A lanternfish that creates a new fish resets its timer to 6, not 7 (because 0 is included as a valid timer value). The new lanternfish starts with an internal timer of 8 and does not start counting down until the next day. Realizing what you're trying to do, the submarine automatically produces a list of the ages of several hundred nearby lanternfish (your puzzle input). For example, suppose you were given the following list: 3,4,3,1,2 This list means that the first fish has an internal timer of 3, the second fish has an internal timer of 4, and so on until the fifth fish, which has an internal timer of 2. Simulating these fish over several days would proceed as follows: Initial state: 3,4,3,1,2 After 1 day: 2,3,2,0,1 After 2 days: 1,2,1,6,0,8 After 3 days: 0,1,0,5,6,7,8 After 4 days: 6,0,6,4,5,6,7,8,8 After 5 days: 5,6,5,3,4,5,6,7,7,8 After 6 days: 4,5,4,2,3,4,5,6,6,7 After 7 days: 3,4,3,1,2,3,4,5,5,6 After 8 days: 2,3,2,0,1,2,3,4,4,5 After 9 days: 1,2,1,6,0,1,2,3,3,4,8 After 10 days: 0,1,0,5,6,0,1,2,2,3,7,8 After 11 days: 6,0,6,4,5,6,0,1,1,2,6,7,8,8,8 After 12 days: 5,6,5,3,4,5,6,0,0,1,5,6,7,7,7,8,8 After 13 days: 4,5,4,2,3,4,5,6,6,0,4,5,6,6,6,7,7,8,8 After 14 days: 3,4,3,1,2,3,4,5,5,6,3,4,5,5,5,6,6,7,7,8 After 15 days: 2,3,2,0,1,2,3,4,4,5,2,3,4,4,4,5,5,6,6,7 After 16 days: 1,2,1,6,0,1,2,3,3,4,1,2,3,3,3,4,4,5,5,6,8 After 17 days: 0,1,0,5,6,0,1,2,2,3,0,1,2,2,2,3,3,4,4,5,7,8 After 18 days: 6,0,6,4,5,6,0,1,1,2,6,0,1,1,1,2,2,3,3,4,6,7,8,8,8,8 Each day, a 0 becomes a 6 and adds a new 8 to the end of the list, while each other number decreases by 1 if it was present at the start of the day. In this example, after 18 days, there are a total of 26 fish. After 80 days, there would be a total of 5934. Find a way to simulate lanternfish. How many lanternfish would there be after 80 days? --- Part Two --- Suppose the lanternfish live forever and have unlimited food and space. Would they take over the entire ocean? After 256 days in the example above, there would be a total of 26984457539 lanternfish! How many lanternfish would there be after 256 days? ================================================ FILE: exm/aoc/2021/aoc_2021_07.adb ================================================ -- Solution to Advent of Code 2021, Day 7 ------------------------------------------ -- The Treachery of Whales -- -- Interesting here: the `fast` mode is running in O(n) -- where n is the span of x positions (x_max - x_min + 1). -- The `slow` and straightforward way is running in O(n**2): -- one outer loop over all positions, one inner loop for -- computing the cost of moving all crabs to the position -- considered in the outer loop. -- -- https://adventofcode.com/2021/day/7 -- Copy of questions in: aoc_2021_07_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2021_07 is use HAT, Interfaces; -- input : constant VString := +"aoc_2021_07.txt"; -- sep : Character; f : File_Type; r : array (1 .. 2) of Integer; x_min_min : constant := 0; x_max_max : constant := 2000; subtype Position_Range is Integer_64 range x_min_min .. x_max_max; type Crab_Population is array (Position_Range) of Integer_64; pop : Crab_Population; xx_inp : Integer; xx, x_min, x_max, cost_1, cost, cost_min, dist, x_cost_min, s_px, s_x_px, total, total_x_px, total_x2_px : Integer_64; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := False; fast : constant Boolean := True; T0 : constant Time := Clock; begin for j in Position_Range loop pop (j) := 0; end loop; total := 0; Open (f, input); loop Get (f, xx_inp); xx := Integer_64 (xx_inp); pop (xx) := pop (xx) + 1; total := total + 1; if total = 1 then x_min := xx; x_max := xx; end if; if xx < x_min then x_min := xx; end if; if xx > x_max then x_max := xx; end if; exit when End_Of_File (f); Get (f, sep); end loop; Close (f); if verbose then Put_Line (+"Pos min:" & Integer_64'Image (x_min)); Put_Line (+"Pos max:" & Integer_64'Image (x_max)); Put_Line (+"Total:" & Integer_64'Image (total)); end if; if fast then total_x_px := 0; total_x2_px := 0; for x in x_min .. x_max loop total_x_px := total_x_px + Integer_64 (x) * pop (x); total_x2_px := total_x2_px + Integer_64 (x * x) * pop (x); end loop; end if; -- cost_min := 0; -- Just calm down a warning. for part in 1 .. 2 loop if fast then s_px := 0; s_x_px := 0; end if; for y in x_min .. x_max loop -- Compute the cost of moving all crabs to position y. if fast then -- Quick computation without inner loop: s_px := s_px + pop (y); -- Partial sum: sum_{x <= y} pop_x s_x_px := s_x_px + Integer_64 (y) * pop (y); -- Partial sum: sum_{x <= y} x * pop_x -- if part = 1 then cost := y * (2 * s_px - total) - 2 * s_x_px + total_x_px; else cost := (2 * y * s_px - -- 2 * s_x_px + -- Maths, total_x2_px + -- pencil & paper (1 - 2 * y) * total_x_px + -- (y ** 2 - y) * total) -- --> 639x faster! / 2; -- end if; else -- Slow, straightforward computation, with inner loop: cost := 0; for x in x_min .. x_max loop dist := abs (x - y); if part = 1 then cost_1 := dist; else cost_1 := dist * (dist + 1) / 2; end if; cost := cost + cost_1 * pop (x); end loop; end if; -- Did we find an optimum ? if y = x_min or cost < cost_min then cost_min := cost; x_cost_min := y; end if; end loop; if verbose then Put_Line ("Minimal cost:" & Integer_64'Image (cost_min) & " at x =" & Integer_64'Image (x_cost_min)); end if; r (part) := Integer (cost_min); end loop; -- if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: sum of linear costs: " & r (1)); Put_Line (+"Part 2: sum of quadratic costs: " & r (2)); -- Part 1: validated by AoC: 340052 -- Part 2: validated by AoC: 92948968 end if; end AoC_2021_07; ================================================ FILE: exm/aoc/2021/aoc_2021_07.txt ================================================ 1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,11,39,71,27,749,252,590,80,445,1125,1044,690,307,145,713,709,468,135,24,330,932,110,1732,1550,826,1,188,1585,388,977,205,351,550,1,782,111,225,523,325,188,134,954,139,448,903,1225,161,791,1539,918,113,15,234,377,2,22,52,1530,119,922,658,41,256,192,161,102,109,8,1492,765,1277,92,245,73,281,1579,485,645,962,287,207,609,109,203,1181,867,371,290,1582,201,16,298,626,329,756,466,433,384,871,84,1661,1177,28,169,263,527,18,619,823,961,41,211,142,842,175,421,202,440,201,104,814,1059,80,17,420,749,522,261,80,540,36,708,1166,357,639,45,224,852,1209,1400,303,13,255,959,83,85,339,184,616,192,688,1145,200,26,376,624,165,10,492,11,866,531,28,20,614,3,500,354,650,74,1156,743,350,8,1641,38,254,673,523,242,186,756,98,1352,425,165,1072,1072,441,487,489,408,685,1083,527,172,32,419,699,672,464,1986,312,941,991,639,260,70,4,490,386,1079,883,285,260,91,204,1724,555,547,468,140,372,94,6,1189,165,439,22,261,255,197,81,9,306,23,61,151,477,326,1393,69,1246,191,113,172,806,116,644,23,500,567,276,237,257,482,262,87,561,530,786,312,1130,251,1391,0,478,85,129,714,64,499,484,771,461,876,563,587,20,4,704,84,230,667,1099,187,491,25,382,1607,14,434,902,1424,263,58,13,394,21,199,885,1113,105,238,423,972,1270,131,103,21,1125,3,1032,122,111,551,122,127,103,1164,1038,688,98,468,547,464,766,1044,1758,718,1476,1057,49,1526,118,391,629,241,280,303,0,915,88,656,1113,100,458,364,1612,362,1090,391,112,722,538,38,54,218,279,893,128,947,336,100,99,1329,342,543,1061,626,40,164,639,640,525,1121,714,592,696,260,103,520,160,151,462,260,1153,1319,132,608,1469,261,1080,96,908,383,36,70,1082,393,99,1573,567,19,1238,391,39,58,334,732,193,79,124,538,1511,185,608,538,0,52,13,190,180,49,184,143,655,74,315,105,906,569,1037,110,224,68,840,1300,130,762,269,560,655,156,819,1137,1483,1037,238,854,91,329,25,677,317,58,563,39,456,919,485,512,37,217,281,1020,914,289,1196,1060,440,1402,85,1130,931,226,325,598,482,861,60,610,308,551,178,1121,436,155,89,1283,887,163,516,1011,26,493,371,538,688,11,1023,148,174,150,401,1115,111,500,84,585,1,307,863,11,1333,414,855,340,810,75,79,292,8,1296,50,17,638,941,260,1250,817,311,184,902,623,97,57,75,425,647,33,225,85,335,34,905,44,644,208,386,194,1427,204,9,226,1278,165,776,510,707,541,378,26,265,661,475,803,344,107,947,307,453,1305,1589,999,55,1364,130,745,545,650,1223,783,965,416,737,275,32,166,951,30,947,1208,159,257,648,214,94,710,386,923,772,910,688,322,312,818,361,77,1,828,280,582,153,428,42,68,1061,271,627,578,12,449,14,583,128,925,355,608,34,492,231,101,6,732,791,94,305,975,1023,201,184,580,591,1604,547,528,417,684,768,1095,925,1429,417,1014,367,1031,160,820,206,227,1045,828,8,170,235,222,483,479,106,182,121,231,282,646,1165,21,68,51,130,14,68,330,1087,76,782,593,85,203,949,164,21,73,14,1590,137,436,163,582,725,46,326,436,59,44,621,317,269,216,486,396,194,713,4,1072,327,186,225,701,320,726,1220,331,17,78,558,1213,1000,436,240,940,1658,19,553,1498,660,152,304,267,33,926,340,556,1098,1434,1813,111,245,1,132,224,782,209,1142,1412,40,716,1,91,184,218,3,484,252,71,263,468,624,12,924,147,687,330,342,746,607,17,709,16,431,232,444,9,1386,44,181,1128,876,74,637,549,213,476,18,320,387,106,61,319,785,165,735,73,806,718,188,327,453,1555,978,13,400,1025,670,698,610,171,97,644,963,1037,53,2,106,20,855,17,7,495,1508,41,205,467,1848,59,243,758,6,396,22,1558,198,227,495,1370,4,128,371,573,1130,591,190,118,1246,1049,122,15,1755,332,567,202,162,989,1061,232,591,308,1433,132,100,564,436,466,15,1229,280,49,1827,701,118,106,246,18,2,184,43,1496,1091,156,334,730,354,429,6,83,1185,1,229,229,16,207,419,1018,197,1492,1805,1334,246,1378,175,297,1362,470,599,263,656,390,119,692,22,859,22,60,1009,5,1310,161,461,157,247,309,195,5,663,402 ================================================ FILE: exm/aoc/2021/aoc_2021_07_questions.txt ================================================ --- Day 7: The Treachery of Whales --- A giant whale has decided your submarine is its next meal, and it's much faster than you are. There's nowhere to run! Suddenly, a swarm of crabs (each in its own tiny submarine - it's too deep for them otherwise) zooms in to rescue you! They seem to be preparing to blast a hole in the ocean floor; sensors indicate a massive underground cave system just beyond where they're aiming! The crab submarines all need to be aligned before they'll have enough power to blast a large enough hole for your submarine to get through. However, it doesn't look like they'll be aligned before the whale catches you! Maybe you can help? There's one major catch - crab submarines can only move horizontally. You quickly make a list of the horizontal position of each crab (your puzzle input). Crab submarines have limited fuel, so you need to find a way to make all of their horizontal positions match while requiring them to spend as little fuel as possible. For example, consider the following horizontal positions: 16,1,2,0,4,2,7,1,2,14 This means there's a crab with horizontal position 16, a crab with horizontal position 1, and so on. Each change of 1 step in horizontal position of a single crab costs 1 fuel. You could choose any horizontal position to align them all on, but the one that costs the least fuel is horizontal position 2: Move from 16 to 2: 14 fuel Move from 1 to 2: 1 fuel Move from 2 to 2: 0 fuel Move from 0 to 2: 2 fuel Move from 4 to 2: 2 fuel Move from 2 to 2: 0 fuel Move from 7 to 2: 5 fuel Move from 1 to 2: 1 fuel Move from 2 to 2: 0 fuel Move from 14 to 2: 12 fuel This costs a total of 37 fuel. This is the cheapest possible outcome; more expensive outcomes include aligning at position 1 (41 fuel), position 3 (39 fuel), or position 10 (71 fuel). Determine the horizontal position that the crabs can align to using the least fuel possible. How much fuel must they spend to align to that position? --- Part Two --- The crabs don't seem interested in your proposed solution. Perhaps you misunderstand crab engineering? As it turns out, crab submarine engines don't burn fuel at a constant rate. Instead, each change of 1 step in horizontal position costs 1 more unit of fuel than the last: the first step costs 1, the second step costs 2, the third step costs 3, and so on. As each crab moves, moving further becomes more expensive. This changes the best horizontal position to align them all on; in the example above, this becomes 5: Move from 16 to 5: 66 fuel Move from 1 to 5: 10 fuel Move from 2 to 5: 6 fuel Move from 0 to 5: 15 fuel Move from 4 to 5: 1 fuel Move from 2 to 5: 6 fuel Move from 7 to 5: 3 fuel Move from 1 to 5: 10 fuel Move from 2 to 5: 6 fuel Move from 14 to 5: 45 fuel This costs a total of 168 fuel. This is the new cheapest possible outcome; the old alignment position (2) now costs 206 fuel instead. Determine the horizontal position that the crabs can align to using the least fuel possible so they can make you an escape route! How much fuel must they spend to align to that position? ================================================ FILE: exm/aoc/2021/aoc_2021_08.adb ================================================ -- Solution to Advent of Code 2021, Day 8 ------------------------------------------ -- Seven Segment Search -- -- https://adventofcode.com/2021/day/8 -- Copy of questions in: aoc_2021_08_questions.txt -- -- HAC 0.098 "nice to have"'s detected in this exercise: -- -- * Comparison (equality operators) "=", "/=" of -- composite types (arrays and records) -- * Logical operators on arrays of Boolean -- -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_08 is use HAT; -- input : constant VString := +"aoc_2021_08.txt"; -- r : array (1 .. 2) of Integer; -- procedure Part_1 is c, sep : Character; f : File_Type; first_line : Boolean := True; size : Integer; begin -- -- Part 1 : count unique patterns (2 segments for digit '1', -- 3 for '7', 4 for '4', 7 for '8') -- r (1) := 0; Open (f, input); first_line := True; while not End_Of_File (f) loop if first_line or End_Of_Line (f) then -- Skip the training message for i in 1 .. 61 loop Get (f, sep); end loop; end if; first_line := False; size := 0; loop Get (f, c); exit when c = ' '; size := size + 1; exit when End_Of_Line (f); end loop; if size = 2 or size = 3 or size = 4 or size = 7 then r (1) := r (1) + 1; end if; end loop; Close (f); end Part_1; -- procedure Part_2 is -- subtype Segment is Character range 'a' .. 'g'; type Segment_Set is array (Segment) of Boolean; zero_set : Segment_Set; -- f : File_Type; c, bar, spc : Character; -- procedure Get_Segment (s : out Segment_Set) is begin s := zero_set; loop Get (f, c); exit when c = ' '; s (c) := True; exit when End_Of_Line (f); end loop; end Get_Segment; -- function Count (s : Segment_Set) return Natural is total : Natural := 0; begin for c in Segment loop if s (c) then total := total + 1; end if; end loop; return total; end Count; -- procedure Intersect (s, t : Segment_Set; s_and_t : out Segment_Set) is begin for c in Segment loop s_and_t (c) := s (c) and t (c); end loop; end Intersect; -- function Equal (s, t : Segment_Set) return Boolean is res : Boolean := True; begin for c in Segment loop res := res and (s (c) = t (c)); exit when not res; end loop; return res; end Equal; -- subtype Digit_Range is Integer range 0 .. 9; subtype Output_Range is Integer range 1 .. 4; training : array (Digit_Range) of Segment_Set; temp, output : Segment_Set; -- k = assoc (i) means: training (i) represents digit k. assoc : array (Digit_Range) of Integer; segs_to_index : array (1 .. 7) of Digit_Range; index_to_segs : array (Digit_Range) of Positive; first_line : Boolean := True; size : Integer; dig_it : Digit_Range; num : Natural; begin -- -- Part 2 : decode the digits! -- r (2) := 0; for s in Segment loop zero_set (s) := False; end loop; Open (f, input); first_line := True; while not End_Of_File (f) loop if first_line or End_Of_Line (f) then for i in Digit_Range loop Get_Segment (training (i)); size := Count (training (i)); segs_to_index (size) := i; index_to_segs (i) := size; case size is when 2 => assoc (i) := 1; when 3 => assoc (i) := 7; when 4 => assoc (i) := 4; when 7 => assoc (i) := 8; when 5 | 6 => assoc (i) := -1; when others => Put ("Error!"); end case; end loop; end if; first_line := False; -- -- Determine the 5- and 6-segment digits: -- _ _ _ _ _ _ -- _| _| |_ | | |_ |_| -- |_ _| _| |_| |_| _| -- for i in Digit_Range loop case index_to_segs (i) is when 5 => -- Intersect with the "4" (4 segments), and count the remaining segments. Intersect (training (i), training (segs_to_index (4)), temp); if Count (temp) = 2 then assoc (i) := 2; else -- Intersect with the "1" (2 segments), and count the remaining segments. Intersect (training (i), training (segs_to_index (2)), temp); if Count (temp) = 2 then assoc (i) := 3; else assoc (i) := 5; end if; end if; when 6 => -- Intersect with the "4" (4 segments), and count the remaining segments. Intersect (training (i), training (segs_to_index (4)), temp); if Count (temp) = 4 then assoc (i) := 9; else -- Intersect with the "1" (2 segments), and count the remaining segments. Intersect (training (i), training (segs_to_index (2)), temp); if Count (temp) = 2 then assoc (i) := 0; else assoc (i) := 6; end if; end if; when others => null; end case; end loop; -- Get (f, bar); -- Absorb '|' Get (f, spc); -- Absorb ' ' num := 0; for i in Output_Range loop Get_Segment (output); size := Count (output); for i in Digit_Range loop if Equal (output, training (i)) then dig_it := assoc (i); exit; end if; end loop; num := num * 10 + dig_it; end loop; r (2) := r (2) + num; end loop; Close (f); end Part_2; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Part_1; Part_2; -- if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: number of unique digit display patterns: " & r (1)); Put_Line (+"Part 2: sum of decoded display numbers: " & r (2)); -- Part 1: validated by AoC: 440 -- Part 2: validated by AoC: 1046281 end if; end AoC_2021_08; ================================================ FILE: exm/aoc/2021/aoc_2021_08.txt ================================================ dfgabce cadfgb cefa ca aecbg dfcegb geabd ecbfg cab agcfbe | egbfadc dbgae gcfeb abgdfc fbcag eg dbge gcbfe acdgfe gec fdcegba efbdc fbedgc efabdc | ge fagbc dfebc eg da gdbcea gdcfbe acgbd dbfcgea ebad aecdfg afcbg adc ecdbg | afcegd dacebg ad cdbafeg gafeb ag acfbed ega ebadfg bfcge dgfa begcda edfba cfgedba | ag dafg dfcbgea feacdb cefdag gcea fag defca gbdaef afcdg dcbgf ga adfecbg fcbdea | geac cfedba cgea fadecg fcgaed abdecgf cfaed ceb febacd dbecf bc cbfa gecbad fbdeg | facde cfgade acdefb cbe bcgae cfedba efcbadg dafbc dfbe fcgbad ef aefgcd acfbe fea | abfcd cafbd fbde dcgbaf geabdc fedga cafdbg cd aefcbg adcge dac bdegafc cegab dceb | dcfgba cad cad deabcg gdecab fde aecf adbgfe egdcaf dgaebcf decfg bcfdg ef ceadg | cefdabg fcea efac edf cbgaf edfa bfgecd fcdbae debca dfb bcdaf bdcaeg fecgadb fd | cafdgeb gabcf df afdebc fdebgc egdfb bfcdg cfedgab fdeagb egcb fcb cfdeba cb fagcd | gebfd afdbgec bc gdcafbe cb gcdefa cdb bacg eabfd ebdac gdabec gcbefd bgdecaf caedg | cgdeab ebfdgca edgbca cbefadg efbc aecgbd ebgdfa ecbag afb cfgeadb bf cadgf bgfca egcabf | bf agdbce fab bfcdeag cedafg aecdbg fcd cgeda cdfag efcg agfdb defcab fagcebd cf | adgcfe daecg abcged fgedbca bcgaed cfdgea caebd gdebc bega fbecadg ge fcdaeb gde gfbdc | gabe eg cadebf ecgadf aefc abefg acfbge agedbf dbgce cab abgdfc ecbga ac bfdceag | beafgd ca ac ac afbde fedag becda dacegf baf gacdbfe fcabdg fgeb fgdabe fb | fb afbdge bcdea fedacbg bfd cdgbfa dgefca fabdeg cgebdfa cabd gfcda cbgef db dgfcb | bd badegcf acdb adegcf ef cfbgd cdbfe bef ceadb bfcgead aedf edbagc abgcef aecbdf | bcfegad bef bef fe cbagef beadgc fae deacb fcagd cgdebfa dfeb bdecaf fe fcdae | dfaceb efdb beafcg bdef gdfeacb bca gfeacb gfeca egcb bc dgeacf fabgd fbcdae gcbfa | bfdeca bca adbgf abdgf faedbc egcaf bdgaf agdebcf fagcb cab bcdgaf dbgc fbgead cb | bdgafc cb dgbfa bgcd dfabc bgacde ad dab edfa bdfec dbgefca facgb eacfbd fcgdeb | ecdbfag bedfc ebfcad bfcdge dfegbc cfagb ba gefbc abec bfcdega bfa egadbf fgbcea fgcda | eafbdg ebfgc fgbdcea ba fgdebca dgbcea adbce cfaedb acebf ef efc cfabg edgafc fedb | fdeb fce gcfab bafgc cfdg daefgcb caedgb aefbc cbdag fg fdbgac fbg beagdf fbcga | dgfc fecgabd fgcd gbf cbadef abgdef cfea ac gedbc dcbafg dca fdbecag dceab deafb | eafc ebfdga cefa abcde fcbged ebdca bde ceagb abcdfeg bd cdaef cgabed ecgfab bgda | baecd dgbcea ecafd dbag bfeag cdabf dbeacg dgbcefa eda fdabge bafde ed egfd ebcafg | ebfcadg defg fadbe cfbgea bfd dgbec gfcadb ecdf aefbg cfbgead fd gcbdfe debgf gcdeab | ecdbga aebgf abcfgde fd ecgfda bcafe dgbefca dagcb dfc acdfb cdabfe cebfag fbde fd | bgdefac cfd febgac df dcafb dgafcb dbeacf bdga degbcfa cgbaf ga fga efdgca cegfb | ag beagdfc abcfg gcdeaf cgbfd fegcba ecgfb cbe dafebg bdface gace ec fcgdeab eagfb | gcdfb acge ecb cebgf adbcgf ef fged feb dabfgce bdgfc becfgd dcabe febgac bdfec | cgdbf fdcgeb afcbge fbdgc cg dagfc dfagbc cgab dagbf gbdcfe dgc aefgdbc aecdf bafegd | cg gfacbed bfgad bgacfed cadfeg cfdegba edagcb fae faebc decfb fa aebcg fgba egafcb | baegc fa acfbe af fed bcdge fcbae gbfd gfabecd cdaegb df egdfac egcfbd becdf | cadegf edcgbf fcbde dbgf fadcg beafcd cedbag edabg abdfge bdagf fba dgcbaef fb fbge | deafcgb dfcaeb geadfb ecfgdba bec fbcea cgbf bfgcea cdefa cgadeb cb fdbeag bdaegcf fgabe | ebfacg bgcf cb bc gb agdbce efacgd cgdfbe agdec afcdb ebag gcb eadfgcb bdgac | efcbagd bedcag bgc baeg fbe dcbgae cedgfba bcgefa bfdge bf dafge edbgc fcdb bcfdeg | bdfc fdabgce ebgfd fegbd fb abfdge fgdca fedcag bafcgd bfg gdeabfc fbgac eagcb bcdf | gacfedb fb bf fcadg bg eadgf bcdea gbd gebda edgbac cagb dfecab fgcbead ecfbgd | gbedca adfebgc acgb bdg adgfce begafc gfeac cde cgabd ed becdfa gfed egfbcda egacd | ed cgeda dfeacb dec agefcb gadec gdbafe dg cebafdg dcfg ecagf edg gdeacf ceadb | dgaefc egcadbf cdfg faecg fdec gcbdaf bafedc cf dbegac ceabd gbadecf fca gbefa bacfe | fc fdce acf afc fdecg gdefcba cg dbcfe dfbeac gcfedb daefg facdgb gebc cfg | begafdc fcdebag dbcgaef gfc adcgef agbdfec dc ecad cgeabf edfbg bcdgaf fdgce ceagf cdg | cdgef ecda cade cd abdefc bdaecfg dgeacb fb gfade bacde bdagcf fdb becf adbef | fcbadg cefabd fdb edfga efcgab bead fcdeg ae cgdab dgcbae aeg edgca bcegdaf gdcfab | gdafceb ea eag aeg dceafb befac fca cf fdcb cadgef bedaf ebagc aedfbg acgdbef | beadfc cf cfeba gbeca gce eacgbd afcdbe eg dfcebga bedca gfbca agfedc gcaeb gebd | gdbe ge ge gbde bcgae bedgfca gde ed gdaec gbfcad cgbdef gdaecf edfa gfadc | cdbfeg bgdfac cfdeag adgfbc gebca dbacfeg dbfeag bagfe eadfb gf fdge fbg dfceba gafbdc | egfd fedg egafb gf begfadc bdcae dgbca edbf acbfeg fcgead be eba afdce aedcbf | bfedac edcab eba fdbace fdbgc cegabf ac dfbage bgfae faec gac caedbg bfgedca bfagc | acef dfgcb face gbafed cdbfge bfceg dgacbe baegfd ecb dfceabg ebdfg cb acfge bdfc | cbe gcbefd egdcba eafbdg fecdb dgbcfae bedca edf ef cfebgd ecgf gfdbc fdbagc afbged | aedbgf ef fecg fagcbd gdecfb fbadge cabe adfcg efcbd ea gbeacfd fcedba dea fdeac | acbe acbe dea fcgedba bg dgfac gabdec dgcabef beafc gfceab cgb bafcde fegb cgafb | bcg bg fdgca faebcg adfgc dfcbge dgafbc gaf acfb dgcea gebcdaf fbgdea fbgdc af | fa agcdf fga gfebda defag begdf fa becgda aef afcg dfaceg cgdae eacdfb acefbgd | cadfeb edgaf fa ecadbf fec edfbc fagecd cgdfb ef fcabdg cedba fbecdg bfge faegbcd | befdc dbfecga acgdbf gcbedfa ed cedbfg bdfac fdeac baed fde eagcbdf abgfdc feadbc gaefc | fdbca de cgbdfe de fcbga ge cagbef acebfdg egbf acbge ceg egcdfa bagdcf adcbe | cgfab ecg ebcda afgcde df fadcbeg gcfbde dcagb fbd afgdbc cbeagd dfcab cafbe adfg | eagdbcf fgda cgbda gbfced agef bgdcaef ade adcbf gdbace cefdg febgdc cgefda fedca ae | ae afdgec febgcd agcdeb gfbc fdg dbaef fg aefgdcb gefdac gebcd dbegac fegcbd fbedg | cfgb gdebc cbaefdg fgd ebfgac gcf geabdfc cegbda fgade bcaeg fcba cf fdecgb ecafg | cfg fgc acfgdeb gdabfec gafeb ebdgac ed cgbfad cgeadfb bdecfa bfcda fabde aed ecdf | bgfdaec fedcbag de fedc age ebcdfg afcdeg dcfeg efadgbc fgad becad ag eacgd gabecf | ag gcdfbe agecd fdgce aecfbd geb afbde fdgeab gfeba ebgcadf bg gdbf fgeac bceagd | eacdgfb bge edabcf ebdaf cgabe aefbcdg fagdce abcdfg dcbe aecgbd cge fbaeg ce dcbga | bgacfed gafcdb egc egc bdefa fagbd fabdce cdae fceagb deb fbdecg fcbea de agedbcf | fgdcabe afbde bde gfcbde dgfcea dcbea dabcf edcbga cedafb gfabc cgdabfe afd fd dbfe | debf egdacb dbef edabcg bfdea adfceb fgcbae feg fdebg bagfdce egcdb fedagb dgaf gf | bgdfea gef cdebfag edcbgaf ade aefgdc ea feac gefdc eacbdfg eabfgd abcdg efbdgc geacd | eafgdc fgebad cbdefg cdefg egfdab edfb agfec dbcage ade ed badcfg gfcdeba afedg fgadb | aedbcg bgfda aed dae cfdbge abgc afgbe cb bcf ebfdga adecf efbacdg agfbce bacfe | bfc fbc cfb bfc gd bgd gcafeb dfcbage ebfgcd egfbd decg gcafdb aedfb ebgfc | gdec gefbacd gdce dg gf dbegac becgadf dfge facbe gfa acdgfe ecgfa dcfbag gceda | gfed cefba cabfe acedfg fd cdbagef fdgbec daebcg dfba fbacdg cdf cfadg gabdc gfcae | agecf cfd cdf egcbad dfca adgefb fbced cfdbge fa egcabfd eabcf eabfcd cabeg afe | acfd dbecf af af agfdec dfcag edgacfb baegfd fd gfaecb dacgb ecfga dfec daf | gabcd ebcgadf fbegac fgace edafg gcfea cbaeg afcdgbe fcde fc acf cedagf begfda cdbfag | cf daecbfg bgace dcgabef bdefagc gcba bfacde adbce ga dgefc cagdeb dgeabf aegdc adg | faecdgb gda ag dga becdag bceadf edcab dgacb bdgcaef gd dga cedg agbfc dafebg | gd gced gad cgabd gbfaed bdacf db fcabg ecfda edcb adcfge adb abcfed cgedfba | bad dba fdecgab edacf ae cabe ecgafb dfgce afbdge gdacfb bdegfca afe agfcb cegfa | ae fgdeab gcfed cgdfabe ad fdbcg cbfea fdabgec dca cgadfe fbdac dbag gbcfde bgcfad | dbagfc dac ad cbfdge fdgbaec ab dabe cabegd cgaed bcdag bgfdc gebcfa agb cadefg | efbgac dcgafe dagecb gba cafbge gdbfac aefcb adfcegb daefc bacge gcabed febg fb bfc | bfcgae gebf bfc abgcdf dfbgca bfcae ebc ebfdac eb eadfgcb dfeb edbagc fdcba gfcea | becadf ecb bce badcf cdefa adcgfe fdceb eacdfbg adf ad fcgea deag gacbfd aecfgb | da dega adcebfg acdbefg dace dcebg adbcfg abdcg de dceagb fcbeg fbacedg bdeafg deb | bed cabgd ed fecbg edabgc fdbaegc gcadfe afed fcd gecbf fd fgdcab fedcg dgace | gaecd bdgcaf gedfcab fead gfbae bgefdc cbfgdae dbgfea abgc bc aecbgf adfce bce afbce | aedgfbc bacgfe bcdefg gfbea cadeg cagdfb bdc bfcedga cgbafe facbe efbd edcba bafdec bd | dbc agdce efdacb bcd ac fegacb bac afdc aedfbc defba dgefba gcdeb edacb dcbeagf | egdbc egcfbad decba adfc bcfdag cgfdbea dce gbcfd ed bgced dfbgec gcaeb fcbead dgfe | defg edc gecdb de eb fbe afdec bfgda cdfbgae fbgcde aedbfc deafgc ecab efdba | aegcdf fedgcab edcfbag be cfabg aceg gba fcebda egabfc cbaef acfbdeg ga gcfdb adbfge | cgae abg gace dfabec fabe af fdaeg bdega fdceg adbfge fad gcedbfa dfgbac aedgbc | afdgceb aebf dfa cgbaed ecgdf bfcagd dcegb gafdc efac feadbgc agcdef eagbfd fge ef | ef egf dcgfa decgf ag ecbga bga fdegab gbdcfe gbecf afbecg ebdac edacgfb cagf | gafc ecgbf bag eadgbf dafe fe cef agdebfc fecdg bedcg bdcafg beafcg dcegaf fdcag | dafe fcdag afdgce adef gefac dagcfe age facdegb acfbg edfa ea edfcg egdcab fcbgde | gcefa ea aebdgc ecfga cdfbea debgca adbec bgfadc cdg ceadg bgce gc gfaed fcdgeab | cg cgd afdcbg cdg gcbefda fdcga cfdebg fgdabc abgd fdbcg cabfde fda efagc ad | dgcfa bacfed cfbegd da cgbaed bcdefg ebdca dcabf feabcdg cgae deabg ced ec efgdba | bgdfce ceag cde dbegac debgfa gbdce ecdgbf ag agdc bga acdgbfe bceag cbaef cebagd | bga ga gaceb abecgd dbgcef eafgb fcdeb bdfcae fadc ac degabc agbcefd abfce cba | fcedb cebdga dacf dafcbeg bag gceb cbafd bg bgfaec dfgcae cbagf gceaf dfageb bcafegd | agb gb gb fedbagc gadce gecdf cgf egbfd beagfc afdc dfcageb cf bcgdae dgefca | fc gfc eacfdg cgf dabcfg ebadf cf cebag fbc eagfcb bcegad fgce eabcf ebcgdaf | feacbdg ebadf adfbe fc ad fgeac afd bfagcde afbcde gdca debgf adgfe fbagec cfaged | adcg adgefc ad adgcef fcdbeag fdbage cadf daecb bgecd bafce bda ad cdbaef eacbgf | ad caebdf gbcefa bcade efbgca cabdgef fabcd dafec bf afdgcb fab agcbd fgbd dgceab | fba fb dcagb dbfcag bea cbfag agefdc cdeb gbadcef aefgdb eagdc cgdeba egbac be | bgace eb be cbde acbdeg cefda fb cfbaeg ebf aefcb gbfc ceagb cegbfda gebafd | agcfbe afdec fbgc dfcegab bc cgdab gbfcad ecbdfa cbd fgdac edfacgb dgaeb afecdg bcgf | fcbg dbc dcafgb bcgf aedf dga cgfbde fgbde cfbgad dabegf cfgabde geacb bdaeg da | dfea agd baecg gcaeb gc cefga dbefac bacedg afedg afcbe becgaf bcgf bdgfeac cag | cgbf bgcf dabceg gc db cdegf gcbfd afgbc dgcfba cbgaef dgba fgebacd fadcbe fdb | fgebac bd fdegc db debgafc dacbeg fdg cgdba fdagcb eacfg bdcf gafbde fd dcagf | fbcd bgcefda cafbged dfbc fcab gdbef begadc fdecga abdcefg bafgec cb cbe efbgc egacf | bce gcfeb cgbfade cbaf aedg agfebcd abfge fge cdbefg eg dgcfba gdebfa acbef gafbd | agdfbc baefc efg gbfea cdgab cbfedga eacbgd cf dceafg cadgfb fdc efbdg bcfa fdbgc | dfc fc cdgbf gcbadf gce eg edcfagb eacgdb bfegdc cdgaf ecgad cebadf eagb cedab | dcbae cdafg gedacfb ge dbeagf gfbda fdebgc gabfdc afbgc cgbea fc cdaf ecadbgf fcb | cfgedb bdagf fc gbecfd bdcefg egcfab acedg fcdb fbgeda bec cebdg deacbgf cb ebdfg | bc decbg eacgd bdcf dfgeab cegba facbegd edg dfgceb gafcbd edbgc gfcbd dcfe de | bdceg fecd cedf defgcb egfb dfgace cfgaebd befac adcgb aeg ge cebag bgface bdacfe | cgbea cgbae cbdgaef afebgc de efd efdbg efabdcg fgaceb bfgdc fgabe edgfab ebda degacf | fecagd ed adbe de fedbga gc gec gaefd ecagf gecbda bafce cgfead cgdf cadfbeg | gafed gcfd cgfd gcfd bedfgca ebfdc acgbfd cfb dfbeg decaf bc dabefc beac aedcgf | debgf efacd cb bc edgcba eg dbfga acfgeb cdbea bcfdaeg dcge gdeba dacefb egb | efgdacb cgeafbd gfadb gedc bacfde dgcefa eabdf acfebdg afgdbc dba aedfc aebgf db bdce | db afecd agcdfe agfedbc dga cgadb cdbge bfgca edab ad cbgade efbcdga afedgc ecfgbd | ad dgecb ad bdgac abfdec dacfegb faecg cbge acgfb fcgaeb bgfda bc bfc fgcdae | cgeb fgaecb cbeg gadbefc ea ecgbfda eacb efa facegb bgfea ebfdg gfbac edcgaf gcdfba | gabfe bgfeca ae cabe ecf bfged cebfgd adfebg dfabec cgdf gbeca cf bdfcgea bgfce | cdfgeab gdbfe daebcf bcagdef ebf efbdc bf bfcdge dgcfea bgfc cedab begdaf egcdf befdcag | ebgcfda gdfaeb bf ecfgd egcdf ecafg afebdc df dgfa agfecd cfbdgea ecgafb gdceb cfd | cdf cgadef acfgbde defgc gbdeacf bfcdg cag acdgf efdbcg ac fagdcb gbfeac bcda edfga | agc gaedf abdc cag cfgd edbcfg gfebc begcdfa acebgf ged dbace faedbg gecbd gd | bagefc dgefabc defabg becgf gcbe ce ebdfa cae bdcagfe bgdac gdeacb cbdagf dbace caegfd | ec acedb gabcd bcagfed efdgba cgabfed ec caef ceagb fbega cbgda ebc afbgec ecbdgf | afegdb gacbd dgefab edafgb ecagd bfdec fabdce bda beadc gfeabd bdfeacg afbc gecbfd ba | becdf dcaeg gcdea adb cefb cfabdg dbf bfeacd baged bf baefd gaecfd cbfaedg fecda | bf fedac fdgecba bdf gce gdbcae fecd efcbgd fbdacg eafbg cefgb cbdfg ec fgdacbe | cge ec bgcfead ceg deagfb af efca gfecad dfa bacdg cfdegb fecdg egdacfb dfcag | fdgce af edbgafc fdgce fagdce ebd abdegf defba cafebdg eb daefg dfbca ebga defcbg | afdeb eb bde egba bafed aecdb fbce cbd gdebafc cfbadg badegf bc ecdfab gecad | dbc dbc badgcfe fdgeba fgbec bfacde ge edgcfb cgdbfae fdecga cfbga efg dbge cdfeb | bedfcg eg ge afebdcg dcaef ag gcab aeg acedg edgcb efgdacb cgfbed dafgeb agdbec | bedagc bdegc dfcebg adecf dcfg abecg bgadc dg fcgbda gadebf cdabfe badcf agd fcdbega | abdfeg gd egbac cabgdf dfgebc eabcd efcdb dbecfa dac aegdb ca bcgafed fbac fcadge | ca egcdafb afcbdge eagdb ebgdc cbgdfe dcbfae bfagcd gdef cebga bceagfd ecd dfbgc ed | de ed fdegcba edc eb feb begdcf efgacb gdbe daecf dgcfb fbdcega cebfd gabcdf | efdbc be afdec efb begac fbec bcdafg acb cb fgaebd afegbc gebadcf dagec beafg | adgce fceb cgdeafb cab ca cdfagb ebfca ebdcgaf afebg dfbgae cega cebfd fbagce fac | bgedaf cgae gdaecfb egdabcf gabfd agfc ecdbfag aefcbd afd af gdabfc bgcfed abedg dcgfb | af bdgcef adgbf gcdafb egfda fed dbfga adgefb de gacbdf aefgc aecbfd bdge fdbecga | ed de eacbgdf bdeg dbfag cdbfea gfdbec agfedbc gfb bg gabfcd fgeda dbfac acbg | dfbac gcba gb fbgda dbcgf gba gdcaeb dgbacfe edfba debgcf cbdgaf afcg ag abfdg | bgafecd edfcgb ag dgfba bdfcg acebfg egfbacd gfdcba fbg dagb bg cbdaf cgdfe edfcab | bagd gfebacd efbcda gfb cedbf fcabdge cge feagbc dfcge gedb adcgf bdcefg edacfb eg | cbdfe cge efbcad cfagdeb cga fgeda ceagd ebcg beadc bgfecad fgdcba gc cagebd dfeabc | cag daebgc cg fcdageb fgdc fda aebgd cabfde fd agbecf fdacgbe dbfga cfgba bdgacf | facbg fbdagec fdcg ebafcgd gbced efbgca gfebd bdc baecg fcabed dcbgeaf gbedac dc acdg | gfbace cdafbe cbaeg bcd afgdec ba dbcge daefg dabeg dfbcage afbd fgdaeb gab cfegab | bcfage bgead ba fgdbcea ace dgcaef daegbc bfgeda ecbd degab cgabf ce eagbdfc bcgea | cdgeaf bdgea edcb cae cd cadf gfead gdefab dce adcfge degcf cgefb gdfbcae aebcgd | efgdc dce ecd dc afdbe ad fgdeb fda aebdcgf bcaefg acbfe fdceab bacd dcagef | afd begfd acfeb fda dfg afgedbc cbfga gbdace dbagf fdegab edgacf df befd edgba | dgeba df efbd cfadge bdcgaf aebg badfce efagc gdefc cabfeg abgcf ecafbdg afe ae | aegdbcf ageb eagb ebdfgca gdceab fb bfe cgbfea edbagfc cafed ebacg ebafc defgcb gbfa | efb efcba bf afgb bafcg cdfgb ac caf fcdabe adgc dbgefc bedafcg bgacdf bfaeg | bcfegad afegb gabfdce bgcfa dafgb gca fcab fcabgd dcfaebg gfcdae cgdba ac gbadef egcbd | bcedg aebgfcd gfeadb afbc adebg fcgaedb dagfe agfc fdbaec fgaecd feg acdfe gf becdgf | feg fge gfe egf gf gfda gfb gfcebd gefab afcbged eabdg adgbfe fbace bgcade | dbafgce fbdaeg dagf fcbae fbegcd ecg cefdbag fcgd ebdac gbecd cg bfcgea bafdeg edfgb | fcbegd acbde bcgaef cge gbcadf cf gfbc defbca acgfd bcaedg afegd cfbgeda caf gcdba | begcad cfa bagfedc gbcdeaf begacdf dcafbg gb cgfbed gbcde cedfab dfcbe gbc cadge ebfg | gbfe gb ebcdfga bfeg fe bgadefc cbgdf gbfade cefgd ecdgaf efg afce eacgd dcgeab | gdebac fcae egbdfac fgdeab ebfca fdac fdb bgdecaf dbcgef cedbfa bgcefa fd eadfb baegd | cgfaeb dgbecf dfb bagecf ebda eagcf gcbea ba bfcegad acebgd gdecb cdafgb acb gfcdbe | fgcebd cedbgf gbfdac cefag edacf fed eacgd febadc ebafc bfcgea ecafgdb adbf fd gbfdec | fabce egfcbd deafgbc bafd gfbe fdbga ged ge aegdf baegcd afecd ebgcfda fgacbd gdeafb | cdfae fdaec ge aefdg gebaf afdbcg cfged dga fgead febdcga ad fbaedg bade gbfaec | cgbfdea gadfecb agfde gad fdg cfgdbe cfbeadg cgbf gedbc dcfage dfgeb fg agcbed adefb | gdf bdecg faedb gfd acdgbe cfabg gfbacd cbf dfbcea bcfegad cf gcdab efbag fdcg | dbfagc fgbdcea cbdga fc afbcg dgbfac dgaebf gcfea gbceadf afb fb abgcd abcdge fdcb | gbceda cgdabe bcgdae fbgdea cgbedf dbgfc cbef cf bgfda gcedb gadceb efdcag fdc bcfdaeg | fecb ebdcfg cf badgf fg cafdg fegadbc aefcdb bcagd degf gfecba adegfc cfg fdeac | gdcafe cgfdae gebfca dfcgae fdbecg fcagbd fgeabd cadbe bcdag dafgb facg gdc bdgeacf cg | cedab cbdga gcd gc gdeaf edbcag fbac fgecdba dfbcea afdce ac fbecd dbefcg cea | efcbd gdeaf dfceagb ace abgdc ebcgd ecgdf ebagcd dabe edgbcfa be cgeabf ceb cdfgba | fdacbg abegcd abdgc cabfdge fbgcd feacb ed eadf becfd bde fdabce cgdbea fadbcge gbefac | dcgbf fcebd ebcfd gbface ================================================ FILE: exm/aoc/2021/aoc_2021_08_questions.txt ================================================ --- Day 8: Seven Segment Search --- You barely reach the safety of the cave when the whale smashes into the cave mouth, collapsing it. Sensors indicate another exit to this cave at a much greater depth, so you have no choice but to press on. As your submarine slowly makes its way through the cave system, you notice that the four-digit seven-segment displays in your submarine are malfunctioning; they must have been damaged during the escape. You'll be in a lot of trouble without them, so you'd better figure out what's wrong. Each digit of a seven-segment display is rendered by turning on or off any of seven segments named a through g: 0: 1: 2: 3: 4: aaaa .... aaaa aaaa .... b c . c . c . c b c b c . c . c . c b c .... .... dddd dddd dddd e f . f e . . f . f e f . f e . . f . f gggg .... gggg gggg .... 5: 6: 7: 8: 9: aaaa aaaa aaaa aaaa aaaa b . b . . c b c b c b . b . . c b c b c dddd dddd .... dddd dddd . f e f . f e f . f . f e f . f e f . f gggg gggg .... gggg gggg So, to render a 1, only segments c and f would be turned on; the rest would be off. To render a 7, only segments a, c, and f would be turned on. The problem is that the signals which control the segments have been mixed up on each display. The submarine is still trying to display numbers by producing output on signal wires a through g, but those wires are connected to segments randomly. Worse, the wire/segment connections are mixed up separately for each four-digit display! (All of the digits within a display use the same connections, though.) So, you might know that only signal wires b and g are turned on, but that doesn't mean segments b and g are turned on: the only digit that uses two segments is 1, so it must mean segments c and f are meant to be on. With just that information, you still can't tell which wire (b/g) goes to which segment (c/f). For that, you'll need to collect more information. For each display, you watch the changing signals for a while, make a note of all ten unique signal patterns you see, and then write down a single four digit output value (your puzzle input). Using the signal patterns, you should be able to work out which pattern corresponds to which digit. For example, here is what you might see in a single entry in your notes: acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf (The entry is wrapped here to two lines so it fits; in your notes, it will all be on a single line.) Each entry consists of ten unique signal patterns, a | delimiter, and finally the four digit output value. Within an entry, the same wire/segment connections are used (but you don't know what the connections actually are). The unique signal patterns correspond to the ten different ways the submarine tries to render a digit using the current wire/segment connections. Because 7 is the only digit that uses three segments, dab in the above example means that to render a 7, signal lines d, a, and b are on. Because 4 is the only digit that uses four segments, eafb means that to render a 4, signal lines e, a, f, and b are on. Using this information, you should be able to work out which combination of signal wires corresponds to each of the ten digits. Then, you can decode the four digit output value. Unfortunately, in the above example, all of the digits in the output value (cdfeb fcadb cdfeb cdbaf) use five segments and are more difficult to deduce. For now, focus on the easy digits. Consider this larger example: be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce Because the digits 1, 4, 7, and 8 each use a unique number of segments, you should be able to tell which combinations of signals correspond to those digits. Counting only digits in the output values (the part after | on each line), in the above example, there are 26 instances of digits that use a unique number of segments (highlighted above). In the output values, how many times do digits 1, 4, 7, or 8 appear? --- Part Two --- Through a little deduction, you should now be able to determine the remaining digits. Consider again the first example above: acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf After some careful analysis, the mapping between signal wires and segments only make sense in the following configuration: dddd e a e a ffff g b g b cccc So, the unique signal patterns would correspond to the following digits: acedgfb: 8 cdfbe: 5 gcdfa: 2 fbcad: 3 dab: 7 cefabd: 9 cdfgeb: 6 eafb: 4 cagedb: 0 ab: 1 Then, the four digits of the output value can be decoded: cdfeb: 5 fcadb: 3 cdfeb: 5 cdbaf: 3 Therefore, the output value for this entry is 5353. Following this same process for each entry in the second, larger example above, the output value of each entry can be determined: fdgacbe cefdb cefbgd gcbe: 8394 fcgedb cgb dgebacf gc: 9781 cg cg fdcagb cbg: 1197 efabcd cedba gadfec cb: 9361 gecf egdcabf bgf bfgea: 4873 gebdcfa ecba ca fadegcb: 8418 cefg dcbef fcge gbcadfe: 4548 ed bcgafe cdgba cbgef: 1625 gbdfcae bgc cg cgb: 8717 fgae cfgab fg bagce: 4315 Adding all of the output values in this larger example produces 61229. For each entry, determine all of the wire/segment connections and decode the four-digit output values. What do you get if you add up all of the output values? ================================================ FILE: exm/aoc/2021/aoc_2021_09.adb ================================================ -- Solution to Advent of Code 2021, Day 9 ------------------------------------------ -- Smoke Basin -- -- First 2021 puzzle with recursion :-) -- -- https://adventofcode.com/2021/day/9 -- Copy of questions in: aoc_2021_09_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_09 is use HAT; -- input : constant VString := +"aoc_2021_09.txt"; sx : constant := 100; sy : constant := 100; -- c : Character; f : File_Type; r : array (1 .. 2) of Integer; map : array (1 .. sx, 1 .. sy) of Natural; seen : array (1 .. sx, 1 .. sy) of Boolean; size, la1, la2, la3 : Natural := 0; -- -- `Visit` returns the size of the basin around point (x, y). -- Side effect: it writes in `seen`. -- function Visit (x, y : Integer) return Natural is begin if x < 1 or else x > sx or else y < 1 or else y > sy or else seen (x, y) then return 0; end if; seen (x, y) := True; if map (x, y) = 9 then return 0; end if; return 1 + Visit (x - 1, y) + Visit (x + 1, y) + Visit (x, y - 1) + Visit (x, y + 1); end Visit; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; begin Open (f, input); for y in 1 .. sy loop for x in 1 .. sx loop Get (f, c); map (x, y) := Ord (c) - Ord ('0'); seen (x, y) := False; end loop; end loop; Close (f); r (1) := 0; for y in 1 .. sy loop for x in 1 .. sx loop if (x = 1 or else map (x - 1, y) > map (x, y)) and then (y = 1 or else map (x, y - 1) > map (x, y)) and then (x = sx or else map (x + 1, y) > map (x, y)) and then (y = sy or else map (x, y + 1) > map (x, y)) then -- We have found a low point - a location (x, y) that is -- lower than any of its adjacent locations. r (1) := r (1) + map (x, y) + 1; size := Visit (x, y); if size > la1 then la3 := la2; la2 := la1; la1 := size; elsif size > la2 then la3 := la2; la2 := size; elsif size > la3 then la3 := size; end if; end if; end loop; end loop; r (2) := la1 * la2 * la3; if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1: number of low points: " & r (1)); Put_Line (+"Part 2: product of the sizes of the 3 largest basins: " & r (2)); -- Part 1: validated by AoC: 423 -- Part 2: validated by AoC: 1198704 end if; end AoC_2021_09; ================================================ FILE: exm/aoc/2021/aoc_2021_09.txt ================================================ 9656799999432123456997667932987634348988901234569972123973212398999898743234578999878965345989412345 8746789898543235689879457891396521236567892347698763299865101987898789652123459998767893239874323458 7657896797654348798968346799987430123456943458987654987654219876747688943435698967656789098765434567 8767945698967859987653235678976521234567894569998785698765345965434567894566987654345678999886548698 9878936989898967998842123799988432345678965679989976789876459876123998999879876543234567999998657789 9989759876789899987651012989999654676789896899877899893987898765017899997989977532123456789879767899 9899898765698789998763123467898765699998789998766568932998989854146789876598765431012345678969878989 9787987974545698999873234578989876987899678987653456949899876543235678995439876532123478989654989678 7656896653432367897654348989678989876996589978321239898787987665366789989321987543234569996543294569 6542985432101256789865457892569998765989439865430149764656798878457899878910197655345699965432123468 7699876543232345699978767893478998654879921996521398943245679987678978567891298876758789899543234589 9989989854345467789989898976569999743467892987432987852134789998789765456789469987899898798954387678 8978998765676778990195999989678987654568909876549896721012878979999879345899878998963934567895698789 7867999876789989321234989999889998987678912987898765432124568965345998976901989029652123458986789899 6756889987899995435345678901999989598789329898969976543234567891299987899893499198743239567899899989 5345678998969876568856789899539976439899498789458987654545678910988956789789598999874358678989999878 3245588999654987678767898788998765323978987672387898765677989899877545695679987898765456789679878567 2133457899865698789898987657897654312369876521256789898788996789765421234989996799976768994598765456 1012345678976789897979998546789762101459985432345698969899345678973210199898765689989879323987654345 2123456789998899976567899434998979299998976543456987654901236789894391985795454767898989212398943234 3234567896789999875478996524567898987897897654567898783212345898765989674889323656987898901999892123 4365788945678998983239987678978987645656789765799969999476556969879876563479312345896567899898789012 5458899656789987899945699899989996534345679879893459878987768956989995412458923456789456998787678923 6867898767999876767896789954399897621236989997992398768998878945999989325567894567992368987654589434 9878939878999765456789899876998765432347895456789987657899999656789878934678985688954979998543678945 8989921989998754345678912999879876749456954397990198845679998769898969895989876999769899876452345796 7797890999989643234678993987764989898987895989891987932348999878987658789999987894998789985321234589 6646789899878932123456789896653299987898939876799876541256896989876545678999898923987679876542345678 5437898768967893236589898765432129876999329865789987652367955798767534567898769219876565987643456789 6545698657657789345679989654321098765695409784679898783458944987654323456789954329765434598754767893 8656798743245678956799878979434998654989598643566799854769432198765412577899895498979123799865698912 9778999894657889767898767898749876543878969432345689965878945987654323989976789987898945678977899101 9889899985769999878987656797657998652569654321298999876989656798768734896565699876787896789988956912 3998769876778954989898545679769876543478998910187892987998969989899656789454598765576997895699349893 2987645987889643498765434568978997655599987651456891098987898778949767895323459874445689934569298789 1985432398995721239897655678989999876789299732345993129986889654339878944413569763234796545678997689 9876543569954310398989767899199896989892196545456789298765678943210989432102698752125689698789976567 0987654567899451987679878954398765496989987656769899987654567894321296563213987643014578999898965456 1398875698998969876556989995459654345678998767898999874323476989432987674345987532123567899987894345 2989976789997898765443293989598743233459899898997898765212345678943498789456896543234598909876743234 9878989899876739874321012378987654102398799989875689654323466789994989898967997654345689412985432123 8767899956965323965632323569876543212399678976554678995567587999989878987898998765467897329876741012 7656789345953219876745456789987656323987567895443456789878678999876567896999019876569976535987899124 2345698999894923987896567896798767434598978987321234998989789998765458345892123987698998976899998934 1235987986789894998987878965439898765989989876510127897699898999854341237789239998987899989998987895 0129876545656789879598989896910999879876599765431456789534967898765210125678998999876787899987656989 9234995434345678965439196789891299989987678976542345678923456789874321434567897998765476799876545678 8945986325234799654321015798789989996598789989753658789212369892986476545698956899656365689995434569 7897995410125679965432123987678678965439894198764767994349498943996589656789346798743234578989323478 6789894323234567897693939876584589896520943299875879765598967899898698767893234989654125689873212369 5556789654356789998989899965423456789699954987976989876987656987769789978932129876543236798764201256 4345679965678893459876799854312345678987899876598991987976549876549890989543234989654345899854342345 1234567896789902398765689763201456899876798765439790999885434985432991299954345698769656789996456976 0145698919893212398764568954342567979985459886545699898766323976421289989895456799898767996987567987 1256789323994323459873487895656878967894398987676789797652109876534569876789567989989878945698878998 2345678999689934598932456976789989656789997699887897679843212987675698765678979878878989234589989129 3476789987567896987541237897895798787999896543999989498765323498789988654568998765767896545678999099 4587899976434679876532698998954679898998798432365679339865454679899876543678999544254898656789998978 7698999874323567998643459999543569999987654321234890123976565678989987654567898432123789767999987867 8789998765213898989654589987656998798798943210126789234597698789678998775689987521035678978999976756 9899987654345799879867678999899899677679854322287898949989989893459789987793298643146789989998865545 7998998785956789769878789934987766543598765643398967898765678932545679999894389743287894393987654334 5387899899897893456989897823496543432349876754679456987654567891234567894976569654398993212398710123 4286789998789954567896945312987932101345989867989347898943498992345698943987698795456789101239853234 3045789987698995778965432109899893232346899978993212349874679989456789932198999987567893234345954345 2134569865567989899879844398786789345456789989654324498765899978987896891099998998678954545467977656 3245698654456778999997656979645678959867898998995455569876998767898945692989987998789765656579998797 9959987843345569998989869868734567893978987687789569699989998756789434989876576899890998767898989898 7898765432123498987879998759823678991989876545678978789990987645678959878789445778921239898997778999 6989887753012397976867897642102899989998765434567899999892998534589998764621234567899399999876567895 5878999864129986545456789543234999878999543212678959898789876523569987653210123456998989998765456894 4569459954298865434345897676349898767987654104588969765698765434678998767821234767897778999987567893 3679598765987654321237898765498789656898983223467899878789897645678959898532345678976569896598678912 2998999879876543210136789877897676545789765434689999989895998656789544999643658789785458789439789323 9887891989987984334545678989987543235678978585693298793934569877894323498754769897654345678929899654 5776790994098875455676789796798763124569987678789109652123488989994212349865878989643234589214978969 4665689873129986566788997654569653023678998789893298743456567895789109456976989878510145679323469998 3534999865434597679899679932398762124589209899984349654567789964899298967987898764321234578934678987 2329898986597698789934567891987643236799919959875498765689891095998987998998949865986465678958789976 1019767899989999892123458910399754568899898945986789898789999989987876989219439877896568789769899895 2398756798978899975234567891239865678938767996797899999891298777896865878901921998989679899878998794 4987645987659798764356789932445978789324456789898989899930987656985434767899890129878989999989987643 9865434596545679875678899945566989893212345999999876789321986549876323457895791298967899998799875432 8754322987634789986789999896678997932101969899898765895439997998765412568934942987856789897698764321 7652101298945678997998988789789236893399898789799654976998998987654324569929899876545476789539875210 8743212349896789999887875678990145994988789677678967899876799398767434567898789986434365689123986929 9854529498789899898766434567891956789876643534567898998765989219976565678987678954321234678934999898 8765698987678998789654323458999897899985432423458999989854978901987676789997569854210176789549898787 9876987976589989698767454567898789989894321012567899876543467892398787899986498769321289998798766656 3989876645459876569878765698923678976789463123478999965432456799459898979876359998434799999897655545 2198765432398965456989876789434569765699954354589789654321347988998959567965219876545678988976543234 1099876541987654367896987898765678954578895455696599796542459977796543459894323987957989477895432123 2989987650199763212345698929987789543456789566789678989763598765689921298765434599768995356789921012 9879998753298654523456999019898897652569899678899789979878689874577890349876545699879654247698892123 8768999865349767684567899998769976543478998789979899869989789843456789456987656789989543123456789434 7656899965459888785678999896658987654567899894567988758899899652345678987898767896798762012348996545 4645788987567999898789998765347998765678987943459876546789998761234569999979898945679843234459987676 3434567987678932949899987643246899876799986212345986323499869810123478934567999637789954345678998789 2123456798889431234989998432143456989897695401234595434987654321234599123456798548898765456789239892 3012348999995432345678999543012345699976543212345976545698975432346789245678987656789876797890123921 ================================================ FILE: exm/aoc/2021/aoc_2021_09_questions.txt ================================================ --- Day 9: Smoke Basin --- These caves seem to be lava tubes. Parts are even still volcanically active; small hydrothermal vents release smoke into the caves that slowly settles like rain. If you can model how the smoke flows through the caves, you might be able to avoid it and be that much safer. The submarine generates a heightmap of the floor of the nearby caves for you (your puzzle input). Smoke flows to the lowest point of the area it's in. For example, consider the following heightmap: 2199943210 3987894921 9856789892 8767896789 9899965678 Each number corresponds to the height of a particular location, where 9 is the highest and 0 is the lowest a location can be. Your first goal is to find the low points - the locations that are lower than any of its adjacent locations. Most locations have four adjacent locations (up, down, left, and right); locations on the edge or corner of the map have three or two adjacent locations, respectively. (Diagonal locations do not count as adjacent.) In the above example, there are four low points, all highlighted: two are in the first row (a 1 and a 0), one is in the third row (a 5), and one is in the bottom row (also a 5). All other locations on the heightmap have some lower adjacent location, and so are not low points. The risk level of a low point is 1 plus its height. In the above example, the risk levels of the low points are 2, 1, 6, and 6. The sum of the risk levels of all low points in the heightmap is therefore 15. Find all of the low points on your heightmap. What is the sum of the risk levels of all low points on your heightmap? --- Part Two --- Next, you need to find the largest basins so you know what areas are most important to avoid. A basin is all locations that eventually flow downward to a single low point. Therefore, every low point has a basin, although some basins are very small. Locations of height 9 do not count as being in any basin, and all other locations will always be part of exactly one basin. The size of a basin is the number of locations within the basin, including the low point. The example above has four basins. The top-left basin, size 3: 2199943210 3987894921 9856789892 8767896789 9899965678 The top-right basin, size 9: 2199943210 3987894921 9856789892 8767896789 9899965678 The middle basin, size 14: 2199943210 3987894921 9856789892 8767896789 9899965678 The bottom-right basin, size 9: 2199943210 3987894921 9856789892 8767896789 9899965678 Find the three largest basins and multiply their sizes together. In the above example, this is 9 * 14 * 9 = 1134. What do you get if you multiply together the sizes of the three largest basins? ================================================ FILE: exm/aoc/2021/aoc_2021_10.adb ================================================ -- Solution to Advent of Code 2021, Day 10 ------------------------------------------- -- Syntax Scoring -- -- https://adventofcode.com/2021/day/10 -- Copy of questions in: aoc_2021_10_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2021_10 is use HAT, Interfaces; -- input : constant VString := +"aoc_2021_10.txt"; -- stack : String (1 .. 200); top : Natural; -- procedure Push (c : Character) is begin top := top + 1; stack (top) := c; end Push; -- function Pop_OK (c : Character) return Boolean is begin if top = 0 then return False; end if; top := top - 1; return stack (top + 1) = c; end Pop_OK; -- scores : array (1 .. 100) of Integer_64; top_score_array : Natural := 0; ins : Natural; line_score : Integer_64 := 0; f : File_Type; c : Character; points : Integer_64; r : array (1 .. 2) of Integer_64; compiler_test_mode : constant Boolean := Argument_Count >= 2; begin r (1) := 0; r (2) := 0; scores (1) := 1; -- Just for calming down a GNAT warning. Open (f, input); while not End_Of_File (f) loop -- Analyse a line's syntax: top := 0; loop Get (f, c); case c is when '(' => Push (')'); when '[' => Push (']'); when '{' => Push ('}'); when '<' => Push ('>'); when ')' | ']' | '}' | '>' => if not Pop_OK (c) then -- Incorrect closing character. case c is when ')' => points := 3; when ']' => points := 57; when '}' => points := 1197; when '>' => points := 25137; when others => null; end case; r (1) := r (1) + points; Skip_Line (f); -- We count only the first error of a line. exit; end if; when others => null; end case; if End_Of_Line (f) then if top > 0 then -- Incomplete line line_score := 0; for i in reverse 1 .. top loop line_score := line_score * 5; case stack (i) is when ')' => points := 1; when ']' => points := 2; when '}' => points := 3; when '>' => points := 4; when others => null; end case; line_score := line_score + points; end loop; ins := 0; for i in reverse 1 .. top_score_array loop if line_score <= scores (i) then ins := i; end if; end loop; if ins = 0 then scores (top_score_array + 1) := line_score; else for i in reverse ins .. top_score_array loop scores (i + 1) := scores (i); end loop; scores (ins) := line_score; end if; top_score_array := top_score_array + 1; end if; exit; end if; end loop; end loop; r (2) := scores (top_score_array / 2 + 1); -- ^ "There will always be an odd number of scores to consider." Close (f); if compiler_test_mode then if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1: invalid closing delimiter points:" & Integer_64'Image (r (1))); Put_Line (+"Part 2: autocomplete points: " & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 388713 -- Part 2: validated by AoC: 3539961434 end if; end AoC_2021_10; ================================================ FILE: exm/aoc/2021/aoc_2021_10.txt ================================================ (({(({{<{{(<{<{}()>(<>{})}{[(){}]{{}[]}}>)<[{{{}[]}{{}{}}}{{[]()}<[][]>}]>}}(<[{([()<>][[]<>])}((( ([<[([<{(<[[[<()[]>[()()]]<[<>()]<[][]>>]](({({}{})}{<[]<>><[]()>})[<<[]<>>([]())>{<<>{}><<><>>}])><{<{( [([(([<<<{(<([()()]{{}{}}){({}[])[()[]]}>({(<>()){{}{}}}<<[]{}>[<>()]>)>}[([<({}[]){{}{}}>])[<<< ([[{{([<<<<({(<>{}){[]{}}]<({}{})[[]()]>)((([]())(()[])){[()[]]{()<>}})>{[<(<>[])>{[()<>]{()[]}}]({(<><>)[[ {<({[(({((({((<>())([]()))}[{{[]()}{()()}}(<<><>>(<>{}))])))}<<((([[<>{}][<><>]](<{}()>[{}}))< ({{<({<{<{{[<{{}<>}[<>()]>[<()<>><[]()>]]}(([{{}<>}{(){}}][(()<>){<><>}])(({{}()})[{[]{}}]))}>} (<[[[<[<{{([{(()()){[]{})}{[[][]][<>[]]}][{({}[])}[<<>[]>]])}}({(<(<(){}>{()[]}){[()[]]{{} [<[[({([(<[{<({}())[[]()]>{<()<>>[(){}]}}]>)]<<{(<<<<>><{}>>([{}()][{}<>])>[[{<>}<{}()>][{()[]}]])}>> [{(<{{([(<[<{(<>[]){{}()}}>(<({}<>)[{}{}]>{{<><>}[<>{}]})]{[{{{}()}<()()>}]{([()[]])[(<>())<()[] <[[<<<{({[<{(<[][]><{}<>>)[([]<>)[[][]]]}[{[<>[]]}((<>()){()<>})]>{[(<()()>{{}()})<[{}[]]{ {[{(([<([[{[(({}<>){<>[]})([[][]](<>[]))]{{[[]{}]}}}]<{(<[()<>]<{}()]>{<[]()>[()[]]})<(<()<>>[[][]] {<<<{<{({[[({<<>{}>[<>]})<[<<>[]><[]<>>][[<>{}]({}{})]>]][{[([[][]][[]()])]([[()()]{[]<>}])}<[({[]<>} ([<(<<{<<((<<({}())[{}<>]>{<[][]>{{}()}}>(<<<>()>(()[])>))<<{[<>()](<>())}<([][])[()()]>>> <<(<[{[<{(<<{<[][]>[<>[]]}<(<>{})([][])>>>)<<[{[()()][[]{}]}<[()[]]<[][]>>]>{<{<[]<>>{<>()}}[<()()>[<>() <(({({{{(([({<<><>>{[]<>}}({()[]}([]{}))}[{<()[]><[][]>}<{[]{}}{[]()}>]]<<<[(){}]{(){}}>{{( [{[[{<<{<{<<([()()]{[]()})[[[][]]<[][]>]>>}>(<{(([[]()][[]()])[({}<>){<>}]){([{}[]]){[{}[]>[[]{} ({[[{<[({[{({{{}[]}[<>[]]}{({}()){{}}})[({<>[]}{[]()}){{(){}}[[]{}]}]}](([[[()<>](<>[])]<< [(<{{[<{<{(<{({}[])<()>}><<<<><>><()()>>>)[{[{{}[]}({}[])]<(()[])({})>][{<<><>>}[({}[])<<> (<({[<<[<(<<<<()()><{}{}>>([{}<>]}>[({{}<>}[()<>])(({}[])[[]()])]>{{<{{}[]}(<>())>[[(){}]< <<{(<({{[{<[(([]<>)<[]{}>)(<<>{}><[]()>)]{{[{}[]]<(){}>}(<{}<>>(()()))}>(<<({})(<>[])>><{{[]<>}(< <(<({[<[[<({[[{}{}][[]<>]}[<<>{}>(()[])]}<{{()[]}}[[<>[]]<[]()>]>)<[(([][])<[]()>)(<()[]>)] ({[<(({[{((((<<>[]>(<>()))<(()[])>)<<({}{})<<><>>>>)[[[<(){}>(<><>)]([(){}][{}()])]])[((<(( ({[{[([{[[<[((<>())[<>()])]({{(){}}{()()}}([(){}]<<>[]>))>]][[<[<[{}<>]<(){}>>({[]()}<{}[]>)]((<()()>( <{[{(<{<({[<<(<>{})((){})>(({}<>)[{}{}])><[[<>[]]<(){}>]<(<>[])<{}{}>>>]{{([{}[]])<<()[]>>} [{[[(([(<[[{<{()[]}([]<>)><<[]()>[<>()]>}]<([<()<>>{<>()}][(()<>){{}{}}])>]<{{[{[][]}(())]}( <<(<<[(([({<{(())}([{}[]](<>[]))]<<<()<>><[]{}>>[<[][]>{{}<>}]>}[[{[[]()]}({()()}{[]})]<(< ({(<<<<[({{<<{<>{}}({}())>({()<>}[()<>])>{{{()<>}(()[])}(<[]<>>(()<>))}}(<<[{}]((){})><({}[ ({[(<<[<[(<[<(()<>)>{(()())({}[])}>[{{[]<>}[{}{}]}({[]()}[<>[]])]>)]({[<[{[]<>}[{}()]][[[]<>]<<>>] {(<{<{[({({[<[[]<>][()[]]>{({}()){<><>}}]{([[]()]({}{}))[<<><>>{{}{}}]}}){{(<([]{})>({<>[]}<[][]>))} <{([{{([{[[{{(()[])<{}[]>}}{{{()()}<<><>>}}][{{[[][]]{[][]}}}]]}])}{([[<(<<<<>[]>([]{})>>({<{}()>[[]()]>([[][ [{(<{[[{((<{<[[][]][[]<>]>[(()())[(){}]]}{{{{}[]}[(){}]}(<()[]>{[]()})}>({((()()}){({}[])([]{})}}))) {{((<({[({{{({<>{}}<[]{}>)[{{}()}{<>[]}]}<[({}[])<<>>]>}}(<<({[]<>}([][]))(<[]()><{}[]>)>{<({}[]){{}{ [<(<[{<({[(([[[]][[]<>]][[<><>]{[]()}])[{({}{}){<>{}}}<{()<>}{{}{}}>])](<[({<>{}}([]()))][[<{}<>>([]())](( <([[<(({{([{[{<>}([]())][{()()}(<>()))}[([<><>]{<>[]})(([]{}){{}()})]](<(([]<>)([]{}))[(<>())]>)) {{{[{[(<((<([{{}{}}[[][]]](([])))])){[<<[<[]()>[<><>]]>>{{<[[][]][{}<>]>[<[]<>>{[]()}]}[[([]() <<([({({{[{[<(()[])><([]<>){<>{}}>]<[(<>[])<{}()>]>}]}<<<[{([][])((){})}(<{}<>>{()[]})][({[][]}{[]{}})]><[( [[((([([[{<([(()()){{}<>}]<([]<>){[]{}}>)[(<{}{}>[{}<>])(<{}{}>[()[]])]><[({{}[]})[[<>()][{}[]]]]{<<()[] <<<{(([{[<({{({}{})(<><>)}({{}()})}{<<()><(){}>>[{<>{}][()<>]]}){(<<{}[]>[<><>]>({[]()}<{}{}>)){{{<>}{[]< ([[{{<{<{[<{([()()]<<>[]>)[[()<>](()<>)]}>[<({()<>}(()))<{[]{}}{{}{}}>>(([(){}]<()()>)<<()()>(<><>)>)]](({ ((<<[<([{<([<<()()>{[]<>}>[<{}[]>([])]][([<>()]{()[]})])><((<<<><>>{<><>}}([{}()][()<>])){[{[]}] [<{(({{[{<[[{[<>()]}[[()()]({}[])]]<[({}<>)(<>{})]<(<>{})[{}<>]>>]<<(([]())<{}()>)(<[][]>(()[]))>>>(( <[<[[([<(<({{[()]<<>>}([<>[]][{}()])}([<[]{}><{}()>][<<>{}){<>()}]))>[<[[<()[]><()[]>][[<> {[[[{<[{[{[[[(<>()){[]}]{[{}()]}]{[<()<>><<><>>]({<>()}{[]()})}]}]<[{(<<()()><[]()>>(<{}<>>{(){}}))([{{}}][[ <([([([{<[[{{<{}()>{[]()}}}<((<><>){[]()}>>]{[[[{}[]]({}<>)]<((){})>]{(<()<>>(()<>))([<>]<{}< [({<[[{[({<{((<>{})<{}[]>)[<[]()>([]<>)]}>}<{<<<[][]>[{}{}]>>([<(){}><{}[]>])}<<<<<><>>{{}<>>>{[<> {<{{<([{([{<[(<>())<{}[]>]({<>[]})>[[(()()){<>{}}]{{<><>}(()[])}]}{([(<>)(()[])])(({<>{}}<[]<>))([ [<{(<<<{{{([{[[][]]{()()}}<[[][]](()())>][(<{}[]>({}[]))]){({<(){}>(<>())}<{(){}}{[]{}}>){<(()())[(){}]>({{}( {<<[<[{([[<{<(<>){<>{}}>{({}())(<>{})}}<(([][]))>><{{[[]<>][[]()]}[<<>()><(){}>]}>]])}[{([((<((){ ([(({<[[((<([([]())[[][]]][{<>{}}<(){}>]]><<(<(){}>[[]()])([[][]][()()])><[{()()}<<>{}>]>>)){ [{(<<<{((<<({[()[]]<{}()>}{<<>{}>{<>[]}})((<{}[]>[()<>])<<<>[]>[<>[]]>)><<<[(){}]>{<()[]>{(){}}}>([<<><>>{{ {([({[[<({{([(<>{})<[]<>>])[[<{}><<>{}>]]}{([<[]()>[{}<>]]<([]{})>)})<({{[{}[]]{<><>}}{[[]{}]<<>{}>}} [[[((<[([({({<<>{}>[<><>]}){{(()<>)<[]()>}<{{}[]}({}())>}})[((({<><>})({[][]}(()())))<[{{}{}}{() <<[([(({<<[[[<[]<>>]]<((<><>)[{}[]])>][([<<>{}>{[][]}]{{()()}[[]()]>){(([]<>)([][])){(<><>)}}]>{[{ <([[(<{{{{({<{{}{}}(()())>[[[]()]{()<>}]}[[{[]()}{()()}>])}}<[<{[(()<>)(()())][(()())]}({<()<>>(<>{} [{{[<(<{(<<<({{}()}<<>()>)([[]()]{()[]})>(({{}<>}[<>{}])([(){}]{()<>}))>[[(<[]{}>(<><>))[<[] {{{[{<{[<<{{{{()<>}{(){}}}}<([{}<>][{}{}])<<{}<>>{()[]}>>}{[<<<>>[()<>]>]([[{}()](<>{})]{{[][]}{(){}}}) [[[{<({{(<([(<()()>({}()))])>)<<(<[(()())]{(<>())[<>[]]}><<{(){}}<{}<>>>[{[]()}(<>{})]>)([{([]<>)([][ (({[(({{[{({[(())<(){}>]})<{<<{}{}](()<>)>({[]{}}((){}))}({<[]()>[[]<>]}{<{}[]>[[]{}]})>}][{< [<{<[[[<(({[[(<>())]<{<>[]}(<><>)>]}[<{<()<>>}><[{()[]}(<>[])]{{<>()}[{}<>]}]])<[<({{}[]}(<>< [(<{{[{{([({{[{}()]<()()>}{[()()]{<>[]}}}(<<()>(<>{})>))]<([(<[]>[[]<>])([{}](<>()])])<{<<[]{}>(<> [[{{([<([{{([{[]{}}<()[]>]{<(){}>([][])})}<<{{<><>}[()]}{<<>{}>{<>}}>([(<>{})<<>[]>]{{<><>}{<>()}})>} <[{([<{<[<(<{{<><>}[{}<>]}<<{}[]><[][]>>>{({()()}{<>[]})<<[]{}>[{}[]]>})<<[({}<>)]>(({{}()})(((){}]))>> {[[<(([<[<<<<[[]()]{()<>>>{({}())<[]{}>}>[({<>{}}(<>[]))((()[])[()])]>>{[[[({})]{(()())[<>()]}]]{<{<()( <([({[[([[{{<[{}[]](<>)><{()()}[[]{}]>}<<({}{})({}{})><<(){}><<>[]>>>}[{{([][])(<>{})}[<<>[]><{}{}>]}[<[ ((<<<[<[(<<[[({}<>)<[]>][[(){}]<<>()>]]{<[()()]<()<>>>{{<>()}((){})}}>[({<<>[]>{()()}))(({[]()}{()[]} [(({{<[([{[[({(){}}{()[]}){([]{})([]{})}][{{<>()}<{}{}>}]]({{[<>[]]}(<{}[]><{}()>)}(({()()}(( <[<<{<({<{<<[(()())[()[]]]]<({{}{}}[[]<>])>>[([<(){}><{}<>>]<<[]()>(<><>)>)[[(()[]){{}()}]{( <{[<({(<({<[[(()[])][<()()>({}())]](<{[]()}[{}[]]>({(){}}{()[]}))>}[<{<<<><>>[(){}]>{<()<>>{<>[]}}}>[<{ {{{<({{(<({{[[<>()]<<>[]>]{<<><>>([]<>)}}}({<<<><>>{[]<>}><(<>()>([][])>}))>([<{[{{}()}[[][]]]<{<>[]}<[]<>>> {{(([{[[([([{<[]()>{[]{}}}(<()[]><[][]>>]({{(){}}[[][]]}[[<>]{<>()}]))])]]}])[[[([<[[[<[[]<>]<( [<(<{{<((([(([()[]]<{}>)<[<><>][{}()]>)<([[]()])>](<{((){})((){})}{([]<>)<<>[]>}){[([]())](({}[]){() <({[<(<(({[([<{}()><(){}>]([<>][()()]))(<[()[]]><[()[]]({}{})>)]{(<(<>{})[{}<>]><{{}{}}{[]()}>) {<<[<{[[[([<{{[][]}[[]()]}<[[][]][<>{}]>>]){{[<<()()>(()[])][[<>()]{<>()}]]((<<><>><{}()>)[{{ {{<([{[[<(<{{{{}[]}{<><>}}}((<{}>))>[(<(()[]){<>{}}>((()())[<>]))])>]]}[{[{((([<(){}>({}[])][<( <[[((([{[[<<[{<>[])[{}[]]]>>(<[{[][]}<{}<>>][[()<>][[][]]]>([([]<>)({}())](<{}()>{()<>})))]< ({<{<[{(((<(<(()[]){[][]}>[<()<>>[<>()]])(<{{}{}}(<>{})>)>[(({(){}}{()()])[{{}{}}[<>{}]])]) ({{((<([(({([[<>()][{}{}]]<(<>)(())>}}{<([<>()]{[]})([<>{}](<>[]))><({[]()}(<>[])){([][])[<>[]]}>})[{ ([{[<(({(<<<<<[]<>>{[]{}}><((){}){<>()}>>([[()[]][<>{}]]([[][]][()<>]))>><<[([()()]{<><>}){<{}<>>{<>< [{({<{<{({(({[[]()]([][])}{{{}()}([][]>}){<({}<>)[<>()]>[[()<>]<<>>]})[(<<()()>{[][]}><[<>( {[[<({<<<<<{[[{}{}](()())]<([][]){<><>}>}>{<[[<>()]<[]>][{<>{}}({}[])]>}>[{{{[()<>][<>{}]}}}[[[({ [<(<(<{<<{{{(<()[]>{{}})}}<[[{[]{}}([]{})][(<><>)[[]()]]]{<{<>[]}(<><>)>[({})(<>[])]}>}[(([[{}{}][ (([([[<<[[(<({()<>}{()<>})<([]<>)(<>[])>>[{<{}[]>{[]()}}])[<<([][])<[]()>>[{{}()>{{}{}}]>]]][[<<(([]<>) [([[{([{[{{<(<<>()>)(<[]()><<>{}>)>><<(<[]()>([][])){<<><>><{}[]>}>([[<><>]{{}()}]<{[]()}>)>}<({([() ([[([{<{([<<<(()())[{}()]>([{}<>](()[]))>({<{}[]><<>[]>}{([]<>)({}())})>[(<<{}()><<>()>>[[<><>]])({[[]()]<{} {[{{([(<<([([<[]()>])<{({}<>)({}())}<([]()){[]<>}>>]){((<{[]<>}({}{})>({{}[]}{{}<>}))[({[][ {{[(<<<({<{[[([]<>){()()}]((<><>)[{}()])]{[(()<>)[{}()]]}}([<<[][]>)[{()<>}<{}{}>]]{{{{}{}}((){})}{[<> {(<<[(<<<<{([[[]<>]{(){}}]{{[]()}}){<<()<>>>[{{}{}}<{}<>>]}}>[[{[{<>()}<{}[]>]<{{}[]}>}<(({}[])(<><>) <<[(<{[({<<<<{[]{}}<{}[]>>>({{()[]}{()()}}<<{}{}>({}{})>)>>})]{(<((<([[]()][()<>]){((){})<[] [[[[{<<[[{<(([{}{}]([]<>))({[]()})}(<{()[]}<{}<>>>{[<>{}]})>({[<{}{}>][<<>{}>(<>)]}[<{[][]}{{}{}} {<<[(<((({{{[[<>[]]{<>{}}](({}())({}{}))}<{<(){}>([]<>)}{((){})}]}}{<{{([]())[()]}{<(){}>(<><>)}}[[<<> <([[[[[[{<(<[<<><>>{[][]}]>)([([()[]][()()])]([{()[]){()[]}][{[]()}(()<>)]))>[{[({<>()}[{} [(({<<<({<{[(<{}{}>{()<>}){{()[]}{[]{}}}]}>})([<<<({<>()}[[]()])>({[{}<>]<[]<>>}(((){})))>>{[[([<><>]([]< {{[[({{[({<{[{()<>}([][])]([(){}])}>(<(([]())<()<>>){[[]()]([]())}><<<<>[]>[()<>]>[<[]{}>[<><>]] <{({((<{[{[<(<[]{}>(<>{}))>][{{<{}<>}{()<>}}<(<>())<()()>>}[[({}()){[]()}](<<>[]>{[]()})]]}<<{(({}<> (<<{{{[{[{((<{()<>}({}<>)>[(()<>)(<><>)]))[[[(<>[])<{}<>>][[[]<>]<{}()>]]<[(<>{})[<>]]>]}]}][( ((({([[<[([[[[()[]]<{}()>](({}())[()])]<[{(){}}({}())](([]()){{}()})>]<(({<>{}}[[]{}])<<()<> {{[(<<([({((([{}<>]{{}[]})([<><>](<>())))[{(()[])[()()]>[(()()){<>[]}]])}<([{[[]()][[]{}]}( [<<({{[<<[({((()<>)[<>()]){<{}>[[]<>]}}[<{[]()}(()<>)>])<([<<>{}>[<><>]]<{[]<>}[()<>]>){[{<><>}<<>[]>]{(( ================================================ FILE: exm/aoc/2021/aoc_2021_10_questions.txt ================================================ --- Day 10: Syntax Scoring --- You ask the submarine to determine the best route out of the deep-sea cave, but it only replies: Syntax error in navigation subsystem on line: all of them All of them?! The damage is worse than you thought. You bring up a copy of the navigation subsystem (your puzzle input). The navigation subsystem syntax is made of several lines containing chunks. There are one or more chunks on each line, and chunks contain zero or more other chunks. Adjacent chunks are not separated by any delimiter; if one chunk stops, the next chunk (if any) can immediately start. Every chunk must open and close with one of four legal pairs of matching characters: If a chunk opens with (, it must close with ). If a chunk opens with [, it must close with ]. If a chunk opens with {, it must close with }. If a chunk opens with <, it must close with >. So, () is a legal chunk that contains no other chunks, as is []. More complex but valid chunks include ([]), {()()()}, <([{}])>, [<>({}){}[([])<>]], and even (((((((((()))))))))). Some lines are incomplete, but others are corrupted. Find and discard the corrupted lines first. A corrupted line is one where a chunk closes with the wrong character - that is, where the characters it opens and closes with do not form one of the four legal pairs listed above. Examples of corrupted chunks include (], {()()()>, (((()))}, and <([]){()}[{}]). Such a chunk can appear anywhere within a line, and its presence causes the whole line to be considered corrupted. For example, consider the following navigation subsystem: [({(<(())[]>[[{[]{<()<>> [(()[<>])]({[<{<<[]>>( {([(<{}[<>[]}>{[]{[(<()> (((({<>}<{<{<>}{[]{[]{} [[<[([]))<([[{}[[()]]] [{[{({}]{}}([{[{{{}}([] {<[[]]>}<{[{[{[]{()[[[] [<(<(<(<{}))><([]([]() <{([([[(<>()){}]>(<<{{ <{([{{}}[<[[[<>{}]]]>[]] Some of the lines aren't corrupted, just incomplete; you can ignore these lines for now. The remaining five lines are corrupted: {([(<{}[<>[]}>{[]{[(<()> - Expected ], but found } instead. [[<[([]))<([[{}[[()]]] - Expected ], but found ) instead. [{[{({}]{}}([{[{{{}}([] - Expected ), but found ] instead. [<(<(<(<{}))><([]([]() - Expected >, but found ) instead. <{([([[(<>()){}]>(<<{{ - Expected ], but found > instead. Stop at the first incorrect closing character on each corrupted line. Did you know that syntax checkers actually have contests to see who can get the high score for syntax errors in a file? It's true! To calculate the syntax error score for a line, take the first illegal character on the line and look it up in the following table: ): 3 points. ]: 57 points. }: 1197 points. >: 25137 points. In the above example, an illegal ) was found twice (2*3 = 6 points), an illegal ] was found once (57 points), an illegal } was found once (1197 points), and an illegal > was found once (25137 points). So, the total syntax error score for this file is 6+57+1197+25137 = 26397 points! Find the first illegal character in each corrupted line of the navigation subsystem. What is the total syntax error score for those errors? --- Part Two --- Now, discard the corrupted lines. The remaining lines are incomplete. Incomplete lines don't have any incorrect characters - instead, they're missing some closing characters at the end of the line. To repair the navigation subsystem, you just need to figure out the sequence of closing characters that complete all open chunks in the line. You can only use closing characters (), ], }, or >), and you must add them in the correct order so that only legal pairs are formed and all chunks end up closed. In the example above, there are five incomplete lines: [({(<(())[]>[[{[]{<()<>> - Complete by adding }}]])})]. [(()[<>])]({[<{<<[]>>( - Complete by adding )}>]}). (((({<>}<{<{<>}{[]{[]{} - Complete by adding }}>}>)))). {<[[]]>}<{[{[{[]{()[[[] - Complete by adding ]]}}]}]}>. <{([{{}}[<[[[<>{}]]]>[]] - Complete by adding ])}>. Did you know that autocomplete tools also have contests? It's true! The score is determined by considering the completion string character-by-character. Start with a total score of 0. Then, for each character, multiply the total score by 5 and then increase the total score by the point value given for the character in the following table: ): 1 point. ]: 2 points. }: 3 points. >: 4 points. So, the last completion string above - ])}> - would be scored as follows: Start with a total score of 0. Multiply the total score by 5 to get 0, then add the value of ] (2) to get a new total score of 2. Multiply the total score by 5 to get 10, then add the value of ) (1) to get a new total score of 11. Multiply the total score by 5 to get 55, then add the value of } (3) to get a new total score of 58. Multiply the total score by 5 to get 290, then add the value of > (4) to get a new total score of 294. The five lines' completion strings have total scores as follows: }}]])})] - 288957 total points. )}>]}) - 5566 total points. }}>}>)))) - 1480781 total points. ]]}}]}]}> - 995444 total points. ])}> - 294 total points. Autocomplete tools are an odd bunch: the winner is found by sorting all of the scores and then taking the middle score. (There will always be an odd number of scores to consider.) In this example, the middle score is 288957 because there are the same number of scores smaller and larger than it. Find the completion string for each incomplete line, score the completion strings, and sort the scores. What is the middle score? ================================================ FILE: exm/aoc/2021/aoc_2021_11.adb ================================================ -- Solution to Advent of Code 2021, Day 11 ------------------------------------------- -- Dumbo Octopus -- -- https://adventofcode.com/2021/day/11 -- Copy of questions in: aoc_2021_11_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_11 is use HAT; input : constant VString := +"aoc_2021_11.txt"; sx : constant := 10; sy : constant := 10; map : array (1 .. sx, 1 .. sy) of Natural; flashed : array (1 .. sx, 1 .. sy) of Boolean; -- procedure Increase (x, y : Integer) is begin map (x, y) := map (x, y) + 1; if map (x, y) > 9 and then not flashed (x, y) then flashed (x, y) := True; for yy in y - 1 .. y + 1 loop for xx in x - 1 .. x + 1 loop if xx in 1 .. sx and then yy in 1 .. sy and then map (xx, yy) <= 9 then Increase (xx, yy); end if; end loop; end loop; end if; end Increase; -- c : Character; step, count : Natural; f : File_Type; r : array (1 .. 2) of Integer; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Open (f, input); for y in 1 .. sy loop for x in 1 .. sx loop Get (f, c); map (x, y) := Ord (c) - Ord ('0'); end loop; end loop; Close (f); r (1) := 0; step := 0; loop step := step + 1; for y in 1 .. sy loop for x in 1 .. sx loop flashed (x, y) := False; end loop; end loop; for y in 1 .. sy loop for x in 1 .. sx loop Increase (x, y); end loop; end loop; -- count := 0; for y in 1 .. sy loop for x in 1 .. sx loop if map (x, y) > 9 then map (x, y) := 0; count := count + 1; end if; end loop; end loop; if step <= 100 then r (1) := r (1) + count; end if; if count = sx * sy then r (2) := step; exit; end if; end loop; if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: Total flashes in the first 100 steps: " & r (1)); Put_Line (+"Part 2: First step during which all octopuses flash: " & r (2)); -- Part 1: validated by AoC: 1679 -- Part 2: validated by AoC: 519 end if; end AoC_2021_11; ================================================ FILE: exm/aoc/2021/aoc_2021_11.txt ================================================ 1553421288 5255384882 1224315732 4258242274 1658564216 6872651182 5775552238 5622545172 8766672318 2178374835 ================================================ FILE: exm/aoc/2021/aoc_2021_11_questions.txt ================================================ --- Day 11: Dumbo Octopus --- You enter a large cavern full of rare bioluminescent dumbo octopuses! They seem to not like the Christmas lights on your submarine, so you turn them off for now. There are 100 octopuses arranged neatly in a 10 by 10 grid. Each octopus slowly gains energy over time and flashes brightly for a moment when its energy is full. Although your lights are off, maybe you could navigate through the cave without disturbing the octopuses if you could predict when the flashes of light will happen. Each octopus has an energy level - your submarine can remotely measure the energy level of each octopus (your puzzle input). For example: 5483143223 2745854711 5264556173 6141336146 6357385478 4167524645 2176841721 6882881134 4846848554 5283751526 The energy level of each octopus is a value between 0 and 9. Here, the top-left octopus has an energy level of 5, the bottom-right one has an energy level of 6, and so on. You can model the energy levels and flashes of light in steps. During a single step, the following occurs: First, the energy level of each octopus increases by 1. Then, any octopus with an energy level greater than 9 flashes. This increases the energy level of all adjacent octopuses by 1, including octopuses that are diagonally adjacent. If this causes an octopus to have an energy level greater than 9, it also flashes. This process continues as long as new octopuses keep having their energy level increased beyond 9. (An octopus can only flash at most once per step.) Finally, any octopus that flashed during this step has its energy level set to 0, as it used all of its energy to flash. Adjacent flashes can cause an octopus to flash on a step even if it begins that step with very little energy. Consider the middle octopus with 1 energy in this situation: Before any steps: 11111 19991 19191 19991 11111 After step 1: 34543 40004 50005 40004 34543 After step 2: 45654 51115 61116 51115 45654 An octopus is highlighted when it flashed during the given step. Here is how the larger example above progresses: Before any steps: 5483143223 2745854711 5264556173 6141336146 6357385478 4167524645 2176841721 6882881134 4846848554 5283751526 After step 1: 6594254334 3856965822 6375667284 7252447257 7468496589 5278635756 3287952832 7993992245 5957959665 6394862637 After step 2: 8807476555 5089087054 8597889608 8485769600 8700908800 6600088989 6800005943 0000007456 9000000876 8700006848 After step 3: 0050900866 8500800575 9900000039 9700000041 9935080063 7712300000 7911250009 2211130000 0421125000 0021119000 After step 4: 2263031977 0923031697 0032221150 0041111163 0076191174 0053411122 0042361120 5532241122 1532247211 1132230211 After step 5: 4484144000 2044144000 2253333493 1152333274 1187303285 1164633233 1153472231 6643352233 2643358322 2243341322 After step 6: 5595255111 3155255222 3364444605 2263444496 2298414396 2275744344 2264583342 7754463344 3754469433 3354452433 After step 7: 6707366222 4377366333 4475555827 3496655709 3500625609 3509955566 3486694453 8865585555 4865580644 4465574644 After step 8: 7818477333 5488477444 5697666949 4608766830 4734946730 4740097688 6900007564 0000009666 8000004755 6800007755 After step 9: 9060000644 7800000976 6900000080 5840000082 5858000093 6962400000 8021250009 2221130009 9111128097 7911119976 After step 10: 0481112976 0031112009 0041112504 0081111406 0099111306 0093511233 0442361130 5532252350 0532250600 0032240000 After step 10, there have been a total of 204 flashes. Fast forwarding, here is the same configuration every 10 steps: After step 20: 3936556452 5686556806 4496555690 4448655580 4456865570 5680086577 7000009896 0000000344 6000000364 4600009543 After step 30: 0643334118 4253334611 3374333458 2225333337 2229333338 2276733333 2754574565 5544458511 9444447111 7944446119 After step 40: 6211111981 0421111119 0042111115 0003111115 0003111116 0065611111 0532351111 3322234597 2222222976 2222222762 After step 50: 9655556447 4865556805 4486555690 4458655580 4574865570 5700086566 6000009887 8000000533 6800000633 5680000538 After step 60: 2533334200 2743334640 2264333458 2225333337 2225333338 2287833333 3854573455 1854458611 1175447111 1115446111 After step 70: 8211111164 0421111166 0042111114 0004211115 0000211116 0065611111 0532351111 7322235117 5722223475 4572222754 After step 80: 1755555697 5965555609 4486555680 4458655580 4570865570 5700086566 7000008666 0000000990 0000000800 0000000000 After step 90: 7433333522 2643333522 2264333458 2226433337 2222433338 2287833333 2854573333 4854458333 3387779333 3333333333 After step 100: 0397666866 0749766918 0053976933 0004297822 0004229892 0053222877 0532222966 9322228966 7922286866 6789998766 After 100 steps, there have been a total of 1656 flashes. Given the starting energy levels of the dumbo octopuses in your cavern, simulate 100 steps. How many total flashes are there after 100 steps? --- Part Two --- It seems like the individual flashes aren't bright enough to navigate. However, you might have a better option: the flashes seem to be synchronizing! In the example above, the first time all octopuses flash simultaneously is step 195: After step 193: 5877777777 8877777777 7777777777 7777777777 7777777777 7777777777 7777777777 7777777777 7777777777 7777777777 After step 194: 6988888888 9988888888 8888888888 8888888888 8888888888 8888888888 8888888888 8888888888 8888888888 8888888888 After step 195: 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 If you can calculate the exact moments when the octopuses will all flash simultaneously, you should be able to navigate through the cavern. What is the first step during which all octopuses flash? ================================================ FILE: exm/aoc/2021/aoc_2021_12.adb ================================================ -- Solution to Advent of Code 2021, Day 12 ------------------------------------------- -- Passage Pathing -- -- https://adventofcode.com/2021/day/12 -- Copy of questions in: aoc_2021_12_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_12 is use HAT; -- dic_max : constant := 30; subtype Dic_Range is Integer range 1 .. dic_max; subtype Segment_Range is Dic_Range; top, segs : Natural := 0; dic : array (Dic_Range) of VString; start_idx, end_idx : Dic_Range; -- type Segment is record from : Dic_Range; to : Dic_Range; end record; -- seg : array (Segment_Range) of Segment; small : array (Dic_Range) of Boolean; seen : array (Dic_Range) of Natural; -- procedure Read_Data is procedure Check (word : VString; pos : out Dic_Range) is begin for i in 1 .. top loop if dic (i) = word then pos := i; return; end if; end loop; -- Word not yet in dictionary. top := top + 1; dic (top) := word; small (top) := True; seen (top) := 0; for i in 1 .. Length (word) loop small (top) := small (top) and then Element (word, i) in 'a' .. 'z'; end loop; pos := top; end Check; -- input : constant VString := +"aoc_2021_12.txt"; -- c : Character; word : VString; f : File_Type; begin Check (+"start", start_idx); Check (+"end", end_idx); small (start_idx) := True; seen (start_idx) := 2; -- This prevents visiting again the "start" cave. -- Open (f, input); while not End_Of_File (f) loop segs := segs + 1; word := +""; loop Get (f, c); exit when c = '-'; word := word & c; end loop; Check (word, seg (segs).from); word := +""; loop Get (f, c); word := word & c; exit when End_Of_Line (f); end loop; Check (word, seg (segs).to); end loop; Close (f); end Read_Data; -- -- `Visit` has a side effect on `seen` array. -- function Visit (cave : Dic_Range; joker : Boolean) return Natural is result : Natural; -- Number of paths from this cave reaching the end. procedure Test (to : Dic_Range) is begin if small (to) then case seen (to) is when 0 => result := result + Visit (to, joker); when 1 => if joker then -- Continue the visit, but joker is discarded. result := result + Visit (to, False); end if; when others => -- We cannot enter this `to` cave. null; end case; else -- Large cave: no limit! result := result + Visit (to, joker); end if; end Test; begin if cave = end_idx then return 1; end if; seen (cave) := seen (cave) + 1; -- As long as we don't find a way to the end, -- there is no interesting path from that cave: result := 0; for s in 1 .. segs loop -- We can go through a segment many times, -- But small caves have to be visited only once. -- In all the data we've have got (3 examples & input), -- there is no segment between two large caves. -- Such a situation would lead to infinite recursion. if cave = seg (s).from then Test (seg (s).to); elsif cave = seg (s).to then Test (seg (s).from); end if; end loop; seen (cave) := seen (cave) - 1; return result; end Visit; r : array (1 .. 2) of Integer; compiler_test_mode : constant Boolean := Argument_Count >= 1; begin Read_Data; r (1) := Visit (start_idx, False); if not compiler_test_mode then r (2) := Visit (start_idx, True); end if; -- if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1: Number of paths (normal rules): " & r (1)); Put_Line (+"Part 2: Number of paths (special rule): " & r (2)); -- Part 1: validated by AoC: 3497 -- Part 2: validated by AoC: 93686 end if; end AoC_2021_12; ================================================ FILE: exm/aoc/2021/aoc_2021_12.txt ================================================ um-end pk-um FE-il ay-FE pk-start end-jt um-FE RO-il xc-ay il-end start-EZ pk-FE xc-start jt-FE EZ-um pk-xc xc-EZ pk-ay il-ay jt-EZ jt-om pk-EZ ================================================ FILE: exm/aoc/2021/aoc_2021_12_questions.txt ================================================ --- Day 12: Passage Pathing --- With your submarine's subterranean subsystems subsisting suboptimally, the only way you're getting out of this cave anytime soon is by finding a path yourself. Not just a path - the only way to know if you've found the best path is to find all of them. Fortunately, the sensors are still mostly working, and so you build a rough map of the remaining caves (your puzzle input). For example: start-A start-b A-c A-b b-d A-end b-end This is a list of how all of the caves are connected. You start in the cave named start, and your destination is the cave named end. An entry like b-d means that cave b is connected to cave d - that is, you can move between them. So, the above cave system looks roughly like this: start / \ c--A-----b--d \ / end Your goal is to find the number of distinct paths that start at start, end at end, and don't visit small caves more than once. There are two types of caves: big caves (written in uppercase, like A) and small caves (written in lowercase, like b). It would be a waste of time to visit any small cave more than once, but big caves are large enough that it might be worth visiting them multiple times. So, all paths you find should visit small caves at most once, and can visit big caves any number of times. Given these rules, there are 10 paths through this example cave system: start,A,b,A,c,A,end start,A,b,A,end start,A,b,end start,A,c,A,b,A,end start,A,c,A,b,end start,A,c,A,end start,A,end start,b,A,c,A,end start,b,A,end start,b,end (Each line in the above list corresponds to a single path; the caves visited by that path are listed in the order they are visited and separated by commas.) Note that in this cave system, cave d is never visited by any path: to do so, cave b would need to be visited twice (once on the way to cave d and a second time when returning from cave d), and since cave b is small, this is not allowed. Here is a slightly larger example: dc-end HN-start start-kj dc-start dc-HN LN-dc HN-end kj-sa kj-HN kj-dc The 19 paths through it are as follows: start,HN,dc,HN,end start,HN,dc,HN,kj,HN,end start,HN,dc,end start,HN,dc,kj,HN,end start,HN,end start,HN,kj,HN,dc,HN,end start,HN,kj,HN,dc,end start,HN,kj,HN,end start,HN,kj,dc,HN,end start,HN,kj,dc,end start,dc,HN,end start,dc,HN,kj,HN,end start,dc,end start,dc,kj,HN,end start,kj,HN,dc,HN,end start,kj,HN,dc,end start,kj,HN,end start,kj,dc,HN,end start,kj,dc,end Finally, this even larger example has 226 paths through it: fs-end he-DX fs-he start-DX pj-DX end-zg zg-sl zg-pj pj-he RW-he fs-DX pj-RW zg-RW start-pj he-WI zg-he pj-fs start-RW How many paths through this cave system are there that visit small caves at most once? --- Part Two --- After reviewing the available paths, you realize you might have time to visit a single small cave twice. Specifically, big caves can be visited any number of times, a single small cave can be visited at most twice, and the remaining small caves can be visited at most once. However, the caves named start and end can only be visited exactly once each: once you leave the start cave, you may not return to it, and once you reach the end cave, the path must end immediately. Now, the 36 possible paths through the first example above are: start,A,b,A,b,A,c,A,end start,A,b,A,b,A,end start,A,b,A,b,end start,A,b,A,c,A,b,A,end start,A,b,A,c,A,b,end start,A,b,A,c,A,c,A,end start,A,b,A,c,A,end start,A,b,A,end start,A,b,d,b,A,c,A,end start,A,b,d,b,A,end start,A,b,d,b,end start,A,b,end start,A,c,A,b,A,b,A,end start,A,c,A,b,A,b,end start,A,c,A,b,A,c,A,end start,A,c,A,b,A,end start,A,c,A,b,d,b,A,end start,A,c,A,b,d,b,end start,A,c,A,b,end start,A,c,A,c,A,b,A,end start,A,c,A,c,A,b,end start,A,c,A,c,A,end start,A,c,A,end start,A,end start,b,A,b,A,c,A,end start,b,A,b,A,end start,b,A,b,end start,b,A,c,A,b,A,end start,b,A,c,A,b,end start,b,A,c,A,c,A,end start,b,A,c,A,end start,b,A,end start,b,d,b,A,c,A,end start,b,d,b,A,end start,b,d,b,end start,b,end The slightly larger example above now has 103 paths through it, and the even larger example now has 3509 paths through it. Given these new rules, how many paths through this cave system are there? ================================================ FILE: exm/aoc/2021/aoc_2021_13.adb ================================================ -- Solution to Advent of Code 2021, Day 13 ------------------------------------------- -- Transparent Origami -- -- https://adventofcode.com/2021/day/13 -- Copy of questions in: aoc_2021_13_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_13 is use HAT; -- input : constant VString := +"aoc_2021_13.txt"; -- x_max : constant := 2000; y_max : constant := 1000; subtype X_Range is Integer range 0 .. x_max; subtype Y_Range is Integer range 0 .. y_max; x_last : X_Range := 0; y_last : Y_Range := 0; map : array (X_Range, Y_Range) of Boolean; -- function Count return Natural is total : Natural := 0; begin for x in 0 .. x_last loop for y in 0 .. y_last loop if map (x, y) then total := total + 1; end if; end loop; end loop; return total; end Count; -- procedure Show is begin for y in 0 .. y_last loop for x in 0 .. x_last loop if map (x, y) then Put ('#'); else Put (' '); end if; end loop; New_Line; end loop; end Show; -- f_max : constant := 20; subtype Fold_Range is Integer range 1 .. f_max; f_last : Natural := 0; type Fold_Instruction_Type is record x_axis : Boolean; line : Natural; end record; fold_instruction : array (Fold_Range) of Fold_Instruction_Type; -- procedure Read_Data is f : File_Type; c, sep : Character; xd : X_Range; yd : Y_Range; skip : String (1 .. 11) := "fold along "; begin for x in X_Range loop for y in Y_Range loop map (x, y) := False; end loop; end loop; Open (f, input); loop Get (f, xd); Get (f, sep); Get (f, yd); map (xd, yd) := True; x_last := Max (x_last, xd); y_last := Max (y_last, yd); if End_Of_Line (f) then Skip_Line (f); end if; exit when End_Of_Line (f); end loop; -- Folding instructions while not End_Of_File (f) loop f_last := f_last + 1; Get (f, skip); Get (f, c); fold_instruction (f_last).x_axis := c = 'x'; Get (f, sep); Get (f, fold_instruction (f_last).line); end loop; Close (f); end Read_Data; -- procedure Fold (f : Fold_Range) is xf, xe : X_Range; yf, ye : Y_Range; begin if fold_instruction (f).x_axis then xf := fold_instruction (f).line; xe := xf * 2; for x in 0 .. xf - 1 loop for y in 0 .. y_last loop map (x, y) := map (x, y) or map (xe - x, y); end loop; end loop; x_last := xf - 1; else yf := fold_instruction (f).line; ye := yf * 2; for x in 0 .. x_last loop for y in 0 .. yf - 1 loop map (x, y) := map (x, y) or map (x, ye - y); end loop; end loop; y_last := yf - 1; end if; end Fold; -- r : Integer; compiler_test_mode : constant Boolean := Argument_Count >= 1; begin Read_Data; for f in 1 .. f_last loop Fold (f); if f = 1 then r := Count; exit when compiler_test_mode; end if; end loop; if compiler_test_mode then if r /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1: Number of dots after 1st fold: " & r); Put_Line (+"Part 2: Height-letter code:"); Show; -- Part 1: validated by AoC: 602 -- Part 2: validated by AoC: CAFJHZCK end if; end AoC_2021_13; ================================================ FILE: exm/aoc/2021/aoc_2021_13.txt ================================================ 1284,359 47,25 699,764 55,204 552,247 731,877 765,12 619,806 437,864 1202,152 105,456 159,165 648,563 701,143 609,861 972,414 1195,379 1097,439 358,95 1126,288 773,332 863,813 1250,63 1280,95 1237,672 224,343 1222,488 748,842 554,208 1086,215 1136,479 1308,826 371,367 972,722 766,719 80,366 920,22 765,882 1208,354 994,526 512,430 1007,507 773,695 909,672 370,231 38,812 766,495 1078,534 633,408 233,770 251,429 874,315 649,666 1140,868 1138,75 808,441 864,150 1066,814 440,674 477,238 1290,739 786,434 263,42 306,891 1086,652 248,621 515,387 378,730 1255,189 769,187 70,473 408,773 1039,581 373,312 537,562 1078,360 1036,775 925,565 1022,530 132,207 1027,815 869,7 631,281 725,404 945,305 1173,509 678,338 788,207 447,753 166,740 745,199 49,383 1151,729 1255,705 351,507 648,331 1,208 728,299 174,479 224,215 179,372 497,541 445,84 952,95 1136,422 1253,341 251,877 269,150 227,154 597,341 72,343 657,656 900,473 117,562 990,474 1096,326 524,147 1228,473 990,420 360,434 493,47 582,299 843,266 1220,850 370,103 176,26 1192,430 890,252 1235,809 1220,318 666,332 711,481 1083,154 825,2 365,305 566,854 1278,658 213,887 26,7 766,399 448,47 892,549 349,38 605,168 303,42 592,114 433,219 7,560 10,526 227,614 186,836 323,109 32,658 1061,802 544,271 289,589 227,280 713,553 997,574 577,221 502,696 497,801 431,486 42,250 68,866 1290,372 736,773 676,3 1208,663 1004,891 202,775 1116,655 1057,670 840,16 160,320 172,371 480,32 666,441 83,880 100,816 813,821 1265,868 976,420 372,822 1284,7 110,495 348,451 1210,526 467,852 170,474 788,339 390,872 119,703 940,663 577,764 316,646 1,460 1027,79 137,509 565,247 838,395 321,93 763,712 268,332 355,42 217,590 410,473 213,439 433,456 733,221 1099,739 1211,602 221,438 371,92 579,205 207,529 487,813 1124,58 1097,455 213,7 1099,67 1149,847 208,744 633,486 1156,813 239,735 174,78 370,663 438,348 599,690 1061,92 987,337 333,93 1126,291 239,541 1029,760 1283,637 78,273 318,186 441,103 1036,119 1074,793 867,827 75,17 415,541 488,154 644,441 64,91 554,816 976,474 676,43 239,353 271,133 92,842 544,719 1097,887 157,801 1309,131 900,421 731,689 597,822 388,175 599,637 385,296 987,785 57,374 1158,889 167,365 731,205 316,722 830,530 239,159 905,92 663,726 927,581 530,483 107,522 455,889 1267,316 502,866 45,26 842,58 833,238 70,638 803,36 211,515 562,52 20,851 480,332 1148,64 679,281 1248,200 666,562 385,744 1093,864 1260,164 888,364 547,74 373,582 480,479 551,486 1021,589 120,476 467,266 1061,753 1298,644 728,103 544,658 561,44 1149,47 1233,316 1195,827 443,155 124,35 88,488 1203,182 1248,305 266,787 249,589 110,770 1019,341 565,199 863,753 1267,255 549,438 612,616 552,551 1208,231 577,130 883,733 43,578 274,551 766,623 584,642 1078,812 410,80 658,68 627,369 216,236 775,540 850,239 366,530 720,803 1252,338 869,551 830,332 1237,448 274,882 110,627 60,130 698,26 758,23 213,791 92,52 808,812 445,114 50,400 758,540 62,200 1066,473 683,628 1097,103 448,418 1247,68 770,789 816,154 1089,456 817,47 502,562 927,294 1267,764 1275,33 338,172 541,187 383,600 539,155 30,799 749,850 981,847 1077,770 808,5 609,420 354,175 383,742 950,434 535,703 1036,12 415,353 264,332 594,588 184,288 415,735 1086,231 1241,490 961,38 974,156 758,354 591,826 1222,406 574,366 502,620 1211,733 927,742 38,530 864,430 644,696 564,402 577,578 415,93 612,644 955,852 1044,130 864,296 1248,835 763,522 1248,694 1124,836 410,814 622,882 662,563 119,191 769,775 90,318 895,541 579,877 822,154 686,351 349,856 473,133 390,22 90,850 418,148 666,696 1136,368 701,644 510,843 1099,379 733,764 825,450 427,733 730,376 883,280 877,456 867,67 217,752 830,252 146,147 1034,46 714,338 619,444 771,620 724,866 403,429 57,822 27,369 1039,152 1129,133 1195,739 959,507 207,753 764,294 564,598 837,740 1257,304 661,271 1208,652 160,574 1083,609 1029,565 274,119 609,644 443,827 1011,42 211,739 580,518 895,801 401,672 815,165 502,396 624,351 445,536 842,338 766,658 1123,266 401,670 113,119 1036,460 85,589 661,623 60,175 249,802 1097,791 45,537 224,802 89,647 236,793 726,256 211,67 80,528 1283,705 537,332 338,816 385,150 221,456 227,609 400,299 248,173 502,498 649,623 1303,560 592,332 316,248 1086,92 117,114 622,658 136,63 748,52 907,465 1230,773 579,689 274,460 107,182 1077,124 1237,446 355,852 174,422 691,603 1283,369 653,656 109,640 433,675 873,30 1225,589 698,616 522,207 540,789 488,546 1186,343 102,231 169,373 354,719 907,429 217,864 249,354 713,822 1059,429 1293,56 488,98 1208,204 60,63 637,56 448,847 1236,152 1161,880 1267,130 545,12 584,252 1191,533 919,516 268,338 410,30 274,12 418,549 634,43 1044,175 544,399 383,294 1193,88 212,553 527,677 224,679 937,312 1066,25 427,280 1300,780 895,735 254,595 706,282 441,392 813,73 700,72 415,159 1171,628 644,889 900,80 209,114 837,133 537,695 716,271 822,740 1143,365 599,413 115,379 1158,476 769,119 373,196 60,287 1022,364 877,219 1265,250 1,763 910,595 937,751 35,33 1066,421 26,359 825,521 1033,231 880,802 49,831 830,642 75,809 80,773 1178,351 142,464 1300,114 2,68 70,256 354,215 813,801 867,739 266,287 480,562 371,815 1241,852 539,620 524,434 1111,5 85,305 174,32 800,395 1046,562 1134,418 1136,78 93,850 107,372 416,152 925,329 194,787 1250,130 705,511 657,238 1225,876 274,775 1129,761 574,773 1242,28 937,143 32,236 758,551 564,850 174,368 1220,150 1101,114 843,8 594,306 545,814 118,38 160,740 1241,42 378,220 994,646 698,278 73,446 552,343 925,296 174,498 1089,438 855,668 609,117 544,627 1265,26 1099,515 100,368 611,130 23,556 1056,708 1250,831 570,497 544,684 682,887 1027,527 43,130 731,533 1200,627 248,684 62,305 740,497 1092,315 1240,638 1086,343 701,582 989,93 830,396 124,411 186,338 1071,353 1158,722 284,663 758,343 152,190 7,334 266,607 706,494 691,88 1261,63 766,175 610,72 373,329 1263,25 174,480 666,364 446,744 1211,161 581,222 790,600 93,178 1141,373 120,215 93,322 597,789 744,854 1010,311 761,149 1019,441 224,231 900,30 472,499 706,730 480,172 688,658 371,540 174,396 825,444 830,172 fold along x=655 fold along y=447 fold along x=327 fold along y=223 fold along x=163 fold along y=111 fold along x=81 fold along y=55 fold along x=40 fold along y=27 fold along y=13 fold along y=6 ================================================ FILE: exm/aoc/2021/aoc_2021_13_questions.txt ================================================ --- Day 13: Transparent Origami --- You reach another volcanically active part of the cave. It would be nice if you could do some kind of thermal imaging so you could tell ahead of time which caves are too hot to safely enter. Fortunately, the submarine seems to be equipped with a thermal camera! When you activate it, you are greeted with: Congratulations on your purchase! To activate this infrared thermal imaging camera system, please enter the code found on page 1 of the manual. Apparently, the Elves have never used this feature. To your surprise, you manage to find the manual; as you go to open it, page 1 falls out. It's a large sheet of transparent paper! The transparent paper is marked with random dots and includes instructions on how to fold it up (your puzzle input). For example: 6,10 0,14 9,10 0,3 10,4 4,11 6,0 6,12 4,1 0,13 10,12 3,4 3,0 8,4 1,10 2,14 8,10 9,0 fold along y=7 fold along x=5 The first section is a list of dots on the transparent paper. 0,0 represents the top-left coordinate. The first value, x, increases to the right. The second value, y, increases downward. So, the coordinate 3,0 is to the right of 0,0, and the coordinate 0,7 is below 0,0. The coordinates in this example form the following pattern, where # is a dot on the paper and . is an empty, unmarked position: ...#..#..#. ....#...... ........... #.......... ...#....#.# ........... ........... ........... ........... ........... .#....#.##. ....#...... ......#...# #.......... #.#........ Then, there is a list of fold instructions. Each instruction indicates a line on the transparent paper and wants you to fold the paper up (for horizontal y=... lines) or left (for vertical x=... lines). In this example, the first fold instruction is fold along y=7, which designates the line formed by all of the positions where y is 7 (marked here with -): ...#..#..#. ....#...... ........... #.......... ...#....#.# ........... ........... ----------- ........... ........... .#....#.##. ....#...... ......#...# #.......... #.#........ Because this is a horizontal line, fold the bottom half up. Some of the dots might end up overlapping after the fold is complete, but dots will never appear exactly on a fold line. The result of doing this fold looks like this: #.##..#..#. #...#...... ......#...# #...#...... .#.#..#.### ........... ........... Now, only 17 dots are visible. Notice, for example, the two dots in the bottom left corner before the transparent paper is folded; after the fold is complete, those dots appear in the top left corner (at 0,0 and 0,1). Because the paper is transparent, the dot just below them in the result (at 0,3) remains visible, as it can be seen through the transparent paper. Also notice that some dots can end up overlapping; in this case, the dots merge together and become a single dot. The second fold instruction is fold along x=5, which indicates this line: #.##.|#..#. #...#|..... .....|#...# #...#|..... .#.#.|#.### .....|..... .....|..... Because this is a vertical line, fold left: ##### #...# #...# #...# ##### ..... ..... The instructions made a square! The transparent paper is pretty big, so for now, focus on just completing the first fold. After the first fold in the example above, 17 dots are visible - dots that end up overlapping after the fold is completed count as a single dot. How many dots are visible after completing just the first fold instruction on your transparent paper? ================================================ FILE: exm/aoc/2021/aoc_2021_14.adb ================================================ -- Solution to Advent of Code 2021, Day 14 ------------------------------------------- -- Extended Polymerization -- -- https://adventofcode.com/2021/day/14 -- Copy of questions in: aoc_2021_14_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2021_14 is use HAT, Interfaces; -- rule_max : constant := 200; subtype Rule_Range is Integer range 1 .. rule_max; -- subtype Alpha is Character range 'A' .. 'Z'; subtype Pair is String (1 .. 2); -- Ideally: `array (1 .. 2) of Alpha` when HAC supports array comparisons. -- type Rule_Type is record from : Pair; to : Alpha; child_1 : Rule_Range; child_2 : Rule_Range; end record; -- rule : array (Rule_Range) of Rule_Type; rules : Natural := 0; -- initial_polymer : VString; type Pair_Population is array (Rule_Range) of Integer_64; zero : Pair_Population; gen_pop : array (1 .. 2) of Pair_Population; -- procedure Read_Data is sep : String (1 .. 4); f : File_Type; input : constant VString := +"aoc_2021_14.txt"; begin Open (f, input); Get_Line (f, initial_polymer); -- Original sequence Skip_Line (f); while not End_Of_File (f) loop rules := rules + 1; Get (f, rule (rules).from (1)); Get (f, rule (rules).from (2)); Get (f, sep); Get (f, rule (rules).to); end loop; Close (f); -- Initial population as pairs for i in Rule_Range loop zero (i) := 0; end loop; gen_pop (1) := zero; for i in 1 .. rules loop for j in 1 .. Length (initial_polymer) - 1 loop if +rule (i).from = Slice (initial_polymer, j, j + 1) then gen_pop (1)(i) := gen_pop (1)(i) + 1; end if; end loop; end loop; end Read_Data; -- procedure Prepare_Computation is child_1, child_2 : Pair; begin -- Prepare shortcuts pair -> new pairs. for i in 1 .. rules loop child_1 (1) := rule (i).from (1); child_1 (2) := rule (i).to; child_2 (1) := rule (i).to; child_2 (2) := rule (i).from (2); for j in 1 .. rules loop if +rule (j).from = +child_1 then rule (i).child_1 := j; end if; if +rule (j).from = +child_2 then rule (i).child_2 := j; end if; end loop; end loop; end Prepare_Computation; -- gen : Positive := 1; -- procedure Evolve is parents : Integer_64; new_gen : constant Positive := 3 - gen; child_1_idx, child_2_idx : Positive; procedure Increase (pop : in out Integer_64) is begin pop := pop + parents; end Increase; begin gen_pop (new_gen) := zero; for i in 1 .. rules loop parents := gen_pop (gen) (i); child_1_idx := rule (i).child_1; child_2_idx := rule (i).child_2; Increase (gen_pop (new_gen) (child_1_idx)); Increase (gen_pop (new_gen) (child_2_idx)); end loop; gen := new_gen; end Evolve; -- r : array (1 .. 2) of Integer_64; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := not compiler_test_mode; -- res : Integer_64; -- procedure Atom_Counts is stat : array (Alpha) of Integer_64; total : Integer_64 := 0; aa : Alpha; stat_most_common_element : Integer_64 := Integer_64'First; -- "- infinity" stat_least_common_element : Integer_64 := Integer_64'Last; -- "+ infinity" begin for a in Alpha loop stat (a) := 0; end loop; for r in 1 .. rules loop aa := rule (r).from (1); stat (aa) := stat (aa) + gen_pop (gen)(r); aa := rule (r).from (2); stat (aa) := stat (aa) + gen_pop (gen)(r); end loop; -- Ghost pair at the beginning of the polymer: aa := Element (initial_polymer, 1); stat (aa) := stat (aa) + 1; -- Ghost pair at the end of the polymer: aa := Element (initial_polymer, Length (initial_polymer)); stat (aa) := stat (aa) + 1; -- Now all stats for all atomic symbols are exactly double counted. for a in Alpha loop stat (a) := stat (a) / 2; total := total + stat (a); if stat (a) > 0 and then verbose then Put_Line (+" " & a & ":" & Integer_64'Image (stat (a))); end if; end loop; if verbose then Put_Line (+" Total:" & Integer_64'Image (total)); end if; for a in Alpha loop if stat (a) > 0 then if stat (a) < stat_least_common_element then stat_least_common_element := stat (a); end if; if stat (a) > stat_most_common_element then stat_most_common_element := stat (a); end if; end if; end loop; res := stat_most_common_element - stat_least_common_element; -- end Atom_Counts; -- begin Read_Data; Prepare_Computation; if verbose then Put_Line (+"Initial: "); end if; Atom_Counts; for gen_count in 1 .. 40 loop Evolve; if verbose then Put_Line (+"Generation " & gen_count & ':'); end if; Atom_Counts; if gen_count = 10 then r (1) := res; end if; end loop; r (2) := res; -- if compiler_test_mode then if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Part 1: count after 10 generations:" & Integer_64'Image (r (1))); Put_Line (+"Part 2: count after 40 generations:" & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 2345 -- Part 2: validated by AoC: 2432786807053 end if; end AoC_2021_14; ================================================ FILE: exm/aoc/2021/aoc_2021_14.txt ================================================ BNSOSBBKPCSCPKPOPNNK HH -> N CO -> F BC -> O HN -> V SV -> S FS -> F CV -> F KN -> F OP -> H VN -> P PF -> P HP -> H FK -> K BS -> F FP -> H FN -> V VV -> O PS -> S SK -> N FF -> K PK -> V OF -> N VP -> K KB -> H OV -> B CH -> F SF -> F NH -> O NC -> N SP -> N NN -> F OK -> S BB -> S NK -> S FH -> P FC -> S OB -> P VS -> P BF -> S HC -> V CK -> O NP -> K KV -> S OS -> V CF -> V FB -> C HO -> S BV -> V KS -> C HB -> S SO -> N PH -> C PN -> F OC -> F KO -> F VF -> V CS -> O VK -> O FV -> N OO -> K NS -> S KK -> C FO -> S PV -> S CN -> O VC -> P SS -> C PO -> P BN -> N PB -> N PC -> H SH -> K BH -> F HK -> O VB -> P NV -> O NB -> C CP -> H NO -> K PP -> N CC -> S CB -> K VH -> H SC -> C KC -> N SB -> B BP -> P KP -> K SN -> H KF -> K KH -> B HV -> V HS -> K NF -> B ON -> H BO -> P VO -> K OH -> C HF -> O BK -> H ================================================ FILE: exm/aoc/2021/aoc_2021_14_questions.txt ================================================ --- Day 14: Extended Polymerization --- The incredible pressures at this depth are starting to put a strain on your submarine. The submarine has polymerization equipment that would produce suitable materials to reinforce the submarine, and the nearby volcanically-active caves should even have the necessary input elements in sufficient quantities. The submarine manual contains instructions for finding the optimal polymer formula; specifically, it offers a polymer template and a list of pair insertion rules (your puzzle input). You just need to work out what polymer would result after repeating the pair insertion process a few times. For example: NNCB CH -> B HH -> N CB -> H NH -> C HB -> C HC -> B HN -> C NN -> C BH -> H NC -> B NB -> B BN -> B BB -> N BC -> B CC -> N CN -> C The first line is the polymer template - this is the starting point of the process. The following section defines the pair insertion rules. A rule like AB -> C means that when elements A and B are immediately adjacent, element C should be inserted between them. These insertions all happen simultaneously. So, starting with the polymer template NNCB, the first step simultaneously considers all three pairs: The first pair (NN) matches the rule NN -> C, so element C is inserted between the first N and the second N. The second pair (NC) matches the rule NC -> B, so element B is inserted between the N and the C. The third pair (CB) matches the rule CB -> H, so element H is inserted between the C and the B. Note that these pairs overlap: the second element of one pair is the first element of the next pair. Also, because all pairs are considered simultaneously, inserted elements are not considered to be part of a pair until the next step. After the first step of this process, the polymer becomes NCNBCHB. Here are the results of a few steps using the above rules: Template: NNCB After step 1: NCNBCHB After step 2: NBCCNBBBCBHCB After step 3: NBBBCNCCNBBNBNBBCHBHHBCHB After step 4: NBBNBNBBCCNBCNCCNBBNBBNBBBNBBNBBCBHCBHHNHCBBCBHCB This polymer grows quickly. After step 5, it has length 97; After step 10, it has length 3073. After step 10, B occurs 1749 times, C occurs 298 times, H occurs 191 times, and N occurs 865 times; taking the quantity of the most common element (B, 1749) and subtracting the quantity of the least common element (H, 161) produces 1749 - 161 = 1588. Apply 10 steps of pair insertion to the polymer template and find the most and least common elements in the result. What do you get if you take the quantity of the most common element and subtract the quantity of the least common element? --- Part Two --- The resulting polymer isn't nearly strong enough to reinforce the submarine. You'll need to run more steps of the pair insertion process; a total of 40 steps should do it. In the above example, the most common element is B (occurring 2192039569602 times) and the least common element is H (occurring 3849876073 times); subtracting these produces 2188189693529. Apply 40 steps of pair insertion to the polymer template and find the most and least common elements in the result. What do you get if you take the quantity of the most common element and subtract the quantity of the least common element? ================================================ FILE: exm/aoc/2021/aoc_2021_15.adb ================================================ -- Solution to Advent of Code 2021, Day 15 ------------------------------------------- -- Chiton -- -- https://adventofcode.com/2021/day/15 -- Copy of questions in: aoc_2021_15_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_15 is use HAT; sx_max : constant := 500; sy_max : constant := 500; map : array (1 .. sx_max, 1 .. sy_max) of Natural; -- Cumulative minimal risk from starting point to (x, y) c_risk : array (1 .. sx_max, 1 .. sy_max) of Natural; risk_max : constant Integer := Integer'Last; sx, sy : Natural; input : constant VString := +"aoc_2021_15.txt"; -- procedure Read_Data is c : Character; f : File_Type; x, y : Natural := 0; begin Open (f, input); while not End_Of_File (f) loop y := y + 1; x := 0; Get (f, c); loop x := x + 1; map (x, y) := Ord (c) - Ord ('0'); c_risk (x, y) := risk_max; exit when End_Of_Line (f); Get (f, c); end loop; end loop; sx := x; sy := y; Close (f); end Read_Data; -- r : array (1 .. 2) of Integer; -- -- `Visit` explores adjacent cells (recursive algorithm). -- Side effect: it writes into `risk`. -- procedure Visit (x, y, risk_from : Integer) is risk_to : Integer; begin if x in 1 .. sx and then y in 1 .. sy then risk_to := risk_from + map (x, y); if risk_to < c_risk (x, y) then -- Ah-ha, we have found a better way, or perhaps -- the first way, to (x, y). c_risk (x, y) := risk_to; -- Since we have a reduced risk (x, y), it's worth -- continuing the exploration. Visit (x - 1, y, risk_to); Visit (x + 1, y, risk_to); Visit (x, y - 1, risk_to); Visit (x, y + 1, risk_to); end if; end if; end Visit; -- -- Now enters Dijkstra. -- How many ready-made sorting containers are currently -- available to HAC ? None! I.e., do it yourself! -- procedure Dijkstra (start_x, start_y : Integer) is list_length_max : constant := 250_000; -- sx_max * sy_max; type Node is record c_risk : Natural; x, y : Positive; end record; list : array (1 .. list_length_max) of Node; current, explored : Natural := 0; -- 0 <= current <= explored -- -- Similar to the `Visit` above, but not recursive. -- procedure Visit (x, y, risk_from : Integer) is risk_to, ins : Integer; begin if x in 1 .. sx and then y in 1 .. sy then risk_to := risk_from + map (x, y); if risk_to < c_risk (x, y) then -- Improvement on cell (x, y). -- This happens only once per (x, y) point in this problem - see below. c_risk (x, y) := risk_to; -- -- Insert in a sorted way (slooow on HAC for Part 2). -- ins := explored + 1; for i in current + 1 .. explored loop if risk_to < list (i).c_risk then ins := i; -- Insert here. -- NB: we might want to remove another node with the same (x, y) and a -- larger risk, but that case never happens in this specific problem! -- Reason: the cost for reaching (x, y) is the same from every -- side (= map (x, y)), and we reach it from (cur_x, cur_y) which has -- the minimum score or (x, y)'s neighbours. exit; end if; end loop; for i in reverse ins .. explored loop list (i + 1) := list (i); end loop; list (ins).c_risk := risk_to; list (ins).x := x; list (ins).y := y; explored := explored + 1; end if; end if; end Visit; -- cur_x, cur_y : Positive; risk_cur : Natural; begin c_risk (start_x, start_y) := 0; cur_x := start_x; cur_y := start_y; loop risk_cur := c_risk (cur_x, cur_y); Visit (cur_x - 1, cur_y, risk_cur); Visit (cur_x + 1, cur_y, risk_cur); Visit (cur_x, cur_y - 1, risk_cur); Visit (cur_x, cur_y + 1, risk_cur); -- -- Switch to the next best explored point. -- current := current + 1; cur_x := list (current).x; cur_y := list (current).y; exit when cur_x = sx and then cur_y = sy; end loop; end Dijkstra; -- procedure Enlarge_Map is xn, yn : Integer; begin for tile_x in 0 .. 4 loop for tile_y in 0 .. 4 loop for x in 1 .. sx loop xn := x + sx * tile_x; for y in 1 .. sy loop yn := y + sy * tile_y; map (xn, yn) := 1 + (map (x, y) - 1 + tile_x + tile_y) mod 9; c_risk (xn, yn) := risk_max; end loop; end loop; end loop; end loop; sx := sx * 5; sy := sy * 5; end Enlarge_Map; -- compiler_test_mode : constant Boolean := Argument_Count >= 1; fast : constant Boolean := True; T0 : constant Time := Clock; begin Read_Data; for part in 1 .. 2 loop if part = 2 then Enlarge_Map; end if; if fast then Dijkstra (1, 1); else Visit (1, 1, -map (1, 1)); end if; r (part) := c_risk (sx, sy); exit when compiler_test_mode; -- ^ We do only part 1 when in test mode. -- Parts 1 & 2 take 96 seconds on an i7 9700 with HAC, -- and only 0.047 seconds with GNAT. end loop; -- if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: total risk on small map: " & r (1)); Put_Line (+"Part 2: total risk on large map: " & r (2)); -- Part 1: validated by AoC: 656 -- Part 2: validated by AoC: 2979 end if; end AoC_2021_15; ================================================ FILE: exm/aoc/2021/aoc_2021_15.txt ================================================ 3885193879879881648295721863446819761149766587914443899626972913439119995971841919742454431896714994 7771129199159639477916156846991956691722436614294489569877288313857938998569854848811311873297851994 5397898789999499191819517198785943798491221139523487792596493985724999919868993675269878171629998699 8959899713991722957643961289419687998443291919429187159951653349827977821257719997961312718268193198 2846219932569842879891692234614311812799724893633989588399819579153814261516987262948716511752796311 6725199579118269699472336812618911979957922329399797959986179939314145983243295469598939327129574198 6818219696128568181789718885928896191549477191193599939262477914196391139665811994294494912838651859 2221716296945891267779128161299579949218877525184884798227965899389488291774899969293987797832516878 9213844231433499999179428692791378242173289513286965996976983442779617964787586326697988447265876996 6313993561615886999167182992899141648998552369794394923931327323397566885891787478878722831777571486 8713991289549818763589939991895849521891966988198382597778921227699759737659939699671923799995284356 9591399317958271818963894572368319763963548141193644118635854987471693848981917779146394281461959595 9371563863819447298489391362565198489677387981171916875818269275785921792592869889719184537255926941 9759413213254611555382917156331878594951999289273329999795947169439981616213999777916131384672945781 3679696586894978847711411569255844845182781854737976795191261169589939159794718699997493872499236216 8494291884994125877784376799158842599959994569992371213981397915549319462895179958195199263973799942 2735796245119192168162841995749994338197856789958799128998179176929129769798961229228259986315798618 3919549626995852791812998455881197733986917951189161796996622918479591289192199822989316196969797761 9221811969262729999666392749549395194914927623938931277683992712289972984156294168596935911994723579 9259839967959351183699987369122784879628595673587616317281991469967675676149919714698676133489158258 1871658432298942253177598476366881898185855558899669482116863111799951999125874191992364757787788358 8739852825782614519891679845942972188264816197178738927924889282235769279955911364987337173691463948 8299121513497179625559826719786159935487869889948649939416556967585528149132799993281891864295925273 9667999482981521598853938199191994937627975958963142955995573785779998768777953536129524791999139921 8565711677873119991423986336939891313758995995761498979518974799162693272998776826559842372285298158 6822737359889336999591591889475198863399198181192341869964891549839939496253238918989492776598168948 1932768376317118329349221931269281281579761312419134999386689181799263851995829415737796344479779161 1146699126764988361859799888677969955699566981916991732711866985948137842221879714999415127978969556 2716826999776621568995483149915971956954949792131367142893274976282898295419519294961429727779179618 9819689511469361769815986275122539755735877514917521784678889599769389571241738999916766875682319681 1739898836468191968269759173841389779923491989982797492258199917378161399777715818949121291398318935 8991681277139272161888388992817669861998471779697922729191795771917917339123894529985942176275989194 8788879213844991256944695116539936618798879147682219917761678773156192616821535733828489999993567517 9792112419978643891198386999273939716785777389699733728699741312154995954284998916346921276226192923 8936179399498567787146928338481217274594929625685299262145795358129817176299499988115561439969169721 3711996665399999667439695218315649989919198455461991968853148989594896318519998541221179229418248199 1291656132987641899759511819979169622814748741595934916983531975799629118915179362474688489529695892 8714922154618318979688217298952681635899934279199225395668557918594721827676544381719997629385251241 9593279399413929493478294797355334766829491318569163644378429481549576659858687835137187849471951446 5854979532981199699169869431926898918194919286675941191958919822798687999927843765176497122196781784 9997819331993888314786377865356591696892611198299964968995887152722272842273694726639232942699932183 1896184172814918918624961195543395551748983681949128898432976291935921971198195382973914172929297364 5837941661987651896287486979997298931652327946749692822583754186238849886262949839188999896727858939 4461864711682831868916812799119298619958698189619694951249686988389189729672287957439646596874979222 9992395918711165753212128992797846899956889991997831181969254119177984939821658789949262131839363344 9913929894915753891516982919449993561972671531999989189396939298993831699699189992855785911896267529 5977191539399768769691985346853389983329338128811976829923188998957757698766999482989529913351836217 5869199599389289736799521175141562189996727899189998168814918991864194179395421179268799759179886971 4995393573286591999148456775893729271716999944792426197991892963522993979581797912398388197438929879 8175985762297792193449825891451669173639831696686977185968298848778111519969913991892852196913658589 7551823929217592981312974557685142328463465848839872122469199897971199199199999869473895171251997563 1487931558946968829951763519656937487546792895476992624978852921947139983499286385266138258935193694 8195371149998678396987884326188152573756198921899135197653384711783648729791328851979354497969392986 9179155119423919779667686698689126113994825739951498172517199198989915292457344126929486295984699195 8692999656696952931996533623896191984859965893774589592193836681957292599821971991739911926636959666 9985998695572727293692296815985734817249613192327999997928979519414463322843958491689891537727548424 6785915139891383111991993528714959958913992938996589981164194172299991578319949554372972869927718986 6812969848431999313262899194267519731924982239497181155761348191171378191195481196281927177836119913 9241449944689196375316993727965949184951599169899984428189812459955788198778389997529996294911755145 8263933869291918953191161435562974124985817581189466197959111943314796298198689894947297889469378986 4993564891474912898412755199548395176295488917317973937991914952763769731425198161936449638498547989 3919725846368347989866832637399995924176992897196895631935386266839399384868371191995999792294157491 6721931979356517372592778489839423879114997193842669196756218474195487978729966911652681225999411831 9597499799876611196188943929378999389985498674958963168888777783921914243997878195898999269889294551 7897535911127197896722972984867282697846153651471124481587828169258769897847822878831383595997369791 5831297848191951191794896484123496673799414573379198153884568889918681971924789669965852999915958216 7823991369999344428821749717198796788139384181691959399667159925814883764695397857939481345499559511 9836733614869491139178987881497398239923811838118399887762713912361489159279391783489832826615994916 5877773698989894889438919996977776999993296984984712292923899479697593879272739579864981289939932771 2542185648228941381995651795998445875943469118314769118387799816194799838958843997735743139876711369 7882123912881669791399598994599691151814649879989998698859687888628677316516841799215998992997293761 7767319886981189839889892188919899791985112499817113117779879369341826441898281556786828873779689187 6517976954449996987552989793838655741268494369149928959518173199587537996199483924421127337969771577 1678653257398811536189799659999587998996928746191167927896289997861386532556616499279932951899917642 9572579385451723885561779217789536117629994941561764419872276282572795264367221933191167982181957692 6315852299992498418936196529371999229568595139535889371219877199885619437539359128266112177998914116 2985881397958192379949795596996995193595668153648864957619593653435123842865151846253963551826892972 9181619666251279936984265494857188682368994967895269896197989182176863694399432137388934122967614868 9593114153726456769958948828218389342288723549641819941784998231817667699584449492849222498974496136 9916299479892917793359999793199917957999777682139987212993989599198969329559479959128381894449114895 4921471293815869819213937928199292981798364834953986973773897966731399149773957385692948461798953879 7939219727388581199654888522599499194589989324361564926162951286688874312293589785941177395118942618 8437633823193749987229493992993524679593478997117499862387295887499449937233698762911944962872393932 1957595152944134991298986921999686429196188856825582891848975799829298278988951176691983617917489212 8139893189759536719371198967498834639886725963146991186976281274983731942436781991256754884914659449 4822925997999862149916429996168888845197975949578265942598274998974448539673169651999879289189841361 5241531889998799394875217768389396418913985512418883112994376949161819917922624829789318615483896826 6952433478181299923958981383758182467119587745189738489917881951247839114135919899874698935397678939 9998178281168138219688629715164393989381385362839223828189989111183769799437851885123913879668776872 3479299968682178666263899849126199949521388659643946294899888287792876178914598796793938289488163984 1225626697911721927373893967969993763233461954269119238318594463694999168939951368891298529984588448 7889492445296989153714423965492969819915271485178757588997394798779977871918771629125225796727359893 5778897199718433999153132896886712358389157788434824924928192158771497689159318619912199459651238768 1795836197799479917189998598989489967373995198279891918988899853122171424496868123951671992389679399 6529853939912918791899868397879535727748279386788285494854993938674449895593868599789269647149499765 1878818925186485199559539319973289118966119867769847635447481798718159348669599911752797688859935711 6236419319741929511583546874658811117988969497296985889278883242999599946847999979139915449889988998 1198678683349613936877939891939118912969187857959968963634732792198997359438989686371429988735182698 1998223474469228586568189895871742229825728879174631691151921998877937199256189155647765161238919158 6432548917454758948968687351996995554975421965763752579179713997554661699137621894836694779175686366 ================================================ FILE: exm/aoc/2021/aoc_2021_15_questions.txt ================================================ --- Day 15: Chiton --- You've almost reached the exit of the cave, but the walls are getting closer together. Your submarine can barely still fit, though; the main problem is that the walls of the cave are covered in chitons, and it would be best not to bump any of them. The cavern is large, but has a very low ceiling, restricting your motion to two dimensions. The shape of the cavern resembles a square; a quick scan of chiton density produces a map of risk level throughout the cave (your puzzle input). For example: 1163751742 1381373672 2136511328 3694931569 7463417111 1319128137 1359912421 3125421639 1293138521 2311944581 You start in the top left position, your destination is the bottom right position, and you cannot move diagonally. The number at each position is its risk level; to determine the total risk of an entire path, add up the risk levels of each position you enter (that is, don't count the risk level of your starting position unless you enter it; leaving it adds no risk to your total). Your goal is to find a path with the lowest total risk. In this example, a path with the lowest total risk is highlighted here: (highlight only on the Web site!) The total risk of this path is 40 (the starting position is never entered, so its risk is not counted). What is the lowest total risk of any path from the top left to the bottom right? --- Part Two --- Now that you know how to find low-risk paths in the cave, you can try to find your way out. The entire cave is actually five times larger in both dimensions than you thought; the area you originally scanned is just one tile in a 5x5 tile area that forms the full map. Your original map tile repeats to the right and downward; each time the tile repeats to the right or downward, all of its risk levels are 1 higher than the tile immediately up or left of it. However, risk levels above 9 wrap back around to 1. So, if your original map had some position with a risk level of 8, then that same position on each of the 25 total tiles would be as follows: 8 9 1 2 3 9 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 Each single digit above corresponds to the example position with a value of 8 on the top-left tile. Because the full map is actually five times larger in both dimensions, that position appears a total of 25 times, once in each duplicated tile, with the values shown above. Here is the full five-times-as-large version of the first example above, with the original map in the top left corner highlighted: /---------| |11637517422274862853338597396444961841755517295286 |13813736722492484783351359589446246169155735727126 |21365113283247622439435873354154698446526571955763 |36949315694715142671582625378269373648937148475914 |74634171118574528222968563933317967414442817852555 |13191281372421239248353234135946434524615754563572 |13599124212461123532357223464346833457545794456865 |31254216394236532741534764385264587549637569865174 |12931385212314249632342535174345364628545647573965 -23119445813422155692453326671356443778246755488935 22748628533385973964449618417555172952866628316397 24924847833513595894462461691557357271266846838237 32476224394358733541546984465265719557637682166874 47151426715826253782693736489371484759148259586125 85745282229685639333179674144428178525553928963666 24212392483532341359464345246157545635726865674683 24611235323572234643468334575457944568656815567976 42365327415347643852645875496375698651748671976285 23142496323425351743453646285456475739656758684176 34221556924533266713564437782467554889357866599146 33859739644496184175551729528666283163977739427418 35135958944624616915573572712668468382377957949348 43587335415469844652657195576376821668748793277985 58262537826937364893714847591482595861259361697236 96856393331796741444281785255539289636664139174777 35323413594643452461575456357268656746837976785794 35722346434683345754579445686568155679767926678187 53476438526458754963756986517486719762859782187396 34253517434536462854564757396567586841767869795287 45332667135644377824675548893578665991468977611257 44961841755517295286662831639777394274188841538529 46246169155735727126684683823779579493488168151459 54698446526571955763768216687487932779859814388196 69373648937148475914825958612593616972361472718347 17967414442817852555392896366641391747775241285888 46434524615754563572686567468379767857948187896815 46833457545794456865681556797679266781878137789298 64587549637569865174867197628597821873961893298417 45364628545647573965675868417678697952878971816398 56443778246755488935786659914689776112579188722368 55172952866628316397773942741888415385299952649631 57357271266846838237795794934881681514599279262561 65719557637682166874879327798598143881961925499217 71484759148259586125936169723614727183472583829458 28178525553928963666413917477752412858886352396999 57545635726865674683797678579481878968159298917926 57944568656815567976792667818781377892989248891319 75698651748671976285978218739618932984172914319528 56475739656758684176786979528789718163989182927419 67554889357866599146897761125791887223681299833479 Equipped with the full map, you can now find a path from the top left corner to the bottom right corner with the lowest total risk: (highlight only on the Web site!) The total risk of this path is 315 (the starting position is still never entered, so its risk is not counted). Using the full map, what is the lowest total risk of any path from the top left to the bottom right? ================================================ FILE: exm/aoc/2021/aoc_2021_16.adb ================================================ -- Solution to Advent of Code 2021, Day 16 ------------------------------------------- -- Packet Decoder -- -- https://adventofcode.com/2021/day/16 -- Copy of questions in: aoc_2021_16_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2021_16 is use HAT, Interfaces; subtype Bit is Integer range 0 .. 1; -- msg_max : constant := 32000; msg : array (1 .. msg_max) of Bit; bits : Natural := 0; -- procedure Read_Data is input : constant VString := +"aoc_2021_16.txt"; f : File_Type; s : VString; digit : Natural; begin -- Examples: -- s := +"D2FE28"; -- Literal: 2021. -- s := +"38006F45291200"; -- Operator with 2 subpackets: 10, 20. -- s := +"EE00D40C823060"; -- Operator with 3 subpackets: 1, 2, 3. -- s := +"8A004A801A8002F478"; -- Sum of versions = 16. -- s := +"A0016C880162017C3686B18A3D4780"; -- Sum of versions = 31. -- s := +"C200B40A82"; -- "1 + 2" -> 3. -- s := +"9C0141080250320F1802104A08"; -- "1 + 3 = 2 * 2" -> 1. -- Open (f, input); Get_Line (f, s); Close (f); -- for i in 1 .. Length (s) loop digit := Integer_Value (+"16#" & Element (s, i) & '#'); for j in reverse 1 .. 4 loop msg (bits + j) := digit mod 2; digit := digit / 2; end loop; bits := bits + 4; end loop; end Read_Data; -- b : Integer_64 := 1; vsum : Integer_64 := 0; -- function Process return Integer_64 is procedure Decode (var : out Integer_64; bits : Positive) is begin var := 0; for i in 1 .. bits loop var := var * 2 + Integer_64 (msg (Integer (b))); b := b + 1; end loop; end Decode; end_mark, length_id, sub_length, sub_num, version, id, lit, res : Integer_64; -- id_sum : constant := 0; id_product : constant := 1; id_minimum : constant := 2; id_maximum : constant := 3; id_literal : constant := 4; id_greater : constant := 5; id_less : constant := 6; id_equal : constant := 7; -- procedure Cumulate (first : Boolean) is term : constant Integer_64 := Process; -- Here is the recursion :-) . begin if first then res := term; else case id is when id_sum => res := res + term; when id_product => res := res * term; when id_minimum => if term < res then res := term; end if; when id_maximum => if term > res then res := term; end if; when id_greater => if res > term then res := 1; else res := 0; end if; when id_less => if res < term then res := 1; else res := 0; end if; when id_equal => if res = term then res := 1; else res := 0; end if; when others => null; end case; end if; end Cumulate; b_mem : Integer_64; begin Decode (version, 3); vsum := vsum + version; Decode (id, 3); case id is when id_literal => res := 0; loop Decode (end_mark, 1); Decode (lit, 4); res := res * 16 + lit; exit when end_mark = 0; end loop; when others => Decode (length_id, 1); if length_id = 0 then Decode (sub_length, 15); b_mem := b; loop Cumulate (b = b_mem); exit when b = b_mem + sub_length; end loop; else Decode (sub_num, 11); for i in 1 .. sub_num loop Cumulate (i = 1); end loop; end if; end case; return res; end Process; -- r : array (1 .. 2) of Integer_64; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; r (2) := Process; r (1) := vsum; if compiler_test_mode then if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: sum of version numbers:" & Integer_64'Image (r (1))); Put_Line (+"Part 2: value of expression: " & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 927 -- Part 2: validated by AoC: 1725277876501 end if; end AoC_2021_16; ================================================ FILE: exm/aoc/2021/aoc_2021_16.txt ================================================ A20D6CE8F00033925A95338B6549C0149E3398DE75817200992531E25F005A18C8C8C0001849FDD43629C293004B001059363936796973BF3699CFF4C6C0068C9D72A1231C339802519F001029C2B9C29700B2573962930298B6B524893ABCCEC2BCD681CC010D005E104EFC7246F5EE7328C22C8400424C2538039239F720E3339940263A98029600A80021B1FE34C69100760B41C86D290A8E180256009C9639896A66533E459148200D5AC0149D4E9AACEF0F66B42696194031F000BCE7002D80A8D60277DC00B20227C807E8001CE0C00A7002DC00F300208044E000E69C00B000974C00C1003DC0089B90C1006F5E009CFC87E7E43F3FBADE77BE14C8032C9350D005662754F9BDFA32D881004B12B1964D7000B689B03254564414C016B004A6D3A6BD0DC61E2C95C6E798EA8A4600B5006EC0008542D8690B80010D89F1461B4F535296B6B305A7A4264029580021D1122146900043A0EC7884200085C598CF064C0129CFD8868024592FEE9D7692FEE9D735009E6BBECE0826842730CD250EEA49AA00C4F4B9C9D36D925195A52C4C362EB8043359AE221733DB4B14D9DCE6636ECE48132E040182D802F30AF22F131087EDD9A20804D27BEFF3FD16C8F53A5B599F4866A78D7898C0139418D00424EBB459915200C0BC01098B527C99F4EB54CF0450014A95863BDD3508038600F44C8B90A0801098F91463D1803D07634433200AB68015299EBF4CF5F27F05C600DCEBCCE3A48BC1008B1801AA0803F0CA1AC6200043A2C4558A710E364CC2D14920041E7C9A7040402E987492DE5327CF66A6A93F8CFB4BE60096006E20008543A8330780010E8931C20DCF4BFF13000A424711C4FB32999EE33351500A66E8492F185AB32091F1841C91BE2FDC53C4E80120C8C67EA7734D2448891804B2819245334372CBB0F080480E00D4C0010E82F102360803B1FA2146D963C300BA696A694A501E589A6C80 ================================================ FILE: exm/aoc/2021/aoc_2021_16_questions.txt ================================================ --- Day 16: Packet Decoder --- As you leave the cave and reach open waters, you receive a transmission from the Elves back on the ship. The transmission was sent using the Buoyancy Interchange Transmission System (BITS), a method of packing numeric expressions into a binary sequence. Your submarine's computer has saved the transmission in hexadecimal (your puzzle input). The first step of decoding the message is to convert the hexadecimal representation into binary. Each character of hexadecimal corresponds to four bits of binary data: 0 = 0000 1 = 0001 2 = 0010 3 = 0011 4 = 0100 5 = 0101 6 = 0110 7 = 0111 8 = 1000 9 = 1001 A = 1010 B = 1011 C = 1100 D = 1101 E = 1110 F = 1111 The BITS transmission contains a single packet at its outermost layer which itself contains many other packets. The hexadecimal representation of this packet might encode a few extra 0 bits at the end; these are not part of the transmission and should be ignored. Every packet begins with a standard header: the first three bits encode the packet version, and the next three bits encode the packet type ID. These two values are numbers; all numbers encoded in any packet are represented as binary with the most significant bit first. For example, a version encoded as the binary sequence 100 represents the number 4. Packets with type ID 4 represent a literal value. Literal value packets encode a single binary number. To do this, the binary number is padded with leading zeroes until its length is a multiple of four bits, and then it is broken into groups of four bits. Each group is prefixed by a 1 bit except the last group, which is prefixed by a 0 bit. These groups of five bits immediately follow the packet header. For example, the hexadecimal string D2FE28 becomes: 110100101111111000101000 VVVTTTAAAAABBBBBCCCCC Below each bit is a label indicating its purpose: The three bits labeled V (110) are the packet version, 6. The three bits labeled T (100) are the packet type ID, 4, which means the packet is a literal value. The five bits labeled A (10111) start with a 1 (not the last group, keep reading) and contain the first four bits of the number, 0111. The five bits labeled B (11110) start with a 1 (not the last group, keep reading) and contain four more bits of the number, 1110. The five bits labeled C (00101) start with a 0 (last group, end of packet) and contain the last four bits of the number, 0101. The three unlabeled 0 bits at the end are extra due to the hexadecimal representation and should be ignored. So, this packet represents a literal value with binary representation 011111100101, which is 2021 in decimal. Every other type of packet (any packet with a type ID other than 4) represent an operator that performs some calculation on one or more sub-packets contained within. Right now, the specific operations aren't important; focus on parsing the hierarchy of sub-packets. An operator packet contains one or more packets. To indicate which subsequent binary data represents its sub-packets, an operator packet can use one of two modes indicated by the bit immediately after the packet header; this is called the length type ID: If the length type ID is 0, then the next 15 bits are a number that represents the total length in bits of the sub-packets contained by this packet. If the length type ID is 1, then the next 11 bits are a number that represents the number of sub-packets immediately contained by this packet. Finally, after the length type ID bit and the 15-bit or 11-bit field, the sub-packets appear. For example, here is an operator packet (hexadecimal string 38006F45291200) with length type ID 0 that contains two sub-packets: 00111000000000000110111101000101001010010001001000000000 VVVTTTILLLLLLLLLLLLLLLAAAAAAAAAAABBBBBBBBBBBBBBBB The three bits labeled V (001) are the packet version, 1. The three bits labeled T (110) are the packet type ID, 6, which means the packet is an operator. The bit labeled I (0) is the length type ID, which indicates that the length is a 15-bit number representing the number of bits in the sub-packets. The 15 bits labeled L (000000000011011) contain the length of the sub-packets in bits, 27. The 11 bits labeled A contain the first sub-packet, a literal value representing the number 10. The 16 bits labeled B contain the second sub-packet, a literal value representing the number 20. After reading 11 and 16 bits of sub-packet data, the total length indicated in L (27) is reached, and so parsing of this packet stops. As another example, here is an operator packet (hexadecimal string EE00D40C823060) with length type ID 1 that contains three sub-packets: 11101110000000001101010000001100100000100011000001100000 VVVTTTILLLLLLLLLLLAAAAAAAAAAABBBBBBBBBBBCCCCCCCCCCC The three bits labeled V (111) are the packet version, 7. The three bits labeled T (011) are the packet type ID, 3, which means the packet is an operator. The bit labeled I (1) is the length type ID, which indicates that the length is a 11-bit number representing the number of sub-packets. The 11 bits labeled L (00000000011) contain the number of sub-packets, 3. The 11 bits labeled A contain the first sub-packet, a literal value representing the number 1. The 11 bits labeled B contain the second sub-packet, a literal value representing the number 2. The 11 bits labeled C contain the third sub-packet, a literal value representing the number 3. After reading 3 complete sub-packets, the number of sub-packets indicated in L (3) is reached, and so parsing of this packet stops. For now, parse the hierarchy of the packets throughout the transmission and add up all of the version numbers. Here are a few more examples of hexadecimal-encoded transmissions: 8A004A801A8002F478 represents an operator packet (version 4) which contains an operator packet (version 1) which contains an operator packet (version 5) which contains a literal value (version 6); this packet has a version sum of 16. 620080001611562C8802118E34 represents an operator packet (version 3) which contains two sub-packets; each sub-packet is an operator packet that contains two literal values. This packet has a version sum of 12. C0015000016115A2E0802F182340 has the same structure as the previous example, but the outermost packet uses a different length type ID. This packet has a version sum of 23. A0016C880162017C3686B18A3D4780 is an operator packet that contains an operator packet that contains an operator packet that contains five literal values; it has a version sum of 31. Decode the structure of your hexadecimal-encoded BITS transmission; what do you get if you add up the version numbers in all packets? --- Part Two --- Now that you have the structure of your transmission decoded, you can calculate the value of the expression it represents. Literal values (type ID 4) represent a single number as described above. The remaining type IDs are more interesting: Packets with type ID 0 are sum packets - their value is the sum of the values of their sub-packets. If they only have a single sub-packet, their value is the value of the sub-packet. Packets with type ID 1 are product packets - their value is the result of multiplying together the values of their sub-packets. If they only have a single sub-packet, their value is the value of the sub-packet. Packets with type ID 2 are minimum packets - their value is the minimum of the values of their sub-packets. Packets with type ID 3 are maximum packets - their value is the maximum of the values of their sub-packets. Packets with type ID 5 are greater than packets - their value is 1 if the value of the first sub-packet is greater than the value of the second sub-packet; otherwise, their value is 0. These packets always have exactly two sub-packets. Packets with type ID 6 are less than packets - their value is 1 if the value of the first sub-packet is less than the value of the second sub-packet; otherwise, their value is 0. These packets always have exactly two sub-packets. Packets with type ID 7 are equal to packets - their value is 1 if the value of the first sub-packet is equal to the value of the second sub-packet; otherwise, their value is 0. These packets always have exactly two sub-packets. Using these rules, you can now work out the value of the outermost packet in your BITS transmission. For example: C200B40A82 finds the sum of 1 and 2, resulting in the value 3. 04005AC33890 finds the product of 6 and 9, resulting in the value 54. 880086C3E88112 finds the minimum of 7, 8, and 9, resulting in the value 7. CE00C43D881120 finds the maximum of 7, 8, and 9, resulting in the value 9. D8005AC2A8F0 produces 1, because 5 is less than 15. F600BC2D8F produces 0, because 5 is not greater than 15. 9C005AC2F8F0 produces 0, because 5 is not equal to 15. 9C0141080250320F1802104A08 produces 1, because 1 + 3 = 2 * 2. What do you get if you evaluate the expression represented by your hexadecimal-encoded BITS transmission? ================================================ FILE: exm/aoc/2021/aoc_2021_17.adb ================================================ -- Solution to Advent of Code 2021, Day 17 ------------------------------------------- -- Trick Shot -- -- https://adventofcode.com/2021/day/17 -- Copy of questions in: aoc_2021_17_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_17 is use HAT; -- Input target area: x=155..215, y=-132..-72 x_min : constant := 155; x_max : constant := 215; y_min : constant := -132; y_max : constant := -72; -- Example: target area: x=20..30, y=-10..-5 -- x_min : constant := 20; -- x_max : constant := 30; -- y_min : constant := -10; -- y_max : constant := -5; r : array (1 .. 2) of Integer; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; x, y, ym, ymm, vx, vy, hits : Integer; begin ymm := 0; hits := 0; for vx_0 in 1 .. x_max loop -- Above x_max you miss the area at first step. for vy_0 in y_min .. 200 loop -- Top value is heuristically searched (stable results). vx := vx_0; vy := vy_0; x := 0; y := 0; ym := 0; loop x := x + vx; y := y + vy; ym := Max (ym, y); vx := Max (0, vx - 1); vy := vy - 1; if x in x_min .. x_max and then y in y_min .. y_max then hits := hits + 1; if ym > ymm then ymm := ym; -- Put_Line (+"hit ym =" & ym & " vx_0 = " & vx_0 & ", vy_0 = " & vy_0); end if; exit; end if; exit when y < y_min; end loop; end loop; end loop; r (1) := ymm; r (2) := hits; if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: highest y position reached on a trajectory with a hit: " & r (1)); Put_Line (+"Part 2: number of distinct initial velocity values causing hits: " & r (2)); -- Part 1: validated by AoC: 8646 -- Part 2: validated by AoC: 5945 end if; end AoC_2021_17; ================================================ FILE: exm/aoc/2021/aoc_2021_17_questions.txt ================================================ --- Day 17: Trick Shot --- You finally decode the Elves' message. HI, the message says. You continue searching for the sleigh keys. Ahead of you is what appears to be a large ocean trench. Could the keys have fallen into it? You'd better send a probe to investigate. The probe launcher on your submarine can fire the probe with any integer velocity in the x (forward) and y (upward, or downward if negative) directions. For example, an initial x,y velocity like 0,10 would fire the probe straight up, while an initial velocity like 10,-1 would fire the probe forward at a slight downward angle. The probe's x,y position starts at 0,0. Then, it will follow some trajectory by moving in steps. On each step, these changes occur in the following order: The probe's x position increases by its x velocity. The probe's y position increases by its y velocity. Due to drag, the probe's x velocity changes by 1 toward the value 0; that is, it decreases by 1 if it is greater than 0, increases by 1 if it is less than 0, or does not change if it is already 0. Due to gravity, the probe's y velocity decreases by 1. For the probe to successfully make it into the trench, the probe must be on some trajectory that causes it to be within a target area after any step. The submarine computer has already calculated this target area (your puzzle input). For example: target area: x=20..30, y=-10..-5 This target area means that you need to find initial x,y velocity values such that after any step, the probe's x position is at least 20 and at most 30, and the probe's y position is at least -10 and at most -5. Given this target area, one initial velocity that causes the probe to be within the target area after any step is 7,2: .............#....#............ .......#..............#........ ............................... S........................#..... ............................... ............................... ...........................#... ............................... ....................TTTTTTTTTTT ....................TTTTTTTTTTT ....................TTTTTTTT#TT ....................TTTTTTTTTTT ....................TTTTTTTTTTT ....................TTTTTTTTTTT In this diagram, S is the probe's initial position, 0,0. The x coordinate increases to the right, and the y coordinate increases upward. In the bottom right, positions that are within the target area are shown as T. After each step (until the target area is reached), the position of the probe is marked with #. (The bottom-right # is both a position the probe reaches and a position in the target area.) Another initial velocity that causes the probe to be within the target area after any step is 6,3: ...............#..#............ ...........#........#.......... ............................... ......#..............#......... ............................... ............................... S....................#......... ............................... ............................... ............................... .....................#......... ....................TTTTTTTTTTT ....................TTTTTTTTTTT ....................TTTTTTTTTTT ....................TTTTTTTTTTT ....................T#TTTTTTTTT ....................TTTTTTTTTTT Another one is 9,0: S........#..................... .................#............. ............................... ........................#...... ............................... ....................TTTTTTTTTTT ....................TTTTTTTTTT# ....................TTTTTTTTTTT ....................TTTTTTTTTTT ....................TTTTTTTTTTT ....................TTTTTTTTTTT One initial velocity that doesn't cause the probe to be within the target area after any step is 17,-4: S.............................................................. ............................................................... ............................................................... ............................................................... .................#............................................. ....................TTTTTTTTTTT................................ ....................TTTTTTTTTTT................................ ....................TTTTTTTTTTT................................ ....................TTTTTTTTTTT................................ ....................TTTTTTTTTTT..#............................. ....................TTTTTTTTTTT................................ ............................................................... ............................................................... ............................................................... ............................................................... ................................................#.............. ............................................................... ............................................................... ............................................................... ............................................................... ............................................................... ............................................................... ..............................................................# The probe appears to pass through the target area, but is never within it after any step. Instead, it continues down and to the right - only the first few steps are shown. If you're going to fire a highly scientific probe out of a super cool probe launcher, you might as well do it with style. How high can you make the probe go while still reaching the target area? In the above example, using an initial velocity of 6,9 is the best you can do, causing the probe to reach a maximum y position of 45. (Any higher initial y velocity causes the probe to overshoot the target area entirely.) Find the initial velocity that causes the probe to reach the highest y position and still eventually be within the target area after any step. What is the highest y position it reaches on this trajectory? --- Part Two --- Maybe a fancy trick shot isn't the best idea; after all, you only have one probe, so you had better not miss. To get the best idea of what your options are for launching the probe, you need to find every initial velocity that causes the probe to eventually be within the target area after any step. In the above example, there are 112 different initial velocity values that meet these criteria: 23,-10 25,-9 27,-5 29,-6 22,-6 21,-7 9,0 27,-7 24,-5 25,-7 26,-6 25,-5 6,8 11,-2 20,-5 29,-10 6,3 28,-7 8,0 30,-6 29,-8 20,-10 6,7 6,4 6,1 14,-4 21,-6 26,-10 7,-1 7,7 8,-1 21,-9 6,2 20,-7 30,-10 14,-3 20,-8 13,-2 7,3 28,-8 29,-9 15,-3 22,-5 26,-8 25,-8 25,-6 15,-4 9,-2 15,-2 12,-2 28,-9 12,-3 24,-6 23,-7 25,-10 7,8 11,-3 26,-7 7,1 23,-9 6,0 22,-10 27,-6 8,1 22,-8 13,-4 7,6 28,-6 11,-4 12,-4 26,-9 7,4 24,-10 23,-8 30,-8 7,0 9,-1 10,-1 26,-5 22,-9 6,5 7,5 23,-6 28,-10 10,-2 11,-1 20,-9 14,-2 29,-7 13,-3 23,-5 24,-8 27,-9 30,-7 28,-5 21,-10 7,9 6,6 21,-5 27,-10 7,2 30,-9 21,-8 22,-7 24,-9 20,-6 6,9 29,-5 8,-2 27,-8 30,-5 24,-7 How many distinct initial velocity values cause the probe to be within the target area after any step? ================================================ FILE: exm/aoc/2021/aoc_2021_18.txt ================================================ [[[1,4],[1,6]],[0,[5,[6,3]]]] [[[8,2],5],[[[9,8],[3,5]],[2,1]]] [[[[6,2],[0,6]],[[9,8],[7,8]]],[[6,3],[[8,8],3]]] [[[1,[2,1]],[5,7]],[[[3,1],[3,1]],[[8,4],[8,5]]]] [[[[6,4],7],[[1,6],5]],[7,[9,5]]] [[7,[[5,3],[0,9]]],[[[6,2],[6,8]],[5,[5,7]]]] [9,5] [[[[7,8],[8,0]],[[3,8],[0,7]]],[[1,[1,2]],2]] [[[4,[5,5]],[[6,8],[4,3]]],[[9,9],[4,[3,6]]]] [[[[2,8],7],[[6,1],[1,0]]],[[6,2],9]] [[[8,1],3],[9,[[1,4],[4,1]]]] [[[[0,1],[3,9]],[[4,3],6]],[[[4,8],8],[[8,3],[9,5]]]] [[[[7,3],7],[[5,9],0]],7] [[[5,[1,6]],3],[[3,5],9]] [[[[2,5],[1,8]],[[6,5],[0,1]]],[[[4,1],1],[0,[9,6]]]] [[[4,8],[[3,6],[3,8]]],[[[2,3],3],[[9,8],[7,9]]]] [[[[5,6],0],[9,[4,4]]],[[[3,1],[3,6]],[[6,0],3]]] [[[[4,3],4],4],[[[1,6],7],[8,[6,0]]]] [[[0,2],1],5] [[[[7,2],[9,0]],[8,[0,1]]],2] [[[1,6],[[6,2],5]],[[1,[8,2]],[[9,8],7]]] [[[8,1],9],[[[4,3],2],[[2,9],6]]] [[[[9,4],0],[4,0]],4] [[[5,[2,8]],[[5,3],[6,4]]],[8,3]] [[0,5],[[[3,4],7],[[0,2],[9,1]]]] [[[8,[7,9]],[[1,8],6]],[[4,[6,0]],0]] [[[1,0],[[6,7],4]],[[[2,5],[9,7]],[[7,8],0]]] [[9,[[7,1],3]],[[[9,2],[4,3]],[2,[1,8]]]] [[[5,[9,6]],4],[1,[[9,2],[6,8]]]] [6,[[[6,1],7],6]] [[4,[[5,6],9]],[[9,[6,6]],[[6,1],[8,2]]]] [[1,[9,5]],[[[5,8],9],5]] [[[[6,6],[1,8]],6],[[[4,9],4],[8,[9,8]]]] [[[[6,5],[4,4]],[[0,2],8]],[[[0,6],[4,5]],3]] [[[1,[6,9]],[9,[5,8]]],[5,2]] [[2,[[2,8],[3,3]]],[[[1,9],9],6]] [[3,2],[9,[2,2]]] [4,[3,[6,[2,0]]]] [[[[1,0],4],3],[[0,9],[[9,8],[7,1]]]] [[[2,6],[3,8]],[[5,5],[2,3]]] [6,[[[8,8],4],[[8,1],[6,6]]]] [[[5,9],[5,3]],7] [[[5,[1,2]],[6,[7,2]]],[[[0,5],3],3]] [[8,[[7,3],[9,7]]],[[2,[3,9]],[[1,7],[5,7]]]] [8,[4,6]] [[[4,4],[[4,5],[2,5]]],[[[9,1],0],[[2,9],1]]] [[[2,[2,8]],9],[5,[6,9]]] [[[[4,1],5],[6,[2,7]]],[1,2]] [[[6,[3,5]],0],[[0,3],4]] [[[[3,2],[8,0]],[5,1]],[[[9,7],3],[[6,5],[2,6]]]] [[1,[0,[1,4]]],[[[8,6],[6,9]],[[4,9],8]]] [[[[5,2],[4,3]],[0,[3,5]]],[0,[1,7]]] [[[8,1],[3,[8,1]]],[[[7,9],[6,2]],[[0,8],2]]] [[[2,[9,7]],[[6,6],[2,7]]],[[8,[6,4]],0]] [[3,0],[[6,3],1]] [[[[5,5],2],[9,7]],[[0,[3,5]],7]] [[[[4,8],2],0],[[4,[7,9]],[6,6]]] [[[1,0],[[9,4],[8,8]]],2] [[[6,1],9],[5,2]] [[[7,[0,3]],[[5,5],7]],[5,[[0,5],[5,3]]]] [[[[8,0],4],[[5,5],[9,4]]],[[[9,0],[2,5]],[6,[8,1]]]] [[[7,8],[0,[5,4]]],[[[7,6],[0,9]],[7,2]]] [[[4,[0,2]],[3,[4,9]]],[[[4,7],8],3]] [[1,[5,[7,3]]],8] [[[[1,3],[6,8]],3],[[6,1],8]] [[[[7,9],5],[[6,2],4]],[[5,[6,9]],1]] [[2,[3,[9,3]]],[[6,[2,7]],[4,8]]] [7,[[6,2],[[6,7],[5,0]]]] [[[9,[8,6]],1],[[4,8],[[6,1],[0,1]]]] [[[[4,6],[4,0]],[[2,4],0]],[[[0,5],[9,8]],[[3,4],[2,5]]]] [9,[3,[[5,5],[3,1]]]] [[[5,[7,1]],3],[[[8,2],5],[[2,8],[0,0]]]] [[[[8,3],0],[[5,0],5]],[[3,[8,2]],[[8,2],3]]] [[4,[[9,4],5]],[[[1,6],[0,2]],[0,8]]] [[[0,0],[[1,8],2]],[[[1,8],1],[0,[0,8]]]] [[[6,[1,5]],5],[[2,[0,1]],9]] [[7,[2,[2,8]]],[4,[[1,1],5]]] [1,[[4,[0,5]],4]] [[3,[[3,1],[1,2]]],[[[5,3],8],[5,2]]] [[[3,[2,0]],6],[[9,3],[[3,0],[1,6]]]] [4,[[6,[5,9]],[[4,1],[6,6]]]] [8,[3,0]] [[[[5,3],[8,8]],[[5,1],4]],[[6,6],[8,2]]] [[1,[[7,1],5]],[[[2,3],7],[[7,6],0]]] [9,[[4,3],[[6,2],0]]] [[[[4,0],4],[1,7]],[[[3,8],8],[[9,1],1]]] [[[0,1],[9,9]],7] [[[[1,7],0],[1,5]],[1,[2,2]]] [[[[6,1],[3,3]],[6,[9,0]]],[[7,0],3]] [[[[6,1],[9,8]],[[2,2],2]],[8,[3,6]]] [[6,[5,0]],[7,[1,7]]] [[4,[[6,1],6]],[[2,5],7]] [8,[8,[[6,4],1]]] [[[[0,2],4],[[2,6],2]],0] [[2,[[6,1],9]],[[7,[0,5]],[5,[9,4]]]] [3,[[8,7],[[8,9],6]]] [[[[7,8],[1,1]],[[2,6],[3,7]]],4] [[[[6,1],1],5],5] [[9,[4,[6,6]]],[[5,1],[8,2]]] [[5,[[7,3],4]],9] ================================================ FILE: exm/aoc/2021/aoc_2021_18_full_ada.adb ================================================ -- Solution to Advent of Code 2021, Day 18 ------------------------------------------- -- Snailfish -- -- NB: this doesn't compile with HAC, only with a "full Ada" compiler. -- -- To do: make a HAC solution using a heap structure for the -- binary tree (idea Maxim Reznik) -- https://adventofcode.com/2021/day/18 -- Copy of questions in: aoc_2021_18_questions.txt -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src with Ada.Unchecked_Deallocation; procedure AoC_2021_18_full_Ada is use HAT; type Node_Type; type Node_Access is access Node_Type; type Node_Type (is_pair : Boolean) is record case is_pair is when True => left, right : Node_Access; when False => number : Integer; end case; end record; procedure Free is new Ada.Unchecked_Deallocation (Node_Type, Node_Access); procedure Clear (n : in out Node_Access) is begin if n /= null then if n.is_pair then Clear (n.left); Clear (n.right); end if; Free (n); end if; end Clear; subtype Snailfish_Number is Node_Access; -- Just a nicer name. procedure Show (node : Snailfish_Number) is begin if node.is_pair then Put ('['); Show (node.left); Put (','); Show (node.right); Put (']'); else Put (node.number, 0); end if; end Show; pragma Unreferenced (Show); procedure Reduce (number : in out Snailfish_Number) is change : Boolean; add_left, add_right : Natural; -- procedure Solve_Left (node : Snailfish_Number) is begin if add_left = 0 then return; end if; if node.is_pair then -- The left exploded number goes rightmost, on the left side: Solve_Left (node.right); -- Prioritize the right node. Solve_Left (node.left); elsif add_left > 0 then node.number := node.number + add_left; add_left := 0; end if; end Solve_Left; -- procedure Solve_Right (node : Snailfish_Number) is begin if add_right = 0 then return; end if; if node.is_pair then -- The right exploded number goes leftmost, on the right side: Solve_Right (node.left); -- Prioritize the left node. Solve_Right (node.right); elsif add_right > 0 then node.number := node.number + add_right; add_right := 0; end if; end Solve_Right; -- procedure Explode (node : in out Snailfish_Number; level : Natural) is begin if change then return; end if; if node.is_pair then if level = 5 then pragma Assert (not node.left.is_pair); pragma Assert (not node.right.is_pair); add_left := node.left.number; add_right := node.right.number; Free (node); node := new Node_Type'(False, 0); change := True; else Explode (node.left, level + 1); if change then -- There is always a number in the part of the tree -- starting at the sibling node. So, no need to try -- adding the number elsewhere in the tree. Solve_Right (node.right); else Explode (node.right, level + 1); if change then -- Same remark as above. Solve_Left (node.left); end if; end if; end if; end if; end Explode; -- procedure Split (node : in out Snailfish_Number) is new_left, new_right : Snailfish_Number; begin if change then return; end if; if node.is_pair then Split (node.left); Split (node.right); elsif node.number > 9 then new_left := new Node_Type'(False, node.number / 2); new_right := new Node_Type'(False, node.number - new_left.number); Free (node); node := new Node_Type'(True, new_left, new_right); change := True; end if; end Split; -- begin loop change := False; add_left := 0; add_right := 0; Explode (number, 1); Split (number); exit when not change; end loop; end Reduce; -- function Magnitude (node : Snailfish_Number) return Integer is begin if node.is_pair then return 3 * Magnitude (node.left) + 2 * Magnitude (node.right); else return node.number; end if; end Magnitude; -- function "+" (a, b : Snailfish_Number) return Snailfish_Number is a_plus_b : Snailfish_Number; begin if a = null then return b; end if; if b = null then return a; end if; -- Snailfish addition: a_plus_b := new Node_Type'(True, a, b); -- "snailfish numbers must always be reduced, and the process -- numbers of adding two snailfish numbers can result in -- snailfish that need to be reduced." -- This rule avoids nesting levels > 5 at any point, including -- after the next unreduced addition. Reduce (a_plus_b); return a_plus_b; end "+"; -- number_of_terms : Natural := 0; root : Snailfish_Number := null; -- procedure Read_Data ( l1, l2 : Natural := 0; -- When not 0, read only lines l1, l2. is_swapped : Boolean := False ) is input : constant VString := +"aoc_2021_18.txt"; -- c, sep : Character; f : File_Type; function Read_Item return Snailfish_Number is node : Snailfish_Number; begin Get (f, c); if c = '[' then -- It's a pair node := new Node_Type (is_pair => True); node.left := Read_Item; Get (f, sep); -- ',' node.right := Read_Item; Get (f, sep); -- ']' else -- It's a literal node := new Node_Type (is_pair => False); node.number := Ord (c) - Ord ('0'); end if; return node; end Read_Item; -- l : Natural := 0; dummy : Snailfish_Number; begin Open (f, input); loop l := l + 1; if l1 = 0 or else l = l1 or else l = l2 then if is_swapped then root := Read_Item + root; else root := root + Read_Item; end if; else dummy := Read_Item; Clear (dummy); end if; exit when End_Of_File (f); end loop; Close (f); number_of_terms := l; end Read_Data; -- max : Natural := 0; r : array (1 .. 2) of Integer; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; -- r (1) := Magnitude (root); Clear (root); for i in 1 .. number_of_terms - 1 loop for j in i + 1 .. number_of_terms loop for is_swapped in Boolean loop -- Re-reading selectively the data is simpler -- than deep-cloning trees. Read_Data (i, j, is_swapped); max := Integer'Max (max, Magnitude (root)); Clear (root); end loop; end loop; end loop; r (2) := max; if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: Magnitude of the sum of all terms : " & r (1)); Put_Line (+"Part 2: Largest magnitude of the sum of any pair of terms: " & r (2)); -- Part 1: validated by AoC: 3665. -- Part 2: validated by AoC: 4775. end if; end AoC_2021_18_full_Ada; ================================================ FILE: exm/aoc/2021/aoc_2021_18_questions.txt ================================================ --- Day 18: Snailfish --- You descend into the ocean trench and encounter some snailfish. They say they saw the sleigh keys! They'll even tell you which direction the keys went if you help one of the smaller snailfish with his math homework. Snailfish numbers aren't like regular numbers. Instead, every snailfish number is a pair - an ordered list of two elements. Each element of the pair can be either a regular number or another pair. Pairs are written as [x,y], where x and y are the elements within the pair. Here are some example snailfish numbers, one snailfish number per line: [1,2] [[1,2],3] [9,[8,7]] [[1,9],[8,5]] [[[[1,2],[3,4]],[[5,6],[7,8]]],9] [[[9,[3,8]],[[0,9],6]],[[[3,7],[4,9]],3]] [[[[1,3],[5,3]],[[1,3],[8,7]]],[[[4,9],[6,9]],[[8,2],[7,3]]]] This snailfish homework is about addition. To add two snailfish numbers, form a pair from the left and right parameters of the addition operator. For example, [1,2] + [[3,4],5] becomes [[1,2],[[3,4],5]]. There's only one problem: snailfish numbers must always be reduced, and the process of adding two snailfish numbers can result in snailfish numbers that need to be reduced. To reduce a snailfish number, you must repeatedly do the first action in this list that applies to the snailfish number: If any pair is nested inside four pairs, the leftmost such pair explodes. If any regular number is 10 or greater, the leftmost such regular number splits. Once no action in the above list applies, the snailfish number is reduced. During reduction, at most one action applies, after which the process returns to the top of the list of actions. For example, if split produces a pair that meets the explode criteria, that pair explodes before other splits occur. To explode a pair, the pair's left value is added to the first regular number to the left of the exploding pair (if any), and the pair's right value is added to the first regular number to the right of the exploding pair (if any). Exploding pairs will always consist of two regular numbers. Then, the entire exploding pair is replaced with the regular number 0. Here are some examples of a single explode action: [[[[[9,8],1],2],3],4] becomes [[[[0,9],2],3],4] (the 9 has no regular number to its left, so it is not added to any regular number). [7,[6,[5,[4,[3,2]]]]] becomes [7,[6,[5,[7,0]]]] (the 2 has no regular number to its right, and so it is not added to any regular number). [[6,[5,[4,[3,2]]]],1] becomes [[6,[5,[7,0]]],3]. [[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]] becomes [[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]] (the pair [3,2] is unaffected because the pair [7,3] is further to the left; [3,2] would explode on the next action). [[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]] becomes [[3,[2,[8,0]]],[9,[5,[7,0]]]]. To split a regular number, replace it with a pair; the left element of the pair should be the regular number divided by two and rounded down, while the right element of the pair should be the regular number divided by two and rounded up. For example, 10 becomes [5,5], 11 becomes [5,6], 12 becomes [6,6], and so on. Here is the process of finding the reduced result of [[[[4,3],4],4],[7,[[8,4],9]]] + [1,1]: after addition: [[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]] after explode: [[[[0,7],4],[7,[[8,4],9]]],[1,1]] after explode: [[[[0,7],4],[15,[0,13]]],[1,1]] after split: [[[[0,7],4],[[7,8],[0,13]]],[1,1]] after split: [[[[0,7],4],[[7,8],[0,[6,7]]]],[1,1]] after explode: [[[[0,7],4],[[7,8],[6,0]]],[8,1]] Once no reduce actions apply, the snailfish number that remains is the actual result of the addition operation: [[[[0,7],4],[[7,8],[6,0]]],[8,1]]. The homework assignment involves adding up a list of snailfish numbers (your puzzle input). The snailfish numbers are each listed on a separate line. Add the first snailfish number and the second, then add that result and the third, then add that result and the fourth, and so on until all numbers in the list have been used once. For example, the final sum of this list is [[[[1,1],[2,2]],[3,3]],[4,4]]: [1,1] [2,2] [3,3] [4,4] The final sum of this list is [[[[3,0],[5,3]],[4,4]],[5,5]]: [1,1] [2,2] [3,3] [4,4] [5,5] The final sum of this list is [[[[5,0],[7,4]],[5,5]],[6,6]]: [1,1] [2,2] [3,3] [4,4] [5,5] [6,6] Here's a slightly larger example: [[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]] [7,[[[3,7],[4,3]],[[6,3],[8,8]]]] [[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]] [[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]] [7,[5,[[3,8],[1,4]]]] [[2,[2,2]],[8,[8,1]]] [2,9] [1,[[[9,3],9],[[9,0],[0,7]]]] [[[5,[7,4]],7],1] [[[[4,2],2],6],[8,7]] The final sum [[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]] is found after adding up the above snailfish numbers: [[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]] + [7,[[[3,7],[4,3]],[[6,3],[8,8]]]] = [[[[4,0],[5,4]],[[7,7],[6,0]]],[[8,[7,7]],[[7,9],[5,0]]]] [[[[4,0],[5,4]],[[7,7],[6,0]]],[[8,[7,7]],[[7,9],[5,0]]]] + [[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]] = [[[[6,7],[6,7]],[[7,7],[0,7]]],[[[8,7],[7,7]],[[8,8],[8,0]]]] [[[[6,7],[6,7]],[[7,7],[0,7]]],[[[8,7],[7,7]],[[8,8],[8,0]]]] + [[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]] = [[[[7,0],[7,7]],[[7,7],[7,8]]],[[[7,7],[8,8]],[[7,7],[8,7]]]] [[[[7,0],[7,7]],[[7,7],[7,8]]],[[[7,7],[8,8]],[[7,7],[8,7]]]] + [7,[5,[[3,8],[1,4]]]] = [[[[7,7],[7,8]],[[9,5],[8,7]]],[[[6,8],[0,8]],[[9,9],[9,0]]]] [[[[7,7],[7,8]],[[9,5],[8,7]]],[[[6,8],[0,8]],[[9,9],[9,0]]]] + [[2,[2,2]],[8,[8,1]]] = [[[[6,6],[6,6]],[[6,0],[6,7]]],[[[7,7],[8,9]],[8,[8,1]]]] [[[[6,6],[6,6]],[[6,0],[6,7]]],[[[7,7],[8,9]],[8,[8,1]]]] + [2,9] = [[[[6,6],[7,7]],[[0,7],[7,7]]],[[[5,5],[5,6]],9]] [[[[6,6],[7,7]],[[0,7],[7,7]]],[[[5,5],[5,6]],9]] + [1,[[[9,3],9],[[9,0],[0,7]]]] = [[[[7,8],[6,7]],[[6,8],[0,8]]],[[[7,7],[5,0]],[[5,5],[5,6]]]] [[[[7,8],[6,7]],[[6,8],[0,8]]],[[[7,7],[5,0]],[[5,5],[5,6]]]] + [[[5,[7,4]],7],1] = [[[[7,7],[7,7]],[[8,7],[8,7]]],[[[7,0],[7,7]],9]] [[[[7,7],[7,7]],[[8,7],[8,7]]],[[[7,0],[7,7]],9]] + [[[[4,2],2],6],[8,7]] = [[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]] To check whether it's the right answer, the snailfish teacher only checks the magnitude of the final sum. The magnitude of a pair is 3 times the magnitude of its left element plus 2 times the magnitude of its right element. The magnitude of a regular number is just that number. For example, the magnitude of [9,1] is 3*9 + 2*1 = 29; the magnitude of [1,9] is 3*1 + 2*9 = 21. Magnitude calculations are recursive: the magnitude of [[9,1],[1,9]] is 3*29 + 2*21 = 129. Here are a few more magnitude examples: [[1,2],[[3,4],5]] becomes 143. [[[[0,7],4],[[7,8],[6,0]]],[8,1]] becomes 1384. [[[[1,1],[2,2]],[3,3]],[4,4]] becomes 445. [[[[3,0],[5,3]],[4,4]],[5,5]] becomes 791. [[[[5,0],[7,4]],[5,5]],[6,6]] becomes 1137. [[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]] becomes 3488. So, given this example homework assignment: [[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]] [[[5,[2,8]],4],[5,[[9,9],0]]] [6,[[[6,2],[5,6]],[[7,6],[4,7]]]] [[[6,[0,7]],[0,9]],[4,[9,[9,0]]]] [[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]] [[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]] [[[[5,4],[7,7]],8],[[8,3],8]] [[9,3],[[9,9],[6,[4,9]]]] [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] [[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]] The final sum is: [[[[6,6],[7,6]],[[7,7],[7,0]]],[[[7,7],[7,7]],[[7,8],[9,9]]]] The magnitude of this final sum is 4140. Add up all of the snailfish numbers from the homework assignment in the order they appear. What is the magnitude of the final sum? --- Part Two --- You notice a second question on the back of the homework assignment: What is the largest magnitude you can get from adding only two of the snailfish numbers? Note that snailfish addition is not commutative - that is, x + y and y + x can produce different results. Again considering the last example homework assignment above: [[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]] [[[5,[2,8]],4],[5,[[9,9],0]]] [6,[[[6,2],[5,6]],[[7,6],[4,7]]]] [[[6,[0,7]],[0,9]],[4,[9,[9,0]]]] [[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]] [[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]] [[[[5,4],[7,7]],8],[[8,3],8]] [[9,3],[[9,9],[6,[4,9]]]] [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] [[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]] The largest magnitude of the sum of any two snailfish numbers in this list is 3993. This is the magnitude of [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] + [[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]], which reduces to [[[[7,8],[6,6]],[[6,0],[7,7]]],[[[7,8],[8,8]],[[7,9],[0,6]]]]. What is the largest magnitude of any sum of two different snailfish numbers from the homework assignment? ================================================ FILE: exm/aoc/2021/aoc_2021_19.adb ================================================ -- Solution to Advent of Code 2021, Day 19 ------------------------------------------- -- Beacon Scanner -- -- https://adventofcode.com/2021/day/19 -- Copy of questions in: aoc_2021_19_questions.txt -- -- Note: this programs takes very long on HAC! -- -- HAC 0.098 "nice to have"'s detected in this exercise: -- * Performance: large "in" parameters passed as reference -- * Comparison (equality operators) "=", "/=" of composite types (arrays and records) -- * Detect an expression as a static (compile-time-known) value -- -- Solved in HAC 0.26: -- * Exiting multiple nested loops -- * `EXIT [Label]` -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_19 is type Vector is array (1 .. 3) of Integer; subtype Cube_Face is Integer range 1 .. 6; subtype Plane_Rotation is Integer range 1 .. 4; use HAT; procedure Rotate (v : in out Vector; face : Cube_Face; spin : Plane_Rotation) is w : Vector; begin w (3) := v (3); case spin is when 1 => w (1) := v (1); w (2) := v (2); -- Rotate around z when 2 => w (1) := -v (2); w (2) := v (1); -- 90 when 3 => w (1) := -v (1); w (2) := -v (2); -- 180 when 4 => w (1) := v (2); w (2) := -v (1); -- -90 end case; -- case face is when 1 => v := w; -- Rotate around x axis (z axis turns and joins -y, -z, or +y) when 2 => v (1) := w (1); v (2) := -w (3); v (3) := w (2); -- 90 when 3 => v (1) := w (1); v (2) := -w (2); v (3) := -w (3); -- 180 when 4 => v (1) := w (1); v (2) := w (3); v (3) := -w (2); -- -90 -- Rotate around y axis (z axis turns and joins -x or x) when 5 => v (2) := w (2); v (1) := -w (3); v (3) := w (1); -- 90 when 6 => v (2) := w (2); v (1) := w (3); v (3) := -w (1); -- -90 end case; end Rotate; procedure Minus (a, b : Vector; c : out Vector) is begin for i in 1 .. 3 loop c (i) := a (i) - b (i); end loop; end Minus; function Dist_L1 (a, b : Vector) return Natural is res : Natural := 0; begin for i in 1 .. 3 loop res := res + abs (a (i) - b (i)); end loop; return res; end Dist_L1; input : constant VString := +"aoc_2021_19.txt"; max_scanners : constant := 50; max_coords : constant := 50; coords : array (1 .. max_scanners) of Natural; data : array (1 .. max_scanners, 1 .. max_coords) of Vector; scanners : Natural; verbose : constant := 1; procedure Read_Data is v1, v2 : Character; f : File_Type; s : VString; begin scanners := 0; Open (f, input); while not End_Of_File (f) loop Get_Line (f, s); -- Header if verbose > 0 then Put_Line (s); end if; scanners := scanners + 1; coords (scanners) := 0; loop coords (scanners) := coords (scanners) + 1; Get (f, data (scanners, coords (scanners)) (1)); Get (f, v1); Get (f, data (scanners, coords (scanners)) (2)); Get (f, v2); Get (f, data (scanners, coords (scanners)) (3)); exit when End_Of_File (f); Skip_Line (f); exit when End_Of_Line (f); end loop; exit when End_Of_File (f); Skip_Line (f); -- Empty line end loop; Close (f); end Read_Data; type Scanner_Pair_Info is record paired : Boolean; face : Cube_Face; spin : Plane_Rotation; shift : Vector; end record; info : array (1 .. max_scanners, 1 .. max_scanners) of Scanner_Pair_Info; procedure Align is vs_1, vs_2, vs_1_to_2, vs_2_o, v_test : Vector; aligned : Natural; threshold : constant := 12; -- This is given. begin for s_1 in 1 .. scanners loop for s_2 in s_1 + 1 .. scanners loop info (s_1, s_2).paired := False; end loop; end loop; -- Scanner_Loop_1 : for s_1 in 1 .. scanners loop Aligned_Beacon_1_Search : for c1 in 1 .. coords (s_1) - threshold + 1 loop vs_1 := data (s_1, c1); Scanner_Loop_2 : for s_2 in 1 .. scanners loop if not (s_1 = s_2 or else info (s_1, s_2).paired) then Rotation_Cube : for face in Cube_Face loop Rotation_Face : for spin in Plane_Rotation loop Aligned_Beacon_2_Search : for cs_2 in 1 .. coords (s_2) loop vs_2 := data (s_2, cs_2); Rotate (vs_2, face, spin); Minus (vs_2, vs_1, vs_1_to_2); -- Now, try to align all data -- between scanner s_1 and scanner s_2 aligned := 0; -- -- Try matching any data of scanner 2 with any data of scanner 1. -- for cs_1_o in 1 .. coords (s_1) loop for cs_2_o in 1 .. coords (s_2) loop vs_2_o := data (s_2, cs_2_o); Rotate (vs_2_o, face, spin); Minus (vs_2_o, vs_1_to_2, v_test); if Dist_L1 (v_test, data (s_1, cs_1_o)) = 0 then aligned := aligned + 1; end if; end loop; end loop; -- if aligned >= threshold then info (s_1, s_2).paired := True; info (s_1, s_2).face := face; info (s_1, s_2).spin := spin; info (s_1, s_2).shift := vs_1_to_2; if verbose > 0 then Put_Line (+"aligned: " & aligned & " beacons between scanners " & (s_1 - 1) & " and " & (s_2 - 1) & " translation vector: " & vs_1_to_2 (1) & ", " & vs_1_to_2 (2) & ", " & vs_1_to_2 (3)); end if; exit Scanner_Loop_2; end if; end loop Aligned_Beacon_2_Search; end loop Rotation_Face; end loop Rotation_Cube; end if; end loop Scanner_Loop_2; end loop Aligned_Beacon_1_Search; end loop Scanner_Loop_1; end Align; max_beacons : constant := 2500; -- "full Ada": max_scanners * max_coords beacons : Natural := 0; beacon : array (1 .. max_beacons) of Vector; scanner_pos : array (1 .. max_scanners) of Vector; procedure Make_Beacon_List is -- Shortcut in the connectivity tree towards the root (first scanner). up : array (2 .. max_scanners) of Natural; connected : Natural := 0; found : Boolean; s : Positive; v, vt : Vector; begin for child_node in 2 .. scanners loop up (child_node) := 0; if info (1, child_node).paired then up (child_node) := 1; connected := connected + 1; end if; end loop; while connected < scanners - 1 loop for child_node in 2 .. scanners loop if up (child_node) = 0 then for parent_node in 2 .. scanners loop if info (parent_node, child_node).paired and then up (parent_node) /= 0 -- Check that the parent is itself connected! then up (child_node) := parent_node; connected := connected + 1; exit; end if; end loop; end if; end loop; end loop; -- beacons := coords (1); for i in 1 .. beacons loop beacon (i) := data (1, i); end loop; -- for d in 1 .. 3 loop scanner_pos (1) (d) := 0; end loop; for i in 2 .. scanners loop if verbose > 0 then Put_Line (+"Convert data from scanner " & (i - 1) & " to scanner 0"); end if; for j in 1 .. coords (i) loop v := data (i, j); s := i; while s /= 1 loop if verbose > 0 and j = 1 then Put_Line (+" Convert data from scanner " & (s - 1) & " to scanner " & (up (s) - 1)); end if; Rotate (v, info (up (s), s).face, info (up (s), s).spin); Minus (v, info (up (s), s).shift, vt); v := vt; s := up (s); end loop; found := False; for k in 1 .. beacons loop if Dist_L1 (vt, beacon (k)) = 0 then found := True; exit; end if; end loop; if not found then beacons := beacons + 1; beacon (beacons) := v; end if; end loop; for d in 1 .. 3 loop v (d) := 0; end loop; s := i; while s /= 1 loop Rotate (v, info (up (s), s).face, info (up (s), s).spin); Minus (v, info (up (s), s).shift, vt); v := vt; s := up (s); end loop; scanner_pos (i) := v; end loop; if verbose > 1 then for k in 1 .. beacons loop for d in 1 .. 3 loop Put (beacon (k)(d)); Put (' '); end loop; New_Line; end loop; end if; end Make_Beacon_List; r : array (1 .. 2) of Integer; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Align; Make_Beacon_List; r (1) := beacons; r (2) := 0; for i in 1 .. scanners loop for j in i + 1 .. scanners loop r (2) := Max (r (2), Dist_L1 (scanner_pos (i), scanner_pos (j))); end loop; end loop; -- if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: Number of beacons : " & r (1)); Put_Line (+"Part 2: Max distance between scanners: " & r (2)); -- Part 1: validated by AoC: 408 -- Part 2: validated by AoC: 13348 end if; end AoC_2021_19; ================================================ FILE: exm/aoc/2021/aoc_2021_19.txt ================================================ --- scanner 0 --- -812,-728,-591 -259,678,-532 735,-470,492 -808,-734,-657 518,-635,-807 -487,402,391 722,545,-708 -529,-401,536 -326,616,-504 -330,707,-663 878,574,-722 670,-614,-747 533,-501,495 -508,406,332 -797,-541,-583 114,15,-132 -522,-438,589 587,-480,480 -639,-447,471 687,564,-674 896,574,424 -449,386,511 652,-513,-789 819,586,254 836,538,409 --- scanner 1 --- 670,487,-847 -432,537,-395 -521,374,359 -666,441,313 740,701,863 -432,701,-383 721,-698,-623 818,605,871 -282,-564,-496 766,577,737 -375,-596,-489 -433,-537,-427 745,-562,-653 650,-523,785 24,36,8 608,-417,733 -386,-616,490 453,-460,776 745,-802,-648 -454,633,-472 -403,-500,596 693,557,-710 669,547,-874 -462,-478,508 -529,539,346 --- scanner 2 --- -566,-825,-742 -662,-843,343 640,-448,544 -593,-867,362 -570,753,323 -17,-6,-139 757,831,503 525,605,-563 -549,694,319 -591,549,-484 763,-859,-617 471,590,-584 673,593,-553 -701,614,-530 -458,-744,-723 -511,574,303 -658,-773,306 554,-488,396 -584,496,-521 646,-875,-525 -522,-801,-721 834,661,491 620,-847,-523 774,676,455 535,-509,628 --- scanner 3 --- -407,-676,-904 734,-560,435 -693,-416,552 399,882,-572 548,-513,-819 11,183,-89 519,898,-534 432,710,811 -700,739,637 -703,-449,648 -496,668,-411 -469,-604,-856 597,-462,-696 -524,606,-344 -738,-466,683 386,-489,-727 690,-596,610 -407,-650,-695 262,698,734 -151,184,58 -714,710,793 -666,720,602 340,878,-593 -655,577,-415 417,746,751 -173,51,-105 711,-649,610 --- scanner 4 --- -685,686,-551 -793,-850,-533 506,696,563 527,750,548 -601,581,-490 -402,-590,371 -841,-861,-490 800,-826,791 830,-666,749 892,-712,744 -418,-589,365 466,601,-889 -489,-491,464 679,-648,-544 -24,2,-135 496,548,551 765,-778,-494 745,-758,-567 -453,667,-530 -548,387,619 -512,447,634 -683,-770,-496 -560,464,789 468,575,-917 560,458,-901 --- scanner 5 --- 732,615,-695 -377,610,685 -495,-902,-457 -505,433,-576 759,628,545 -517,-805,-466 -580,496,-693 665,747,-728 857,-888,591 177,-41,-4 -459,-809,-623 -337,660,590 485,-555,-387 849,-900,646 -644,-838,551 -614,-772,389 785,-859,453 685,-519,-419 613,-405,-367 877,738,569 -460,592,573 -512,326,-661 726,794,-640 864,609,696 -542,-810,573 --- scanner 6 --- 368,683,-372 -857,-729,708 457,760,741 -3,99,-25 545,663,-382 480,897,862 -905,509,-355 -916,663,-479 -906,-735,758 422,-243,537 606,-464,-412 441,812,817 273,-327,570 -562,815,894 -798,-679,712 -905,559,-596 -540,877,853 -737,-434,-303 439,538,-369 -181,108,134 -679,818,855 -740,-438,-319 -794,-617,-290 695,-432,-474 369,-298,651 574,-454,-602 --- scanner 7 --- -709,-537,525 599,400,517 663,-549,-537 673,-739,-569 -701,443,-586 89,-29,-107 -634,281,431 -730,-492,-645 695,-611,-448 -777,425,-724 -105,-82,14 -788,-554,-704 496,-458,611 -731,-460,429 418,-461,417 -497,248,333 598,545,385 492,501,528 800,433,-870 -881,-561,-672 884,400,-721 829,514,-774 -642,294,266 362,-418,539 -731,-448,593 -760,531,-608 --- scanner 8 --- 868,710,-814 690,-331,685 565,-365,-644 -685,583,-647 -697,-418,-635 -349,-747,573 -493,633,703 586,-389,-600 773,450,395 -744,575,-732 9,-31,-170 -518,485,615 801,717,-874 784,-343,542 782,-315,568 -818,-396,-542 -517,527,665 729,413,317 -465,-739,603 -770,385,-662 88,113,15 584,-446,-536 -315,-721,499 -829,-468,-584 901,814,-873 680,344,371 --- scanner 9 --- -653,928,-587 346,683,280 358,723,474 480,663,-657 620,-449,-847 396,-500,338 590,-425,-711 -590,784,464 -363,-702,598 375,797,-631 433,643,397 -56,55,-65 -695,917,-515 -701,-485,-565 -575,869,266 -423,-769,591 -505,843,456 -364,-802,695 104,143,-139 369,-501,398 533,-477,408 595,-425,-951 -637,-487,-508 -602,796,-537 396,701,-702 -593,-466,-484 --- scanner 10 --- 756,-811,536 -758,-858,-662 739,715,624 806,663,-794 -652,507,398 667,-661,-781 743,656,645 725,-602,-719 756,812,-753 818,-634,-712 759,536,683 -107,-5,-89 -726,-769,-724 -601,458,521 803,740,-620 -628,669,490 -692,-753,567 -573,631,-846 39,-141,-38 -736,-737,-534 -756,574,-833 -795,-724,606 -638,-667,644 700,-905,601 -752,577,-817 719,-881,532 --- scanner 11 --- 613,-415,-869 445,-621,752 634,-608,-805 372,329,-516 -678,-535,350 -108,-6,-44 366,608,735 -754,574,571 -410,-728,-442 424,549,797 -754,814,576 391,305,-585 -477,-735,-382 -694,428,-720 423,-525,829 -377,-832,-383 273,576,728 -702,-545,514 -730,710,601 335,399,-520 619,-438,-850 -679,-475,377 -141,-123,113 423,-689,841 -692,371,-656 -713,347,-612 --- scanner 12 --- 505,-657,846 -749,-804,321 -402,829,-859 -697,-747,-878 -40,16,-16 6,-145,-110 -736,362,736 430,-544,830 -695,382,662 551,368,-797 396,305,-817 392,-594,853 -692,-755,-648 -659,-810,-829 326,-775,-453 674,256,394 -430,828,-824 -461,791,-808 601,418,407 -608,-913,341 390,-836,-416 378,-759,-593 478,378,-719 -664,-796,330 -723,300,759 719,347,368 --- scanner 13 --- -683,-433,912 -412,754,548 875,592,853 632,746,-671 -762,-449,-503 -404,724,432 644,598,-661 -786,-493,-482 -430,650,398 -808,693,-701 -755,-391,901 535,-511,-703 872,-418,739 -820,836,-607 -733,-484,780 629,544,-640 29,142,144 720,-392,823 86,15,19 -836,719,-699 776,-433,907 653,-628,-694 -705,-385,-501 785,426,889 588,-518,-740 907,419,813 --- scanner 14 --- 628,-598,-362 -516,-802,-652 686,-755,-366 -286,494,718 897,579,-580 -250,670,-377 -444,-854,-766 -349,-780,795 785,406,633 723,-849,884 165,-54,23 631,462,682 -370,-774,635 644,-742,800 551,427,609 760,-750,817 964,535,-476 -315,583,-430 -316,-834,-616 -258,493,644 664,-764,-269 -276,636,663 -421,632,-340 24,-5,137 -428,-673,723 854,601,-573 --- scanner 15 --- -749,785,-618 417,-330,-362 -443,-804,-604 -753,865,-519 375,468,-886 -761,-303,467 -680,-231,339 641,-312,702 586,758,698 410,496,-885 -534,-806,-420 -319,870,752 405,725,753 -389,795,893 437,-485,-425 515,-412,-435 40,131,60 -418,-812,-408 426,527,-848 -287,937,853 818,-324,779 781,-260,718 -788,804,-653 356,763,690 -78,-6,-26 -617,-318,414 --- scanner 16 --- -431,706,-288 -482,756,-420 756,435,-652 -431,-753,-293 -390,-697,-377 705,-334,838 421,-884,-387 -541,-560,789 -389,778,-299 -437,-612,830 133,-7,158 -480,-698,721 548,-356,897 654,534,888 726,427,-768 -526,459,526 636,632,763 45,93,2 538,505,792 682,-308,868 594,-852,-347 -428,368,530 652,453,-802 428,-762,-311 -632,372,515 -416,-849,-461 --- scanner 17 --- 613,752,-489 -669,-401,471 830,-871,458 465,-966,-607 633,-880,521 538,558,560 562,528,696 675,-828,415 -550,668,506 -638,-446,546 -459,-792,-782 543,-958,-703 -610,790,-625 -684,773,480 -19,-95,-128 614,779,-549 590,615,-559 -377,-719,-724 -530,715,-548 -637,-466,507 -570,802,-431 -588,752,551 538,553,800 -452,-883,-717 517,-832,-579 --- scanner 18 --- -652,609,-485 -553,629,-400 -797,-625,803 742,693,613 -747,-626,845 -87,12,81 -449,621,917 -835,-601,697 682,760,620 16,-138,21 337,-818,-760 -608,761,-388 483,615,-340 489,-772,-735 -527,665,880 -661,-558,-657 352,675,-367 515,-793,747 530,-878,945 -773,-582,-587 600,-852,755 -710,-428,-598 741,793,516 378,-876,-798 -503,572,986 299,530,-336 --- scanner 19 --- 544,633,786 -897,723,-366 428,527,803 378,616,-803 704,-509,-669 -817,-377,895 -731,-354,-663 -894,-551,892 566,545,727 282,535,-774 -789,677,-422 583,-637,-647 -653,827,834 480,-459,907 -848,673,-372 -23,-27,114 -966,-418,845 615,-447,-637 507,-390,756 -785,-325,-484 448,-452,814 -590,914,909 -120,107,-57 431,502,-858 -509,842,781 -728,-338,-667 --- scanner 20 --- 468,632,619 -457,496,524 186,-93,14 -220,695,-807 769,-571,-448 766,-674,566 647,638,564 774,-341,-456 936,-606,598 -249,-766,-428 -445,-529,681 -573,-584,726 515,571,531 806,404,-253 -313,-803,-367 -301,-626,-444 736,-390,-393 829,-599,683 881,334,-394 -292,776,-679 0,27,-3 -610,-564,710 -307,632,-732 -461,437,474 948,302,-293 -411,388,468 117,78,152 --- scanner 21 --- 826,-509,-542 -398,-562,-530 51,60,-92 -421,734,361 -319,-733,428 808,-359,-646 -349,-606,427 752,461,756 775,527,646 -546,-537,-442 795,-572,422 834,-393,-572 -257,636,-774 -326,685,-828 -365,849,387 418,646,-460 825,441,776 -294,-548,435 -363,729,-750 879,-444,392 145,-98,74 849,-457,429 -440,-561,-480 -453,767,334 430,740,-603 402,738,-577 --- scanner 22 --- -308,534,801 -633,-448,-329 -861,475,-605 345,-401,879 482,-523,877 -598,-646,511 -612,-389,-333 675,430,949 -7,103,77 -481,-528,520 877,402,-744 -671,-568,-313 898,564,-789 505,-336,806 670,428,929 -591,-593,474 765,-292,-316 842,447,-767 -790,606,-634 632,-364,-269 782,481,847 -312,600,807 -794,447,-543 806,-441,-266 -323,526,614 --- scanner 23 --- 496,-729,710 825,723,-386 -613,-891,470 557,406,738 -33,-165,-85 -666,-651,-848 -813,321,308 -751,428,-367 -644,-658,-805 -710,-755,-915 -814,466,-416 824,695,-421 -914,254,276 758,-857,-383 533,-814,583 -173,-2,-88 -575,-854,299 -759,433,-597 578,-771,-404 -662,-801,364 787,664,-437 579,-920,-389 592,387,777 -954,396,378 458,326,742 479,-829,713 --- scanner 24 --- -369,-585,-682 -848,-535,620 -359,838,803 -367,813,607 532,547,-468 585,-256,525 652,908,492 590,-496,525 -796,-641,662 -434,-549,-650 -414,-510,-651 515,434,-573 -24,114,10 502,387,-427 805,-576,-697 560,-360,549 812,843,419 -365,722,791 675,721,421 700,-550,-563 -839,-598,817 -620,728,-861 784,-505,-601 -579,729,-733 -686,686,-703 --- scanner 25 --- -634,465,-978 836,-736,352 -114,-56,-6 -557,844,715 443,386,-469 784,-720,492 684,417,618 772,-797,315 -355,-849,743 770,-555,-954 -641,-533,-791 657,-618,-947 766,344,716 -681,-571,-903 23,49,-124 488,295,-495 -334,-894,581 -736,-561,-685 732,-505,-931 -601,313,-932 -565,523,-890 -390,-872,698 -562,824,717 -450,742,664 561,457,-508 611,407,696 --- scanner 26 --- -634,-845,-463 709,-612,-774 747,568,-391 779,368,-427 700,-634,-677 -638,367,-613 -549,-364,616 473,-697,624 526,609,922 -487,311,509 -346,381,584 -38,59,151 590,-622,561 505,-629,454 471,615,743 799,496,-277 543,-576,-681 438,548,875 -541,-594,621 14,-42,-3 -725,302,-666 -386,279,442 -687,473,-703 -486,-413,654 -656,-802,-470 -590,-912,-567 --- scanner 27 --- 942,-325,-622 653,572,551 852,-309,-551 -496,443,-571 562,392,-533 406,-302,686 -44,118,134 -492,627,839 73,75,-10 822,-297,-709 435,582,606 -775,-518,-455 -479,664,944 -648,443,-676 547,544,646 -400,-520,429 -503,375,-727 626,414,-598 -605,-531,-394 -492,620,722 360,-454,653 -689,-603,-505 448,-512,722 559,418,-683 -461,-522,488 -256,-497,436 --- scanner 28 --- 632,274,-680 367,-616,715 32,-122,-3 -833,742,839 808,-415,-420 838,541,794 834,632,635 -854,787,677 697,296,-616 -623,-630,-794 -547,426,-695 352,-803,707 -452,454,-589 905,603,766 -631,-951,811 -798,765,794 -587,-420,-836 -626,-931,813 356,-809,641 -554,-572,-882 -507,464,-807 721,-443,-300 650,-427,-390 -738,-849,760 782,300,-683 --- scanner 29 --- 650,-462,893 -474,-732,-757 696,-400,888 408,486,-380 632,-613,-400 762,-527,-350 -766,-765,692 -712,-786,707 -564,-796,695 44,-15,-7 -617,-826,-745 616,563,781 -556,423,-349 378,358,-296 810,-492,935 742,-547,-423 -660,273,-367 -586,307,-341 415,371,-326 -884,764,848 -591,-824,-773 -718,728,938 -91,-120,132 782,510,743 -891,688,970 706,715,738 --- scanner 30 --- -413,599,524 -666,-613,-524 767,-832,-734 -675,-495,-641 65,-17,-99 929,795,-761 809,679,309 -307,-740,302 675,653,414 -5,49,68 580,-444,582 -454,826,-659 539,-284,612 -475,802,-703 940,723,-719 -380,-805,462 685,-331,599 -712,-548,-634 -309,-618,439 851,-680,-760 -437,463,554 808,773,-668 -413,359,529 713,608,330 -473,745,-767 935,-736,-719 --- scanner 31 --- 600,-425,411 -761,-790,-561 -437,353,-479 854,339,-706 -738,-719,-374 273,-408,-444 761,779,792 -573,-842,390 281,-604,-469 -898,-792,-439 -478,403,-330 773,702,615 767,414,-643 -401,854,409 782,467,-787 -345,876,526 755,-362,391 -611,356,-402 673,-435,489 825,718,755 -461,-760,443 -366,831,364 -40,-18,45 279,-420,-560 -568,-862,392 --- scanner 32 --- 375,548,-471 -561,629,-647 520,522,-443 -635,-398,564 424,-582,-461 -303,-450,-754 450,503,-445 585,584,438 -502,810,505 -492,619,553 -544,-394,723 -473,654,519 105,-30,-137 806,-876,570 -3,-96,14 613,-865,644 800,-880,636 -522,534,-587 707,450,420 412,-424,-491 -277,-600,-751 -299,-535,-687 -516,573,-732 -606,-327,695 686,602,480 440,-511,-371 --- scanner 33 --- -772,-465,-547 -457,472,-525 -752,565,511 908,-813,712 681,286,606 -743,628,314 -563,588,-542 118,45,-42 447,-773,-433 -271,-783,524 23,-105,-104 656,390,582 -263,-808,328 748,-878,639 -475,610,-601 621,-850,-436 771,-691,710 -700,671,469 -844,-546,-419 529,524,-421 -757,-609,-494 -269,-692,340 522,492,-514 686,526,606 460,551,-572 488,-922,-483 --- scanner 34 --- 528,907,-644 219,-657,839 -670,-313,-652 677,-838,-586 -39,71,118 652,576,852 358,-618,879 -573,428,-654 -727,725,447 -676,-436,739 720,513,703 625,-704,-614 -595,505,-558 731,625,767 -595,822,433 -597,-481,743 281,-683,880 -726,872,547 529,880,-704 -807,-280,-750 552,743,-634 -573,416,-490 599,-830,-490 -662,-326,-817 -612,-453,767 --- scanner 35 --- -663,869,837 930,-557,831 -393,792,-453 499,-533,-282 -480,-609,-256 -741,906,793 421,779,875 448,811,842 -687,975,744 474,867,957 515,913,-625 577,-545,-247 -443,834,-454 -582,-399,933 61,29,150 -355,686,-429 -538,-496,781 -417,-598,-410 -18,124,10 485,-532,-307 514,883,-498 853,-608,733 -637,-411,801 -529,-668,-386 522,938,-440 956,-549,611 ================================================ FILE: exm/aoc/2021/aoc_2021_19_questions.txt ================================================ --- Day 19: Beacon Scanner --- As your probe drifted down through this area, it released an assortment of beacons and scanners into the water. It's difficult to navigate in the pitch black open waters of the ocean trench, but if you can build a map of the trench using data from the scanners, you should be able to safely reach the bottom. The beacons and scanners float motionless in the water; they're designed to maintain the same position for long periods of time. Each scanner is capable of detecting all beacons in a large cube centered on the scanner; beacons that are at most 1000 units away from the scanner in each of the three axes (x, y, and z) have their precise position determined relative to the scanner. However, scanners cannot detect other scanners. The submarine has automatically summarized the relative positions of beacons detected by each scanner (your puzzle input). For example, if a scanner is at x,y,z coordinates 500,0,-500 and there are beacons at -500,1000,-1500 and 1501,0,-500, the scanner could report that the first beacon is at -1000,1000,-1000 (relative to the scanner) but would not detect the second beacon at all. Unfortunately, while each scanner can report the positions of all detected beacons relative to itself, the scanners do not know their own position. You'll need to determine the positions of the beacons and scanners yourself. The scanners and beacons map a single contiguous 3d region. This region can be reconstructed by finding pairs of scanners that have overlapping detection regions such that there are at least 12 beacons that both scanners detect within the overlap. By establishing 12 common beacons, you can precisely determine where the scanners are relative to each other, allowing you to reconstruct the beacon map one scanner at a time. For a moment, consider only two dimensions. Suppose you have the following scanner reports: --- scanner 0 --- 0,2 4,1 3,3 --- scanner 1 --- -1,-1 -5,0 -2,1 Drawing x increasing rightward, y increasing upward, scanners as S, and beacons as B, scanner 0 detects this: ...B. B.... ....B S.... Scanner 1 detects this: ...B.. B....S ....B. For this example, assume scanners only need 3 overlapping beacons. Then, the beacons visible to both scanners overlap to produce the following complete map: ...B.. B....S ....B. S..... Unfortunately, there's a second problem: the scanners also don't know their rotation or facing direction. Due to magnetic alignment, each scanner is rotated some integer number of 90-degree turns around all of the x, y, and z axes. That is, one scanner might call a direction positive x, while another scanner might call that direction negative y. Or, two scanners might agree on which direction is positive x, but one scanner might be upside-down from the perspective of the other scanner. In total, each scanner could be in any of 24 different orientations: facing positive or negative x, y, or z, and considering any of four directions "up" from that facing. For example, here is an arrangement of beacons as seen from a scanner in the same position but in different orientations: --- scanner 0 --- -1,-1,1 -2,-2,2 -3,-3,3 -2,-3,1 5,6,-4 8,0,7 --- scanner 0 --- 1,-1,1 2,-2,2 3,-3,3 2,-1,3 -5,4,-6 -8,-7,0 --- scanner 0 --- -1,-1,-1 -2,-2,-2 -3,-3,-3 -1,-3,-2 4,6,5 -7,0,8 --- scanner 0 --- 1,1,-1 2,2,-2 3,3,-3 1,3,-2 -4,-6,5 7,0,8 --- scanner 0 --- 1,1,1 2,2,2 3,3,3 3,1,2 -6,-4,-5 0,7,-8 By finding pairs of scanners that both see at least 12 of the same beacons, you can assemble the entire map. For example, consider the following report: --- scanner 0 --- 404,-588,-901 528,-643,409 -838,591,734 390,-675,-793 -537,-823,-458 -485,-357,347 -345,-311,381 -661,-816,-575 -876,649,763 -618,-824,-621 553,345,-567 474,580,667 -447,-329,318 -584,868,-557 544,-627,-890 564,392,-477 455,729,728 -892,524,684 -689,845,-530 423,-701,434 7,-33,-71 630,319,-379 443,580,662 -789,900,-551 459,-707,401 --- scanner 1 --- 686,422,578 605,423,415 515,917,-361 -336,658,858 95,138,22 -476,619,847 -340,-569,-846 567,-361,727 -460,603,-452 669,-402,600 729,430,532 -500,-761,534 -322,571,750 -466,-666,-811 -429,-592,574 -355,545,-477 703,-491,-529 -328,-685,520 413,935,-424 -391,539,-444 586,-435,557 -364,-763,-893 807,-499,-711 755,-354,-619 553,889,-390 --- scanner 2 --- 649,640,665 682,-795,504 -784,533,-524 -644,584,-595 -588,-843,648 -30,6,44 -674,560,763 500,723,-460 609,671,-379 -555,-800,653 -675,-892,-343 697,-426,-610 578,704,681 493,664,-388 -671,-858,530 -667,343,800 571,-461,-707 -138,-166,112 -889,563,-600 646,-828,498 640,759,510 -630,509,768 -681,-892,-333 673,-379,-804 -742,-814,-386 577,-820,562 --- scanner 3 --- -589,542,597 605,-692,669 -500,565,-823 -660,373,557 -458,-679,-417 -488,449,543 -626,468,-788 338,-750,-386 528,-832,-391 562,-778,733 -938,-730,414 543,643,-506 -524,371,-870 407,773,750 -104,29,83 378,-903,-323 -778,-728,485 426,699,580 -438,-605,-362 -469,-447,-387 509,732,623 647,635,-688 -868,-804,481 614,-800,639 595,780,-596 --- scanner 4 --- 727,592,562 -293,-554,779 441,611,-461 -714,465,-776 -743,427,-804 -660,-479,-426 832,-632,460 927,-485,-438 408,393,-506 466,436,-512 110,16,151 -258,-428,682 -393,719,612 -211,-452,876 808,-476,-593 -575,615,604 -485,667,467 -680,325,-822 -627,-443,-432 872,-547,-609 833,512,582 807,604,487 839,-516,451 891,-625,532 -652,-548,-490 30,-46,-14 Because all coordinates are relative, in this example, all "absolute" positions will be expressed relative to scanner 0 (using the orientation of scanner 0 and as if scanner 0 is at coordinates 0,0,0). Scanners 0 and 1 have overlapping detection cubes; the 12 beacons they both detect (relative to scanner 0) are at the following coordinates: -618,-824,-621 -537,-823,-458 -447,-329,318 404,-588,-901 544,-627,-890 528,-643,409 -661,-816,-575 390,-675,-793 423,-701,434 -345,-311,381 459,-707,401 -485,-357,347 These same 12 beacons (in the same order) but from the perspective of scanner 1 are: 686,422,578 605,423,415 515,917,-361 -336,658,858 -476,619,847 -460,603,-452 729,430,532 -322,571,750 -355,545,-477 413,935,-424 -391,539,-444 553,889,-390 Because of this, scanner 1 must be at 68,-1246,-43 (relative to scanner 0). Scanner 4 overlaps with scanner 1; the 12 beacons they both detect (relative to scanner 0) are: 459,-707,401 -739,-1745,668 -485,-357,347 432,-2009,850 528,-643,409 423,-701,434 -345,-311,381 408,-1815,803 534,-1912,768 -687,-1600,576 -447,-329,318 -635,-1737,486 So, scanner 4 is at -20,-1133,1061 (relative to scanner 0). Following this process, scanner 2 must be at 1105,-1205,1229 (relative to scanner 0) and scanner 3 must be at -92,-2380,-20 (relative to scanner 0). The full list of beacons (relative to scanner 0) is: -892,524,684 -876,649,763 -838,591,734 -789,900,-551 -739,-1745,668 -706,-3180,-659 -697,-3072,-689 -689,845,-530 -687,-1600,576 -661,-816,-575 -654,-3158,-753 -635,-1737,486 -631,-672,1502 -624,-1620,1868 -620,-3212,371 -618,-824,-621 -612,-1695,1788 -601,-1648,-643 -584,868,-557 -537,-823,-458 -532,-1715,1894 -518,-1681,-600 -499,-1607,-770 -485,-357,347 -470,-3283,303 -456,-621,1527 -447,-329,318 -430,-3130,366 -413,-627,1469 -345,-311,381 -36,-1284,1171 -27,-1108,-65 7,-33,-71 12,-2351,-103 26,-1119,1091 346,-2985,342 366,-3059,397 377,-2827,367 390,-675,-793 396,-1931,-563 404,-588,-901 408,-1815,803 423,-701,434 432,-2009,850 443,580,662 455,729,728 456,-540,1869 459,-707,401 465,-695,1988 474,580,667 496,-1584,1900 497,-1838,-617 527,-524,1933 528,-643,409 534,-1912,768 544,-627,-890 553,345,-567 564,392,-477 568,-2007,-577 605,-1665,1952 612,-1593,1893 630,319,-379 686,-3108,-505 776,-3184,-501 846,-3110,-434 1135,-1161,1235 1243,-1093,1063 1660,-552,429 1693,-557,386 1735,-437,1738 1749,-1800,1813 1772,-405,1572 1776,-675,371 1779,-442,1789 1780,-1548,337 1786,-1538,337 1847,-1591,415 1889,-1729,1762 1994,-1805,1792 In total, there are 79 beacons. Assemble the full map of beacons. How many beacons are there? --- Part Two --- Sometimes, it's a good idea to appreciate just how big the ocean is. Using the Manhattan distance, how far apart do the scanners get? In the above example, scanners 2 (1105,-1205,1229) and 3 (-92,-2380,-20) are the largest Manhattan distance apart. In total, they are 1197 + 1175 + 1249 = 3621 units apart. What is the largest Manhattan distance between any two scanners? ================================================ FILE: exm/aoc/2021/aoc_2021_20.adb ================================================ -- Solution to Advent of Code 2021, Day 20 ------------------------------------------- -- Trench Map -- -- A Game-of-life puzzle! -- -- https://adventofcode.com/2021/day/20 -- Copy of questions in: aoc_2021_20_questions.txt -- -- Note: this programs takes very long on HAC! -- -- HAC 0.098 "nice to have"'s detected in this exercise: -- -- * Detect an expression as a static (compile-time-known) value -- -> Good for arithmetic in number declaration -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . procedure AoC_2021_20 is use HAT; iter_max : constant := 50; -- margin : constant := 101; -- "full Ada": iter_max * 2 + 1 map_min : constant := -101; -- "full Ada": -margin -- input : constant VString := +"mini.txt"; data_max : constant := 4; input : constant VString := +"aoc_2021_20.txt"; data_max : constant := 99; map_max : constant := 200; -- "full Ada": data_max + margin iea_max : constant := 511; subtype Bit is Integer range 0 .. 1; iea : array (0 .. iea_max) of Bit; type Map_Type is array (map_min .. map_max, map_min .. map_max) of Bit; map : array (0 .. 1) of Map_Type; cur_map : Natural := 0; procedure Read_Data is -- c : Character; s : VString; f : File_Type; begin Open (f, input); Get_Line (f, s); for i in 0 .. iea_max loop if Element (s, i + 1) = '#' then iea (i) := 1; else iea (i) := 0; end if; end loop; Skip_Line (f); for y in map_min .. map_max loop for x in map_min .. map_max loop map (0)(x, y) := 0; map (1)(x, y) := 0; if x in 0 .. data_max and then y in 0 .. data_max then Get (f, c); if c = '#' then map (cur_map)(x, y) := 1; end if; end if; end loop; end loop; Close (f); end Read_Data; procedure Show_Map (extension : Natural) is begin for y in -extension .. data_max + extension loop for x in -extension .. data_max + extension loop if map (cur_map)(x, y) = 1 then Put ('#'); else Put ('.'); end if; end loop; New_Line; end loop; New_Line; end Show_Map; procedure Enhance is code : Natural; new_map : constant Natural := 1 - cur_map; begin for y in map_min + 1 .. map_max - 1 loop for x in map_min + 1 .. map_max - 1 loop code := 0; for yy in -1 .. 1 loop for xx in -1 .. 1 loop code := code * 2 + map (cur_map)(x + xx, y + yy); end loop; end loop; map (new_map)(x, y) := iea (code); end loop; end loop; cur_map := new_map; end Enhance; function Count (extension : Natural) return Natural is total : Natural := 0; begin for y in -extension .. data_max + extension loop for x in -extension .. data_max + extension loop total := total + map (cur_map)(x, y); end loop; end loop; return total; end Count; r : array (1 .. 2) of Integer; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := False; T0 : constant Time := Clock; begin Read_Data; if verbose then Show_Map (0); end if; for iteration in 1 .. iter_max loop Enhance; case iteration is when 2 => r (1) := Count (2); when 50 => r (2) := Count (50); when others => null; end case; if verbose then Show_Map (iteration); end if; end loop; if verbose then Show_Map (iter_max); end if; if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: pixels after 2 iterations : " & r (1)); Put_Line (+"Part 2: pixels after 50 iterations: " & r (2)); -- Part 1: validated by AoC: 5306 -- Part 2: validated by AoC: 17497 end if; end AoC_2021_20; ================================================ FILE: exm/aoc/2021/aoc_2021_20.txt ================================================ #.#.##...###......#.##..#..##....#.#.##...#..###....##...#####.#...#.#.#...#..###..#...#......####..#.#..########.#.###......##.##...###.###..######.....####.#..#.#..##..###..####..#....####..######.###..###.........##.##.###......##...#####.######..#.....##..#..#...#.#...#..#..#.#..#..#.##..#####..##.###.####...#..#....##....####...#.#.#.#.#.###...##..#....##......####.##.###...#####..##..#.#...#..#.#..####.###..###..#..####....#.#.##.#..#...#.#...##...#..#.#.##...##..##.####..#...###.#...#####.######..... ...#.#...####.##.####.#...#..##.###..##...###..#.#.#.#...##....#####..#...##.#.##.#.#.....###.#....# .##.####......##.#.#..#.#.#.#.##....#..##...###.#..#..#.##...##.#..##.###.#......###....#..##.###..# ####.#.####...#.#.#.#....#...#.##..###.#####..#...#.#..#.#.#.####...##.##..#.#.#..##.########..###.. .####......#.##.##.##.#.#.....##..#.##....#######.##..##.####.#..#.#.#.#.#.###.#..#......#.#.#..###. ..#.#.####..#.#.#....##....#...######..##......#.......###.#..###.#.#.#.#.###.##..#.####.....#.##.#. .#..##..#####.....#....#.#.#..###..#.###.#.###.##..##.#.###...#.##....##...#.###.#.##....#...###..## .#.##.####.##.##..#..#.##..##.##..##..#.##..#.######..####.##.#.##....##..#.##.####.##...####....##. ##..#.#####.#.#.#..#...#...#.....##.#...#.##.#.#.#.#.....##...#.#.....##..##..###.#.####..#...##...# ##..#.#.##.####....##.#.#..#.#.#.###.#.#..#.#.....#..##.##.#.#...##....##.########.#..#.....##...### ######......#..#.#.####.#.###.#################.##..#.###.##.#...#..###.##..##..##..#..#.##..#.##.## ...##.#.###.........#...#...##.###...######..#.#...#........##.#...###.###.###...#...#.......#####.# .#....##...##.#.#.##.#..########.#..#..#..#.##.##..###.##.#..##.#.#.#....#..##...###..###.##.#.##.## .##.......##.#.#...#.##.##..#.#...#..####.#....###..#.#.....#.###....#...#.##.....#..#...##.##...### ..###.#..##..#....#...#.#.##.##.#.#.#.##.###.#####..###....#......##.....##..#..####.#....#####.#... #...#.##.#.#.#...#####.#..##.######......##.#.#.#..#..#.##.######..#.##...##.##.##..#.#....##.###..# ##.##.##..#.##.########.##..##.##..####..#...####.######.####..####.#.#.#.#..#.##....#.##.#..#..###. #..#####.##..#.###.#.##.##.###....###.#..#.####..##...#...###.#..#.....##...#..####.#...###.#.####.. ....#.#####..##.###..#..#.....##..##.#...#.#..##.##.#.##..##....#.##..##..###...##.#..#.#.###..#..#. .#########..####.###...#.##.#.##..###....##.#..#...##....#.####.#..#.###.#.###....#......#...#.##.#. .#######....####..##..#..#....#..#.####........#.##.#..##.######.#.###.###.###..##..####...##..#.##. .#....###.####.###..#..##......##.##.##...#..##...##.####..##....######..####.#..##..#######.#.#...# .#.####..########.#.#.######...##.###...#.....#...###....###..####.........#.###.#.....#.###.##..##. ...#.#.#..#.###..###.##.#.#.##...#..####.#..#.#...#....##.##.###.####.###...##..#.#......##..#...... .#...######.#.##....##.##.##.....#...#.#.#######.#.#..###.#.#...##...#....#.#...#...#...##.###.###.. .#...#..##.##.###.....##..#.###..####.##.########...#.##.....####...##...#.#..#....#...##.#.#..####. ..##...##.#..####...#.#...##.##..##..##..##..#..#...##..#..###.#..###..#..#....#..##....##...######. ##..###...##...##.#.#######..#.#.#..#...#.#..#..#....###..#.#####.##.#...##..#.....#..##.###..#.##.. ###.#.#..##.#.####..######....#.#.##....###.##.#.##..###.#.#...#..#####....#########...##..#....#.## #..#####.....##.#.#.###.#.#.......####..#.##.#.####.#..#...#...#.#.###.######.##..##..#.......####.. ...#####..#.####.#..##.####.#####...#.#...#####.##.##..#..#...##.###..#.#.###.#....#..##..###.##.#.# .##..#.##...##..#.#.##.#.#...#..####..#......##.###.#.##.#.#....####..#..#.####..###..#..#.#.###.#.# #.#####..#.###.#.#.###.#.#...#.#....###.#..#.####...#####.#..##...##......###.##..#.###.#..####.#.#. #..#......###...#.#...###....###.#####....#.#.###.##.#.#...##.....#.#####................#.###..#..# #....##....#.#..####..#.##.####.###.###..####.##.....###.##.##...#..#...#.###...#####......#...#.... ##.#..#.##..##..##.#.#.#.#.##.######.#..#.#..###.#....#...#.#.#.#.....#....##..##....####..#.##..### .##..#.#.####...##...#.######.....#.#...#####...##########.....##.###..#..######..#.#.....##..###..# ####..#.#...#...###.#####.##.#...#####..#.....#.#####.##..#.##.#.#.###.#...#.#.#####.......##.####.# ...###.##..###.#.#.#..##..#####......#####..#..##.##.....####..###...#...#####.....#.#....###...#.#. ..#..#.#.....##.#.#...#.......##.###.....###..#####.#####.#..###..###..#..#.#.#.#..###.#.###..#.#.## ####..#.##.##...#.#.#.##.#.#.#..#..#####..##.#.####.#..#######.####.#....#..###.##.#...##...###.#.#. ..#...#..#...#.####.##..##..#######.#.##.####.#..#......#.#.###.##.#..#.#.....##....#.#.#.#.##.###.# .###..###.#...##..#....#.#..##..#.###.#...##.######.####.###.#..##..###.##.#.#....#.#...#...###.##.# #....#.#....#..#####..##..#.##.#.#..##.##.#.....#.##..##..##........#.##...##.#.#..##.#.#..###....#. ##...#......#.#.#.#......#..#.#..#######...#.####..#...###..#...#..#...####..#.#.##....#...##..#.... .####...##..###.##....#.#..#...#.##.#.##.#####.####.....#...#..#..#..##.#..####.#.#..###....##...#.# #..####.#.#.######.####.#..#####..#.####...#.#.#.##..##..#.##.#.#.##.#..#..##.###.#.#..#.##..####.## .#.###.....###....#...#..#.#####..#####..###..#..#...##...#.###..#..#.##..#..####..##..##########... .#.....##..#.#.##...#...#.#.#.#.#..#.###...##.#.####.....#....#.....#.#.####..###.#######..#..##.#.. ....##...#...####..###.##.#.#.#...##.##...####..##..###..#.#.######.##.....#............#.######.#.. ..#....#....#..##.....#.#.##....###.##..###.#####...#....#.#.#....##.#.#.#.#.....#.#.....##...#.#.#. .##...#.#.##.######..#.####..######.##.....##.##..##....#...#..##.#..#....#.##...#....#.##...##.#.## #...#.#...##.#.##.##..#..####.#...###.#...##.##....#.#..##.......##....####...#...#.......#....####. .#.##..###.##.##...##.#..##.###.#.#.#####.#.###...#.##....#...#..##..###..#..##.##.#..##.#.#....##.. ###.##.##..##.#.###.#...###.#..#.#.####..###.##.##..###.#####...##.....####.#.##.###..####.#..#.#.## #....#.#.##...##.#...#......#####..###.#.##..#.####..##..#..##..###...###.#.#.##.##..####.###.....#. #.##..#...#.#..##..##..#..###..##.#.###....#.#.####.##.##.###.#..#.##...#.###.##.#...#.#.##...#..... #......#......#.#.#.######.##.#.###.###..#..####...##.#.######..#.....###..#.....#########.#####.##. .#.#.#.##.#.###...#..#.##...#...##.#####.###..####.##..........####..#.#####.####..#.##.#####..###.. ...##.###.#.####.###.#.#.#.##...#####.#.......##.##...####.#..###....###.#..###..#.#####..#.###..#.. #.#....#....###.###..##.##.##.##.#..###.##.....#.##.###...#.###....###.####...#.####...#.###.#.##### ##....#..#......##.###.....##.###.##..##.#.##...#..#.##.##.##..##.#...#...#...#.#.#.#.##.###.....### .###..##.#....#..###..#.#.#..####.#.#.#.##.#...###.#.##....##..###.....#.##.....#......###.####..#.. .....##.#...#####.#..###....#.#.#.#..##.###.#########.#.##..##.#.#.####..##..##..##.#..#.....#.#.#.. #.####.#....##..#########...#.####..#.......#....##.#...##.#.##.##...#.#.#...#..###.#.#..#####.##..# ..#####...#.#.###......#....#...###...##.##...##.#..##.#.#..##.##.###.#....##.##...#####.......####. #..##.###.....#...#.#.###.####..###.#....#..#...###.##.....#.##..##..###..##.##.###..#.#..#..#...#.. ##.###.....##.....##.#######.#.##....###.####.....#..##.#.###.#.#......##..####.#.####.##.#.##...### ###..#..######..#.#.#...##..#.#...####...##........####....#...#..#########.#.###.##.##.#####...##.. ..#####.#.####...#.######.#..#.#.#.#....#...#.###...###.###..#...##..##..#####..#####.###..#.#.#.##. ##.#..###..###.#.......##..####..######.#..#.####.##....#####.#.#.###.#..###..########..####..#..#.. ##.#.####....#.#.##..#..#..######.#..##.#.##..###.#..#.#....#.##...#.##.####...####.....##.##.##..## ####..##....#..#.#.#.....#..#...#.#...#..###...##.#.###.#...#.##..##..###..###....#..########.#....# ##..#...#.#.....#####..##..##....#......##.#.#...#..#####....##..#.##.........#.#.##...#.#.#..#.#.#. ##...###..#.###...###.###.##...##.#.##...#...####..#.#.#.###...######......##..###.....#..#.##...#.# #.#....#.####.##.#.#.#.##..#.##.......#..##..#..##.##.##.#..##..#.##.#.#####.......#####..#........# .#.#..###..#....#.#.....#.##..#....#..##..##..##.#....###..#.######.#.#...#..###......####....####.. .#...###.....#...#....#.##.##.#........####.####..#....#..#....#.#.#..#.#.##.#.######.#...###.##.### ...#.#.#..##.#..#.##.#.#.##.##...##....###.....#####...#.#..#.##.#.####..##..#..#....#.##.##.##..##. ####....###..#..####.##.#..##.#..##.#.......###..#.##....#..#####.##..##.#...####..#.#..#.#.####...# .#..###....#..#####.##..##...#.#...#.##.#..#....#.#.##.#.#.......#.#....#...#....#...#...#..##.#.... #.#...####.#.##..###..#.##.##.#.##.#..##.#.##.###..#.###.#..##.#..#..#.#.####.#.###.##..#..#....##.. .....#...#.####.#..##..#######.#.#.#...#.#####.#.#...#...####.....###.###.##..##..#..#..#.#..######. #..#.#.####..###.###..#.##...##..###.##.###..#.####.#####.....###..###..#.#...#.#.########.#.##..##. ####..###..#...###.#.##.#.###..#.#...##.##....#####......###..##....###..#.#.#..##..######..####.#.. ...#....##.###..#.##.##..##..#.#.##.##...######....#....##.#.#.#.##.#...####...##...#.####.#.#.##.#. ...##...#.##..###.###...#.#.#.#.##.####...#.###..####..#...###.....#....####..##.#..##......#..#.#.. .#.#..#.....#.#.###....#.###.#..#..###...#.#####....#.....###.#..###.##.#..#...#.####..#.###.####... .####..#..##....#.##.##.#...#.###....#....#.##..#...#...##...#...###....###.##.#..#.###.#.##.#..###. ##.###.#...#.....#.#.#......#.##..#.#.##.##...###...#.###.####..###..#..###.#..#.#...#...#......##.. ######...##.##..#...##.#.###.#.####.#.##.##...###.#.#.....###.##.##....##.##....##.##.#..##..#.##### #...#..#...####.#.###.##...#...#..##.#..##.....##.#..#.#..#....##.##..##..#..#.###..###.#......#..## .##.##.######..#.##....#...#.....#.#.###....######..#.#..##.###......##.#..#.#.####..#...###.###.#.# ..#.#...##.#.....######.....####...##.###.#..#..#..######....###.....##...###..#.#####.#..##.###.### ###........#.##..##.........#.##.....#..#.####.##...........###...#.#.###..###..#..###...#......#### #...#.......#.##.#.#.##.#.#.##.#.#..#...##..#..#####.#.##.##.#####.####...#..##.#.###...#..##..##... ..#......#..#####.....#.##.....#..#..#####..#.....###..##.####.###...#####.#...##.#..#.......#.....# ###..#.#.###.#.#..##..##..##...#.#........#...#...#.#.#..#.##.##.....#.##.###############.##...#.#.. .#.#....#..##.......#........#..#...#.#.##.#...##.#.#.#.#.#..##...#.####.##.#.#...#...##.##########. .######.##.........#.########....#.######....##.##.#..####.###.##.#..##..##..####.#...#####...##.#.# ...#..#.#..#.#..#.#.#########.#..##.#.#.#.#.#########....#...####...#.#..#.......#.##....####....### ================================================ FILE: exm/aoc/2021/aoc_2021_20_questions.txt ================================================ --- Day 20: Trench Map --- With the scanners fully deployed, you turn their attention to mapping the floor of the ocean trench. When you get back the image from the scanners, it seems to just be random noise. Perhaps you can combine an image enhancement algorithm and the input image (your puzzle input) to clean it up a little. For example: ..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..## #..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.### .######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#. .#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#..... .#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.. ...####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#..... ..##..####..#...#.#.#...##..#.#..###..#####........#..####......#..# #..#. #.... ##..# ..#.. ..### The first section is the image enhancement algorithm. It is normally given on a single line, but it has been wrapped to multiple lines in this example for legibility. The second section is the input image, a two-dimensional grid of light pixels (#) and dark pixels (.). The image enhancement algorithm describes how to enhance an image by simultaneously converting all pixels in the input image into an output image. Each pixel of the output image is determined by looking at a 3x3 square of pixels centered on the corresponding input image pixel. So, to determine the value of the pixel at (5,10) in the output image, nine pixels from the input image need to be considered: (4,9), (4,10), (4,11), (5,9), (5,10), (5,11), (6,9), (6,10), and (6,11). These nine input pixels are combined into a single binary number that is used as an index in the image enhancement algorithm string. For example, to determine the output pixel that corresponds to the very middle pixel of the input image, the nine pixels marked by [...] would need to be considered: # . . # . #[. . .]. #[# . .]# .[. # .]. . . # # # Starting from the top-left and reading across each row, these pixels are ..., then #.., then .#.; combining these forms ...#...#.. By turning dark pixels (.) into 0 and light pixels (#) into 1, the binary number 000100010 can be formed, which is 34 in decimal. The image enhancement algorithm string is exactly 512 characters long, enough to match every possible 9-bit binary number. The first few characters of the string (numbered starting from zero) are as follows: 0 10 20 30 34 40 50 60 70 | | | | | | | | | ..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..## In the middle of this first group of characters, the character at index 34 can be found: #. So, the output pixel in the center of the output image should be #, a light pixel. This process can then be repeated to calculate every pixel of the output image. Through advances in imaging technology, the images being operated on here are infinite in size. Every pixel of the infinite output image needs to be calculated exactly based on the relevant pixels of the input image. The small input image you have is only a small region of the actual infinite input image; the rest of the input image consists of dark pixels (.). For the purposes of the example, to save on space, only a portion of the infinite-sized input and output images will be shown. The starting input image, therefore, looks something like this, with more dark pixels (.) extending forever in every direction not shown here: ............... ............... ............... ............... ............... .....#..#...... .....#......... .....##..#..... .......#....... .......###..... ............... ............... ............... ............... ............... By applying the image enhancement algorithm to every pixel simultaneously, the following output image can be obtained: ............... ............... ............... ............... .....##.##..... ....#..#.#..... ....##.#..#.... ....####..#.... .....#..##..... ......##..#.... .......#.#..... ............... ............... ............... ............... Through further advances in imaging technology, the above output image can also be used as an input image! This allows it to be enhanced a second time: ............... ............... ............... ..........#.... ....#..#.#..... ...#.#...###... ...#...##.#.... ...#.....#.#... ....#.#####.... .....#.#####... ......##.##.... .......###..... ............... ............... ............... Truly incredible - now the small details are really starting to come through. After enhancing the original input image twice, 35 pixels are lit. Start with the original input image and apply the image enhancement algorithm twice, being careful to account for the infinite size of the images. How many pixels are lit in the resulting image? --- Part Two --- You still can't quite make out the details in the image. Maybe you just didn't enhance it enough. If you enhance the starting input image in the above example a total of 50 times, 3351 pixels are lit in the final output image. Start again with the original input image and apply the image enhancement algorithm 50 times. How many pixels are lit in the resulting image? ================================================ FILE: exm/aoc/2021/aoc_2021_21.adb ================================================ -- Solution to Advent of Code 2021, Day 21 ------------------------------------------- -- Dirac Dice -- -- https://adventofcode.com/2021/day/21 -- Copy of questions in: aoc_2021_21_questions.txt -- -- HAC 0.098 "nice to have"'s detected in this exercise: -- -- * aggregates, like ` hits := (others => (others => 0)); ` -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2021_21 is use Interfaces; r : array (1 .. 2) of Integer_64; subtype Player_Range is Integer range 0 .. 1; cells : constant := 10; subtype Cell_Range is Integer range 0 .. 9; -- "full Ada": cells - 1 procedure Play_Part_1 (start_player_1, start_player_2 : Positive) is score : array (Player_Range) of Natural; start : array (Player_Range) of Cell_Range; space, rolls : Natural; win_score : constant := 1000; begin score (0) := 0; score (1) := 0; start (0) := start_player_1 - 1; -- Start position, 0-based start (1) := start_player_2 - 1; -- Start position, 0-based for round in 1 .. win_score loop -- Worst case for any player: +1 point on each round. for playing in Player_Range loop space := 1 + (start (playing) + 9 * round ** 2 + (9 * playing - 3) * round) mod cells; score (playing) := score (playing) + space; if score (playing) >= 1000 then rolls := 3 * (1 + (round - 1) * 2 + playing); r (1) := Interfaces.Integer_64 (score (1 - playing) * rolls); return; end if; end loop; end loop; end Play_Part_1; subtype Dirac_Dice_Range is Integer range 3 .. 9; -- Number of combinations of 3 dice rolls for each outcome. dice_counts : array (Dirac_Dice_Range) of Positive; -- "full Ada": ` dice_counts ... := (1,3,6,7,6,3,1) ` procedure Init_Dirac is begin dice_counts (3) := 1; -- One combination: 1,1,1 dice_counts (4) := 3; -- 3 combinations: 1,1,2, 1,2,1, 2,1,1 dice_counts (5) := 6; dice_counts (6) := 7; dice_counts (7) := 6; dice_counts (8) := 3; dice_counts (9) := 1; end Init_Dirac; -- Universes wins counts for player 1 and 2. type Univs_Pair is array (1 .. 2) of Integer_64; procedure Play_Part_2 (start_player_1, start_player_2 : Positive) is win_score : constant := 21; subtype Score_Range is Integer range 0 .. win_score; -- Memoization of intermediate results, depending -- on the possible scores and positions: cache : array (Score_Range, Score_Range, Cell_Range, Cell_Range) of Univs_Pair; not_seen : constant := -1; -- -- We simulate player A (1 or 2) rolling the dice then -- winning, or giving the hand to player B (2 or 1). -- procedure Winning_Universes ( score_A, score_B : in Natural; pos_A, pos_B : in Cell_Range; univs : out Univs_Pair ) is new_pos_A : Cell_Range; new_score_A : Natural; other_play : Univs_Pair; begin if cache (score_A, score_B, pos_A, pos_B)(1) /= not_seen then univs := cache (score_A, score_B, pos_A, pos_B); return; end if; univs (1) := 0; univs (2) := 0; -- Player A rolls the Dirac dices 3 times. -- We go through the possible outcomes, after the 3 draws: -- the parallel universes become only different -- depending on the sum of the 3 draws. for dirac_dice_3 in 3 .. 9 loop new_pos_A := (pos_A + dirac_dice_3) mod cells; new_score_A := score_A + 1 + new_pos_A; -- Our positions are 0-based. if new_score_A >= win_score then -- In this case, player A wins when reaching new_pos_A. -- It happens once if the numbers diced were 1, 1, 1; -- 3 times if the numbers diced were 1, 1, 2 (in any order), etc. univs (1) := univs (1) + Integer_64 (dice_counts (dirac_dice_3)); else -- Player A doesn't win, so it's player B's turn to play. Winning_Universes ( score_B, new_score_A, pos_B, new_pos_A, other_play -- = (#universes where B wins, #universes where A wins) ); univs (1) := univs (1) + Integer_64 (dice_counts (dirac_dice_3)) * other_play (2); univs (2) := univs (2) + Integer_64 (dice_counts (dirac_dice_3)) * other_play (1); end if; end loop; -- cache (score_A, score_B, pos_A, pos_B) := univs; end Winning_Universes; res : Univs_Pair; begin -- "full Ada": the following could be done in `cache` declaration -- with a (others => (others => (others => (others => not_seen)))) for s1 in Score_Range loop for s2 in Score_Range loop for c1 in Cell_Range loop for c2 in Cell_Range loop cache (s1, s2, c1, c2)(1) := not_seen; end loop; end loop; end loop; end loop; -- Winning_Universes (0, 0, start_player_1 - 1, start_player_2 - 1, res); r (2) := res (1); if res (2) > res (1) then r (2) := res (2); end if; end Play_Part_2; use HAT; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Init_Dirac; Play_Part_1 (7, 1); Play_Part_2 (7, 1); if compiler_test_mode then if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & Integer_64'Image (r (1))); Put_Line (+"Part 2:" & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 684495 -- Part 2: validated by AoC: 152587196649184 end if; end AoC_2021_21; ================================================ FILE: exm/aoc/2021/aoc_2021_21_questions.txt ================================================ --- Day 21: Dirac Dice --- There's not much to do as you slowly descend to the bottom of the ocean. The submarine computer challenges you to a nice game of Dirac Dice. This game consists of a single die, two pawns, and a game board with a circular track containing ten spaces marked 1 through 10 clockwise. Each player's starting space is chosen randomly (your puzzle input). Player 1 goes first. Players take turns moving. On each player's turn, the player rolls the die three times and adds up the results. Then, the player moves their pawn that many times forward around the track (that is, moving clockwise on spaces in order of increasing value, wrapping back around to 1 after 10). So, if a player is on space 7 and they roll 2, 2, and 1, they would move forward 5 times, to spaces 8, 9, 10, 1, and finally stopping on 2. After each player moves, they increase their score by the value of the space their pawn stopped on. Players' scores start at 0. So, if the first player starts on space 7 and rolls a total of 5, they would stop on space 2 and add 2 to their score (for a total score of 2). The game immediately ends as a win for any player whose score reaches at least 1000. Since the first game is a practice game, the submarine opens a compartment labeled deterministic dice and a 100-sided die falls out. This die always rolls 1 first, then 2, then 3, and so on up to 100, after which it starts over at 1 again. Play using this die. For example, given these starting positions: Player 1 starting position: 4 Player 2 starting position: 8 This is how the game would go: Player 1 rolls 1+2+3 and moves to space 10 for a total score of 10. Player 2 rolls 4+5+6 and moves to space 3 for a total score of 3. Player 1 rolls 7+8+9 and moves to space 4 for a total score of 14. Player 2 rolls 10+11+12 and moves to space 6 for a total score of 9. Player 1 rolls 13+14+15 and moves to space 6 for a total score of 20. Player 2 rolls 16+17+18 and moves to space 7 for a total score of 16. Player 1 rolls 19+20+21 and moves to space 6 for a total score of 26. Player 2 rolls 22+23+24 and moves to space 6 for a total score of 22. ...after many turns... Player 2 rolls 82+83+84 and moves to space 6 for a total score of 742. Player 1 rolls 85+86+87 and moves to space 4 for a total score of 990. Player 2 rolls 88+89+90 and moves to space 3 for a total score of 745. Player 1 rolls 91+92+93 and moves to space 10 for a final score, 1000. Since player 1 has at least 1000 points, player 1 wins and the game ends. At this point, the losing player had 745 points and the die had been rolled a total of 993 times; 745 * 993 = 739785. Play a practice game using the deterministic 100-sided die. The moment either player wins, what do you get if you multiply the score of the losing player by the number of times the die was rolled during the game? --- Part Two --- Now that you're warmed up, it's time to play the real game. A second compartment opens, this time labeled Dirac dice. Out of it falls a single three-sided die. As you experiment with the die, you feel a little strange. An informational brochure in the compartment explains that this is a quantum die: when you roll it, the universe splits into multiple copies, one copy for each possible outcome of the die. In this case, rolling the die always splits the universe into three copies: one where the outcome of the roll was 1, one where it was 2, and one where it was 3. The game is played the same as before, although to prevent things from getting too far out of hand, the game now ends when either player's score reaches at least 21. Using the same starting positions as in the example above, player 1 wins in 444356092776315 universes, while player 2 merely wins in 341960390180808 universes. Using your given starting positions, determine every possible outcome. Find the player that wins in more universes; in how many universes does that player win? ================================================ FILE: exm/aoc/2021/aoc_2021_22.adb ================================================ -- Solution to Advent of Code 2021, Day 22 ------------------------------------------- -- Reactor Reboot -- -- https://adventofcode.com/2021/day/22 -- Copy of questions in: aoc_2021_22_questions.txt -- -- GNAT: - runs in 2081 seconds i.e. 35 min in fast mode -- - needs to use Integer_64 for counters. -- -- To do: make a HAC variant of a smarter solution, with -- applying the "on/off" rules in the outer loop and -- (in dimension d) skipping sorted values not within -- current rule's range. Inspiration: -- https://github.com/mytbk/advent_of_code/blob/main/2021/22/advent_22_2.adb -- -- Wish from HAC 0.098 solved in HAC 0.1: -- * package Interfaces with at least -- Integer_64 for compatibility with GNAT -- (GNAT's Integer is always 32 bits) -- -- with HAT; -- For a build with "full Ada": files HAT*.ad* are in ../../../src -- See also the GNAT project file aoc_2021.gpr . with Interfaces; -- Needed for GNAT (Integer_64). procedure AoC_2021_22 is use HAT, Interfaces; dim_max : constant := 3; subtype Dimension_Range is Integer range 1 .. dim_max; type Point is array (Dimension_Range) of Integer; type Rule_Type is record on : Boolean; low, high : Point; end record; rules_max : constant := 1000; rules : Natural := 0; rule : array (1 .. rules_max) of Rule_Type; -- Lists of numbers -- NB: of course in "full Ada" we would do it in a much -- smarter way, with Vectors & sorting. list_length_max : constant := rules_max; type List_Array_Type is array (1 .. list_length_max) of Integer; type List_Type is record top : Natural; val : List_Array_Type; end record; -- Insert and sort ascending procedure Insert (list : in out List_Type; num : Integer) is ins : Natural := list.top + 1; begin for i in 1 .. list.top loop if num = list.val (i) then return; elsif num < list.val (i) then ins := i; -- Insert here. exit; end if; end loop; for i in reverse ins .. list.top loop list.val (i + 1) := list.val (i); end loop; list.val (ins) := num; list.top := list.top + 1; end Insert; -- We record every point in every dimension. coord : array (Dimension_Range) of List_Type; procedure Read_Data is input : constant VString := +"aoc_2021_22.txt"; -- c, sep : Character; num : Integer; onoff : String (1 .. 3); xyz, dotdot : String (1 .. 2); f : File_Type; begin for d in Dimension_Range loop coord (d).top := 0; end loop; Open (f, input); while not End_Of_File (f) loop rules := rules + 1; Get (f, onoff); rule (rules).on := onoff = "on "; if not rule (rules).on then Get (f, c); end if; for d in Dimension_Range loop Get (f, xyz); Get (f, num); rule (rules).low (d) := num; Insert (coord (d), num); Get (f, dotdot); Get (f, num); rule (rules).high (d) := num; Insert (coord (d), num); exit when d = dim_max; Get (f, sep); end loop; end loop; Close (f); end Read_Data; r : array (1 .. 2) of Integer_64; procedure Part_1 is on : Boolean; count : Integer_64 := 0; begin for x in -50 .. 50 loop for y in -50 .. 50 loop for z in -50 .. 50 loop on := False; for r in 1 .. rules loop if x in rule (r).low (1) .. rule (r).high (1) and then y in rule (r).low (2) .. rule (r).high (2) and then z in rule (r).low (3) .. rule (r).high (3) then on := rule (r).on; end if; end loop; if on then count := count + 1; end if; end loop; end loop; end loop; r (1) := count; end Part_1; procedure Part_2 is count : Integer_64 := 0; -- -- When d <= dim_max we test different cuboid vertices, -- for each dimension. -- When d = dim_max + 1 we scan the cuboid delimited by -- opposite vertices input_vertex_1 (included), input_vertex_2 -- (excluded) through the list of rules, and count the cuboid's -- volume when it is `on`. -- procedure Scan (input_vertex_1, input_vertex_2 : Point; d : Positive) is vertex_1, vertex_2 : Point; inside, on : Boolean; volume : Integer_64; begin if d = dim_max + 1 then -- -- Vertice are complete in all dimensions, we can check the cuboid. -- on := False; for r in 1 .. rules loop inside := True; for dd in Dimension_Range loop inside := inside and then -- Vertex 1 (or any point within the cuboid) is sufficient -- for checking the whole cuboid against the rules since -- we know that no rule goes through the cuboid. input_vertex_1 (dd) in rule (r).low (dd) .. rule (r).high (dd); end loop; if inside then on := rule (r).on; end if; end loop; if on then volume := 1; for dd in Dimension_Range loop volume := volume * Integer_64 (input_vertex_2 (dd) - input_vertex_1 (dd)); end loop; count := count + volume; end if; else -- We construct cuboids such that all the cubes they contain -- are either "on" or "off". The union of all constructed cuboids -- is itself a giant cuboid which contains all cuboids described -- in the "on/off" rules. -- -- A little drawing to explain the code below. -- '#' are rule cuboid boundaries. -- '.' are examples of constructed cuboids touching -- no rule boundary. -- '>' and '^' indicate boundaries of a rule (or more). -- '-' and '|' indicate boundaries of the giant cuboid. -- -- > --------##############------ -- |.. ....# # | -- > ############# ####### -- #.. ....#...# on # # -- #.. ....#...# # off # -- #.. ....#...# # # -- #.. ....#...# # # -- > # #################### -- > # # # | -- #.. ...# | -- > #############--------------- -- ^ ^ ^ ^ ^ ^ -- for i in 1 .. coord (d).top loop vertex_1 := input_vertex_1; vertex_2 := input_vertex_2; -- Check the cuboids, of width 1 in dimension d, -- touching a boundary of a rule (or more). vertex_1 (d) := coord (d).val (i); vertex_2 (d) := coord (d).val (i) + 1; Scan (vertex_1, vertex_2, d + 1); if i < coord (d).top then -- Check the cuboids with opposite vertices that -- don't touch any rule cuboid's boundary in -- dimension d. vertex_1 (d) := coord (d).val (i) + 1; vertex_2 (d) := coord (d).val (i + 1); Scan (vertex_1, vertex_2, d + 1); end if; end loop; end if; end Scan; -- dummy_vertex_1, dummy_vertex_2 : Point; begin Scan (dummy_vertex_1, dummy_vertex_2, 1); r (2) := count; end Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Part_1; Part_2; if compiler_test_mode then if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: : number of cubes which are ""on"" within small region " & Integer_64'Image (r (1))); Put_Line (+"Part 2: : number of cubes which are ""on"" " & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 587097 -- Part 2: validated by AoC: 1359673068597669 end if; end AoC_2021_22; ================================================ FILE: exm/aoc/2021/aoc_2021_22.txt ================================================ on x=-5..46,y=-32..20,z=-18..26 on x=-47..-1,y=-28..19,z=-49..3 on x=-19..30,y=-22..31,z=-20..33 on x=-27..19,y=-38..7,z=-9..35 on x=-37..7,y=-11..34,z=-44..7 on x=-18..27,y=-13..39,z=1..45 on x=-8..37,y=-35..13,z=-29..21 on x=-8..46,y=-46..3,z=-18..30 on x=-34..10,y=0..48,z=-40..14 on x=-9..40,y=-42..5,z=-1..44 off x=6..25,y=6..16,z=12..23 on x=-28..26,y=-35..9,z=-19..35 off x=7..17,y=-38..-28,z=26..45 on x=-22..32,y=-8..36,z=-38..13 off x=30..41,y=-42..-29,z=8..27 on x=-24..23,y=-18..28,z=-10..43 off x=26..36,y=16..32,z=-47..-32 on x=-49..2,y=-19..28,z=-3..45 off x=-38..-22,y=1..12,z=1..16 on x=-39..8,y=-5..49,z=-28..18 on x=51548..69612,y=-60212..-36528,z=-25189..-16754 on x=-59209..-41074,y=-47258..-18479,z=43187..67447 on x=-7732..15267,y=28887..44205,z=-78972..-69135 on x=-56485..-41367,y=35643..60725,z=9955..38448 on x=-45609..-30383,y=42538..67043,z=-62848..-27707 on x=16585..38511,y=61520..81118,z=35888..62067 on x=-67525..-48645,y=7892..19788,z=-59876..-45177 on x=-78784..-51262,y=32167..54511,z=4045..30666 on x=-58038..-30559,y=-34516..-9371,z=-74896..-49631 on x=59490..71576,y=-46392..-27677,z=-19354..4915 on x=2789..22240,y=-85959..-62180,z=18830..28722 on x=-57568..-43338,y=63096..75178,z=926..32659 on x=-36402..-25163,y=56158..72356,z=-34059..-23691 on x=19381..37737,y=52036..68217,z=29949..43546 on x=37800..56883,y=-65115..-54626,z=7625..22209 on x=29861..55671,y=-70522..-59084,z=-9952..22480 on x=-4943..4619,y=-82644..-55578,z=-47007..-23182 on x=-77849..-71032,y=16058..44694,z=-1827..11132 on x=-23897..4513,y=-32899..-19780,z=74118..93642 on x=-60931..-43684,y=41018..76777,z=-3631..29159 on x=-69808..-59244,y=-51812..-25532,z=-45864..-9434 on x=-15717..2260,y=35502..45822,z=-72800..-64438 on x=-43443..-25264,y=-34577..-4572,z=-71311..-49556 on x=33953..53184,y=-24517..-12192,z=67205..70115 on x=-41613..-10171,y=-90989..-64734,z=1939..27480 on x=46293..54347,y=34679..57929,z=41751..66847 on x=-76583..-57535,y=-48670..-21474,z=5815..29534 on x=-80510..-57928,y=-29414..-6514,z=-37580..-9861 on x=34411..44577,y=45833..60226,z=34129..52711 on x=-54987..-24702,y=35411..65161,z=22013..51876 on x=63172..82294,y=1664..5780,z=-28578..-11907 on x=-67996..-54355,y=-44787..-25403,z=37322..54489 on x=-88986..-66707,y=-438..8596,z=15392..26773 on x=24230..44153,y=30762..34631,z=-74945..-53755 on x=35628..53039,y=15552..30471,z=-73777..-45796 on x=-52060..-30732,y=-42710..-35117,z=-69599..-56932 on x=-25002..1751,y=-81083..-59751,z=-50786..-30720 on x=-73739..-54969,y=31242..54593,z=-15062..-5453 on x=-47432..-33101,y=-76534..-50415,z=14492..27925 on x=-41274..-24626,y=13752..36312,z=-77251..-62098 on x=-6015..10536,y=65091..87672,z=-8552..19147 on x=10536..33835,y=-45299..-21530,z=60435..67449 on x=-6943..11903,y=-12128..16312,z=-90681..-78248 on x=19487..42357,y=47438..82073,z=21946..53196 on x=-21443..-4774,y=-40617..-24129,z=54316..78982 on x=63707..77304,y=-38874..-28037,z=-18266..6915 on x=-6608..25825,y=72777..97505,z=-17109..11691 on x=2889..21341,y=65169..90385,z=18937..38113 on x=-77060..-67800,y=-51373..-14093,z=-8648..14762 on x=42229..66044,y=-60623..-46142,z=-54862..-31092 on x=-31747..-1959,y=-56945..-43565,z=-66618..-51357 on x=40909..51753,y=-30080..-16886,z=48239..61214 on x=69140..93786,y=5799..19749,z=-6841..872 on x=-6320..9006,y=-86599..-63122,z=-13738..12967 on x=-8408..7465,y=4860..11903,z=77529..78985 on x=-72765..-50331,y=6535..18747,z=-58335..-51186 on x=-4003..16109,y=51255..89213,z=-55782..-20348 on x=-80053..-69750,y=-4588..15466,z=21830..30736 on x=65397..85386,y=6545..33466,z=-21152..-13938 on x=-11846..-3287,y=-25751..-7512,z=65275..84910 on x=-8452..15638,y=-14228..5220,z=-90071..-73008 on x=33452..61442,y=-19321..15551,z=49363..80378 on x=20735..47619,y=58344..71302,z=21735..41485 on x=11894..17984,y=31286..38843,z=69448..84141 on x=-28901..-20476,y=56147..81693,z=25668..51544 on x=6892..29595,y=64220..87570,z=-4733..20349 on x=-19082..4923,y=-77762..-69631,z=-38618..-23768 on x=36297..71252,y=-46927..-22141,z=43163..67184 on x=37857..43987,y=-40548..-13497,z=55402..60685 on x=-18613..3908,y=63432..84514,z=-37998..-30669 on x=12594..38169,y=66206..86022,z=-39692..-17639 on x=-32769..-1538,y=-49140..-26552,z=-79489..-51197 on x=53359..70274,y=26290..55000,z=-47687..-20020 on x=-66712..-35804,y=-77484..-56383,z=2674..24161 on x=-43228..-29410,y=45851..81707,z=-40520..-25586 on x=-20560..-9751,y=51994..82219,z=31331..68243 on x=-21397..-2481,y=41154..66963,z=49167..79202 on x=-16407..13119,y=48433..79148,z=34394..65994 on x=-36116..-19914,y=-17493..-1274,z=-83827..-59340 on x=-65917..-60015,y=-22232..-8123,z=44955..52754 on x=35522..62422,y=-47708..-41694,z=30631..52175 on x=-19027..-16358,y=-69201..-59790,z=40059..63066 on x=-11051..9182,y=40384..59830,z=-82502..-64612 on x=45221..58438,y=-57873..-30492,z=-62317..-37220 on x=20911..38767,y=-83455..-67100,z=15685..42250 on x=-85424..-62312,y=15633..41768,z=-11400..1596 on x=-22319..1952,y=14052..20241,z=-80323..-60026 on x=-36511..-3117,y=76591..88287,z=-7433..10958 on x=-66952..-44475,y=14319..31064,z=-58790..-36803 on x=54959..76207,y=-35201..-16191,z=-16849..-5914 on x=1597..26993,y=-10079..6267,z=63496..85390 on x=16494..39087,y=-17926..9408,z=-96055..-57690 on x=61259..85576,y=1205..18753,z=-43630..-35549 on x=9246..42812,y=4903..18157,z=-91998..-64639 on x=56336..60328,y=38496..41872,z=-45204..-16725 on x=38207..53167,y=32557..48679,z=-45752..-31483 on x=35536..40478,y=59087..82670,z=-22132..-8228 on x=30311..65221,y=28463..49610,z=-56548..-43899 on x=39910..64396,y=-15554..6772,z=-77870..-61149 on x=63583..81517,y=-27533..4944,z=-25021..2998 on x=33270..48936,y=29978..53349,z=-64005..-46652 on x=-56719..-45447,y=48476..70535,z=19845..43624 on x=-18909..-4514,y=-33630..-18313,z=-81121..-68081 on x=31236..49957,y=37375..64529,z=40066..50479 on x=23928..60990,y=47394..71017,z=-38356..-19687 on x=14948..29328,y=10910..33468,z=-80969..-58848 on x=-3772..13969,y=-63212..-52751,z=-57568..-40117 on x=-87668..-65329,y=5661..25191,z=-16217..-2548 on x=-85618..-61349,y=-28751..724,z=-55669..-27090 on x=31666..50666,y=61760..79239,z=-5421..13325 on x=-43549..-16273,y=11600..29339,z=58406..69643 on x=-71478..-49781,y=27481..49069,z=11039..36531 on x=-17921..763,y=-88151..-58003,z=30178..41080 on x=46026..66776,y=14383..45440,z=40733..70614 on x=6163..18610,y=34482..54360,z=60951..89457 on x=19365..38532,y=-76528..-64410,z=11243..32396 on x=43561..71092,y=37565..67440,z=-7400..10989 on x=-78980..-62759,y=-37937..-18712,z=-1174..20466 on x=-84895..-61183,y=-49742..-11414,z=-40817..-27778 on x=-4950..15040,y=-68419..-47571,z=-53761..-38955 on x=49075..58693,y=47622..72167,z=-38355..-14042 on x=-251..24365,y=-83737..-52646,z=-46887..-23747 on x=7867..22830,y=-69902..-54281,z=39203..56857 on x=9363..26818,y=-90361..-66389,z=498..11013 on x=-83134..-56144,y=-28208..-24507,z=-54343..-27431 on x=6218..37705,y=-46023..-13463,z=63985..73956 on x=18495..39411,y=-26282..5248,z=-88148..-58497 on x=-45343..-35708,y=60706..70020,z=5612..17818 on x=-84718..-59568,y=-43294..-5711,z=-6416..2360 on x=31112..44903,y=68718..77761,z=-9607..6150 on x=38564..51370,y=-58071..-40868,z=16841..56101 on x=-90218..-62438,y=-16396..15602,z=7324..40169 on x=22063..40035,y=-82841..-51548,z=-12200..-2319 on x=61862..68317,y=-58231..-29405,z=-30145..-16073 on x=-35659..-26115,y=-80307..-58295,z=-7971..4817 on x=65798..82975,y=16152..37978,z=-13348..9888 on x=-22630..-2020,y=61028..82758,z=17882..53557 on x=-67183..-35832,y=53346..61736,z=-12538..-3992 on x=17561..43947,y=-691..17483,z=-80636..-71364 on x=-85254..-57085,y=-45670..-26674,z=-35836..-16893 on x=50248..59220,y=51067..53406,z=5200..24299 on x=-66088..-58018,y=-54019..-18590,z=22979..55616 on x=-21580..-1226,y=-70163..-50890,z=35971..58676 on x=-28699..-7879,y=58342..80552,z=-2944..4892 on x=32137..37434,y=57922..89847,z=-11139..4540 on x=-30782..-26050,y=-71857..-56160,z=25962..45221 on x=3458..14941,y=39444..54613,z=-78667..-51181 on x=-80957..-61391,y=-50519..-44099,z=558..36217 on x=56295..67502,y=-52211..-21726,z=-38237..-23495 on x=-59221..-26440,y=-8835..8022,z=-69874..-51958 on x=9703..31412,y=-66797..-44997,z=-69333..-41279 on x=-25059..-4256,y=50641..81219,z=41651..53960 on x=-78241..-51194,y=31612..49911,z=8201..31693 on x=54112..76706,y=12410..48082,z=-4849..18133 on x=-69337..-38953,y=49176..56256,z=23632..36858 on x=-2661..28887,y=-70999..-53499,z=-62680..-47815 on x=-47941..-29732,y=70681..92846,z=11502..17530 on x=42289..62010,y=36246..60613,z=27169..37328 on x=-91319..-65281,y=-12414..-1137,z=-562..33562 on x=67610..87861,y=-16375..5387,z=4908..37520 on x=-64941..-37494,y=12789..19739,z=43684..59305 on x=-48315..-23707,y=-63379..-46409,z=-52056..-50037 on x=39998..55060,y=-23924..174,z=47043..74650 on x=15519..54000,y=-37758..-7362,z=56719..86415 on x=-48899..-33632,y=-70284..-38768,z=-35439..-12719 on x=-32719..-19579,y=-72481..-55178,z=22036..45341 on x=3957..31100,y=-43843..-7496,z=-77904..-55904 on x=58913..74866,y=427..13237,z=-32194..-25180 on x=14045..39458,y=57126..69184,z=-56733..-40909 on x=-33890..-15281,y=-87080..-60332,z=-7896..17708 on x=-62854..-44941,y=25995..33486,z=-40656..-31936 on x=-92186..-67248,y=-31617..-10693,z=-13091..10422 on x=-20335..-1607,y=33592..61801,z=49129..66118 on x=4923..21291,y=56686..89367,z=13440..33655 on x=-85603..-58549,y=-57595..-29882,z=-29310..7688 on x=-31013..-12004,y=65998..87119,z=20798..38505 on x=-31477..631,y=-4218..13444,z=64468..96359 on x=-53080..-23970,y=-67988..-50724,z=35761..56920 on x=-3114..31515,y=-8351..9393,z=59128..93321 on x=-55700..-34434,y=2745..17959,z=61954..88396 on x=-11042..14693,y=-54901..-21447,z=67817..81842 on x=21055..36006,y=-87302..-60889,z=-15547..1734 on x=-54134..-40995,y=-47264..-26058,z=-60793..-32468 on x=58900..84612,y=19801..52338,z=-29863..-5113 on x=51518..67122,y=-73957..-44881,z=-21799..377 on x=-76186..-60253,y=-52998..-32671,z=-10966..22158 on x=-85814..-69675,y=-16314..-1479,z=12576..29151 on x=-17279..-7487,y=69461..82491,z=-43685..-20033 on x=40521..54246,y=27004..54142,z=29821..43721 on x=39205..48927,y=-76831..-53845,z=10907..30764 on x=-33186..-8425,y=-25334..-12643,z=-90320..-73208 on x=-28871..-10579,y=52805..71984,z=40782..48756 on x=-84199..-69384,y=-24294..10470,z=-31795..-504 on x=14215..35943,y=-68234..-54826,z=-40696..-26587 on x=-1154..8736,y=541..27118,z=-92688..-67093 on x=-78094..-57999,y=30080..50610,z=14623..47207 on x=-71351..-61777,y=32493..36723,z=-43154..-20385 on x=29680..49711,y=64389..80775,z=-14976..-7530 on x=21466..32444,y=-71107..-49184,z=32025..47710 on x=-13395..2005,y=55307..82256,z=13571..32919 off x=-75925..-51372,y=38378..56338,z=4726..22058 off x=-81435..-61321,y=-19944..14261,z=-12909..5888 on x=-28811..-418,y=-60179..-36825,z=60339..82792 on x=-56836..-42864,y=51509..69993,z=-38353..-9466 off x=33241..47683,y=-57215..-42041,z=-66120..-48804 off x=5602..32171,y=67207..82648,z=687..19684 on x=-77530..-54996,y=-18932..14116,z=-41205..-26951 off x=-26770..539,y=34948..50177,z=48516..78552 off x=-46087..-28406,y=-34280..-25940,z=-88646..-67393 off x=18159..44447,y=61027..74243,z=11037..47721 on x=12856..22197,y=-77260..-63311,z=9644..14020 on x=73356..83326,y=-28895..-11586,z=-12672..-9461 off x=67712..93385,y=4383..29307,z=-20971..-918 on x=-45997..-33017,y=-73653..-54744,z=-45919..-18834 on x=60720..69779,y=-36283..-5920,z=-50708..-27954 on x=19053..47867,y=2081..28770,z=64876..71876 on x=-527..17979,y=54470..79654,z=-40446..-35448 on x=57634..74279,y=-12554..-1277,z=-32432..-15188 off x=-5832..-3671,y=-73172..-56981,z=-55793..-43538 on x=-1264..8465,y=-42248..-24987,z=-89062..-53822 off x=-15774..21815,y=27050..48731,z=56418..72513 off x=-46133..-21613,y=66137..75384,z=6208..30313 on x=33118..53938,y=-65582..-37843,z=-37735..-12944 off x=-49999..-44727,y=-6444..11058,z=56795..82782 on x=48809..67169,y=19871..40744,z=-52762..-34126 off x=-83411..-59176,y=25797..45572,z=-40278..-27145 off x=32616..41066,y=-9846..22502,z=65723..76470 on x=-20460..-2811,y=-83364..-60153,z=29259..46240 on x=-4678..31497,y=-66769..-42660,z=47122..52963 off x=-79373..-44004,y=15610..27145,z=-60155..-24820 on x=-75928..-66979,y=-38564..-25541,z=-19893..-6451 on x=-40648..-20377,y=-16448..15340,z=68020..86613 off x=-62245..-35670,y=-31396..-7005,z=-65944..-45697 on x=-13973..20255,y=11258..38206,z=-88464..-74070 on x=-79431..-61223,y=-24640..2553,z=-45829..-35435 on x=-4924..9129,y=-80374..-53014,z=26057..45688 off x=6404..27786,y=47552..72969,z=-56049..-33886 off x=-60433..-45352,y=54256..72101,z=-1351..13871 on x=14354..49643,y=33977..50411,z=-78584..-53528 off x=-1250..19190,y=-69591..-51054,z=32606..57993 on x=44601..65261,y=-22387..-4877,z=-47514..-27914 off x=-76961..-53337,y=11751..35762,z=26662..51798 on x=-6110..17117,y=35295..55448,z=49203..65916 on x=-26314..7333,y=-10014..-190,z=-96699..-63078 on x=5073..27938,y=48893..68369,z=46606..53060 off x=9161..32324,y=31253..49108,z=59376..78095 off x=-76724..-46080,y=-37471..-7527,z=39313..59143 on x=-12104..25230,y=43873..63566,z=54973..71127 on x=-72007..-40895,y=-29918..-2483,z=-65639..-46254 off x=23116..41418,y=-16707..518,z=66003..82373 off x=7546..31315,y=-236..14978,z=73882..88170 off x=2975..26627,y=-28535..4054,z=65551..79183 off x=-63548..-40819,y=4251..34856,z=-69125..-53738 off x=36116..53160,y=18391..43033,z=53283..69572 off x=-8169..-7213,y=17466..44306,z=53116..81956 on x=43606..72143,y=38753..51975,z=30789..41812 on x=35845..48867,y=-15869..989,z=-69562..-58096 on x=-67758..-55029,y=-56935..-34340,z=-16747..14847 on x=45091..70880,y=18972..32828,z=-58444..-56030 off x=11622..45729,y=-11464..15892,z=55396..77935 off x=30723..44124,y=-50216..-38776,z=-58362..-52717 off x=53359..57764,y=-28444..-7054,z=47399..61343 on x=-72327..-61742,y=36941..63691,z=-9967..9016 on x=1184..28614,y=-72042..-59895,z=29436..49413 off x=-69303..-45932,y=-34340..-25505,z=-38098..-33099 on x=59045..88304,y=-30319..-10678,z=11682..39990 off x=53524..67731,y=-68251..-44887,z=882..10308 off x=-32029..-15563,y=-76737..-44100,z=-50442..-39369 off x=194..33756,y=-81633..-73368,z=-43607..-17799 off x=-48326..-13807,y=53400..85780,z=-5482..17259 on x=-4836..8518,y=-88585..-59292,z=-38817..-19966 off x=-39059..-5289,y=-38701..-18212,z=62298..87934 on x=38636..52369,y=-67782..-55060,z=-39916..-24812 off x=41566..50837,y=22379..30551,z=-65974..-50435 on x=-83246..-64136,y=-29788..2021,z=25088..51721 off x=-7306..17520,y=73996..76916,z=-44293..-10369 on x=-64653..-52809,y=14691..34105,z=-58569..-42334 on x=15682..33355,y=50316..82171,z=27668..43094 off x=-29490..-20692,y=51678..60437,z=39101..53564 off x=19272..37050,y=13981..31882,z=67811..82763 off x=24474..43806,y=-53159..-30998,z=29529..55383 on x=-90714..-55089,y=14725..45316,z=-1160..12104 on x=-64836..-35562,y=-8351..5014,z=-71436..-52114 off x=30933..47732,y=-64548..-62131,z=6870..17374 on x=-77680..-53166,y=8312..40487,z=36033..43235 on x=-5863..28121,y=14413..32208,z=-86695..-63943 on x=32413..51029,y=-68162..-40475,z=-64026..-40258 on x=-48144..-41618,y=-28042..-10133,z=-64990..-50925 on x=73532..98724,y=-21663..8040,z=662..20743 off x=51689..54423,y=40915..69007,z=3378..19020 off x=-3711..20642,y=66808..81277,z=-32665..-18224 off x=29497..56099,y=-59154..-38611,z=32874..69747 off x=-32780..2492,y=-81309..-65288,z=-52012..-28083 off x=12238..28287,y=60040..85737,z=2251..20540 off x=-78514..-47095,y=-52287..-24038,z=-51482..-20767 on x=-2476..22624,y=76854..93819,z=-16182..1908 on x=25782..55736,y=61375..79709,z=9605..31807 on x=-12247..16212,y=-75039..-64291,z=-43708..-25037 off x=-26281..-4119,y=31802..45275,z=61617..72578 off x=-77629..-55347,y=-37694..-22601,z=-48750..-25744 on x=-41090..-17088,y=-42730..-21946,z=-71684..-44738 off x=21171..52548,y=-73087..-62415,z=-24139..4853 on x=-10430..13741,y=-87082..-60233,z=29057..37997 off x=-33776..-18921,y=-9022..10689,z=60785..92622 off x=-17316..-5440,y=-46992..-37935,z=-72734..-65376 off x=-25276..-1515,y=-4036..5863,z=-94213..-63783 on x=6018..30570,y=-75934..-59098,z=-3614..21349 off x=47020..60774,y=16941..24239,z=52244..74152 on x=-28035..-8076,y=-83562..-56357,z=20214..35904 off x=-4864..9282,y=-58885..-52290,z=46576..71092 off x=-38607..-25227,y=-10107..20288,z=56552..78626 on x=-49296..-38783,y=1776..37729,z=-68328..-54075 off x=27839..40291,y=-2748..5372,z=-73179..-64910 off x=57012..63558,y=33773..63448,z=12538..30013 on x=7376..22139,y=46931..53925,z=40614..77423 on x=-36815..-4231,y=-79653..-53534,z=-54320..-30272 off x=-72451..-44505,y=11708..45028,z=30438..48099 on x=19422..54740,y=61056..68389,z=11710..35395 on x=34256..51333,y=24928..52293,z=-65652..-36708 off x=11235..22363,y=1316..13305,z=-95660..-75393 on x=40699..63818,y=-71842..-49029,z=-4105..24818 off x=-56129..-51451,y=-4050..32239,z=-62360..-48415 off x=7724..42005,y=-8468..7046,z=67268..89366 on x=-50038..-29191,y=190..9704,z=-85587..-62369 on x=52569..76812,y=29834..57890,z=-5460..24255 off x=3998..24292,y=-20205..10100,z=77120..86720 off x=-12018..6886,y=-28175..-5906,z=63737..83970 on x=64370..76913,y=20946..44292,z=-15861..-5899 off x=3647..21883,y=-73520..-66435,z=19047..38036 on x=26881..35736,y=50047..83360,z=27009..43013 on x=-54204..-46977,y=-58133..-44730,z=25366..34727 on x=60963..72747,y=-40989..-1428,z=27149..44298 on x=-86903..-63974,y=15796..44312,z=14110..31846 on x=30800..51265,y=67817..83500,z=7398..35684 on x=26115..46933,y=-78183..-68457,z=16590..22235 on x=50801..69558,y=14960..41009,z=-52573..-42699 on x=-76762..-62114,y=-41535..-30916,z=30799..36061 off x=-36971..-16432,y=69302..80179,z=5427..37800 on x=-59304..-42151,y=38961..75025,z=19077..30930 off x=-68878..-43214,y=-38416..-34281,z=-56876..-32491 off x=-41227..-30387,y=67997..78440,z=-18866..-4078 on x=-18264..4145,y=25638..53883,z=55825..72054 off x=-34237..-23188,y=-18538..-14122,z=-84576..-66422 on x=48651..72652,y=-75451..-55934,z=-5750..21478 off x=8517..15398,y=-47195..-20040,z=-91462..-57328 off x=1946..24398,y=-9423..-7809,z=-98479..-63063 off x=48647..64112,y=-44400..-36389,z=43567..50295 on x=-53108..-28792,y=-18105..16521,z=-79485..-50653 on x=10610..28165,y=74425..88696,z=-15151..11655 on x=26563..41972,y=-44034..-22600,z=-75006..-53514 on x=8785..23672,y=-17501..1486,z=70023..87851 off x=-23526..-2495,y=-9907..13959,z=-86018..-74132 on x=39471..66769,y=-76484..-41637,z=4179..30148 on x=3968..41357,y=-12766..21564,z=-83232..-58999 off x=5657..25453,y=69672..92433,z=-5865..1093 on x=196..22654,y=-76890..-45710,z=30347..50177 on x=53591..67443,y=641..12115,z=-53289..-40127 on x=38502..45974,y=26606..37157,z=-73606..-59489 off x=-28470..-4391,y=65949..75960,z=-52362..-18690 off x=-12052..12226,y=-43285..-11455,z=-76126..-67446 off x=28539..47924,y=30936..61611,z=39553..62922 on x=-51301..-29348,y=-61136..-41356,z=-62122..-40860 off x=-10842..12256,y=-4453..28219,z=62816..90429 off x=-65177..-46992,y=-996..14455,z=43331..66866 off x=-41471..-34895,y=-87935..-53932,z=-15068..10098 off x=64368..85731,y=20782..34222,z=20343..56619 on x=-66495..-37890,y=53669..66986,z=16753..25052 off x=-55523..-37167,y=-50099..-14312,z=-62328..-40509 on x=46869..65044,y=2893..32395,z=48728..67114 off x=-22730..-6869,y=-89892..-55716,z=-39058..-9375 on x=-35338..-10108,y=-79088..-61919,z=-52266..-26583 on x=-87579..-54734,y=3661..13979,z=-43516..-26852 on x=-26237..6696,y=31736..52895,z=-88832..-51997 on x=-6261..18171,y=35455..40829,z=-82724..-51885 off x=-84061..-53865,y=-37690..-28185,z=17406..27387 on x=22146..33574,y=-8382..21678,z=60530..93596 off x=-34985..-14118,y=-85401..-53871,z=-27449..-20505 on x=-65653..-57152,y=-41709..-26255,z=-55300..-30989 on x=-41289..-18827,y=-54843..-30751,z=43268..77728 on x=52348..65143,y=-66867..-47070,z=-18590..-2919 on x=25408..46684,y=52219..74706,z=-45724..-26197 off x=36306..61505,y=1854..18823,z=51517..71882 on x=28807..42884,y=-44933..-19495,z=-81888..-68452 off x=-22712..10868,y=-91624..-66163,z=-29698..2061 on x=-44614..-22060,y=-12205..6362,z=-75228..-67848 off x=69181..83413,y=22509..30155,z=-5505..7620 off x=-541..33061,y=-29171..-1387,z=-89039..-65688 off x=56369..86895,y=25436..32999,z=-36190..-5946 on x=-80106..-58102,y=4812..40730,z=-39905..-27846 off x=38087..49836,y=12311..28936,z=56763..70449 off x=-45431..-9536,y=27172..52966,z=54708..70851 on x=-49616..-21967,y=25466..55138,z=-65862..-49517 on x=-3678..22714,y=-89185..-68818,z=-38953..-22111 on x=57043..82773,y=-61228..-42569,z=6701..17395 on x=45714..76420,y=-58263..-27644,z=-39439..-20345 on x=-69167..-43379,y=7904..39678,z=-72903..-43716 off x=-87370..-55908,y=41125..52870,z=-338..26930 on x=-20884..1182,y=-87244..-73126,z=-17967..-8207 off x=-89696..-61051,y=-48909..-27178,z=-319..19788 off x=11134..25390,y=40961..62596,z=-79259..-41800 ================================================ FILE: exm/aoc/2021/aoc_2021_22_questions.txt ================================================ --- Day 22: Reactor Reboot --- Operating at these extreme ocean depths has overloaded the submarine's reactor; it needs to be rebooted. The reactor core is made up of a large 3-dimensional grid made up entirely of cubes, one cube per integer 3-dimensional coordinate (x,y,z). Each cube can be either on or off; at the start of the reboot process, they are all off. (Could it be an old model of a reactor you've seen before?) To reboot the reactor, you just need to set all of the cubes to either on or off by following a list of reboot steps (your puzzle input). Each step specifies a cuboid (the set of all cubes that have coordinates which fall within ranges for x, y, and z) and whether to turn all of the cubes in that cuboid on or off. For example, given these reboot steps: on x=10..12,y=10..12,z=10..12 on x=11..13,y=11..13,z=11..13 off x=9..11,y=9..11,z=9..11 on x=10..10,y=10..10,z=10..10 The first step (on x=10..12,y=10..12,z=10..12) turns on a 3x3x3 cuboid consisting of 27 cubes: 10,10,10 10,10,11 10,10,12 10,11,10 10,11,11 10,11,12 10,12,10 10,12,11 10,12,12 11,10,10 11,10,11 11,10,12 11,11,10 11,11,11 11,11,12 11,12,10 11,12,11 11,12,12 12,10,10 12,10,11 12,10,12 12,11,10 12,11,11 12,11,12 12,12,10 12,12,11 12,12,12 The second step (on x=11..13,y=11..13,z=11..13) turns on a 3x3x3 cuboid that overlaps with the first. As a result, only 19 additional cubes turn on; the rest are already on from the previous step: 11,11,13 11,12,13 11,13,11 11,13,12 11,13,13 12,11,13 12,12,13 12,13,11 12,13,12 12,13,13 13,11,11 13,11,12 13,11,13 13,12,11 13,12,12 13,12,13 13,13,11 13,13,12 13,13,13 The third step (off x=9..11,y=9..11,z=9..11) turns off a 3x3x3 cuboid that overlaps partially with some cubes that are on, ultimately turning off 8 cubes: 10,10,10 10,10,11 10,11,10 10,11,11 11,10,10 11,10,11 11,11,10 11,11,11 The final step (on x=10..10,y=10..10,z=10..10) turns on a single cube, 10,10,10. After this last step, 39 cubes are on. The initialization procedure only uses cubes that have x, y, and z positions of at least -50 and at most 50. For now, ignore cubes outside this region. Here is a larger example: on x=-20..26,y=-36..17,z=-47..7 on x=-20..33,y=-21..23,z=-26..28 on x=-22..28,y=-29..23,z=-38..16 on x=-46..7,y=-6..46,z=-50..-1 on x=-49..1,y=-3..46,z=-24..28 on x=2..47,y=-22..22,z=-23..27 on x=-27..23,y=-28..26,z=-21..29 on x=-39..5,y=-6..47,z=-3..44 on x=-30..21,y=-8..43,z=-13..34 on x=-22..26,y=-27..20,z=-29..19 off x=-48..-32,y=26..41,z=-47..-37 on x=-12..35,y=6..50,z=-50..-2 off x=-48..-32,y=-32..-16,z=-15..-5 on x=-18..26,y=-33..15,z=-7..46 off x=-40..-22,y=-38..-28,z=23..41 on x=-16..35,y=-41..10,z=-47..6 off x=-32..-23,y=11..30,z=-14..3 on x=-49..-5,y=-3..45,z=-29..18 off x=18..30,y=-20..-8,z=-3..13 on x=-41..9,y=-7..43,z=-33..15 on x=-54112..-39298,y=-85059..-49293,z=-27449..7877 on x=967..23432,y=45373..81175,z=27513..53682 The last two steps are fully outside the initialization procedure area; all other steps are fully within it. After executing these steps in the initialization procedure region, 590784 cubes are on. Execute the reboot steps. Afterward, considering only cubes in the region x=-50..50,y=-50..50,z=-50..50, how many cubes are on? --- Part Two --- Now that the initialization procedure is complete, you can reboot the reactor. Starting with all cubes off, run all of the reboot steps for all cubes in the reactor. Consider the following reboot steps: on x=-5..47,y=-31..22,z=-19..33 on x=-44..5,y=-27..21,z=-14..35 on x=-49..-1,y=-11..42,z=-10..38 on x=-20..34,y=-40..6,z=-44..1 off x=26..39,y=40..50,z=-2..11 on x=-41..5,y=-41..6,z=-36..8 off x=-43..-33,y=-45..-28,z=7..25 on x=-33..15,y=-32..19,z=-34..11 off x=35..47,y=-46..-34,z=-11..5 on x=-14..36,y=-6..44,z=-16..29 on x=-57795..-6158,y=29564..72030,z=20435..90618 on x=36731..105352,y=-21140..28532,z=16094..90401 on x=30999..107136,y=-53464..15513,z=8553..71215 on x=13528..83982,y=-99403..-27377,z=-24141..23996 on x=-72682..-12347,y=18159..111354,z=7391..80950 on x=-1060..80757,y=-65301..-20884,z=-103788..-16709 on x=-83015..-9461,y=-72160..-8347,z=-81239..-26856 on x=-52752..22273,y=-49450..9096,z=54442..119054 on x=-29982..40483,y=-108474..-28371,z=-24328..38471 on x=-4958..62750,y=40422..118853,z=-7672..65583 on x=55694..108686,y=-43367..46958,z=-26781..48729 on x=-98497..-18186,y=-63569..3412,z=1232..88485 on x=-726..56291,y=-62629..13224,z=18033..85226 on x=-110886..-34664,y=-81338..-8658,z=8914..63723 on x=-55829..24974,y=-16897..54165,z=-121762..-28058 on x=-65152..-11147,y=22489..91432,z=-58782..1780 on x=-120100..-32970,y=-46592..27473,z=-11695..61039 on x=-18631..37533,y=-124565..-50804,z=-35667..28308 on x=-57817..18248,y=49321..117703,z=5745..55881 on x=14781..98692,y=-1341..70827,z=15753..70151 on x=-34419..55919,y=-19626..40991,z=39015..114138 on x=-60785..11593,y=-56135..2999,z=-95368..-26915 on x=-32178..58085,y=17647..101866,z=-91405..-8878 on x=-53655..12091,y=50097..105568,z=-75335..-4862 on x=-111166..-40997,y=-71714..2688,z=5609..50954 on x=-16602..70118,y=-98693..-44401,z=5197..76897 on x=16383..101554,y=4615..83635,z=-44907..18747 off x=-95822..-15171,y=-19987..48940,z=10804..104439 on x=-89813..-14614,y=16069..88491,z=-3297..45228 on x=41075..99376,y=-20427..49978,z=-52012..13762 on x=-21330..50085,y=-17944..62733,z=-112280..-30197 on x=-16478..35915,y=36008..118594,z=-7885..47086 off x=-98156..-27851,y=-49952..43171,z=-99005..-8456 off x=2032..69770,y=-71013..4824,z=7471..94418 on x=43670..120875,y=-42068..12382,z=-24787..38892 off x=37514..111226,y=-45862..25743,z=-16714..54663 off x=25699..97951,y=-30668..59918,z=-15349..69697 off x=-44271..17935,y=-9516..60759,z=49131..112598 on x=-61695..-5813,y=40978..94975,z=8655..80240 off x=-101086..-9439,y=-7088..67543,z=33935..83858 off x=18020..114017,y=-48931..32606,z=21474..89843 off x=-77139..10506,y=-89994..-18797,z=-80..59318 off x=8476..79288,y=-75520..11602,z=-96624..-24783 on x=-47488..-1262,y=24338..100707,z=16292..72967 off x=-84341..13987,y=2429..92914,z=-90671..-1318 off x=-37810..49457,y=-71013..-7894,z=-105357..-13188 off x=-27365..46395,y=31009..98017,z=15428..76570 off x=-70369..-16548,y=22648..78696,z=-1892..86821 on x=-53470..21291,y=-120233..-33476,z=-44150..38147 off x=-93533..-4276,y=-16170..68771,z=-104985..-24507 After running the above reboot steps, 2758514936282235 cubes are on. (Just for fun, 474140 of those are also in the initialization procedure region.) Starting again with all cubes off, execute all reboot steps. Afterward, considering all cubes, how many cubes are on? ================================================ FILE: exm/aoc/2022/aoc_2022.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the Advent of Code 2022 examples. -- -- Some programs work with both HAC and "full Ada" compilers like, -- GNAT some (titled *_full_ada.adb) work only with "full Ada". -- project AoC_2022 is for Source_Dirs use (".", "..", -- For the AoC_Toolbox package "../../../src"); -- GNAT's access to the HAT package. for Exec_Dir use "."; for Create_Missing_Dirs use "True"; type AoC_Build_Mode_Type is ("Debug", "Fast" ); AoC_Build_Mode : AoC_Build_Mode_Type := external ("AoC_Build_Mode", "Debug"); type AoC_Styles_Checks_Type is ("Off", "On", "Extra" ); AoC_Styles_Checks : AoC_Styles_Checks_Type := external ("AoC_Styles_Checks", "On"); for Main use ( "aoc_2022_25.adb", "aoc_2022_24.adb", "aoc_2022_23.adb", "aoc_2022_22.adb", "aoc_2022_21.adb", "aoc_2022_20.adb", "aoc_2022_19.adb", "aoc_2022_19_full_ada.adb", "aoc_2022_18.adb", "aoc_2022_17.adb", "aoc_2022_16.adb", "aoc_2022_15.adb", "aoc_2022_14.adb", "aoc_2022_13.adb", "aoc_2022_12.adb", "aoc_2022_11.adb", "aoc_2022_10.adb", "aoc_2022_09.adb", "aoc_2022_08.adb", "aoc_2022_07.adb", "aoc_2022_06.adb", "aoc_2022_05.adb", "aoc_2022_04.adb", "aoc_2022_03.adb", "aoc_2022_02.adb", "aoc_2022_01.adb", "gen_jumbo_day_1.adb" ); case AoC_Build_Mode is when "Debug" => for Object_Dir use "obj_debug"; when "Fast" => for Object_Dir use "obj_fast"; end case; Common_Options := ( "-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatwCijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ"); -- Don't quit, write ali/tree file even if compile errors Style_Checks_1 := ("-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens "-gnaty2", -- Style: check indentation "-gnatytc"); -- Style: check t:token separation rules, c:comment format (two spaces) Style_Checks_2 := ("-gnatye"); -- Style: check e:end/exit labels present case AoC_Styles_Checks is when "Off" => null; when "On" => Common_Options := Common_Options & Style_Checks_1; when "Extra" => Common_Options := Common_Options & Style_Checks_1 & Style_Checks_2; end case; Fast_Options := ( "-O3", "-funroll-loops", "-fpeel-loops", "-funswitch-loops", "-ftracer", "-fweb", "-frename-registers", "-ftree-vectorize", "-fipa-cp-clone", "-fgcse-after-reload" ); Debug_Options := ( -- "-gnateV", -- Validity check for parameters, GNAT > 4.6, redundant with -gnatVim ? "-gnatVa", -- Turn on all validity checking options "-gnato", -- Enable overflow checking in STRICT (-gnato1) mode "-g", "-fno-inline", "-fstack-check" ); package Compiler is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Options & Debug_Options ; when "Fast" => for Default_Switches ("ada") use Common_Options & Fast_Options & ("-gnatpn", "-ffunction-sections"); end case; end Compiler; package Linker is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use ("-g"); when "Fast" => for Default_Switches ("ada") use ("-g", "-s", "-Wl,--gc-sections"); end case; end Linker; package Binder is -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks for Default_Switches ("ada") use ("-Es"); end Binder; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-j0"); end Builder; end AoC_2022; ================================================ FILE: exm/aoc/2022/aoc_2022_01.adb ================================================ -- Solution to Advent of Code 2022, Day 1 ------------------------------------------ -- Calorie Counting -- -- https://adventofcode.com/2022/day/1 -- Copy of questions in: aoc_2022_01_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_01 is use HAT; f : File_Type; s : VString; sum, max_1, max_2, max_3 : Integer := 0; procedure Add_To_Top_3 is begin if sum > max_1 then max_3 := max_2; max_2 := max_1; max_1 := sum; elsif sum > max_2 then max_3 := max_2; max_2 := sum; elsif sum > max_3 then max_3 := sum; end if; end Add_To_Top_3; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; begin Open (f, "aoc_2022_01.txt"); Read_Data : while not End_Of_File (f) loop Get_Line (f, s); if s = "" then Add_To_Top_3; sum := 0; else sum := sum + Integer_Value (s); end if; end loop Read_Data; Add_To_Top_3; Close (f); r (1) := max_1; r (2) := max_1 + max_2 + max_3; if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: Calories carried by the Elf with the most calories:" & Integer'Image (r (1))); Put_Line (+"Part 2: Calories carried by the top 3 . . . . . . . . . . :" & Integer'Image (r (2))); -- Part 1: validated by AoC: 68442 -- Part 2: validated by AoC: 204837 end if; end AoC_2022_01; ================================================ FILE: exm/aoc/2022/aoc_2022_01.txt ================================================ 62797 1137 6086 6104 1895 7909 1651 4973 6964 5989 6003 6859 2817 3841 5360 2614 1746 3507 1159 3226 4541 1007 3881 4243 1733 4184 2377 2528 2950 5635 3664 5782 4580 4672 5989 3426 5600 2057 2901 6175 48610 8330 9058 2953 10409 10515 6073 6772 2197 1454 1167 5647 5849 2001 1754 3536 1370 1518 1575 5506 3905 2339 2355 5373 5845 5561 2919 6506 1409 5879 4604 4714 2980 4867 1823 4103 20451 23221 3067 1509 7380 6207 1031 8739 1796 7860 8132 2552 4885 14523 4281 8129 8511 1435 4589 2922 9486 8125 9379 3055 3639 38740 16211 4294 7687 1712 10099 9368 7818 11449 3561 2537 11958 7674 6052 3795 3846 4678 3629 7318 6585 2001 7220 5358 9548 4062 7399 7033 11264 46275 2748 20038 7423 6073 3395 3001 1685 3782 4034 7477 2787 5189 4928 7834 6152 2078 3983 5973 3099 2668 5509 6790 5095 5716 3928 3651 4353 2324 4994 7860 6198 5793 8073 6584 3618 5454 4393 2767 3584 3049 1330 6495 2401 2032 6093 4161 2423 2227 1485 47294 3251 4899 4344 7427 5739 3455 7449 6505 5732 5556 4162 7382 6713 2642 3282 6120 6768 2510 1058 5668 3874 6522 2193 68177 1202 16326 5274 5407 4950 1632 7838 7200 2903 7157 7222 2700 1327 3808 9007 18835 8076 2472 8440 2343 3318 1370 7294 7302 1086 7312 3203 1707 2442 4856 2106 4742 5322 1625 3597 1216 1860 2986 4170 2550 2291 1334 5510 6574 7667 3351 5168 1992 1642 7325 3045 3026 11629 30436 4759 4378 2336 2445 1654 3107 3573 5823 3674 5412 4144 6008 5593 2144 4744 3597 7879 9312 2539 6903 5299 2385 1285 2235 1842 2412 3271 7324 4749 4947 6445 3707 5131 6081 2996 6119 1077 1532 3836 3825 1677 2989 2320 2993 4053 3514 4403 2769 1642 3576 1351 2614 1445 5560 1064 1447 3491 4846 1895 4172 5915 4801 6360 5495 3521 1020 7024 2201 1956 5994 7108 4368 6589 2125 9607 7759 8294 9219 13252 9410 1002 2930 2950 1481 4450 6035 4757 3031 1162 4348 3853 4003 3810 5328 3700 7222 7908 10261 8815 5428 5628 5901 5817 2869 4236 3255 6376 3519 3320 1550 5964 3036 6141 3363 3451 8692 5150 6968 2349 9604 1650 5346 4464 14434 1269 2245 3604 4102 3153 4847 5630 1368 4024 3184 3043 4360 5111 2277 4309 1028 5088 4334 2923 4670 5247 2517 2019 2905 2714 4577 6086 3578 3444 3577 1890 2953 6922 2579 8789 5689 3900 5203 2389 9776 2610 4602 5502 10238 4465 7608 4954 8619 4813 7994 2818 3322 4977 4664 8612 1085 1957 8435 2875 8535 2645 5352 5266 8246 6632 4577 2210 6604 6558 7280 6908 2512 6758 2750 1126 9574 9451 16976 5250 6844 3339 7324 6934 5858 6420 1676 8578 5335 10082 9784 4599 7897 7693 8058 18781 3566 20903 6380 1702 3926 3902 6939 8036 5419 1289 5025 5554 3435 3332 1916 7356 12520 7346 11017 11388 4624 5334 5736 5901 1639 1296 2931 4830 4069 4097 5665 5529 5345 4527 2858 5476 1781 6609 4309 7392 1871 5736 7117 6936 3482 4152 4186 6365 5636 4565 4235 6395 2761 3815 7923 6308 7684 9859 4769 8278 12910 1311 2143 2474 3505 2759 3216 3787 3693 2637 3237 5553 5879 5727 2734 3346 2406 2187 4922 1515 2084 3633 6094 1252 6325 3206 5142 6339 1757 5358 11241 7086 6813 14664 1548 7377 5783 11235 9630 4109 8722 16111 3786 13852 14660 14906 3257 9139 2882 5982 10228 3118 13293 5413 11057 12677 17863 9645 3589 13556 15197 7093 7078 9565 15193 7844 5907 1152 2321 3793 1991 7892 10004 3540 5861 11769 10640 9553 1750 3876 4046 2345 5389 5518 6114 5106 5426 3467 1493 1241 5264 5131 3364 5723 1905 2588 4692 3798 1245 6449 3754 1998 6074 3699 2096 1999 5222 5688 10979 5452 2078 11543 1844 7544 10666 5272 6913 8789 7957 8348 4984 7278 2353 2444 7917 5469 8641 1132 4171 4078 20787 18527 5276 6022 1680 4706 2061 5053 3811 2078 2219 3921 4008 3360 1241 3652 5379 3261 1286 12019 15867 9142 6718 6759 1763 5639 8586 2769 8583 5679 7839 7346 6043 2270 8994 2060 12109 47450 4222 3717 2902 1498 3681 1365 5850 4158 3379 2187 1534 3932 4737 6031 4562 4430 3096 2073 6403 4148 3698 2477 3360 2148 2615 2159 6438 1214 6891 6856 7163 2424 7346 4006 3889 5080 4668 5496 6872 8337 13654 3495 8348 5138 3214 5881 2857 6331 7476 1135 4155 4699 7203 6356 8627 2205 5096 2580 7067 1478 4245 3098 8610 9747 3238 10772 4767 8079 5361 7130 5330 9323 4661 3677 2658 9525 9844 1451 1186 1323 3923 4568 1052 4270 4108 3231 4942 5792 6037 5366 5402 9001 15082 9282 11469 7401 2070 2095 3183 6326 1557 4983 6324 1198 5658 5539 4435 5491 1304 7164 2101 8308 3432 6310 9321 6141 6546 7730 6191 4811 1707 3732 7322 3741 5246 2825 5243 4113 4916 5626 7351 3369 2744 2540 3542 5842 3729 1105 1135 13062 2337 14278 8078 8178 4760 8051 1113 4351 5652 5403 4777 4998 1638 3990 5943 2335 4550 4345 3359 1514 4685 4102 4274 6022 5273 7334 7391 6920 5420 6627 3521 6289 6204 6416 4061 4534 4935 3249 3556 3618 4499 4136 1690 5033 2002 2454 1912 2113 4829 4944 2339 4860 1381 5035 4417 3075 2366 3567 1740 3126 1691 1147 1525 13371 14166 9536 10956 2600 3575 2155 4514 2401 3693 6379 6587 1079 4094 3327 7573 3948 5553 3883 1557 4833 4933 4883 1973 2027 4852 5735 5726 1879 1185 3525 2863 1210 2359 6505 3668 2682 5567 6375 6425 6476 6051 1022 5208 3114 8666 11550 4922 3332 7784 6833 3659 3279 3382 8593 9552 2903 2951 2006 1185 5092 5625 1309 4907 3835 2464 2644 5631 2786 4778 2325 4312 9449 9341 8140 8892 5531 1109 7598 8012 5204 5931 4082 3376 3591 2371 4945 2603 6084 2646 5100 3494 5278 3099 11334 6895 3636 6227 5295 12703 8582 6879 10795 11724 13546 14298 12038 3535 11070 8190 1032 1780 8630 10640 13274 10643 11940 10745 9333 5299 6239 1648 6467 6426 2154 7880 5169 3356 6129 5647 6595 2143 1898 12562 13508 2781 59552 16571 4935 17641 12096 6189 3250 5458 5146 5237 2684 18772 5692 9163 9268 5695 3416 2703 3018 4433 1425 1974 4673 2166 3893 3446 1994 2070 2429 3554 5665 3356 4739 1915 6877 5874 2883 2279 4966 7503 1155 2329 5544 2294 3644 6202 7787 6605 7045 3263 1268 2627 1220 5707 1469 4518 5697 3414 2047 2939 3679 2503 5031 3764 5935 3138 2639 4127 5061 2213 5332 5037 4830 3694 3624 3598 4000 2683 5122 6805 10017 1863 11675 2237 10887 1055 1975 2769 6245 3790 1178 2163 5553 5305 6089 1417 1221 6235 54647 8508 5207 1608 3986 8532 7425 4530 8413 2097 33681 2280 7109 2871 6096 6170 1314 4713 1607 4944 3316 2818 7431 1166 6475 1105 1780 5602 5682 6187 4856 7860 3409 4299 3875 3364 4489 3995 1565 4798 2285 1420 5877 3158 3045 2505 1329 9029 1967 7691 3366 7301 2855 4228 3900 2025 3340 6056 5221 5220 1911 2349 3789 3567 2859 3079 5720 1134 3072 1291 22613 20435 13975 14789 5745 5492 1882 3895 6104 8598 3351 1932 4913 2592 1662 3183 3923 5857 6563 3160 3119 5727 6071 3931 6513 1218 10399 3885 3363 2470 9626 3802 6307 2664 9753 10741 1295 3046 1421 4492 2172 6367 5986 1478 1235 1913 1700 2661 3187 3694 1704 2332 2555 1548 1891 3985 2238 3802 4168 5491 1374 5104 6353 64543 2774 7026 2622 1898 7236 1896 4399 3438 2436 2732 7431 2737 5452 3365 8054 2730 4786 11186 2474 22732 2187 2855 7552 9401 6355 10015 4238 9319 7351 5587 3761 6320 4344 7272 1465 1207 5586 6134 2607 6004 6759 4749 4338 1058 5400 3173 3262 7818 6438 5852 6804 11175 14866 6020 1809 1258 4816 3171 6714 2291 4243 4824 10385 4451 3102 5924 6672 1872 1009 1176 5943 2068 3702 14085 14731 5651 6762 1985 5851 7277 1493 7316 1193 3737 3291 1918 9163 3715 5271 8317 3085 2782 7762 5383 1195 2050 4127 1946 5662 1608 6606 6708 2771 5533 2638 6048 8916 2959 16153 3649 17831 11271 4407 11756 1932 5296 4133 3164 2942 5498 4442 4447 3267 4143 2401 5074 1831 4235 1529 1414 4775 3829 3121 3573 3423 3269 1017 4698 5104 2655 2427 5958 1209 7712 3681 6730 6569 1763 5465 2218 4656 1828 2045 10343 3841 7177 8506 12930 3801 4977 5578 2208 4739 4811 2201 3004 5233 4112 5234 5615 2187 7309 7544 1423 2269 5221 4858 4996 1683 9331 1834 6149 6941 1568 1886 6818 7022 5841 5568 8000 3910 8233 5998 2020 6423 7691 1420 5081 8221 5648 7694 14918 18742 10687 19905 3390 8841 2124 10402 4664 10831 9777 7834 10672 9873 6758 1471 11828 1679 6895 6007 2245 8309 3319 1232 10468 51082 2292 6231 3446 3591 1553 1615 1514 6233 6327 3430 1732 5356 4799 2583 4699 5594 3530 3477 3473 4356 3594 5404 2738 5766 5897 2218 1597 3830 4683 4634 6635 5255 2092 6636 3209 7142 1022 6301 9915 4277 11866 10155 24693 24851 4192 10576 9003 7156 11894 8088 14949 19773 13274 4683 22445 14904 10069 9513 7768 11446 6753 12021 2863 6080 3395 2648 6585 1411 3363 5331 2830 1437 3281 5924 6409 6012 4523 1688 5603 3035 3220 7254 4670 6197 4181 6032 4619 2186 5986 5703 3074 7566 4097 7971 4868 7182 5065 1279 10973 9182 13792 9868 1509 9266 2846 4728 5432 1085 4273 1620 3800 1631 1141 4895 1402 5547 1131 2330 8273 3309 8168 12350 11300 4743 11440 5977 1085 13808 2190 9288 2271 11361 4963 1680 7510 5354 2117 7728 6051 5256 3478 1075 1961 3812 4709 2691 4316 3328 2828 2937 2812 1539 5201 1182 2697 2406 2574 4539 4415 8204 1583 10931 7518 3135 11661 3389 5173 5986 3872 3959 8821 7434 2166 8156 2463 4935 7038 6770 5818 6881 2282 7335 4367 1801 2507 4071 9939 14902 7567 15568 10587 2163 2588 2715 4589 6593 6838 4404 3186 4271 3686 3641 5165 5708 6209 13133 25360 3109 5778 4388 1042 4937 8197 1456 8167 9199 7098 14027 6382 1660 2778 8067 3405 2429 6503 7984 5799 7534 5088 9638 14010 5875 6893 2598 2706 3987 4140 3171 5672 5529 3617 5198 2429 2728 4763 2852 5389 3719 1285 4554 3677 5209 3827 5062 4835 8068 4674 5854 6077 6747 6325 4287 7242 6317 3989 6724 1754 5498 1931 10902 11104 10540 4778 7178 4711 1705 3407 6048 3364 3743 3938 4784 6080 3543 1957 2590 2031 28157 6204 7129 7476 1886 10496 4930 2967 1258 3532 4133 2586 1916 4464 1008 3310 5367 4347 5569 3878 3210 2442 2355 5997 3101 4460 18575 6967 17122 1720 2723 5410 8981 3355 4210 2549 3094 14639 17107 14832 3736 24734 3133 3998 5708 6961 1514 3927 4208 5004 2708 1381 5082 4476 4021 1075 1593 3541 2463 4776 4665 6168 1928 6421 3967 5875 2584 1946 3506 1054 1846 4946 3394 7435 7099 3703 6746 2129 1980 4505 7828 8885 8007 4297 1731 3825 1728 4304 3217 12089 2242 10288 9462 11809 10335 3139 10617 6833 1976 3093 8219 7749 5487 7508 6975 5363 4141 3823 7609 5667 4064 7969 6803 1600 8970 8154 3949 9138 6012 4745 6778 5215 8264 3784 14282 5819 13811 5523 3645 12004 8659 1039 1507 3797 2568 12129 3547 7073 5035 2269 7986 6478 5045 6103 1003 7281 7503 2567 6027 6497 5871 2833 2117 4851 4934 6324 4101 2032 4308 4369 4262 15796 13104 9996 4521 4209 4691 11223 1369 11416 8253 8708 11136 15770 1132 1488 4493 5822 3022 4249 1436 5324 4237 3740 3071 1298 5247 5217 6199 9151 9154 8903 9415 6703 7137 7053 4727 15631 16811 14050 5183 4988 3932 6304 6914 4061 5694 5111 3668 5769 6458 6400 3736 ================================================ FILE: exm/aoc/2022/aoc_2022_01_questions.txt ================================================ --- Day 1: Calorie Counting --- Santa's reindeer typically eat regular reindeer food, but they need a lot of magical energy to deliver presents on Christmas. For that, their favorite snack is a special type of star fruit that only grows deep in the jungle. The Elves have brought you on their annual expedition to the grove where the fruit grows. To supply enough magical energy, the expedition needs to retrieve a minimum of fifty stars by December 25th. Although the Elves assure you that the grove has plenty of fruit, you decide to grab any fruit you see along the way, just in case. Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck! The jungle must be too overgrown and difficult to navigate in vehicles or access from the air; the Elves' expedition traditionally goes on foot. As your boats approach land, the Elves begin taking inventory of their supplies. One important consideration is food - in particular, the number of Calories each Elf is carrying (your puzzle input). The Elves take turns writing down the number of Calories contained by the various meals, snacks, rations, etc. that they've brought with them, one item per line. Each Elf separates their own inventory from the previous Elf's inventory (if any) by a blank line. For example, suppose the Elves finish writing their items' Calories and end up with the following list: 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 This list represents the Calories of the food carried by five Elves: The first Elf is carrying food with 1000, 2000, and 3000 Calories, a total of 6000 Calories. The second Elf is carrying one food item with 4000 Calories. The third Elf is carrying food with 5000 and 6000 Calories, a total of 11000 Calories. The fourth Elf is carrying food with 7000, 8000, and 9000 Calories, a total of 24000 Calories. The fifth Elf is carrying one food item with 10000 Calories. In case the Elves get hungry and need extra snacks, they need to know which Elf to ask: they'd like to know how many Calories are being carried by the Elf carrying the most Calories. In the example above, this is 24000 (carried by the fourth Elf). Find the Elf carrying the most Calories. How many total Calories is that Elf carrying? --- Part Two --- By the time you calculate the answer to the Elves' question, they've already realized that the Elf carrying the most Calories of food might eventually run out of snacks. To avoid this unacceptable situation, the Elves would instead like to know the total Calories carried by the top three Elves carrying the most Calories. That way, even if one of those Elves runs out of snacks, they still have two backups. In the example above, the top three Elves are the fourth Elf (with 24000 Calories), then the third Elf (with 11000 Calories), then the fifth Elf (with 10000 Calories). The sum of the Calories carried by these three elves is 45000. Find the top three Elves carrying the most Calories. How many Calories are those Elves carrying in total? ================================================ FILE: exm/aoc/2022/aoc_2022_02.adb ================================================ -- Solution to Advent of Code 2022, Day 2 ------------------------------------------ -- Rock Paper Scissors -- -- https://adventofcode.com/2022/day/2 -- Copy of questions in: aoc_2022_02_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_02 is use HAT; c, sep : Character; f : File_Type; -- verbose : constant Boolean := False; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; -- type Object is (Rock, Paper, Scissors); them, you : Object; function Defeats (opponent : Object) return Object is begin case opponent is when Rock => return Paper; when Paper => return Scissors; when Scissors => return Rock; end case; end Defeats; function Is_Defeated_By (opponent : Object) return Object is begin case opponent is when Paper => return Rock; when Scissors => return Paper; when Rock => return Scissors; end case; end Is_Defeated_By; score, total : Integer; begin Parts : for part in 1 .. 2 loop total := 0; Open (f, "aoc_2022_02.txt"); Read_Data : while not End_Of_File (f) loop Get (f, c); them := Object'Val (Character'Pos (c) - Character'Pos ('A')); Get (f, sep); Get (f, c); case part is when 1 => -- In the puzzle's part 1, the second column with X, Y or Z -- seems to represent what your move should be. you := Object'Val (Character'Pos (c) - Character'Pos ('X')); when 2 => -- Actually the Elf explains that the second column -- contains what the outcome of your move should be. case c is when 'X' => -- You lose you := Is_Defeated_By (them); when 'Y' => -- Draw you := them; when 'Z' => -- You win you := Defeats (them); when others => null; end case; end case; score := Object'Pos (you) + 1; if them = you then -- Draw score := score + 3; end if; if you = Defeats (them) then -- You win score := score + 6; end if; if verbose then Put_Line (+them'Image & ' ' & you'Image & ' ' & score); end if; total := total + score; end loop Read_Data; Close (f); -- r (part) := total; end loop Parts; -- if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: total score, rule #1: " & Integer'Image (r (1))); Put_Line (+"Part 2: total score, rule #2: " & Integer'Image (r (2))); -- Part 1: validated by AoC: 14531 -- Part 2: validated by AoC: 11258 end if; end AoC_2022_02; ================================================ FILE: exm/aoc/2022/aoc_2022_02.txt ================================================ A Y C Y C X A Y C X C Y B Z A Y A Y C Z A Y A Y A Y C Y A Y A Y A Y A X B X A X A Y C Y C X A Y A Y C Y A X A Y B Z A Y C X A Y A Y C Z C Y C X A Y A Z A Y A Y A Y A Y C Y C Y B Z B Z C Y B X A Y A Y A Y C Z A Y C X A Z C Y A Y A Y A Y A Y A Y C X A Y C Y A Y C Y A Y A X C Y A X A Y C Y C Y A Y C X A Y A Y A Y C X A Y A Y A Y C X A Y C X A Y A Y C Z A Y A Y A Y C X A Y A X C Y A X B Z C Y A Y A Y B Z C Y A Y A Z C Z C Y B Z A Y A Y C Y A Y C X A Y A Y C X C X C Y A Y A Y C X A Y A Y A Y A Y C X C Y A Y A Y A Y C Z A Y C Y A Y C X C Z A Y B X A Y C X A Y B X A Y C Z A Y A Y A Y A X A Y A Y A Y C Y A Y A Y A Y A Y C Y C X A Y A Y A Y A Y C Y A Y A Y A Y C Y B X A Y A Y A Y A Y A Y A X C Y A Y C X A X B Y A Y C X A Y C Y C Y A Z C Z C X B X C Y A Y C Z A Z A Y C X A Y A Y C X A Y B X C X A Z C Y A Y C X A Y A Y A Y B Z C Z A Y A X C X A Y A Y C Y A Y A Y A X A X C Y C X B X A Y A Y A Y A Y B Y A Y C Y A Y A X B Z A X C Z C X C X C Y C X C X A X C X A Y C Y A X C X B Z C Z A Y C X B Y A Z C Y C X A Y A Y A Y C X A Y A Y A Y A X B Y C Y C X B Z A Y A Y B Y A Y A Y A Y C X A Y A Y A Y A Y A Y A Y A Y A Y A Y C Y C Y C Z A Y C Y A Y A Y A X A X A Y A Y C Y A Y A X A Y A Y C X A Y C X C X C Y B Y A Y C X A Y A Y A X A Y A Y A X A Y B Z C Y A Y A Y A Y C Y C Z A Y A Y A Y A Y A Y C Y C Y C Y C Y C Y A X C Y A Y A Y A Y A Y C X A Y C Z A Y B Y A X A Y A Y A Y C Y C Y A X C Y A Y A Y A Y B Z A X A Y A Y A Z C Y A Y C X C Y C Y C Z B Y C X C X A Z C Y A Y A Z A X A Z C Y C X B Z A X C Y A Y C Y B Z A Y A Y C X C X C X A Y B X C X C Y C X A X A X B X A Y A Y A Y C X A Y C Y C X A Y B Z A Y A Y A Y B X A Y A Y A Y C Y A Y C X C Y C Y A Y B Z C Y C X C Y C X C X C Y A Y A Z A Y A Y A Y A Y C Z A Y A Y C Y A Y A X C Z C Y C X C X A Y A Z A Z B Y A X C X C X A Y A Y A Y C Z C X C X C X A Y C Z A Z C X C Y A X C X C X A Y C Y C Y B X B Z A Y A Y A Y B Z C Y A Y B Z A X C Y C Y B X C X B Y A Y B X C Z A Y A Z C Z C Z A Y A X A Y A X C Y A Y A Y A Y C X C X C X A Y A Y A Y A Y A Y C Y A Y C Y A Z C X C Y A Y A Y B Y C Y A Y C Z C Z A Y B Y A Y A Y A X C Y A Y A Y A Y C Z C Y C X A Y A Y B Z C Y C X C Z A Y C Y A Y A Y C X C Y C Y A Y C Y C X C Y A Y A Y A Y A Z B Z A Y A Y A X C Z C X A Y A Y A Y C X C Y B Z C X A Y A Y A Y C Y A Y C X C Z C X A Y A X A Y C Z C X B Y A Y A X A Y B Y A Y A Y C Y C Z C Y C Y C X A Y A Y A X A Y A Y A Z A X C Y A Y C Y C Y C Z C Y C Y A Z A Y C Z C Y C Y C Y B X C Y A Y C X A Y B X C Z C Z C Y A Y C X A Y A Y A Y A Y C Z A Z A X C Y C X A Y A Y C X C Y C Z C X C Y A X A Y A Y B X A Y A X C X A Y A Y A Y B Z A Z B Z C X B Z A Y C X A Y C X A Y A Y C Y A Y A Y B X A Y C Y A Y A Y A Y C Y A Y A Y A Y B Y A Y C Y A Y A Y A Y A Y C Y A X B X A Y B Z C X A X B X C Y A Y B X C Y A Y B X A Y C X B X A Y A Y A Y A Y C X C X A Y B X C Y A Y A Y A Y A Y B X A Y B Z C X A Y B Z C X C Z C Z B X C Y A Y A Y A Y A Y A Y A Y C Y A Y A Y A X A X C X A Y C Z C Y A Y C X A Z A Z A Y C Z A Y A Y A Y C Y A X C X C Z A Y A Y C X B X A Y A Z C Y A Z A Y A Y A Y A Y A Y B X A Y C Y C X A Y A Y C Z C Z C Y A Y B Z A Y A Y A Y A Y A Y C X A Z A Y C Y A Z C X A Y C X A Y A Y C Z C Y A Y A Z C X C X A Y B Z A Y B X C Y C X C Z A Y A X C X C Z C Y C X A Y A Y A Y A Y A Y A Y C Y A Y C Y A Y C Y B Y A Y A Y A Y A Y B Z C Y A Y C Y A X C Y A Y B Y C Y C X C X A Y A Y A Y C X A X A Y A X C Y A Y A Y C Y C Y A Z A Y A Y B X A Z B X A Y C Y A X C Y C Z B Z A Y A Y C Y A Y C Z A Y A X A Y C Y A Y A Y A Y A Y A Y A Y A Y A Y C X C Y A Y A Z A Y C X A Y C Z A Y C X A X A Y C Y A Y C X A X A Y A Y A Y C Y A Y C Y A Y B Y C Y C Y A Y A Y A Y A Y C Z A Y C Z A Y C Y B X A X C Y C Z A X A Z A Y A X C Z C Y A Z C Y A X A Y A Y A X C Z A X A Z C Y A Y C Y A Z B Z A Y C X C X A Y A Y A X A Y A Y A Y C X A Y B X A Y C X A Y C Y A Y C Y C Z C Y C Z A Z A Y C Y C Z C Z A Y A Y C Y A X A Y C Y A Y A Y A Y A X A Y B Z C Y C X A Y C X B X C Y C Y A Y C Y C Y A X A Y A X A Y A Z C Z B X A Y C X A Y C Z A Y C Y A Z A Y A Y A Y C Y C Y A Y A Y C Y A Y C Y C Y A X A Y C X C Z A Y A Y A Y C X C X C Y C Y C Z A X A Y C Y C Z A Y B Y A Y C Z C Z A Y A Y A Y B Z A Y A Z A X C X C X C Z A Y C Z A Z C Y C Z C X C Y C X A Y C Y A Z A Y A Y A Y A Y C Y A X C X A Y A Y C Z B Z A Y A Y C X A Y C Y C Y B Z A Y C Y A Y C X C X A Y C Y A X C X A Y C Z A Y C X A Y C X A Y C Y A Y C Z A Y C Z A Y A Y A Y C Y A Y A X A Z A Y C Y C Y A Y A Y B Z A X A X C X C X C Z C Z A Y A Y A Y A X A X A Y A Z C Y C Y C X A Y C X B X A X A Z A Y B X A Y B Z B Z A Y B X C Y A Y A Y C Y C Y A Y A Y A Z A Y C Z B X A Y C Y C Y A Y B X C X C Y A X C X A Y A X A Y A Y B Z A X C Y A Y A Z B Y A Y B X A Z C Y C Z C Z C Z C Y A Y C Y C Y B Y A Y C Z B Y A Y A Y A Y A X B Z A Y C Z A Y A X C Z C X A Y A Y A Y B Z B Z A Y C Z A Y A Y A Y C Y C Z C X A Y B Z C Y B Z C X C X A Y A X A X B Z C Y C Y C X A Y C X C X A Y C X C Z A X C Y C Y C Y A Y A X C Y A Y A Y C Y C X C Y B X C X A Z A X A Y C Y A Y A X C Y A Y A X C X A X C X C Y C Y A Y C X A Y A X C Y A Y C Z A Z A Y A Y A Y A Z A Y B X B Z C X A Z C X A Y A Z A X C Y C Y B Z A Z A Y A Y A Y B X C Y A Y A X A Y B Z B Z A Y A Y A Y C X C X C X C Y A Y C Y C Y A Y A Y A Y A Y C Y A Y C X A Y C X C Y C Y C Z B X A Y C Y A Y C Y A Y A Y A Y A Y B Z C Z C Y A X C Y A Y C Y C Y A Y B Z C Y B X B X A Y A Y C Y C Y B X A X C Y C X C Y A Y A Y C X A X A Z A Y A Z A Y B X A X C X A X C X C Z A Y C X C Y C X C Y A Y C Y A Y A Y C Y C Z C X A Y A Y A X C Y B Z A Y C Y B Z C Y A Y C Y A X A X A Y B X A Y C X C Y A Y A Y A Y C X C Z A Y C Y A Z C Y A Y C Y A Y C Z C Y C X A Y C X A Z B Z A Y A X A Y A Y A X A Y A Y A Y A Y C Y C X A Y A Y A Y A Y A Y C Y C Y C Y A X A Z A Y C X A Y A Y C Y B Y C Y A X A Y A Y A Y C X A X C Y C Z A Y B Z A Z C Y A Y A Y B Z A X A Y C Y A Y A X B X C Z B X A Y A Y C Y A Y A Z A Y A Y A Y C X A Y A Z A Z A Y C X A Y C Z C Y B X C Y A Y C Z B Z A Y C Y A Z A Y C X C Y A X A Y C Z A Y A Y A Y A Y B Z A Z C Z A X A Y A Y A Y A Y A Y C Y C Y A Y C X A Y A Y A X A X A Y C Y C Z A Z A Y A X B X B X B Z C X C Y A Y A Y A Y C Z A Y A Y A Y C Y C Y B Y C Z B Z C Y B Z A Y A X C X A X C X B Y A Y A Z A Y A X A Y A Y C X A Y A Y C X C X A Y C X C Z C X B Z B Z B Z C Y B Z C Y C Z B Y A Y C Z A Y C X C X B Z B Y A Y A Z C Y C X C Y A Z C X C X C X A Y A Y C Y A Y C Y C Y A Y C Y C Z A Y B Y C Y C X A Y A Y A X A Y C Y B Z A Y A Y A Y A Y C X B X A Y A Y A Y A Y B X A Y A Y A X C Y A Y A Y C X A Y A Y A Y C X B Y A Z C Y C X A Y A Z B X A Y A Y A X C Y C Y C Y A Y C Z A Y A Y C Y B Z A Y A Y C X A X A Y A Y A Y B Z C Y A Y C Y C Y A Y A Y C Y C Y A Y C Y A Y B X C Y A X A Z A Y A Y C Y C Y A Y C Z A Z A Y A Y C Y C Y C X C Y A Y C X C Y A Y C X C Y C Y A Y A Y A Y C X C Y A Y A Y C Y A Y C Y A Y A Y C Y C Y C Y A Z A Y C Y C Y A Y A X C X A Y C Y B X C Y A Y A Y C Y C Y A Y A Y A Y B Z A Y C Y A Y A Y C X C Y A Y A Y C Y C Y C Y C Z A Y A Y C X A Y C Z A X C X B X A Y C Y A Y A Y A X A Y A Z B Y A X A Y C Y C Y C X A Y C Y A Y C Y A Y C X C X A Y C Y C Z C X B X A Y B X A Y A Y C Y A Y C Y A Y A Y A Y A Y A X A Z A Y B X A Y A Y C X A Y C Z A Y A Y C Y C X C X A Y A Y B X C X A Y C Y A Y C Y A Y B Z A Y C Y A Y A Y A Y C Z A Y A X C X A X A Y A Y A Y C X C Y C Y C Y A Y A Y A Z C X A Y A Y A Y C Y C Y A X A Y C Y B Y A Y A Z C X A Y A Z A X A Y A Y A Y C Y A Y A Y A X C Y A X B X C X C Y A Y A Y A Y C Y A Y A Y A Y A X C X A Y A Y A Y C Y A Y B Y C Y C Y C Y C Y A Y A Y C Y C Y A Y C Y C Y A Y C Y C X C X C Y A X C X C X A Z C Y C Z A Y B Z A Y A Y B X C Y A Y C Z A Y C Z A Y A Y A X C Y C X C X C Y C X A Y A Y C X A Y A Z B X C X C Y B X B Z A Y A Y A Y C Y A X C Y C Y C X A Y C X A Y A X C X A Y A Y A X C Y B Y A Y A X A Y C Y A X C Y A Z A Y A Y C Z A Z C Y A Y C Y A Y A Z C Y C Y B Z B Y C X C X B Z A Y A Y A Y A Y A Y A Y C X A Y C Y A Y B Y A Y A Y B X A X C X C Y A Y C Y A Y A Y A Y A Y C X B Z A Z C Y B Y C X A Y A X A Y A Y C Y C Y A Y A Y C Y B Z C Y A X C Y A Z A Y A Y A Y B X A Y C Y C X B Y C Y A Y B Y A Y A Y C X C Y C Y A Y A Y C X C X C Y A Y C X C X B X C Y A Y C Y B Z A Y B X C Y C X A X A Y C Y A Y A Y A Y C X A Y C X C X A Y C Y A Y B Z C X C Y C Y B X A Y C Y A X A X B Z C X A Y C Y A Y A X C Y A Y A Y A X A X A Z C Z B Y C Y C X A Y A Y C Y A Y C Z C X C X C Z C Y C X C X A Y C Z B X C Z A Y A Y C Y C X C Z C X C X C Y C X C Y A Y A X A Y C X A Y A Y A Y A Y A Z C X A X B X A Y A Y C Z C Y A Y A Y C Y C Y C Y A Y A Y A Y B X A Y B Z A Z A X A X C Y A Y C Z A Y A Y C Y A Y A X C Y C Y A X A Y C Y A Y C X A Y C X A X A Y A Y A Y B X C Z A Z B Y A Y B Z B Z A Y C Z B Z A Y A Y A Y C Y B X A Y C X A Y C Z C X B Y C X C X B X C Y B Z A X A Y B Y C Z A Y A Z A Y C X A Y A Y C Y C X B Y B X C Y B X C Y A X A Z A X C X B Z C Y C X A Y A Y A X B X C X A Y B Y C Z A Y C Y A Y A Y A Y B X A Y C X A Y A Y A Y A X C X A X C Z C Y A Y A Y C Y A X C Z A Y A Y A Y B Y C Y C Y C Z C Z C Z A Y C Y A Y A Y A Y A Y A Y B Y C Y C Y A X C Z C Y A Y A Y A Y C X A Z A Y A Y A X A Z C X B Y A Y A Y C Y B X A Y A Y C Y C Y C Z A X C Y C X C X C Z A X B Z C X C X C Y C X C Z C X C X B Z B Z A Y B Z A Y A Y A Y B X C X A Y C Z A Z A X A Y B Y B X B Z A Y A X A X A Y C X B X A Y C Y A Y A Y C X C Y C X C Z B X C X C Z A Z A X A Y A Y A Y C Z A Y C Y C X A Y A Y C X C X A Y C Y C Z C Y C X B Y C Y C X A Y B X C X A Y A Y C Y C Z A Y A Z B Y A Y B X C Y C Z B X B X C X A Y B Z A Y A Y A Y A Y C X A Y A Y C Z C X B Y C Y C Y A Y C X B Z A Z C Y A Y B Y B X B Y A Z C Y C Z A Y C Z C X A Y A Z C Z A Y A Y A Y C X A Y C Y B Z A Y C X A X A Y C Y C Z C Y A Y C Z A Z A Y C Y A Y C X A Y A Y B Z A Y A Y A Y C Y C Y C Y C X C Y C X B Z A Y A Y A Z A Z A Y A Z A Y A Y A X C Z A Y A Y A Y C X C Y C X A Y A Y A Y C Y C X B Y A Y C Y C Y A Z C Z A Y A X A Y A Y B X A Y C Y A X C Y A Y A Y A X C Y A X B X C Y A Y A Y A Y A Y C Z C Y C X A X A Y C X C Y A X A X B Y B Z A Y C Z A X C Y A X A Y C Y C X C Y C X A Y A X A Y A X C Z A X A Y C Y C X C Y C X A Y C Y C X A Y A Y C Y C Y A Y A Z C Y A Z A Y C Y A Y A Y C Y A Y B X C X C Y C X A Y B Y C Z A Y C X A Y ================================================ FILE: exm/aoc/2022/aoc_2022_02_questions.txt ================================================ --- Day 2: Rock Paper Scissors --- The Elves begin to set up camp on the beach. To decide whose tent gets to be closest to the snack storage, a giant Rock Paper Scissors tournament is already in progress. Rock Paper Scissors is a game between two players. Each game contains many rounds; in each round, the players each simultaneously choose one of Rock, Paper, or Scissors using a hand shape. Then, a winner for that round is selected: Rock defeats Scissors, Scissors defeats Paper, and Paper defeats Rock. If both players choose the same shape, the round instead ends in a draw. Appreciative of your help yesterday, one Elf gives you an encrypted strategy guide (your puzzle input) that they say will be sure to help you win. "The first column is what your opponent is going to play: A for Rock, B for Paper, and C for Scissors. The second column--" Suddenly, the Elf is called away to help with someone's tent. The second column, you reason, must be what you should play in response: X for Rock, Y for Paper, and Z for Scissors. Winning every time would be suspicious, so the responses must have been carefully chosen. The winner of the whole tournament is the player with the highest score. Your total score is the sum of your scores for each round. The score for a single round is the score for the shape you selected (1 for Rock, 2 for Paper, and 3 for Scissors) plus the score for the outcome of the round (0 if you lost, 3 if the round was a draw, and 6 if you won). Since you can't be sure if the Elf is trying to help you or trick you, you should calculate the score you would get if you were to follow the strategy guide. For example, suppose you were given the following strategy guide: A Y B X C Z This strategy guide predicts and recommends the following: In the first round, your opponent will choose Rock (A), and you should choose Paper (Y). This ends in a win for you with a score of 8 (2 because you chose Paper + 6 because you won). In the second round, your opponent will choose Paper (B), and you should choose Rock (X). This ends in a loss for you with a score of 1 (1 + 0). The third round is a draw with both players choosing Scissors, giving you a score of 3 + 3 = 6. In this example, if you were to follow the strategy guide, you would get a total score of 15 (8 + 1 + 6). What would your total score be if everything goes exactly according to your strategy guide? --- Part Two --- The Elf finishes helping with the tent and sneaks back over to you. "Anyway, the second column says how the round needs to end: X means you need to lose, Y means you need to end the round in a draw, and Z means you need to win. Good luck!" The total score is still calculated in the same way, but now you need to figure out what shape to choose so the round ends as indicated. The example above now goes like this: In the first round, your opponent will choose Rock (A), and you need the round to end in a draw (Y), so you also choose Rock. This gives you a score of 1 + 3 = 4. In the second round, your opponent will choose Paper (B), and you choose Rock so you lose (X) with a score of 1 + 0 = 1. In the third round, you will defeat your opponent's Scissors with Rock for a score of 1 + 6 = 7. Now that you're correctly decrypting the ultra top secret strategy guide, you would get a total score of 12. Following the Elf's instructions for the second column, what would your total score be if everything goes exactly according to your strategy guide? ================================================ FILE: exm/aoc/2022/aoc_2022_03.adb ================================================ -- Solution to Advent of Code 2022, Day 3 ------------------------------------------ -- Rucksack Reorganization -- -- https://adventofcode.com/2022/day/3 -- Copy of questions in: aoc_2022_03_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_03 is use HAT; T0 : constant Time := Clock; si : Character; f : File_Type; s : VString; function Score (c : Character) return Natural is begin case c is when 'a' .. 'z' => return 1 + Character'Pos (c) - Character'Pos ('a'); when 'A' .. 'Z' => return 27 + Character'Pos (c) - Character'Pos ('A'); when others => return 0; end case; end Score; type Set is array (Character) of Boolean; group : array (0 .. 2) of Set; procedure Reset is begin for i in group'Range loop for c in Character loop group (i)(c) := False; end loop; end loop; end Reset; line, t1, t2 : Natural := 0; count : Natural; item : Set; begin Reset; Open (f, "aoc_2022_03.txt"); Read_Data : while not End_Of_File (f) loop Get_Line (f, s); -- Part 1's job: Add priority of the item that ----------------- is on both halves of each sack. for c in Character loop item (c) := False; end loop; for i in 1 .. Length (s) / 2 loop item (Element (s, i)) := True; end loop; for i in Length (s) / 2 + 1 .. Length (s) loop si := Element (s, i); if item (si) then t1 := t1 + Score (si); exit; end if; end loop; -- Part 2's job: Add priority of the item that is ----------------- on each sack of a group of three. for i in 1 .. Length (s) loop group (line mod 3)(Element (s, i)) := True; end loop; line := line + 1; if line mod 3 = 0 then for c in Character loop count := 0; for i in group'Range loop if group (i)(c) then count := count + 1; if count = 3 then t2 := t2 + Score (c); end if; end if; end loop; end loop; Reset; end if; end loop Read_Data; Close (f); if Argument_Count >= 2 then -- Compiler test mode. if t1 /= Integer'Value (To_String (Argument (1))) or t2 /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Priorities of items present in ..."); Put_Line (+" (part 1) both half-sacks . . . . . . . : " & t1); Put_Line (+" (part 2) all sacks of a group of three : " & t2); -- Part 1: validated by AoC: 8185 -- Part 2: validated by AoC: 2817 end if; end AoC_2022_03; ================================================ FILE: exm/aoc/2022/aoc_2022_03.txt ================================================ shzsFcPssFhjFssBzdpRcNHNZrpdJdJVJZ fwvMCntfCCbSbSbtDgDNrDtDtJHZVH GbCwwbwwnGrLhBzjFFFsWPhL PpCqRsqqmmtCwMJC LHFrLLHDSNHlfWNhDzmjzzJlJzPJMvPJjQ SGSWDNrhZhPDSWDZLgVVRgbRppgpGVnpnn GRRjbVjmJZlgMRzzrN FpDptHpfHfnpPTvDFTWpFPnPcMfNCClNrzcVcrMMzVsCZlsZ TFTQDnvLHPFDtVbLwbjdGjdwwJ lhljvvhCjjzhjszzBPmnmGVZMGzG FbTcTwbtSFdtcMPnTBPQVnnBZT SFMpHDtNDSSbSdwppvgJWjJCJJgWgvlJHH wzNCWpzCzJnWWpRRNdJrgHLhjfbLrHrchV lBMStmPmmLQDPQZlshrdhgrfrcrrddgHgs mvGDGQSvDPBlGMLGCvCWpNvpzRWFwqRw stBttBThtDZqPWssPWZp gRggwwggCGFSBBvPRpHZZrHdZLZq ccFJGCNJmmGQzbTDhnQhBBnB HJqMqtZbJMmJTqtLtVMqhpfphNdQfhfzzjhhlHll rWSBrnwFwWCvwWCwBgPgCgzjQccQhhgRzcdQzjfcNfzR CWBCwCvCvvwssWLMtJJGMdMZJsGV nFwSFQwsNrrsssSwCrhrCNnfcCRgJRMJTJcMfRzMCMCRvW DdbGdLZLttllWWvTzgzzgR ZqGzPdLtDjBjDZGPZVmnhQFwqrFQhVFnss sNNpCjttjsJjSpgpWjslCTnqqSVffrnhSfDhmhrhfm dBwcGzbPBHbbwZcwJbcTTFDFFFDVrdVmFdnDqf HzGcczQPHGwzPzGHRctWlvRgtvJlvNlJvRNj cFNCFdvcCHvFBCZcwBfRSpttGhDmCghGShmSRt QjLnTTzQVzTTnLMqhDgPhGDDSjGPrgSh TTJGnJJlLQdNWZWJNBJZ WHBpHcMDZHLDbHLtGCnmRmLNGmRqvsCC PzTFzPPTJzrSbGsvnmqfsqfqRz dJSQQdVFQgjTrjQPWcWHbBVcZVccZtWp JDtnRtJzNzTTNlHc rQPJFrLPGMMwrGPFwjFMVLjSTWHdWBTdSWdWZlcWTHlZ MGFrCvLLwrwPFVVhvLMGGtnqfsmRJgDnqbRgfbqmfC jnTtFjcSSvctJjznzvFmpqqPMqQDRVpRqPzqQzVQ bhHBfrWpfHsfGNllRrRCPqDCqPqq gsGZZpbWgbwHWGNgfZNjvLSTTjtnTgjSSSSJmL RLQNdVNnRQdQHVVLGpspNqvtsqptqpTtsp MlRWwbRBBFMFjCTFTTFDvj WmlWBmBwwmrndnmLRHRQ WnftJWlfnWSHGCjWWWSCFqFGBDqBwMcDmmMmGmqD pTNhpTrPhhhRPzbhrppLhThLgqDmwccwqPBmMMqnFBcwwmBB ZrhQTpzdjSVVtnvZ jgtnJtBjtlTdJBZJVQBngQGDCGWpPGCcPWCbWdWMbcpP wHstNNttSHPDmHcMCp rrFFSvLLNfsFtNSqrtfrhsNjjVTBVgVvnTBvTQvjTgjVZz qhZwlqFqFwlJwrDHqHcDvgcNzv RCCTQmjCbQTBtRTbjJRDpBrgDHPPpPDvHccDPc VmjVWstQJhlJlGVJ GggpGwZmgvgJMvbJFQQDbDFbBbFCQDCW rtrLzNLtNSPnNqDSQDcQCWlqBQ VtzdRPtztLtVRtZmmMTRwCGZpMwp vtvqjsCqtshfjcWFHWGjGFJj zGrnzDDMpPcTHcSTVTJP DbDwMbZRDrZdBBnMznZMGZDfwtlgQhsqCttClsqvsLfCff JLzLtLsrzsQdvrWRwMHwcc qPmCTzlPjljjFTZmWwcwwvHMMRWwHvMm PFqZnVCqTCNjCzNgQsbGBLzLQQ CBnppDHllVpPCBshBHpjDTSmZcSrfwvmJcDDTJfw dFRLdLFQzNSTBTSNmBJv FzFFzRMBFWtQlPlsjjPVMnhC CVCfwnfdVvBdBbTNTT LNzsHPNWsDjTZqDHqT PtLgQsGQLSzWLstPgGWcgQLSNrpplffrnrNhpVCwlGVlrwMn jPPVqPsHffzVnHzvSgMcCJGGMSVCll pdbpDpBLNmNNppJgcvgSllGjDSGQ hrbBwLpjLhhhNZLhNrhZZLHzfsztFzzsrtHfRFnFfRHf tdjBdbmSfdHBdHHmZlWjFrnlWQlqvMFvFn pDNDJhLhPVPLLLJphJLwNcwnQTcWWTqTrqMWTZvqMrlvFM gpVLhNwpgZJCghCLDNwphgmsBdzHHHmSstmfggzdbR TfMpfMBVftLMDBSjWDHgzHbgwLgHHvdzggzs QJnZcFFnZRHdHjJvwgdg RjjRRnmNmmZNjZqZnQcVffBrWqVTqrtffTSTVV fZTdTVcVjrjdBzdTnGtgnnGSHHNFGn thMWPtPMslmGnWnNnS thvbMvQMRphhLCjrzBjZVdcQfC MpmgZFgMGdrFrBCVnJ JsbJlTTlvLQbVffRRvBBRVjd LWlbhHlJhLTJmmGcMMHNmNgN bhvmhPrbhqNqQRRGzQjVvvRL wTwBZDBTwwggfnngcDfdsVVFQCdzCzDVRsFdQs pngWMcgzMgpZWncnMpWNrbNHrNbmHhltWlbl nPndBjLPscWSccBVGnScsSzMdhMppMthdMgpMgrzvhhp CCFTFDwqZqCCJmhvpDzztVzDNztp qQFJTbRVbmCfwTwfmnnssWBGnLnWlRLSGn JRlJDSvLRRCdvmDSvdlbZNVBSWZGNgWsZGNgZBVs QrjPMqMnLzzjLjFnNNgBpsgtgGGGVZ hrjrFqjqFrQfMHPhQzDvvCLJdwwwmvbJbwDH HDGrDDDpNsGQNdZQ jpjgtgjSjpjllfZZtZsvNdtshqqq cbgMfjclWTJcMwjWJfpfmVPLPBnVBHnmVbnmLBbD rPrMZNsNrsvrwqvFFFdgQWNzLJJzRW pStppStHmcmHpgVSllVcbVbWWDdLFhdbzdRRFhJFLLRF cltCHmCBmtSlgjpllgGvTwPZPMfZvPsCMCwZvC FRQQMdlFMDWRFQRQMQQDWdFbSSSVJSBbJSlBVVBnPJnzJL rsftPfhsrgwznSzzHSLgJG fhNsjrjhvsTTvdjcCRMRMRPcCW tRtJttHFrjtDQHHBQMMBgMBSghhZQb vqWPLpLvqrmPdmqwvqfmPhNBBBlSnbwbgnlnlhNSZZ pGpdfzLLspddmqsqPvfvvPpGTVcJJCDRjHrccRtDjcRDFD GJMHCdTMWJRhSTlhhSPllt fVvqpfBFrqvqNzzgVDFrpDPmSVtQSlSmhjwltlRtmVhn pzpBNDBzfDrsNsDRJJRdCssMLdLZWZ hFfvWWvdpCwwcwFhphpcZCMmllHLfmbQlbrQLBJmGgQrQm nVSNGjGzzSVNTsjzSJrbSrHBSHlrrmQHJB PttTNsTRVnNjNqRnzRzRWCCCcpMCWGPMwwFZvFwW DvZbFnDDsqDBwwRQgNBm HhWpWWRMWChlChdHLlGlGtQtggSNPSSpgPmNgPJQtw CMlWGMhhCVHlLCdHTHdrGHdbzjVqnzcvqqjRjFbbzbFFqR ZZgCNqqBmjZsNgZCqJgNBdrLFHbBrWlPdHWFbPnHPW TVwTDfzDwSDzmcSTcrzdbllnHPHdFlLzbF tvDQwVtVvDVmtRsNMgRpJg BBpDCpNJnmnpnDDmDGGmtTzqHcGTvTTjTbGjHLVcLb swNNhPwwHzTVwwHw rPRlPRhSQmmBDpnNfl pbRhffPzcPDmfcNTpVBLpBjMGBGjZLLg ssrCsqrszgJjZMqZLQ SzCwnsllCrssvdrvwzPmDmPPbFRbSThPTPDD QWLfcfczQQpcDTpLPfdZRRvRRVqbFWvZbvtqvv NsGGJBhCmNdZVqsbdssZ rMwwwBBJMrdzPfQMpzMnLQ rdtCQhrCtQQprtTWQCHFjPgGBPdFPgvBqRRPqB lsVsSnVSbLmmgBcgTLTFGgvq wTTDTszsbzMDppJrJhDQ ZlmsGLBVCBBZFCFFHqcHVvQhqVQSSHpH dbbTRMrRwwzDfrTbFtMvcptvHFQQpqtc gdJTDWgfwDwTwmgmNPnNsgFBlZ PWhWhGFzzzrLdHCPccbJQJcHPD NRpVTpTgRWVlHJNHMcHQMb pSRSpVSZWRSTZjgTRTWnFLdZLrrndhdzZvtvzn LgctLgVBVLhlPjqRhBLVcVlhbDDcGnNGfwCrbNDnrGbGCJNw HmppHMWWmQmMqZZHWQrDDfDCffJrDGJrCb qpWZsZZZMZWTLPhTRgTtThRP hfhQfFQWzBfhfTQdmzdLDtDjtvHLjt qsgpcqMNRmgpqsCwpCmZDvjwvdddHZHvZDtrrd SgmNmqScbTSJbhJQ dvMTQvTnZJsrQdbbSvMVZMblDwlflfDGgwwHcfGjPfjjrG FqBLpBpFpFzRzqNFmgjGlDRHcwPPGwgcgs tLNtWshsLLqWMJhTQVVbhvJd bgZLMZgzbbLCcPCbMZbcNMgBqSTqSWVtSzvvTTBTqBvRBW FhQpJQnGrlhGlrnTqRtTRJqSwDwtVR FqlnnFnqFHnGHHdNZdbZbCNMdPLMPb HHFnbftcfnfbbTbTnHTNVZZzJlPQlFrFzVJFZsdr mvpGCBgwqCvLCqvMQWWzsQQWlPzwzsrV hpGSGgqSvqbHcnhfVfct lGVrnHsGcnVHzscrlGjHcrHqqWPlJCPJClTLLqCSPLPdqS fRbwbtMQZtMMRFMSqfJTTWCTJPJCmd ggdvtvdbVVGnpDGg BnBjTcbnvhjjlMnNJJfnDnQDGdNDfP qwFqVSWwqLpWFmFVCSqFpDDCJNJRQTRfRDGPfdfDQN zwHwWVVWWFSqqwWTLqzzztHMvBhlcghblMlcttMllh PFFNPNPmlFllbctNLmcjBstrsVrQHJSSHHSnnB fddfDhdwGhTWWTDMwMggssjsjndsBsjsnSrVqSVV MCvvTWvRMwCvGPpzCcmbplpCVC thTqlPPTNbGNhGdqRRhRrNtFWnDnvvFZDpnFvfQDZtvWvv HcMzVcVVcHrgHzcMcmmgfQvFQnMjnWDjfnvjQFfQ VSmHJLHBJrTrJTlT NjnsHjLLjNRddNdBFBSR ftsbqfDcDqsrDtqsfSVBhJVFJgdBRVFS wvDqwtDlsDDczjzjHvLzLQQM qDwstwDtRfpJfVhBVZBMvnlRvv zSFzQHFWdgZBVTZhTzrp NHdggjGjWHQFPWHNPPbpJfPDtCwCtqDqJfbt pvnbqHvnTvlCCpjsBsMGBGWWPp RJSJhJCRVJmJwScrhSJdfwFsBGhZBjhGFFFFGgFPGhZW cdRrdmwtfcdSmLtcSCQlvQNqQTlqqvtTlv rnSlSrgWjVGpTTRhSffpRd HtgHPsNNgNHszPcTBphMdhHhBcTc JNNbZPZZsszNmtDbPgsmJlwFvWVnCwrlmWlnjnGvCC WrVBVgVGGQCrSTTqvVjDqDjv FmwRRwwRQhhLFMjFMzdqSSzS RcJtbnnLtQWrGHcfrP vpzssjmVjVZWNZzzQwtQwccpQhgtQCct qDdfLMnMrrTbBLqTqltlTfbGQnghgRwggGgRnhhccCJJcG MtdLfSSSddMftlrjjzsSWVSjFvjNvs qTRPpRPzJglzGJzpGRHWHljwDtbwffjtbhjfwNfHmwwf SZLVdsvrrdFdBcdZvsBdDCNtbmftNwfNbNhCNvtz MLzzddLsQRppRlQGPq PDDpdJgtpppGgttgdGdgJFzLjVcvVnnCTrVrRPTLvwnTTC ZSbHBsSNlZcsfNnnvRrnVjrHwvCC NmSmsfsfhmzcDmctJW NbrLfrrLqpqWQHtBzbFttJgcgB CmwjPPjjjShPvljwvwwjPBFttBtcHzFJcHTRHJRRmT CCljjDGhvPCVdVSCdPvrrNfnnQsGqMpqqMqnFW bdPdbcDZlddsZbHjrrgrmZmCZhCGjv BffLfLVFVMMBRfwMpfzhFGFhGWvWvrhNvvNj RMBpRSnffBJjSbJqdPHsDcbqtl BgwGwDDZttDDTNND WzNNnFRWFtTFlFsh WJjPpPqqzWRbrqnNqvVvgvvdcBwgdrVBZG FFbMVMFPvJppgvcvrZMjHlCJWHmHHBlqhCmqChCl RGQVdVVLnLsQnQnnqWBlBmDRBDWWlhBD SftLzQndGfVgFfjvvM npvLlFLTWWqdLnJCmBmmpjQjjmjB tfgDwzwVVVVtgtrsJtrbjSPQjQmjNBCNBNhPHDHC ggVzVtMRgzMrvJLqFnnRnnRT gZFZssWgNZTDwHDWzsFwWDQMMpqqpBPMjFtMPSQFqqqM vrmvhdnVvQpftStnMN JCdLddhhdJdcCdrrmCGhlgNsWDWDwWsgwHgHLZHW vSsSGjSPvjvRSGpFprFbqFpppRfp ZdmlndtBZbwrwfpWFn JmdHdBBHtgllZldBhJZldLLBjPVQTfvGPNzQQSjjzPgTGNTs TjTjBjVrTsLRRrMBsMMgzLqGGqgQHQdCQGgpgd nbZcmNnPNcbNftvhlhZpgQgCqdSpgCHCqPFzSH WfcNvtmmNmQlvNcbsWWjMwMVMRDVMDJM hHHnfZSwHDgHcfclSGSnvrnvBCvWWntvzvzbWWVq dTJTmspFTsFdRRLvtvLzvvVqtPVtrb VFMNFpRJNTppTpsJVRcMGgfGfgZwghgGfcGh lLGvwsMJLCMVnTrCrVdHRd tbzqtDNNBpNWBtqzfRrFFnrVTTdrQVSVGp tztfzmfzzPDzgWNNBbhGMlJLsvhJJjGJhGmM rHrVJQVQVJLggDQQLbTvdCCSTdWLLLbCbS pNtnwPthmZGRpmPFtqbMSzqffFSdTvbSzW GpvvshwtmwsZDljjssHjVBVj SmhJdtJhhzQSrzVhtQbtBRNfnFNSnDNGRfFGGMgR lHwqPjqwTjLHCWLvPpvNrNMvnNGNfNGNBffGRN lCrPTrwpPZWlqPlqpWWqZjsmJzbzVtVhhdsJcQdddZVJ QqpCWHdQdVQlWcQCqcfRjnZZZPDnSPqPhhqZ tmmzgWGgwJwwStSZZDRnZssR GbFbLLvgmMMwGgmLCrppQrWVlWrFTHHd qdqCgSVdVSVqfwsdZhpJspZsph RjZBbmRlrlmmJwLNNNhLpwhB vZlRrtTZCzCMfSPT JBjhCNwjrlJlHJJRsscZrTcvLLgTsLPP dDztmntCSgbLgqTzgc fGVWnSMFtVGMNNNQllBjWHJC dSDhVVdVZtnSgHQGThQvFNQQqF LcfLRpMpcBpbrJfsbsscBNWRNPRGHvqPdTGPGqPWFH spmrCcrdJJpLLmcmLLLDlzSzCCjVwZVtgnSZzn ZJtgPTHtZPZQGbtNzzprVWWVrbrpCD BRlfcRmBhSMVBqSVfBvNWrDrjWCjjzprCDCl LfMRSmfqfSLcnnMqVSfccnhZwJFHZFTGZQGFLggwZTZGPJ BChWddRRRcfmDbfhDP MgpMFFsvMfGwvLgPjQPzPPmDcztDtw NFgJpqvpLgqFnWWVNSfnNSCR zMMMRmMfJpfhpzQJLMVtjtjPntgBtlZlVgJP SdNbZvZbvbHTNbZbSWTdrTVBglBDlWBjDPDgntPqBDPt rrNcrFwNdSrfzwMzZMLQQs JPmCSfHTGJdTCbHgpgqLgRhghhffhg ZWSSFVSVFQghQvwpphgh lsDtZjVMMSdCNdbGCbjb PBQPvDvVVRvQDqLDzJTlzwjz tGcZTcdgGcncdrFrsTjzJSJqJqqwHSzzSZwq CgtgdFgcFCMnMgsGFGGQWPQpQTCBvbNpNVVWVT FHVFWMHMgVhnLWWMpnppfcdZNcPplnfn RSvSCBSqGgDRjqCpPlPpppTpPjlcNP zRzsGgJDqJwLVWVFwM ThhWhNthVWTWqbWbFWbTdBtWSdMlHSlGlCGCdsCMClmnSlMn DPPpvvfDHfLgDHvzpvPDsssMsmmzsMcClScMMcGG rgPLHHJJHgZfvvZQQZfrpfFqBBwFBTNTBNBwtthQwVqt JJgSWDSmSDQCFrhbRLSwLS VznqzVNsMsZLdqslbRChtbHdHRrwHb LVfNLMsLTmWDpBpf cbTsnNpcnnchllFQlMRgJhRP WddmdMVSBMWSBWjwCJVCPRwPFCQRRC DWSSfjdSrTpDnHHMbZ fgsVqqwQQtHhCrDfJH pvbnBZWBbvWbTdthrJbDmqrmHq TvZSNSNNSvFMBpqpnLnTBZBFGQwlQFggcFzcVGRlswsRll zfMcQHzPtRNvlllc BLnMhbZMLJLNNVtCdNgZgt BJGFpqMBhBLLMqnwBhbrbhLssjFzssjfDzsmFmjmQFQPjT JPBJPnpBFrqBJHtjlCjHJcCthM wQZggQWQGfZFVmmGfDRjlvvNcvlNDhcNttlctt SfmWfwVFwVGZWQVGSTdTbBpTPSqBbLnnrn RJqBRJbqpqqJGvqHMmcfczfcjvHQfm llgVnSWSlsssTnlWjhTcsZMcZcZMZMcccMNmcH TnFhhllnWCnVCTllLnhhVSrbDDPrdpjRRqjBPRBBpbFJ mRwRRNDjNTqwDNjNnNRTsQLcQWpQWZJLlLpQWs PMFGCSzzgbBVzCGShVQZcgWsQLLftttQtlZZ SlGVldCGGbBPMhPCVSBrNNdjRqjDrNmDnmrRwN mqGGqGHnqGBCMrnGCbbbLgTTFFNNghHNTj SdRfcsDPPcDdRzWPWltSlscwTSbShhgpQhgbFLbTQFjwhN DPWWZzzztsDDtfzlscsPdcWZnVMNVqqGJnBrVqCrMrVvZnBJ ZgglFCrrrlrWCJswHmwRVmFSwSsP zhzqBLcjjnpzMzjhTtcqnVGbwssVRmqbHNPbwPsVNH ftBjzLtptRWdvZlQQZQf nGpsMncVRMGSnfsBllZdppwrTljZrQ gcgHmtbCthHWhwBFBWZBlWlWrd bCDDqHhcqbbtqcqtvJMzsGRsvVfPsfnzJV TclPvSGZsPZRjhjWDgjp JtnwHFtJqtwfQfgWgRWhdhjtgdRM JBwnHwgFFqVJrsGmPvNTPsVvSN ZJnfZNnDNZJLzNntDtDNNzNWTVBPrrvRRGdBcVRfPPcvfdMr CFgjFmggQSQQmSggVMMvRdTvBVRjrdrc mbsqQFqFgwwmgmSbwQWWLDWzpLcLnzZzLbLL PnwSFSLSTwbbHdtstW RrDZVVfJNZCmDCfVDVlblZHbddtHScbWbMjt NmzqhzCCqmzffhCCqrhhLLnPvpnTPPgpGTTBSL ShhfLSDDFMPQddpMrDgNbjzffqqqzgcjbqZR sCstmwJwVBtmTltVmTVbRbcbcRvqvrZvBRvZbR VwCnwnVrrrWShWPHHDdQFL pbpDpWjZMmFCmmmb jTjtJLJgJncCFmnJFC LvhvhTQhBSdRNtLNsSszlGrHSGjZDlGf JrhvTNJJhhCrtVtcrNLwDBSBwqzDwQVbBLQS RnCgHmHHGMdPsGMfDlDqlSQbQnQQDbzD RdPMPsmWHmjfMffPcCWrptcprpFTFrFp ================================================ FILE: exm/aoc/2022/aoc_2022_03_questions.txt ================================================ --- Day 3: Rucksack Reorganization --- One Elf has the important job of loading all of the rucksacks with supplies for the jungle journey. Unfortunately, that Elf didn't quite follow the packing instructions, and so a few items now need to be rearranged. Each rucksack has two large compartments. All items of a given type are meant to go into exactly one of the two compartments. The Elf that did the packing failed to follow this rule for exactly one item type per rucksack. The Elves have made a list of all of the items currently in each rucksack (your puzzle input), but they need your help finding the errors. Every item type is identified by a single lowercase or uppercase letter (that is, a and A refer to different types of items). The list of items for each rucksack is given as characters all on a single line. A given rucksack always has the same number of items in each of its two compartments, so the first half of the characters represent items in the first compartment, while the second half of the characters represent items in the second compartment. For example, suppose you have the following list of contents from six rucksacks: vJrwpWtwJgWrhcsFMMfFFhFp jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL PmmdzqPrVvPwwTWBwg wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn ttgJtRGJQctTZtZT CrZsJsPPZsGzwwsLwLmpwMDw The first rucksack contains the items vJrwpWtwJgWrhcsFMMfFFhFp, which means its first compartment contains the items vJrwpWtwJgWr, while the second compartment contains the items hcsFMMfFFhFp. The only item type that appears in both compartments is lowercase p. The second rucksack's compartments contain jqHRNqRjqzjGDLGL and rsFMfFZSrLrFZsSL. The only item type that appears in both compartments is uppercase L. The third rucksack's compartments contain PmmdzqPrV and vPwwTWBwg; the only common item type is uppercase P. The fourth rucksack's compartments only share item type v. The fifth rucksack's compartments only share item type t. The sixth rucksack's compartments only share item type s. To help prioritize item rearrangement, every item type can be converted to a priority: Lowercase item types a through z have priorities 1 through 26. Uppercase item types A through Z have priorities 27 through 52. In the above example, the priority of the item type that appears in both compartments of each rucksack is 16 (p), 38 (L), 42 (P), 22 (v), 20 (t), and 19 (s); the sum of these is 157. Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types? --- Part Two --- As you finish identifying the misplaced items, the Elves come to you with another issue. For safety, the Elves are divided into groups of three. Every Elf carries a badge that identifies their group. For efficiency, within each group of three Elves, the badge is the only item type carried by all three Elves. That is, if a group's badge is item type B, then all three Elves will have item type B somewhere in their rucksack, and at most two of the Elves will be carrying any other item type. The problem is that someone forgot to put this year's updated authenticity sticker on the badges. All of the badges need to be pulled out of the rucksacks so the new authenticity stickers can be attached. Additionally, nobody wrote down which item type corresponds to each group's badges. The only way to tell which item type is the right one is by finding the one item type that is common between all three Elves in each group. Every set of three lines in your list corresponds to a single group, but each group can have a different badge item type. So, in the above example, the first group's rucksacks are the first three lines: vJrwpWtwJgWrhcsFMMfFFhFp jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL PmmdzqPrVvPwwTWBwg And the second group's rucksacks are the next three lines: wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn ttgJtRGJQctTZtZT CrZsJsPPZsGzwwsLwLmpwMDw In the first group, the only item type that appears in all three rucksacks is lowercase r; this must be their badges. In the second group, their badge item type must be Z. Priorities for these items must still be found to organize the sticker attachment efforts: here, they are 18 (r) for the first group and 52 (Z) for the second group. The sum of these is 70. Find the item type that corresponds to the badges of each three-Elf group. What is the sum of the priorities of those item types? ================================================ FILE: exm/aoc/2022/aoc_2022_04.adb ================================================ -- Solution to Advent of Code 2022, Day 4 ------------------------------------------ -- Camp Cleanup -- -- https://adventofcode.com/2022/day/4 -- Copy of questions in: aoc_2022_04_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_04 is use HAT; T0 : constant Time := Clock; f : File_Type; sep1, sep2, sep3 : Character; l1, u1, l2, u2 : Natural; t1, t2 : Natural := 0; begin Open (f, "aoc_2022_04.txt"); Read_Data : while not End_Of_File (f) loop -- Read data in the form: "2-4,6-8": Get (f, l1); Get (f, sep1); Get (f, u1); Get (f, sep2); Get (f, l2); Get (f, sep3); Get (f, u2); if (l1 >= l2 and u1 <= u2) or (l2 >= l1 and u2 <= u1) then -- Count redundancies (one set contained in the other one): t1 := t1 + 1; end if; if u1 >= l2 and u2 >= l1 then -- Count overlaps: t2 := t2 + 1; -- The sets are separated when and only when u1 < l2 or u2 < l1. -- Thus the condition for an overlap is: -- not (u1 < l2 or u2 < l1) -- which is equivalent to: -- u1 >= l2 and u2 >= l1 end if; end loop Read_Data; Close (f); if Argument_Count >= 2 then -- Compiler test mode. if t1 /= Integer'Value (To_String (Argument (1))) or t2 /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: pairs with redundancies . . : " & t1); Put_Line (+"Part 2: pairs with overlaps . . . . : " & t2); -- Part 1: validated by AoC: 657 -- Part 2: validated by AoC: 938 end if; end AoC_2022_04; ================================================ FILE: exm/aoc/2022/aoc_2022_04.txt ================================================ 54-59,17-62 20-93,57-92 6-54,7-54 3-99,59-98 5-8,5-8 89-94,32-89 1-91,1-90 26-90,91-93 33-76,21-75 59-60,19-60 15-94,15-94 60-62,59-77 16-26,12-21 5-10,11-98 10-97,9-10 62-92,61-92 57-74,38-74 79-85,84-86 14-86,13-86 23-27,22-93 20-99,19-99 37-62,36-63 77-95,88-94 1-1,3-28 18-19,18-84 75-94,74-99 34-52,20-21 63-95,2-63 98-98,82-85 1-89,2-90 18-99,22-91 26-43,27-43 40-97,41-96 43-94,88-97 35-79,11-36 10-63,10-88 54-69,53-70 4-53,2-52 40-77,77-77 17-84,79-84 4-45,5-46 6-43,7-33 26-81,26-81 12-76,11-65 47-94,47-84 27-99,26-99 81-87,80-87 16-30,1-15 23-77,23-77 35-43,36-36 3-90,17-90 16-50,15-18 13-37,37-69 45-45,44-52 28-70,28-70 61-68,61-69 32-94,32-93 48-48,31-51 33-35,34-49 27-38,38-39 11-37,11-14 4-49,3-49 16-73,72-73 16-98,22-78 5-92,91-91 11-96,10-96 67-86,82-95 28-91,92-99 5-9,5-25 7-98,6-30 2-79,11-78 13-85,85-85 6-99,98-98 24-97,68-97 4-39,3-39 24-82,57-82 3-99,1-99 52-90,90-91 69-70,69-70 62-83,61-61 71-72,17-71 5-95,4-94 50-70,46-48 33-34,34-96 29-84,29-98 28-88,27-87 20-96,21-96 21-45,46-68 54-87,54-97 10-22,10-22 75-87,15-76 15-36,14-99 10-99,9-92 28-89,29-84 8-71,7-72 36-87,36-88 76-80,46-82 36-49,7-36 38-40,40-61 94-99,28-93 15-69,54-69 31-53,52-52 69-71,5-70 27-83,3-84 6-59,59-60 34-43,33-79 3-97,4-88 13-47,13-47 3-11,10-42 13-83,12-83 63-63,62-80 40-60,60-70 6-96,7-96 6-40,21-40 30-43,27-42 4-11,21-69 96-99,5-97 2-92,2-91 22-67,23-52 17-94,17-27 25-25,24-93 18-86,18-71 32-38,38-76 45-91,45-83 72-72,72-72 34-64,64-76 64-95,43-96 19-91,2-90 38-85,84-84 4-68,3-5 7-9,8-20 12-12,12-97 43-76,75-76 49-72,71-71 84-88,84-88 24-64,23-63 27-79,11-27 8-85,5-89 38-77,6-78 24-98,25-98 8-98,25-83 15-32,5-15 72-97,7-98 69-91,70-87 45-92,5-91 25-75,76-76 10-99,10-99 4-12,10-12 95-96,64-95 29-84,29-84 56-95,94-95 14-93,11-42 43-43,3-44 5-93,47-93 80-88,79-96 25-56,16-25 25-88,26-64 1-93,2-2 20-74,20-74 95-98,96-98 41-41,40-40 18-19,12-19 29-37,36-36 2-50,3-50 2-97,3-96 12-12,11-30 25-86,26-87 18-42,18-36 8-10,9-11 47-49,27-48 2-69,69-69 16-18,17-96 18-18,17-99 34-55,34-55 8-83,88-98 55-56,46-55 22-63,11-64 47-86,32-85 2-2,1-67 5-97,6-6 4-35,1-44 43-86,54-97 23-95,23-95 29-39,29-38 5-93,5-93 3-3,3-99 2-96,22-68 47-78,48-78 58-77,58-78 2-75,2-89 23-53,17-20 26-60,9-27 7-7,6-64 25-42,15-43 27-75,37-75 20-96,21-96 18-36,35-35 10-97,10-97 4-6,9-68 12-83,13-13 43-48,26-44 43-98,43-99 40-96,40-40 1-2,2-82 14-85,14-85 11-44,10-45 71-92,91-92 23-69,24-64 75-75,11-76 14-99,2-99 67-74,73-73 12-85,13-85 39-80,40-40 33-34,32-34 58-59,13-59 83-88,84-84 17-24,9-70 4-87,1-99 1-48,2-94 14-95,10-89 31-43,31-92 67-81,49-72 15-74,16-16 29-66,29-66 30-98,97-97 3-75,3-76 40-41,26-40 68-68,67-78 23-53,24-90 51-55,36-58 3-97,4-93 8-90,8-48 9-64,8-95 17-48,47-48 19-69,46-68 21-96,21-96 41-41,37-42 2-98,97-99 13-13,13-13 21-82,38-82 6-82,81-81 2-38,37-37 26-93,5-93 1-45,2-28 3-70,8-63 48-54,51-54 3-8,7-41 17-76,16-77 40-44,40-43 57-86,27-57 27-87,24-71 81-93,92-93 27-46,46-46 4-94,7-93 48-85,84-85 61-63,13-62 11-12,11-22 33-86,33-34 17-34,18-34 8-30,31-34 6-91,6-90 21-55,21-55 15-48,25-35 28-29,30-53 48-81,47-83 12-26,11-26 89-89,22-89 20-98,21-98 5-97,76-81 3-76,3-76 17-79,79-90 20-75,28-74 9-58,8-59 55-57,56-72 52-58,45-49 6-97,21-86 8-74,8-74 48-95,75-94 1-87,8-88 40-49,36-49 8-72,8-73 2-76,3-76 22-33,2-33 46-94,18-94 13-98,7-98 52-66,14-65 7-8,8-8 34-35,34-72 8-21,20-86 96-97,2-97 60-60,59-89 4-11,10-96 14-43,14-43 31-44,43-79 36-78,35-78 70-91,67-91 65-66,43-65 3-6,5-96 27-50,9-35 27-28,13-28 73-82,72-81 2-43,2-42 76-77,75-79 88-89,23-89 5-5,4-68 6-6,5-98 21-22,9-22 6-94,5-6 26-89,20-88 39-93,13-95 5-93,22-93 8-23,9-23 30-52,31-51 55-55,6-55 26-83,26-83 52-72,51-78 25-28,41-87 35-98,36-64 96-97,79-97 56-81,57-79 40-42,17-41 30-82,30-81 6-14,9-15 11-29,11-30 8-41,6-40 28-97,97-97 33-67,33-68 29-90,28-91 2-30,12-29 5-70,6-6 8-39,9-79 5-29,28-35 17-55,17-55 3-90,2-90 15-30,15-72 77-78,16-78 60-82,36-83 2-91,4-89 37-52,52-52 11-98,10-98 55-56,24-55 27-59,25-59 2-2,1-93 11-49,49-50 23-71,23-86 17-52,3-51 98-98,21-99 3-92,4-4 81-85,81-85 17-99,18-95 5-90,1-2 33-78,33-77 34-47,20-47 1-97,35-98 95-98,34-96 80-92,94-98 63-70,69-70 89-94,90-95 38-38,39-81 74-75,33-75 16-33,25-97 29-97,29-29 28-30,29-93 26-75,74-75 98-99,1-98 37-60,32-46 18-36,17-88 29-95,29-95 16-32,32-33 36-37,19-38 36-84,33-42 56-68,6-69 14-57,42-57 68-76,67-73 14-24,23-37 59-60,60-87 16-98,15-98 46-47,43-72 97-97,64-97 45-65,64-64 35-98,12-35 1-99,1-98 7-77,8-76 7-89,8-56 65-65,54-68 19-94,13-95 86-90,85-88 14-79,13-80 15-15,15-77 6-68,6-68 6-6,5-60 50-89,37-90 7-66,7-67 20-38,20-37 45-92,46-97 77-78,67-77 3-3,2-99 3-91,3-4 4-84,25-84 10-11,10-66 4-45,4-45 33-62,25-34 38-67,39-39 15-70,63-64 58-75,57-74 6-98,3-7 22-54,47-53 20-45,32-46 1-91,1-90 3-97,99-99 1-45,1-1 3-92,28-91 5-83,5-84 5-98,20-98 51-52,51-52 15-93,12-23 18-21,21-89 89-92,88-95 8-27,12-54 12-28,13-28 25-27,26-27 63-64,63-70 1-75,1-25 13-41,14-14 15-30,30-93 9-89,9-90 14-70,15-70 11-12,11-52 3-3,2-98 8-10,9-91 67-68,57-68 7-33,8-94 33-90,2-89 13-57,12-58 62-91,73-74 31-99,32-77 4-19,1-3 26-35,34-42 19-64,18-55 51-64,87-91 3-99,98-99 4-45,8-92 53-86,85-86 22-84,22-79 17-79,80-86 37-37,36-82 7-83,7-82 94-95,78-95 93-94,49-93 70-82,18-98 4-85,3-84 31-84,30-71 16-32,24-31 10-91,4-63 11-94,11-92 70-71,62-70 43-83,60-82 10-47,6-46 12-58,57-58 10-64,10-56 24-95,42-94 1-38,18-37 19-53,20-53 26-37,26-37 76-80,77-81 10-16,16-16 24-98,40-79 26-92,27-92 14-99,14-15 1-98,96-96 85-99,84-96 34-60,14-61 40-82,81-85 1-99,1-21 20-28,20-29 4-73,1-73 2-2,3-93 55-97,7-98 18-66,19-74 78-80,80-80 9-80,26-81 26-97,4-99 14-87,13-88 81-82,82-86 29-33,30-35 81-89,13-82 33-42,34-68 27-94,26-95 5-93,93-94 8-86,64-87 5-74,4-75 66-90,94-97 58-61,58-60 52-90,50-58 22-22,22-22 53-61,53-54 9-66,65-77 42-60,43-43 68-97,68-97 16-89,15-90 44-96,95-97 12-89,13-88 35-52,34-52 45-78,46-86 7-24,7-20 6-53,5-54 57-58,14-57 73-82,77-81 43-50,44-50 32-48,32-70 91-92,29-91 4-86,70-87 91-92,45-90 34-98,35-35 34-98,90-97 24-96,23-97 30-62,29-62 37-37,36-66 20-91,49-90 85-94,19-99 37-77,10-36 1-46,45-72 50-88,19-88 87-89,19-98 3-91,2-97 10-75,10-75 4-96,3-97 50-85,22-50 68-94,69-92 7-66,7-8 18-72,25-73 13-52,51-52 84-87,2-87 4-86,87-93 45-49,49-56 4-25,3-26 26-55,24-27 25-47,26-26 45-56,44-56 61-64,60-64 33-96,34-95 49-50,26-51 3-94,4-94 8-97,8-95 6-64,5-35 21-31,22-32 33-73,11-72 14-75,11-11 97-97,5-98 28-29,29-30 90-99,23-47 83-84,1-83 3-92,2-4 3-4,4-96 96-97,28-91 23-52,22-53 67-67,66-68 23-91,22-92 2-99,2-99 3-41,2-94 36-87,59-86 69-77,69-77 9-99,8-99 4-96,3-96 52-52,21-51 19-89,18-53 86-87,29-87 18-65,25-54 62-82,4-61 49-94,49-93 95-98,5-96 22-87,22-49 98-98,41-99 8-93,7-96 67-72,67-73 29-62,50-78 4-95,95-96 29-90,16-89 2-75,74-74 54-56,30-57 1-95,1-95 7-98,8-8 83-90,40-92 50-93,49-94 34-47,46-47 72-87,72-75 26-69,27-69 15-58,14-16 14-63,17-99 9-87,9-86 1-99,3-97 45-51,34-63 24-43,13-13 5-20,4-21 5-75,6-6 99-99,8-97 12-40,11-85 26-85,27-84 5-86,6-6 22-82,22-81 42-94,43-75 6-7,6-96 5-92,4-92 32-37,32-38 64-87,65-82 58-63,60-60 15-97,15-91 10-17,16-45 70-71,49-71 2-34,29-35 7-81,6-7 36-88,37-54 81-86,76-87 2-93,2-5 33-89,88-88 25-37,18-36 11-56,12-55 8-91,7-95 5-83,6-66 65-97,19-66 60-81,80-82 23-94,1-93 42-91,41-92 79-94,79-93 3-99,2-17 75-75,24-76 16-61,16-76 33-75,34-74 32-88,87-88 4-26,24-27 36-46,40-50 15-76,5-11 2-12,3-12 3-97,4-92 9-21,20-20 9-95,66-94 14-92,14-25 33-49,20-48 31-67,35-68 1-97,96-96 35-35,34-92 57-86,56-72 68-85,53-86 80-87,67-89 94-94,5-94 65-84,84-91 11-99,7-9 20-92,21-82 3-61,1-3 34-59,33-58 12-98,13-13 80-80,13-80 55-97,54-98 59-76,3-77 8-97,7-74 45-46,43-45 60-81,9-82 4-88,25-87 5-97,96-96 39-70,25-51 44-61,41-42 33-36,33-34 91-92,6-91 39-53,43-53 9-31,30-32 60-96,59-98 17-98,17-17 41-41,40-43 16-44,35-44 42-42,14-43 1-5,5-98 18-87,33-87 56-56,46-57 6-99,2-98 9-22,10-10 14-15,15-61 17-82,18-34 95-98,14-95 81-81,38-82 30-50,39-46 94-94,6-95 14-54,15-53 3-80,2-4 55-55,54-98 99-99,2-99 70-70,9-71 8-20,9-9 1-98,98-99 31-71,63-71 74-97,25-97 4-61,61-61 37-58,38-53 15-20,14-15 44-79,45-80 45-68,29-75 24-94,19-98 42-86,9-41 75-89,70-75 25-55,6-25 41-69,40-41 6-96,4-4 20-94,93-94 16-69,2-68 76-78,47-77 7-54,3-36 2-38,1-98 4-16,16-16 1-99,88-99 12-35,15-35 14-98,13-99 60-61,8-61 26-68,58-67 28-98,28-95 13-15,14-30 23-41,24-24 33-88,14-81 36-94,3-67 16-74,73-74 83-93,3-94 3-65,6-66 31-93,32-32 30-54,41-54 9-77,76-96 11-12,11-74 14-14,19-72 34-60,33-61 3-4,3-25 3-75,75-76 28-99,29-97 29-85,30-84 21-31,24-29 10-35,10-11 92-98,56-93 3-96,95-96 36-55,36-90 4-91,5-91 1-93,92-98 21-37,22-36 9-32,30-33 46-83,47-89 31-63,30-32 28-54,58-66 33-97,33-97 71-80,59-79 11-97,12-98 68-69,66-70 9-62,6-46 50-92,50-91 5-19,18-77 23-25,19-25 2-11,3-15 11-92,12-92 21-99,22-87 57-92,56-93 12-91,2-9 6-13,1-14 8-92,9-91 7-38,4-71 2-11,2-80 6-99,6-99 23-56,55-65 44-78,54-77 47-63,48-63 9-81,8-31 67-84,67-87 2-74,3-73 3-11,10-97 18-20,21-99 92-92,34-93 44-95,33-94 4-61,14-61 4-97,1-97 79-88,80-90 13-93,10-97 16-44,15-44 47-90,8-75 17-59,8-60 11-87,4-11 4-64,4-69 66-67,67-91 48-67,49-66 26-50,25-51 4-91,4-91 60-60,59-83 1-1,1-16 4-15,16-16 68-72,67-68 42-84,41-85 22-73,18-72 50-51,51-78 6-98,6-97 72-83,72-86 1-98,1-97 6-28,6-79 27-82,81-82 3-72,2-3 2-97,6-66 9-92,8-44 3-6,5-65 85-86,30-86 75-97,8-69 5-60,6-6 9-64,8-76 36-88,41-92 1-57,57-57 76-92,75-93 18-85,2-18 18-68,14-31 48-49,11-48 86-86,15-87 41-93,42-92 9-40,10-39 5-6,6-86 2-38,24-84 16-90,7-17 19-63,18-64 6-97,78-99 19-48,20-93 6-8,7-55 3-74,2-73 5-22,6-6 6-84,6-92 30-30,30-82 17-37,16-37 82-89,5-98 49-98,97-98 6-19,18-20 6-95,5-95 10-46,29-45 5-84,6-83 97-97,21-98 57-83,58-82 21-59,45-60 2-98,1-99 52-56,9-51 71-86,44-87 3-81,2-82 53-94,80-93 1-83,2-84 31-32,31-84 79-87,80-87 77-79,6-78 27-88,18-73 77-93,6-94 76-76,8-76 36-38,34-39 20-37,9-20 33-34,34-99 22-98,98-99 97-98,5-98 1-40,2-40 62-93,62-93 47-94,48-94 5-89,1-5 5-62,23-61 7-60,8-59 88-89,43-88 3-95,94-95 18-31,6-31 60-73,48-74 5-56,5-56 33-78,34-55 33-37,34-36 2-68,2-68 80-82,13-84 73-73,63-73 54-70,53-96 7-16,8-48 39-79,39-80 12-37,13-67 4-72,5-71 77-88,34-78 40-74,40-74 97-98,97-97 31-92,32-32 37-61,28-61 1-91,2-91 31-58,4-13 27-80,60-80 33-94,33-94 67-72,13-90 31-51,30-52 18-90,18-90 33-43,33-44 23-98,33-97 13-45,12-49 89-90,54-90 4-60,4-59 5-92,6-85 19-23,9-22 8-96,1-8 37-87,23-37 30-62,31-61 29-79,29-79 27-96,23-95 5-99,6-97 92-93,4-93 13-36,35-78 32-48,32-47 17-96,99-99 4-98,98-98 17-17,17-92 79-84,11-85 34-95,33-95 10-79,8-80 7-32,27-27 3-98,2-99 3-63,2-64 22-98,13-21 9-20,19-96 62-97,60-74 14-86,13-14 15-90,15-91 11-92,10-89 93-98,7-94 1-75,8-63 3-92,4-59 54-72,72-72 52-84,84-89 55-55,55-72 5-5,4-52 21-84,66-75 13-18,7-87 82-83,6-82 19-66,11-12 69-96,69-95 3-98,36-97 12-31,6-12 21-49,14-18 35-97,8-97 16-82,81-82 4-92,4-99 68-79,19-67 36-56,77-83 46-47,29-46 91-92,21-91 2-2,1-90 61-93,39-74 6-33,33-33 7-95,2-7 59-60,53-60 7-90,4-8 94-94,84-95 69-85,68-94 9-73,9-73 47-99,48-99 7-37,7-7 3-3,2-74 18-18,17-28 25-51,46-50 1-98,1-99 48-80,49-56 16-94,93-95 59-83,60-82 16-79,78-78 24-26,29-85 10-77,10-11 4-96,4-48 44-97,43-87 33-71,70-71 27-57,26-57 30-53,16-31 15-68,14-69 14-95,7-94 82-82,15-81 22-40,22-23 6-94,53-65 76-95,77-83 12-83,13-82 41-94,40-98 37-58,38-58 7-91,1-6 23-68,34-67 27-97,96-96 56-57,56-57 1-61,3-7 28-55,27-55 32-32,31-56 13-76,13-76 10-18,11-56 5-99,2-5 7-80,14-39 16-82,81-82 4-24,2-4 2-97,97-98 24-88,87-88 28-95,29-96 56-72,57-71 71-73,1-72 52-98,51-98 4-57,57-58 82-83,40-82 54-78,29-77 10-25,25-26 46-89,87-88 59-89,68-89 84-86,57-84 24-94,54-93 41-63,40-63 87-90,89-90 ================================================ FILE: exm/aoc/2022/aoc_2022_04_questions.txt ================================================ --- Day 4: Camp Cleanup --- Space needs to be cleared before the last supplies can be unloaded from the ships, and so several Elves have been assigned the job of cleaning up sections of the camp. Every section has a unique ID number, and each Elf is assigned a range of section IDs. However, as some of the Elves compare their section assignments with each other, they've noticed that many of the assignments overlap. To try to quickly find overlaps and reduce duplicated effort, the Elves pair up and make a big list of the section assignments for each pair (your puzzle input). For example, consider the following list of section assignment pairs: 2-4,6-8 2-3,4-5 5-7,7-9 2-8,3-7 6-6,4-6 2-6,4-8 For the first few pairs, this list means: Within the first pair of Elves, the first Elf was assigned sections 2-4 (sections 2, 3, and 4), while the second Elf was assigned sections 6-8 (sections 6, 7, 8). The Elves in the second pair were each assigned two sections. The Elves in the third pair were each assigned three sections: one got sections 5, 6, and 7, while the other also got 7, plus 8 and 9. This example list uses single-digit section IDs to make it easier to draw; your actual list might contain larger numbers. Visually, these pairs of section assignments look like this: .234..... 2-4 .....678. 6-8 .23...... 2-3 ...45.... 4-5 ....567.. 5-7 ......789 7-9 .2345678. 2-8 ..34567.. 3-7 .....6... 6-6 ...456... 4-6 .23456... 2-6 ...45678. 4-8 Some of the pairs have noticed that one of their assignments fully contains the other. For example, 2-8 fully contains 3-7, and 6-6 is fully contained by 4-6. In pairs where one assignment fully contains the other, one Elf in the pair would be exclusively cleaning sections their partner will already be cleaning, so these seem like the most in need of reconsideration. In this example, there are 2 such pairs. In how many assignment pairs does one range fully contain the other? --- Part Two --- It seems like there is still quite a bit of duplicate work planned. Instead, the Elves would like to know the number of pairs that overlap at all. In the above example, the first two pairs (2-4,6-8 and 2-3,4-5) don't overlap, while the remaining four pairs (5-7,7-9, 2-8,3-7, 6-6,4-6, and 2-6,4-8) do overlap: 5-7,7-9 overlaps in a single section, 7. 2-8,3-7 overlaps all of the sections 3 through 7. 6-6,4-6 overlaps in a single section, 6. 2-6,4-8 overlaps in sections 4, 5, and 6. So, in this example, the number of overlapping assignment pairs is 4. In how many assignment pairs do the ranges overlap? ================================================ FILE: exm/aoc/2022/aoc_2022_05.adb ================================================ -- Solution to Advent of Code 2022, Day 5 ------------------------------------------ -- Supply Stacks -- -- https://adventofcode.com/2022/day/5 -- Copy of questions in: aoc_2022_05_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_05 is use HAT; type Storage is array (1 .. 100) of Character; type Stack is record top : Natural; s : Storage; end record; subtype Crane_Range is Integer range 1 .. 9; s : array (Crane_Range) of Stack; procedure Show (title : VString) is empty : Boolean; begin Put_Line (title); New_Line; for y in reverse 1 .. Storage'Last loop empty := True; for x in s'Range loop empty := empty and y > s (x).top; end loop; if not empty then for x in s'Range loop if y > s (x).top then Put (" "); else Put (+'[' & s (x).s (y) & "] "); end if; end loop; New_Line; end if; end loop; Put_Line ((4 * s'Length - 1) * '-'); New_Line; end Show; T0 : constant Time := Clock; r : array (1 .. 2) of String (Crane_Range); c, sep, bra, ket : Character; move : String (1 .. 4); from : String (1 .. 5); to : String (1 .. 4); a, b, n : Integer; max_y : Natural := 0; name : constant VString := +"aoc_2022_05.txt"; f : File_Type; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := not compiler_test_mode; begin -- Get the maximum height of the crates stacks: Open (f, name); while not End_Of_File (f) loop Get (f, sep); Get (f, c); exit when c in '1' .. '9'; max_y := max_y + 1; Skip_Line (f); end loop; Close (f); -- Parts : for part in 1 .. 2 loop for x in s'Range loop s (x).top := 0; end loop; -- Get the initial setup of the crates: Open (f, name); for y in reverse 1 .. max_y loop for x in s'Range loop Get (f, bra); Get (f, c); if c in 'A' .. 'Z' then s (x).s (y) := c; s (x).top := Max (s (x).top, y); end if; Get (f, ket); if x < s'Last then Get (f, sep); end if; end loop; end loop; if verbose and part = 1 then Show (+"Data:"); end if; -- Skip the "1 2 3 ..." line and the next empty one: Skip_Line (f, 2); -- Read and execute the instructions for moving crates: while not End_Of_File (f) loop -- Read line "move n from a to b": Get (f, move); Get (f, n); Get (f, from); Get (f, a); Get (f, to); Get (f, b); for count in 1 .. n loop case part is when 1 => -- CrateMover 9000 -- Move one by one, taking each crate `c` from the top, downwards: c := s (a).s (s (a).top - count + 1); when 2 => -- CrateMover 9001 -- Move the crates "stack-wise": c := s (a).s (s (a).top - n + count); end case; s (b).s (s (b).top + count) := c; end loop; s (a).top := s (a).top - n; s (b).top := s (b).top + n; end loop; Close (f); if verbose then Show (+"Result, part " & part & ':'); end if; for x in s'Range loop r (part)(x) := s (x).s (s (x).top); end loop; end loop Parts; -- if compiler_test_mode then if +r (1) /= Argument (1) or +r (2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Top crates after..."); Put_Line (+" (part 1) one-by-one moves: " & r (1)); Put_Line (+" (part 2) stack-wise moves: " & r (2)); -- Part 1: validated by AoC: VQZNJMWTR -- Part 2: validated by AoC: NLCDCLVMQ end if; end AoC_2022_05; ================================================ FILE: exm/aoc/2022/aoc_2022_05.txt ================================================ [L] [M] [M] [D] [R] [Z] [C] [L] [C] [S] [T] [G] [V] [M] [R] [L] [Q] [B] [B] [D] [F] [H] [B] [G] [D] [Q] [Z] [T] [J] [M] [J] [H] [M] [P] [S] [V] [L] [N] [P] [C] [N] [T] [S] [F] [R] [G] [Q] [Z] [P] [S] [F] [F] [T] [N] [P] [W] 1 2 3 4 5 6 7 8 9 move 7 from 3 to 9 move 5 from 8 to 9 move 3 from 9 to 5 move 6 from 9 to 2 move 9 from 9 to 3 move 3 from 7 to 3 move 8 from 2 to 3 move 9 from 3 to 1 move 11 from 3 to 8 move 5 from 6 to 9 move 1 from 6 to 3 move 1 from 2 to 7 move 1 from 4 to 8 move 1 from 3 to 9 move 4 from 4 to 3 move 6 from 8 to 3 move 2 from 8 to 2 move 4 from 9 to 3 move 3 from 2 to 5 move 2 from 5 to 4 move 5 from 3 to 4 move 11 from 1 to 4 move 1 from 7 to 6 move 1 from 3 to 5 move 2 from 1 to 9 move 1 from 1 to 4 move 7 from 5 to 8 move 21 from 4 to 6 move 6 from 6 to 2 move 6 from 8 to 9 move 5 from 8 to 5 move 2 from 2 to 7 move 4 from 3 to 7 move 1 from 2 to 6 move 1 from 2 to 5 move 2 from 2 to 7 move 4 from 3 to 7 move 1 from 4 to 6 move 9 from 5 to 3 move 7 from 3 to 4 move 7 from 7 to 3 move 7 from 4 to 1 move 8 from 3 to 5 move 1 from 3 to 5 move 3 from 8 to 2 move 2 from 2 to 9 move 13 from 9 to 4 move 5 from 5 to 3 move 4 from 7 to 6 move 1 from 7 to 4 move 2 from 4 to 2 move 3 from 3 to 4 move 2 from 5 to 2 move 6 from 1 to 7 move 1 from 2 to 8 move 1 from 3 to 8 move 1 from 1 to 6 move 1 from 3 to 4 move 1 from 2 to 6 move 24 from 6 to 1 move 3 from 2 to 3 move 3 from 3 to 5 move 2 from 8 to 6 move 2 from 5 to 4 move 3 from 5 to 1 move 7 from 4 to 8 move 3 from 8 to 9 move 2 from 9 to 5 move 2 from 6 to 3 move 1 from 9 to 8 move 5 from 7 to 5 move 2 from 3 to 1 move 1 from 7 to 1 move 7 from 4 to 7 move 2 from 4 to 8 move 6 from 8 to 6 move 3 from 6 to 9 move 10 from 5 to 1 move 7 from 7 to 1 move 1 from 4 to 9 move 1 from 6 to 3 move 2 from 9 to 7 move 1 from 4 to 2 move 1 from 9 to 5 move 1 from 8 to 5 move 39 from 1 to 8 move 1 from 2 to 5 move 2 from 6 to 9 move 3 from 9 to 5 move 3 from 1 to 6 move 1 from 7 to 2 move 1 from 3 to 2 move 2 from 6 to 2 move 3 from 2 to 3 move 1 from 6 to 2 move 1 from 1 to 8 move 3 from 1 to 2 move 3 from 2 to 4 move 2 from 4 to 5 move 2 from 3 to 8 move 8 from 5 to 2 move 8 from 8 to 2 move 15 from 2 to 7 move 1 from 1 to 5 move 25 from 8 to 7 move 2 from 2 to 4 move 2 from 4 to 3 move 1 from 8 to 4 move 2 from 4 to 6 move 1 from 2 to 1 move 26 from 7 to 2 move 15 from 2 to 1 move 7 from 8 to 9 move 10 from 1 to 6 move 10 from 7 to 2 move 1 from 8 to 1 move 5 from 9 to 8 move 1 from 8 to 9 move 2 from 6 to 9 move 3 from 7 to 1 move 1 from 7 to 1 move 5 from 9 to 2 move 1 from 3 to 1 move 9 from 6 to 3 move 1 from 6 to 1 move 4 from 2 to 4 move 3 from 4 to 8 move 1 from 4 to 1 move 9 from 3 to 1 move 1 from 7 to 6 move 9 from 2 to 5 move 14 from 1 to 6 move 1 from 3 to 8 move 5 from 2 to 6 move 8 from 1 to 8 move 6 from 6 to 8 move 14 from 6 to 7 move 1 from 1 to 7 move 10 from 5 to 4 move 11 from 8 to 5 move 15 from 7 to 1 move 4 from 5 to 6 move 4 from 8 to 9 move 6 from 5 to 3 move 1 from 6 to 9 move 1 from 1 to 6 move 1 from 5 to 8 move 2 from 6 to 2 move 6 from 1 to 5 move 1 from 5 to 8 move 2 from 5 to 4 move 9 from 2 to 9 move 13 from 9 to 8 move 1 from 2 to 1 move 1 from 4 to 8 move 3 from 3 to 1 move 2 from 4 to 5 move 2 from 1 to 5 move 1 from 9 to 3 move 17 from 8 to 1 move 3 from 3 to 2 move 4 from 5 to 1 move 2 from 2 to 4 move 1 from 6 to 1 move 1 from 2 to 8 move 4 from 4 to 6 move 1 from 5 to 9 move 5 from 6 to 8 move 1 from 5 to 4 move 1 from 5 to 6 move 3 from 8 to 6 move 8 from 4 to 5 move 32 from 1 to 7 move 11 from 7 to 6 move 8 from 5 to 3 move 3 from 8 to 7 move 6 from 3 to 9 move 4 from 3 to 8 move 5 from 8 to 2 move 1 from 8 to 5 move 11 from 6 to 3 move 1 from 5 to 2 move 2 from 8 to 6 move 12 from 7 to 8 move 2 from 6 to 2 move 2 from 6 to 4 move 5 from 2 to 5 move 8 from 7 to 2 move 2 from 7 to 1 move 2 from 7 to 6 move 5 from 5 to 4 move 5 from 4 to 7 move 5 from 8 to 2 move 2 from 9 to 7 move 5 from 8 to 4 move 2 from 7 to 3 move 2 from 9 to 3 move 3 from 7 to 9 move 1 from 1 to 8 move 2 from 6 to 1 move 2 from 9 to 8 move 1 from 7 to 8 move 1 from 2 to 5 move 1 from 7 to 9 move 7 from 4 to 3 move 3 from 3 to 6 move 5 from 8 to 6 move 3 from 9 to 5 move 16 from 3 to 1 move 2 from 9 to 1 move 7 from 1 to 8 move 1 from 1 to 2 move 5 from 8 to 2 move 12 from 1 to 4 move 1 from 3 to 5 move 1 from 2 to 9 move 1 from 9 to 4 move 4 from 6 to 5 move 5 from 6 to 1 move 1 from 6 to 5 move 1 from 1 to 4 move 1 from 4 to 7 move 1 from 3 to 7 move 9 from 4 to 6 move 2 from 7 to 8 move 1 from 3 to 4 move 2 from 8 to 9 move 4 from 8 to 4 move 4 from 2 to 8 move 2 from 9 to 7 move 2 from 7 to 8 move 10 from 2 to 4 move 1 from 2 to 1 move 5 from 4 to 7 move 1 from 1 to 3 move 3 from 8 to 7 move 6 from 7 to 2 move 3 from 2 to 7 move 1 from 6 to 7 move 5 from 5 to 8 move 4 from 1 to 3 move 4 from 3 to 1 move 8 from 4 to 2 move 1 from 3 to 2 move 2 from 7 to 2 move 2 from 6 to 3 move 4 from 7 to 2 move 4 from 5 to 7 move 14 from 2 to 7 move 3 from 2 to 1 move 3 from 8 to 2 move 1 from 5 to 7 move 6 from 2 to 4 move 2 from 2 to 7 move 2 from 3 to 6 move 6 from 8 to 2 move 4 from 6 to 4 move 2 from 6 to 9 move 4 from 4 to 2 move 2 from 4 to 8 move 10 from 7 to 2 move 18 from 2 to 6 move 2 from 2 to 6 move 2 from 9 to 2 move 2 from 8 to 5 move 1 from 2 to 9 move 1 from 2 to 9 move 1 from 5 to 7 move 1 from 2 to 6 move 2 from 9 to 2 move 6 from 7 to 3 move 7 from 6 to 8 move 5 from 7 to 2 move 1 from 7 to 4 move 1 from 5 to 7 move 4 from 8 to 7 move 5 from 2 to 3 move 1 from 7 to 5 move 2 from 2 to 8 move 9 from 4 to 3 move 13 from 6 to 8 move 10 from 3 to 1 move 1 from 5 to 2 move 3 from 6 to 8 move 5 from 1 to 2 move 1 from 1 to 8 move 2 from 4 to 3 move 17 from 8 to 6 move 5 from 6 to 3 move 3 from 1 to 2 move 9 from 6 to 5 move 2 from 6 to 8 move 5 from 5 to 9 move 3 from 9 to 8 move 3 from 1 to 3 move 3 from 7 to 5 move 6 from 5 to 8 move 7 from 2 to 4 move 1 from 6 to 3 move 1 from 1 to 5 move 4 from 4 to 5 move 2 from 2 to 9 move 3 from 1 to 3 move 4 from 5 to 8 move 1 from 4 to 5 move 6 from 8 to 7 move 1 from 5 to 2 move 4 from 9 to 2 move 2 from 5 to 9 move 2 from 1 to 8 move 2 from 4 to 9 move 6 from 7 to 5 move 3 from 5 to 2 move 3 from 2 to 5 move 10 from 8 to 3 move 2 from 8 to 5 move 3 from 2 to 5 move 6 from 5 to 1 move 4 from 5 to 6 move 1 from 7 to 5 move 23 from 3 to 7 move 2 from 5 to 9 move 2 from 1 to 5 move 2 from 6 to 3 move 6 from 3 to 1 move 1 from 1 to 7 move 4 from 3 to 1 move 1 from 8 to 5 move 2 from 9 to 2 move 3 from 3 to 8 move 2 from 6 to 8 move 12 from 1 to 3 move 1 from 9 to 7 move 3 from 5 to 9 move 9 from 3 to 8 move 1 from 1 to 7 move 1 from 9 to 4 move 3 from 3 to 6 move 3 from 2 to 1 move 3 from 8 to 6 move 1 from 4 to 2 move 1 from 2 to 9 move 1 from 2 to 7 move 20 from 7 to 5 move 3 from 7 to 3 move 3 from 1 to 3 move 5 from 8 to 1 move 5 from 1 to 5 move 4 from 5 to 2 move 3 from 2 to 6 move 3 from 8 to 7 move 1 from 2 to 6 move 2 from 8 to 6 move 2 from 7 to 5 move 2 from 3 to 6 move 12 from 5 to 1 move 6 from 5 to 7 move 12 from 6 to 8 move 4 from 9 to 3 move 4 from 5 to 8 move 3 from 1 to 5 move 4 from 7 to 4 move 3 from 5 to 9 move 7 from 1 to 6 move 1 from 1 to 3 move 6 from 7 to 6 move 1 from 1 to 3 move 10 from 3 to 6 move 10 from 6 to 2 move 2 from 9 to 5 move 4 from 6 to 5 move 9 from 6 to 1 move 16 from 8 to 7 move 3 from 8 to 7 move 1 from 8 to 1 move 7 from 2 to 1 move 1 from 5 to 9 move 1 from 6 to 1 move 2 from 2 to 1 move 3 from 1 to 4 move 1 from 6 to 8 move 7 from 4 to 1 move 1 from 8 to 2 move 22 from 1 to 8 move 18 from 7 to 9 move 6 from 5 to 2 move 2 from 2 to 7 move 2 from 1 to 5 move 4 from 7 to 6 move 1 from 5 to 6 move 2 from 8 to 2 move 3 from 2 to 6 move 1 from 5 to 6 move 15 from 9 to 6 move 6 from 9 to 5 move 1 from 9 to 8 move 1 from 2 to 9 move 5 from 5 to 9 move 9 from 8 to 6 move 3 from 2 to 7 move 12 from 8 to 9 move 1 from 7 to 5 move 1 from 5 to 7 move 3 from 7 to 1 move 17 from 6 to 3 move 1 from 2 to 6 move 2 from 1 to 4 move 16 from 6 to 4 move 7 from 4 to 6 move 1 from 5 to 7 move 8 from 4 to 5 move 9 from 9 to 8 move 16 from 3 to 7 move 1 from 1 to 5 move 3 from 5 to 1 move 5 from 6 to 2 move 3 from 1 to 7 move 3 from 6 to 7 move 3 from 9 to 3 move 5 from 8 to 5 move 11 from 5 to 7 move 2 from 3 to 7 move 1 from 2 to 1 move 1 from 3 to 6 move 17 from 7 to 9 move 1 from 3 to 2 move 3 from 4 to 6 move 1 from 1 to 2 move 1 from 6 to 4 move 14 from 7 to 6 move 15 from 9 to 6 move 4 from 8 to 7 move 1 from 4 to 7 move 7 from 9 to 5 move 5 from 2 to 9 move 7 from 5 to 1 move 3 from 1 to 7 move 29 from 6 to 4 move 1 from 2 to 4 move 18 from 4 to 2 move 3 from 1 to 4 move 1 from 1 to 7 move 18 from 2 to 4 move 3 from 6 to 5 move 15 from 4 to 1 move 1 from 5 to 1 move 1 from 5 to 4 move 9 from 4 to 1 move 5 from 1 to 3 move 9 from 1 to 5 move 2 from 4 to 3 move 5 from 5 to 6 move 3 from 7 to 9 move 7 from 7 to 5 move 6 from 4 to 6 move 2 from 3 to 7 move 6 from 5 to 8 move 2 from 8 to 4 move 1 from 8 to 9 move 9 from 6 to 2 move 3 from 9 to 3 move 1 from 2 to 1 move 6 from 7 to 4 move 2 from 2 to 8 move 3 from 9 to 5 move 5 from 4 to 8 move 1 from 6 to 9 move 1 from 3 to 1 move 1 from 3 to 4 move 1 from 6 to 5 move 1 from 9 to 3 move 10 from 8 to 7 move 3 from 9 to 2 move 7 from 2 to 4 move 6 from 5 to 7 move 4 from 5 to 8 move 7 from 3 to 2 move 3 from 7 to 1 move 9 from 1 to 5 move 5 from 7 to 9 move 7 from 1 to 4 move 11 from 4 to 2 move 4 from 8 to 3 move 5 from 4 to 7 move 4 from 4 to 1 move 1 from 3 to 6 move 12 from 7 to 4 move 2 from 1 to 8 move 5 from 9 to 7 move 7 from 5 to 6 move 1 from 1 to 4 move 1 from 9 to 8 move 1 from 4 to 7 move 1 from 8 to 9 move 5 from 7 to 9 move 2 from 7 to 5 move 2 from 6 to 3 move 5 from 2 to 7 move 1 from 7 to 8 move 1 from 1 to 6 move 3 from 5 to 1 ================================================ FILE: exm/aoc/2022/aoc_2022_05_questions.txt ================================================ --- Day 5: Supply Stacks --- The expedition can depart as soon as the final supplies have been unloaded from the ships. Supplies are stored in stacks of marked crates, but because the needed supplies are buried under many other crates, the crates need to be rearranged. The ship has a giant cargo crane capable of moving crates between stacks. To ensure none of the crates get crushed or fall over, the crane operator will rearrange them in a series of carefully-planned steps. After the crates are rearranged, the desired crates will be at the top of each stack. The Elves don't want to interrupt the crane operator during this delicate procedure, but they forgot to ask her which crate will end up where, and they want to be ready to unload them as soon as possible so they can embark. They do, however, have a drawing of the starting stacks of crates and the rearrangement procedure (your puzzle input). For example: [D] [N] [C] [Z] [M] [P] 1 2 3 move 1 from 2 to 1 move 3 from 1 to 3 move 2 from 2 to 1 move 1 from 1 to 2 In this example, there are three stacks of crates. Stack 1 contains two crates: crate Z is on the bottom, and crate N is on top. Stack 2 contains three crates; from bottom to top, they are crates M, C, and D. Finally, stack 3 contains a single crate, P. Then, the rearrangement procedure is given. In each step of the procedure, a quantity of crates is moved from one stack to a different stack. In the first step of the above rearrangement procedure, one crate is moved from stack 2 to stack 1, resulting in this configuration: [D] [N] [C] [Z] [M] [P] 1 2 3 In the second step, three crates are moved from stack 1 to stack 3. Crates are moved one at a time, so the first crate to be moved (D) ends up below the second and third crates: [Z] [N] [C] [D] [M] [P] 1 2 3 Then, both crates are moved from stack 2 to stack 1. Again, because crates are moved one at a time, crate C ends up below crate M: [Z] [N] [M] [D] [C] [P] 1 2 3 Finally, one crate is moved from stack 1 to stack 2: [Z] [N] [D] [C] [M] [P] 1 2 3 The Elves just need to know which crate will end up on top of each stack; in this example, the top crates are C in stack 1, M in stack 2, and Z in stack 3, so you should combine these together and give the Elves the message CMZ. After the rearrangement procedure completes, what crate ends up on top of each stack? --- Part Two --- As you watch the crane operator expertly rearrange the crates, you notice the process isn't following your prediction. Some mud was covering the writing on the side of the crane, and you quickly wipe it away. The crane isn't a CrateMover 9000 - it's a CrateMover 9001. The CrateMover 9001 is notable for many new and exciting features: air conditioning, leather seats, an extra cup holder, and the ability to pick up and move multiple crates at once. Again considering the example above, the crates begin in the same configuration: [D] [N] [C] [Z] [M] [P] 1 2 3 Moving a single crate from stack 2 to stack 1 behaves the same as before: [D] [N] [C] [Z] [M] [P] 1 2 3 However, the action of moving three crates from stack 1 to stack 3 means that those three moved crates stay in the same order, resulting in this new configuration: [D] [N] [C] [Z] [M] [P] 1 2 3 Next, as both crates are moved from stack 2 to stack 1, they retain their order as well: [D] [N] [C] [Z] [M] [P] 1 2 3 Finally, a single crate is still moved from stack 1 to stack 2, but now it's crate C that gets moved: [D] [N] [Z] [M] [C] [P] 1 2 3 In this example, the CrateMover 9001 has put the crates in a totally different order: MCD. Before the rearrangement process finishes, update your simulation so that the Elves know where they should stand to be ready to unload the final supplies. After the rearrangement procedure completes, what crate ends up on top of each stack? ================================================ FILE: exm/aoc/2022/aoc_2022_06.adb ================================================ -- Solution to Advent of Code 2022, Day 6 ------------------------------------------ -- Tuning Trouble -- -- https://adventofcode.com/2022/day/6 -- Copy of questions in: aoc_2022_06_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_06 is use HAT; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; f : File_Type; s : VString; s_i : Character; count : array (Character) of Natural; marker_length : Positive; duplicates : Natural; begin Open (f, "aoc_2022_06.txt"); Get_Line (f, s); Close (f); Parts : for part in 1 .. 2 loop for c in Character loop count (c) := 0; end loop; duplicates := 0; -- for i in 1 .. Length (s) loop s_i := Element (s, i); -- Count occurrences of the character at position i. count (s_i) := count (s_i) + 1; if count (s_i) = 2 then duplicates := duplicates + 1; end if; case part is when 1 => marker_length := 4; when 2 => marker_length := 14; end case; if i >= marker_length then if i > marker_length then -- Forget occurrence of the character that has -- just disappeared from the marker candidate. s_i := Element (s, i - marker_length); count (s_i) := count (s_i) - 1; if count (s_i) = 1 then duplicates := duplicates - 1; end if; end if; if duplicates = 0 then r (part) := i; exit; -- Leave after first match. end if; end if; end loop; end loop Parts; -- if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Number of characters that need to be " & " processed before the first..."); Put_Line (+" (part 1) start-of-packet marker . . . : " & r (1)); Put_Line (+" (part 2) start-of-message marker . . : " & r (2)); -- Part 1: validated by AoC: 1802 -- Part 2: validated by AoC: 3551 end if; end AoC_2022_06; ================================================ FILE: exm/aoc/2022/aoc_2022_06.txt ================================================ qhbhzbzzfrzrbzzcjzjrrvcvrvqvvnggnngcgssswbblplrlflfnnnmmjppgddqndnrnlnccpfcfjcjvjdjqqqmhhmwhwmmsnsvsjvjnvjnvjvsjsmjsjccwcqwcqwqjqwjwmwbmmbzbsbvsslbsbbbntnvvphpqqvrrtbrtrfftppbggpzzfhfcfsfmssffmbmzzmqzzblzzzmwwnggjwgjwgjgpgmmjvvmcvmmcfchfhllwmlljqqldqdqttsgsvscsmsnsmstmtssvgsgddwdffbppwfpplhlchhhdvvdrrmttmptmmmjsmshmmmgqmgggzjgzzmwzwcwhchqqfpfvvbqvbqbrblrrmtmstmmjvmmdnmmzczdzpztppjhjjwzjjjtdjjpljpjcppjllsffhbffbhhgttqjqzzfzbzcbzcbcrrjjrwrgwwbcbpcccctrtqtfqqfjjpgpdgdfgfrggpjjljglgclcqcqmcqmmgjjllpmphpjjgfjjqrrbppwmpmccftctjtjgjtgggzffcggwzzzdjdzzlgzgjzzvqvppczzjnjvvfhhtwtttdwtdtvddpzpnpcnppmvmcmcsmstthctchcggtssdttvztvvldlfftqqbzzjttvzztppscctzccgmcmvmhhchcscbbshbssgwwthwhmwwcgwcwrrvrzvrzzzvhvdvmmprrdmrmfmrmbmjbbmqbmbqqhbbszsjjlqjljtjstshhgphpffdhhtggtgbbqcqgqccfffcpcbpbfppwqpqcclbbwdwsscpchhfpfmpfmflfnnmggwrrznnghgvhhghrrhwrrcschcscqcmcfcvvgzztjtqjjshspsqsmmjnnmttsshvhmmqfqzztbzttvhttmwttnqnfncfcpfflmllmtlmmphmhlmmltmtztcczhzbbfmmlglnnfpppqplljwjfwfdwdzwddszddqzqnzzzwwlzzqvvjlllrwlrrmpmrmbmpplpspqsqmqcmcjjshsvstvvwtvthvvrfvvqmmjpmjmrjmmlvvnnrjjrcrwrhwwqzzvgvngncgcqqcffmfzfssbnbfblbggwhggmtgtvvqhhpttbcbczcjjbqbhqbhqbbccbhbqhbbmppdlpdllbvvdpvdvwvsvppllgblbttmcmtccbsswmswwwzfwfhhtfhthctchcfhhhfjjvhjhgjjjcwjwggrtgrttcqcwcswccfdffvpvtptprrvjjqvjjghggshhwmmcscmsmhmvmppprfrwwrhhvghhtnhncctbbbwzzbgzgdzgdzdpdvpvbbwgbwwrqwrqwqbqvvclccfcfzfdfrrthrrqcqddplpqlppbbfrfmmrmnnwhhgddmwwrzrsswpwhwdwhhsmhshqsqllbvlbllwbwbpwwfwmwsmspsvsdsbscctpctppvvpggtjjdmdqqgqbgglccvzcvcnczcgzgmzznpzzpcpnpvpcvvffrttqrqttflfbfjfnnwnlwlhwwqzqnqfftstdsttglldwwgqwwvqqzczfzdffbfsfssfwswdwnwdnnbcncwctttvsvjsvsrvvbtvvzhhvjvtvtjtsjjvhjjwpjjnzzpczzppgcpgcpgcgsgvsgvsscrcpcpspllzvzddpssssdpsddhffllzmzhzfhhdvhhvbvwwpwqpwqpwwmvwmvwvgvmvpvmpmrmzrrblltjtggvnggvppthhzjhzhffrvrhvrhrlrslsflfhhtvhvmmhppjgpjpcccmqcqvqhvvfssrtmnwjjslwhjgpvrwspjlwdwrmvfgwmplrmjrllndrjzvjfbwvzpjpfqrnjspwcpsgcvdlmfdfrvwdcvmbrnzncgnqlcvgqtpsbbpvprncdsgvpqbpcnffwqmmfsvnzspchhrlnzbhcdfdgtsllmqfbrcqwbmmzrfvsghjpmrndsdbqvtprmblnbvbnpvhtphbpjwdssvwgdzwztbpzdcsqzldjzrgcwhhspblrtncvntppcgttlflflnntcnzpbpgsclcjvbjhldcdzwjjhnfwzjmgcwtljhvbncwqnjhbrhfqcmnsdvntsbgnpqttzvbhzzpdznrhjpnsqzsztsblstbghlpwbmqjctlnqnttwshfvmjdhgbgjdhbzrfjqndrrhlqcmplczjtwpstlsmwwzqzmgvhsvjgbrtfwmvwlbhpccbqvmfmlgmbmbmldbcwmmhpnnbnffbnqgwhclgpzgbpjqvzmqhhhpltnwrdfrrnmlfrzflpnjztlnfzzzgmncprtblpsvrqgrnzbzfzhzhjjjdrnpvjpnwmlmlgvvtqmdvpnhvcrdmthcnnnvhnzmvgrtdvcthgjtvcgmtpsvmfztrflrrzbmcfhftwwcnjfpjtsnzjccmvdnrrwvbfjgcjttdvzncqhlqqphwphclztbhlqcfmnhcjmsscplnrsjqpdzrrzbthbcdnrzgdmstpgqqsvzclvmzjjdfqhhhttwcjtmwcbltghmslqvltqbjqqjpjvgntvnlttjcnhltflglgsmjwjjfldpfgjgrhttbwfhpsdbsmsfmfbtjlnhvjfqjrqhwdrcwpfthdgqzjjjfcvgdffrhvvwzfghpszmjjgscjvjnlgnbfbgfrbbzbzbnzngthrddfmsgsqqdddpfqwlchfblrvjdcgnzfzwmmnmvnzmpfmhbbhsbfdfclzcnbrlgpbsvfgfpshrpvpgccmmghphrcvzwnlqjcfwrtwvlvcsdldldvnpwgrcsqlftllcctnvcwbdswvqlzwzzbpmvvctcrgnjfstbqvnzczrjlljfqzrwtfwmlvvdfbfntrrljtbrtbdfsqpnppfbppbsmghbnqddhrvwmgzttnqjrqlfrdhqjndmnjlbctgclltmznmrqtfjsjwnztdvhnhlfwpnnqlhhsrfzglsnrdnfvrqssbtlthzfnjdvrcgzsbnpdgqhhrlwspfqfqpvzdfwgrlhwplzvbzprsqzcwvhggvzpgjztnvwvddsflgsvqljmmhhdzqsqmthwzvllqwmsnvdpdbjcgdtrsnmwhnzhbhgjssstmhrpssnhnntmrbbbjgmjqtncbdljcgtmbctpgdrnqcnrpssrdtpbsmlzlcztbrggglswnjzqgbsmgbqdzppqrwgtnlrjrvlpnqlcdwhltzzlqdwwrglldzcqrjtjtlgdqrtwzjgtdthsdccsmsrbjjsgdqcwdltvnjwtddsnpnsvzcdbfqnvsjbngqrztmbrnbvhhjzdtqrgldpvjqjpnshbjdsdgbjdjzdmrvzhwmtgcjrfnprstqgfgnwfpcjzhlnwpdbtqbspssqdrzhmmsrqtlwngvbrvgdgztnrlwcnqwvcdmhhdrmpfqbgbjpvzwbsbgcpsnpjplcrjdhflqvsdctclqqnmprngtvbmlmpqrsqdsrzgsmzmsczpsnmfmtfnjvnddjhqbjdvtgftjfvjhgpjqdhlszqjmcbnwrppzwjvmgblspjmfhjdbnmrllnfqlpcbndvqdzhhmmrpsljgdshpnrgnmwfjsdncqcwlctccrqghfdbsqqbnwctcqpvlrqqqvdjwlcnzmvdmcvlwnftjnqqldfwhmdtcpnlgfcdjdrfvmwqdzsjzctmmmrswhlwthttvcsqqscdcsmjgqfjhswlpsfjrppdmbwrthcwszqwwgnjsdqdrswmnzbrvqcwlrlwwvjmrrhsnzprggbzhhdqwvnspsmzzqdtbphzvwrzvqnbntjndrwllzwchczdwvnfjjdwfhdlgncftldzwdtjzjrmnfwwgmqdrltmgrfsjztfcvwjsggtvbnsvthflwfdtljrgqhmfqhmhfffqhtgwtlmwgzsglqnfwnrnvgvbdgqjrqtsmgsmzdpffnnzwlpbqphqmgdzspfrdqlptwmfwlgnqqdhtbbjtfhllrhhdcszjtmrprzhzzlgjqbcnhzcmhzrsnmmrzztffrldthhfvwhgjhwmjfbdvnllfmlpdsldjnpcwlpbwqzdwbgjb ================================================ FILE: exm/aoc/2022/aoc_2022_06_questions.txt ================================================ --- Day 6: Tuning Trouble --- The preparations are finally complete; you and the Elves leave camp on foot and begin to make your way toward the star fruit grove. As you move through the dense undergrowth, one of the Elves gives you a handheld device. He says that it has many fancy features, but the most important one to set up right now is the communication system. However, because he's heard you have significant experience dealing with signal-based systems, he convinced the other Elves that it would be okay to give you their one malfunctioning device - surely you'll have no problem fixing it. As if inspired by comedic timing, the device emits a few colorful sparks. To be able to communicate with the Elves, the device needs to lock on to their signal. The signal is a series of seemingly-random characters that the device receives one at a time. To fix the communication system, you need to add a subroutine to the device that detects a start-of-packet marker in the datastream. In the protocol being used by the Elves, the start of a packet is indicated by a sequence of four characters that are all different. The device will send your subroutine a datastream buffer (your puzzle input); your subroutine needs to identify the first position where the four most recently received characters were all different. Specifically, it needs to report the number of characters from the beginning of the buffer to the end of the first such four-character marker. For example, suppose you receive the following datastream buffer: mjqjpqmgbljsphdztnvjfqwrcgsmlb After the first three characters (mjq) have been received, there haven't been enough characters received yet to find the marker. The first time a marker could occur is after the fourth character is received, making the most recent four characters mjqj. Because j is repeated, this isn't a marker. The first time a marker appears is after the seventh character arrives. Once it does, the last four characters received are jpqm, which are all different. In this case, your subroutine should report the value 7, because the first start-of-packet marker is complete after 7 characters have been processed. Here are a few more examples: bvwbjplbgvbhsrlpgdmjqwftvncz: first marker after character 5 nppdvjthqldpwncqszvftbrmjlhg: first marker after character 6 nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg: first marker after character 10 zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw: first marker after character 11 How many characters need to be processed before the first start-of-packet marker is detected? --- Part Two --- Your device's communication system is correctly detecting packets, but still isn't working. It looks like it also needs to look for messages. A start-of-message marker is just like a start-of-packet marker, except it consists of 14 distinct characters rather than 4. Here are the first positions of start-of-message markers for all of the above examples: mjqjpqmgbljsphdztnvjfqwrcgsmlb: first marker after character 19 bvwbjplbgvbhsrlpgdmjqwftvncz: first marker after character 23 nppdvjthqldpwncqszvftbrmjlhg: first marker after character 23 nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg: first marker after character 29 zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw: first marker after character 26 How many characters need to be processed before the first start-of-message marker is detected? ================================================ FILE: exm/aoc/2022/aoc_2022_07.adb ================================================ -- Solution to Advent of Code 2022, Day 7 ------------------------------------------ -- No Space Left On Device -- -- https://adventofcode.com/2022/day/7 -- Copy of questions in: aoc_2022_07_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_07 is use HAT; root : constant := -1; subtype Cat_Entry_Range is Integer range root .. 1000; type Dir_Info is record name : VString; parent : Cat_Entry_Range; size : Natural; end record; cat : array (Cat_Entry_Range) of Dir_Info; current, up, last, i_min : Cat_Entry_Range := root; size, new_disk_size, size_cumul_small_dirs, best_new_size : Natural := 0; f : File_Type; s : VString; verbose : constant Boolean := False; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; begin Open (f, "aoc_2022_07.txt"); cat (root).name := +"/"; cat (root).parent := root; cat (root).size := 0; Read_Data : while not End_Of_File (f) loop Get_Line (f, s); s := s & ' '; case Element (s, 1) is when '$' => -- Command: case Element (s, 3) is when 'c' => -- "cd": case Element (s, 6) is when '.' => current := cat (current).parent; when '/' => current := root; when others => -- Subdirectory (hopefully unseen so far...): last := last + 1; cat (last).name := cat (current).name & Slice (s, 6, Index (s, ' ', 6) - 1) & '/'; cat (last).parent := current; cat (last).size := 0; current := last; end case; if verbose then Put_Line (+"New dir " & cat (current).name); end if; when others => null; end case; when '0' .. '9' => size := Integer_Value (Slice (s, 1, Index (s, ' ') - 1)); if verbose then Put_Line (+" File size : " & size); end if; up := current; loop cat (up).size := cat (up).size + size; if verbose then Put_Line (+" New total size for " & cat (up).name & " : " & cat (up).size); end if; exit when up = root; up := cat (up).parent; end loop; when others => -- Any other information, unused. null; end case; end loop Read_Data; Close (f); for i in root .. last loop -- -- We sum up the size of all directories with total sizes up to 100_000. -- Sub-directories are double-counted. -- if cat (i).size <= 100_000 then size_cumul_small_dirs := size_cumul_small_dirs + cat (i).size; end if; -- -- We look for removing the smallest possible directory, -- which means getting the largest possible new disk size, -- as long as the new disk size is up to 40_000_000. -- new_disk_size := cat (root).size - cat (i).size; if new_disk_size > best_new_size and then new_disk_size <= 40_000_000 then best_new_size := new_disk_size; i_min := i; end if; end loop; r (1) := size_cumul_small_dirs; r (2) := cat (i_min).size; if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: sum of total sizes of at most 100_000 : " & r (1)); Put_Line (+"Part 2: smallest directory to delete : " & r (2)); -- Part 1: validated by AoC: 1749646 -- Part 2: validated by AoC: 1498966 end if; end AoC_2022_07; ================================================ FILE: exm/aoc/2022/aoc_2022_07.txt ================================================ $ cd / $ ls dir gqlg dir hchrwstr dir lswlpt 189381 mzsnhlf dir plmdrbn dir rjwmjd dir stqq 93174 zfn dir zjhqnlrr dir zssdlnc $ cd gqlg $ ls 187654 cfrdsjf 100589 ntvmgbw 46922 zcmfcjhf.tzw $ cd .. $ cd hchrwstr $ ls 227766 cljjlcp.pjh 102770 rdbrcf.pjl 9887 rfnjn.lqn dir rzsrp dir shlhgj dir slwwgc $ cd rzsrp $ ls dir rzsrp $ cd rzsrp $ ls dir dvzvmsjz 208001 tnflwcsn dir zfn $ cd dvzvmsjz $ ls 149823 hvgbhm.zsc $ cd .. $ cd zfn $ ls 292424 gqlg.tzc $ cd .. $ cd .. $ cd .. $ cd shlhgj $ ls 61753 fzpzwjdt.jvl 195204 jjhc.tzr 288094 zcmfcjhf.tzw $ cd .. $ cd slwwgc $ ls 118185 jjhc.tzr 291916 jwnw.wqv 116377 ptlz 300849 pzjpw.hwg 28679 zfn.grz $ cd .. $ cd .. $ cd lswlpt $ ls 124160 dbnlt.rqz 154412 sfd $ cd .. $ cd plmdrbn $ ls dir fmzjhrq 224144 rlc.qns 2985 zcmfcjhf.tzw $ cd fmzjhrq $ ls 9749 lqj.szc dir rrjjsvm $ cd rrjjsvm $ ls 66652 zcmfcjhf.tzw $ cd .. $ cd .. $ cd .. $ cd rjwmjd $ ls dir twcrf 125294 zpfws.ctc dir zwmmrqj $ cd twcrf $ ls 229364 tnflwcsn 262716 zcmfcjhf.tzw $ cd .. $ cd zwmmrqj $ ls 11466 gqlg.ftg 220272 lflcgss.jrm 79574 tnflwcsn $ cd .. $ cd .. $ cd stqq $ ls 185160 cwjqldbf.cnm 266439 dpg.pwn dir hpgbcvtb 139357 jvps dir llbthqc 250148 mctn.dqw dir rzsrp 22196 tnflwcsn dir whmdbn $ cd hpgbcvtb $ ls 231579 fvjjtd.wdb 168118 gjdtscqs 113434 ldbqbg dir mqjfvg 182214 nnnr 112389 pqqdt.wnn $ cd mqjfvg $ ls 170328 gqlg.jjc $ cd .. $ cd .. $ cd llbthqc $ ls 25611 bftwd.qrr 91550 tnflwcsn $ cd .. $ cd rzsrp $ ls 272315 wrsfh.pzd 123877 zcmfcjhf.tzw $ cd .. $ cd whmdbn $ ls 29628 jjhc.tzr 65193 mrhb $ cd .. $ cd .. $ cd zjhqnlrr $ ls dir bzzvj dir ddzmvh dir dsjd 180806 fqz.dch dir nnzvl 109161 rptmqt 6463 rzsrp.sjf 111549 rzsrp.wwz 241532 zfn $ cd bzzvj $ ls 278759 gqlg.nsn 174223 mvggzqrq 156518 tnflwcsn dir wjtlg dir zfn $ cd wjtlg $ ls 52198 fvqbtm.tch 44881 tnflwcsn $ cd .. $ cd zfn $ ls 22926 tnflwcsn $ cd .. $ cd .. $ cd ddzmvh $ ls dir cpvfln 180764 gqlg.bjq dir hgrnmh 186254 hgrnmh.tpr dir hjpgf dir mghmb dir pvdwhmcr 256578 rzsrp 269955 shlhgj 172163 vrr.nnm $ cd cpvfln $ ls 87025 hgrnmh.lvr 187453 rwmq.dph dir sthhc $ cd sthhc $ ls 289580 fdzwmfnf 57504 hgrnmh.vqj 277639 mzcfchr.mch dir slsj dir vsvvprg 94836 zqglfrl $ cd slsj $ ls 178013 hdjgtqt $ cd .. $ cd vsvvprg $ ls 102783 fvqbtm.tch $ cd .. $ cd .. $ cd .. $ cd hgrnmh $ ls dir mrnmbbt 240216 rzsrp.nfg $ cd mrnmbbt $ ls 245579 gqlg $ cd .. $ cd .. $ cd hjpgf $ ls 257544 cjfd.wdq 296077 jjhc.tzr 195752 zcmfcjhf.tzw $ cd .. $ cd mghmb $ ls dir bgrcsdc dir btjq dir gqlg dir gtwdqw dir hgrnmh dir jts dir jvp dir jvrjcv 206272 pgf.rgj 130746 tnflwcsn 256698 zfn.dhl $ cd bgrcsdc $ ls 235762 lflcgss.jrm $ cd .. $ cd btjq $ ls dir bvrcqb dir drslln dir dwzpblb dir gqlg dir hgrnmh dir hvb dir rqtc dir vsdz dir wrnftqh $ cd bvrcqb $ ls 51508 gjjg.msw dir gqlg 13206 pdwn 10427 vbw 6909 zfn.ztq $ cd gqlg $ ls 20816 cmgcvlh.mzs 10358 fvqbtm.tch 215142 rzsrp.dns 192153 wdjdppzm $ cd .. $ cd .. $ cd drslln $ ls 258102 tnflwcsn $ cd .. $ cd dwzpblb $ ls 302466 fvqbtm.tch $ cd .. $ cd gqlg $ ls dir hnr dir mdzdht $ cd hnr $ ls dir fjd 159298 fvqbtm.tch 46324 gchdll.nrm 287907 lflcgss.jrm dir mqp 140272 twdff 47399 zfn $ cd fjd $ ls 227109 fvqbtm.tch 223413 wdsfwwwm.rmd $ cd .. $ cd mqp $ ls dir rzsrp $ cd rzsrp $ ls dir pgwng $ cd pgwng $ ls 218271 hgrnmh.gnf $ cd .. $ cd .. $ cd .. $ cd .. $ cd mdzdht $ ls dir gqlg dir tvd $ cd gqlg $ ls dir gfjqbdp 108335 jjhc.tzr $ cd gfjqbdp $ ls 143536 fzvn.jtv $ cd .. $ cd .. $ cd tvd $ ls 238491 wsjmrlqv.bwb $ cd .. $ cd .. $ cd .. $ cd hgrnmh $ ls 265289 lflcgss.jrm 111283 thb $ cd .. $ cd hvb $ ls dir hgrnmh dir smmwg $ cd hgrnmh $ ls dir wpvssts 84939 zcmfcjhf.tzw $ cd wpvssts $ ls 305634 whcmr $ cd .. $ cd .. $ cd smmwg $ ls 36722 cvdbwg.rll 16840 nnhbcbwz dir rzsrp 9405 zfn.jzr $ cd rzsrp $ ls dir fzsngr $ cd fzsngr $ ls 142687 zcmfcjhf.tzw $ cd .. $ cd .. $ cd .. $ cd .. $ cd rqtc $ ls dir pbzhfsg dir rzsrp dir shlhgj $ cd pbzhfsg $ ls 41865 hpshz.sdf $ cd .. $ cd rzsrp $ ls dir gqlg dir mbsjjzft $ cd gqlg $ ls dir gqlg dir nvjqp $ cd gqlg $ ls 21860 tnflwcsn $ cd .. $ cd nvjqp $ ls dir gcq $ cd gcq $ ls dir mslhm dir rzsrp $ cd mslhm $ ls 41304 rpgvllw.zfj $ cd .. $ cd rzsrp $ ls 290199 ddsnt $ cd .. $ cd .. $ cd .. $ cd .. $ cd mbsjjzft $ ls 47727 ggpmg.pps dir stgszvmj 275954 tnflwcsn 248613 vbgnwh.sjz $ cd stgszvmj $ ls dir dthcrbmr dir shlhgj 206580 zcmfcjhf.tzw dir zfn $ cd dthcrbmr $ ls dir lhp dir npf dir qbgrjr $ cd lhp $ ls 37925 hgrnmh.lvm $ cd .. $ cd npf $ ls 77162 bqvd $ cd .. $ cd qbgrjr $ ls 48767 fvqbtm.tch $ cd .. $ cd .. $ cd shlhgj $ ls dir wtlngn 35422 zfn $ cd wtlngn $ ls dir gqlg $ cd gqlg $ ls 64761 fwtqw $ cd .. $ cd .. $ cd .. $ cd zfn $ ls 47247 dmlr.flv 259570 htvn.rbz 149238 qrdw $ cd .. $ cd .. $ cd .. $ cd .. $ cd shlhgj $ ls dir cjmv dir tns $ cd cjmv $ ls 140919 jjhc.tzr $ cd .. $ cd tns $ ls 248127 fvqbtm.tch 216202 pwg dir qhhtgsvz $ cd qhhtgsvz $ ls 68979 fvqbtm.tch $ cd .. $ cd .. $ cd .. $ cd .. $ cd vsdz $ ls 224491 hgrnmh dir jsrqjjtc dir shlhgj 123062 zfn.gss $ cd jsrqjjtc $ ls 245991 phc $ cd .. $ cd shlhgj $ ls 284208 ctwmwlp.lnm 11067 vwsrmlf.dvz $ cd .. $ cd .. $ cd wrnftqh $ ls 237658 lldrh 14804 nszc.wdf $ cd .. $ cd .. $ cd gqlg $ ls 211474 jjhc.tzr $ cd .. $ cd gtwdqw $ ls 92613 fvqbtm.tch 206813 ppzhmnb.grd $ cd .. $ cd hgrnmh $ ls 249351 bftm $ cd .. $ cd jts $ ls 132190 gqlg.vnn 208091 ldnq 202593 zcmfcjhf.tzw $ cd .. $ cd jvp $ ls 258220 lflcgss.jrm $ cd .. $ cd jvrjcv $ ls 20148 dzzlwp.bdj 289774 hgrnmh.bvc 296981 jwscd.cvj 16617 tbnwvcl.tlv $ cd .. $ cd .. $ cd pvdwhmcr $ ls dir bhmmsbmb dir bjwbvcq dir hgrnmh dir ltvtrtth dir prtqcb dir rmn dir shlhgj dir tmzcmb dir vlbqvps dir wmmfp $ cd bhmmsbmb $ ls dir nccjwf $ cd nccjwf $ ls dir drwhjfjn 206638 lflcgss.jrm $ cd drwhjfjn $ ls 291772 zcmfcjhf.tzw $ cd .. $ cd .. $ cd .. $ cd bjwbvcq $ ls dir zfn $ cd zfn $ ls 303808 wrbldbd $ cd .. $ cd .. $ cd hgrnmh $ ls 142765 fvqbtm.tch 159497 scqf.scf 270819 zcmfcjhf.tzw $ cd .. $ cd ltvtrtth $ ls dir fwtwqvn 156894 jnmqdq.zgp 297860 lflcgss.jrm dir mcgcc dir zfn 179328 zfn.vnn dir zzsnz $ cd fwtwqvn $ ls dir rqndc dir rzsrp 124999 rzsrp.tvr dir shlhgj $ cd rqndc $ ls 45124 zrcv $ cd .. $ cd rzsrp $ ls 74041 rzsrp $ cd .. $ cd shlhgj $ ls 117219 qptfpz.cgc 281188 shlhgj.bhd 121750 sptql 173637 vqp.dbs $ cd .. $ cd .. $ cd mcgcc $ ls 18295 gqlg dir ngvwhnvf 177283 rjsrn.rlq 54239 rzsrp.tfq $ cd ngvwhnvf $ ls 207616 jjhc.tzr $ cd .. $ cd .. $ cd zfn $ ls dir cwzbljh $ cd cwzbljh $ ls 134952 hmchpgn.nwf $ cd .. $ cd .. $ cd zzsnz $ ls 273014 shlhgj.pls $ cd .. $ cd .. $ cd prtqcb $ ls dir dtr dir rzsrp 199012 tnflwcsn $ cd dtr $ ls dir gqlg dir grwpbs dir hgrnmh 115701 lflcgss.jrm 247838 tnflwcsn 268721 zcmfcjhf.tzw 15320 zwcd.dqb $ cd gqlg $ ls 285009 jjhc.tzr 125691 nhnlcjjt.zlj 54424 rzsrp.rll $ cd .. $ cd grwpbs $ ls 59390 rzsrp.cms $ cd .. $ cd hgrnmh $ ls 185747 lvtnqqdh.nzq $ cd .. $ cd .. $ cd rzsrp $ ls 268631 hvvpfd.smn 263890 tcrctpb.pcc $ cd .. $ cd .. $ cd rmn $ ls dir gtnvc 205894 hqb.fwh 280887 lvvmjb.scj dir rsnqlfsz $ cd gtnvc $ ls 28523 jjhc.tzr $ cd .. $ cd rsnqlfsz $ ls dir hgrnmh dir nsfhtthc $ cd hgrnmh $ ls 183216 fvqbtm.tch $ cd .. $ cd nsfhtthc $ ls 284747 jspmbh.rvh $ cd .. $ cd .. $ cd .. $ cd shlhgj $ ls 144391 dzf dir lrths 178083 nhlmsd.mnc dir rwn 173833 shlhgj.qss 39183 tnflwcsn 125029 zfn.hjr $ cd lrths $ ls dir hgrnmh dir pfc 86563 rzsrp.gbc 280631 tmhnc.hmc 28181 ttsnjc.rhm 98060 vdmr.czg dir vlshvmvj dir wsn 210337 zfn.pqp $ cd hgrnmh $ ls dir mvrlcvj $ cd mvrlcvj $ ls 121034 vssbr.qjm $ cd .. $ cd .. $ cd pfc $ ls dir gqlg $ cd gqlg $ ls 305519 hdhn.wds $ cd .. $ cd .. $ cd vlshvmvj $ ls 56641 lflcgss.jrm 29190 rzsrp.vsh 36663 zcmfcjhf.tzw $ cd .. $ cd wsn $ ls 137307 gmdfbfjf.crs dir hgtqj 297924 lflcgss.jrm dir shlhgj $ cd hgtqj $ ls 214202 qnlszftb.bzg $ cd .. $ cd shlhgj $ ls dir pmldlbbh $ cd pmldlbbh $ ls 263722 zwfptl.wsh $ cd .. $ cd .. $ cd .. $ cd .. $ cd rwn $ ls 279589 ttqg.qct $ cd .. $ cd .. $ cd tmzcmb $ ls 138557 jjhc.tzr $ cd .. $ cd vlbqvps $ ls dir nmfnf 123659 rzsrp $ cd nmfnf $ ls dir jhpnd 50537 trzvzvgz.bqp 41828 vps 195245 wlwt.ftj $ cd jhpnd $ ls 257519 shlhgj.fwz 32963 wzmbdtz $ cd .. $ cd .. $ cd .. $ cd wmmfp $ ls 94749 lflcgss.jrm $ cd .. $ cd .. $ cd .. $ cd dsjd $ ls 284923 bjvwg.phz dir bwjp dir gqlg dir hgrnmh 8771 jjhc.tzr dir jntt 271995 qbtn.vps 299501 shlhgj.crl dir vmph dir zvg $ cd bwjp $ ls 117739 vtrg $ cd .. $ cd gqlg $ ls dir dwhr 159876 hgrnmh.jvw dir rzsrp $ cd dwhr $ ls 193289 gqlg 171323 lflcgss.jrm $ cd .. $ cd rzsrp $ ls dir pmsgd $ cd pmsgd $ ls 12648 lflcgss.jrm dir wbppspwq $ cd wbppspwq $ ls 38834 tnflwcsn $ cd .. $ cd .. $ cd .. $ cd .. $ cd hgrnmh $ ls 76649 cfdcbvdl.gfs 257249 gmmzf 83045 lhrtfcz $ cd .. $ cd jntt $ ls 286866 lhqvt.lst $ cd .. $ cd vmph $ ls dir fnvpsr dir gfnvsznj 19765 zcmfcjhf.tzw 204319 zzsnj.dcp $ cd fnvpsr $ ls dir flz 173924 fvqbtm.tch 248297 mjrhs.scq dir rzsrp 130580 zfn $ cd flz $ ls 106168 brsgg $ cd .. $ cd rzsrp $ ls 221882 hgrnmh.nsl dir smd $ cd smd $ ls dir drsld 131686 fvqbtm.tch dir gqlg 288283 hcw $ cd drsld $ ls 85885 zfn.wdf $ cd .. $ cd gqlg $ ls 8466 dzjtj.zbc $ cd .. $ cd .. $ cd .. $ cd .. $ cd gfnvsznj $ ls dir fqb 265075 gqlg dir hdhmbtj 74385 hpz dir lzdq dir rlvqmwv dir rzsrp $ cd fqb $ ls 55182 ccjgpg 245930 ppdgwcm.zfb 164364 sgtgqdn.tfp $ cd .. $ cd hdhmbtj $ ls dir gqlg 68609 jjhc.tzr dir rzsrp dir vrmrnt 66988 zcmfcjhf.tzw $ cd gqlg $ ls 156776 tnflwcsn dir vdcbg $ cd vdcbg $ ls 261780 lflcgss.jrm $ cd .. $ cd .. $ cd rzsrp $ ls 27818 zfn $ cd .. $ cd vrmrnt $ ls 273664 msmzfnj.llc 145156 svzmwnrq.chh $ cd .. $ cd .. $ cd lzdq $ ls 214363 fms 190021 lfzcgh.dsq 21357 qtvvmj.zqw $ cd .. $ cd rlvqmwv $ ls dir gqlg 198296 gqlg.sdz 842 gshcswc.dcb dir shlhgj 199828 snng $ cd gqlg $ ls 183087 zfn.nsj $ cd .. $ cd shlhgj $ ls 73040 tzgjrqmb $ cd .. $ cd .. $ cd rzsrp $ ls 229576 vtftgng.wfz $ cd .. $ cd .. $ cd .. $ cd zvg $ ls 85701 shlhgj.dvf $ cd .. $ cd .. $ cd nnzvl $ ls dir wwzsf $ cd wwzsf $ ls 105177 tvbdz $ cd .. $ cd .. $ cd .. $ cd zssdlnc $ ls dir nfgh 166004 twdcrh.zld dir zfn $ cd nfgh $ ls 102281 fvqbtm.tch $ cd .. $ cd zfn $ ls dir fbmww dir jsst 206602 shlhgj.cln $ cd fbmww $ ls 179734 fll $ cd .. $ cd jsst $ ls dir flp $ cd flp $ ls 32274 gctgt.stn 67650 ggvj.bwz ================================================ FILE: exm/aoc/2022/aoc_2022_07_questions.txt ================================================ --- Day 7: No Space Left On Device --- You can hear birds chirping and raindrops hitting leaves as the expedition proceeds. Occasionally, you can even hear much louder sounds in the distance; how big do the animals get out here, anyway? The device the Elves gave you has problems with more than just its communication system. You try to run a system update: $ system-update --please --pretty-please-with-sugar-on-top Error: No space left on device Perhaps you can delete some files to make space for the update? You browse around the filesystem to assess the situation and save the resulting terminal output (your puzzle input). For example: $ cd / $ ls dir a 14848514 b.txt 8504156 c.dat dir d $ cd a $ ls dir e 29116 f 2557 g 62596 h.lst $ cd e $ ls 584 i $ cd .. $ cd .. $ cd d $ ls 4060174 j 8033020 d.log 5626152 d.ext 7214296 k The filesystem consists of a tree of files (plain data) and directories (which can contain other directories or files). The outermost directory is called /. You can navigate around the filesystem, moving into or out of directories and listing the contents of the directory you're currently in. Within the terminal output, lines that begin with $ are commands you executed, very much like some modern computers: cd means change directory. This changes which directory is the current directory, but the specific result depends on the argument: cd x moves in one level: it looks in the current directory for the directory named x and makes it the current directory. cd .. moves out one level: it finds the directory that contains the current directory, then makes that directory the current directory. cd / switches the current directory to the outermost directory, /. ls means list. It prints out all of the files and directories immediately contained by the current directory: 123 abc means that the current directory contains a file named abc with size 123. dir xyz means that the current directory contains a directory named xyz. Given the commands and output in the example above, you can determine that the filesystem looks visually like this: - / (dir) - a (dir) - e (dir) - i (file, size=584) - f (file, size=29116) - g (file, size=2557) - h.lst (file, size=62596) - b.txt (file, size=14848514) - c.dat (file, size=8504156) - d (dir) - j (file, size=4060174) - d.log (file, size=8033020) - d.ext (file, size=5626152) - k (file, size=7214296) Here, there are four directories: / (the outermost directory), a and d (which are in /), and e (which is in a). These directories also contain files of various sizes. Since the disk is full, your first step should probably be to find directories that are good candidates for deletion. To do this, you need to determine the total size of each directory. The total size of a directory is the sum of the sizes of the files it contains, directly or indirectly. (Directories themselves do not count as having any intrinsic size.) The total sizes of the directories above can be found as follows: The total size of directory e is 584 because it contains a single file i of size 584 and no other directories. The directory a has total size 94853 because it contains files f (size 29116), g (size 2557), and h.lst (size 62596), plus file i indirectly (a contains e which contains i). Directory d has total size 24933642. As the outermost directory, / contains every file. Its total size is 48381165, the sum of the size of every file. To begin, find all of the directories with a total size of at most 100000, then calculate the sum of their total sizes. In the example above, these directories are a and e; the sum of their total sizes is 95437 (94853 + 584). (As in this example, this process can count files more than once!) Find all of the directories with a total size of at most 100000. What is the sum of the total sizes of those directories? Your puzzle answer was 1749646. --- Part Two --- Now, you're ready to choose a directory to delete. The total disk space available to the filesystem is 70000000. To run the update, you need unused space of at least 30000000. You need to find a directory you can delete that will free up enough space to run the update. In the example above, the total size of the outermost directory (and thus the total amount of used space) is 48381165; this means that the size of the unused space must currently be 21618835, which isn't quite the 30000000 required by the update. Therefore, the update still requires a directory with total size of at least 8381165 to be deleted before it can run. To achieve this, you have the following options: Delete directory e, which would increase unused space by 584. Delete directory a, which would increase unused space by 94853. Delete directory d, which would increase unused space by 24933642. Delete directory /, which would increase unused space by 48381165. Directories e and a are both too small; deleting them would not free up enough space. However, directories d and / are both big enough! Between these, choose the smallest: d, increasing unused space by 24933642. Find the smallest directory that, if deleted, would free up enough space on the filesystem to run the update. What is the total size of that directory? ================================================ FILE: exm/aoc/2022/aoc_2022_08.adb ================================================ -- Solution to Advent of Code 2022, Day 8 ------------------------------------------ -- Treetop Tree House -- -- https://adventofcode.com/2022/day/8 -- Copy of questions in: aoc_2022_08_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_08 is use HAT; m : constant := 99; subtype Tree_Height is Natural range 0 .. 9; map : array (1 .. m, 1 .. m) of Tree_Height; dump : constant Boolean := False; procedure Dump_CSV is d : File_Type; begin Create (d, "forest.csv"); for i in 1 .. m loop for j in 1 .. m loop Put (d, map (i, j)); Put (d, ';'); end loop; New_Line (d); end loop; Close (d); end Dump_CSV; -- PPM output. Sources: -- https://codeberg.org/rommudoh/aoc2022-Ada/src/branch/main/src/day08.adb -- https://rosettacode.org/wiki/Bitmap/Write_a_PPM_file#Ada -- procedure Dump_PPM is subtype Color_Range is Natural range 0 .. 255; type Pixel is record R, G, B : Color_Range; end record; d : File_Type; px : Pixel; begin Create (d, "forest.ppm"); Put (d, "P6" & Chr (10)); Put (d, m); Put (d, ' '); Put (d, m); Put (d, Chr (10)); Put (d, "255" & Chr (10)); for i in 1 .. m loop for j in 1 .. m loop case map (i, j) is when 0 .. 1 => px.R := 16#99#; px.G := 16#99#; px.B := 16#ff#; when 2 .. 3 => px.R := 16#99#; px.G := 16#33#; px.B := 16#66#; when 4 .. 5 => px.R := 16#ff#; px.G := 16#ff#; px.B := 16#cc#; when 6 .. 7 => px.R := 16#cc#; px.G := 16#ff#; px.B := 16#ff#; when 8 .. 9 => px.R := 16#66#; px.G := 16#00#; px.B := 16#66#; end case; Put (d, Chr (px.R)); Put (d, Chr (px.G)); Put (d, Chr (px.B)); end loop; end loop; Close (d); end Dump_PPM; new_tree : array (1 .. m, 1 .. m) of Boolean; scenic : array (1 .. m, 1 .. m) of Natural; h : Tree_Height; score, visible_trees : Natural; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; c : Character; f : File_Type; begin Open (f, "aoc_2022_08.txt"); Read_Data : for i in 1 .. m loop for j in 1 .. m loop Get (f, c); map (i, j) := Ord (c) - Ord ('0'); scenic (i, j) := 1; new_tree (i, j) := True; end loop; end loop Read_Data; Close (f); if dump then -- Just for plotting the forest :-) Dump_CSV; Dump_PPM; end if; --------------------------- -- Part 1 -- -- Count visible trees -- --------------------------- visible_trees := 0; Horizontal_Scans : for i in 2 .. m - 1 loop h := map (i, 1); From_Left : for j in 2 .. m - 1 loop if map (i, j) > h then if new_tree (i, j) then visible_trees := visible_trees + 1; new_tree (i, j) := False; end if; h := map (i, j); end if; end loop From_Left; h := map (i, m); From_Right : for j in reverse 2 .. m - 1 loop if map (i, j) > h then if new_tree (i, j) then visible_trees := visible_trees + 1; new_tree (i, j) := False; end if; h := map (i, j); end if; end loop From_Right; end loop Horizontal_Scans; Vertical_Scans : for j in 2 .. m - 1 loop h := map (1, j); From_Top : for i in 2 .. m - 1 loop if map (i, j) > h then if new_tree (i, j) then visible_trees := visible_trees + 1; new_tree (i, j) := False; end if; h := map (i, j); end if; end loop From_Top; h := map (m, j); From_Bottom : for i in reverse 2 .. m - 1 loop if map (i, j) > h then if new_tree (i, j) then visible_trees := visible_trees + 1; new_tree (i, j) := False; end if; h := map (i, j); end if; end loop From_Bottom; end loop Vertical_Scans; -- Variable `visible_trees` holds now the number -- of visible trees that are inside the forest. -- The trees on the edge are all visible. r (1) := 2 * m + 2 * (m - 2) + visible_trees; ------------------------------------ -- Part 2 -- -- Compute highest scenic score -- ------------------------------------ for i in 1 .. m loop for j in 1 .. m loop score := 0; To_the_Left : for jj in reverse 1 .. j - 1 loop score := score + 1; exit To_the_Left when map (i, jj) >= map (i, j); end loop To_the_Left; scenic (i, j) := scenic (i, j) * score; score := 0; To_the_Right : for jj in j + 1 .. m loop score := score + 1; exit To_the_Right when map (i, jj) >= map (i, j); end loop To_the_Right; scenic (i, j) := scenic (i, j) * score; score := 0; To_the_Top : for ii in reverse 1 .. i - 1 loop score := score + 1; exit To_the_Top when map (ii, j) >= map (i, j); end loop To_the_Top; scenic (i, j) := scenic (i, j) * score; score := 0; To_the_Bottom : for ii in i + 1 .. m loop score := score + 1; exit To_the_Bottom when map (ii, j) >= map (i, j); end loop To_the_Bottom; scenic (i, j) := scenic (i, j) * score; end loop; end loop; -- Compute highest scenic score: score := 0; for i in 2 .. m - 1 loop for j in 2 .. m - 1 loop score := Max (score, scenic (i, j)); end loop; end loop; r (2) := score; if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: visible trees . . . . . . : " & r (1)); Put_Line (+"Part 2: highest scenic score . . : " & r (2)); -- Part 1: validated by AoC: 1843 -- Part 2: validated by AoC: 180000 end if; end AoC_2022_08; ================================================ FILE: exm/aoc/2022/aoc_2022_08.txt ================================================ 102212110110302230012132130441442043243242145112422525112333344240121120342411110001231112222021211 222101001302011022124443303121322323142224235123233315215333545242421321241403143213333101310210211 200201223122002022301310313414224443253123231515151513541254251131310343344222040320023211301320200 200010213032223103230132143412204353411323525332513442523314324332413034422122304413120211230122212 010211000332000340422300132032513533513115523254315325423242433353351244232123121111220123121333221 200122303232310323111312343413321244422555551325423211253434511531321144403333313021201212232131220 000212003210330240303442205443113542544534111314155152232435243131155352422402104202123433111201232 103312101101443020314140255354241134315242455146454323625133153413235312512313332430221300331131100 010220000301314241214335313133422432322123354664326463436444322422342554355225140334421002113133121 323101132001123022243353315252233331435562622453564455524652525652244413142424222440021003003130221 311311300011420441113315524451532135232526456634245324454325625255644144511435413342301130211231301 122330114303143110342335214315243456332354435254662545365545352556636544332142113343020330142302023 022120000403423231542555223312544433353262526636242665353354342624542223253541435144031113311431220 210013131013443325232155555522255445233525524424425466462465252544334662211253135515414212121223103 122130234323200111421534352526522446635243456643673475346653325362454362443421552412233011444032132 330230413401024335441342264233664326224445367753634776764473243636265344556415445523524224043114211 020342003212232435413445263654334245243765543345436537434453757662242253666363442422244144403424000 200102231042423341434316352256242653765564636564563755363577363456266625662553514113422123403421132 313204040243524231344465644555626363733665445433637447335677545646763646633226445435325125112213414 314103222004445425153443435336445733737355475744355366644536666633436334423645665121453234041020422 241224100115215322523535566553547766677645474354634357364574375657645546622424324323251244433440201 022222042544545521533326245235374365344376774543443767376646565377535776236535264522124353322203234 422222135434133533655352463473735556656745548755787857555356377355447565365456463664354434453044312 304324242134435426624362552443745545463386458858447758455754543677463336472433462334512421444332223 341414135242433442655442346556355346658767857767584647675766884536373667347366462552211223152411402 322422011132511352664233364365653466744454566746588468655774844685736565337465223255264314431430230 230422221453335454423325334433457458687888455486757548466746647544834643335672463455634151341522302 234004552353522225535427357745555646855484747845567786675574858868655476475453443665223324353452113 020135314133142653352266355334757758775757788848887684458858675874884637537467525625364253131211244 414342423551254236456446367655347867476487576757978699668748774646468564677435372565356631415154301 402224514555445234247373353744455587885585976595966767878796785855864485334466564262266452143444311 322114434454542333646465444736668764744886688767569596959858556668754886535574755434322662442212133 121324243324423343546763375477766585857886776859668579795978997478645686674366773535335522313423220 133542124333622654643366436564658876577978579997657798669999767568447887467776367522435455533321443 023413415133262422437473376558558855786797675666795779995686567865485584745545375742263662533555543 141153353554563662677655657576756468676875598877958956899955978897446555748753563362626454221131125 325353321363522257537756588466744857658697678559699997698595865765578845586445367745536633643312255 423213544666625365635544655675458885666985859697786876896858858797786874566466456657466442525434421 111454444524556247634754788885848856779676996689987686878899758967589455644666556534542332454425232 113454234223324274556335586767549686998856766879779799897977886877798476548873366444323624534235512 413111246643442463347377577668885588996599677886898888866767856868795965878475573774545255562121514 033322552545543547534354548647668766698879698968876698988768678695558875847754474335753623445451141 033335136263443377434448478688978869869678786967679698969669778569788867674444636373445324354533414 234114125435462653577777876855756557856867678669979986768879699797765796588455677467665646523542244 315515242442526536477764768685998958898698776897898777978978889975778988546787635537642445246521555 321543542424553344445665648775695579876967767799989797989877898976866779658748865436436245526532153 214442166263264436546368554888589767787766679977779878789696679785859879648657647656345336454331514 534225433653422444656547767677967556776977788979899998877878867678798578885766845756635543235613324 451252264522467473463764566489668785797977788978898788799896886865858766846568667573775654463254212 142243545346537474556565585866986596889698977988978988797896887869755867746847846457535246243622521 314533543366656735447764644785876759686776988887899987977868668886569975674466755746757543333613415 423155324556563534544657846546998786988679877979797897977866789679597759764485834747537363422511525 111123232243256547763345885669578779768699999987898779978667968776659685647547563666543566442343212 153351242236666565346454875568986796797687677988888979789886768978999686477777536735573656352555412 323332424652563666766546867459698977996778977989988888888788678879875896444874453373545246666243111 135523512363264534676375878685595968577686668988899788976766699895667985668547534554755246336443443 532252346635325565376768676458557777667966786898889778979967688766768868568846557747445423253133325 021423433266355547435457658778656599566767767766877768698699878975689884477647674353546424463554451 143143223365543567635335747757587977786897796676679778966786689768589657474877567637754423223422312 042415253643232575556737767785757788676996887999678977967666877589856675557885677334454634555223453 234134135655336276745375664665486567958579869999988689769887997756966947584657365476724435655111251 042425212462644477445435755454677877597667699897769689877689755868578567458576456463552232355231414 354513445446645356573335466767579577676958688689866686776999686878859666766855753737445265524242214 233154124332425336374475485444574569589885768789686679877995988778897787557646674666625354631424244 242554311144536267576756377488488867896687566758869688757566767878568654674856637746343532221224535 031352533424343666353537635778657888979797968869596858555897765778484557476745657576565652351431515 244111523123546656444743447588484547797769687556999759895965969964878878867565456634442462655533330 101154321124235234634644573645444776899979778958586696559589578574766767767776545323635556543324520 230453243413346443656346633655876856466765588966595989676877687676564857856756335622566465554243444 400115531525436425435363466676884457554568997656888965766988578885546646566546575455244664152151421 121244523334642663334357574375756475655847758985795997565974854847688754735474744655256243422233523 442124553352143426554554663364376844777584585568578895884475557584464677453543662566322652421252333 121445542333545553333233367636337576575784548858744665868786757667467367567665363332432223545423200 020321333225342646522423376435557446777478648478548458845546545678744437577337244622534425211350022 041332232423124342256245433633577566478865647545565685666764666787764767576462433566522451433113043 014424132244453224234546334667567447876654868784855884886878754645547664773756545644453424241524312 414311054242342142224533466634464356437556445785767567866777856766576577644556443654324531342222310 310322213415213433425552662577476354776577788877577647884464577437343437336643223244511135242014011 300241033122121121456356264344335565375647366774864774858553747547334674624355256434534221515041124 244113020144235342335234634564444633644736357543455335653765466354354346565443633362331511132134132 143133204011342551536234336443376364333444577754334556634356574777657644433624432451425543542044012 124214441344114214133244352626436376363654365447576564735347353654435326246226356243423532004304101 101243244443555155315534544462433463654377635665747456733666473757525254363464365544115552421213312 220422144420114253554354265345456453344337374375545645445347674334436455364526444454513431401002123 313223311020451432455413454445642422634537364635666546754656735345535652356322545145325423121103202 331004402420123535413315226646464442326356744477434645574333466622343266264444114525225333122240311 112302121222114254552233452266654536466263462644653436655626223464363536324452444455541022040211131 212012013423120023144244325334534664552523526224436442254665635246443333635121151334524401320433130 001121341442114243125433441523554465523535244533322625264462365223623553532133143211423424102210003 223220023212441130233151252342414632544243253526323465544536453355466344221452532544441122243331202 312121212403143043222224331132453532666642654664652655433535463465343224212113542013034330243203021 202012103340130001242425435444222111424542356345243653462563232352212415345354221301440242321032000 212202110121021140441443523243344241514332562652664256563344623454345255222133212212024343023301122 021010131200334014423400143154151315325512332544243346551323121315214235513143134101443433302011002 122302321231131322434420345125245413215132313112255444513255422341524133353314114412224230231302110 110111100102010040122344032453213533213254233521331414232113423512123251530432223244441332003202300 200023022231020232023042313022141535414442413511535352414333413345343120402340033343211011203223002 001120213231313130220231100314421411535333234424124253354254335222245404210032440401122303031121122 011011030023132123022011022032214014533223521512511221453113132215230244324434210342210100311021222 ================================================ FILE: exm/aoc/2022/aoc_2022_08_questions.txt ================================================ --- Day 8: Treetop Tree House --- The expedition comes across a peculiar patch of tall trees all planted carefully in a grid. The Elves explain that a previous expedition planted these trees as a reforestation effort. Now, they're curious if this would be a good location for a tree house. First, determine whether there is enough tree cover here to keep a tree house hidden. To do this, you need to count the number of trees that are visible from outside the grid when looking directly along a row or column. The Elves have already launched a quadcopter to generate a map with the height of each tree (your puzzle input). For example: 30373 25512 65332 33549 35390 Each tree is represented as a single digit whose value is its height, where 0 is the shortest and 9 is the tallest. A tree is visible if all of the other trees between it and an edge of the grid are shorter than it. Only consider trees in the same row or column; that is, only look up, down, left, or right from any given tree. All of the trees around the edge of the grid are visible - since they are already on the edge, there are no trees to block the view. In this example, that only leaves the interior nine trees to consider: The top-left 5 is visible from the left and top. (It isn't visible from the right or bottom since other trees of height 5 are in the way.) The top-middle 5 is visible from the top and right. The top-right 1 is not visible from any direction; for it to be visible, there would need to only be trees of height 0 between it and an edge. The left-middle 5 is visible, but only from the right. The center 3 is not visible from any direction; for it to be visible, there would need to be only trees of at most height 2 between it and an edge. The right-middle 3 is visible from the right. In the bottom row, the middle 5 is visible, but the 3 and 4 are not. With 16 trees visible on the edge and another 5 visible in the interior, a total of 21 trees are visible in this arrangement. Consider your map; how many trees are visible from outside the grid? --- Part Two --- Content with the amount of tree cover available, the Elves just need to know the best spot to build their tree house: they would like to be able to see a lot of trees. To measure the viewing distance from a given tree, look up, down, left, and right from that tree; stop if you reach an edge or at the first tree that is the same height or taller than the tree under consideration. (If a tree is right on the edge, at least one of its viewing distances will be zero.) The Elves don't care about distant trees taller than those found by the rules above; the proposed tree house has large eaves to keep it dry, so they wouldn't be able to see higher than the tree house anyway. In the example above, consider the middle 5 in the second row: 30373 25512 65332 33549 35390 Looking up, its view is not blocked; it can see 1 tree (of height 3). Looking left, its view is blocked immediately; it can see only 1 tree (of height 5, right next to it). Looking right, its view is not blocked; it can see 2 trees. Looking down, its view is blocked eventually; it can see 2 trees (one of height 3, then the tree of height 5 that blocks its view). A tree's scenic score is found by multiplying together its viewing distance in each of the four directions. For this tree, this is 4 (found by multiplying 1 * 1 * 2 * 2). However, you can do even better: consider the tree of height 5 in the middle of the fourth row: 30373 25512 65332 33549 35390 Looking up, its view is blocked at 2 trees (by another tree with a height of 5). Looking left, its view is not blocked; it can see 2 trees. Looking down, its view is also not blocked; it can see 1 tree. Looking right, its view is blocked at 2 trees (by a massive tree of height 9). This tree's scenic score is 8 (2 * 2 * 1 * 2); this is the ideal spot for the tree house. Consider each tree on your map. What is the highest scenic score possible for any tree? ================================================ FILE: exm/aoc/2022/aoc_2022_09.adb ================================================ -- Solution to Advent of Code 2022, Day 9 ------------------------------------------ -- Rope Bridge -- -- https://adventofcode.com/2022/day/9 -- Copy of questions in: aoc_2022_09_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_09 is use HAT; mx : constant := 300; my : constant := 1000; type Column is array (1 .. my) of Boolean; empty : Column; map : array (1 .. mx) of Column; -- PPM output adapted from AoC_2022_08. -- procedure Dump_PPM (title : VString) is subtype Color_Range is Natural range 0 .. 255; type Pixel is record R, G, B : Color_Range; end record; d : File_Type; px : Pixel; min_x : constant := 1; max_x : constant := mx; -- 200; min_y : constant := 1; -- 401; max_y : constant := my; -- 990; begin Create (d, title & ".ppm"); Put (d, "P6" & Chr (10)); Put (d, max_x - min_x + 1); Put (d, ' '); Put (d, max_y - min_y + 1); Put (d, Chr (10)); Put (d, "255" & Chr (10)); for y in reverse min_y .. max_y loop for x in min_x .. max_x loop case map (x)(y) is when False => px.R := 16#ff#; px.G := 16#ff#; px.B := 16#cc#; when True => px.R := 16#66#; px.G := 16#00#; px.B := 16#66#; end case; Put (d, Chr (px.R)); Put (d, Chr (px.G)); Put (d, Chr (px.B)); end loop; end loop; Close (d); end Dump_PPM; type Movement is (L, R, U, D); move : Movement; type Pos is record x, y : Natural; end record; type Rope_Type is array (0 .. 9) of Pos; rope, old_rope : Rope_Type; len : Positive; type Method_for_following is (use_previous_position, -- ^ When needed for preserving the distance, a tail knot goes -- into the head knot's previous position. -- This method is correct but doesn't deliver the result -- expected by Advent of Code - the rules represent a rare -- case of ambiguity in AoC... reduce_distance); -- ^ We move the tail knot by at most one in each dimension -- towards the head knot. method : constant Method_for_following := reduce_distance; verbose : constant Boolean := False; T0 : constant Time := Clock; res : array (1 .. 2) of Integer; c : Character; total, steps : Integer; f : File_Type; function Dist (a, b : Pos) return Natural is begin return Max (abs (a.x - b.x), abs (a.y - b.y)); end Dist; procedure Follow_Geometrically (head : in Pos; tail : in out Pos) is begin -- The tail follows the head with a step of maximum 1 in each dimension. tail.x := tail.x + Sgn (head.x - tail.x); tail.y := tail.y + Sgn (head.y - tail.y); end Follow_Geometrically; begin for y in Column'Range loop empty (y) := False; end loop; Parts : for part in 1 .. 2 loop for i in rope'Range loop rope (i).x := mx / 2; rope (i).y := my / 2; end loop; for x in map'Range loop map (x) := empty; end loop; case part is when 1 => len := 1; when 2 => len := 9; end case; Open (f, "aoc_2022_09.txt"); Read_Data : while not End_Of_File (f) loop Get (f, c); Get (f, steps); move := Movement'Value (c & ""); for count in 1 .. steps loop old_rope := rope; -- Move the head of the rope: case move is when L => rope (0).x := rope (0).x - 1; when R => rope (0).x := rope (0).x + 1; when D => rope (0).y := rope (0).y - 1; when U => rope (0).y := rope (0).y + 1; end case; for i in 1 .. len loop if Dist (rope (i - 1), rope (i)) > 1 then case method is when use_previous_position => rope (i) := old_rope (i - 1); when reduce_distance => Follow_Geometrically (rope (i - 1), rope (i)); end case; end if; end loop; map (rope (len).x)(rope (len).y) := True; end loop; end loop Read_Data; Close (f); if verbose then Dump_PPM (To_Lower (+"length_" & Image (len) & '_' & Method_for_following'Image (method))); end if; total := 0; for x in 1 .. mx loop for y in 1 .. my loop if map (x)(y) then total := total + 1; end if; end loop; end loop; res (part) := total; end loop Parts; if Argument_Count >= 2 then -- Compiler test mode. if res (1) /= Integer'Value (To_String (Argument (1))) or res (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Method for following: " & To_Lower (+Method_for_following'Image (method))); Put_Line (+"Number of visited points tail for a rope of..."); Put_Line (+" (part 1) length 1: " & res (1)); Put_Line (+" (part 2) length 9: " & res (2)); -- Part 1: validated by AoC: 6314 -- Part 2: validated by AoC: 2504 end if; end AoC_2022_09; ================================================ FILE: exm/aoc/2022/aoc_2022_09.txt ================================================ L 1 D 2 R 1 L 1 R 2 L 1 U 2 L 2 D 1 L 2 U 2 R 2 D 2 L 1 D 2 U 2 L 2 R 2 L 1 U 2 D 2 U 2 D 2 L 1 R 2 L 2 D 2 R 1 D 1 R 2 U 1 R 2 L 2 R 1 U 2 R 1 D 1 U 1 L 2 R 1 D 2 U 1 R 1 U 2 L 1 R 2 U 1 R 2 L 2 R 1 D 2 R 1 D 1 U 2 R 1 D 1 U 1 D 2 L 1 U 1 D 1 R 2 D 2 R 1 D 2 L 2 D 2 U 1 L 1 D 1 L 1 R 2 U 2 L 2 D 2 L 2 D 1 U 2 D 2 L 2 R 1 D 1 L 1 U 1 L 1 U 2 L 1 U 1 D 1 R 1 L 1 R 2 D 1 L 2 D 2 R 1 D 2 R 1 D 1 R 2 L 2 U 1 D 2 L 2 U 2 D 2 R 1 D 1 U 2 R 2 U 2 D 3 L 1 U 2 R 2 D 1 U 1 L 1 U 3 L 3 U 2 L 3 U 3 L 3 D 3 R 1 U 3 R 3 U 3 D 2 R 2 U 2 R 3 L 3 U 1 R 1 D 3 L 1 U 1 R 3 U 3 D 1 L 3 R 1 U 3 D 2 U 2 D 2 R 1 U 2 L 2 U 3 L 1 U 3 D 3 U 3 L 2 R 3 D 1 L 1 R 3 L 2 D 3 U 3 R 2 L 1 R 2 D 3 U 3 R 2 U 3 L 1 R 2 U 3 D 2 U 3 L 3 R 3 D 3 U 1 D 1 U 2 R 2 U 3 D 3 U 2 D 2 L 2 D 2 L 2 R 1 U 2 D 2 L 2 R 1 D 3 L 3 D 2 L 3 D 3 L 2 D 2 L 2 D 2 U 2 L 3 D 3 L 2 U 2 D 2 R 3 D 2 U 3 L 1 R 1 D 2 U 3 R 1 U 2 D 2 R 2 U 3 R 2 U 1 L 1 D 2 R 4 D 1 U 4 D 2 U 3 R 1 D 2 R 3 L 2 D 3 L 3 R 1 D 1 U 2 R 1 L 2 R 2 D 1 L 1 D 1 L 4 D 3 R 1 U 3 R 2 U 1 R 1 D 2 L 2 D 2 U 3 L 4 D 4 R 4 L 2 U 1 R 2 L 2 U 4 D 1 R 4 L 3 R 4 U 1 D 2 L 2 R 2 D 1 L 2 U 1 D 3 R 2 U 2 L 3 D 4 U 3 R 4 L 4 R 1 U 1 D 2 L 3 D 1 U 4 R 2 D 4 L 2 D 3 L 2 D 2 L 1 U 3 L 4 U 3 D 4 L 3 D 1 R 2 D 2 U 4 L 4 U 3 L 4 D 2 R 3 U 1 L 2 R 2 D 2 U 4 L 2 U 4 D 1 U 2 R 4 L 2 U 4 L 4 U 2 D 2 U 4 L 2 U 3 D 2 L 3 U 1 L 2 R 3 D 2 R 5 L 5 D 3 R 4 D 2 R 4 U 4 R 5 D 5 R 5 L 4 U 2 D 2 R 2 U 4 R 2 L 4 R 3 U 2 R 5 D 3 L 4 R 2 L 3 U 4 R 2 D 4 R 2 L 4 D 4 R 3 D 5 U 1 L 2 R 5 L 5 U 5 D 1 U 1 L 3 D 1 U 5 D 2 R 3 U 4 R 4 U 3 L 5 U 5 D 5 R 1 D 3 L 5 R 5 U 2 D 2 U 4 D 3 R 5 U 5 L 3 U 3 L 2 U 4 L 2 R 4 D 3 L 4 U 3 D 1 L 1 D 4 U 4 D 1 R 2 L 5 D 1 U 4 R 2 D 3 R 1 D 1 L 4 D 2 L 4 R 3 U 5 L 1 D 1 L 5 U 5 R 5 U 4 D 5 U 3 D 5 R 2 U 2 R 4 D 1 U 4 R 3 D 2 U 3 R 3 L 1 R 2 D 4 L 5 D 6 L 2 D 3 R 3 U 3 L 3 R 3 U 5 R 4 D 3 R 5 L 4 D 6 U 3 R 2 L 4 D 3 L 3 R 3 U 5 R 1 D 6 L 5 D 3 U 2 R 3 D 3 R 3 U 1 L 5 R 6 D 2 U 4 R 5 U 1 D 2 U 5 R 3 L 4 D 3 L 6 U 6 R 2 U 6 L 3 D 1 R 2 U 2 R 3 U 6 L 4 D 3 R 2 U 2 L 3 R 6 U 3 R 6 L 2 U 3 R 3 D 2 R 6 D 2 L 4 U 6 D 2 U 6 L 1 D 1 L 5 D 3 R 6 L 5 R 6 D 2 R 4 L 1 U 4 L 5 U 5 D 5 R 6 L 5 U 5 R 2 D 6 U 3 R 2 D 3 U 3 L 4 D 5 R 3 U 5 D 3 R 3 L 6 R 3 D 1 U 2 L 4 D 4 U 2 L 4 U 6 D 5 L 6 U 5 D 1 U 6 D 5 U 2 R 7 U 6 R 2 D 2 R 7 D 4 L 7 U 5 L 2 U 4 D 2 R 2 L 2 D 3 U 3 D 6 L 7 R 5 D 5 L 7 U 1 D 5 L 6 U 1 R 1 D 7 U 5 D 4 L 2 U 1 D 2 U 6 D 5 U 1 R 1 L 3 D 3 U 3 L 5 D 5 U 3 R 6 L 6 R 1 U 2 D 3 L 2 U 6 D 3 R 3 U 2 D 1 L 4 U 2 L 7 U 4 R 2 D 6 L 4 D 6 L 1 D 3 L 6 D 4 R 6 U 3 D 1 L 4 R 6 U 5 R 5 U 5 R 3 L 6 U 1 D 2 U 3 D 1 L 7 D 6 U 4 D 5 L 6 U 7 L 2 U 4 L 6 R 6 U 3 D 4 R 6 U 1 D 5 R 5 U 6 R 4 U 2 D 2 U 2 R 3 L 6 U 6 R 2 L 2 R 6 L 1 D 6 R 2 D 2 L 8 U 6 R 7 L 7 D 3 L 3 R 8 U 2 L 7 D 4 R 5 D 4 R 1 U 5 D 2 R 6 L 7 U 2 L 4 R 1 D 2 U 4 D 3 R 2 U 1 L 5 U 5 L 5 R 7 D 6 R 2 D 7 R 1 L 6 R 8 D 7 R 3 U 6 L 7 R 7 U 8 L 4 D 4 U 6 L 5 R 2 L 2 R 7 D 8 L 7 D 2 R 1 U 1 R 6 D 5 U 8 R 5 L 1 R 7 U 1 L 7 D 5 L 6 R 5 L 3 U 7 L 8 R 6 U 6 R 4 U 1 R 8 U 1 D 1 U 8 D 7 R 1 L 8 R 1 L 6 D 8 L 6 U 7 R 8 D 4 U 6 R 7 L 8 U 4 L 4 D 6 R 5 L 1 U 2 D 1 L 3 D 7 R 6 L 3 R 5 L 1 D 5 L 3 R 5 U 5 R 7 U 6 D 6 U 2 R 8 D 3 L 7 D 5 U 9 R 5 L 9 D 5 R 2 U 6 L 5 U 9 L 7 D 3 L 6 U 3 R 5 D 7 R 3 L 5 R 2 L 6 R 9 L 8 D 4 L 6 U 8 L 8 D 4 R 2 U 1 D 6 U 6 R 3 L 8 U 2 L 8 D 9 R 9 L 1 D 3 R 6 D 6 L 9 D 3 R 9 L 2 D 8 U 2 R 8 L 3 D 9 L 6 D 9 U 3 D 9 R 5 L 2 D 7 L 6 U 2 L 8 D 9 L 5 R 7 L 3 D 7 U 4 L 8 R 9 L 5 R 7 D 7 R 6 D 6 L 6 R 8 L 6 D 4 R 5 D 2 L 5 U 2 D 8 R 9 L 3 U 1 L 6 D 1 R 9 L 4 U 1 R 4 L 1 D 3 R 5 D 9 L 4 D 3 U 9 D 7 L 5 R 3 L 7 R 8 L 1 U 6 L 8 D 8 R 6 L 1 U 1 D 7 R 10 U 3 D 4 U 5 D 3 R 7 U 8 D 3 U 8 D 9 L 10 D 5 L 7 U 3 D 3 U 5 R 5 U 7 L 2 D 6 U 6 R 6 U 9 R 9 L 5 R 1 L 4 D 3 U 4 D 8 U 3 R 7 D 1 U 5 L 6 R 4 U 2 L 8 U 10 D 8 U 8 R 6 L 1 U 9 R 9 D 10 U 8 L 9 D 5 U 9 D 9 U 6 D 10 L 9 R 4 D 3 R 10 D 6 R 8 D 1 U 4 L 1 D 6 R 1 L 1 D 7 R 1 L 4 R 5 U 9 R 5 U 1 R 9 D 3 U 4 D 6 L 3 U 10 D 3 U 10 R 10 D 7 L 5 R 4 D 4 L 1 R 7 L 4 R 5 D 2 L 9 D 9 L 5 D 8 R 1 D 3 L 8 D 4 L 8 U 8 L 7 D 7 U 4 D 7 R 10 U 2 R 7 D 4 L 6 D 4 U 3 L 4 U 8 D 7 L 9 R 4 D 9 U 10 L 7 U 11 R 5 U 2 D 4 U 10 L 3 R 5 U 8 D 10 L 7 D 7 R 2 D 5 U 6 L 1 U 11 R 6 D 9 U 1 L 4 U 2 D 1 L 3 D 6 L 8 U 9 D 9 L 5 D 3 R 2 L 11 D 9 U 9 R 10 U 7 D 11 R 4 L 11 U 6 R 2 U 6 D 1 U 8 L 11 R 5 L 11 U 10 R 2 L 3 D 8 U 7 R 11 L 9 U 7 D 8 R 2 L 2 R 5 L 10 R 4 D 3 R 5 L 7 D 2 U 7 R 2 U 10 L 1 D 1 U 2 R 2 D 1 R 10 L 6 U 8 R 3 D 8 U 10 D 5 R 3 U 1 L 2 D 5 R 11 U 2 R 11 L 9 U 1 R 5 L 6 U 5 D 1 U 11 D 1 R 7 L 9 U 5 D 11 L 9 U 1 L 4 D 1 R 3 D 10 U 9 L 3 R 11 L 9 R 12 U 8 D 9 L 12 D 1 U 10 R 11 U 9 R 8 U 11 R 8 U 6 D 7 R 7 U 10 L 10 U 4 L 10 R 2 D 6 L 10 D 10 R 10 U 1 L 7 D 8 L 12 R 9 U 9 L 10 R 11 D 12 R 6 U 10 R 3 D 12 U 12 R 1 D 3 R 5 U 8 D 2 U 4 D 12 L 3 D 11 U 9 L 2 R 7 L 5 U 2 R 5 L 5 U 1 L 4 R 12 L 11 R 8 D 4 U 5 R 5 U 9 R 7 L 6 R 7 L 1 U 6 D 6 L 3 U 1 L 4 U 6 R 5 L 9 U 12 D 11 R 11 U 11 D 7 U 3 L 12 U 7 L 2 D 3 U 10 D 2 U 6 L 9 R 2 D 12 R 11 U 12 L 1 D 9 R 4 D 4 U 5 D 12 R 9 U 6 L 8 D 5 U 6 D 10 R 3 L 1 U 4 R 2 L 8 U 9 L 6 D 1 L 6 U 5 R 6 D 4 L 7 U 2 R 12 U 12 R 13 U 6 R 7 D 12 R 3 U 3 D 10 U 12 R 11 D 3 U 11 L 6 R 5 D 7 L 10 D 5 L 7 U 8 L 3 U 5 R 1 L 1 R 1 D 10 L 2 R 1 U 9 L 10 U 13 R 3 D 9 R 6 D 1 R 7 U 8 D 7 U 13 R 3 U 11 L 13 R 8 L 13 D 6 L 8 U 6 D 10 R 3 D 9 R 11 U 1 L 11 U 5 R 6 U 6 D 10 R 5 L 1 R 6 U 11 L 8 R 3 D 7 U 4 R 5 D 8 U 7 L 6 U 6 L 9 U 10 R 5 L 7 R 5 L 13 U 7 D 1 L 7 U 2 R 9 L 8 U 5 L 13 R 11 D 4 R 6 U 13 D 13 L 9 R 8 D 12 R 6 D 1 L 12 R 8 U 1 L 7 R 13 D 13 L 13 U 7 D 7 L 4 U 13 R 7 U 14 D 11 R 7 U 3 L 9 U 8 L 3 R 14 D 2 U 4 R 1 L 13 U 2 D 5 U 2 R 7 U 14 D 10 L 1 D 7 L 2 U 14 L 14 R 12 U 2 D 5 L 10 U 3 R 11 D 12 R 14 U 7 R 10 D 9 L 13 D 13 R 12 D 14 R 3 D 4 U 8 L 11 U 9 L 5 U 1 R 12 D 6 U 1 R 1 L 5 U 5 L 1 D 5 U 4 D 13 U 7 R 5 D 11 U 9 R 3 D 11 L 9 D 8 R 8 U 8 L 6 R 3 D 5 L 10 U 1 L 4 R 13 L 5 D 8 L 5 U 11 L 8 R 12 L 6 R 12 U 5 D 12 R 12 D 4 U 9 L 4 R 11 L 2 R 11 U 12 D 14 L 2 U 5 L 7 D 8 U 12 D 4 R 4 L 13 D 9 U 11 R 1 D 2 U 8 D 10 U 8 L 6 U 9 R 8 L 12 U 9 R 3 U 14 R 3 U 9 L 11 U 2 L 10 D 6 U 2 L 4 D 12 L 8 R 15 D 11 L 9 R 6 U 9 R 11 U 7 R 13 L 9 D 9 U 2 R 9 U 11 R 15 U 4 L 4 U 6 D 3 R 10 L 5 U 8 D 6 R 6 D 6 U 10 L 7 R 9 D 6 U 12 R 15 L 8 D 9 U 15 D 6 L 14 D 2 R 15 U 14 D 15 U 13 R 1 U 11 R 8 U 13 D 6 L 2 R 1 U 7 R 6 D 13 U 13 R 15 D 15 R 1 U 14 D 9 U 5 L 6 R 9 L 13 D 6 U 2 R 7 D 3 L 10 R 7 L 2 U 4 D 1 L 9 U 9 R 7 U 3 D 7 U 1 R 12 L 11 R 7 L 14 R 3 L 15 R 15 U 5 R 12 D 9 R 5 U 12 L 12 U 6 L 4 R 2 U 2 L 5 D 3 R 12 D 8 U 16 D 16 L 11 D 7 U 15 R 13 U 5 D 6 L 12 D 2 L 16 D 16 L 8 U 9 R 12 D 16 U 2 R 1 L 12 U 9 D 15 U 16 L 14 D 4 U 5 L 2 R 5 D 9 L 4 R 13 L 2 U 2 R 4 L 15 R 13 D 11 R 13 L 13 U 14 R 8 U 5 D 10 L 2 U 15 D 3 L 8 U 2 L 14 U 3 R 16 U 4 D 1 R 5 L 3 R 1 L 16 D 16 L 12 U 14 R 12 U 8 R 1 L 1 R 9 U 9 R 12 L 1 U 9 L 14 U 11 L 8 U 10 L 7 U 1 L 11 R 2 D 12 U 3 R 2 L 14 D 1 L 12 R 16 D 16 R 8 L 15 R 3 L 10 D 14 R 9 U 2 D 4 U 7 D 2 R 11 D 6 U 2 R 4 L 2 R 6 L 11 R 9 L 1 R 8 D 3 R 4 U 14 D 7 L 11 R 14 L 8 D 9 L 6 D 15 R 4 D 9 U 7 R 6 L 13 D 11 R 10 L 17 R 17 D 17 R 7 U 15 D 14 R 6 U 14 R 5 U 17 R 7 L 17 U 14 L 14 R 13 U 4 R 14 U 10 L 16 U 8 R 2 U 4 D 16 U 4 L 14 R 7 D 13 U 10 L 10 R 3 L 6 D 7 R 13 L 6 U 7 R 16 L 10 U 6 L 6 U 11 D 6 U 5 L 4 U 17 R 6 L 3 D 5 R 4 U 1 L 14 R 10 L 4 U 9 R 7 D 2 R 6 U 12 D 15 R 15 L 13 U 5 L 12 D 3 U 15 L 9 U 3 D 12 R 15 U 7 L 7 R 11 L 14 R 2 D 6 R 6 D 9 R 2 L 12 R 2 U 12 R 8 L 2 U 12 R 2 D 17 L 8 D 1 U 16 D 1 R 5 L 9 U 4 L 1 U 9 L 11 R 9 D 7 R 16 D 12 R 3 U 7 L 4 R 7 L 8 D 9 U 10 D 7 U 10 D 5 U 14 D 5 U 11 R 15 U 8 D 12 U 8 L 18 U 16 D 16 U 3 R 5 D 2 U 10 L 17 R 5 U 15 R 9 D 5 U 9 L 12 D 17 R 14 L 4 R 14 L 17 D 9 L 10 D 17 R 1 U 2 R 7 U 13 R 1 U 17 R 4 L 3 D 14 U 11 L 15 R 6 U 4 D 8 L 17 D 3 R 13 U 10 R 4 U 5 R 3 U 16 D 6 L 5 R 18 L 11 D 16 U 7 R 7 U 1 R 14 U 14 R 4 D 3 R 12 D 13 U 5 D 8 R 17 L 9 D 4 L 13 U 8 R 13 D 5 U 17 L 11 U 13 D 9 L 8 R 14 L 15 D 10 R 11 D 8 L 10 U 3 L 3 R 12 L 9 R 17 U 10 L 17 U 13 L 12 U 1 D 2 R 1 L 16 R 11 D 15 L 8 R 10 L 12 U 3 L 17 U 7 R 6 U 16 R 1 L 3 R 5 L 11 R 4 D 10 L 1 R 4 U 12 L 18 R 8 L 7 R 16 U 19 R 10 U 11 D 12 R 6 U 17 L 16 D 19 L 9 U 1 R 12 U 12 R 15 D 4 L 15 R 4 L 9 R 15 L 10 R 7 L 16 U 16 L 19 U 5 L 4 U 12 L 6 U 5 R 17 U 11 R 6 U 15 L 9 D 4 R 2 L 7 R 16 L 13 U 19 R 4 U 13 L 18 D 19 U 15 R 13 L 11 U 18 D 2 U 9 D 18 L 13 D 13 L 11 U 3 D 11 U 16 R 14 D 6 L 12 D 9 R 2 D 14 L 12 R 15 D 2 R 11 U 7 D 9 L 16 R 12 L 12 D 14 U 2 D 12 R 8 U 9 D 10 U 12 L 17 U 19 L 4 U 15 R 12 L 11 D 12 L 8 U 3 R 7 L 2 D 4 U 17 ================================================ FILE: exm/aoc/2022/aoc_2022_09_questions.txt ================================================ --- Day 9: Rope Bridge --- This rope bridge creaks as you walk along it. You aren't sure how old it is, or whether it can even support your weight. It seems to support the Elves just fine, though. The bridge spans a gorge which was carved out by the massive river far below you. You step carefully; as you do, the ropes stretch and twist. You decide to distract yourself by modeling rope physics; maybe you can even figure out where not to step. Consider a rope with a knot at each end; these knots mark the head and the tail of the rope. If the head moves far enough away from the tail, the tail is pulled toward the head. Due to nebulous reasoning involving Planck lengths, you should be able to model the positions of the knots on a two-dimensional grid. Then, by following a hypothetical series of motions (your puzzle input) for the head, you can determine how the tail will move. Due to the aforementioned Planck lengths, the rope must be quite short; in fact, the head (H) and tail (T) must always be touching (diagonally adjacent and even overlapping both count as touching): .... .TH. .... .... .H.. ..T. .... ... .H. (H covers T) ... If the head is ever two steps directly up, down, left, or right from the tail, the tail must also move one step in that direction so it remains close enough: ..... ..... ..... .TH.. -> .T.H. -> ..TH. ..... ..... ..... ... ... ... .T. .T. ... .H. -> ... -> .T. ... .H. .H. ... ... ... Otherwise, if the head and tail aren't touching and aren't in the same row or column, the tail always moves one step diagonally to keep up: ..... ..... ..... ..... ..H.. ..H.. ..H.. -> ..... -> ..T.. .T... .T... ..... ..... ..... ..... ..... ..... ..... ..... ..... ..... ..H.. -> ...H. -> ..TH. .T... .T... ..... ..... ..... ..... You just need to work out where the tail goes as the head follows a series of motions. Assume the head and the tail both start at the same position, overlapping. For example: R 4 U 4 L 3 D 1 R 4 D 1 L 5 R 2 This series of motions moves the head right four steps, then up four steps, then left three steps, then down one step, and so on. After each step, you'll need to update the position of the tail if the step means the head is no longer adjacent to the tail. Visually, these motions occur as follows (s marks the starting position as a reference point): == Initial State == ...... ...... ...... ...... H..... (H covers T, s) == R 4 == ...... ...... ...... ...... TH.... (T covers s) ...... ...... ...... ...... sTH... ...... ...... ...... ...... s.TH.. ...... ...... ...... ...... s..TH. == U 4 == ...... ...... ...... ....H. s..T.. ...... ...... ....H. ....T. s..... ...... ....H. ....T. ...... s..... ....H. ....T. ...... ...... s..... == L 3 == ...H.. ....T. ...... ...... s..... ..HT.. ...... ...... ...... s..... .HT... ...... ...... ...... s..... == D 1 == ..T... .H.... ...... ...... s..... == R 4 == ..T... ..H... ...... ...... s..... ..T... ...H.. ...... ...... s..... ...... ...TH. ...... ...... s..... ...... ....TH ...... ...... s..... == D 1 == ...... ....T. .....H ...... s..... == L 5 == ...... ....T. ....H. ...... s..... ...... ....T. ...H.. ...... s..... ...... ...... ..HT.. ...... s..... ...... ...... .HT... ...... s..... ...... ...... HT.... ...... s..... == R 2 == ...... ...... .H.... (H covers T) ...... s..... ...... ...... .TH... ...... s..... After simulating the rope, you can count up all of the positions the tail visited at least once. In this diagram, s again marks the starting position (which the tail also visited) and # marks other positions the tail visited: ..##.. ...##. .####. ....#. s###.. So, there are 13 positions the tail visited at least once. Simulate your complete hypothetical series of motions. How many positions does the tail of the rope visit at least once? --- Part Two --- A rope snaps! Suddenly, the river is getting a lot closer than you remember. The bridge is still there, but some of the ropes that broke are now whipping toward you as you fall through the air! The ropes are moving too quickly to grab; you only have a few seconds to choose how to arch your body to avoid being hit. Fortunately, your simulation can be extended to support longer ropes. Rather than two knots, you now must simulate a rope consisting of ten knots. One knot is still the head of the rope and moves according to the series of motions. Each knot further down the rope follows the knot in front of it using the same rules as before. Using the same series of motions as the above example, but with the knots marked H, 1, 2, ..., 9, the motions now occur as follows: == Initial State == ...... ...... ...... ...... H..... (H covers 1, 2, 3, 4, 5, 6, 7, 8, 9, s) == R 4 == ...... ...... ...... ...... 1H.... (1 covers 2, 3, 4, 5, 6, 7, 8, 9, s) ...... ...... ...... ...... 21H... (2 covers 3, 4, 5, 6, 7, 8, 9, s) ...... ...... ...... ...... 321H.. (3 covers 4, 5, 6, 7, 8, 9, s) ...... ...... ...... ...... 4321H. (4 covers 5, 6, 7, 8, 9, s) == U 4 == ...... ...... ...... ....H. 4321.. (4 covers 5, 6, 7, 8, 9, s) ...... ...... ....H. .4321. 5..... (5 covers 6, 7, 8, 9, s) ...... ....H. ....1. .432.. 5..... (5 covers 6, 7, 8, 9, s) ....H. ....1. ..432. .5.... 6..... (6 covers 7, 8, 9, s) == L 3 == ...H.. ....1. ..432. .5.... 6..... (6 covers 7, 8, 9, s) ..H1.. ...2.. ..43.. .5.... 6..... (6 covers 7, 8, 9, s) .H1... ...2.. ..43.. .5.... 6..... (6 covers 7, 8, 9, s) == D 1 == ..1... .H.2.. ..43.. .5.... 6..... (6 covers 7, 8, 9, s) == R 4 == ..1... ..H2.. ..43.. .5.... 6..... (6 covers 7, 8, 9, s) ..1... ...H.. (H covers 2) ..43.. .5.... 6..... (6 covers 7, 8, 9, s) ...... ...1H. (1 covers 2) ..43.. .5.... 6..... (6 covers 7, 8, 9, s) ...... ...21H ..43.. .5.... 6..... (6 covers 7, 8, 9, s) == D 1 == ...... ...21. ..43.H .5.... 6..... (6 covers 7, 8, 9, s) == L 5 == ...... ...21. ..43H. .5.... 6..... (6 covers 7, 8, 9, s) ...... ...21. ..4H.. (H covers 3) .5.... 6..... (6 covers 7, 8, 9, s) ...... ...2.. ..H1.. (H covers 4; 1 covers 3) .5.... 6..... (6 covers 7, 8, 9, s) ...... ...2.. .H13.. (1 covers 4) .5.... 6..... (6 covers 7, 8, 9, s) ...... ...... H123.. (2 covers 4) .5.... 6..... (6 covers 7, 8, 9, s) == R 2 == ...... ...... .H23.. (H covers 1; 2 covers 4) .5.... 6..... (6 covers 7, 8, 9, s) ...... ...... .1H3.. (H covers 2, 4) .5.... 6..... (6 covers 7, 8, 9, s) Now, you need to keep track of the positions the new tail, 9, visits. In this example, the tail never moves, and so it only visits 1 position. However, be careful: more types of motion are possible than before, so you might want to visually compare your simulated rope to the one above. Here's a larger example: R 5 U 8 L 8 D 3 R 17 D 10 L 25 U 20 These motions occur as follows (individual steps are not shown): == Initial State == .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... ...........H.............. (H covers 1, 2, 3, 4, 5, 6, 7, 8, 9, s) .......................... .......................... .......................... .......................... .......................... == R 5 == .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... ...........54321H......... (5 covers 6, 7, 8, 9, s) .......................... .......................... .......................... .......................... .......................... == U 8 == .......................... .......................... .......................... .......................... .......................... .......................... .......................... ................H......... ................1......... ................2......... ................3......... ...............54......... ..............6........... .............7............ ............8............. ...........9.............. (9 covers s) .......................... .......................... .......................... .......................... .......................... == L 8 == .......................... .......................... .......................... .......................... .......................... .......................... .......................... ........H1234............. ............5............. ............6............. ............7............. ............8............. ............9............. .......................... .......................... ...........s.............. .......................... .......................... .......................... .......................... .......................... == D 3 == .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .........2345............. ........1...6............. ........H...7............. ............8............. ............9............. .......................... .......................... ...........s.............. .......................... .......................... .......................... .......................... .......................... == R 17 == .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... ................987654321H .......................... .......................... .......................... .......................... ...........s.............. .......................... .......................... .......................... .......................... .......................... == D 10 == .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... ...........s.........98765 .........................4 .........................3 .........................2 .........................1 .........................H == L 25 == .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... ...........s.............. .......................... .......................... .......................... .......................... H123456789................ == U 20 == H......................... 1......................... 2......................... 3......................... 4......................... 5......................... 6......................... 7......................... 8......................... 9......................... .......................... .......................... .......................... .......................... .......................... ...........s.............. .......................... .......................... .......................... .......................... .......................... Now, the tail (9) visits 36 positions (including s) at least once: .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... #......................... #.............###......... #............#...#........ .#..........#.....#....... ..#..........#.....#...... ...#........#.......#..... ....#......s.........#.... .....#..............#..... ......#............#...... .......#..........#....... ........#........#........ .........########......... Simulate your complete series of motions on a larger rope with ten knots. How many positions does the tail of the rope visit at least once? ================================================ FILE: exm/aoc/2022/aoc_2022_10.adb ================================================ -- Solution to Advent of Code 2022, Day 10 ------------------------------------------- -- Cathode-Ray Tube -- -- https://adventofcode.com/2022/day/10 -- Copy of questions in: aoc_2022_10_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_10 is use HAT; T0 : constant Time := Clock; asm : String (1 .. 4); arg : Integer; f : File_Type; add : array (1 .. 241) of Integer; screen : array (0 .. 5, 0 .. 39) of Character; sum, cycle, x, scr_i, scr_j : Integer; begin for i in add'Range loop add (i) := 0; end loop; cycle := 1; Open (f, "aoc_2022_10.txt"); while not End_Of_File (f) loop Get (f, asm); if asm = "noop" then cycle := cycle + 1; else Get (f, arg); cycle := cycle + 2; add (cycle) := arg; end if; end loop; Close (f); for i in screen'Range (1) loop for j in screen'Range (2) loop -- We fill the screen with spaces. -- In the end it should be full with '.' or '#'. screen (i, j) := ' '; end loop; end loop; -- Here we start the virtual machine. x := 1; sum := 0; VM_Run : for cy in 1 .. cycle loop x := x + add (cy); if (cy - 20) mod 40 = 0 then sum := sum + x * cy; end if; -- scr_i := (cy - 1) / 40; scr_j := (cy - 1) mod 40; if scr_i in screen'Range (1) then if abs (scr_j - x) < 2 then screen (scr_i, scr_j) := '#'; else screen (scr_i, scr_j) := '.'; end if; end if; end loop VM_Run; if Argument_Count >= 1 then -- Compiler test mode. if sum /= Integer'Value (To_String (Argument (1))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: sum of signal strengths: " & sum); Put_Line (+"Part 2:"); for i in screen'Range (1) loop for j in screen'Range (2) loop Put (screen (i, j)); end loop; New_Line; end loop; -- Part 1: validated by AoC: 12880 -- Part 2: validated by AoC: FCJAPJRE end if; end AoC_2022_10; ================================================ FILE: exm/aoc/2022/aoc_2022_10.txt ================================================ addx 2 addx 15 addx -11 addx 6 noop noop noop addx -1 addx 5 addx -1 addx 5 noop noop noop noop noop addx 7 addx -1 addx 3 addx 1 addx 5 addx 1 noop addx -38 noop addx 1 addx 6 addx 3 noop addx -8 noop addx 13 addx 2 addx 3 addx -2 addx 2 noop addx 3 addx 9 addx -2 addx 2 addx -10 addx 11 addx 2 addx -14 addx -21 addx 2 noop addx 5 addx 29 addx -2 noop addx -19 noop addx 2 addx 11 addx -10 addx 2 addx 5 addx -9 noop addx 14 addx 2 addx 3 addx -2 addx 3 addx 1 noop addx -37 noop addx 13 addx -8 noop noop noop noop addx 13 addx -5 addx 3 addx 3 addx 3 noop noop noop noop noop noop noop addx 6 addx 3 addx 1 addx 5 addx -15 addx 5 addx -27 addx 30 addx -23 addx 33 addx -32 addx 2 addx 5 addx 2 addx -16 addx 17 addx 2 addx -10 addx 17 addx 10 addx -9 addx 2 addx 2 addx 5 addx -29 addx -8 noop noop noop addx 19 addx -11 addx -1 addx 6 noop noop addx -1 addx 3 noop addx 3 addx 2 addx -3 addx 11 addx -1 addx 5 addx -2 addx 5 addx 2 noop noop addx 1 noop noop ================================================ FILE: exm/aoc/2022/aoc_2022_10_questions.txt ================================================ --- Day 10: Cathode-Ray Tube --- You avoid the ropes, plunge into the river, and swim to shore. The Elves yell something about meeting back up with them upriver, but the river is too loud to tell exactly what they're saying. They finish crossing the bridge and disappear from view. Situations like this must be why the Elves prioritized getting the communication system on your handheld device working. You pull it out of your pack, but the amount of water slowly draining from a big crack in its screen tells you it probably won't be of much immediate use. Unless, that is, you can design a replacement for the device's video system! It seems to be some kind of cathode-ray tube screen and simple CPU that are both driven by a precise clock circuit. The clock circuit ticks at a constant rate; each tick is called a cycle. Start by figuring out the signal being sent by the CPU. The CPU has a single register, X, which starts with the value 1. It supports only two instructions: addx V takes two cycles to complete. After two cycles, the X register is increased by the value V. (V can be negative.) noop takes one cycle to complete. It has no other effect. The CPU uses these instructions in a program (your puzzle input) to, somehow, tell the screen what to draw. Consider the following small program: noop addx 3 addx -5 Execution of this program proceeds as follows: At the start of the first cycle, the noop instruction begins execution. During the first cycle, X is 1. After the first cycle, the noop instruction finishes execution, doing nothing. At the start of the second cycle, the addx 3 instruction begins execution. During the second cycle, X is still 1. During the third cycle, X is still 1. After the third cycle, the addx 3 instruction finishes execution, setting X to 4. At the start of the fourth cycle, the addx -5 instruction begins execution. During the fourth cycle, X is still 4. During the fifth cycle, X is still 4. After the fifth cycle, the addx -5 instruction finishes execution, setting X to -1. Maybe you can learn something by looking at the value of the X register throughout execution. For now, consider the signal strength (the cycle number multiplied by the value of the X register) during the 20th cycle and every 40 cycles after that (that is, during the 20th, 60th, 100th, 140th, 180th, and 220th cycles). For example, consider this larger program: addx 15 addx -11 addx 6 addx -3 addx 5 addx -1 addx -8 addx 13 addx 4 noop addx -1 addx 5 addx -1 addx 5 addx -1 addx 5 addx -1 addx 5 addx -1 addx -35 addx 1 addx 24 addx -19 addx 1 addx 16 addx -11 noop noop addx 21 addx -15 noop noop addx -3 addx 9 addx 1 addx -3 addx 8 addx 1 addx 5 noop noop noop noop noop addx -36 noop addx 1 addx 7 noop noop noop addx 2 addx 6 noop noop noop noop noop addx 1 noop noop addx 7 addx 1 noop addx -13 addx 13 addx 7 noop addx 1 addx -33 noop noop noop addx 2 noop noop noop addx 8 noop addx -1 addx 2 addx 1 noop addx 17 addx -9 addx 1 addx 1 addx -3 addx 11 noop noop addx 1 noop addx 1 noop noop addx -13 addx -19 addx 1 addx 3 addx 26 addx -30 addx 12 addx -1 addx 3 addx 1 noop noop noop addx -9 addx 18 addx 1 addx 2 noop noop addx 9 noop noop noop addx -1 addx 2 addx -37 addx 1 addx 3 noop addx 15 addx -21 addx 22 addx -6 addx 1 noop addx 2 addx 1 noop addx -10 noop noop addx 20 addx 1 addx 2 addx 2 addx -6 addx -11 noop noop noop The interesting signal strengths can be determined as follows: During the 20th cycle, register X has the value 21, so the signal strength is 20 * 21 = 420. (The 20th cycle occurs in the middle of the second addx -1, so the value of register X is the starting value, 1, plus all of the other addx values up to that point: 1 + 15 - 11 + 6 - 3 + 5 - 1 - 8 + 13 + 4 = 21.) During the 60th cycle, register X has the value 19, so the signal strength is 60 * 19 = 1140. During the 100th cycle, register X has the value 18, so the signal strength is 100 * 18 = 1800. During the 140th cycle, register X has the value 21, so the signal strength is 140 * 21 = 2940. During the 180th cycle, register X has the value 16, so the signal strength is 180 * 16 = 2880. During the 220th cycle, register X has the value 18, so the signal strength is 220 * 18 = 3960. The sum of these signal strengths is 13140. Find the signal strength during the 20th, 60th, 100th, 140th, 180th, and 220th cycles. What is the sum of these six signal strengths? --- Part Two --- It seems like the X register controls the horizontal position of a sprite. Specifically, the sprite is 3 pixels wide, and the X register sets the horizontal position of the middle of that sprite. (In this system, there is no such thing as "vertical position": if the sprite's horizontal position puts its pixels where the CRT is currently drawing, then those pixels will be drawn.) You count the pixels on the CRT: 40 wide and 6 high. This CRT screen draws the top row of pixels left-to-right, then the row below that, and so on. The left-most pixel in each row is in position 0, and the right-most pixel in each row is in position 39. Like the CPU, the CRT is tied closely to the clock circuit: the CRT draws a single pixel during each cycle. Representing each pixel of the screen as a #, here are the cycles during which the first and last pixel in each row are drawn: Cycle 1 -> ######################################## <- Cycle 40 Cycle 41 -> ######################################## <- Cycle 80 Cycle 81 -> ######################################## <- Cycle 120 Cycle 121 -> ######################################## <- Cycle 160 Cycle 161 -> ######################################## <- Cycle 200 Cycle 201 -> ######################################## <- Cycle 240 So, by carefully timing the CPU instructions and the CRT drawing operations, you should be able to determine whether the sprite is visible the instant each pixel is drawn. If the sprite is positioned such that one of its three pixels is the pixel currently being drawn, the screen produces a lit pixel (#); otherwise, the screen leaves the pixel dark (.). The first few pixels from the larger example above are drawn as follows: Sprite position: ###..................................... Start cycle 1: begin executing addx 15 During cycle 1: CRT draws pixel in position 0 Current CRT row: # During cycle 2: CRT draws pixel in position 1 Current CRT row: ## End of cycle 2: finish executing addx 15 (Register X is now 16) Sprite position: ...............###...................... Start cycle 3: begin executing addx -11 During cycle 3: CRT draws pixel in position 2 Current CRT row: ##. During cycle 4: CRT draws pixel in position 3 Current CRT row: ##.. End of cycle 4: finish executing addx -11 (Register X is now 5) Sprite position: ....###................................. Start cycle 5: begin executing addx 6 During cycle 5: CRT draws pixel in position 4 Current CRT row: ##..# During cycle 6: CRT draws pixel in position 5 Current CRT row: ##..## End of cycle 6: finish executing addx 6 (Register X is now 11) Sprite position: ..........###........................... Start cycle 7: begin executing addx -3 During cycle 7: CRT draws pixel in position 6 Current CRT row: ##..##. During cycle 8: CRT draws pixel in position 7 Current CRT row: ##..##.. End of cycle 8: finish executing addx -3 (Register X is now 8) Sprite position: .......###.............................. Start cycle 9: begin executing addx 5 During cycle 9: CRT draws pixel in position 8 Current CRT row: ##..##..# During cycle 10: CRT draws pixel in position 9 Current CRT row: ##..##..## End of cycle 10: finish executing addx 5 (Register X is now 13) Sprite position: ............###......................... Start cycle 11: begin executing addx -1 During cycle 11: CRT draws pixel in position 10 Current CRT row: ##..##..##. During cycle 12: CRT draws pixel in position 11 Current CRT row: ##..##..##.. End of cycle 12: finish executing addx -1 (Register X is now 12) Sprite position: ...........###.......................... Start cycle 13: begin executing addx -8 During cycle 13: CRT draws pixel in position 12 Current CRT row: ##..##..##..# During cycle 14: CRT draws pixel in position 13 Current CRT row: ##..##..##..## End of cycle 14: finish executing addx -8 (Register X is now 4) Sprite position: ...###.................................. Start cycle 15: begin executing addx 13 During cycle 15: CRT draws pixel in position 14 Current CRT row: ##..##..##..##. During cycle 16: CRT draws pixel in position 15 Current CRT row: ##..##..##..##.. End of cycle 16: finish executing addx 13 (Register X is now 17) Sprite position: ................###..................... Start cycle 17: begin executing addx 4 During cycle 17: CRT draws pixel in position 16 Current CRT row: ##..##..##..##..# During cycle 18: CRT draws pixel in position 17 Current CRT row: ##..##..##..##..## End of cycle 18: finish executing addx 4 (Register X is now 21) Sprite position: ....................###................. Start cycle 19: begin executing noop During cycle 19: CRT draws pixel in position 18 Current CRT row: ##..##..##..##..##. End of cycle 19: finish executing noop Start cycle 20: begin executing addx -1 During cycle 20: CRT draws pixel in position 19 Current CRT row: ##..##..##..##..##.. During cycle 21: CRT draws pixel in position 20 Current CRT row: ##..##..##..##..##..# End of cycle 21: finish executing addx -1 (Register X is now 20) Sprite position: ...................###.................. Allowing the program to run to completion causes the CRT to produce the following image: ##..##..##..##..##..##..##..##..##..##.. ###...###...###...###...###...###...###. ####....####....####....####....####.... #####.....#####.....#####.....#####..... ######......######......######......#### #######.......#######.......#######..... Render the image given by your program. What eight capital letters appear on your CRT? ================================================ FILE: exm/aoc/2022/aoc_2022_11.adb ================================================ -- Solution to Advent of Code 2022, Day 11 ------------------------------------------- -- Monkey in the Middle -- -- https://adventofcode.com/2022/day/1 -- Copy of questions in: aoc_2022_11_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; -- Interfaces is needed for compiling on both -- HAC and another compiler, like GNAT. -- 64-bit integer in Interfaces: Integer_64. with Interfaces; procedure AoC_2022_11 is use HAT, Interfaces; subtype Monkey_Range is Integer range 0 .. 9; type Operation_Type is (plus, times, square); type Item_Worry_List is array (1 .. 100) of Integer_64; type Monkey_Data is record top : Natural; s : Item_Worry_List; operation : Operation_Type; operand : Positive; divisor : Positive; if_true : Monkey_Range; if_false : Monkey_Range; inspected : Natural; end record; mm : array (Monkey_Range) of Monkey_Data; product_of_divisors : Integer_64; last_id : Integer; verbose : constant Boolean := False; procedure Data_Acquisition is c, space : Character; idx, idx_comma : Integer; starting_items_string : String (1 .. 18); -- " Starting items: " operation_string : String (1 .. 23); -- " Operation: new = old " test_string : String (1 .. 21); -- " Test: divisible by" monkey_true_string : String (1 .. 28); -- " If true: throw to monkey" monkey_false_string : String (1 .. 29); -- " If false: throw to monkey" f : File_Type; s : VString; begin product_of_divisors := 1; last_id := -1; Open (f, "aoc_2022_11.txt"); Read_Data : loop last_id := last_id + 1; Skip_Line (f); -- "Monkey [last_id]:" mm (last_id).top := 0; mm (last_id).inspected := 0; Get (f, starting_items_string); Get_Line (f, s); Parse_Worries : loop idx_comma := Index (s, ','); if idx_comma > 0 then idx := idx_comma - 1; else idx := Length (s); end if; mm (last_id).top := mm (last_id).top + 1; mm (last_id).s (mm (last_id).top) := Integer_64 (Integer_Value (Slice (s, 1, idx))); exit Parse_Worries when idx_comma = 0; Delete (s, 1, idx_comma); end loop Parse_Worries; Get (f, operation_string); Get (f, c); case c is when '*' => Get (f, space); Get (f, c); if c = 'o' then -- "old * old" mm (last_id).operation := square; Skip_Line (f); else mm (last_id).operation := times; Get_Line (f, s); mm (last_id).operand := Integer_Value (c & s); end if; when others => mm (last_id).operation := plus; Get (f, mm (last_id).operand); end case; Get (f, test_string); Get (f, mm (last_id).divisor); product_of_divisors := product_of_divisors * Integer_64 (mm (last_id).divisor); Get (f, monkey_true_string); Get (f, mm (last_id).if_true); Get (f, monkey_false_string); Get (f, mm (last_id).if_false); exit Read_Data when End_Of_File (f); Skip_Line (f, 2); end loop Read_Data; Close (f); end Data_Acquisition; rounds : array (1 .. 2) of Positive; function Simulation (part : Positive) return Integer_64 is i : Integer_64; dest : Monkey_Range; top, top_1 : Positive; begin for round in 1 .. rounds (part) loop for m in 0 .. last_id loop if verbose then Put_Line (+"Monkey " & m); end if; for o in 1 .. mm (m).top loop if verbose then Put (+" Worry:" & Integer_64'Image (mm (m).s (o))); end if; i := mm (m).s (o); case mm (m).operation is when plus => i := i + Integer_64 (mm (m).operand); if verbose then Put (+" Plus " & mm (m).operand); end if; when times => i := i * Integer_64 (mm (m).operand); if verbose then Put (+" Times " & mm (m).operand); end if; when square => i := i * i; if verbose then Put (+" Square"); end if; end case; if part = 1 then i := i / 3; else i := i mod product_of_divisors; -- ^ i mod divisor = (i mod product_of_divisors) mod divisor. end if; if i mod Integer_64 (mm (m).divisor) = 0 then dest := mm (m).if_true; else dest := mm (m).if_false; end if; if verbose then Put_Line (+" throw" & Integer_64'Image (i) & " to " & dest); end if; mm (dest).top := mm (dest).top + 1; mm (dest).s (mm (dest).top) := i; end loop; mm (m).inspected := mm (m).inspected + mm (m).top; mm (m).top := 0; end loop; end loop; if verbose then Put_Line ("Inspected:"); for m in 0 .. last_id loop Put_Line (mm (m).inspected); end loop; end if; top := 1; top_1 := 1; for m in 0 .. last_id loop if mm (m).inspected >= top then top_1 := top; top := mm (m).inspected; elsif mm (m).inspected > top_1 then top_1 := mm (m).inspected; end if; end loop; return Integer_64 (top) * Integer_64 (top_1); end Simulation; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; r : array (1 .. 2) of Integer_64; begin rounds (1) := 20; rounds (2) := 10_000; Parts : for part in 1 .. 2 loop Data_Acquisition; r (part) := Simulation (part); exit Parts when compiler_test_mode; -- Skip part 2. end loop Parts; if compiler_test_mode then if r (1) /= Integer_64'Value (To_String (Argument (1))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Level of monkey business:"); Put_Line (+" part 1: " & Integer_64'Image (r (1))); Put_Line (+" part 2: " & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 102399 -- Part 2: validated by AoC: 23641658401 end if; end AoC_2022_11; ================================================ FILE: exm/aoc/2022/aoc_2022_11.txt ================================================ Monkey 0: Starting items: 50, 70, 54, 83, 52, 78 Operation: new = old * 3 Test: divisible by 11 If true: throw to monkey 2 If false: throw to monkey 7 Monkey 1: Starting items: 71, 52, 58, 60, 71 Operation: new = old * old Test: divisible by 7 If true: throw to monkey 0 If false: throw to monkey 2 Monkey 2: Starting items: 66, 56, 56, 94, 60, 86, 73 Operation: new = old + 1 Test: divisible by 3 If true: throw to monkey 7 If false: throw to monkey 5 Monkey 3: Starting items: 83, 99 Operation: new = old + 8 Test: divisible by 5 If true: throw to monkey 6 If false: throw to monkey 4 Monkey 4: Starting items: 98, 98, 79 Operation: new = old + 3 Test: divisible by 17 If true: throw to monkey 1 If false: throw to monkey 0 Monkey 5: Starting items: 76 Operation: new = old + 4 Test: divisible by 13 If true: throw to monkey 6 If false: throw to monkey 3 Monkey 6: Starting items: 52, 51, 84, 54 Operation: new = old * 17 Test: divisible by 19 If true: throw to monkey 4 If false: throw to monkey 1 Monkey 7: Starting items: 82, 86, 91, 79, 94, 92, 59, 94 Operation: new = old + 7 Test: divisible by 2 If true: throw to monkey 5 If false: throw to monkey 3 ================================================ FILE: exm/aoc/2022/aoc_2022_11_questions.txt ================================================ --- Day 11: Monkey in the Middle --- As you finally start making your way upriver, you realize your pack is much lighter than you remember. Just then, one of the items from your pack goes flying overhead. Monkeys are playing Keep Away with your missing things! To get your stuff back, you need to be able to predict where the monkeys will throw your items. After some careful observation, you realize the monkeys operate based on how worried you are about each item. You take some notes (your puzzle input) on the items each monkey currently has, how worried you are about those items, and how the monkey makes decisions based on your worry level. For example: Monkey 0: Starting items: 79, 98 Operation: new = old * 19 Test: divisible by 23 If true: throw to monkey 2 If false: throw to monkey 3 Monkey 1: Starting items: 54, 65, 75, 74 Operation: new = old + 6 Test: divisible by 19 If true: throw to monkey 2 If false: throw to monkey 0 Monkey 2: Starting items: 79, 60, 97 Operation: new = old * old Test: divisible by 13 If true: throw to monkey 1 If false: throw to monkey 3 Monkey 3: Starting items: 74 Operation: new = old + 3 Test: divisible by 17 If true: throw to monkey 0 If false: throw to monkey 1 Each monkey has several attributes: Starting items lists your worry level for each item the monkey is currently holding in the order they will be inspected. Operation shows how your worry level changes as that monkey inspects an item. (An operation like new = old * 5 means that your worry level after the monkey inspected the item is five times whatever your worry level was before inspection.) Test shows how the monkey uses your worry level to decide where to throw an item next. If true shows what happens with an item if the Test was true. If false shows what happens with an item if the Test was false. After each monkey inspects an item but before it tests your worry level, your relief that the monkey's inspection didn't damage the item causes your worry level to be divided by three and rounded down to the nearest integer. The monkeys take turns inspecting and throwing items. On a single monkey's turn, it inspects and throws all of the items it is holding one at a time and in the order listed. Monkey 0 goes first, then monkey 1, and so on until each monkey has had one turn. The process of each monkey taking a single turn is called a round. When a monkey throws an item to another monkey, the item goes on the end of the recipient monkey's list. A monkey that starts a round with no items could end up inspecting and throwing many items by the time its turn comes around. If a monkey is holding no items at the start of its turn, its turn ends. In the above example, the first round proceeds as follows: Monkey 0: Monkey inspects an item with a worry level of 79. Worry level is multiplied by 19 to 1501. Monkey gets bored with item. Worry level is divided by 3 to 500. Current worry level is not divisible by 23. Item with worry level 500 is thrown to monkey 3. Monkey inspects an item with a worry level of 98. Worry level is multiplied by 19 to 1862. Monkey gets bored with item. Worry level is divided by 3 to 620. Current worry level is not divisible by 23. Item with worry level 620 is thrown to monkey 3. Monkey 1: Monkey inspects an item with a worry level of 54. Worry level increases by 6 to 60. Monkey gets bored with item. Worry level is divided by 3 to 20. Current worry level is not divisible by 19. Item with worry level 20 is thrown to monkey 0. Monkey inspects an item with a worry level of 65. Worry level increases by 6 to 71. Monkey gets bored with item. Worry level is divided by 3 to 23. Current worry level is not divisible by 19. Item with worry level 23 is thrown to monkey 0. Monkey inspects an item with a worry level of 75. Worry level increases by 6 to 81. Monkey gets bored with item. Worry level is divided by 3 to 27. Current worry level is not divisible by 19. Item with worry level 27 is thrown to monkey 0. Monkey inspects an item with a worry level of 74. Worry level increases by 6 to 80. Monkey gets bored with item. Worry level is divided by 3 to 26. Current worry level is not divisible by 19. Item with worry level 26 is thrown to monkey 0. Monkey 2: Monkey inspects an item with a worry level of 79. Worry level is multiplied by itself to 6241. Monkey gets bored with item. Worry level is divided by 3 to 2080. Current worry level is divisible by 13. Item with worry level 2080 is thrown to monkey 1. Monkey inspects an item with a worry level of 60. Worry level is multiplied by itself to 3600. Monkey gets bored with item. Worry level is divided by 3 to 1200. Current worry level is not divisible by 13. Item with worry level 1200 is thrown to monkey 3. Monkey inspects an item with a worry level of 97. Worry level is multiplied by itself to 9409. Monkey gets bored with item. Worry level is divided by 3 to 3136. Current worry level is not divisible by 13. Item with worry level 3136 is thrown to monkey 3. Monkey 3: Monkey inspects an item with a worry level of 74. Worry level increases by 3 to 77. Monkey gets bored with item. Worry level is divided by 3 to 25. Current worry level is not divisible by 17. Item with worry level 25 is thrown to monkey 1. Monkey inspects an item with a worry level of 500. Worry level increases by 3 to 503. Monkey gets bored with item. Worry level is divided by 3 to 167. Current worry level is not divisible by 17. Item with worry level 167 is thrown to monkey 1. Monkey inspects an item with a worry level of 620. Worry level increases by 3 to 623. Monkey gets bored with item. Worry level is divided by 3 to 207. Current worry level is not divisible by 17. Item with worry level 207 is thrown to monkey 1. Monkey inspects an item with a worry level of 1200. Worry level increases by 3 to 1203. Monkey gets bored with item. Worry level is divided by 3 to 401. Current worry level is not divisible by 17. Item with worry level 401 is thrown to monkey 1. Monkey inspects an item with a worry level of 3136. Worry level increases by 3 to 3139. Monkey gets bored with item. Worry level is divided by 3 to 1046. Current worry level is not divisible by 17. Item with worry level 1046 is thrown to monkey 1. After round 1, the monkeys are holding items with these worry levels: Monkey 0: 20, 23, 27, 26 Monkey 1: 2080, 25, 167, 207, 401, 1046 Monkey 2: Monkey 3: Monkeys 2 and 3 aren't holding any items at the end of the round; they both inspected items during the round and threw them all before the round ended. This process continues for a few more rounds: After round 2, the monkeys are holding items with these worry levels: Monkey 0: 695, 10, 71, 135, 350 Monkey 1: 43, 49, 58, 55, 362 Monkey 2: Monkey 3: After round 3, the monkeys are holding items with these worry levels: Monkey 0: 16, 18, 21, 20, 122 Monkey 1: 1468, 22, 150, 286, 739 Monkey 2: Monkey 3: After round 4, the monkeys are holding items with these worry levels: Monkey 0: 491, 9, 52, 97, 248, 34 Monkey 1: 39, 45, 43, 258 Monkey 2: Monkey 3: After round 5, the monkeys are holding items with these worry levels: Monkey 0: 15, 17, 16, 88, 1037 Monkey 1: 20, 110, 205, 524, 72 Monkey 2: Monkey 3: After round 6, the monkeys are holding items with these worry levels: Monkey 0: 8, 70, 176, 26, 34 Monkey 1: 481, 32, 36, 186, 2190 Monkey 2: Monkey 3: After round 7, the monkeys are holding items with these worry levels: Monkey 0: 162, 12, 14, 64, 732, 17 Monkey 1: 148, 372, 55, 72 Monkey 2: Monkey 3: After round 8, the monkeys are holding items with these worry levels: Monkey 0: 51, 126, 20, 26, 136 Monkey 1: 343, 26, 30, 1546, 36 Monkey 2: Monkey 3: After round 9, the monkeys are holding items with these worry levels: Monkey 0: 116, 10, 12, 517, 14 Monkey 1: 108, 267, 43, 55, 288 Monkey 2: Monkey 3: After round 10, the monkeys are holding items with these worry levels: Monkey 0: 91, 16, 20, 98 Monkey 1: 481, 245, 22, 26, 1092, 30 Monkey 2: Monkey 3: ... After round 15, the monkeys are holding items with these worry levels: Monkey 0: 83, 44, 8, 184, 9, 20, 26, 102 Monkey 1: 110, 36 Monkey 2: Monkey 3: ... After round 20, the monkeys are holding items with these worry levels: Monkey 0: 10, 12, 14, 26, 34 Monkey 1: 245, 93, 53, 199, 115 Monkey 2: Monkey 3: Chasing all of the monkeys at once is impossible; you're going to have to focus on the two most active monkeys if you want any hope of getting your stuff back. Count the total number of times each monkey inspects items over 20 rounds: Monkey 0 inspected items 101 times. Monkey 1 inspected items 95 times. Monkey 2 inspected items 7 times. Monkey 3 inspected items 105 times. In this example, the two most active monkeys inspected items 101 and 105 times. The level of monkey business in this situation can be found by multiplying these together: 10605. Figure out which monkeys to chase by counting how many items they inspect over 20 rounds. What is the level of monkey business after 20 rounds of stuff-slinging simian shenanigans? --- Part Two --- You're worried you might not ever get your items back. So worried, in fact, that your relief that a monkey's inspection didn't damage an item no longer causes your worry level to be divided by three. Unfortunately, that relief was all that was keeping your worry levels from reaching ridiculous levels. You'll need to find another way to keep your worry levels manageable. At this rate, you might be putting up with these monkeys for a very long time - possibly 10000 rounds! With these new rules, you can still figure out the monkey business after 10000 rounds. Using the same example above: == After round 1 == Monkey 0 inspected items 2 times. Monkey 1 inspected items 4 times. Monkey 2 inspected items 3 times. Monkey 3 inspected items 6 times. == After round 20 == Monkey 0 inspected items 99 times. Monkey 1 inspected items 97 times. Monkey 2 inspected items 8 times. Monkey 3 inspected items 103 times. == After round 1000 == Monkey 0 inspected items 5204 times. Monkey 1 inspected items 4792 times. Monkey 2 inspected items 199 times. Monkey 3 inspected items 5192 times. == After round 2000 == Monkey 0 inspected items 10419 times. Monkey 1 inspected items 9577 times. Monkey 2 inspected items 392 times. Monkey 3 inspected items 10391 times. == After round 3000 == Monkey 0 inspected items 15638 times. Monkey 1 inspected items 14358 times. Monkey 2 inspected items 587 times. Monkey 3 inspected items 15593 times. == After round 4000 == Monkey 0 inspected items 20858 times. Monkey 1 inspected items 19138 times. Monkey 2 inspected items 780 times. Monkey 3 inspected items 20797 times. == After round 5000 == Monkey 0 inspected items 26075 times. Monkey 1 inspected items 23921 times. Monkey 2 inspected items 974 times. Monkey 3 inspected items 26000 times. == After round 6000 == Monkey 0 inspected items 31294 times. Monkey 1 inspected items 28702 times. Monkey 2 inspected items 1165 times. Monkey 3 inspected items 31204 times. == After round 7000 == Monkey 0 inspected items 36508 times. Monkey 1 inspected items 33488 times. Monkey 2 inspected items 1360 times. Monkey 3 inspected items 36400 times. == After round 8000 == Monkey 0 inspected items 41728 times. Monkey 1 inspected items 38268 times. Monkey 2 inspected items 1553 times. Monkey 3 inspected items 41606 times. == After round 9000 == Monkey 0 inspected items 46945 times. Monkey 1 inspected items 43051 times. Monkey 2 inspected items 1746 times. Monkey 3 inspected items 46807 times. == After round 10000 == Monkey 0 inspected items 52166 times. Monkey 1 inspected items 47830 times. Monkey 2 inspected items 1938 times. Monkey 3 inspected items 52013 times. After 10000 rounds, the two most active monkeys inspected items 52166 and 52013 times. Multiplying these together, the level of monkey business in this situation is now 2713310158. Worry levels are no longer divided by three after each item is inspected; you'll need to find another way to keep your worry levels manageable. Starting again from the initial state in your puzzle input, what is the level of monkey business after 10000 rounds? ================================================ FILE: exm/aoc/2022/aoc_2022_12.adb ================================================ -- Solution to Advent of Code 2022, Day 12 ------------------------------------------- -- Hill Climbing Algorithm -- -- https://adventofcode.com/2022/day/12 -- Copy of questions in: aoc_2022_12_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_12 is type Point is record x, y : Integer; end record; start, finish, n : Point; inf : constant Natural := Integer'Last / 4; nx_max : constant := 200; ny_max : constant := 100; subtype Range_x is Integer range 1 .. nx_max; subtype Range_y is Integer range 1 .. ny_max; map : array (Range_x, Range_y) of Character; best : array (Range_x, Range_y) of Natural; use HAT; procedure Data_Acquisition is c : Character; f : File_Type; x, y : Natural := 0; begin Open (f, "aoc_2022_12.txt"); Read_Data : while not End_Of_File (f) loop y := y + 1; x := 0; Get (f, c); loop x := x + 1; case c is when 'S' => start.x := x; start.y := y; map (x, y) := 'a'; when 'E' => finish.x := x; finish.y := y; map (x, y) := 'z'; when others => map (x, y) := c; end case; exit when End_Of_Line (f); Get (f, c); end loop; end loop Read_Data; n.x := x; n.y := y; Close (f); end Data_Acquisition; -- Dijkstra shortest path algorithm. -- Code adapted from AoC_2021_15. -- -- The following definitions belong to the Dijkstra algorithm, but -- we keep them less local because of the visualization. list_length_max : constant := 7500; subtype List_Range is Integer range 1 .. list_length_max; type Node is record len : Natural; pt : Point; pred : Natural; -- This is just for displaying the path. end record; list : array (List_Range) of Node; current, explored : Natural; -- 0 <= current <= explored function Dijkstra_Algorithm (start : Point; part : Positive) return Natural is cur_len : Natural; cur_c : Character; procedure Visit (x, y : Integer) is len_to, ins : Integer; ok_step : Boolean; begin if x in 1 .. n.x and then y in 1 .. n.y then if part = 1 then -- We avoid ascending more than one unit. ok_step := map (x, y) <= Succ (cur_c); else -- We avoid descending more than one unit (reverse walk). ok_step := map (x, y) >= Pred (cur_c); end if; if ok_step then len_to := cur_len + 1; if len_to < best (x, y) then -- Improvement on cell (x, y). best (x, y) := len_to; -- -- Insert in a sorted way. -- ins := explored + 1; for i in current + 1 .. explored loop if len_to < list (i).len then ins := i; -- Insert here. -- Optional: remove another node -- with the same (x, y) and a larger length. exit; end if; end loop; for i in reverse ins .. explored loop list (i + 1) := list (i); end loop; list (ins).len := len_to; list (ins).pt.x := x; list (ins).pt.y := y; list (ins).pred := current; explored := explored + 1; end if; end if; end if; end Visit; -- cur_pt : Point; begin current := 0; explored := 0; for x in 1 .. n.x loop for y in 1 .. n.y loop best (x, y) := inf; end loop; end loop; best (start.x, start.y) := 0; cur_pt := start; loop cur_len := best (cur_pt.x, cur_pt.y); cur_c := map (cur_pt.x, cur_pt.y); Visit (cur_pt.x - 1, cur_pt.y); Visit (cur_pt.x + 1, cur_pt.y); Visit (cur_pt.x, cur_pt.y - 1); Visit (cur_pt.x, cur_pt.y + 1); -- -- Switch to the next best explored point. -- current := current + 1; if current > explored then Put_Line ("No way found."); return inf; end if; cur_pt := list (current).pt; if part = 1 then exit when cur_pt.x = finish.x and then cur_pt.y = finish.y; else exit when map (cur_pt.x, cur_pt.y) = 'a'; end if; end loop; return best (cur_pt.x, cur_pt.y); end Dijkstra_Algorithm; --------------- -- Display -- --------------- package Display is subtype Color_Range is Natural range 0 .. 255; type Pixel is record R, G, B : Color_Range; end record; black, red, green, blue, yellow, pink, white : Pixel; min_x : Range_x; max_x : Range_x; min_y : Range_y; max_y : Range_y; bitmap : array (Range_x, Range_y) of Pixel; procedure Init; procedure Show_Map; procedure Show_Path (path_color : Pixel; part : Positive); procedure Show_Ends; procedure Dump_PPM (title : VString); end Display; package body Display is procedure Init is begin Display.min_x := 1; Display.max_x := n.x; -- 200; Display.min_y := 1; -- 401; Display.max_y := n.y; -- 990; -- black.R := 0; black.G := 0; black.B := 0; -- white.R := 16#ff#; white.G := 16#ff#; white.B := 16#ff#; -- red := black; red.R := 16#ff#; green := black; green.G := 16#ff#; blue := black; blue.B := 16#ff#; -- yellow := white; yellow.B := 16#00#; -- pink.R := 255; pink.G := 174; pink.B := 201; end Init; procedure Show_Map is height, value : Real; px : Pixel; begin -- Display the map on the RGB bitmap: for y in min_y .. max_y loop for x in min_x .. max_x loop height := Real (Ord (map (x, y)) - Ord ('a')) / 25.0; value := height ** 0.4; -- Enhance low values. px.R := 10 + Integer (90.0 * value); px.G := 80 + Integer (115.0 * value); px.B := 50 + Integer (110.0 * value); bitmap (x, y) := px; end loop; end loop; end Show_Map; procedure Show_Path (path_color : Pixel; part : Positive) is px, path : Pixel; i, j : Natural; fall : Boolean; begin -- Display optimal path, back from the end (E). i := current; while i /= 0 loop j := list (i).pred; if i = current then bitmap (list (i).pt.x, list (i).pt.y) := path_color; elsif j /= 0 then px := bitmap (list (i).pt.x, list (i).pt.y); if part = 1 then fall := map (list (i).pt.x, list (i).pt.y) < map (list (j).pt.x, list (j).pt.y); else -- The path is walked in reverse, from the -- hill's top to the plains. fall := map (list (i).pt.x, list (i).pt.y) > map (list (j).pt.x, list (j).pt.y); end if; if fall then -- Show differently the point(s) -- where the guy falls. path := red; else path := path_color; end if; -- Blend current pixel with the color chose for the path: px.R := (path.R + 2 * px.R) / 3; px.G := (path.G + 2 * px.G) / 3; px.B := (path.B + 2 * px.B) / 3; bitmap (list (i).pt.x, list (i).pt.y) := px; end if; i := j; end loop; end Show_Path; procedure Show_Ends is begin -- Display start (S) and end (E) points. bitmap (start.x, start.y) := green; bitmap (finish.x, finish.y) := blue; end Show_Ends; -- PPM output adapted from AoC_2022_09. -- procedure Dump_PPM (title : VString) is d : File_Type; begin Create (d, title & ".ppm"); Put (d, "P6" & Chr (10)); Put (d, max_x - min_x + 1); Put (d, ' '); Put (d, max_y - min_y + 1); Put (d, Chr (10)); Put (d, "255" & Chr (10)); for y in min_y .. max_y loop for x in min_x .. max_x loop Put (d, Chr (bitmap (x, y).R)); Put (d, Chr (bitmap (x, y).G)); Put (d, Chr (bitmap (x, y).B)); end loop; end loop; Close (d); end Dump_PPM; end Display; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := not compiler_test_mode; begin Data_Acquisition; if verbose then Display.Init; Display.Show_Map; end if; r (1) := Dijkstra_Algorithm (start, 1); if verbose then Display.Show_Path (Display.yellow, 1); end if; r (2) := Dijkstra_Algorithm (finish, 2); if verbose then Display.Show_Path (Display.pink, 2); Display.Show_Ends; Display.Dump_PPM (+"height_map"); end if; if compiler_test_mode then if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: shortest path from S to E . . . . . . : " & r (1)); Put_Line (+"Part 2: shortest path from E to the ground . . : " & r (2)); -- Part 1: validated by AoC: 440 -- Part 2: validated by AoC: 439 end if; end AoC_2022_12; ================================================ FILE: exm/aoc/2022/aoc_2022_12.txt ================================================ abccccccaaccaaccccaaaaacccccaaaaccccccccccccccccccccccccccccccccaaaaaaaaaaaaaaaaaaaccccccccccccccccaaaccccccccccccaacccccccccccccccccccccccccccccccccccccccccaaaa abaaaaccaaaaaccccaaaaaccccccaaaaccccccccccccccccccccaaacccccccccccaaaaaaaaaaaaaaaaaaccccccccccccccccaaaaccccccaaacaaccccccccccccccccccccccccccccccccccccccccaaaaa abaaacccaaaaaaaacaaaaaacccccaaaaccccccccccccccccccccaaaaacccccccccaaaaaaaaaaaaaaaaacccccccccaaccccaaaaaacccccccaaaaaccccaaccccccccccccccacccccccccccccccccccaaaaa abaaacccccaaaaaccccaaaaccccccaaacccccccccccccccccccaaaaaccccccccccaaaaaacacaaaaaacccccccccccaaccccaaaaacccccccccaaaaaaccaaaaaaccccccccccaaaccccacccccccccccaaaaaa abaacccccaaaaaccccaacccccccccccccccaaaaacccccccccccaaaaacccccccccaaaaaaaaccaaaaaaacccccccaaaaaaaaccaaaaacccccccaaaaaaaccaaaaacccccccccccaaacccaaaccccccccccccccaa abaaacccaaacaacccccccccccccccccccccaaaaaccccccccccccaaaaacccccccaaaaaaaaaccaaccaaacccccccaaaaaaaaccaacccccccccaaaaaaccaaaaaaccccccccccccaaaacaaaaccccccccccccccaa abaaacccccccaaccccccccccccccccccccaaaaaaccccccccccccaaccccccaacccaaaccaaaaccccccaacccccccccaaaacccccccccccccccaacaaaccaaaaaaaccccccccccccajjjjjjjcccccccccccccccc abcaacccccccccccccccccccccccccccccaaaaaaccccccccccccccccccccaaaaccccccaaaaccccccccccccccaacaaaaaccccccccccccccccccaaccccaaaaaacccccccccccjjjjjjjjjcccccaaaccccccc abccccccccccccccccccccccccccccccccaaaaaaccaaccccccccccccccaaaaaacccccccaaacccccccccccaacaaaaaaaaccccccccccccccccccccccccaaccaaccccccccaiijjjjojjjjcccccaaacaccccc abcccccccccccccccccccccccaaacccccccaaacacaaacccccccccccccccaaaaccccaaccccccccccccccccaaaaaaacccaccccccccccccccccccccccccaacccccccccccaiiijjooooojjkccaaaaaaaacccc abccccccccccccccccccccccaaaaccccccccccaaaaaccccccccccccccccaaaaacccaaaaaccccccccccccccaaaaaacccccccccccccccccccccccccccccccccccccciiiiiiiioooooookkkcaaaaaaaacccc abccccccccccccccccccccccaaaaccccccccccaaaaaaaacccccccccccccaacaaccaaaaacccccccaaacccaaaaaaaaccccccccccccccccccccccccccccccccccchiiiiiiiiooooouoookkkccaaaaaaccccc abcccccccccaaccccccccccccaaaccccccccccccaaaaacccccccccccccccccccccaaaaaccccccaaaacccaaaaacaacccccccccccccaacaacccccccccccccccchhhiiiinnnooouuuuoookkkccaaaaaccccc abcccccccccaaacccccccccccccccccccccccccaaaaacccccccccccccccccccccccaaaaacccccaaaaccccccaaccccccccccccccccaaaaacccccccccccccccchhhnnnnnnnnouuuuuuppkkkkaaaaaaccccc abccccccaaaaaaaacccaaccccccccccccccccccaacaaccaacaaccccccccccccccccaacccccccccaaaccccccaacccccccccccccccaaaaacccccccccccccccchhhnnnnnnnnntuuxuuupppkkkkkacccccccc abccccccaaaaaaaacacaaaacccccccccccccccccccaaccaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaacccccccaacccccchhhnnnnttttttuxxxuuppppkkkkkcccccccc abcccccccaaaaaaccaaaaaaccccccccccaaccccccccccaaaaaccccccccccccccccccccccccaaacccccccccccccccccccccccccccccaaaaccaaccaaacccaaahhhnnntttttttuxxxxuupppppllllccccccc abcccccccaaaaaacccaaaacccccccccaaaaaaccccccccaaaaaacccccccccccccccccccccccaaacccccccccccccccccccccccccccccacccccaaaaaaacaaaaahhhppntttxxxxxxxxuuuuvpppplllccccccc abcccccccaaaaaacccaaaacccccccccaaaaaacccccaaaaaaaaaccccccccccccccccccccaaaaaaaacccccccccccccccccccccaaaccccccaacaaaaaaccaaaaahhhpppttxxxxxxxxyuuvvvvvppplllcccccc abcccccccaaccaacccaacaccaaaaccccaaaaacccccaaaaaaaaaccccccccccccccccccccaaaaaaaacccccccccccccccccccccaaacaaaaaaaccaaaaaaaaaaaaahhppptttxxxxxxyyyyyyvvvppplllcccccc SbccccccccccccccccccccccaaaacccaaaaacccccccaaaaaaaaacaaaccccccccaacccccccaaaaaccccccccaaaaacccccccccaaaaaaaaaaaaaaaaaaaaaaaaacgggpppttxxxxEzzyyyyyvvvqqqlllcccccc abccccccccccccccccccccccaaaacccaaaaacccccccaaaaaaaaccaaaccccccccaaacaaccaaaaaaccccccccaaaaacccccccaaaaaaaaaaaaaaaaaaaaaaaaaaacgggpppsssxxxyyyyyyvvvvvqqlllccccccc abcccaaaccccccccccccccccaaaccccccccccccccccaaaaaaaaaaaaaccccccccaaaaaaccaaaaaacccccccaaaaaacccaaaccaaaaaccaaaaaaaaaaaacccccccccgggppssswwyyyyyyvvvvqqqqlllccccccc abcaaaaaccccccccccccccccccccccccccccccccccaaaaaaaaaaaaacccccccaaaaaaacccaccaaacccccccaaaaaacccaaacccaaaaaaaaaaaccccaaacccaaaaacgggppsswwwyyyyyyvvqqqqqlllcccccccc abcaaaaaaccccccccccccccccccccccccccccccccccaaccaaaaaaaaaaaccccaaaaaaacccccccccccccccccaaaaacccaaacaaaacaaaaaaaaccccaaacccaaaaacggpppsswwwywwyyyvvqqqmmmlccccccccc abcaaaaaacccccccaacaaccccccccccccccccccccccccccaaaaaaaaaaaccccccaaaaacccccccccccccccccaaaccaaaaaaaaaaacccccccaacccccccccaaaaaacggpppsswwwwwwwwyvvqqqmmmcccccccccc abcaaaaaccccccccaaaaaccccccccccccccccccccccccccccaaaaaaaacccccccaacaaacccccccccccccccccccccaaaaaaaaaccccccccccccccccccccaaaaaagggoossswwwwrrwwwvvqqmmmccccccccccc abcaaaaacccccccaaaaaccccccccccccccccccccccccccccaaaaaaacccccccccaaccccccccccccccccccccccccccaaaaaaacccccccccccaaaccccccccaaaaagggooosssssrrrrwwwvqqmmmcccaacccccc abcccccccccccccaaaaaaccccccccccccccccccccaacccccccccaaaccccccccccccccccccccccccccccccccccccccaaaaaaccccccccccccaaaaccccccaaaccgggooosssssrrrrrwwrrqmmmcccaacccccc abcccccccccccccccaaaacccccccccccccccccccaaaacccccccacaaacccccccccccccccccccccccccccccccccccccaaaaaaacccccccccaaaaaacccccccccccgffoooooosoonrrrrrrrrmmmccaaaaacccc abcccccccccccccccaccccccccccccccccccccccaaaacccccccaaaaacccccccccccccccccccccccccccccccccccccaaacaaacccccccccaaaaacccccccccccccfffoooooooonnnrrrrrmmmddcaaaaacccc abccccccccccccccccccccccccccccccccccccccaaaaccccccccaaaaacccccccccccccccccccccccccaaaccccccccaacccccccccccccccaaaaaccccccccccccffffoooooonnnnnnrnnmmmdddaaaaacccc abcccccccccccccccccccccccccccccccccccccccccccccccccaaaaaacccccccccccccccccaaaaaccaaaacccccccccccccccccccccccccaacccccccccccccccfffffffffeeeennnnnnmmdddaaaacccccc abcccccccaaaccccccccaccccccccccccccccccccccccccccccaaaaccccccccccccaaaccccaaaaaccaaaaccccccccccccccccccccccccccccccccccccccccccccfffffffeeeeennnnnmddddaaaaaccccc abcccaaccaaacccccaaaacccccaacccccccccccccccccccccccccaaacccccccccccaaacccaaaaaacccaaaccccccccccccccccccccccccccccccccccccccccccccccffffeeeeeeeedddddddcccaacccccc abcccaaaaaaacccccaaaaaaccaaacccccccccccccccccccccccccccacccccccccccaaaaccaaaaaaccccccccccccccccccccccccccaacccccccccaaaccccccccccccccaaaaaaeeeeedddddcccccccccccc abcccaaaaaacccccccaaaacccaaacaaaccccaaaacccccccccaaacaaaccccccaacccaaaacaaaaaaacccccccccccccccccccccccccaaaccccccccaaaacccccccccccccccccccaaaaeeddddccccccccccccc abccccaaaaaaaacccaaaaaaaaaaaaaaaccccaaaacccccccccaaaaaaacccccaaacccaaaaaaaaaacccccccccccccccccccccccaaacaaaccccccccaaaaccccccccccccccccccccaaaccccccccccccccaaaca abcccaaaaaaaaacccaacaaaaaaaaaaacccccaaaaccccccccccaaaaaacaaacaaacaaaaaaaaaacccccccccccccccaaacccccccaaaaaaaaaaccccccaaaccccccccccccccccccccaacccccccccccccccaaaaa abcccaaaaaaaacccccccccccaaaaaacccccccaacccccccccccaaaaaaaaaaaaaaaaaaaaaaaaccccccccccccccccaaaacccccccaaaaaaaaacccccccccccccccccccccccccccccaaacccccccccccccccaaaa abccaaaaaaacccccccccccccaaaaaaacccccccccccccccccaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccaaaacccccccaaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccaaaaa ================================================ FILE: exm/aoc/2022/aoc_2022_12_questions.txt ================================================ --- Day 12: Hill Climbing Algorithm --- You try contacting the Elves using your handheld device, but the river you're following must be too low to get a decent signal. You ask the device for a heightmap of the surrounding area (your puzzle input). The heightmap shows the local area from above broken into a grid; the elevation of each square of the grid is given by a single lowercase letter, where a is the lowest elevation, b is the next-lowest, and so on up to the highest elevation, z. Also included on the heightmap are marks for your current position (S) and the location that should get the best signal (E). Your current position (S) has elevation a, and the location that should get the best signal (E) has elevation z. You'd like to reach E, but to save energy, you should do it in as few steps as possible. During each step, you can move exactly one square up, down, left, or right. To avoid needing to get out your climbing gear, the elevation of the destination square can be at most one higher than the elevation of your current square; that is, if your current elevation is m, you could step to elevation n, but not to elevation o. (This also means that the elevation of the destination square can be much lower than the elevation of your current square.) For example: Sabqponm abcryxxl accszExk acctuvwj abdefghi Here, you start in the top-left corner; your goal is near the middle. You could start by moving down or right, but eventually you'll need to head toward the e at the bottom. From there, you can spiral around to the goal: v..v<<<< >v.vv<<^ .>vv>E^^ ..v>>>^^ ..>>>>>^ In the above diagram, the symbols indicate whether the path exits each square moving up (^), down (v), left (<), or right (>). The location that should get the best signal is still E, and . marks unvisited squares. This path reaches the goal in 31 steps, the fewest possible. What is the fewest steps required to move from your current position to the location that should get the best signal? --- Part Two --- As you walk up the hill, you suspect that the Elves will want to turn this into a hiking trail. The beginning isn't very scenic, though; perhaps you can find a better starting point. To maximize exercise while hiking, the trail should start as low as possible: elevation a. The goal is still the square marked E. However, the trail should still be direct, taking the fewest steps to reach its goal. So, you'll need to find the shortest path from any square at elevation a to the square marked E. Again consider the example from above: Sabqponm abcryxxl accszExk acctuvwj abdefghi Now, there are six choices for starting position (five marked a, plus the square marked S that counts as being at elevation a). If you start at the bottom-left square, you can reach the goal most quickly: ...v<<<< ...vv<<^ ...v>E^^ .>v>>>^^ >^>>>>>^ This path reaches the goal in only 29 steps, the fewest possible. What is the fewest steps required to move starting from any square with elevation a to the location that should get the best signal? ================================================ FILE: exm/aoc/2022/aoc_2022_13.adb ================================================ -- Solution to Advent of Code 2022, Day 13 ------------------------------------------- -- Distress Signal -- -- https://adventofcode.com/2022/day/13 -- Copy of questions in: aoc_2022_13_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_13 is use HAT; type Order is (correct, wrong, undecided); -- Here we compare a pair of recursive lists in the form: -- [[1],[2,3,4]] -- [[1],4] function Compare_List (s1, s2 : VString) return Order; function Compare_Elements (s1, s2 : VString) return Order is i1, i2 : Integer; h1, h2 : Character; begin h1 := Element (s1, 1); h2 := Element (s2, 1); if h1 in '0' .. '9' and then h2 in '0' .. '9' then i1 := Integer_Value (Slice (s1, 1, Length (s1))); i2 := Integer_Value (Slice (s2, 1, Length (s2))); if i1 < i2 then return correct; elsif i1 > i2 then return wrong; else return undecided; end if; elsif h1 = '[' and h2 = '[' then return Compare_List (s1, s2); elsif h1 = '[' then return Compare_List (s1, '[' & s2 & ']'); else return Compare_List ('[' & s1 & ']', s2); end if; end Compare_Elements; function Element_End (s : VString) return Natural is l : constant Natural := Length (s); skip : Natural := 0; begin if l = 0 then return 0; end if; for i in 1 .. l loop case Element (s, i) is when ',' => if skip = 0 then return i - 1; end if; when '[' => skip := skip + 1; when ']' => skip := skip - 1; when others => null; end case; end loop; return l; end Element_End; -- Remove first element in "a,b,c" procedure Delete_Head (s : in out VString; element_length : Natural) is begin Delete (s, 1, element_length); if Length (s) > 0 and then Element (s, 1) = ',' then Delete (s, 1, 1); end if; end Delete_Head; -- Remove then '[' and ']' at both ends. procedure Delete_Brackets (s : in out VString) is begin Delete (s, Length (s), Length (s)); Delete (s, 1, 1); end Delete_Brackets; function Compare_List (s1, s2 : VString) return Order is e1, e2 : Integer; v1, v2 : VString; res : Order; begin v1 := s1; v2 := s2; -- Remove the outmost brackets around the list. Delete_Brackets (v1); Delete_Brackets (v2); -- Process the elements, if any. loop e1 := Element_End (v1); e2 := Element_End (v2); if e1 = 0 and e2 = 0 then return undecided; elsif e1 = 0 then -- "If the left list runs out of items first, -- the inputs are in the right order." return correct; elsif e2 = 0 then -- "If the right list runs out of items first, -- the inputs are not in the right order." return wrong; end if; res := Compare_Elements (Slice (v1, 1, e1), Slice (v2, 1, e2)); if res /= undecided then return res; end if; -- Move to next element on both lists. Delete_Head (v1, e1); Delete_Head (v2, e2); end loop; end Compare_List; function One_if_lesser (s1, s2 : VString) return Natural is begin if Compare_List (s1, s2) = correct then return 1; else return 0; end if; end One_if_lesser; f : File_Type; s : array (1 .. 2) of VString; pair_index, sum_correct_pair_indices, before_2, before_6 : Natural := 0; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; begin Open (f, "aoc_2022_13.txt"); Read_Data : loop for i in 1 .. 2 loop Get_Line (f, s (i)); before_2 := before_2 + One_if_lesser (s (i), +"[[2]]"); before_6 := before_6 + One_if_lesser (s (i), +"[[6]]"); end loop; pair_index := pair_index + 1; if Compare_List (s (1), s (2)) = correct then sum_correct_pair_indices := sum_correct_pair_indices + pair_index; end if; exit Read_Data when End_Of_File (f); Skip_Line (f); end loop Read_Data; Close (f); r (1) := sum_correct_pair_indices; r (2) := (before_2 + 1) * (before_6 + 2); if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: sum of indices of list pairs in correct order : " & r (1)); Put_Line (+"Part 2: product of indices of [[2]] and [[6]] dividers : " & r (2)); -- Part 1: validated by AoC: 6568 -- Part 2: validated by AoC: 19493 end if; end AoC_2022_13; ================================================ FILE: exm/aoc/2022/aoc_2022_13.txt ================================================ [[[],2,9,4],[],[[[],[0]],[[7,0,10,8],[10,5,5,4,1],0,6]],[]] [[[8],[3,6,9,[10,4,2],[4,5]],[10,[3],[7,10,7,2],[0,5]],2]] [[[3,6],[]],[[7,[7,9,1,8,2],[],[1],3],[[8,0,10],[5],0,8],[[6,4,5],[1,3,1,10,8],[],[8]],9,9]] [[[[5,0],[4,7,3],[4,5],[0,2]],9,0]] [] [[6,[4,8,0,[1,9]]],[[0,4,[8,10,8],[1,4,9,2,4]]]] [[8,4,8,8,1],[2,[1,8,[5,3,8]],[[3,2,2,9,8]]],[[[2,5,0,7],[6,8,8,8,2],1,7],2,8,[6,5,0]],[10],[[[2,6],[2],[0,7,8]],10]] [[],[6,10,[8]],[7,[[0,3,8],[7,0],9,[8,3],[2,7]],5,6],[2,[[7],[7,1,8,6]],0]] [[[[4,3,7],0],2,[3]],[2,0,[10,2,[4],1,0],9],[[10,9,[7]],0,4,[6],[10,[6,10,7,0,9],9]],[10,[8,[2],10,[7,10,9,6],6],5]] [[],[[9,10,1,[9]]],[9,[],[[],[2,1,8,4],[3,4,1,3]],0]] [[[[1,5,4],[0,9,6,4,9],[6,3,6,2],[1,4,10,4],5],0,[5]],[8]] [[[[6,4,9,3,1],[6,10,5,1,3],[3,10,8,4],3],7,3,10,3],[[5,[],0,6,4],8,[[7,8,5]],[6,[9,10,4,2,9],[6,7,4,6]]],[9,5,[[2,0,2,4,10],[2],4],[],9],[]] [[5,[[2],9],[5,7,[6,2,9,6],2]],[[2,5],4],[7,[2,4,[10],10],[0,2,9],[[],[6,4,10,8,0]],[]],[]] [[[10,4,7,4],3],[[[2,10,3,10],2,3,0],[[8,9,5,10,8]]],[[]],[3,[1,[5,5,9,2],[1],[],[5,3,4]],3,2],[3,4]] [[[[6],9],5,[1,1,[5,7,2,9,9],5,0],[3,[],[3,6],8]],[[4,[8,7],3],[[9],[4,5,3]]],[3,[],4,9,[3,[5,3,7]]]] [[3,3,0]] [[],[1],[]] [[[[0,3],[7,0,5,1]],[],[2,[4,3,3,6,4]]],[[],[10,[]],[5,[2,7,7,10],[9,8,2,10,4]]],[[],[[1],[4,4,6],10,[4]],[[1,1,7,7],[6,9],0]],[[3,[3,5,4],[8,2,4,0,3],5,[3,10]],10,[]],[[3],2,[],[[6,1,2,3],[7,7,9,1],7]]] [[]] [[3,8,5],[0,[[5,4,7,0,5],4]],[7,[[8,10,6,9,8],3]]] [[],[6,4,3,[8,[],1,[9,9,7],1],[[],[2,0,3],[4,5,5,8],5,[]]],[[2,2,2,[4,4,7]],8,[[4,9,4,10],8]]] [[[[2,3,0],[],[7],[3,8,5],2],[5,[]],8,[]],[],[],[7],[2]] [[[[2,4,5,2,9],9,7,[8,1,5,7,6]],[[10,9,9]],9],[[[],2,10],[9,4]],[8,9],[[[8,7,5]],1,[[1,7],[],[9,2,4],0],4],[3,3,5,4]] [[7,[8,[9,1,10,1],[8,7]],7,5],[[10,[4],[7,0]],0,5],[4,7,5],[],[9,[[9],[9,1]],5]] [[4,9,[8],[9,7,[0,7],0,0]]] [[4,0,0,2],[3,[[1,6],[5,4,7,1,9],9,5],[[9,1,3],5],8],[[[8,5,8],[],[10,10,0,9,0],[2,0,10]],[[6,3,8]],10,[[5,1,9,10],6]],[[]],[1,2,[[6,4,9,0,2]],8]] [[1,8,4],[6,[[2],4,3],10,1,[10,[8,8,7,3],1,2,7]],[8]] [[[0]]] [[5,[4,[3,7,6],[2,2,6,7]],[[5,8],3,2,[10,1,1,10,2],[3,2]],10],[8,[[],2,[]],[5,6,[3],0],1]] [[9,8,[],[[4,3,8,7,2],[0,5,7,2],8,1],7],[[[10,6],3]]] [[[2]],[[[7,2,8,9],[],2,[]],[6,9,[1,5,5,5],8],6],[[4,3,6,7],[[6,4,8],[0,6,2],6],[4,6],[[5,2,3,4,8]]]] [[[6],7,8,[7,[4],[1,10,0,3],[6]],[[8,10,9,1,2],[9,9,0,2],[2,7,0,2,9],8]],[[[8],0],9,5,[],7]] [[8],[[1,[],0,[10,3,0,8,6]],9,2,[8,[4,3,4],3]],[]] [[],[[[10,9,7],1,[6,3,7],[]],1,[[4,9,8,3,1],[9,8],[0,10,4,3],[0,0]],[6]],[[[5,7,10],10,[5,9,0,6],1,[0,0]],[10,[],[2,1,3]],[9,[5,1],[6,6,9],8]],[0,[],[2,[6,10,2,0],[3,2,9],[8,10,10],4]],[]] [[[[6,1,1,9,0],[2]],6,5,0,[[],[3,4]]],[[],[10,9,1],[2]],[2,[[8,5],5,[]],[1,8,[4],[0,4,4,4],[0,6]],6]] [[7,[9],[0,[4,0],3]],[[[],6,[6]],5,[[1,5,5],4,2],5,[0,1,[]]],[]] [[[4],[5],[9,8,9,1],1],[[[8,2,5]],[10,[9,0,0,6],6,[2,6,2],[4,8]],4,10],[],[[9,3,8,[10,10],4],[]]] [[5,2]] [[10],[0],[4,7,[[4,8],[2,4,8],[4,10,2,5,7],10],2,7],[[[7,0,0,1,0],[0,6,8,6,9],4,6]],[[[],7,[1,6],7],[[10,10,4,2]],[0,3,10,[6]]]] [[[[3],10,[7,3,2],[6,8,5,9]],[4,4,0,[8,6,9,2]]],[]] [[[2,[7,6],5,1,4]],[[8,0,10],[[2,8,6],9,[7],6,4]],[5]] [[4,4,[3,6,5,[10,8,9,5,4]]]] [[],[[9],3,[[6,10,10]],0,4],[[[10,10,10,8,1]],[9,[]]],[4,[8,5,[0],0,[7,6,6,3]],3,[7,0,5,7]]] [[[5,2,8,[1,6,10],5],[],[]],[[[]],[[0,1],5,0],[[8,2,9,1],[2,8,7],5],[[],9,0,6,0],4],[[[2]],[],[0,[3],[],5,6],0,[[7,3,0],1,[0,2,9,10]]]] [[9],[[[],0,9,0,2],5],[0,[10],[10,[8,0,5],5,9]]] [[],[[8],[],2,3],[1,[[10,2,7],6,[3,0,9,6],9,[9,5]],2,6,[3,5,[9,9,8]]],[6,[4,[8,7],4,[2,1,0]],[[10,1,7],10,[1,9,1,0]],9],[0]] [[2],[5,[1,[2,8,9],4,[4,1,7,8]],[],5],[9,9,[3,[10,2,9,0,4]],1],[5,[],8,[9,3,5,2]],[[[5],4,[0],[5],3],3,6]] [[2,2,6],[5,6,[2,10]]] [[[[6,10,5,10,8],[5,8]]],[[[6,4,8,4],[8,7,8],[8,9],3],5,2],[9,[5,9,[2,3]],[[],[7,1,4,4],[],10]],[]] [[6,5,[4,[8],[6,2],2,3],[2,1],10],[8,[8,[],[4,2,7,4]],[9,[5,2,2,0,9],[],[],[8,5]]],[[[4,3,9,6],[5,6,1],4,4,[6,8,1]],[[],9],[[2],6,2]],[7],[[[5,5,4]],3]] [[[[5],[0]],[5,10,[],5,4],[1,[1,9,2],8,[2]],8],[[[2,0,10,0]],5,3],[[[]],[5,1],[[0,2,4],5,10,[7,4]],0,[[5,8,2],[7,9,0],6]],[8,[[1,8],8,[3,0,4,10]],9]] [[],[],[[[5,8],8,[2,8,6,9]]],[9,9],[8,[9,[1,4,4,7,3],8],9,4]] [[10,[9,8],[[],[5,8,10,10,7],[7],4,[]],[0,3,[8,3,2],5]],[4,[0,[]]],[[[4]],[7,2,0,[3,0,7,6],3],[1,[0,9,7]],[5],[[0],3,2,8,2]],[6,[[6,10,6,0],[0],4,1,[5,8,5,3,10]]]] [[7,4,[[7,9],[6,1,7,9],[10],[9,4]],[[6,4],8,[9,3,8,10,1],[]],2]] [[[[1,0],[8,1,2,4,0]],2,[],5],[0,[]],[9,[],5]] [[[[10,0,9],8,[4,10],[8,3,10,6],4],10],[6,[[10,10,1,7],6],6],[[[10,7],3,6,4,[1,2]],10,[[8,3],[],5,1,0],[[],[0,7,0],5]],[]] [[9,3,2,[6,7,[10,5,7,3,2]],[[7,9,0,10],9,[10],[8,1,4,2]]],[10,9,8,[[9,4,10,3],2],[6]],[3,8,6,[[10,7,3,6]],[2,4,10,[3,3,0,5],[]]],[9,8,[2,9,10,[5]],[[],[3,7,10,10,9],[7,1,3,1,7],0,[]],[[2,1,10,7,9],[4],10]]] [[8,[[],[4,1,5,5,1]],6,9,5]] [[6],[[[3,6,10,8,9],1,[10,2,4,0,7],9]],[5,[6,1],[0],4],[],[[],[],[6,9,9],[],[]]] [[[7,[3,0,4,1],[2,9,10,6,4]]]] [[],[[],9,3,9]] [[[],[[8],[7,7,6,3],[],[9,7]],10,10]] [[[10,6]],[8,9,[7,9,6,[4],6],9,[[8],[7,1],[7,7],0]],[[10,6,[6]],7,7]] [[[[10,5,8],[8,1]],[[4,0,0,1,10],0,[8,10,2,9],[0,1,2,0],[4,0]],[8,[],0,2,[4,3,8,7,2]],[0,[0,3,6]],4],[[7,[3,8]],10,[]],[8]] [[[4,9,[3,5],9],10,7,5],[6,[5,[7,9,4,4,8],[0,3,3,5],10,6],[[]]]] [[9,[],[[6,3,2],9,3,5],7,[]]] [[[10,[],[5],[3],0],[6,[5,4,5,8,7]],5,2,5],[[5,8],[[]],0],[9,3,7,5],[7,[8,5,9],[3],[[],6,[4,5,8]],9],[[9],10,[[5,9,4,5],[]],2]] [[10],[5,10],[[9,9,[8]]],[[10,[],[5,10,6,2],[9],[]],[[0,8,10,10],[0,5,1,5,0],[2,2,5,1,9],9]],[3,7,[[3]],[[3,4,10,8],[2,3,10],3,[8]]]] [[3],[2,[],[[4,8,10],[7],3,[0,5,4]],3,3],[],[[],[[9,7,7]],[[8]]],[8,[],[[8],3],[]]] [[9,4,4],[[[1],9,6,[4,5]],[6,2,0],5],[[3,[6],9],7,[[],[6,0,2,4],[]],8,[6,[0,1],7,5]]] [[10,[],[[1],[8]],[],[[],5,[8],[3,8],[1]]],[[[],[4,8],[9,6,7,1]],3,5],[[[2,9,3,10,0],0,6,[3,7,5],[9,7]],10],[[8,0,[8,7]],6,5,5]] [[6,8]] [[],[],[]] [[[2,5,7],9,0,[1,10]],[8,[0,[2],5,[],[5,6]],6],[[[7,7],1,[6],[1,9],3]]] [[2,4,[[4,3,4,10],[7],6],[9]],[3,[],[[8,9,10,9],6,[2,3,2,4,10],6],[[4,8,4,8],2,6]],[3,[2],[7],4],[[2,[2,1],[9,3],[9,4,5]],[[1],[5,5,10]]],[1,[]]] [[[7,[3,6,6,6,2],[7,0,3,0],7,5]],[[4]],[],[3,9,1,4,[[1,7,0,10,8],0,5,[0]]],[[5,9,[4,5,5,10],[0,7]],0]] [[[2,8,2,8]],[]] [[],[6,9,[[8,7,7],[0],[4],[]],0,[[],[7,1,9,2],[2,5,9,4],2,[2]]]] [[7,3,[[8,9,3,7],[7,10,6,2],[4,0,7,0,8],[0]]],[[[],[4,3],8]],[]] [[[10,[9,9,4]],6],[4,[4,[],5,[3,1,8,6],0]],[5],[]] [[[],[4,0,[0,0,6,9],[8,0,3,7],[3]],9]] [[],[],[[[7,3,7,7],[5,8,3],6],10,4,[2,4]],[4,1,6,[]],[]] [[[[],4,4],4,6,9,[0,[1,10]]],[],[5],[6,[[8]],5],[[2,[6,3,1,10],[]],0,[[],[1,6,2,10,6],[8,10,6,2,1],1]]] [[[[0,9,8,3],1,0,5,[9,0]],[[5,8,3,4,9],[4,1,2,9,4],1,[],5]],[[[10,10,1,6],[5,10,3]],[[7,7,8,8,7],0,0,10]]] [[2,[[8,7,0,1,6],10,9],5],[]] [[[[3,9,9,2,4]],8,[],4,[[8,8,4],[],4,6,[5,6]]],[[[],0,7,3,[3,0,4,9,0]],[[4,5,6,7,0],5,0]],[2,[[0,1,5,6],[3,2,0,6]],[[6,7,1],4,[2,2],[4,10,9]],[9,2,[6]],[[7,7,9],1]],[[],[1,10,[7,9,2],2,10],2,[[]],[2,2,2,1,8]]] [[[7,8],[2,[7],[2,3,0]],1,[5,[6],5,[4,1,5,9]],[]],[0],[[[7,5,0],3,[6],8]],[6]] [[9,[[4,8],[1,4,8]],6],[[8,[3,6,2,2],[],[8,4,3],8],8,[[5,0],[],[4]],2,0],[[[7,6,1,6],[2,10,1,5,1],3]],[[[10,0,0],[8,1,4,3],[2,0,4],7,1],[8,9,[8,4,2,0,9]]],[[8,1],[[],[7,9,6],6,[10,0,8]]]] [[[8],1,2,[0,[4,4,8,7],[6,5,3]]],[],[[[5,7,10],4],[[10,10,4,6,5],0,[]],5,[[10,8],9,2],9]] [[],[],[[1],3,[[3,8,10],[9],4,[],[7,6]]],[[[7,5,4,7,5],[7,6]],[9],[[4,0],6,[2,0,5,6,7]],[[],9,[7,4,5,0,6]],[[8,0,2],[1,3,3,6]]]] [[6,7,4,8],[9],[8,[[3,6,6,5]]]] [[6,4,[[],10,2,[1,1],[7,2,2]]],[10,[10,[5,10,9,7,7]],7,[9,[0],9,10],10]] [[[0,[7,8,3]],7],[0,6,7,[8,[5,1],[7,6]]],[5],[[[],10],6]] [[8,[7,[8,9],8,9],3,[8,[2],6],2],[[[8,5],8,[0,4,10,4,5],[5],[4,4,2,6]],[],1,4,[10,4,[1,9,10,2,8],3,7]],[[[],4,[9,1,0,10,8],[6],[10,4,3,10,9]],4]] [[6],[],[6,9,[[6],5],[[5,8]],[[9,9,3,4,3],[0,5,6],[1,1,9]]]] [[6,5,10,[[]],1]] [[0,[0],[10,5,2,[9,0,10,4,0],5]]] [[7,2,3,[[1,10,7,1]]],[6,9,[[9,0,10,4,6],7,[1,8,6]],[[7,3]],3]] [[0,1,3,1],[3,6,[[0,1],9,[0,6,8,3,0],[1,10,10]]],[[],5,9],[4,[],[[8,6],[8,5,6,6,0],[2,6,5]],4],[10,[]]] [[],[8,[10]],[[10,[3,0,1,4],1],6,[[5,8,6],[10,10,6,4],[9,7,7]],[]],[]] [[0,3,[],[9,[7,2,4,9],[6,7],9,5],[]],[],[[7,[],[9,7,9,0,4],5],[6,[9,4,5,10,5],[1,4],[3,7,10,3],8],2],[]] [[8,6]] [[[[8,4,8,10,8],[7],[4,6,0],2,[1,1]],9,[[],0]]] [[2,[]]] [[[],2,10,2],[[[4,9],[4,8,9,9],[8,6,8],[1,1]],[7,3,[],[],2],[9,[6]],1],[[],[1,5,2,7,4]],[[[2],9,[7,7,2],8,6]]] [[],[9,9,[[],8],[[1,8],[10],9,[4,7,10,0],9],2],[]] [[[1,6,[9,3],9],[6,[4,7,9,2],[10],[4,10,8,1],[]]],[[[9,8],[4,9,1],9,[6,0,6,10]],[8,1,[8,3],2,6],9],[],[[6,[4,4,6,10],5,7,[2,0,8]],[[]],6]] [[8,8,[1,6,[9,4,8,3,7],[7,6]]],[9,7,4,[]]] [[2],[],[],[[[7,4,1,0,1],[0,9]],6,[[8,10,0,4,8]]]] [[1,9,9],[1,[[2],[0,5,9],2],[[9,7,7],6,6]],[[1,6,8,[]],[[0,1,5],3],5,[[9,2],2,6,5],5],[5,8,[4,4,[],[9]],1,7]] [[10,7,6],[[[],[4],4,5,10],1]] [[],[5],[0,[[5,3],1,10,[2,0],[8,1]],[1],4],[5,4,10,10,[[9,2,1,3],[2,10,10],[8,1,9],[3],[]]],[[0,2,[2,4,1],2,1],4,5,[[10],[7,5],[],1]]] [[7,[[8],2,[0,9,5,5,2],[5,3,4,2]]],[[[3,5,7,3,2],[5,10],8,9],4,7,8]] [[],[3,0,1,9,10]] [8,10,7,6,5] [8,10,7,6] [[[[6,5,4],[4,0,8,7,0],[1,9],5,[1,9,1,1,0]],[[4,6,6,2]],[8,[4,7],[8,2,7,9],[5],[]],1,[10,6,[1,5,8]]],[7,7,[8,[9],[2],4,[7,4,4,3,9]],[[],[3,7,3,1],3,[4,7]],2]] [[[9,5,[7],8],[[10,7,4,4],10,[3],8],10],[[[5,1,5,6],[2,2,5,4,5],0],[9,[10,9],8,8,7],3,[9],[[]]],[[8,5,8,6],4,[],[[]],9]] [[[0,7,7,5,9],[[],8,[2,2,7,3,7],6,[10,6]],[3,7,[8]]],[],[[],1,3,0,3],[]] [[3]] [[[[],[]],2,[8]],[],[0,[[0,3,3,7],1,[7,6,10]],7,1,[[3,0,8]]],[[[]],[[4,6,2,9,3]]],[[],[6,[2,8,6],4,7,[3,1,5,7,1]],1]] [[5,2,8,[[9,6,0]],10],[[[],[4,0,7,9],6,[9,0,7,5,9],[7,5,3]]],[5],[[1,10,7,[2,2]],[9,3]]] [[[],[[],[0,6]],10,7,[7,[],[2,5,2,10],[6,1],[2,0]]],[],[[2]]] [[6,[[10,6],4,3,[6,10]],[[7,6,9,10]],[7],10],[[5]],[[],[0,[8,3],5,[]],[[2]],0,[[2,8,3,7]]]] [[4],[2,[3,[10],[6,4,1,0],[],[1,9,9,2]],10],[3],[1,4,8],[7]] [[],[6,[],3,5]] [[],[5,[[3,1]],2,[],[[6,7,0,10],[7,8,6,4]]],[[[7,7,9,2],3,[1,1]],2,[10,[9,2,3],0],0,[[2],[10]]],[4,[[]],[4,6],[5,7],[3,[]]],[5,2]] [[8,[[],[9,2,8],[2,8,10,0],3,[10,10]],7],[[8],5,2,[10,1,[9,1],[4,0,0],2]],[9,2]] [[[[],[10,2]],9,7,[6,[9,6,8],8]]] [[[],0,10,0],[[[]]],[],[],[6,[],8,[],8]] [[[[4,8,6],9,[7,8],2,[1,3]],1,7,[[0]],8],[[0,[0,9],[9,1,2,8,3]],[]],[8,3,[7,[]],[2,[3,7,8],10],4],[10,[[9,2]],[[],4,10,9]],[[7,[9,5],[8,10],[8,2,5,6]],[9,[4,1,10,8],[3,7],2,9],[6],1]] [[],[],[],[]] [[8,1],[],[6,[[2,7,5,9],[4],7],[5,3,[1,7,1,2],3]]] [[2,5,7,[0,[7,4,0]]],[],[1,[7,3],9,9],[]] [[4,[],5,[[4,2,8],[7,2,8,9],[10,4,2,0],6,2]],[0,[[6],[7,0,6,7],8],[2,[2]],[],9]] [[1,[7,[2,0,7],8]],[8],[],[[[],0,6,[7,7,5,7],[6,7]],10],[0,[3,[8]],[3,[6],[9],[6],[4,5,0,1,1]],7]] [[[[],[2,8],[8],[1,6,3]],[6,[4,9,10,1],0],[[3,4,3],7,[9],[1,1,10,7]],3],[[[7,5,7,1],[7,5],6,5,[6,5,7,4,4]],4,2],[],[6,[],10]] [[5,[[1,4,1,6,9]],2],[[[],8],3,[[10,0,10]]],[[[4,7],4],4,[[7,3,2],[]]],[3]] [[1],[],[],[2,[[7,6],10,3,2],3,[[3,0,5,6],[1,8,9],[3,8,7]]]] [[2,[[6,10,6,7,8],[9,10,2,4,8],6],7],[[1]]] [[],[3,[6,[],7,9,[1]]]] [[[],5,7,[7,[10]],[8,10,7]],[[8],[6,[7,2,4,9]],[0,[10,1,8],8],[7,[10,0,8],[5,9,4],[],[5,1,1,7]]],[[[8],4,[],[]],1,3,8]] [[[7,[8,1,6,9],4],8,[[4,1,9,3,7],[9,7,8,4,10],8],8]] [[[3]],[9,1,4,[4,[7,1,1,6,0],4,[]]],[4,9,[6,[2,9,8],[4],6,[5,10,9,0]],1]] [[10,[],[[4]]],[[[4,4,3,2,9],6],1],[[6,[3],[3,6,2,5],1,[]],[[],[5,4,3,8],[2],8,[6]],8,8],[8,8]] [[],[1,[[2,0,10,0,8],[2,10,7,9,9],4,[7,9],[2,6,6,7]]]] [[4,[5],[],[[],[],0,1,10],2],[[0,7,[3],[7,4,7,4]],8],[[[6],[3,1],5,[],[1,1,7,0]],5],[[2,[10,3,4],[0,9,5,1,1],0,4],9,[5,[2,5,6,0],[2,5,3,3],4,7],3,[0,[10]]]] [[3,1,8,7,[7,0]],[[[5,4,4,10],2,[3,1,6,4]],[],10,9],[6,9,[4,[3,9]]]] [[],[[[]],[3,[8,4,4,4],3,2,[9,1,5,2]],10,[6,9,2,7,8],1]] [[10,[],2,0,7],[[8],4,[[1,5,3,1],1,[0,10],3,2],[[10,5,7,7],[7,8,8,6],[3,5,2,5],[8,0,7,2]]],[[],[4,[3,6,5,2]],[2,[8]]],[0,[10,1,3,[6],9],[6,3,[4,5,6],7],[1,[7,0,3,2],6,0]]] [[[[]],4,[[2,4,3,1,7],[4,5,8,0,0],[1,1,6,2,4]]],[[5,8,[7,2],4,[4,10,0,2,8]],9],[6,[]]] [[[6,[]],3,[0,[3,10,1,6],7,2]],[0]] [[7]] [[8,[[5],2,[2,10,9],[7,8,8]]]] [[[[9,9,0],8,[6,2,7,5,7]],3],[],[]] [[5,6,[9,2,[10,0,2],[5,9,6,10],[5,1,9,9,2]]],[[0,[4],[6,3]],2,[10],[2],7],[[],8,[],[2]],[0,[],[10]]] [[7,3],[[10,10,[],8,3],0,1,[],8],[1],[[5]],[9,9,8,8,[[10,10,3,10,0],9,6]]] [[[],[],2]] [[[8,10,0],1,[[4,6],[7,10,1],2,[8,2,8],[4,1,7]],7]] [[[2,[]],4,5,[4,[2],[]],5],[7,[9,[3,8]],[[10,7,3],8,10,4,8],[[4,10,8,4],7,0],[7,[3,9,9,5,10]]],[6],[0,[[0,8,7,1],7],4,[5]],[[[4,0]],[[10,2,8,5,10],5,4,[],2],1]] [[0,6,[[],9,6],3,[]],[[2,10,10,[3,9],8],[[1,8],6],3,2],[3,4,[9,[9],[3,6]],[5,2,[6],[10,10],[4,4,3,8,0]]]] [[[4],[[9,1,4,4],[],1,[6,10,7],[]]],[[],[8,5],[3,[3,0,0,9,1],[4,7,4,2,0]]],[[],[10,0,[6],[6,3,7],[5,0,10]]]] [[6,8],[3,9,[],[[1],[8],0,0]]] [[7],[],[8,[5,[3,5,6,4],[7,4],4,[10,9,2,1,6]],[9,[2,4],[7,8]]],[[[2,0,2],6,[5],[3,3,9,9],[4,8,8,0,7]],[6,[]],[],[10,[]]]] [[[[2,0,3],10],[7,[],[9,8,7,4,8],7,[4,10,6,10]],8],[7,9,[6,[],[]],2],[[5,1,[8],[10,8,10]],[10],[4,[],[1],6],[1,[],[1,9],[4]],3],[[[7,1,7,9,6]],[],2,[]],[[4],[[4,0,1,1,1],[5,9,10,7],0,[1]],[2,0]]] [[],[[],[[1,0,7,8,2],[4,6,8,10],[6],7,5]]] [[5],[[[1,8,7,5,1],2,7],8],[9,[[10]],[[7,1,0,6,1],[0],[6,9,2,6],[8],5],[5,9,9,[8,5,3,8],[]],2],[1,[5]],[[3,[8,9,8,6],1],[[],[1,8],[10,7,0,8],[5,9,7,8,8],[8,8,2,5,8]],[]]] [[[9,[4,6,0,10],[7],[1,4,1],[10,3]],[[10,10,7]],0],[[6,[0,8,3,1],[0,3],4,5],[4,0,[9,0,1],[0,4,9],7],[[8]],1,[]],[[[],3,2,[]],[9,[6,9,8,8]],5],[7,0,3,8,4],[10]] [[10,[8]],[6,0,[[7],2,0,1]],[[3,[1],[1,3],[1],[6]],8,[[6,8,4]]]] [[[9,[]],6,5,[9,0,[4]],[[1,4,1,8,10],9]],[[6,5,[8,1,7,3,0],[8,3],[]],1],[[[10,4,4],7,[4,8,2,10],[9,10]],1,4,5]] [[[[1,10,0,4,0],2],4,4,6,10],[[3],[0,[6],[0,5,2,1,5],6,[8,1,2,0,1]],[],[6],4],[[[]],[],[4],[9,[3],9],[9,6]],[1,4,6],[0]] [[[7,[2,5],[6,6,7],[9,9],[7,0,9]],0,6,[],[]],[[5,[1,7,10,0],[8,5],[2,5,6,4],7],8],[[[1,2,5,2,6],5],[[]],9,7],[[9,[2,3,9],9,[],[7,0,8,3,5]],[7,[3,2],[]],1,9,[]]] [[2,1],[5,[8,[]]],[]] [[0,2,2,[[4,9,8,10,0],3,5,7,[8,8,1]],[[3,7,8,1],[2,2,10,0,0],[4,5,3],[],6]],[5,[3],1,3],[[8,3,[9,9],[9,0],1],[5]],[[[4,9],1,[5,7,10],[8,7,4,2,2],2],[2,0,[6,1],9],4]] [[2,[3,8,[8],[10]],[[]]],[6]] [[7,[0]],[[7,[2,0],4,4]],[]] [[[[10,9],[3],[7,10,3]]],[]] [[[1,4,3,1,[]],[]],[]] [[],[[[],6,0,[3,4,4,2,10],[2,2,7,8]],[[4,8,3,4,9],0],[],[]],[]] [[3],[[6,2,[2]],3,4,7],[[2,[],[5,9,10],[3],[8]],[[4,2,0],8],4,10,[2]]] [[9,[[7,8,10,9],3,[3],[3,8,3,1,8]]],[[],4,[]]] [[5,6,8,[]],[[8],[],4,9]] [[[],[3]],[9],[],[[5],[],[2,8,10,[7,7,6,2],0],[[],[4,9],[3]]],[[[2,2,5]]]] [[],[[],[5,[4,3,6,7],9,2],[[4,1,8,10,5],6,7]],[[[0],7],[[6,9,2,6,5],7]],[[[0,10,3],[5],7,10],9,8,[[],4,0,[7,2,3]]]] [[3,4,0,[7,7]],[[[2,9],10,9,[2,10,7,0],[7,2,1]],10,0,[5,[],[7],[1,9,2]],[1,3,[],4]]] [[[3,5,6,[0,6,5]],[[],[],[2],1]],[5,[],[4,0,4,[]]],[4],[[[3,7,4,8,7],[0],[1,9,1],[7,9,8,0,6],4]],[[[7,10,5],[5,5,6],0,7,[9]]]] [[[[2,9,7,8,4],2],[8,2,[3],[5,5]],9,[[2],[7,8,9],4,6,[]]],[[],7,[[8,10,2],0],[[4,10,5,7],3,6,[2,6,3,4]],[5]],[10,10,[0,[4,7],[2,1,6,3]]],[9,[4]],[]] [[[3]],[7,[9,[],7,[8,3,1,1]],7]] [[10,[[0,1,4],8],[4],[],9],[5,[7,3,[10,8,4],9],[9,[4,3,8,3],2,[6,6,5,9,0],10],10,[[],[6,3,0,8,7],0,5]],[4,10,[1,[10,3],1,8]],[4,[[],[1,0,8,8,9],3,7],9,[[10,7,1,1],[],[8,2,6],5,[]]]] [[[5,[3,0,3,2],4],[1,[],7,[],[1]],[[10,10,4,0,2],9,[9,3,9,7,5],[4,2]],[7,1,[5,7,8],6,10]],[[[7,2],[9,3,0,6]],[[9,10],[],[10,7],[6,4,7,5]],1,4,[]],[[[7,6,3],5,[0,2]]],[[5,8,3],2,6,[]],[[[10],[],[],8,0],[],[8,6,[7,5,3],[2]],3,[[7,10],5,3]]] [[[[8,6,2,3],9]],[[1,7,1,5,[6,1,1,2]],[],[[4,1,1,9,9],[0,2,5,0,7]],9],[1,[[10,10],6,4,0,0],1,[8],[10,0,9,5,[4,7,3,5]]],[10,[[0,4,8,3,5]]]] [[0,[[5,6,6,7]],[6,3,[6],7,[3,0]],[8]],[2,10,9,5,10]] [[5,1],[7,[2,10,3,5,[10,4,6]]]] [[7,7,9,1,9],[]] [[[],[5,1,[],6,[4,2,2,6,6]],10,[[],[5,8,5],0,[3,2,0,7,8]]],[[[8,10,3,7]],[[2,1,6,1,9]]],[2,7,6,0,[[4,6],10,[3,2,7],0,[]]],[10,[[],3,[9,10]],9,5,[[]]],[[[],[10]],7,6,[[5,0,1,1,5],[]],3]] [[5],[6,[8,[10],4],[8,1],[[10],10,[7]],1]] [[2,[7,[],[],6],[[],3,[]]]] [[],[],[[9,[3,10,0],0,[8]]],[8,[[],5,0,[4,6,5,2,5],8]],[[7],[3],[[9,5],[7,6,7]]]] [[4,2,8],[[[],0,9],2,6,3],[],[[[2,3],[1,0,0,8],1,6],7,6]] [[[[3],10,2,8]],[6,3,[4,0,[7,7,2,9,9],[],5],[[0],3,6]],[8,[[6,7,10],[0,4],[2]],4,0,[]],[[9,[7,3],[0,0,5],4,4]],[1]] [[],[1],[1,[[10,9,2,0],[6,5,7]]],[10]] [[[5,[3,6],4,[]],8,2,10,[[7,0,0,7],7]]] [[[],[[],8,1],[1],8],[],[3],[1,10],[3,[],[[4,0,10,8],2,3,[5]]]] [[[[3,9,8]]],[[[0],9,[3,9,6,10],3]]] [[7,9,9,[],8],[[1,4]],[[1,[9,2,6,3],[1,4,6,0,2],4,[7,0]],9,[[3,2,1,9],[4,10,10],[7,7,5],[10,4,9,3,8],3],[[7,1,7,0,3],[10,2,7,0],5,[10,4,5]],[1,[8,3,2,0,0],7]],[2,[]],[]] [[[[5,5,1,8,5],[2,6,0],[3]],[1,3,[4,5,2,1],6],[[7,4,8,5],10,[10,3]],0]] [[[4,8],0,2,[[3]]],[[4,4,8],9,10],[3,3,4,[[],7],[[6]]]] [[8,[],[4,5,0,[1,5,5,6,6],[3,5,9,1,6]]],[[],6,8],[[2,9,[6,1,2,1,1]],[]],[9,6,3,1,2]] [[],[[[5,9,1,1,3],7,[10,0,5,7,5],[8,8]],4,7,[[2,10,8,4],[9,5,9,6],[]],8],[8,[[1,5,5,9]]],[5,6]] [[7,0],[[[5],[],7]],[5],[10],[6,0]] [[],[]] [[[],[],[7,4,7,[6,6,1]],[3,9,8,0,[5,2,3]],3],[[[1],1,7],[6,2,3],[1,[6,8,3,1,9],[]],[3,7,7,5,[2,2,3,5,9]],[4,5]]] [[4,[[8,6,3,10,0],2]],[9,[5,10,9,[3,1,0,8],3],1,8],[]] [[],[],[9,[[2,4,7,0],8,[],7,2],4,5,1]] [[2,[7,[3,8],[7,2,3],7,[7,6,7,4]]],[0],[6,[7,[10,10,5],8],[7,[10,7,6],[9],3,9],10],[[[10,7],[2]],[6,[7,5,8],1,6,[10,0]]],[[],[1],[],[10,[10,3,4,8],6,[7,0,3]]]] [[[[6,2,1]],2,1],[],[[1,[],0],0],[[8,[3,0,4,4],[7,7,10,9,1],2,[9]]]] [[3],[],[],[2,0,1],[10]] [[2,[10,[],[1,0,5,4],[],1]],[4,[2]],[[4,2,4],4,[2],7],[[],[[1,4,7,10,6],[3]],[],1,[2,6,6]]] [[],[],[],[0,[[2,0],[2,6,10,0],5,[0,3,7,6,4]],[10,7],3,5],[2,2,[2,1,[5,2,2,8]]]] [[[5],7,[5,[9,7,9],1]],[3]] [[[5,[5,8,0,2]],[10,6],1,6,[7,2,[],3,8]]] [[[7,5,3,6],[6,[3],4,[]],[[3],[],[5,5],[0]],[[10,0,3,8,7],[5,3,6],[8,4,5],8,4]],[[7,7],[10,[10,7,6],[9,7,5,5],[4],9],0,[2],[]],[[],4,4,[1,0,[],0],[[5,4],0,[0],8,1]],[8,[4,[7,0]],[8,10,0,7],[[6,6],10,[8,1],4]]] [[],[[[],3,8],[4,8,9,[3]]],[],[2,1,10,[],[5]]] [[[[3],1,[9,5],5,7],9,2],[2],[[0]],[],[[[7],10,9,[9,6,2]],[[10,1],8]]] [[],[],[[10],[[],[4],[0,2,1,4],[8,7,4,3],6],[9,[2]],[]],[[[10,5,3,1,9],0],[2,1,[7,7,8,9,1],5,[7,3,1,9]]]] [[10,[5]],[]] [[7,2,[[],[2,1,0,1,9],6,[10,6,7,1]],[[],[6,6,1,2],[6],6,[8,2,2,10,8]],9],[6,[6,[3,5,0],[1,0,0,2],[5,9,8,1]]],[],[[[],8,0,[0,5,1,0,6]],[[3,5,9],8,0,0,[10,3]],[]],[8,[],[[2],10,8,[1,10,10,10]]]] [[1,[[8,5,10,0,3],8,8],6]] [[[],[],5,9,[[],3]],[[[],[],[10,3,2,6]]],[[6]]] [[[[0]],1,2,[[0],[10,6,7],[8,2,9,4,9],[6],[0,7,6,6]]],[6,3,[[8,6,8,9],[8],8,9],[2]]] [[6,[],5],[10],[5,3,8,[[7,1,2,1],[7,7,2],3]],[[4],[9,[5,6],10,3]]] [[[1,7],0]] [[5,[]],[],[],[],[6,[[],0,[6,10,7,5],9],[[3],6,2,[7,8,8,1,6],7]]] [[[2],0,[8,[5,6,2],1,3],[[7],10,[8,8]],[[8,5,4,7],9,[7,3,2,7,0]]],[1,[[2,6]],[5,6,8,[8,1,7,0,7]]],[3,7]] [[8,1],[0,5],[],[]] [[8,6,[5]],[],[[],4,[[9,2]],4,[[9,10],[9,7,7],[6,6,5]]],[[[9,7,9,10],3,[1,5,2,6]],0],[[[10,1,7],[5,3,0],[]],1,[8,0,[9,6,7,5,0],[],[6,1]],[[8,7,2,1],7,1,4,10],[[5,6,8,5],[8,10,7,6,9],9,1,[]]]] [[[],[],7,6,3],[6,3,6,10],[[],[],[6,1,[7,9,8,2],[10]],3],[[]]] [[2,[9,2],[[0,0,8,5]],7]] [[[7,5,2,5,3],1,[[],2,[],9],[[4,0,10,6,6],2],2],[[],[]]] [[4],[]] [[[4,6,[7,9],9],6,[[0,10],[10,8,1],[6],[3,10,9]],3],[10,[[]]],[8,9,7]] [[[8,8,[9,4,4,5],[8],3]],[],[10,10,3],[[[1],[5,0,2],0],3,[[4,1]],[[4,7,5],5,[]]]] [[[1,0,[],[10,2,7,5,3]],1],[[8,[7,6,3,5,6],[8,5,3,8]],9,[3,10],[1,2,[],5,1],[]],[[3,2,[],[1,4],[10]]],[]] [[],[[0,2,9,7],5],[9]] [[5],[[]],[[[0,7,2],[5,6,6],[6,10,9,9,7],8],[],10]] [[[[0],[6,2,8],[1,0,8,9],[]],[9],1],[10,4],[5,7,6,1],[]] [[[[6,10,7],[2],[3,0,2,9]],9,[[5,8,1,1,4],5,4,[0,2,4],[2,3,6,4]],[[10],[10,0,1]]]] [[[6],5],[[2,1]]] [[10,[5,[1]],5],[[[1,4,6,6,7],[2,5],4,[5,3,5,3,7]]]] [[9,[3,[],[],[3]],7,1],[[6,9,0,2,[8,8,10]],10,8,[]],[]] [[[6],[[10,9],5,[7],[7],[10,5,9]],0,[[10],[4,9],6,[0,1,4,10]],8]] [[0,[0],[],5],[],[[[9,8],[6,3,1,3],7,8,[]],2,[[4,0,3]],[6]],[7,[[10,2,0,1],9,2],[[9,7,0,4,10],10,[3,10],5,6]]] [[0,0],[1,[],2],[6,4,5],[5]] [[7,[[0],5],5],[5,[[4,3,8,4,0],[8,7,0],7],[],[[],10,5]]] [[],[5,2,[[5,2,4,8,5],9,6],[],[[8,5,5,4,10],8]],[[],[[1,7,4],[6,4,7],[10,1,10,7,3],[1,4,10,4],[]],[9,[5,0,10,5,9]]],[],[6,3,[10,[0,10,0,10]],2]] [[],[[[8,7,10],1],[[5,2,8],[8,8,10],10],[[],8,[7,10,4]]],[[],[3,10,[7,0,8,4,6],2],10,[[6,6,5]],2]] [[],[1,[[],9,3,[1,2],[]],[10,1,7,[7,9,0,1,2]],3,3],[1,8,[[5,1,7]],6,[[9,1,3],[7]]],[7]] [[[[],5],3,[],3],[[[],5],[[2,3,0,8,5],8],[[],3],3,0],[[[9,9,2,2]],7,5,2],[2,[],[8,6,[5,1,2],[9,0,7],[10,2,0]]]] [[[10,2,7]]] [[4,[6],[[8,1]],[]],[[3],2],[[[],[7,0],[],[9,1],[4,2]],10,5],[7],[2]] [[[10,[10,3],[],4,[]],6],[[],0,[[],[8,7,8,2],3,[2,6,8,8],3],8,[[4,5,5,5,1],[1,4,6],[5,8,0],9]]] [[],[5,[[4,4]],[[8,3,3,9]],[]],[1,2],[5,1,[[8,9,7,0,8],[10,2,0,4],0,7],1]] [[6,[[1,6,0,0],1],[8,9,5],4,0],[[[3,7,10,3]]]] [[7,[6,[5,0],10,8],[0,9,[7,10,5,7,4],6],[7,[8,0,0,4,3],[7,10,8]],2],[[1,1,4],[[10]]]] [[[9,[6,2,5,1,1],5],6,10,9,9]] [[[2,7,3]]] [[],[],[7],[2,[[2],[1,1,2]],4,[3,2]],[6,[10,1,9,3],9]] [[3,2],[],[[[],[4,6],[7,1,10,4],3,9],[8,[8],[1,7],[4,5,1,1],[]],9,0,9],[1,[[1,9],[0,4,1],[2,8],[],0],[[0,0,3],[9,8,1],[5],4]],[[4,[4,10,2],[]]]] [4,6,9,10] [4,6,9,10,4] [[],[],[2,9],[]] [[7,9,10],[2,[[8,2,3],[1,4,1,4,10],7],5,[[6,8,0,5,1],[8,10,9],1],2],[9],[[]]] [[[[],[9],[],[7]],[0,0],5]] [[],[3,8,[5,5,9]],[7,1,[10,[]]],[[1,5]]] [[],[9,10,10],[6,[[5,0,0],9]],[0]] [[[],4]] [[4,10,10]] [[5],[9,8,10,[[2,1,8,7,4],[],7,9,[]]],[9,[],[4]],[],[[10]]] [[3,3,[],0],[],[[1,7,0],[],[7,5,[7,6]],[[3],[7,8]]],[4],[7]] [[[6,[7,7,5,1,4],2,10]],[],[[7,10,[],5],[8],10],[4,[[5,1]],[]]] [[1,2,4,10],[],[[10,[7,10,7,10],[8],6],[[0,6,7,6,1],2,8,8,7]],[],[]] [[9,10],[7]] [[[7,6,[9,9,3,3]]]] [[0,3],[[],8,4],[1],[[[],8,[6,1,3,0]]],[[0,1,7,0,[6,2,8,5]],[[7,7,7],[2,7],3,10,6],0,[[9,5,2,5],6,[4]],6]] [[4,6,4,10,[]],[],[]] [[],[[],[[3,8,7],1,[6,0,3,3],[6,9],[9,7,10,6]],10,[0,7,2]],[[[9,6,6],1,[],[6,9,4,0]]],[[[6,5,3,7,4]],[],[7],[8,8,[1,5,2,7,7]]]] [[[[5,1,2,2,9]],[3,5,6,[7,10]],7,[8,[9,10,3],[3,10,4,2,1]],[[5,3,4,10,3],[10,1],7,1,[]]],[[[8,8,8],9,[],3,[2,9]],9,[5,5,[10,9,5,1,1],[],4]]] [[[9,10,[4],[]],[10]],[[],9,4,[[9],[1],[5,10,4],2,[0,4,7,10]]],[2,2,5,[[6,0],2,[8,7]]]] [[],[],[6,9,7],[1,[[8],[],5,[3,1]],[[2,5],10,[],3]]] [[[5,[7,0,7,10,5],5,0],1,6],[0,8],[1,0,[[3],[9],[1,3,4,5,3],10],[],5]] [[6,3,[[3,2,9,3]],[]],[[],2,5],[],[1,6,3],[9]] [[9]] [[2,4,[6,[6],[2,8]],[[7,10,7,3]]],[9,4,[],7,2]] [[9],[],[8,[[5,10,6],1],7,0,2]] [[1,5,[5,9,[3,0]],[9,[5,6],[8],[8,1,8,0]],10],[9,[0]]] [[4,5,[3,8]]] [[],[[[]],[[6,5,7],2,[0,0,3,0]]]] [[6,[],1,2],[[[10,4,1,6,9],[8,8,1,7,8],[]],1,10,2]] [[2,[10,0,1,[5,7,9,10,10],[10]]],[0,[9,0,6,6],4,0],[2,[10,[],[],1],[[2,10],[9,7],[5,4,10]],7,[[8,10,1],5,9,[8,3,2,1]]],[2,[[6,8,3]]],[0,1]] [[8,[4,[5,1,5]],5,5,9],[],[[4,4,[]]]] ================================================ FILE: exm/aoc/2022/aoc_2022_13_questions.txt ================================================ --- Day 13: Distress Signal --- You climb the hill and again try contacting the Elves. However, you instead receive a signal you weren't expecting: a distress signal. Your handheld device must still not be working properly; the packets from the distress signal got decoded out of order. You'll need to re-order the list of received packets (your puzzle input) to decode the message. Your list consists of pairs of packets; pairs are separated by a blank line. You need to identify how many pairs of packets are in the right order. For example: [1,1,3,1,1] [1,1,5,1,1] [[1],[2,3,4]] [[1],4] [9] [[8,7,6]] [[4,4],4,4] [[4,4],4,4,4] [7,7,7,7] [7,7,7] [] [3] [[[]]] [[]] [1,[2,[3,[4,[5,6,7]]]],8,9] [1,[2,[3,[4,[5,6,0]]]],8,9] Packet data consists of lists and integers. Each list starts with [, ends with ], and contains zero or more comma-separated values (either integers or other lists). Each packet is always a list and appears on its own line. When comparing two values, the first value is called left and the second value is called right. Then: If both values are integers, the lower integer should come first. If the left integer is lower than the right integer, the inputs are in the right order. If the left integer is higher than the right integer, the inputs are not in the right order. Otherwise, the inputs are the same integer; continue checking the next part of the input. If both values are lists, compare the first value of each list, then the second value, and so on. If the left list runs out of items first, the inputs are in the right order. If the right list runs out of items first, the inputs are not in the right order. If the lists are the same length and no comparison makes a decision about the order, continue checking the next part of the input. If exactly one value is an integer, convert the integer to a list which contains that integer as its only value, then retry the comparison. For example, if comparing [0,0,0] and 2, convert the right value to [2] (a list containing 2); the result is then found by instead comparing [0,0,0] and [2]. Using these rules, you can determine which of the pairs in the example are in the right order: == Pair 1 == - Compare [1,1,3,1,1] vs [1,1,5,1,1] - Compare 1 vs 1 - Compare 1 vs 1 - Compare 3 vs 5 - Left side is smaller, so inputs are in the right order == Pair 2 == - Compare [[1],[2,3,4]] vs [[1],4] - Compare [1] vs [1] - Compare 1 vs 1 - Compare [2,3,4] vs 4 - Mixed types; convert right to [4] and retry comparison - Compare [2,3,4] vs [4] - Compare 2 vs 4 - Left side is smaller, so inputs are in the right order == Pair 3 == - Compare [9] vs [[8,7,6]] - Compare 9 vs [8,7,6] - Mixed types; convert left to [9] and retry comparison - Compare [9] vs [8,7,6] - Compare 9 vs 8 - Right side is smaller, so inputs are not in the right order == Pair 4 == - Compare [[4,4],4,4] vs [[4,4],4,4,4] - Compare [4,4] vs [4,4] - Compare 4 vs 4 - Compare 4 vs 4 - Compare 4 vs 4 - Compare 4 vs 4 - Left side ran out of items, so inputs are in the right order == Pair 5 == - Compare [7,7,7,7] vs [7,7,7] - Compare 7 vs 7 - Compare 7 vs 7 - Compare 7 vs 7 - Right side ran out of items, so inputs are not in the right order == Pair 6 == - Compare [] vs [3] - Left side ran out of items, so inputs are in the right order == Pair 7 == - Compare [[[]]] vs [[]] - Compare [[]] vs [] - Right side ran out of items, so inputs are not in the right order == Pair 8 == - Compare [1,[2,[3,[4,[5,6,7]]]],8,9] vs [1,[2,[3,[4,[5,6,0]]]],8,9] - Compare 1 vs 1 - Compare [2,[3,[4,[5,6,7]]]] vs [2,[3,[4,[5,6,0]]]] - Compare 2 vs 2 - Compare [3,[4,[5,6,7]]] vs [3,[4,[5,6,0]]] - Compare 3 vs 3 - Compare [4,[5,6,7]] vs [4,[5,6,0]] - Compare 4 vs 4 - Compare [5,6,7] vs [5,6,0] - Compare 5 vs 5 - Compare 6 vs 6 - Compare 7 vs 0 - Right side is smaller, so inputs are not in the right order What are the indices of the pairs that are already in the right order? (The first pair has index 1, the second pair has index 2, and so on.) In the above example, the pairs in the right order are 1, 2, 4, and 6; the sum of these indices is 13. Determine which pairs of packets are already in the right order. What is the sum of the indices of those pairs? --- Part Two --- Now, you just need to put all of the packets in the right order. Disregard the blank lines in your list of received packets. The distress signal protocol also requires that you include two additional divider packets: [[2]] [[6]] Using the same rules as before, organize all packets - the ones in your list of received packets as well as the two divider packets - into the correct order. For the example above, the result of putting the packets in the correct order is: [] [[]] [[[]]] [1,1,3,1,1] [1,1,5,1,1] [[1],[2,3,4]] [1,[2,[3,[4,[5,6,0]]]],8,9] [1,[2,[3,[4,[5,6,7]]]],8,9] [[1],4] [[2]] [3] [[4,4],4,4] [[4,4],4,4,4] [[6]] [7,7,7] [7,7,7,7] [[8,7,6]] [9] Afterward, locate the divider packets. To find the decoder key for this distress signal, you need to determine the indices of the two divider packets and multiply them together. (The first packet is at index 1, the second packet is at index 2, and so on.) In this example, the divider packets are 10th and 14th, and so the decoder key is 140. Organize all of the packets into the correct order. What is the decoder key for the distress signal? ================================================ FILE: exm/aoc/2022/aoc_2022_14.adb ================================================ -- Solution to Advent of Code 2022, Day 14 ------------------------------------------- -- Regolith Reservoir -- -- https://adventofcode.com/2022/day/14 -- Copy of questions in: aoc_2022_14_questions.txt -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_14 is use HAT, AoC_Toolbox; subtype Range_x is Integer range 300 .. 800; subtype Range_y is Integer range 0 .. 200; map : array (Range_x, Range_y) of Character; m, n : Point; procedure Adapt_Top_Left_Corner (using : Point) is begin m.x := Min (m.x, using.x); m.y := Min (m.y, using.y); end Adapt_Top_Left_Corner; procedure Adapt_Bottom_Right_Corner (using : Point) is begin n.x := Max (n.x, using.x); n.y := Max (n.y, using.y); end Adapt_Bottom_Right_Corner; procedure Show (title : VString) is begin New_Line; Put_Line (title); New_Line; Put_Line (+" x is in range: " & m.x & " .. " & n.x); Put_Line (+" y is in range: " & m.y & " .. " & n.y); New_Line; for y in m.y .. n.y loop Put (" "); for x in m.x .. n.x loop Put (map (x, y)); end loop; New_Line; end loop; end Show; procedure Data_Acquisition (enhanced : Boolean) is p1, p2, p : Point; arrow : String (1 .. 4) := " -> "; sep : Character; f : File_Type; begin m.x := Range_x'Last; m.y := 0; n.x := Range_x'First; n.y := Range_y'First; for x in Range_x loop for y in Range_y loop map (x, y) := '.'; end loop; end loop; Open (f, "aoc_2022_14.txt"); Read_Data : while not End_Of_File (f) loop Get (f, p1.x); Get (f, sep); Get (f, p1.y); Adapt_Top_Left_Corner (p1); Adapt_Bottom_Right_Corner (p1); map (p1.x, p1.y) := '#'; loop Get (f, arrow); Get (f, p2.x); Get (f, sep); Get (f, p2.y); Adapt_Top_Left_Corner (p2); Adapt_Bottom_Right_Corner (p2); p := p1; for count in 1 .. Dist_L1 (p1, p2) loop p.x := p.x + Sgn (p2.x - p1.x); p.y := p.y + Sgn (p2.y - p1.y); map (p.x, p.y) := '#'; end loop; exit when End_Of_Line (f); p1 := p2; end loop; end loop Read_Data; Close (f); if enhanced then -- Added a layer of rock 2 units below: p.y := n.y + 2; p.x := m.x - p.y; Adapt_Top_Left_Corner (p); p.x := n.x + p.y; Adapt_Bottom_Right_Corner (p); for x in m.x .. n.x loop map (x, p.y) := '@'; end loop; end if; end Data_Acquisition; pouring_point : Point; full_or_blocked : Boolean; procedure Simulate_Sand_Unit is p : Point := pouring_point; begin full_or_blocked := False; if map (p.x, p.y) = 'o' then -- Source is blocked! full_or_blocked := True; return; end if; loop if map (p.x, p.y + 1) = '.' then -- Cell below is free -> fall further. p.y := p.y + 1; else -- Obstacle. if map (p.x - 1, p.y + 1) = '.' then -- Move diagonally (left). p.x := p.x - 1; p.y := p.y + 1; elsif map (p.x + 1, p.y + 1) = '.' then -- Move diagonally (right). p.x := p.x + 1; p.y := p.y + 1; else -- Sand unit cannot move anymore. map (p.x, p.y) := 'o'; -- Displayed portion of the map may increase: Adapt_Top_Left_Corner (p); exit; end if; end if; if p.y = n.y then -- Reach floor level: will "fall into the endless void". full_or_blocked := True; exit; end if; end loop; end Simulate_Sand_Unit; compiler_test_mode : constant Boolean := Argument_Count >= 1; verbose : constant Boolean := False; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; begin pouring_point.x := 500; pouring_point.y := 0; Parts : for part in 1 .. 2 loop Data_Acquisition (part = 2); if verbose then Show (+"Initial:"); end if; for step in Positive loop Simulate_Sand_Unit; if verbose and then n.y < 100 then Show (+"Sand unit #" & step & ':'); end if; if full_or_blocked then r (part) := step - 1; -- ^ "- 1" is because "How many units of sand come to rest -- *before* sand starts flowing into the abyss below" exit; end if; end loop; if verbose then Show (+"Final:"); end if; exit Parts when compiler_test_mode; -- Skip part 2. end loop Parts; if compiler_test_mode then if r (1) /= Integer'Value (To_String (Argument (1))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Number of sand units for..."); Put_Line (+" (part 1): original map: " & r (1)); Put_Line (+" (part 2): enhanced map: " & r (2)); -- Part 1: validated by AoC: 964 -- Part 2: validated by AoC: 32041 end if; end AoC_2022_14; ================================================ FILE: exm/aoc/2022/aoc_2022_14.txt ================================================ 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 534,94 -> 538,94 519,92 -> 523,92 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 499,27 -> 499,28 -> 515,28 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 525,88 -> 529,88 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 533,116 -> 537,116 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 523,70 -> 528,70 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 542,107 -> 542,104 -> 542,107 -> 544,107 -> 544,101 -> 544,107 -> 546,107 -> 546,100 -> 546,107 540,126 -> 540,127 -> 543,127 -> 543,126 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 560,161 -> 565,161 540,94 -> 544,94 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 542,107 -> 542,104 -> 542,107 -> 544,107 -> 544,101 -> 544,107 -> 546,107 -> 546,100 -> 546,107 554,167 -> 559,167 544,170 -> 544,174 -> 536,174 -> 536,182 -> 554,182 -> 554,174 -> 549,174 -> 549,170 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 542,107 -> 542,104 -> 542,107 -> 544,107 -> 544,101 -> 544,107 -> 546,107 -> 546,100 -> 546,107 542,107 -> 542,104 -> 542,107 -> 544,107 -> 544,101 -> 544,107 -> 546,107 -> 546,100 -> 546,107 533,122 -> 533,123 -> 541,123 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 543,164 -> 548,164 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 523,44 -> 523,48 -> 517,48 -> 517,55 -> 530,55 -> 530,48 -> 525,48 -> 525,44 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 525,92 -> 529,92 525,119 -> 537,119 -> 537,118 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 530,70 -> 535,70 516,94 -> 520,94 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 544,170 -> 544,174 -> 536,174 -> 536,182 -> 554,182 -> 554,174 -> 549,174 -> 549,170 525,119 -> 537,119 -> 537,118 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 544,170 -> 544,174 -> 536,174 -> 536,182 -> 554,182 -> 554,174 -> 549,174 -> 549,170 528,90 -> 532,90 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 533,67 -> 538,67 546,161 -> 551,161 537,70 -> 542,70 542,107 -> 542,104 -> 542,107 -> 544,107 -> 544,101 -> 544,107 -> 546,107 -> 546,100 -> 546,107 532,61 -> 537,61 499,27 -> 499,28 -> 515,28 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 534,90 -> 538,90 531,88 -> 535,88 556,158 -> 561,158 525,61 -> 530,61 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 541,130 -> 541,133 -> 537,133 -> 537,138 -> 548,138 -> 548,133 -> 545,133 -> 545,130 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 546,141 -> 546,144 -> 541,144 -> 541,152 -> 554,152 -> 554,144 -> 550,144 -> 550,141 523,44 -> 523,48 -> 517,48 -> 517,55 -> 530,55 -> 530,48 -> 525,48 -> 525,44 533,122 -> 533,123 -> 541,123 546,141 -> 546,144 -> 541,144 -> 541,152 -> 554,152 -> 554,144 -> 550,144 -> 550,141 557,164 -> 562,164 552,155 -> 557,155 531,92 -> 535,92 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 544,170 -> 544,174 -> 536,174 -> 536,182 -> 554,182 -> 554,174 -> 549,174 -> 549,170 547,167 -> 552,167 523,44 -> 523,48 -> 517,48 -> 517,55 -> 530,55 -> 530,48 -> 525,48 -> 525,44 542,107 -> 542,104 -> 542,107 -> 544,107 -> 544,101 -> 544,107 -> 546,107 -> 546,100 -> 546,107 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 561,167 -> 566,167 522,64 -> 527,64 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 519,67 -> 524,67 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 523,44 -> 523,48 -> 517,48 -> 517,55 -> 530,55 -> 530,48 -> 525,48 -> 525,44 550,164 -> 555,164 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 516,70 -> 521,70 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 523,44 -> 523,48 -> 517,48 -> 517,55 -> 530,55 -> 530,48 -> 525,48 -> 525,44 536,64 -> 541,64 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 539,110 -> 543,110 529,64 -> 534,64 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 528,86 -> 532,86 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 540,126 -> 540,127 -> 543,127 -> 543,126 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 545,116 -> 549,116 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 546,141 -> 546,144 -> 541,144 -> 541,152 -> 554,152 -> 554,144 -> 550,144 -> 550,141 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 544,170 -> 544,174 -> 536,174 -> 536,182 -> 554,182 -> 554,174 -> 549,174 -> 549,170 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 541,130 -> 541,133 -> 537,133 -> 537,138 -> 548,138 -> 548,133 -> 545,133 -> 545,130 568,167 -> 573,167 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 546,141 -> 546,144 -> 541,144 -> 541,152 -> 554,152 -> 554,144 -> 550,144 -> 550,141 546,141 -> 546,144 -> 541,144 -> 541,152 -> 554,152 -> 554,144 -> 550,144 -> 550,141 553,161 -> 558,161 541,130 -> 541,133 -> 537,133 -> 537,138 -> 548,138 -> 548,133 -> 545,133 -> 545,130 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 546,141 -> 546,144 -> 541,144 -> 541,152 -> 554,152 -> 554,144 -> 550,144 -> 550,141 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 540,67 -> 545,67 541,130 -> 541,133 -> 537,133 -> 537,138 -> 548,138 -> 548,133 -> 545,133 -> 545,130 546,141 -> 546,144 -> 541,144 -> 541,152 -> 554,152 -> 554,144 -> 550,144 -> 550,141 523,44 -> 523,48 -> 517,48 -> 517,55 -> 530,55 -> 530,48 -> 525,48 -> 525,44 522,90 -> 526,90 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 528,58 -> 533,58 549,158 -> 554,158 542,107 -> 542,104 -> 542,107 -> 544,107 -> 544,101 -> 544,107 -> 546,107 -> 546,100 -> 546,107 541,130 -> 541,133 -> 537,133 -> 537,138 -> 548,138 -> 548,133 -> 545,133 -> 545,130 523,44 -> 523,48 -> 517,48 -> 517,55 -> 530,55 -> 530,48 -> 525,48 -> 525,44 526,67 -> 531,67 540,167 -> 545,167 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 544,170 -> 544,174 -> 536,174 -> 536,182 -> 554,182 -> 554,174 -> 549,174 -> 549,170 544,170 -> 544,174 -> 536,174 -> 536,182 -> 554,182 -> 554,174 -> 549,174 -> 549,170 541,130 -> 541,133 -> 537,133 -> 537,138 -> 548,138 -> 548,133 -> 545,133 -> 545,130 541,130 -> 541,133 -> 537,133 -> 537,138 -> 548,138 -> 548,133 -> 545,133 -> 545,130 540,126 -> 540,127 -> 543,127 -> 543,126 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 542,113 -> 546,113 528,94 -> 532,94 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 522,94 -> 526,94 539,116 -> 543,116 544,70 -> 549,70 542,107 -> 542,104 -> 542,107 -> 544,107 -> 544,101 -> 544,107 -> 546,107 -> 546,100 -> 546,107 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 536,113 -> 540,113 537,92 -> 541,92 507,41 -> 507,39 -> 507,41 -> 509,41 -> 509,35 -> 509,41 -> 511,41 -> 511,34 -> 511,41 -> 513,41 -> 513,40 -> 513,41 -> 515,41 -> 515,38 -> 515,41 -> 517,41 -> 517,31 -> 517,41 -> 519,41 -> 519,33 -> 519,41 -> 521,41 -> 521,32 -> 521,41 -> 523,41 -> 523,39 -> 523,41 513,83 -> 513,76 -> 513,83 -> 515,83 -> 515,73 -> 515,83 -> 517,83 -> 517,80 -> 517,83 -> 519,83 -> 519,82 -> 519,83 -> 521,83 -> 521,80 -> 521,83 -> 523,83 -> 523,73 -> 523,83 -> 525,83 -> 525,81 -> 525,83 -> 527,83 -> 527,81 -> 527,83 -> 529,83 -> 529,74 -> 529,83 564,164 -> 569,164 490,23 -> 490,17 -> 490,23 -> 492,23 -> 492,14 -> 492,23 -> 494,23 -> 494,20 -> 494,23 -> 496,23 -> 496,18 -> 496,23 -> 498,23 -> 498,19 -> 498,23 -> 500,23 -> 500,20 -> 500,23 -> 502,23 -> 502,17 -> 502,23 -> 504,23 -> 504,14 -> 504,23 -> 506,23 -> 506,18 -> 506,23 -> 508,23 -> 508,15 -> 508,23 ================================================ FILE: exm/aoc/2022/aoc_2022_14_questions.txt ================================================ --- Day 14: Regolith Reservoir --- The distress signal leads you to a giant waterfall! Actually, hang on - the signal seems like it's coming from the waterfall itself, and that doesn't make any sense. However, you do notice a little path that leads behind the waterfall. Correction: the distress signal leads you behind a giant waterfall! There seems to be a large cave system here, and the signal definitely leads further inside. As you begin to make your way deeper underground, you feel the ground rumble for a moment. Sand begins pouring into the cave! If you don't quickly figure out where the sand is going, you could quickly become trapped! Fortunately, your familiarity with analyzing the path of falling material will come in handy here. You scan a two-dimensional vertical slice of the cave above you (your puzzle input) and discover that it is mostly air with structures made of rock. Your scan traces the path of each solid rock structure and reports the x,y coordinates that form the shape of the path, where x represents distance to the right and y represents distance down. Each path appears as a single line of text in your scan. After the first point of each path, each point indicates the end of a straight horizontal or vertical line to be drawn from the previous point. For example: 498,4 -> 498,6 -> 496,6 503,4 -> 502,4 -> 502,9 -> 494,9 This scan means that there are two paths of rock; the first path consists of two straight lines, and the second path consists of three straight lines. (Specifically, the first path consists of a line of rock from 498,4 through 498,6 and another line of rock from 498,6 through 496,6.) The sand is pouring into the cave from point 500,0. Drawing rock as #, air as ., and the source of the sand as +, this becomes: 4 5 5 9 0 0 4 0 3 0 ......+... 1 .......... 2 .......... 3 .......... 4 ....#...## 5 ....#...#. 6 ..###...#. 7 ........#. 8 ........#. 9 #########. Sand is produced one unit at a time, and the next unit of sand is not produced until the previous unit of sand comes to rest. A unit of sand is large enough to fill one tile of air in your scan. A unit of sand always falls down one step if possible. If the tile immediately below is blocked (by rock or sand), the unit of sand attempts to instead move diagonally one step down and to the left. If that tile is blocked, the unit of sand attempts to instead move diagonally one step down and to the right. Sand keeps moving as long as it is able to do so, at each step trying to move down, then down-left, then down-right. If all three possible destinations are blocked, the unit of sand comes to rest and no longer moves, at which point the next unit of sand is created back at the source. So, drawing sand that has come to rest as o, the first unit of sand simply falls straight down and then stops: ......+... .......... .......... .......... ....#...## ....#...#. ..###...#. ........#. ......o.#. #########. The second unit of sand then falls straight down, lands on the first one, and then comes to rest to its left: ......+... .......... .......... .......... ....#...## ....#...#. ..###...#. ........#. .....oo.#. #########. After a total of five units of sand have come to rest, they form this pattern: ......+... .......... .......... .......... ....#...## ....#...#. ..###...#. ......o.#. ....oooo#. #########. After a total of 22 units of sand: ......+... .......... ......o... .....ooo.. ....#ooo## ....#ooo#. ..###ooo#. ....oooo#. ...ooooo#. #########. Finally, only two more units of sand can possibly come to rest: ......+... .......... ......o... .....ooo.. ....#ooo## ...o#ooo#. ..###ooo#. ....oooo#. .o.ooooo#. #########. Once all 24 units of sand shown above have come to rest, all further sand flows out the bottom, falling into the endless void. Just for fun, the path any new sand takes before falling forever is shown here with ~: .......+... .......~... ......~o... .....~ooo.. ....~#ooo## ...~o#ooo#. ..~###ooo#. ..~..oooo#. .~o.ooooo#. ~#########. ~.......... ~.......... ~.......... Using your scan, simulate the falling sand. How many units of sand come to rest before sand starts flowing into the abyss below? --- Part Two --- You realize you misread the scan. There isn't an endless void at the bottom of the scan - there's floor, and you're standing on it! You don't have time to scan the floor, so assume the floor is an infinite horizontal line with a y coordinate equal to two plus the highest y coordinate of any point in your scan. In the example above, the highest y coordinate of any point is 9, and so the floor is at y=11. (This is as if your scan contained one extra rock path like -infinity,11 -> infinity,11.) With the added floor, the example above now looks like this: ...........+........ .................... .................... .................... .........#...##..... .........#...#...... .......###...#...... .............#...... .............#...... .....#########...... .................... <-- etc #################### etc --> To find somewhere safe to stand, you'll need to simulate falling sand until a unit of sand comes to rest at 500,0, blocking the source entirely and stopping the flow of sand into the cave. In the example above, the situation finally looks like this after 93 units of sand come to rest: ............o............ ...........ooo........... ..........ooooo.......... .........ooooooo......... ........oo#ooo##o........ .......ooo#ooo#ooo....... ......oo###ooo#oooo...... .....oooo.oooo#ooooo..... ....oooooooooo#oooooo.... ...ooo#########ooooooo... ..ooooo.......ooooooooo.. ######################### Using your scan, simulate the falling sand until the source of the sand becomes blocked. How many units of sand come to rest? ================================================ FILE: exm/aoc/2022/aoc_2022_15.adb ================================================ -- Solution to Advent of Code 2022, Day 15 ------------------------------------------- -- Beacon Exclusion Zone -- -- https://adventofcode.com/2022/day/15 -- Copy of questions in: aoc_2022_15_questions.txt -- -- Note: this solution takes an insane amount of time with HAC. -- Fortunately, you can compile it with GNAT and -- the total run-time is there 1.17 seconds on an i7 machine. -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; -- Interfaces is needed for compiling on both -- HAC and GNAT (64-bit integer: Integer_64): with Interfaces; procedure AoC_2022_15 is use AoC_Toolbox, HAT, Interfaces; lowest, highest : Point; procedure Adapt_Lowest_Value_Point (using : Point) is begin lowest.x := Min (lowest.x, using.x); lowest.y := Min (lowest.y, using.y); end Adapt_Lowest_Value_Point; procedure Adapt_Highest_Value_Point (using : Point) is begin highest.x := Max (highest.x, using.x); highest.y := Max (highest.y, using.y); end Adapt_Highest_Value_Point; type Observation is record sensor, beacon : Point; d : Natural; end record; type Storage is array (1 .. 100) of Observation; top : Natural; k : Storage; -- If (x, y) is within topological disc (which is a square, -- geometrically, due to the distance used, L1) around any -- sensor delimited by the distance to the next beacon, then -- it is beacon-free [2] unless it is the point where -- the beacon is [1]. -- NB: the puzzle kindly excludes *two* beacons -- at the same distance of a sensor ("There is never a tie where -- two beacons are the same distance to a sensor"). -- function Beacon_Free (x, y : Integer) return Boolean is p : Point; begin p.x := x; p.y := y; for i in 1 .. top loop if k (i).beacon.x = x and then k (i).beacon.y = y then return False; -- [1] end if; if Dist_L1 (p, k (i).sensor) <= k (i).d then return True; -- [2] end if; end loop; return False; end Beacon_Free; -- Count for x in a given range, and a given y, -- the number of beacon-free points. function Scan_for_Beacon_Free_Range (mx, nx, y : Integer) return Natural is t : Natural := 0; begin for x in mx .. nx loop if Beacon_Free (x, y) then t := t + 1; end if; end loop; return t; end Scan_for_Beacon_Free_Range; -- Count for "any" value of x, and a given y, -- the number of beacon-free points. function Scan_for_Beacon_Free (y : Integer) return Natural is begin return Scan_for_Beacon_Free_Range (lowest.x - (highest.x - lowest.x), highest.x + (highest.x - lowest.x), y); end Scan_for_Beacon_Free; -- name : constant VString := +"mini.txt"; -- y_p1 : constant := 10; -- lim_p2 : constant := 20; name : constant VString := +"aoc_2022_15.txt"; y_p1 : constant := 2_000_000; lim_p2 : constant := 4_000_000; tuning_frequency : Integer_64; procedure Search_Undetected_Beacon is sensor_i : Point; distance_i : Integer; procedure Check (x, y : Integer) is begin if x in 0 .. lim_p2 and then y in 0 .. lim_p2 and then not Beacon_Free (x, y) then tuning_frequency := Integer_64 (x) * 4_000_000 + Integer_64 (y); end if; end Check; begin tuning_frequency := 0; -- -- Since there is only one possible point where the beacon is, -- it is surrounded by beacon-free zones, which are the topological -- discs (geometrically, squares with diagonally-oriented edges) -- around a sensor. -- So it is sufficient to search the point right outside the squares. -- -- Idea from Maxim Reznik, -- https://forum.ada-lang.io/t/2022-day-15-beacon-exclusion-zone/254/2 -- -- The brute force method would check more than 16 trillion points! -- for i in 1 .. top loop sensor_i := k (i).sensor; distance_i := k (i).d; for dx in 0 .. distance_i loop -- Check one unit above the top-right side -- of the square around sensor_i #i. Check (sensor_i.x + dx, sensor_i.y + (distance_i - dx) + 1); -- NB: we should scan the other sides for the special -- case where the searched point is on the edge of -- the given search area, but in the example and our -- data, the point is inside the area, so it is surrounded -- by four squares with one kind edge each touching the point. -- -- 12222233 -- 11222333 -- 1112*433 <--- the point *. The check above will detect it for -- 11114443 square #1. -- 11144444 exit when tuning_frequency > 0; end loop; exit when tuning_frequency > 0; end loop; end Search_Undetected_Beacon; s1 : String (1 .. 12) := "Sensor at x="; s2 : String (1 .. 4) := ", y="; s3 : String (1 .. 25) := ": closest beacon is at x="; s4 : String (1 .. 4) := ", y="; f : File_Type; T0 : constant Time := Clock; r : array (1 .. 2) of Integer_64; begin top := 0; lowest.x := Integer'Last; lowest.y := Integer'Last; highest.x := Integer'First; highest.y := Integer'First; Open (f, name); Read_Data : while not End_Of_File (f) loop top := top + 1; Get (f, s1); Get (f, k (top).sensor.x); Get (f, s2); Get (f, k (top).sensor.y); Get (f, s3); Get (f, k (top).beacon.x); Get (f, s4); Get (f, k (top).beacon.y); k (top).d := Dist_L1 (k (top).beacon, k (top).sensor); Adapt_Lowest_Value_Point (k (top).beacon); Adapt_Highest_Value_Point (k (top).beacon); Adapt_Lowest_Value_Point (k (top).sensor); Adapt_Highest_Value_Point (k (top).sensor); end loop Read_Data; Close (f); Search_Undetected_Beacon; r (1) := Integer_64 (Scan_for_Beacon_Free (y_p1)); r (2) := tuning_frequency; Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1 answer:" & Integer_64'Image (r (1))); Put_Line (+"Part 2 answer:" & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 5240818 -- Part 2: validated by AoC: 13213086906101 end AoC_2022_15; ================================================ FILE: exm/aoc/2022/aoc_2022_15.txt ================================================ Sensor at x=2899860, y=3122031; closest beacon is at x=2701269, y=3542780 Sensor at x=1836719, y=1116779; closest beacon is at x=2037055, y=2000000 Sensor at x=3995802, y=2706630; closest beacon is at x=3944538, y=3053285 Sensor at x=2591204, y=2008272; closest beacon is at x=2597837, y=2509170 Sensor at x=2546593, y=1538222; closest beacon is at x=2037055, y=2000000 Sensor at x=252214, y=61954; closest beacon is at x=1087565, y=-690123 Sensor at x=950, y=1106672; closest beacon is at x=-893678, y=1276864 Sensor at x=1349445, y=1752783; closest beacon is at x=2037055, y=2000000 Sensor at x=3195828, y=3483667; closest beacon is at x=3334657, y=3531523 Sensor at x=2057761, y=2154359; closest beacon is at x=2037055, y=2000000 Sensor at x=2315350, y=3364640; closest beacon is at x=2701269, y=3542780 Sensor at x=327139, y=2426600; closest beacon is at x=-88420, y=3646947 Sensor at x=3943522, y=2854345; closest beacon is at x=3944538, y=3053285 Sensor at x=3358620, y=516881; closest beacon is at x=3260516, y=2246079 Sensor at x=1788376, y=8679; closest beacon is at x=1087565, y=-690123 Sensor at x=3344883, y=3537985; closest beacon is at x=3334657, y=3531523 Sensor at x=2961064, y=2697125; closest beacon is at x=2597837, y=2509170 Sensor at x=3780090, y=2093546; closest beacon is at x=3260516, y=2246079 Sensor at x=3291917, y=3398703; closest beacon is at x=3334657, y=3531523 Sensor at x=3999864, y=2998005; closest beacon is at x=3944538, y=3053285 Sensor at x=2919272, y=3732950; closest beacon is at x=2701269, y=3542780 Sensor at x=2057404, y=2947435; closest beacon is at x=2037055, y=2000000 Sensor at x=1072126, y=645784; closest beacon is at x=1087565, y=-690123 Sensor at x=3549465, y=2554712; closest beacon is at x=3260516, y=2246079 Sensor at x=3550313, y=3121694; closest beacon is at x=3944538, y=3053285 Sensor at x=3405149, y=3483630; closest beacon is at x=3334657, y=3531523 Sensor at x=2600212, y=3961193; closest beacon is at x=2701269, y=3542780 Sensor at x=1102632, y=3932527; closest beacon is at x=-88420, y=3646947 Sensor at x=67001, y=3506079; closest beacon is at x=-88420, y=3646947 Sensor at x=3994250, y=3975025; closest beacon is at x=3944538, y=3053285 Sensor at x=3019750, y=2125144; closest beacon is at x=3260516, y=2246079 Sensor at x=3282319, y=3656404; closest beacon is at x=3334657, y=3531523 Sensor at x=2797371, y=3645126; closest beacon is at x=2701269, y=3542780 ================================================ FILE: exm/aoc/2022/aoc_2022_15_questions.txt ================================================ --- Day 15: Beacon Exclusion Zone --- You feel the ground rumble again as the distress signal leads you to a large network of subterranean tunnels. You don't have time to search them all, but you don't need to: your pack contains a set of deployable sensors that you imagine were originally built to locate lost Elves. The sensors aren't very powerful, but that's okay; your handheld device indicates that you're close enough to the source of the distress signal to use them. You pull the emergency sensor system out of your pack, hit the big button on top, and the sensors zoom off down the tunnels. Once a sensor finds a spot it thinks will give it a good reading, it attaches itself to a hard surface and begins monitoring for the nearest signal source beacon. Sensors and beacons always exist at integer coordinates. Each sensor knows its own position and can determine the position of a beacon precisely; however, sensors can only lock on to the one beacon closest to the sensor as measured by the Manhattan distance. (There is never a tie where two beacons are the same distance to a sensor.) It doesn't take long for the sensors to report back their positions and closest beacons (your puzzle input). For example: Sensor at x=2, y=18: closest beacon is at x=-2, y=15 Sensor at x=9, y=16: closest beacon is at x=10, y=16 Sensor at x=13, y=2: closest beacon is at x=15, y=3 Sensor at x=12, y=14: closest beacon is at x=10, y=16 Sensor at x=10, y=20: closest beacon is at x=10, y=16 Sensor at x=14, y=17: closest beacon is at x=10, y=16 Sensor at x=8, y=7: closest beacon is at x=2, y=10 Sensor at x=2, y=0: closest beacon is at x=2, y=10 Sensor at x=0, y=11: closest beacon is at x=2, y=10 Sensor at x=20, y=14: closest beacon is at x=25, y=17 Sensor at x=17, y=20: closest beacon is at x=21, y=22 Sensor at x=16, y=7: closest beacon is at x=15, y=3 Sensor at x=14, y=3: closest beacon is at x=15, y=3 Sensor at x=20, y=1: closest beacon is at x=15, y=3 So, consider the sensor at 2,18; the closest beacon to it is at -2,15. For the sensor at 9,16, the closest beacon to it is at 10,16. Drawing sensors as S and beacons as B, the above arrangement of sensors and beacons looks like this: 1 1 2 2 0 5 0 5 0 5 0 ....S....................... 1 ......................S..... 2 ...............S............ 3 ................SB.......... 4 ............................ 5 ............................ 6 ............................ 7 ..........S.......S......... 8 ............................ 9 ............................ 10 ....B....................... 11 ..S......................... 12 ............................ 13 ............................ 14 ..............S.......S..... 15 B........................... 16 ...........SB............... 17 ................S..........B 18 ....S....................... 19 ............................ 20 ............S......S........ 21 ............................ 22 .......................B.... This isn't necessarily a comprehensive map of all beacons in the area, though. Because each sensor only identifies its closest beacon, if a sensor detects a beacon, you know there are no other beacons that close or closer to that sensor. There could still be beacons that just happen to not be the closest beacon to any sensor. Consider the sensor at 8,7: 1 1 2 2 0 5 0 5 0 5 -2 ..........#................. -1 .........###................ 0 ....S...#####............... 1 .......#######........S..... 2 ......#########S............ 3 .....###########SB.......... 4 ....#############........... 5 ...###############.......... 6 ..#################......... 7 .#########S#######S#........ 8 ..#################......... 9 ...###############.......... 10 ....B############........... 11 ..S..###########............ 12 ......#########............. 13 .......#######.............. 14 ........#####.S.......S..... 15 B........###................ 16 ..........#SB............... 17 ................S..........B 18 ....S....................... 19 ............................ 20 ............S......S........ 21 ............................ 22 .......................B.... This sensor's closest beacon is at 2,10, and so you know there are no beacons that close or closer (in any positions marked #). None of the detected beacons seem to be producing the distress signal, so you'll need to work out where the distress beacon is by working out where it isn't. For now, keep things simple by counting the positions where a beacon cannot possibly be along just a single row. So, suppose you have an arrangement of beacons and sensors like in the example above and, just in the row where y=10, you'd like to count the number of positions a beacon cannot possibly exist. The coverage from all sensors near that row looks like this: 1 1 2 2 0 5 0 5 0 5 9 ...#########################... 10 ..####B######################.. 11 .###S#############.###########. In this example, in the row where y=10, there are 26 positions where a beacon cannot be present. Consult the report from the sensors you just deployed. In the row where y=2000000, how many positions cannot contain a beacon? --- Part Two --- Your handheld device indicates that the distress signal is coming from a beacon nearby. The distress beacon is not detected by any sensor, but the distress beacon must have x and y coordinates each no lower than 0 and no larger than 4000000. To isolate the distress beacon's signal, you need to determine its tuning frequency, which can be found by multiplying its x coordinate by 4000000 and then adding its y coordinate. In the example above, the search space is smaller: instead, the x and y coordinates can each be at most 20. With this reduced search area, there is only a single position that could have a beacon: x=14, y=11. The tuning frequency for this distress beacon is 56000011. Find the only possible position for the distress beacon. What is its tuning frequency? ================================================ FILE: exm/aoc/2022/aoc_2022_16.adb ================================================ -- Solution to Advent of Code 2022, Day 16 ------------------------------------------- -- Proboscidea Volcanium -- -- https://adventofcode.com/2022/day/16 -- Copy of questions in: aoc_2022_16_questions.txt -- -- Note: this solution takes an insane amount of time with HAC. -- Fortunately, you can compile it with GNAT and -- the total run-time is there 0.94 seconds on an i7 machine. -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_16 is use HAT; type Valve is (nil, AA, AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AU, AV, AW, AX, AY, AZ, BA, BB, BC, BD, BE, BF, BG, BH, BI, BJ, BK, BL, BM, BN, BO, BP, BQ, BR, BS, BT, BU, BV, BW, BX, BY, BZ, CA, CB, CC, CD, CE, CF, CG, CH, CI, CJ, CK, CL, CM, CN, CO, CP, CQ, CR, CS, CT, CU, CV, CW, CX, CY, CZ, DA, DB, DC, DD, DE, DF, DG, DH, DI, DJ, DK, DL, DM, DN, DP, DQ, DR, DS, DT, DU, DV, DW, DX, DY, DZ, EA, EB, EC, ED, EE, EF, EG, EH, EI, EJ, EK, EL, EM, EN, EO, EP, EQ, ER, ES, ET, EU, EV, EW, EX, EY, EZ, FA, FB, FC, FD, FE, FF, FG, FH, FI, FJ, FK, FL, FM, FN, FO, FP, FQ, FR, FS, FT, FU, FV, FW, FX, FY, FZ, GA, GB, GC, GD, GE, GF, GG, GH, GI, GJ, GK, GL, GM, GN, GO, GP, GQ, GR, GS, GT, GU, GV, GW, GX, GY, GZ, HA, HB, HC, HD, HE, HF, HG, HH, HI, HJ, HK, HL, HM, HN, HO, HP, HQ, HR, HS, HT, HU, HV, HW, HX, HY, HZ, IA, IB, IC, ID, IE, IG, IH, II, IJ, IK, IL, IM, IO, IP, IQ, IR, IT, IU, IV, IW, IX, IY, IZ, JA, JB, JC, JD, JE, JF, JG, JH, JI, JJ, JK, JL, JM, JN, JO, JP, JQ, JR, JS, JT, JU, JV, JW, JX, JY, JZ, KA, KB, KC, KD, KE, KF, KG, KH, KI, KJ, KK, KL, KM, KN, KO, KP, KQ, KR, KS, KT, KU, KV, KW, KX, KY, KZ, LA, LB, LC, LD, LE, LF, LG, LH, LI, LJ, LK, LL, LM, LN, LO, LP, LQ, LR, LS, LT, LU, LV, LW, LX, LY, LZ, MA, MB, MC, MD, ME, MF, MG, MH, MI, MJ, MK, ML, MM, MN, MO, MP, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NB, NC, ND, NE, NF, NG, NH, NI, NJ, NK, NL, NM, NN, NO, NP, NQ, NR, NS, NT, NU, NV, NW, NX, NY, NZ, OA, OB, OC, OD, OE, OG, OH, OI, OJ, OK, OL, OM, ON, OO, OP, OQ, OS, OT, OU, OV, OW, OX, OY, OZ, PA, PB, PC, PD, PE, PF, PG, PH, PJ, PK, PL, PM, PN, PO, PP, PQ, PR, PS, PT, PU, PV, PW, PX, PY, PZ, QA, QB, QC, QD, QE, QF, QG, QH, QI, QJ, QK, QL, QM, QN, QO, QP, QQ, QR, QS, QT, QU, QV, QW, QX, QY, QZ, RA, RB, RC, RD, RE, RF, RG, RH, RI, RJ, RK, RL, RM, RN, RO, RP, RQ, RR, RS, RT, RU, RV, RW, RX, RY, RZ, SA, SB, SC, SD, SE, SF, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SP, SQ, SR, SS, ST, SU, SV, SW, SX, SY, SZ, TA, TB, TC, TD, TE, TF, TG, TH, TI, TJ, TK, TL, TM, TN, TO, TP, TQ, TR, TS, TT, TU, TV, TW, TX, TY, TZ, UA, UB, UC, UD, UE, UF, UG, UH, UI, UJ, UK, UL, UM, UN, UO, UP, UQ, UR, US, UT, UU, UV, UW, UX, UY, UZ, VA, VB, VC, VD, VE, VF, VG, VH, VI, VJ, VK, VL, VM, VN, VO, VP, VQ, VR, VS, VT, VU, VV, VW, VX, VY, VZ, WA, WB, WC, WD, WE, WF, WG, WH, WI, WJ, WK, WL, WM, WN, WO, WP, WQ, WR, WS, WT, WU, WV, WW, WX, WY, WZ, XA, XB, XC, XD, XE, XF, XG, XH, XI, XJ, XK, XL, XM, XN, XO, XP, XQ, XR, XS, XT, XU, XV, XW, XX, XY, XZ, YA, YB, YC, YD, YE, YF, YG, YH, YI, YJ, YK, YL, YM, YN, YO, YP, YQ, YR, YS, YT, YU, YV, YW, YX, YY, YZ, ZA, ZB, ZC, ZD, ZE, ZF, ZG, ZH, ZI, ZJ, ZK, ZL, ZM, ZN, ZO, ZP, ZQ, ZR, ZS, ZT, ZU, ZV, ZW, ZX, ZY, ZZ); flow : array (Valve) of Integer; next : array (Valve, 1 .. 5) of Valve; verbosity_level : constant Natural := 0; procedure Data_Acquisition is c1, c2, sep : Character; valve_nr : String (1 .. 6) := "Valve "; has_flow_rate : String (1 .. 15) := " has flow rate="; tunnels_lead_to : String (1 .. 24) := "; tunnel lead to valves "; -- "tunnel" can be with or without 's' f : File_Type; val : Valve; begin for i in Valve loop flow (i) := 0; for j in next'Range (2) loop next (i, j) := nil; end loop; end loop; Open (f, "aoc_2022_16.txt"); Read_Data : while not End_Of_File (f) loop Get (f, valve_nr); Get (f, c1); Get (f, c2); val := Valve'Value (c1 & c2); if verbosity_level > 0 then Put (val'Image & ": "); end if; Get (f, has_flow_rate); Get (f, flow (val)); if verbosity_level > 0 then Put (flow (val), 3); Put (" -> "); end if; Get (f, tunnels_lead_to); for j in next'Range (2) loop Get (f, sep); if sep = ' ' then Get (f, c1); else c1 := sep; end if; Get (f, c2); next (val, j) := Valve'Value (c1 & c2); if verbosity_level > 0 then Put (" " & next (val, j)'Image); end if; exit when End_Of_Line (f); Get (f, sep); end loop; if verbosity_level > 0 then New_Line; end if; end loop Read_Data; Close (f); end Data_Acquisition; -- The following "laziness filter" is very efficient at -- cutting the recursion for paths that are obviously -- unefficient. For solving part 2 (man + elephant), the -- run time goes from 12+ hours to 6 seconds on a lame -- laptop even if the filter is filled in a very rough way. -- The run-time for part 1 & 2 is less than one second -- on an i7 machine. -- -- TBD: fill the filter in a non-arbitrary way, using -- for instance the ditance of a valve to the AA point -- and its potential score. laziness_filter : array (0 .. 30) of Integer; procedure Fill_Laziness_Filter_Affine_Function (floor_final_score : Natural; -- ^ Final score must be at least that value. max_time_left_for_0_score : Natural) -- ^ Allow score to be still 0 when time left if that amount or more is begin for t in laziness_filter'Range loop -- Here we have an unsophisticated affine function. -- Score increments are small for small values of time left. -- Score increments must be large at the beginning of -- the journey in order to maximize the result and compensate -- for the first lazy steps where no valve is opened. -- So on both ends the affine function is on the safer side. -- However, it is empirical and we have no proof that the optimal -- is not filtered out by this function. laziness_filter (t) := floor_final_score - t * (floor_final_score / max_time_left_for_0_score); end loop; end Fill_Laziness_Filter_Affine_Function; function Visit_One_Agent (v, from : Valve; time_left, score : Natural) return Natural is mem_flow : Positive; result_opening, result_moving : Natural := 0; next_valve : Valve; begin if time_left = 0 then if verbosity_level > 1 then Put_Line ("Time exhausted!"); for v in Valve loop if flow (v) > 0 then Put (v'Image & ": "); Put (flow (v), 3); New_Line; end if; end loop; end if; -- No time left. return 0; end if; if score < laziness_filter (time_left) then return 0; end if; if flow (v) > 0 then -- Try a variant where we open the valve v. mem_flow := flow (v); result_opening := flow (v) * (time_left - 1); -- ^ The flow begins only after one minute for -- opening the valve. flow (v) := 0; result_opening := result_opening + Visit_One_Agent (v, nil, time_left - 1, score + result_opening); -- ^ The recursive visit includes moving further. -- We forget the previous node's location since -- it is meaningful to walk back in that case: -- purpose was for opening a valve. -- -- Restore previous state: flow (v) := mem_flow; end if; -- Move to adjacent nodes: for j in next'Range (2) loop next_valve := next (v, j); exit when next_valve = nil; if next_valve /= from then -- ^ Avoid hesitant moves (going back right -- after coming and having done nothing). result_moving := Max (result_moving, Visit_One_Agent (next_valve, v, time_left - 1, score)); end if; end loop; return Max (result_opening, result_moving); end Visit_One_Agent; function Visit_Two_Agents (v_m, from_m, v_e, from_e : Valve; time_left, score : Natural) return Natural is mem_flow_m, mem_flow_e : Positive; result_opening_m, result_opening_e, result_opening_2, result_moving_m, result_moving_e, result_moving_2 : Natural := 0; next_valve_m, next_valve_e : Valve; begin if time_left = 0 or else score < laziness_filter (time_left) then return 0; end if; if flow (v_m) > 0 and then flow (v_e) > 0 and then v_m /= v_e then -- Man and Elephant open valves mem_flow_m := flow (v_m); mem_flow_e := flow (v_e); result_opening_2 := (flow (v_m) + flow (v_e)) * (time_left - 1); flow (v_m) := 0; flow (v_e) := 0; result_opening_2 := result_opening_2 + Visit_Two_Agents (v_m, nil, v_e, nil, time_left - 1, score + result_opening_2); flow (v_m) := mem_flow_m; flow (v_e) := mem_flow_e; end if; if flow (v_m) > 0 then -- Man opens valve mem_flow_m := flow (v_m); result_opening_m := flow (v_m) * (time_left - 1); flow (v_m) := 0; -- Elephant moves for j_e in next'Range (2) loop next_valve_e := next (v_e, j_e); exit when next_valve_e = nil; if next_valve_e /= from_e then result_moving_e := Max (result_moving_e, Visit_Two_Agents (v_m, nil, next_valve_e, v_e, time_left - 1, score + result_opening_m)); end if; end loop; flow (v_m) := mem_flow_m; result_opening_m := result_opening_m + result_moving_e; end if; if flow (v_e) > 0 then -- Elephant opens valve mem_flow_e := flow (v_e); result_opening_e := flow (v_e) * (time_left - 1); flow (v_e) := 0; -- Man moves for j_m in next'Range (2) loop next_valve_m := next (v_m, j_m); exit when next_valve_m = nil; if next_valve_m /= from_m then result_moving_m := Max (result_moving_m, Visit_Two_Agents (next_valve_m, v_m, v_e, nil, time_left - 1, score + result_opening_e)); end if; end loop; flow (v_e) := mem_flow_e; result_opening_e := result_opening_e + result_moving_m; end if; -- Man and Elephant move for j_m in next'Range (2) loop next_valve_m := next (v_m, j_m); exit when next_valve_m = nil; if next_valve_m /= from_m then for j_e in next'Range (2) loop next_valve_e := next (v_e, j_e); exit when next_valve_e = nil; if next_valve_e /= from_e and then not (v_m = v_e and then next_valve_m >= next_valve_e) -- If Man and Elephant are in the same room, -- we skip symmetrical movements. then result_moving_2 := Max (result_moving_2, Visit_Two_Agents (next_valve_m, v_m, next_valve_e, v_e, time_left - 1, score)); end if; end loop; end if; end loop; return Max (Max (result_opening_2, result_opening_m), Max (result_opening_e, result_moving_2)); end Visit_Two_Agents; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; begin Data_Acquisition; Fill_Laziness_Filter_Affine_Function (1700, 25); r (1) := Visit_One_Agent (AA, nil, 30, 0); Fill_Laziness_Filter_Affine_Function (2270, 20); r (2) := Visit_Two_Agents (AA, nil, AA, nil, 26, 0); Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: maximum pressure release . . . . . . . . : " & r (1)); Put_Line (+"Part 2: maximum pressure release (2 players) . . : " & r (2)); -- Part 1: validated by AoC: 1728 -- Part 2: validated by AoC: 2304 end AoC_2022_16; ================================================ FILE: exm/aoc/2022/aoc_2022_16.txt ================================================ Valve GJ has flow rate=14; tunnels lead to valves UV, AO, MM, UD, GM Valve HE has flow rate=0; tunnels lead to valves QE, SV Valve ET has flow rate=0; tunnels lead to valves LU, SB Valve SG has flow rate=0; tunnels lead to valves FF, SB Valve LC has flow rate=0; tunnels lead to valves QJ, GM Valve EE has flow rate=13; tunnels lead to valves RE, BR Valve AA has flow rate=0; tunnels lead to valves QC, ZR, NT, JG, FO Valve TF has flow rate=0; tunnels lead to valves LU, MM Valve GO has flow rate=0; tunnels lead to valves LB, AH Valve QE has flow rate=24; tunnels lead to valves LG, HE Valve MI has flow rate=0; tunnels lead to valves KU, FF Valve BR has flow rate=0; tunnels lead to valves HY, EE Valve UV has flow rate=0; tunnels lead to valves GP, GJ Valve EH has flow rate=0; tunnels lead to valves UU, FF Valve WK has flow rate=0; tunnels lead to valves HY, EL Valve NT has flow rate=0; tunnels lead to valves FF, AA Valve KI has flow rate=0; tunnels lead to valves OQ, AO Valve AH has flow rate=22; tunnels lead to valves GO, RE Valve EL has flow rate=0; tunnels lead to valves WK, SQ Valve GP has flow rate=0; tunnels lead to valves SB, UV Valve GM has flow rate=0; tunnels lead to valves LC, GJ Valve LU has flow rate=9; tunnels lead to valves UU, DW, TF, ET, ML Valve LB has flow rate=0; tunnels lead to valves GO, VI Valve QC has flow rate=0; tunnels lead to valves ML, AA Valve JJ has flow rate=0; tunnels lead to valves QJ, DV Valve MM has flow rate=0; tunnels lead to valves TF, GJ Valve VI has flow rate=18; tunnel leads to valve LB Valve NV has flow rate=0; tunnels lead to valves SB, KU Valve VT has flow rate=0; tunnels lead to valves HY, JG Valve RE has flow rate=0; tunnels lead to valves AH, EE Valve FO has flow rate=0; tunnels lead to valves SB, AA Valve DV has flow rate=10; tunnels lead to valves JH, UD, JJ Valve SQ has flow rate=12; tunnels lead to valves EL, QA Valve OQ has flow rate=23; tunnels lead to valves KI, IV, JS Valve FF has flow rate=3; tunnels lead to valves EU, NT, SG, MI, EH Valve IV has flow rate=0; tunnels lead to valves LG, OQ Valve HY has flow rate=8; tunnels lead to valves VT, BR, WK Valve ML has flow rate=0; tunnels lead to valves LU, QC Valve JS has flow rate=0; tunnels lead to valves EM, OQ Valve KU has flow rate=5; tunnels lead to valves MI, VL, NV, HU, DW Valve QA has flow rate=0; tunnels lead to valves OS, SQ Valve EU has flow rate=0; tunnels lead to valves FF, OS Valve SV has flow rate=0; tunnels lead to valves QJ, HE Valve JG has flow rate=0; tunnels lead to valves AA, VT Valve DW has flow rate=0; tunnels lead to valves LU, KU Valve UD has flow rate=0; tunnels lead to valves DV, GJ Valve QJ has flow rate=17; tunnels lead to valves JJ, SV, LC, EM, YA Valve HU has flow rate=0; tunnels lead to valves JH, KU Valve ZR has flow rate=0; tunnels lead to valves AA, VL Valve YA has flow rate=0; tunnels lead to valves QJ, OS Valve JH has flow rate=0; tunnels lead to valves HU, DV Valve OS has flow rate=15; tunnels lead to valves EU, YA, QA Valve LG has flow rate=0; tunnels lead to valves QE, IV Valve SB has flow rate=4; tunnels lead to valves FO, SG, NV, GP, ET Valve UU has flow rate=0; tunnels lead to valves EH, LU Valve VL has flow rate=0; tunnels lead to valves ZR, KU Valve AO has flow rate=0; tunnels lead to valves GJ, KI Valve EM has flow rate=0; tunnels lead to valves QJ, JS ================================================ FILE: exm/aoc/2022/aoc_2022_16_questions.txt ================================================ --- Day 16: Proboscidea Volcanium --- The sensors have led you to the origin of the distress signal: yet another handheld device, just like the one the Elves gave you. However, you don't see any Elves around; instead, the device is surrounded by elephants! They must have gotten lost in these tunnels, and one of the elephants apparently figured out how to turn on the distress signal. The ground rumbles again, much stronger this time. What kind of cave is this, exactly? You scan the cave with your handheld device; it reports mostly igneous rock, some ash, pockets of pressurized gas, magma... this isn't just a cave, it's a volcano! You need to get the elephants out of here, quickly. Your device estimates that you have 30 minutes before the volcano erupts, so you don't have time to go back out the way you came in. You scan the cave for other options and discover a network of pipes and pressure-release valves. You aren't sure how such a system got into a volcano, but you don't have time to complain; your device produces a report (your puzzle input) of each valve's flow rate if it were opened (in pressure per minute) and the tunnels you could use to move between the valves. There's even a valve in the room you and the elephants are currently standing in labeled AA. You estimate it will take you one minute to open a single valve and one minute to follow any tunnel from one valve to another. What is the most pressure you could release? For example, suppose you had the following scan output: Valve AA has flow rate=0; tunnels lead to valves DD, II, BB Valve BB has flow rate=13; tunnels lead to valves CC, AA Valve CC has flow rate=2; tunnels lead to valves DD, BB Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE Valve EE has flow rate=3; tunnels lead to valves FF, DD Valve FF has flow rate=0; tunnels lead to valves EE, GG Valve GG has flow rate=0; tunnels lead to valves FF, HH Valve HH has flow rate=22; tunnel leads to valve GG Valve II has flow rate=0; tunnels lead to valves AA, JJ Valve JJ has flow rate=21; tunnel leads to valve II All of the valves begin closed. You start at valve AA, but it must be damaged or jammed or something: its flow rate is 0, so there's no point in opening it. However, you could spend one minute moving to valve BB and another minute opening it; doing so would release pressure during the remaining 28 minutes at a flow rate of 13, a total eventual pressure release of 28 * 13 = 364. Then, you could spend your third minute moving to valve CC and your fourth minute opening it, providing an additional 26 minutes of eventual pressure release at a flow rate of 2, or 52 total pressure released by valve CC. Making your way through the tunnels like this, you could probably open many or all of the valves by the time 30 minutes have elapsed. However, you need to release as much pressure as possible, so you'll need to be methodical. Instead, consider this approach: == Minute 1 == No valves are open. You move to valve DD. == Minute 2 == No valves are open. You open valve DD. == Minute 3 == Valve DD is open, releasing 20 pressure. You move to valve CC. == Minute 4 == Valve DD is open, releasing 20 pressure. You move to valve BB. == Minute 5 == Valve DD is open, releasing 20 pressure. You open valve BB. == Minute 6 == Valves BB and DD are open, releasing 33 pressure. You move to valve AA. == Minute 7 == Valves BB and DD are open, releasing 33 pressure. You move to valve II. == Minute 8 == Valves BB and DD are open, releasing 33 pressure. You move to valve JJ. == Minute 9 == Valves BB and DD are open, releasing 33 pressure. You open valve JJ. == Minute 10 == Valves BB, DD, and JJ are open, releasing 54 pressure. You move to valve II. == Minute 11 == Valves BB, DD, and JJ are open, releasing 54 pressure. You move to valve AA. == Minute 12 == Valves BB, DD, and JJ are open, releasing 54 pressure. You move to valve DD. == Minute 13 == Valves BB, DD, and JJ are open, releasing 54 pressure. You move to valve EE. == Minute 14 == Valves BB, DD, and JJ are open, releasing 54 pressure. You move to valve FF. == Minute 15 == Valves BB, DD, and JJ are open, releasing 54 pressure. You move to valve GG. == Minute 16 == Valves BB, DD, and JJ are open, releasing 54 pressure. You move to valve HH. == Minute 17 == Valves BB, DD, and JJ are open, releasing 54 pressure. You open valve HH. == Minute 18 == Valves BB, DD, HH, and JJ are open, releasing 76 pressure. You move to valve GG. == Minute 19 == Valves BB, DD, HH, and JJ are open, releasing 76 pressure. You move to valve FF. == Minute 20 == Valves BB, DD, HH, and JJ are open, releasing 76 pressure. You move to valve EE. == Minute 21 == Valves BB, DD, HH, and JJ are open, releasing 76 pressure. You open valve EE. == Minute 22 == Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure. You move to valve DD. == Minute 23 == Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure. You move to valve CC. == Minute 24 == Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure. You open valve CC. == Minute 25 == Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. == Minute 26 == Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. == Minute 27 == Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. == Minute 28 == Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. == Minute 29 == Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. == Minute 30 == Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. This approach lets you release the most pressure possible in 30 minutes with this valve layout, 1651. Work out the steps to release the most pressure in 30 minutes. What is the most pressure you can release? --- Part Two --- You're worried that even with an optimal approach, the pressure released won't be enough. What if you got one of the elephants to help you? It would take you 4 minutes to teach an elephant how to open the right valves in the right order, leaving you with only 26 minutes to actually execute your plan. Would having two of you working together be better, even if it means having less time? (Assume that you teach the elephant before opening any valves yourself, giving you both the same full 26 minutes.) In the example above, you could teach the elephant to help you as follows: == Minute 1 == No valves are open. You move to valve II. The elephant moves to valve DD. == Minute 2 == No valves are open. You move to valve JJ. The elephant opens valve DD. == Minute 3 == Valve DD is open, releasing 20 pressure. You open valve JJ. The elephant moves to valve EE. == Minute 4 == Valves DD and JJ are open, releasing 41 pressure. You move to valve II. The elephant moves to valve FF. == Minute 5 == Valves DD and JJ are open, releasing 41 pressure. You move to valve AA. The elephant moves to valve GG. == Minute 6 == Valves DD and JJ are open, releasing 41 pressure. You move to valve BB. The elephant moves to valve HH. == Minute 7 == Valves DD and JJ are open, releasing 41 pressure. You open valve BB. The elephant opens valve HH. == Minute 8 == Valves BB, DD, HH, and JJ are open, releasing 76 pressure. You move to valve CC. The elephant moves to valve GG. == Minute 9 == Valves BB, DD, HH, and JJ are open, releasing 76 pressure. You open valve CC. The elephant moves to valve FF. == Minute 10 == Valves BB, CC, DD, HH, and JJ are open, releasing 78 pressure. The elephant moves to valve EE. == Minute 11 == Valves BB, CC, DD, HH, and JJ are open, releasing 78 pressure. The elephant opens valve EE. (At this point, all valves are open.) == Minute 12 = = Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. ... == Minute 20 == Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. ... == Minute 26 == Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure. With the elephant helping, after 26 minutes, the best you could do would release a total of 1707 pressure. With you and an elephant working together for 26 minutes, what is the most pressure you could release? ================================================ FILE: exm/aoc/2022/aoc_2022_17.adb ================================================ -- Solution to Advent of Code 2022, Day 17 ------------------------------------------- -- Pyroclastic Flow -- -- A giant and deterministic Tetris without rotations. -- -- https://adventofcode.com/2022/day/17 -- Copy of questions in: aoc_2022_17_questions.txt -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; -- Interfaces is needed for compiling on both -- HAC and GNAT (64-bit integer: Integer_64): with Interfaces; procedure AoC_2022_17 is use AoC_Toolbox, HAT, Interfaces; verbosity_level : constant Natural := 0; subtype Range_x is Integer range 0 .. 8; subtype Range_y is Integer range 0 .. 8000; map : array (Range_x, Range_y) of Character; lowest, highest : Point; procedure Adapt_Highest_Value_Point (using : Point) is begin highest.x := Max (highest.x, using.x); highest.y := Max (highest.y, using.y); end Adapt_Highest_Value_Point; procedure Show is begin for y in reverse lowest.y .. highest.y loop for x in lowest.x .. highest.x loop Put (map (x, y)); end loop; New_Line; end loop; end Show; type Rock_Type is (minus, plus, L, I, square); -- #### -- -- .#. -- ### -- .#. -- -- ..# -- ..# -- ### -- -- # -- # -- # -- # -- -- ## -- ## rock : Rock_Type; -- pattern_mini : String (1 .. 40) := ">>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>"; pattern : VString; jet : Positive; old_n_rock, old_height : Integer_64; rocks_per_cycle, height_per_cycle : Integer_64; target_rock : Integer_64 := 0; cycles : Integer_64; tera : constant := 1e12; procedure Simulate_Rock (n_rock : Integer_64) is lb : Point; -- Left, Bottom point of the "sprite". w, h : Integer; -- Width, Height rt : Point; -- Right, Top fits, fit_px : Boolean; rest : Integer_64; begin -- Start position: lb.x := 3; lb.y := highest.y + 4; case rock is when minus => w := 4; h := 1; when plus => w := 3; h := 3; when L => w := 3; h := 3; when I => w := 1; h := 4; when square => w := 2; h := 2; end case; loop -- Gas jet: if Element (pattern, jet) = '<' then case rock is when plus => fits := map (lb.x, lb.y) = '.' and then map (lb.x - 1, lb.y + 1) = '.' and then map (lb.x, lb.y + 2) = '.'; when L => fits := map (lb.x - 1, lb.y) = '.' and then map (lb.x + 1, lb.y + 1) = '.' and then map (lb.x + 1, lb.y + 2) = '.'; when others => fits := True; for y in 0 .. h - 1 loop fit_px := map (lb.x - 1, lb.y + y) = '.'; fits := fits and then fit_px; exit when not fit_px; end loop; end case; if fits then lb.x := lb.x - 1; end if; else case rock is when plus => fits := map (lb.x + 2, lb.y) = '.' and then map (lb.x + 3, lb.y + 1) = '.' and then map (lb.x + 2, lb.y + 2) = '.'; when others => fits := True; for y in 0 .. h - 1 loop fit_px := map (lb.x + w, lb.y + y) = '.'; fits := fits and then fit_px; exit when not fit_px; end loop; end case; if fits then lb.x := lb.x + 1; end if; end if; if jet = Length (pattern) then jet := 1; if old_n_rock /= 0 then -- We observe a cycle (the pattern having a prime -- number of symbols does the magic). -- Every rocks_per_cycle after n_rock - 1 + (any n >= 0), -- the tower is height_per_cycle higher. -- -- We decompose tera = 1e12 falling rocks as: -- -- tera = n_rock + rocks_per_cycle * cycles + rest -- -- Hence, the relation -- -- (tera - n_rock) = rocks_per_cycle * cycles + rest -- -- allow us to calculate cycles and rest. -- Now we can see the decomposition like this: -- -- tera = (n_rock + rest) + (rocks_per_cycle * cycles) -- -- So, we can let falling (target_rock := n_rock + rest), -- measure the height h, let (rocks_per_cycle * cycles) more -- rocks falling. Then the total rocks is 1e12 and the total -- height is: h + height_per_cycle * cycles. -- rocks_per_cycle := n_rock - old_n_rock; height_per_cycle := Integer_64 (highest.y) - old_height; rest := (tera - n_rock) mod rocks_per_cycle; target_rock := n_rock + rest; cycles := (tera - n_rock) / rocks_per_cycle; if verbosity_level > 0 then Put_Line (+"After rock nb " & Integer_64'Image (n_rock - 1) & " heap is height " & highest.y & " cycle rock " & Integer_64'Image (rocks_per_cycle) & "; cycle height: " & Integer_64'Image (height_per_cycle)); Put_Line (+"Must reach rock nb " & Integer_64'Image (target_rock)); end if; end if; old_n_rock := n_rock; old_height := Integer_64 (highest.y); else jet := jet + 1; end if; -- Simulate falling: case rock is when plus => fits := map (lb.x, lb.y) = '.' and then map (lb.x + 1, lb.y - 1) = '.' and then map (lb.x + 2, lb.y) = '.'; when others => fits := True; for x in 0 .. w - 1 loop fit_px := map (lb.x + x, lb.y - 1) = '.'; fits := fits and then fit_px; exit when not fit_px; end loop; end case; if fits then lb.y := lb.y - 1; else -- "Write" the sprite case rock is when minus => for x in 0 .. 3 loop map (lb.x + x, lb.y) := '#'; end loop; when plus => map (lb.x + 1, lb.y + 2) := '#'; for x in 0 .. 2 loop map (lb.x + x, lb.y + 1) := '#'; end loop; map (lb.x + 1, lb.y) := '#'; when L => map (lb.x + 2, lb.y + 2) := '#'; map (lb.x + 2, lb.y + 1) := '#'; for x in 0 .. 2 loop map (lb.x + x, lb.y) := '#'; end loop; when I => for y in 0 .. 3 loop map (lb.x, lb.y + y) := '#'; end loop; when square => for x in 0 .. 1 loop for y in 0 .. 1 loop map (lb.x + x, lb.y + y) := '#'; end loop; end loop; end case; exit; end if; end loop; -- Calculate Right-Top corner. rt.x := lb.x + w - 1; rt.y := lb.y + h - 1; Adapt_Highest_Value_Point (rt); if rock = square then rock := minus; else rock := Rock_Type'Succ (rock); end if; end Simulate_Rock; f : File_Type; T0 : constant Time := Clock; r : array (1 .. 2) of Integer_64; begin r (1) := 0; r (2) := 0; Open (f, "aoc_2022_17.txt"); Get_Line (f, pattern); -- pattern := + pattern_mini; Close (f); lowest.x := Range_x'First; highest.x := Range_x'Last; lowest.y := Range_y'First; highest.y := 0; map (0, 0) := '+'; map (0, 8) := '+'; for x in 1 .. 7 loop map (x, 0) := '-'; end loop; for y in 1 .. Range_y'Last loop map (0, y) := '|'; for x in 1 .. 7 loop map (x, y) := '.'; end loop; map (8, y) := '|'; end loop; rock := minus; jet := 1; old_n_rock := 0; for rock_count in 1 .. 6000 loop Simulate_Rock (Integer_64 (rock_count)); if verbosity_level > 0 and then rock_count <= 5 then Put_Line (rock_count, 0); Show; end if; if rock_count = 2022 then r (1) := Integer_64 (highest.y); elsif Integer_64 (rock_count) = target_rock then r (2) := Integer_64 (highest.y) + cycles * height_per_cycle; exit; end if; end loop; if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Height of the tower of..."); Put_Line (+" (part 1): 2022 rocks . . . . . . . . :" & Integer_64'Image (r (1))); Put_Line (+" (part 2): 1_000_000_000_000 rocks . :" & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 3193 -- Part 2: validated by AoC: 1577650429835 end if; end AoC_2022_17; ================================================ FILE: exm/aoc/2022/aoc_2022_17.txt ================================================ ><<<>>><<<><<<>>><<>>>><<<>>>><>>>><<<>>><<<<>>><<>>>><<<>>><<<<>>><<<<>>><<<<>>>><<<<>>>><<<<>><<<<><<<<><<<>>>><<<>><<>>><<<>><<>>><<>>><>><<<>><<<<>>><<>><>>><<<<>>><>><>>><<<<>>>><<<>>><<<><<<<>>><><>>>><<<><<<<>><<<>><<<>>>><><<<><<>>>><<>>>><<<><<>>>><<>><<><<<>><>>>><<<>>>><<<>><>><<<>>>><<<<><<><<<>><<>>>><<<<>><<<<><<<<><<<<><>><<><<>>><>><<<<>>><>>><>>>><<<<>>><><<>><<<<><<<>>><>>><<<><<<<><<<<><<<<>><>>><><><<<<>><>>>><<<<><>><<<<>>><<<>>><<>>>><<<<><>>>><<>><<<<>>>><<>>><<<>>><><<>>>><<<<>><<>>><<<>><><<<<>>>><<<<>>><>>>><<>>>><<<>>><>>>><<<>>>><<><<>>><>>><<<>>><<<>><>>><<<<>><<<><<>>><>>>><<<<>>><<<>>><<<<>>><<<<>><<>><><<<<>><<<>>><<<<><<<<>>>><<<>><<<><>>><<>>>><<<>>>><<>>><<<<>>><<<>>>><<<>><<<<>>><<<<>>><<>>>><<<>>>><>>><<<>>>><<>><>>>><<>>>><<<>>>><<<<><<<><<>><<<>><<<>>>><<>>>><<<<>><>>>><<<<><<<<>><<>><<>><<<<>>><<>><<><>>>><<<>><>><<>><<>><>><<<>><<<<><<<>>>><<<>>>><<<<>><>><<<<><<<>><<<<>>><>>><<<<><<<>><<<<>><<>>>><<<>>>><<<<>><<<>><><<<<>>><>><<><<<<>><<<><<<><<<<>>>><<<<>>>><><>><<<>>>><<<<>><>>><<<<><<>>><<<>>>><<>><<<>>><>>><<><<<>>><<<><<<>>><<<<><<<<>><<><<>><><<<<>><<<<>>>><><<<>>>><<<>><>>>><<>>>><<<<>>>><<<>>><<<<><<>>>><<<><<<>>>><<><<<>>>><><<<><>>>><>>>><<<>>><>><>>>><>><<>>><>>>><<<>>><<>>>><<>>>><<><<<<>>>><<>>><>><<<<>>><<<>>>><<<>>>><<>>><>><>><<<<>>>><<><<><>>>><<>>>><>>><<<<>>>><<<<>>><<><<<><<>>>><<>>><>>><>>><<<><<<>>>><<<>><<>>><><<<<>>><<<<>><<<>>>><<>><<<<><<<><<<<>><<<<>>>><<><<<><<<<>>>><<<<><<<<>>><<<>>>><<<>>><><<<<>>>><<<>><<<<><>><<<><<>>><>>>><<<><<<<>><<<<><<<<>><<>>>><>><<<>>>><<<<><<<>><<<>>>><><<<>><<<><<<<>>>><><<>><<>>><<<<><<<<><<<<><<>>>><<>>>><<><<<<>><<<<>><<<><>><<<<><<<>>>><<<>><>>>><<<<><<<<><<>><<>><<<<>><<<<>><><><<>><<<<>>>><<<>>>><>>><<<>>>><<>>><><><<><>>><<<<>>>><<>>><<<>>>><<<>>>><>><<<<>>>><<<<>>><<>>>><>>><<<<>>>><<<>>>><<<<>><><>><<<>>>><<>><<<>>><>>>><<<>>>><>><<<>>><<<<>><<<>><<<<>>>><>>>><><><<>><<<<>><<<>><<><<<<>><<>>><>><<><<>><<<<>>><>>>><<<>>>><<>>><>>>><<<><<<<>>>><<<><<<><<<>><<>>>><<<><<<<><<<<>>>><<<<>>>><<<><<<<>>><<>>>><<<>><<<>><<>>>><<>><<<>>>><><<<<>><><<<<>><<<>>><<<>>>><<<>>>><<>>><<<>><<<><>><><<<><>>>><<><<<<>>>><>>><<>>><>>>><<<<>>>><<>><<<<>><<<>><><<<<>><<>>>><<>>>><<<>><<<<>>><<><<<<>>><<>>>><<>><<<<>><<><<<><>><>>><>><<<>>><<<<>>><<>>>><<<><<<<><<<<>><<<<>>>><<<<>>><<>><<<><>>>><<<><<>>>><<<>><>>>><<<<>><<<<>><<>>>><<><<<><>>><<<>>><<>>><<>><<<<>>>><<<<>><<<<>><<<>>>><<<<>>><<>>><<<<><<<>>><<<><<>><<<<>><>>><<><<>>><<<<>>>><<<>>><<<>><<<<>>>><<>><<<<>><><<>>>><>><<<>><<<>><<<<>><>><>><<<>>>><<>><<><<>>><<>>>><<<<>>><<>>>><><<<>>><<>><<<<><<<<>><<>>>><<<<>>>><>>><>>><<<>><><<<>>><<<<>>><>>>><<<>><<<<><<<>>><<<<>>>><<<>>>><<<<>>><<<>><<<<>>><<<>>>><<<<>>>><>>><<<<><><<><<><<>>>><>>>><<<>>><<><><><<<<><<<<>>><<<>>>><<<<>>>><>>><<>>><<>><<<>>>><<><<>><<>>><<<><<<><<<>>>><>><>>><>>>><<<<>>><>><<<><>>>><<<>>>><<<><<<<>>><<<<><<>>><>>>><><<><<<<>>><>>><>><<>>><<<>>>><<<>>>><<<<><<<>>><<<<><<<>>>><<<>>>><>>><<>>>><<>>><<<<><>>><<<><<>><>>><>><<>><<>><<<>>>><<<<>><<<>>><<<<>>>><<>><>>><>>><<<>><<<><<>><>><><<<>>>><<<><<>><<<>>><<<<>><<<>>>><<<<>><>>>><>><<<><>>>><<<<><<<><>>>><<<>>>><><>>><><>>><<<>>>><<>>><<>><<>><>><>>>><<<>>>><><>>><<<<>>><<<>><<><>><<<<>>><<>>>><<<>>><<<>>><<<><<<>><<<<>>><><>>>><<>><<<>>><<<<>><<<>><><<<>>><<<><>>>><><<>><<<><<<>>><<<>>><<>>>><<<>>><<<<>>>><<>>>><<>>><<<<>><>>>><<>>>><><<>><><<<<>><<>>><<>>><<<><<>>><<<>><<<>>>><<>>><>>>><<<><<<><<>>>><><<<<>>><<>>><<<<>>>><<<>>><<<<>>>><<<<>><<>><<>>><<<>>><<<><<<<>>>><<>><<<><<<<>><<<<>>>><<><<<<><>><><<<>><<><<<>>>><<><<<><>>>><<<>>>><<<<><<>>><<<>>><<>>><<><<<<><>>><<>><<<<><<<>><<><><<<><<<><><>>><<><>>>><<><<<><<<<>>>><><<>>>><<><<><<<>>><<<<>><<<><<<>>><<<>>>><<<<>>><<>>>><<<><<<<>><<<<><<<>>>><<<>>>><<<>>>><<<>><<>>>><>><<<><<>>><<<<>>>><><<<<>>><<>><<>><<<<>><<<<><<<<>><<<<>><<<<>>><<>>>><<<<>>>><<<<>>><<<><><<<<>>><<<>>><<>><<><<<>>>><<>><<<><>><<<<>>><<<<><<<<><<><>><<>>><<<><<><<<<>>><<<>>><<<<>><<<<>>>><>>>><><<>><<>><>><<<><<>>>><<<>><<<><<>><<><<<<>>><<>>><<<<>>>><>><<>>>><<<>>><>><<<<>>><<<<>>>><<<>>><<>>><<<<><<<><>>><>><<<>>>><><<<>><<><>><<<><<<>><<>>>><<>>>><<<>><<<>>>><>>><><>>><<<>>>><<<>>><<<><<<<>><<<<><><<<><<><<<<>><><<<<>>><<<>><<<<>>>><<<>>>><<<>>><<<>>><<>>>><<>>>><<<>>>><<<>>><<<>><>>><>>><<<>>>><<>>>><<><>>>><<<><<<>>>><<><<<>><<>><<<<><<<<>>>><<<<><>>><<<<>>>><<<>>>><><<><<<>>>><<<><<>><<>>>><>>><>>>><<>>><<>><<>>><>>><<<>>>><<<>>><<<<>>><<<>>>><<<<>><><<>>>><<<<><>>><<><<<>>>><>>>><<>>>><<<><<><<<<>>>><>>><<<>>>><<<>><><<>>><<<><<>><><<<>>><<<<><<><<<>>><<>>><>>>><>>><<>>><>><><<<<>>>><<<<>>>><><<<<><<<<><<<<>>>><<<<>>><<<<><<<>><<>>>><<><<<>>><<><<<>><>>><<<<>>><<><<>>><<<><<><<<>><<<<><<>>><><<>><><><<<><<>>><<>>>><<<<>>><<<>><<<<><<>>>><>>>><<<<><<<<>>>><<>>><<<<>>><<>>><<<>>><>>><<<>>>><<<>><<><<<<><>>>><<>><<>>>><<<>>><<<>>><>>><<<<>><<<<>><<><<<<>>><<>>>><>>>><>>><<<<>>>><><<<>>>><<<<>>>><<<>>>><<<>>>><<<<><<<>>>><<<>>><<<<>>>><<<><>>><><>>>><<<<>><<>>><<<><<<<><<>><<<<>><><<><<<>>><<<<>><<<>>>><<<>>>><<><>>><<>>><<<>>><<<<><<<<>>><<<<>><>>>><<<<>>>><<<><<<<>>><<>>>><<<>>>><<><>>>><<>>>><<>><<<>><<>>><<<<>>>><<><>>><<><<<>>>><<<<>><>>><><>>>><<<>><<<<>>>><<<<><<>>>><<<<>><<<>>><><<<<>>><<>>>><<>>>><<<><<><<<<>>><<<<>>>><<<><<<<><><<<<>>>><<<<>>><<<<><<<><<<>><><<<<><<>>><<<>><<<>>>><<>>>><<>>>><<>>>><<><<<<>><<<<><<<<>>><<><>>>><>>><><>><<><<>>>><<<<><>><<<<><<>><<>>><>><<<>><>><>><<<>>><<>>>><<<>>>><<>>><<>>>><<>>><<<<>>><<<<>>><<<<><<>>>><<<<>>>><<<>>><>>><<>>>><<<>>>><>>>><>><<<<>>>><<<<><<>>>><<<<><>>>><<<>><<<<>>>><>>><<<<>>>><<>>><<<<>><<<<><<<>><<<>><<>><>>>><>><<<<>>>><<<>><<>><<>>><<<>>>><>>>><<>>><>>><<><<>><<<<>><<<>>><<<><<<>>><<<<>>><<<><<<>>>><<<<><<>>><<<>>>><>>>><<<<><><<<<>>>><<>>><>>><<<<>>>><<<<>><<>><<<>>>><<<>><>>>><>>>><><<<>>>><<<<><<<>>><<>>><><<<<>><<<<>><>>><>><<<>>>><<<>>>><<<<>><<>>><<<><<<>><<<>><<<>><<>>><<<<>><<<>>>><<>>>><<<>><>>><>>>><<<<>>>><<<>><>>><<>><><<<>>>><>><<<<>>>><<<<><>>>><<<<><<><<<<>>>><<>><<<>>>><<<><<>>><<<<><<<<>><<>>><<<<>>><<><<<<>>><<><<>>><<>><<<<><>>><<<<>>><<>><<<<>>><<<><>>>><><<><><<<>><>>><>><>>><<<>>>><>><<<<>><<<>><<<<>>><<<>>><<<>>>><><<><<<>><<<<>><<><<<<>><<<<>>>><<<<>><<<>>><<<<>>>><<>>>><<<><<<>>>><<>>><<>>>><<<<>>><<>>>><>>>><<<<>>>><<<>>><<<>>><<<><>>>><>>>><<<<>>><<<>>>><>>>><<>>><<>>><><<<<>><<>><<>><<<<>>><<<<>>>><<<>>>><<<>><>><<<<><>><>>>><<<<>>>><<<>>>><<<>>>><<>>>><>>>><<<<>>><>>>><<<<>><<><<<>><<<<>><<<>><<<<><<<>>>><<>><>><>><<<>>>><>><<<><<><<<<>>><<<<><>>>><<><>><<<>><>><<<>>>><<<><<<<>>>><<<<><>>>><<<<>><<<<>><<<<><>>>><>>><<<<>>>><<<><<<>>><<<>><<>><<<<>>>><<<>><<<<>>><<>>>><<>><<>>>><<><<><<<<>>>><<<>>><<<><>>>><<>>>><><<<>><>><<><<>>>><><>>>><<<>>>><<<<>><<>><<<>>>><>>><<>>><>>><><<><<<<>><>><<<>>><<<>><><<<<>><<<>>><><<<<><>>><<<><><<<<>>><<>>><>>><>>>><<<>><<<<>>>><>>><<>>>><<>>><<<>>>><>>><<<>>>><<<<>>><<<<>>><<><<><<>>><<<<>>>><<<><>><>>>><<>>>><<<>>>><>>><<<><<><>>>><<>>><<<>>>><<>>>><<<><<<<>>>><>><<<>>><<<><<<>>><><<<<>>>><>><>>>><<<<><<<<>>>><<>>>><><<<>><>>><<<<>><<<<>>><<<<>>>><<<>><<<<>>>><<><>><<<>>><><<<<>>>><<<<><<<>><>><<>>><<<><<<<>><<>>>><<<>>>><<>>>><<<<>><<>><>>><<<<>>><<<>>>><<<<>>>><<>><<><<>><<<<>>><<<<>>><<<<>>>><><<<>>><<<<>>><<<<><><<<<><>><<<<>>><<<>>><<<<>>>><<<<>>><>>><<>>><<<<>><<<>><>><<>>>><>>>><>><<<>>>><<<<>>>><<<>>>><<<><<<><<<>><>>><<<<>>>><<<>>>><<<<>>><<<<>><<>><<<<><<<><>><>>><><<<><<<>>>><<<>>><<<<>>>><<<<><<>>>><<<<><<<>>><<>><<<<>><>>><<>>>><<<><<>>><>>><<>>><<<>>>><>><><<<<>>><><<<<>>><<<>>>><<><><<><<>>><>><<<<>>><<<>>>><<<><<<>><<<<>>><><>><<>>>><<<><<<<><>>><>><<<<>>>><<>>><<<<>>>><<<<>>><<>>><<<<><<>>>><<<>>>><<>>><>>><<>>><<<><<<>><<<<>>>><<<<>>><<>><>>>><<<<>>>><<<><>>>><<<<><<<<>><<>>><<<<>>>><><<>><<<<><>>>><<<<>><>>><><>>><<>>>><<<><><<<<>><<<><<<<>>>><><>>><<>>><<<>>><<<<>>><<<<>><<>>>><<<>>><>>><<<<>>>><<><>>><<<><<<>>>><<<>>>><<<><>>>><<<<>>><>>>><<<>>><<<><<<<>>><<<<><<<<>>><<>>>><<<>>><<<<><<><<<<>>>><<<>><<<<>><>>><<<<><<>>>><<>><>>>><<<<><<<>><<>>>><<>>>><<<<>><<<<>>>><<>>>><<<>>>><<>>><><<<>>><<><<>>>><<<>>>><<>>>><>><<<<>>>><<<<>>>><<><<><<<<><<>>><<>>><<<<>>>><<<>><<<<><<<<>>><<<<>>><<<>>><<<<><<>>>><<<<>>>><<<>><<<>><>>>><<<><><<<<><><<<>>><<<<>>>><<<><<<<>>>><<<>>>><>><<<<>>>><<>>>><<<>>>><<<<><<<>>>><>>>><><<<><<<>><>>>><<<>><<<<><<<<>><<>>><>>>><<>><>><>><<<>>><<<>>><<<>>><<>>><<>><<<>>>><<<<>>><<<>><>>>><<<<><<><>>>><<>>><<><<<<>><<<<>>>><<>><<<><<>>><<<<>><<<>><<><<<<>>>><<<>>>><<<<>>><>><<<<>><<<><>><<>>><<<<><<<<>>>><<<>><<<>>>><<<<>>>><<<>>><<>><>>><>>><<<>>><><<<<>>><>>><>>>><>>><<<<>>>><<<><<><><<<>>>><<<><<<>><<<<>>><<<><<><<<<>>>><<><<<<>>><>>>><>>>><>><<<<>>>><<<<>>><>>><<<>><>>>><<<<>><<<<>>>><>>><>>><<<<>><<<>>>><<<><<<<><>>><<<<>>><<<>>>><><<<><>><<<<>><<<><<<<>>>><>><><<<<><<<<>>>><<<>>>><<>><<<<><<>>><<<<><<<><<<<>><<<><<>>>><<<<>><>>>><<<>>><<>><<<>><><<<<>>>><<<>><<>><>>>><<<>>><<>>><<<>>><<>>><<<><<<<>>><>><<<>>>><<<<>>>><<<>><<<<>>>><>><<<><><<<<>><<<>>>><>>>><<<<>>>><<>>><<>>><><>>><<<><>><<>>>><>>><<<>>>><><>><>>>><<>>><>><<<<>><<>>><<>>>><><<><<<>><<>>>><<<>>><<><<<>>>><<<><><<>><<<>><<<><<<>>>><<<>>><>><<<>>><>>><>>><<>>><<<<><<<<>><<<>>><<<><>>><<<<>><>><<<>>><<>><>><<><>>><<<<>><>>><<<<><<<><<<><<<>>><<>>>><<<<>><<>><<>>><<>><<>><<<<>>><<><<<><>>><>><<><<>>>><<>>><<<<>>><<<>>>><>>><>>><<>>><><<<><<><<>>><>>>><>>>><<<<>>><>><<<>>>><>><<<>><<>>><>><<><<<><<<>>><<>>><<<<>>><><<<<>>><<<>><>>>><<<>>>><<<<><<<<>>>><<>><><<>>><<<><<>>><<>>>><<>><<<><<<><<<>>><<>><<<>>>><><<<<>>>><<>>><<>><<>>><<>>><<>>>><<<><<<<>><<>>>><<<>>><><<><<><<>>><<<<><<<><<><<>>>><<>>><><<<<>><<>><><<><>>><>>><<>>><<<<>>><<<<><>><<>>>><<<<>>>><>><<<<>><<><<<>>>><>><<<<>>>><<<><<<>><><<<<>>>><><<<<>><<<><<>>>><<><<<>><<<>><<<>><<<>>><<><<<>>>><>><<>>>><<>>><>>>><>>><><>><<<>>><<<><><<>><<<>>><<<<>>><<<>>>><><>>><<><>><<<>><<>><<>>><<<<>>><<<><<<<><>><<<>>><<<>>><<>>>><<<<>>><<>>><<<><<>>><<<>><<<>>><>>>><<<<>>>><<<<>><<<<>>><<>><<<<>><<<>>><<<>><><<<>>>><<>>>><<<<>>>><<>><>>>><<<<>>><>>>><>><<<<>>><>>><<>>>><<<<><<<><<<>><<>>><<><>>><<<<>>><>>>><<>>><<<<>>><>><<<>><<><<<><<<<>>><><<<<>>><<<<>>><<><<<<>><<>>>><>>>><<><><<<>>><>><>><>>>><><<<<>>><<<<>>>><<>><<> ================================================ FILE: exm/aoc/2022/aoc_2022_17_questions.txt ================================================ --- Day 17: Pyroclastic Flow --- Your handheld device has located an alternative exit from the cave for you and the elephants. The ground is rumbling almost continuously now, but the strange valves bought you some time. It's definitely getting warmer in here, though. The tunnels eventually open into a very tall, narrow chamber. Large, oddly-shaped rocks are falling into the chamber from above, presumably due to all the rumbling. If you can't work out where the rocks will fall next, you might be crushed! The five types of rocks have the following peculiar shapes, where # is rock and . is empty space: #### .#. ### .#. ..# ..# ### # # # # ## ## The rocks fall in the order shown above: first the - shape, then the + shape, and so on. Once the end of the list is reached, the same order repeats: the - shape falls first, sixth, 11th, 16th, etc. The rocks don't spin, but they do get pushed around by jets of hot gas coming out of the walls themselves. A quick scan reveals the effect the jets of hot gas will have on the rocks as they fall (your puzzle input). For example, suppose this was the jet pattern in your cave: >>><<><>><<<>><>>><<<>>><<<><<<>><>><<>> In jet patterns, < means a push to the left, while > means a push to the right. The pattern above means that the jets will push a falling rock right, then right, then right, then left, then left, then right, and so on. If the end of the list is reached, it repeats. The tall, vertical chamber is exactly seven units wide. Each rock appears so that its left edge is two units away from the left wall and its bottom edge is three units above the highest rock in the room (or the floor, if there isn't one). After a rock appears, it alternates between being pushed by a jet of hot gas one unit (in the direction indicated by the next symbol in the jet pattern) and then falling one unit down. If any movement would cause any part of the rock to move into the walls, floor, or a stopped rock, the movement instead does not occur. If a downward movement would have caused a falling rock to move into the floor or an already-fallen rock, the falling rock stops where it is (having landed on something) and a new rock immediately begins falling. Drawing falling rocks with @ and stopped rocks with #, the jet pattern in the example above manifests as follows: The first rock begins falling: |..@@@@.| |.......| |.......| |.......| +-------+ Jet of gas pushes rock right: |...@@@@| |.......| |.......| |.......| +-------+ Rock falls 1 unit: |...@@@@| |.......| |.......| +-------+ Jet of gas pushes rock right, but nothing happens: |...@@@@| |.......| |.......| +-------+ Rock falls 1 unit: |...@@@@| |.......| +-------+ Jet of gas pushes rock right, but nothing happens: |...@@@@| |.......| +-------+ Rock falls 1 unit: |...@@@@| +-------+ Jet of gas pushes rock left: |..@@@@.| +-------+ Rock falls 1 unit, causing it to come to rest: |..####.| +-------+ A new rock begins falling: |...@...| |..@@@..| |...@...| |.......| |.......| |.......| |..####.| +-------+ Jet of gas pushes rock left: |..@....| |.@@@...| |..@....| |.......| |.......| |.......| |..####.| +-------+ Rock falls 1 unit: |..@....| |.@@@...| |..@....| |.......| |.......| |..####.| +-------+ Jet of gas pushes rock right: |...@...| |..@@@..| |...@...| |.......| |.......| |..####.| +-------+ Rock falls 1 unit: |...@...| |..@@@..| |...@...| |.......| |..####.| +-------+ Jet of gas pushes rock left: |..@....| |.@@@...| |..@....| |.......| |..####.| +-------+ Rock falls 1 unit: |..@....| |.@@@...| |..@....| |..####.| +-------+ Jet of gas pushes rock right: |...@...| |..@@@..| |...@...| |..####.| +-------+ Rock falls 1 unit, causing it to come to rest: |...#...| |..###..| |...#...| |..####.| +-------+ A new rock begins falling: |....@..| |....@..| |..@@@..| |.......| |.......| |.......| |...#...| |..###..| |...#...| |..####.| +-------+ The moment each of the next few rocks begins falling, you would see this: |..@....| |..@....| |..@....| |..@....| |.......| |.......| |.......| |..#....| |..#....| |####...| |..###..| |...#...| |..####.| +-------+ |..@@...| |..@@...| |.......| |.......| |.......| |....#..| |..#.#..| |..#.#..| |#####..| |..###..| |...#...| |..####.| +-------+ |..@@@@.| |.......| |.......| |.......| |....##.| |....##.| |....#..| |..#.#..| |..#.#..| |#####..| |..###..| |...#...| |..####.| +-------+ |...@...| |..@@@..| |...@...| |.......| |.......| |.......| |.####..| |....##.| |....##.| |....#..| |..#.#..| |..#.#..| |#####..| |..###..| |...#...| |..####.| +-------+ |....@..| |....@..| |..@@@..| |.......| |.......| |.......| |..#....| |.###...| |..#....| |.####..| |....##.| |....##.| |....#..| |..#.#..| |..#.#..| |#####..| |..###..| |...#...| |..####.| +-------+ |..@....| |..@....| |..@....| |..@....| |.......| |.......| |.......| |.....#.| |.....#.| |..####.| |.###...| |..#....| |.####..| |....##.| |....##.| |....#..| |..#.#..| |..#.#..| |#####..| |..###..| |...#...| |..####.| +-------+ |..@@...| |..@@...| |.......| |.......| |.......| |....#..| |....#..| |....##.| |....##.| |..####.| |.###...| |..#....| |.####..| |....##.| |....##.| |....#..| |..#.#..| |..#.#..| |#####..| |..###..| |...#...| |..####.| +-------+ |..@@@@.| |.......| |.......| |.......| |....#..| |....#..| |....##.| |##..##.| |######.| |.###...| |..#....| |.####..| |....##.| |....##.| |....#..| |..#.#..| |..#.#..| |#####..| |..###..| |...#...| |..####.| +-------+ To prove to the elephants your simulation is accurate, they want to know how tall the tower will get after 2022 rocks have stopped (but before the 2023rd rock begins falling). In this example, the tower of rocks will be 3068 units tall. How many units tall will the tower of rocks be after 2022 rocks have stopped falling? --- Part Two --- The elephants are not impressed by your simulation. They demand to know how tall the tower will be after 1000000000000 rocks have stopped! Only then will they feel confident enough to proceed through the cave. In the example above, the tower would be 1514285714288 units tall! How tall will the tower be after 1000000000000 rocks have stopped? ================================================ FILE: exm/aoc/2022/aoc_2022_18.adb ================================================ -- Solution to Advent of Code 2022, Day 18 ------------------------------------------- -- Boiling Boulders -- -- https://adventofcode.com/2022/day/18 -- Copy of questions in: aoc_2022_18_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src with HAT; procedure AoC_2022_18 is use HAT; subtype The_Range is Integer range -1 .. 20; type Big_Cube is array (The_Range, The_Range, The_Range) of Natural; space : Big_Cube; air : constant := 0; lava : constant := 1; procedure Flood_Fill (x, y, z : Integer) is begin if x in The_Range and then y in The_Range and then z in The_Range and then space (x, y, z) = air then space (x, y, z) := lava; Flood_Fill (x - 1, y, z); Flood_Fill (x + 1, y, z); Flood_Fill (x, y - 1, z); Flood_Fill (x, y + 1, z); Flood_Fill (x, y, z - 1); Flood_Fill (x, y, z + 1); end if; end Flood_Fill; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; f : File_Type; c1, c2 : Character; x, y, z : Natural; cubes_lava, contacts_lava, cubes_air, inner_faces_air : Natural := 0; surface_area_lava, surface_area_air : Natural; begin for x in Big_Cube'Range (1) loop for y in Big_Cube'Range (2) loop for z in Big_Cube'Range (3) loop space (x, y, z) := air; end loop; end loop; end loop; Open (f, "aoc_2022_18.txt"); Read_Data : while not End_Of_File (f) loop Get (f, x); Get (f, c1); Get (f, y); Get (f, c2); Get (f, z); space (x, y, z) := lava; cubes_lava := cubes_lava + 1; -- Count the faces of each lava cube that is -- connected to the new lava cube. -- Each square is counted once. contacts_lava := contacts_lava + space (x - 1, y, z) + space (x + 1, y, z) + space (x, y - 1, z) + space (x, y + 1, z) + space (x, y, z - 1) + space (x, y, z + 1); end loop Read_Data; Close (f); surface_area_lava := 6 * cubes_lava - 2 * contacts_lava; r (1) := surface_area_lava; Flood_Fill (-1, -1, -1); -- Now the only air remaining is trapped inside the lava droplet. for x in Big_Cube'Range (1) loop for y in Big_Cube'Range (2) loop for z in Big_Cube'Range (3) loop if space (x, y, z) = air then cubes_air := cubes_air + 1; -- Count the faces of each air cube that is -- connected to another air cube. -- Each square is counted twice. inner_faces_air := inner_faces_air + 6 - (space (x - 1, y, z) + space (x + 1, y, z) + space (x, y - 1, z) + space (x, y + 1, z) + space (x, y, z - 1) + space (x, y, z + 1)); end if; end loop; end loop; end loop; surface_area_air := (6 * cubes_air - inner_faces_air); r (2) := surface_area_lava - surface_area_air; if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: surface area of lava . . . . . : " & r (1)); Put_Line (+"Part 2: exterior surface area of lava : " & r (2)); -- Part 1: validated by AoC: 3374 -- Part 2: validated by AoC: 2010 end if; end AoC_2022_18; ================================================ FILE: exm/aoc/2022/aoc_2022_18.txt ================================================ 13,4,13 13,7,5 4,6,14 11,17,11 7,5,16 10,11,2 5,14,7 12,5,4 12,17,7 16,9,5 10,8,17 17,9,11 11,10,16 2,12,7 8,4,15 15,9,15 18,7,9 5,10,15 9,3,8 9,3,7 15,8,15 12,1,10 7,4,14 17,11,10 13,2,9 6,15,4 2,13,11 17,10,9 9,5,16 5,2,8 16,15,9 10,2,8 2,11,11 12,16,14 7,4,13 12,16,9 13,9,3 6,2,9 16,8,14 9,3,13 15,8,4 7,7,2 11,16,12 4,13,15 8,7,17 6,15,15 1,6,9 3,7,6 14,6,3 11,13,2 16,6,10 5,3,9 6,12,16 12,14,4 2,6,11 13,3,4 11,7,2 12,4,4 11,7,17 8,8,17 15,4,14 3,10,11 9,6,2 15,5,8 4,14,8 5,6,6 10,18,12 4,11,5 11,2,10 14,12,4 12,7,16 9,14,16 11,16,13 14,10,15 5,5,13 15,4,8 6,11,3 10,12,3 3,6,8 12,14,3 8,4,13 9,2,12 7,6,2 10,15,15 14,7,15 6,3,8 16,8,7 8,5,4 7,4,8 12,5,16 3,11,15 12,16,12 12,16,13 17,12,10 8,16,7 9,11,3 6,11,18 4,4,10 11,2,12 16,9,14 4,5,7 17,12,8 3,12,14 14,2,9 7,17,9 10,9,3 14,12,16 3,6,11 9,18,11 16,13,4 12,11,17 5,5,10 4,14,5 17,5,6 15,6,6 7,5,3 8,18,8 3,14,9 10,16,6 12,12,17 12,13,14 4,13,6 5,8,3 5,12,17 8,17,8 8,11,18 2,9,13 3,6,7 8,11,16 12,5,15 4,4,8 5,16,11 10,17,5 6,5,15 13,10,16 12,3,13 6,9,2 1,12,10 8,4,4 11,12,2 4,9,3 14,6,15 15,4,13 9,6,1 3,5,12 10,10,18 6,1,10 3,7,13 18,11,10 6,18,11 17,13,8 5,6,16 10,17,10 5,13,6 16,11,5 16,8,8 10,6,4 12,9,3 14,7,4 15,3,12 4,5,12 3,10,14 4,6,12 16,9,7 15,13,5 9,4,4 7,15,5 18,9,12 16,7,3 15,14,14 3,7,14 17,9,9 9,16,8 2,7,8 9,4,15 8,5,14 13,13,17 12,7,3 13,7,15 5,5,15 14,7,16 14,13,15 6,5,5 7,12,17 17,9,7 9,5,1 6,12,4 14,12,14 4,4,7 10,8,2 17,9,6 5,4,5 7,6,5 3,13,7 16,10,11 18,8,10 17,7,9 3,10,12 17,10,6 8,5,17 5,11,17 2,8,13 4,12,4 13,17,6 12,14,16 8,5,15 12,15,14 16,10,5 5,5,5 3,8,6 15,10,8 9,6,17 17,11,6 5,6,10 7,16,10 4,6,5 14,14,14 6,8,16 17,6,11 9,15,14 5,14,15 9,8,17 14,3,12 10,1,11 13,12,3 7,6,3 16,11,13 10,17,7 3,5,10 4,13,13 5,6,4 5,14,5 16,7,11 15,3,9 16,14,5 4,8,6 12,2,8 9,4,5 7,11,2 16,6,11 9,8,1 8,12,16 12,4,14 7,9,3 10,4,5 3,6,13 5,4,12 14,16,11 10,17,13 15,5,14 6,4,6 5,17,9 12,10,2 4,2,9 13,5,3 15,14,10 10,5,3 8,2,7 3,7,11 8,15,4 9,15,4 9,16,16 11,8,18 2,13,13 5,5,14 9,17,6 4,4,11 14,8,16 14,14,3 9,17,13 16,8,11 13,6,16 9,9,18 15,15,10 6,10,2 5,5,12 6,4,15 2,5,7 10,18,9 5,15,15 10,1,7 17,13,13 6,17,13 7,12,2 14,7,3 10,11,17 16,12,14 14,14,13 2,10,12 5,10,3 13,16,13 4,4,9 9,17,11 5,13,14 7,2,8 14,15,7 7,3,5 10,3,14 17,6,9 5,4,11 17,8,11 10,9,18 13,15,7 10,13,3 8,3,7 5,8,16 5,16,5 13,11,15 6,11,16 2,7,6 17,11,9 10,6,16 5,3,8 15,13,4 4,9,15 12,15,7 11,3,9 12,1,8 14,10,4 6,2,7 13,16,12 2,7,5 1,8,10 6,6,16 12,17,11 10,14,4 12,13,4 10,2,6 13,14,14 3,12,7 15,13,9 12,12,3 10,2,10 9,18,7 10,15,6 14,17,12 6,8,8 14,14,4 9,15,7 4,6,6 5,7,15 12,16,11 5,17,13 13,17,10 8,1,10 13,6,4 6,17,7 4,3,7 2,5,6 11,19,11 12,16,7 2,7,7 6,5,16 7,11,16 7,16,8 9,15,16 5,6,14 15,10,3 2,5,11 13,3,12 9,5,17 8,3,14 5,9,17 17,10,14 7,11,15 8,3,12 10,5,2 7,3,13 15,6,5 5,7,2 10,10,3 14,2,12 9,16,14 15,12,16 7,4,4 7,14,3 5,9,3 8,11,2 16,5,13 10,4,4 7,9,16 10,2,13 17,15,7 5,13,4 11,2,8 1,10,7 5,14,14 17,6,10 14,15,15 14,9,2 12,3,6 11,18,8 17,10,13 15,6,13 8,17,11 3,4,6 17,9,8 6,3,6 8,15,8 17,8,8 15,5,5 12,4,8 7,6,16 2,11,12 9,17,8 12,14,5 2,11,7 14,6,4 13,12,17 6,16,15 11,9,2 7,15,15 9,12,1 2,9,5 10,9,17 1,9,7 2,13,9 4,10,15 16,14,13 15,10,5 14,15,6 7,14,11 2,8,7 8,4,16 10,6,1 1,8,9 4,14,4 13,4,6 8,2,14 6,10,16 8,18,9 9,14,4 7,17,6 3,5,13 13,12,16 9,6,16 3,11,5 9,12,15 3,10,5 5,15,14 17,7,14 6,4,5 5,9,16 6,14,3 1,11,11 14,11,3 8,14,15 2,8,9 17,8,9 11,14,15 18,8,11 10,2,9 14,4,14 14,5,6 7,10,17 3,12,8 16,4,10 4,8,8 9,5,4 16,12,12 14,9,4 3,11,7 10,12,2 4,9,12 8,3,5 11,14,4 15,6,4 7,16,12 11,17,7 11,17,8 15,14,13 14,16,13 13,6,17 6,16,9 14,16,10 11,15,13 3,11,16 15,6,14 13,8,16 3,6,6 16,9,6 14,13,4 16,5,11 4,11,13 9,15,3 5,10,7 8,16,8 15,5,15 7,13,3 8,12,3 7,10,2 3,9,15 8,7,2 17,9,10 11,3,10 9,3,14 12,7,18 4,6,13 4,12,3 11,10,2 11,1,9 15,13,6 7,18,10 4,14,11 10,16,10 10,3,13 8,16,6 11,1,8 5,15,11 5,9,4 8,6,3 8,10,2 11,5,7 10,2,12 9,12,3 15,14,7 4,6,10 5,11,15 14,4,7 2,12,12 8,17,7 14,17,11 1,7,10 4,5,13 7,3,4 15,5,11 7,2,11 9,18,8 14,9,3 15,13,7 17,7,11 10,13,17 10,10,17 16,13,7 16,14,7 5,17,11 7,11,17 3,13,4 15,12,4 4,14,7 14,16,5 7,4,12 14,5,15 2,12,13 5,4,4 13,10,17 15,14,8 12,6,14 5,15,5 12,4,7 3,5,6 13,5,4 13,13,4 10,8,1 6,13,3 2,10,6 9,16,5 10,12,17 3,9,10 11,3,5 11,1,12 10,4,3 8,2,9 9,13,16 11,5,16 17,8,6 5,8,2 9,11,18 15,8,16 10,16,7 6,4,8 15,4,7 9,12,2 16,7,13 12,6,16 7,13,2 11,5,15 6,13,17 2,14,8 9,17,14 6,3,11 17,13,10 3,9,14 12,4,15 14,10,3 8,10,16 13,3,7 7,12,15 8,17,13 9,10,1 17,8,7 5,14,6 4,9,4 13,7,2 7,14,4 7,16,13 3,12,11 12,4,9 8,8,1 7,4,16 9,7,18 16,13,9 13,7,16 5,15,13 6,2,10 9,7,3 17,7,10 7,7,18 15,12,6 12,10,3 15,5,13 5,12,2 15,6,15 14,8,3 12,18,9 2,12,11 5,16,13 6,3,9 4,4,12 6,13,16 14,4,9 16,4,11 2,7,10 8,17,9 13,6,15 13,5,6 6,5,4 9,2,11 9,8,2 2,13,8 15,16,10 4,8,14 7,13,5 7,1,10 18,11,11 11,3,7 14,5,5 8,2,6 16,14,6 13,5,5 5,12,3 8,2,10 18,10,8 16,14,14 13,17,9 3,9,12 7,13,4 3,8,14 14,8,17 16,4,9 3,10,4 1,7,8 11,15,15 8,12,13 2,8,5 1,9,8 4,17,9 15,9,17 6,6,5 11,10,18 16,12,7 15,17,8 1,8,6 12,9,2 3,4,7 14,13,16 14,15,8 15,14,5 4,9,8 5,17,10 12,7,2 16,9,8 4,11,14 16,9,4 4,15,11 13,3,11 13,8,2 7,7,4 13,6,2 17,8,14 17,12,12 4,9,14 16,13,11 16,16,11 17,11,7 10,2,4 13,13,3 5,12,4 6,11,2 17,9,5 13,14,7 11,15,3 13,16,11 5,10,2 8,13,2 4,15,6 18,9,6 17,13,9 14,15,12 15,7,4 14,13,11 14,12,15 12,11,15 9,15,15 16,12,11 4,16,11 14,4,12 12,16,6 4,8,16 12,12,2 10,3,5 16,6,7 13,3,8 15,12,12 16,16,6 8,4,5 12,15,11 14,15,13 16,4,7 4,5,8 3,3,7 10,15,4 12,16,10 4,14,13 3,11,13 13,6,14 13,16,6 2,9,9 4,9,16 5,11,4 8,4,14 5,12,14 10,16,5 7,8,2 17,14,10 14,3,6 17,15,10 4,14,9 11,7,1 3,14,6 10,14,15 12,6,17 9,2,8 17,7,7 17,14,6 15,8,5 7,7,5 9,0,11 4,3,10 10,13,16 9,17,10 2,10,7 16,8,13 14,3,10 9,14,3 14,9,16 11,10,3 9,14,15 5,16,6 15,9,16 2,15,9 12,10,17 13,16,7 15,3,8 16,7,6 3,9,5 13,3,14 13,14,5 3,8,16 6,8,17 3,10,16 13,7,4 13,15,14 15,6,7 2,10,9 11,0,9 16,5,8 14,15,10 6,10,15 16,6,13 3,15,13 3,5,11 14,4,15 4,6,11 5,5,16 13,10,2 3,5,9 14,12,3 5,4,14 10,5,16 6,13,15 12,5,3 5,5,3 14,14,6 9,8,16 13,4,4 3,14,12 4,7,5 12,13,2 7,5,4 13,14,16 16,4,8 6,2,6 16,11,14 15,15,14 9,11,17 11,15,5 2,14,9 16,14,8 12,15,15 14,9,17 13,5,13 11,1,11 18,11,9 12,4,5 16,13,13 8,14,16 7,15,14 3,14,13 16,9,11 11,15,4 3,6,10 15,12,7 5,14,13 3,7,12 10,3,9 8,2,12 15,15,12 10,16,4 16,8,12 15,15,13 17,6,8 13,3,13 11,16,6 10,9,1 12,12,18 5,12,13 9,10,3 3,11,6 16,14,9 7,15,16 14,3,9 13,2,8 10,16,13 12,16,5 14,5,4 11,17,13 4,11,15 2,7,11 13,5,11 6,4,10 12,17,12 10,14,16 10,17,9 1,10,11 17,10,8 9,7,2 10,6,2 4,15,9 17,12,15 9,17,12 15,9,4 6,15,6 12,4,13 10,2,11 15,4,4 4,8,4 6,17,11 6,3,7 12,4,3 16,4,6 9,1,11 9,3,4 9,1,9 14,6,13 8,16,11 7,8,4 9,16,12 11,2,13 11,3,14 6,4,13 16,15,8 13,1,9 5,14,16 6,10,3 6,16,10 12,4,12 5,10,4 9,11,2 11,6,5 11,16,14 9,5,5 12,3,9 10,3,15 14,8,13 10,17,11 16,7,5 14,16,7 12,14,15 5,15,8 17,13,6 12,17,9 5,12,12 13,12,2 10,3,12 7,17,11 6,3,14 10,5,1 9,18,12 5,16,10 4,4,5 11,18,14 8,8,18 2,5,8 7,8,17 7,17,10 7,3,7 14,8,2 16,6,9 14,3,8 8,10,3 1,12,11 15,4,5 11,18,11 3,10,9 12,15,16 7,13,16 14,11,15 8,15,3 3,8,7 16,12,13 3,12,15 10,15,14 12,6,4 11,6,3 2,6,7 2,8,8 8,5,3 17,10,12 8,16,13 5,15,6 13,16,9 7,3,6 10,6,15 3,14,10 11,2,7 1,8,12 14,13,5 7,13,17 9,2,9 11,7,3 11,2,6 2,9,12 6,16,7 8,13,15 15,5,6 4,3,12 9,6,12 7,2,13 16,4,12 3,4,10 3,12,9 10,16,8 8,1,12 11,17,6 14,8,4 14,15,9 7,3,9 17,9,12 8,9,3 16,10,15 15,6,11 2,10,14 11,6,14 14,6,14 11,13,3 16,9,13 11,4,5 17,8,12 3,9,6 15,4,12 10,17,8 5,10,17 8,7,16 6,8,2 16,10,8 13,11,17 13,10,3 2,11,4 12,17,13 13,4,12 13,17,7 14,11,13 9,6,3 15,15,6 4,3,13 13,2,12 11,11,17 14,13,14 13,6,3 14,6,5 17,14,8 9,12,17 15,14,6 7,3,10 16,13,12 12,10,15 7,4,15 9,10,18 8,1,11 7,8,18 8,3,11 11,8,17 5,3,6 16,11,9 17,12,7 11,16,15 15,15,8 5,4,8 6,11,15 15,6,8 7,11,3 5,15,12 4,7,11 5,15,10 10,18,11 17,10,5 4,14,14 3,12,12 2,6,9 13,5,14 16,13,10 8,16,10 13,3,15 16,9,12 4,15,7 11,3,11 15,14,11 10,13,4 13,18,9 13,9,4 6,16,12 16,12,5 15,11,6 3,8,13 11,1,10 15,7,5 15,4,9 10,5,15 8,6,2 12,9,18 10,3,6 17,12,11 9,6,18 11,4,14 14,8,15 8,2,8 4,7,16 2,10,4 8,5,16 4,14,6 8,14,3 14,13,3 2,10,13 12,4,11 13,4,14 2,9,10 9,17,7 12,17,10 3,7,5 11,2,14 12,15,5 7,8,1 7,3,11 17,7,6 14,4,11 7,12,16 15,5,12 6,16,11 6,6,4 8,15,5 7,2,7 9,10,17 14,2,10 11,8,4 3,11,12 6,9,16 15,7,3 3,15,10 3,8,5 12,10,16 8,8,2 12,13,3 6,15,12 11,5,3 16,6,6 4,5,9 5,13,15 18,9,10 15,13,13 6,2,11 6,16,6 13,8,3 9,5,3 10,12,16 1,10,9 15,5,10 13,4,11 4,7,4 12,3,14 11,9,16 10,14,3 2,10,8 9,16,6 13,16,10 17,10,7 10,16,14 13,13,5 3,12,5 4,14,10 3,12,13 6,14,8 13,4,7 5,6,9 14,4,5 11,13,15 16,15,10 7,17,8 18,9,8 12,11,16 16,14,10 12,4,16 10,12,14 7,3,12 8,11,3 4,3,9 10,6,3 11,16,4 14,12,6 7,5,6 12,3,7 13,13,15 13,15,15 3,8,3 13,10,4 14,13,6 12,3,5 7,7,16 17,14,9 13,15,4 16,6,12 6,14,4 12,6,15 10,1,9 7,8,16 4,15,10 14,12,11 8,9,16 2,13,7 13,14,3 6,12,3 16,12,9 17,5,8 5,7,8 11,2,11 10,9,4 8,2,11 11,15,14 6,18,12 16,12,4 3,6,12 7,14,16 3,5,7 5,2,10 4,12,14 15,11,3 15,7,14 10,17,14 12,2,6 3,13,11 2,8,10 18,14,9 2,6,6 2,5,9 5,8,5 15,15,11 11,18,10 13,5,16 9,9,2 15,7,16 7,6,17 12,11,2 2,12,14 10,18,7 8,5,2 11,9,1 11,8,2 6,9,3 15,2,9 6,17,8 4,7,3 10,3,7 2,12,10 2,6,13 7,9,1 6,15,14 8,10,1 11,16,5 5,15,7 9,2,13 18,8,8 17,13,12 16,9,15 17,10,10 14,5,3 13,15,13 14,10,1 7,9,17 13,16,8 4,15,8 17,11,13 10,17,15 3,6,5 13,6,6 4,8,15 5,5,6 12,5,14 6,8,18 12,2,9 16,6,5 10,7,16 3,10,7 13,13,14 18,12,8 13,8,15 6,2,12 14,15,14 4,13,8 15,5,9 4,12,6 2,8,14 2,12,9 4,12,12 3,14,5 7,5,10 11,4,15 6,13,2 9,1,13 14,7,12 2,11,13 6,3,12 11,7,5 14,13,13 7,10,18 13,11,16 18,10,7 6,15,8 10,7,2 6,15,16 15,13,11 6,4,14 15,8,3 7,16,7 1,10,10 9,13,1 4,11,8 12,2,10 9,12,18 7,5,17 3,13,13 5,13,5 15,7,15 6,14,13 9,16,11 8,3,15 6,15,11 12,13,15 12,12,16 7,6,15 4,15,13 11,18,7 18,10,9 11,16,9 15,5,7 9,1,7 5,5,4 10,1,10 8,13,17 13,17,11 10,4,14 10,10,1 9,16,15 13,4,15 16,15,11 7,2,5 8,11,1 12,3,11 16,10,6 12,3,4 13,16,5 16,12,6 7,14,15 9,1,14 6,11,5 4,10,14 11,15,17 3,10,8 11,17,10 12,5,13 17,8,5 2,11,6 2,9,8 4,9,13 13,9,17 9,7,1 4,13,4 3,9,8 16,8,6 16,11,6 12,8,3 13,13,16 13,6,5 13,11,4 15,12,8 16,11,11 6,14,14 12,17,6 17,10,11 15,3,10 13,7,3 4,8,13 9,3,12 16,5,12 14,11,6 9,13,17 15,4,10 14,15,11 14,11,16 7,2,6 12,14,17 8,14,4 5,16,9 7,16,6 10,13,15 15,10,15 16,11,7 8,8,4 10,15,16 14,14,15 7,5,14 0,9,8 13,9,16 7,12,3 16,12,15 9,13,3 16,3,12 4,10,13 15,11,14 18,8,12 3,5,14 7,17,14 14,12,5 8,17,6 16,10,9 8,18,10 4,14,12 14,5,10 11,6,16 7,8,3 12,6,3 16,13,6 10,7,1 17,6,6 15,17,9 14,16,8 4,6,8 3,10,6 8,11,17 4,16,8 5,3,10 4,16,7 6,11,4 9,9,19 6,4,7 18,10,6 15,15,9 8,12,2 12,2,13 8,13,1 3,4,11 8,9,18 5,4,7 14,6,8 10,2,15 8,17,10 7,5,2 9,4,14 6,5,3 14,8,6 3,13,14 2,11,9 6,5,14 6,15,5 6,14,5 4,13,5 7,17,12 3,13,9 14,14,11 11,4,13 3,12,6 11,17,14 2,13,10 15,13,10 12,1,12 12,7,1 15,10,16 13,12,4 16,3,10 7,4,6 2,9,6 5,9,2 13,4,10 5,13,7 3,7,9 7,3,8 3,11,14 16,5,9 5,4,13 11,14,16 7,8,15 5,14,11 12,2,14 0,8,11 8,13,3 13,5,15 10,18,10 11,3,6 4,7,15 3,16,9 4,4,13 9,7,16 8,3,4 11,1,5 6,10,17 10,15,12 4,16,12 7,4,5 1,10,6 12,17,14 6,16,4 4,7,9 2,9,7 8,15,16 5,3,7 14,16,12 4,11,17 10,10,16 12,9,17 6,7,2 8,9,17 12,15,4 11,18,12 9,16,13 6,13,5 6,17,9 1,10,8 5,16,8 2,7,12 15,12,9 13,14,13 5,10,16 11,8,16 15,4,6 12,14,12 15,10,4 5,7,3 15,9,2 8,17,5 1,11,12 18,6,9 11,12,17 2,12,4 4,9,5 5,14,4 11,4,17 11,4,4 13,17,8 11,14,2 11,4,16 11,10,1 10,12,18 5,10,5 11,11,3 9,8,18 16,5,5 9,5,15 10,6,5 13,11,3 12,8,17 16,8,15 9,8,3 16,5,10 6,8,5 12,1,11 14,5,8 9,11,16 12,9,16 9,7,17 5,17,12 12,7,17 10,9,2 19,9,9 13,13,2 6,14,15 2,8,11 15,12,3 8,4,6 3,8,9 4,7,14 8,2,13 9,1,12 13,2,6 6,16,14 13,3,9 7,16,14 14,6,12 5,12,16 12,13,17 12,5,12 13,11,14 14,12,2 4,5,5 18,13,9 3,5,8 7,10,4 15,5,4 11,15,7 17,7,13 1,11,10 18,12,10 12,17,8 5,17,8 3,10,13 4,10,3 6,9,14 15,12,15 7,16,5 6,3,13 17,14,12 9,3,16 4,9,6 5,3,13 1,10,12 15,12,17 3,7,8 12,11,1 7,14,5 14,16,6 14,17,9 4,8,3 14,15,4 6,6,14 18,8,9 5,2,9 16,10,12 10,5,17 14,4,13 2,7,9 15,14,15 5,8,15 5,5,11 7,1,9 15,3,13 15,12,5 3,7,7 15,11,5 13,9,18 8,6,15 11,12,16 13,8,13 5,4,15 15,10,6 2,10,10 18,7,6 13,17,12 16,10,10 15,12,14 2,9,4 14,4,8 7,1,7 16,11,15 6,6,18 11,5,4 9,3,6 17,7,5 16,15,13 19,10,10 3,12,10 11,13,16 12,11,3 4,7,17 5,4,9 4,10,16 9,19,8 13,1,10 15,4,11 2,8,12 8,13,4 12,9,4 12,10,18 10,1,6 4,10,12 3,11,9 5,12,15 4,4,6 6,4,4 7,7,17 12,8,16 17,11,11 9,5,7 7,5,5 9,4,16 16,13,8 8,8,3 11,5,2 13,2,11 11,10,15 8,10,17 6,13,4 14,14,5 15,7,6 16,16,7 8,6,17 8,5,6 2,4,9 14,6,16 5,6,5 4,6,9 16,7,8 4,13,3 15,11,4 11,7,16 16,8,5 5,4,10 5,11,3 17,13,7 13,14,15 5,6,15 9,4,6 16,7,15 16,11,12 10,17,12 6,8,3 4,5,6 13,3,10 8,15,17 3,15,9 1,7,9 5,10,14 17,5,9 14,7,2 5,9,12 15,15,5 4,3,8 13,12,5 14,14,12 4,12,5 9,16,9 13,16,14 11,6,17 5,16,12 4,13,7 2,5,12 17,11,12 2,8,6 12,7,14 7,16,9 11,16,7 17,11,8 3,3,10 8,15,13 12,16,8 11,17,9 6,9,1 10,7,17 2,6,8 11,10,17 16,12,10 14,13,12 1,10,5 8,7,3 14,3,7 6,7,16 7,5,15 0,11,12 7,2,9 10,18,8 14,7,5 15,8,6 7,1,11 8,1,9 10,11,16 9,1,10 16,5,6 12,3,8 1,12,7 2,11,10 18,12,9 13,15,10 11,16,10 5,9,5 10,11,3 18,13,10 13,11,2 2,14,10 11,5,18 10,8,3 11,7,18 17,14,11 10,15,3 10,4,16 1,11,9 8,1,8 13,13,12 16,5,4 8,8,16 7,13,14 9,17,5 4,7,7 17,11,3 2,6,12 3,14,7 6,7,3 9,17,9 12,8,18 16,11,4 10,17,6 3,4,8 7,14,13 6,17,10 5,11,16 11,8,1 6,2,8 16,16,9 4,7,6 10,2,7 18,11,7 11,6,18 15,11,2 4,6,15 12,10,5 3,9,7 13,3,6 10,4,15 16,6,8 3,13,5 5,16,7 12,15,10 18,12,7 17,8,13 3,14,8 14,14,8 4,3,11 9,16,7 6,10,1 10,3,10 8,16,9 11,7,4 9,3,5 7,1,13 13,15,6 13,15,11 8,16,4 16,6,4 7,15,4 8,2,5 4,12,15 9,9,16 14,2,7 6,5,6 8,12,17 13,15,5 8,18,12 7,7,3 13,12,15 3,4,9 6,12,17 17,6,7 6,6,15 17,13,11 11,8,14 7,6,18 15,14,4 15,13,12 4,5,10 4,11,16 11,4,3 16,14,11 1,9,12 7,17,13 9,3,15 14,5,2 13,7,14 14,2,6 9,15,11 7,15,11 16,12,8 15,11,11 15,9,13 7,9,19 12,6,5 4,5,14 13,8,17 11,14,3 13,15,16 6,3,15 9,12,16 2,12,8 15,7,10 13,2,7 4,10,7 17,6,13 13,15,12 4,6,7 11,5,14 10,15,5 15,16,11 9,13,2 9,2,14 2,14,12 10,16,17 9,14,17 10,3,8 10,16,15 15,9,3 5,5,8 16,7,9 3,15,8 9,16,10 17,6,12 1,6,11 5,9,15 7,11,18 18,6,7 7,15,13 9,13,4 10,8,18 1,9,10 4,6,3 7,2,10 11,9,17 16,6,14 18,9,9 1,12,9 3,6,9 3,6,14 12,11,18 12,12,15 13,4,3 16,8,9 14,11,11 3,8,15 5,14,12 6,7,14 13,5,9 15,14,12 7,2,12 4,13,12 6,5,12 3,9,13 17,8,10 17,7,12 9,2,10 12,18,11 12,8,15 2,12,5 7,15,6 17,12,13 5,9,14 2,11,8 6,5,8 14,16,14 16,10,13 5,12,6 18,11,8 4,4,14 5,4,6 15,11,16 15,13,14 4,5,11 10,4,6 11,11,2 9,18,9 9,9,17 14,7,13 8,7,1 4,13,14 6,15,3 8,15,14 11,14,5 15,15,7 15,11,15 7,10,16 14,10,17 2,10,5 3,13,12 6,7,15 9,5,2 12,2,12 7,9,18 4,8,5 8,5,7 7,9,4 7,14,10 14,11,4 10,6,17 8,15,10 13,5,2 9,10,2 8,16,15 11,12,18 8,4,12 5,7,4 2,12,6 6,15,13 15,7,9 5,14,8 8,13,16 12,13,16 12,4,6 9,2,7 16,14,12 11,17,12 16,7,7 1,13,9 12,9,15 10,7,18 8,14,13 4,16,13 7,15,8 4,16,10 14,5,13 10,4,13 13,16,4 8,12,4 11,4,6 14,6,6 6,3,5 3,9,4 12,8,4 14,5,7 13,7,17 4,12,16 16,8,3 12,10,1 6,14,16 10,13,2 10,7,3 8,3,6 10,11,1 9,11,1 7,4,7 15,6,12 6,6,3 4,13,16 14,3,11 8,16,5 13,1,11 7,3,15 3,13,8 13,15,9 6,16,13 4,10,8 15,14,9 4,6,16 1,13,10 6,3,10 6,12,14 6,3,4 9,10,16 18,11,12 1,8,7 2,13,12 16,7,14 12,14,14 9,15,17 8,9,2 12,7,4 8,4,3 5,15,9 16,13,14 15,12,13 15,12,11 11,3,12 13,9,15 8,3,9 6,6,2 18,7,11 7,16,4 16,7,12 7,17,4 5,8,13 13,7,7 14,14,7 7,15,3 10,2,14 1,13,8 3,8,11 15,8,12 14,14,10 14,10,16 5,11,2 14,6,10 15,8,14 3,7,16 14,10,12 4,11,4 17,6,5 13,18,10 13,4,9 7,9,2 10,9,16 6,6,13 10,10,2 14,3,13 4,12,13 11,15,10 11,3,8 11,4,7 4,7,13 2,11,15 6,7,4 6,5,11 1,9,11 2,6,10 8,12,1 7,2,14 5,14,3 17,7,8 6,16,8 16,10,7 18,6,10 12,2,7 15,3,11 16,5,7 4,13,11 13,5,7 6,9,17 2,7,14 8,7,5 13,2,10 10,15,11 6,17,6 17,12,9 15,7,7 13,9,2 12,7,15 12,15,13 1,6,10 15,16,9 6,15,10 7,16,15 13,4,5 14,15,5 3,9,16 11,15,16 6,8,4 18,10,12 17,12,6 12,2,5 18,13,11 11,6,2 15,10,13 12,2,11 11,14,14 10,7,4 12,14,9 10,2,5 14,10,5 5,13,3 12,3,12 8,16,14 8,3,8 14,16,9 4,12,10 8,13,14 12,3,10 3,14,4 0,9,11 3,13,6 16,8,10 11,9,18 18,12,11 14,12,7 9,15,12 15,8,2 7,4,3 4,10,10 12,8,1 3,12,4 15,2,7 9,13,14 14,2,11 16,10,4 12,15,6 1,10,13 15,6,10 3,11,3 8,8,5 17,4,12 3,14,14 3,11,11 16,10,14 13,14,4 8,6,16 9,7,5 15,13,8 8,15,15 10,12,1 11,2,9 10,12,4 5,8,14 17,11,4 12,8,2 12,1,7 9,16,3 11,18,9 8,16,12 15,10,7 9,18,10 10,8,16 14,10,2 11,13,18 6,5,7 2,14,11 7,11,14 10,5,14 6,8,15 6,15,7 9,6,15 18,10,10 8,14,2 9,2,6 9,9,1 1,11,7 15,9,6 6,12,15 17,15,11 7,13,15 10,3,11 9,4,3 5,13,16 15,11,12 17,14,13 5,5,7 3,3,8 9,19,10 5,17,7 1,8,11 9,19,9 11,11,18 14,14,9 5,8,9 3,3,9 7,15,7 15,10,17 14,2,8 10,11,18 9,15,10 18,6,11 3,8,4 8,6,4 9,16,4 9,2,5 13,16,15 4,10,4 5,8,17 8,14,5 5,16,14 8,12,18 9,15,5 6,7,17 6,11,17 4,3,5 14,3,14 5,1,11 14,12,17 12,13,12 5,8,4 16,9,17 1,8,8 ================================================ FILE: exm/aoc/2022/aoc_2022_18_questions.txt ================================================ --- Day 18: Boiling Boulders --- You and the elephants finally reach fresh air. You've emerged near the base of a large volcano that seems to be actively erupting! Fortunately, the lava seems to be flowing away from you and toward the ocean. Bits of lava are still being ejected toward you, so you're sheltering in the cavern exit a little longer. Outside the cave, you can see the lava landing in a pond and hear it loudly hissing as it solidifies. Depending on the specific compounds in the lava and speed at which it cools, it might be forming obsidian! The cooling rate should be based on the surface area of the lava droplets, so you take a quick scan of a droplet as it flies past you (your puzzle input). Because of how quickly the lava is moving, the scan isn't very good; its resolution is quite low and, as a result, it approximates the shape of the lava droplet with 1x1x1 cubes on a 3D grid, each given as its x,y,z position. To approximate the surface area, count the number of sides of each cube that are not immediately connected to another cube. So, if your scan were only two adjacent cubes like 1,1,1 and 2,1,1, each cube would have a single side covered and five sides exposed, a total surface area of 10 sides. Here's a larger example: 2,2,2 1,2,2 3,2,2 2,1,2 2,3,2 2,2,1 2,2,3 2,2,4 2,2,6 1,2,5 3,2,5 2,1,5 2,3,5 In the above example, after counting up all the sides that aren't connected to another cube, the total surface area is 64. What is the surface area of your scanned lava droplet? --- Part Two --- Something seems off about your calculation. The cooling rate depends on exterior surface area, but your calculation also included the surface area of air pockets trapped in the lava droplet. Instead, consider only cube sides that could be reached by the water and steam as the lava droplet tumbles into the pond. The steam will expand to reach as much as possible, completely displacing any air on the outside of the lava droplet but never expanding diagonally. In the larger example above, exactly one cube of air is trapped within the lava droplet (at 2,2,5), so the exterior surface area of the lava droplet is 58. What is the exterior surface area of your scanned lava droplet? ================================================ FILE: exm/aoc/2022/aoc_2022_19.adb ================================================ -- Solution to Advent of Code 2022, Day 19 ------------------------------------------- -- Not Enough Minerals -- -- https://adventofcode.com/2022/day/19 -- Copy of questions in: aoc_2022_19_questions.txt -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- Note: this solution takes a large amount of time -- with GNAT and an even larger one with HAC. -- See AoC_2022_19_Full_Ada for a fast solution. -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; procedure AoC_2022_19 is use AoC_Toolbox, HAT; verbosity_level : constant Natural := 1; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; f : File_Type; -- Parseable copy of the example (part after column with '|'): -- -- |Blueprint 1: -- | Each ore robot costs 4 ore. -- | Each clay robot costs 2 ore. -- | Each obsidian robot costs 3 ore and 14 clay. -- | Each geode robot costs 2 ore and 7 obsidian. -- | -- |Blueprint 2: -- | Each ore robot costs 2 ore. -- | Each clay robot costs 3 ore. -- | Each obsidian robot costs 3 ore and 8 clay. -- | Each geode robot costs 3 ore and 12 obsidian. type Resource_Type is (ore, clay, obsidian, geode); type Portfolio_Type is array (Resource_Type) of Natural; type State_Type is record resource : Portfolio_Type; robot : Portfolio_Type; end record; subtype Cost_Type is Portfolio_Type; -- Costs of a robot producing a certain resource. type Blueprint_Type is array (Resource_Type) of Cost_Type; function Best_Geode_Opening (blueprint : Blueprint_Type; total_time : Positive) return Natural is initial : State_Type; obsidian_cost_geode_robot, clay_cost_obsidian_robot : Positive; greedy : constant Boolean := True; procedure Visit (state : State_Type; time_left : Natural; geodes : out Natural) is robot_creation_possible, any_possible : Boolean; score_build_robot : array (Resource_Type) of Natural; score_same_robots : Natural; new_state : State_Type; result : Natural; begin case time_left is when 0 => geodes := state.resource (geode); return; -- Some recursion breakers on desperately unefficient scenarios when 1 => if state.robot (geode) = 0 then -- There is not even a single geode-breaking robot in the last minute. geodes := 0; return; end if; when 2 => if state.robot (obsidian) = 0 then -- There is not even a single obsidian-collecting robot -- in the needed time to construct the first geode-breaking robot -- and produce the first geode. geodes := 0; return; end if; if state.robot (geode) = 0 then -- No geode-breaking robot? Fair enough, we contruct one. if state.resource (obsidian) < obsidian_cost_geode_robot then -- There is not enough obsidian to construct the -- first geode-breaking robot. geodes := 0; return; end if; end if; when 3 => if state.robot (clay) = 0 then -- Too late for the first clay robot. geodes := 0; return; end if; if state.robot (obsidian) = 0 then if state.resource (clay) < clay_cost_obsidian_robot then -- Not enough clay to construct the first obsidian-collecting robot. geodes := 0; return; end if; end if; if state.robot (geode) = 0 then if state.resource (obsidian) + state.robot (obsidian) < obsidian_cost_geode_robot then -- There won't be not enough obsidian on next step to construct the -- first geode-breaking robot. geodes := 0; return; end if; end if; when 4 => if state.robot (obsidian) = 0 then if state.resource (clay) + state.robot (clay) < clay_cost_obsidian_robot then -- Not enough clay to construct the first obsidian-collecting -- robot in the last possible minute. geodes := 0; return; end if; end if; if state.robot (geode) = 0 then case state.robot (obsidian) is when 0 => if state.resource (obsidian) < obsidian_cost_geode_robot - 1 then geodes := 0; return; end if; when 1 => if state.resource (obsidian) < obsidian_cost_geode_robot - 3 then geodes := 0; return; end if; when 2 => if state.resource (obsidian) < obsidian_cost_geode_robot - 6 then geodes := 0; return; end if; when others => null; end case; end if; when 5 => if state.robot (geode) = 0 then case state.robot (obsidian) is when 0 => -- Best case : one more obsidian robot is constructed at each -- subsequent time step, allowing for constructin a geode robot. if state.resource (obsidian) < obsidian_cost_geode_robot - 3 then geodes := 0; return; end if; when 1 => if state.resource (obsidian) < obsidian_cost_geode_robot - 7 then geodes := 0; return; end if; when others => null; end case; end if; when 6 => if state.robot (geode) = 0 and then state.robot (obsidian) = 0 and then state.resource (obsidian) < obsidian_cost_geode_robot - 6 then geodes := 0; return; end if; when others => null; end case; any_possible := False; for new_robot in Resource_Type loop score_build_robot (new_robot) := 0; robot_creation_possible := False; if state.resource (ore) >= blueprint (new_robot)(ore) then case new_robot is when ore | clay => new_state := state; new_state.resource (ore) := new_state.resource (ore) - blueprint (new_robot)(ore); robot_creation_possible := True; when obsidian => if state.resource (clay) >= blueprint (obsidian)(clay) then new_state := state; new_state.resource (ore) := new_state.resource (ore) - blueprint (obsidian)(ore); new_state.resource (clay) := new_state.resource (clay) - blueprint (obsidian)(clay); robot_creation_possible := True; end if; when geode => if state.resource (obsidian) >= blueprint (geode)(obsidian) then new_state := state; new_state.resource (ore) := new_state.resource (ore) - blueprint (geode)(ore); new_state.resource (obsidian) := new_state.resource (obsidian) - blueprint (geode)(obsidian); robot_creation_possible := True; end if; end case; end if; if robot_creation_possible then -- Earn new resources for res in Resource_Type loop new_state.resource (res) := new_state.resource (res) + new_state.robot (res); end loop; new_state.robot (new_robot) := new_state.robot (new_robot) + 1; Visit (new_state, time_left - 1, score_build_robot (new_robot)); end if; any_possible := any_possible or robot_creation_possible; end loop; -- Variant without constructing a new robot. if greedy and then any_possible then -- We ignore this variant if it is possible to construct a robot. score_same_robots := 0; else new_state := state; -- Earn new resources for res in Resource_Type loop new_state.resource (res) := new_state.resource (res) + new_state.robot (res); end loop; Visit (new_state, time_left - 1, score_same_robots); end if; -- Find max: result := score_same_robots; for res in Resource_Type loop result := Max (result, score_build_robot (res)); end loop; geodes := result; end Visit; max_geodes : Natural; begin for r in Resource_Type loop initial.robot (r) := 0; initial.resource (r) := 0; end loop; initial.robot (ore) := 1; obsidian_cost_geode_robot := blueprint (geode)(obsidian); clay_cost_obsidian_robot := blueprint (obsidian)(clay); -- put(min_time_to_collect_enough_obsidian); -- put(min_time_to_collect_enough_clay); -- new_line; Visit (initial, total_time, max_geodes); return max_geodes; end Best_Geode_Opening; last : Natural := 0; blueprint : array (1 .. 30) of Blueprint_Type; best : Natural; begin Open (f, "aoc_2022_19.txt"); Read_Data : while not End_Of_File (f) loop Skip_till_Space (f, 6); exit Read_Data when End_Of_File (f); last := last + 1; for robot in Resource_Type loop for cost in Resource_Type loop blueprint (last)(robot)(cost) := 0; end loop; end loop; Get (f, blueprint (last)(ore)(ore)); Skip_till_Space (f, 6); Get (f, blueprint (last)(clay)(ore)); Skip_till_Space (f, 6); Get (f, blueprint (last)(obsidian)(ore)); Skip_till_Space (f, 3); Get (f, blueprint (last)(obsidian)(clay)); Skip_till_Space (f, 6); Get (f, blueprint (last)(geode)(ore)); Skip_till_Space (f, 3); Get (f, blueprint (last)(geode)(obsidian)); Skip_till_Space (f, 1); end loop Read_Data; Close (f); r (1) := 0; r (2) := 1; for b in 1 .. last loop best := Best_Geode_Opening (blueprint (b), 24); if verbosity_level > 0 then Put_Line (+"In 24 steps (minutes), blueprint #" & b & ": " & best & " geodes cracked, T = " & (Clock - T0)); end if; r (1) := r (1) + b * best; if b <= 3 then best := Best_Geode_Opening (blueprint (b), 32); if verbosity_level > 0 then Put_Line (+"In 32 steps (minutes), blueprint #" & b & ": " & best & " geodes cracked, T = " & (Clock - T0)); end if; r (2) := r (2) * best; end if; end loop; if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1 (24 minutes):" & r (1)'Image); Put_Line (+"Part 2 (32 minutes):" & r (2)'Image); -- Part 1: validated by AoC: 1192 -- Part 2: validated by AoC: 14725 end if; end AoC_2022_19; ================================================ FILE: exm/aoc/2022/aoc_2022_19_full_ada.adb ================================================ -- Solution to Advent of Code 2022, Day 19 ------------------------------------------- -- Not Enough Minerals -- -- https://adventofcode.com/2022/day/19 -- Copy of questions in: aoc_2022_19_questions.txt with AoC_Toolbox; -- Note: this solution uses a cache for "memoizing" -- the nodes which were already computed. -- Total run time with GNAT: 58 seconds. -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; with Ada.Containers.Hashed_Maps; procedure AoC_2022_19_Full_Ada is use AoC_Toolbox, HAT; verbosity_level : constant Natural := 1; T0 : constant Time := Clock; r : array (1 .. 2) of Integer; f : File_Type; -- Parseable copy of the example (part after column with '|'): -- -- |Blueprint 1: -- | Each ore robot costs 4 ore. -- | Each clay robot costs 2 ore. -- | Each obsidian robot costs 3 ore and 14 clay. -- | Each geode robot costs 2 ore and 7 obsidian. -- | -- |Blueprint 2: -- | Each ore robot costs 2 ore. -- | Each clay robot costs 3 ore. -- | Each obsidian robot costs 3 ore and 8 clay. -- | Each geode robot costs 3 ore and 12 obsidian. type Resource_Type is (ore, clay, obsidian, geode); type Portfolio_Type is array (Resource_Type) of Natural; type State_Type is record resource : Portfolio_Type; robot : Portfolio_Type; time_left : Natural; end record; function State_Hash (s : State_Type) return Ada.Containers.Hash_Type with Inline is use Ada.Containers; x : Hash_Type := 0; multiplier : constant := 37; -- Can be any value: Hash_Type does not overflow. begin for res in Resource_Type loop x := x * multiplier + Hash_Type (s.robot (res)); x := x * multiplier + Hash_Type (s.resource (res)); end loop; return x * multiplier + Hash_Type (s.time_left); end State_Hash; package State_Maps is new Ada.Containers.Hashed_Maps (State_Type, Natural, State_Hash, "="); subtype Cost_Type is Portfolio_Type; -- Costs of a robot producing a certain resource. type Blueprint_Type is array (Resource_Type) of Cost_Type; function Best_Geode_Opening (blueprint : Blueprint_Type; total_time : Positive) return Natural is initial : State_Type; obsidian_cost_geode_robot, clay_cost_obsidian_robot : Positive; greedy : constant Boolean := True; cache : State_Maps.Map; procedure Visit (state : State_Type; geodes : out Natural) is robot_creation_possible, any_possible : Boolean; score_build_robot : array (Resource_Type) of Natural; score_same_robots : Natural; new_state : State_Type; result : Natural; cursor : State_Maps.Cursor; use State_Maps; begin case state.time_left is when 0 => geodes := state.resource (geode); return; -- Some recursion breakers on desperately unefficient scenarios when 1 => if state.robot (geode) = 0 then -- There is not even a single geode-breaking robot in the last minute. geodes := 0; return; end if; when 2 => if state.robot (obsidian) = 0 then -- There is not even a single obsidian-collecting robot -- in the needed time to construct the first geode-breaking robot -- and produce the first geode. geodes := 0; return; end if; if state.robot (geode) = 0 then -- No geode-breaking robot? Fair enough, we contruct one. if state.resource (obsidian) < obsidian_cost_geode_robot then -- There is not enough obsidian to construct the -- first geode-breaking robot. geodes := 0; return; end if; end if; when 3 => if state.robot (clay) = 0 then -- Too late for the first clay robot. geodes := 0; return; end if; if state.robot (obsidian) = 0 then if state.resource (clay) < clay_cost_obsidian_robot then -- Not enough clay to construct the first obsidian-collecting robot. geodes := 0; return; end if; end if; if state.robot (geode) = 0 then if state.resource (obsidian) + state.robot (obsidian) < obsidian_cost_geode_robot then -- There won't be not enough obsidian on next step to construct the -- first geode-breaking robot. geodes := 0; return; end if; end if; when others => null; end case; cursor := cache.Find (state); if cursor /= No_Element then geodes := Element (cursor); return; end if; any_possible := False; for new_robot in Resource_Type loop score_build_robot (new_robot) := 0; robot_creation_possible := False; if state.resource (ore) >= blueprint (new_robot)(ore) then case new_robot is when ore | clay => new_state := state; new_state.resource (ore) := new_state.resource (ore) - blueprint (new_robot)(ore); robot_creation_possible := True; when obsidian => if state.resource (clay) >= blueprint (obsidian)(clay) then new_state := state; new_state.resource (ore) := new_state.resource (ore) - blueprint (obsidian)(ore); new_state.resource (clay) := new_state.resource (clay) - blueprint (obsidian)(clay); robot_creation_possible := True; end if; when geode => if state.resource (obsidian) >= blueprint (geode)(obsidian) then new_state := state; new_state.resource (ore) := new_state.resource (ore) - blueprint (geode)(ore); new_state.resource (obsidian) := new_state.resource (obsidian) - blueprint (geode)(obsidian); robot_creation_possible := True; end if; end case; end if; if robot_creation_possible then -- Earn new resources for res in Resource_Type loop new_state.resource (res) := new_state.resource (res) + new_state.robot (res); end loop; new_state.robot (new_robot) := new_state.robot (new_robot) + 1; new_state.time_left := new_state.time_left - 1; Visit (new_state, score_build_robot (new_robot)); end if; any_possible := any_possible or robot_creation_possible; end loop; -- Variant without constructing a new robot. if greedy and then any_possible then -- We ignore this variant if it is possible to construct a robot. score_same_robots := 0; else new_state := state; -- Earn new resources for res in Resource_Type loop new_state.resource (res) := new_state.resource (res) + new_state.robot (res); end loop; new_state.time_left := new_state.time_left - 1; Visit (new_state, score_same_robots); end if; -- Find max: result := score_same_robots; for res in Resource_Type loop result := Max (result, score_build_robot (res)); end loop; geodes := result; cache.Insert (state, result); end Visit; max_geodes : Natural; begin for r in Resource_Type loop initial.robot (r) := 0; initial.resource (r) := 0; end loop; initial.robot (ore) := 1; initial.time_left := total_time; obsidian_cost_geode_robot := blueprint (geode)(obsidian); clay_cost_obsidian_robot := blueprint (obsidian)(clay); -- put(min_time_to_collect_enough_obsidian); -- put(min_time_to_collect_enough_clay); -- new_line; Visit (initial, max_geodes); return max_geodes; end Best_Geode_Opening; last : Natural := 0; blueprint : array (1 .. 30) of Blueprint_Type; best : Natural; begin Open (f, "aoc_2022_19.txt"); Read_Data : while not End_Of_File (f) loop Skip_till_Space (f, 6); exit Read_Data when End_Of_File (f); last := last + 1; for robot in Resource_Type loop for cost in Resource_Type loop blueprint (last)(robot)(cost) := 0; end loop; end loop; Get (f, blueprint (last)(ore)(ore)); Skip_till_Space (f, 6); Get (f, blueprint (last)(clay)(ore)); Skip_till_Space (f, 6); Get (f, blueprint (last)(obsidian)(ore)); Skip_till_Space (f, 3); Get (f, blueprint (last)(obsidian)(clay)); Skip_till_Space (f, 6); Get (f, blueprint (last)(geode)(ore)); Skip_till_Space (f, 3); Get (f, blueprint (last)(geode)(obsidian)); Skip_till_Space (f, 1); end loop Read_Data; Close (f); r (1) := 0; r (2) := 1; for b in 1 .. last loop best := Best_Geode_Opening (blueprint (b), 24); if verbosity_level > 0 then Put_Line (+"In 24 steps (minutes), blueprint #" & b & ": " & best & " geodes cracked, T = " & (Clock - T0)); end if; r (1) := r (1) + b * best; if b <= 3 then best := Best_Geode_Opening (blueprint (b), 32); if verbosity_level > 0 then Put_Line (+"In 32 steps (minutes), blueprint #" & b & ": " & best & " geodes cracked, T = " & (Clock - T0)); end if; r (2) := r (2) * best; end if; end loop; if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer'Value (To_String (Argument (1))) or r (2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1 (24 minutes):" & r (1)'Image); Put_Line (+"Part 2 (32 minutes):" & r (2)'Image); -- Part 1: validated by AoC: 1192 -- Part 2: validated by AoC: 14725 end if; end AoC_2022_19_Full_Ada; ================================================ FILE: exm/aoc/2022/aoc_2022_19_questions.txt ================================================ --- Day 19: Not Enough Minerals --- Your scans show that the lava did indeed form obsidian! The wind has changed direction enough to stop sending lava droplets toward you, so you and the elephants exit the cave. As you do, you notice a collection of geodes around the pond. Perhaps you could use the obsidian to create some geode-cracking robots and break them open? To collect the obsidian from the bottom of the pond, you'll need waterproof obsidian-collecting robots. Fortunately, there is an abundant amount of clay nearby that you can use to make them waterproof. In order to harvest the clay, you'll need special-purpose clay-collecting robots. To make any type of robot, you'll need ore, which is also plentiful but in the opposite direction from the clay. Collecting ore requires ore-collecting robots with big drills. Fortunately, you have exactly one ore-collecting robot in your pack that you can use to kickstart the whole operation. Each robot can collect 1 of its resource type per minute. It also takes one minute for the robot factory (also conveniently from your pack) to construct any type of robot, although it consumes the necessary resources available when construction begins. The robot factory has many blueprints (your puzzle input) you can choose from, but once you've configured it with a blueprint, you can't change it. You'll need to work out which blueprint is best. For example: Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian. Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian. (Blueprints have been line-wrapped here for legibility. The robot factory's actual assortment of blueprints are provided one blueprint per line.) The elephants are starting to look hungry, so you shouldn't take too long; you need to figure out which blueprint would maximize the number of opened geodes after 24 minutes by figuring out which robots to build and when to build them. Using blueprint 1 in the example above, the largest number of geodes you could open in 24 minutes is 9. One way to achieve that is: == Minute 1 == 1 ore-collecting robot collects 1 ore; you now have 1 ore. == Minute 2 == 1 ore-collecting robot collects 1 ore; you now have 2 ore. == Minute 3 == Spend 2 ore to start building a clay-collecting robot. 1 ore-collecting robot collects 1 ore; you now have 1 ore. The new clay-collecting robot is ready; you now have 1 of them. == Minute 4 == 1 ore-collecting robot collects 1 ore; you now have 2 ore. 1 clay-collecting robot collects 1 clay; you now have 1 clay. == Minute 5 == Spend 2 ore to start building a clay-collecting robot. 1 ore-collecting robot collects 1 ore; you now have 1 ore. 1 clay-collecting robot collects 1 clay; you now have 2 clay. The new clay-collecting robot is ready; you now have 2 of them. == Minute 6 == 1 ore-collecting robot collects 1 ore; you now have 2 ore. 2 clay-collecting robots collect 2 clay; you now have 4 clay. == Minute 7 == Spend 2 ore to start building a clay-collecting robot. 1 ore-collecting robot collects 1 ore; you now have 1 ore. 2 clay-collecting robots collect 2 clay; you now have 6 clay. The new clay-collecting robot is ready; you now have 3 of them. == Minute 8 == 1 ore-collecting robot collects 1 ore; you now have 2 ore. 3 clay-collecting robots collect 3 clay; you now have 9 clay. == Minute 9 == 1 ore-collecting robot collects 1 ore; you now have 3 ore. 3 clay-collecting robots collect 3 clay; you now have 12 clay. == Minute 10 == 1 ore-collecting robot collects 1 ore; you now have 4 ore. 3 clay-collecting robots collect 3 clay; you now have 15 clay. == Minute 11 == Spend 3 ore and 14 clay to start building an obsidian-collecting robot. 1 ore-collecting robot collects 1 ore; you now have 2 ore. 3 clay-collecting robots collect 3 clay; you now have 4 clay. The new obsidian-collecting robot is ready; you now have 1 of them. == Minute 12 == Spend 2 ore to start building a clay-collecting robot. 1 ore-collecting robot collects 1 ore; you now have 1 ore. 3 clay-collecting robots collect 3 clay; you now have 7 clay. 1 obsidian-collecting robot collects 1 obsidian; you now have 1 obsidian. The new clay-collecting robot is ready; you now have 4 of them. == Minute 13 == 1 ore-collecting robot collects 1 ore; you now have 2 ore. 4 clay-collecting robots collect 4 clay; you now have 11 clay. 1 obsidian-collecting robot collects 1 obsidian; you now have 2 obsidian. == Minute 14 == 1 ore-collecting robot collects 1 ore; you now have 3 ore. 4 clay-collecting robots collect 4 clay; you now have 15 clay. 1 obsidian-collecting robot collects 1 obsidian; you now have 3 obsidian. == Minute 15 == Spend 3 ore and 14 clay to start building an obsidian-collecting robot. 1 ore-collecting robot collects 1 ore; you now have 1 ore. 4 clay-collecting robots collect 4 clay; you now have 5 clay. 1 obsidian-collecting robot collects 1 obsidian; you now have 4 obsidian. The new obsidian-collecting robot is ready; you now have 2 of them. == Minute 16 == 1 ore-collecting robot collects 1 ore; you now have 2 ore. 4 clay-collecting robots collect 4 clay; you now have 9 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 6 obsidian. == Minute 17 == 1 ore-collecting robot collects 1 ore; you now have 3 ore. 4 clay-collecting robots collect 4 clay; you now have 13 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 8 obsidian. == Minute 18 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 1 ore-collecting robot collects 1 ore; you now have 2 ore. 4 clay-collecting robots collect 4 clay; you now have 17 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 3 obsidian. The new geode-cracking robot is ready; you now have 1 of them. == Minute 19 == 1 ore-collecting robot collects 1 ore; you now have 3 ore. 4 clay-collecting robots collect 4 clay; you now have 21 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 5 obsidian. 1 geode-cracking robot cracks 1 geode; you now have 1 open geode. == Minute 20 == 1 ore-collecting robot collects 1 ore; you now have 4 ore. 4 clay-collecting robots collect 4 clay; you now have 25 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 7 obsidian. 1 geode-cracking robot cracks 1 geode; you now have 2 open geodes. == Minute 21 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 1 ore-collecting robot collects 1 ore; you now have 3 ore. 4 clay-collecting robots collect 4 clay; you now have 29 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 2 obsidian. 1 geode-cracking robot cracks 1 geode; you now have 3 open geodes. The new geode-cracking robot is ready; you now have 2 of them. == Minute 22 == 1 ore-collecting robot collects 1 ore; you now have 4 ore. 4 clay-collecting robots collect 4 clay; you now have 33 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 4 obsidian. 2 geode-cracking robots crack 2 geodes; you now have 5 open geodes. == Minute 23 == 1 ore-collecting robot collects 1 ore; you now have 5 ore. 4 clay-collecting robots collect 4 clay; you now have 37 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 6 obsidian. 2 geode-cracking robots crack 2 geodes; you now have 7 open geodes. == Minute 24 == 1 ore-collecting robot collects 1 ore; you now have 6 ore. 4 clay-collecting robots collect 4 clay; you now have 41 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 8 obsidian. 2 geode-cracking robots crack 2 geodes; you now have 9 open geodes. However, by using blueprint 2 in the example above, you could do even better: the largest number of geodes you could open in 24 minutes is 12. Determine the quality level of each blueprint by multiplying that blueprint's ID number with the largest number of geodes that can be opened in 24 minutes using that blueprint. In this example, the first blueprint has ID 1 and can open 9 geodes, so its quality level is 9. The second blueprint has ID 2 and can open 12 geodes, so its quality level is 24. Finally, if you add up the quality levels of all of the blueprints in the list, you get 33. Determine the quality level of each blueprint using the largest number of geodes it could produce in 24 minutes. What do you get if you add up the quality level of all of the blueprints in your list? --- Part Two --- While you were choosing the best blueprint, the elephants found some food on their own, so you're not in as much of a hurry; you figure you probably have 32 minutes before the wind changes direction again and you'll need to get out of range of the erupting volcano. Unfortunately, one of the elephants ate most of your blueprint list! Now, only the first three blueprints in your list are intact. In 32 minutes, the largest number of geodes blueprint 1 (from the example above) can open is 56. One way to achieve that is: == Minute 1 == 1 ore-collecting robot collects 1 ore; you now have 1 ore. == Minute 2 == 1 ore-collecting robot collects 1 ore; you now have 2 ore. == Minute 3 == 1 ore-collecting robot collects 1 ore; you now have 3 ore. == Minute 4 == 1 ore-collecting robot collects 1 ore; you now have 4 ore. == Minute 5 == Spend 4 ore to start building an ore-collecting robot. 1 ore-collecting robot collects 1 ore; you now have 1 ore. The new ore-collecting robot is ready; you now have 2 of them. == Minute 6 == 2 ore-collecting robots collect 2 ore; you now have 3 ore. == Minute 7 == Spend 2 ore to start building a clay-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. The new clay-collecting robot is ready; you now have 1 of them. == Minute 8 == Spend 2 ore to start building a clay-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 1 clay-collecting robot collects 1 clay; you now have 1 clay. The new clay-collecting robot is ready; you now have 2 of them. == Minute 9 == Spend 2 ore to start building a clay-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 2 clay-collecting robots collect 2 clay; you now have 3 clay. The new clay-collecting robot is ready; you now have 3 of them. == Minute 10 == Spend 2 ore to start building a clay-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 3 clay-collecting robots collect 3 clay; you now have 6 clay. The new clay-collecting robot is ready; you now have 4 of them. == Minute 11 == Spend 2 ore to start building a clay-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 4 clay-collecting robots collect 4 clay; you now have 10 clay. The new clay-collecting robot is ready; you now have 5 of them. == Minute 12 == Spend 2 ore to start building a clay-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 5 clay-collecting robots collect 5 clay; you now have 15 clay. The new clay-collecting robot is ready; you now have 6 of them. == Minute 13 == Spend 2 ore to start building a clay-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 6 clay-collecting robots collect 6 clay; you now have 21 clay. The new clay-collecting robot is ready; you now have 7 of them. == Minute 14 == Spend 3 ore and 14 clay to start building an obsidian-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 2 ore. 7 clay-collecting robots collect 7 clay; you now have 14 clay. The new obsidian-collecting robot is ready; you now have 1 of them. == Minute 15 == 2 ore-collecting robots collect 2 ore; you now have 4 ore. 7 clay-collecting robots collect 7 clay; you now have 21 clay. 1 obsidian-collecting robot collects 1 obsidian; you now have 1 obsidian. == Minute 16 == Spend 3 ore and 14 clay to start building an obsidian-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 7 clay-collecting robots collect 7 clay; you now have 14 clay. 1 obsidian-collecting robot collects 1 obsidian; you now have 2 obsidian. The new obsidian-collecting robot is ready; you now have 2 of them. == Minute 17 == Spend 3 ore and 14 clay to start building an obsidian-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 2 ore. 7 clay-collecting robots collect 7 clay; you now have 7 clay. 2 obsidian-collecting robots collect 2 obsidian; you now have 4 obsidian. The new obsidian-collecting robot is ready; you now have 3 of them. == Minute 18 == 2 ore-collecting robots collect 2 ore; you now have 4 ore. 7 clay-collecting robots collect 7 clay; you now have 14 clay. 3 obsidian-collecting robots collect 3 obsidian; you now have 7 obsidian. == Minute 19 == Spend 3 ore and 14 clay to start building an obsidian-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 7 clay-collecting robots collect 7 clay; you now have 7 clay. 3 obsidian-collecting robots collect 3 obsidian; you now have 10 obsidian. The new obsidian-collecting robot is ready; you now have 4 of them. == Minute 20 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 3 ore. 7 clay-collecting robots collect 7 clay; you now have 14 clay. 4 obsidian-collecting robots collect 4 obsidian; you now have 7 obsidian. The new geode-cracking robot is ready; you now have 1 of them. == Minute 21 == Spend 3 ore and 14 clay to start building an obsidian-collecting robot. 2 ore-collecting robots collect 2 ore; you now have 2 ore. 7 clay-collecting robots collect 7 clay; you now have 7 clay. 4 obsidian-collecting robots collect 4 obsidian; you now have 11 obsidian. 1 geode-cracking robot cracks 1 geode; you now have 1 open geode. The new obsidian-collecting robot is ready; you now have 5 of them. == Minute 22 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 2 ore. 7 clay-collecting robots collect 7 clay; you now have 14 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 9 obsidian. 1 geode-cracking robot cracks 1 geode; you now have 2 open geodes. The new geode-cracking robot is ready; you now have 2 of them. == Minute 23 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 2 ore. 7 clay-collecting robots collect 7 clay; you now have 21 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 7 obsidian. 2 geode-cracking robots crack 2 geodes; you now have 4 open geodes. The new geode-cracking robot is ready; you now have 3 of them. == Minute 24 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 2 ore. 7 clay-collecting robots collect 7 clay; you now have 28 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 5 obsidian. 3 geode-cracking robots crack 3 geodes; you now have 7 open geodes. The new geode-cracking robot is ready; you now have 4 of them. == Minute 25 == 2 ore-collecting robots collect 2 ore; you now have 4 ore. 7 clay-collecting robots collect 7 clay; you now have 35 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 10 obsidian. 4 geode-cracking robots crack 4 geodes; you now have 11 open geodes. == Minute 26 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 4 ore. 7 clay-collecting robots collect 7 clay; you now have 42 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 8 obsidian. 4 geode-cracking robots crack 4 geodes; you now have 15 open geodes. The new geode-cracking robot is ready; you now have 5 of them. == Minute 27 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 4 ore. 7 clay-collecting robots collect 7 clay; you now have 49 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 6 obsidian. 5 geode-cracking robots crack 5 geodes; you now have 20 open geodes. The new geode-cracking robot is ready; you now have 6 of them. == Minute 28 == 2 ore-collecting robots collect 2 ore; you now have 6 ore. 7 clay-collecting robots collect 7 clay; you now have 56 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 11 obsidian. 6 geode-cracking robots crack 6 geodes; you now have 26 open geodes. == Minute 29 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 6 ore. 7 clay-collecting robots collect 7 clay; you now have 63 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 9 obsidian. 6 geode-cracking robots crack 6 geodes; you now have 32 open geodes. The new geode-cracking robot is ready; you now have 7 of them. == Minute 30 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 6 ore. 7 clay-collecting robots collect 7 clay; you now have 70 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 7 obsidian. 7 geode-cracking robots crack 7 geodes; you now have 39 open geodes. The new geode-cracking robot is ready; you now have 8 of them. == Minute 31 == Spend 2 ore and 7 obsidian to start building a geode-cracking robot. 2 ore-collecting robots collect 2 ore; you now have 6 ore. 7 clay-collecting robots collect 7 clay; you now have 77 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 5 obsidian. 8 geode-cracking robots crack 8 geodes; you now have 47 open geodes. The new geode-cracking robot is ready; you now have 9 of them. == Minute 32 == 2 ore-collecting robots collect 2 ore; you now have 8 ore. 7 clay-collecting robots collect 7 clay; you now have 84 clay. 5 obsidian-collecting robots collect 5 obsidian; you now have 10 obsidian. 9 geode-cracking robots crack 9 geodes; you now have 56 open geodes. However, blueprint 2 from the example above is still better; using it, the largest number of geodes you could open in 32 minutes is 62. You no longer have enough blueprints to worry about quality levels. Instead, for each of the first three blueprints, determine the largest number of geodes you could open; then, multiply these three values together. Don't worry about quality levels; instead, just determine the largest number of geodes you could open using each of the first three blueprints. What do you get if you multiply these numbers together? ================================================ FILE: exm/aoc/2022/aoc_2022_20.adb ================================================ -- Solution to Advent of Code 2022, Day 20 ------------------------------------------- -- Grove Positioning System -- -- https://adventofcode.com/2022/day/20 -- Copy of questions in: aoc_2022_20_questions.txt -- -- This problem resembles to the Crab Cups puzzle (AoC_2020_23). -- -- Note: this solution takes a large amount of time -- with HAC (62 seconds). -- Fortunately, you can compile it with GNAT and -- the total run-time is there 0.29 seconds on an i7 machine. -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; -- Interfaces is needed for compiling on both -- HAC and GNAT (64-bit integer: Integer_64): with Interfaces; procedure AoC_2022_20 is use HAT, Interfaces; verbosity_level : constant Natural := 0; info_max : constant := 5000; subtype Extended_Info_Range is Integer range -1 .. info_max; subtype Info_Range is Integer range 0 .. info_max; type Info is record label : Integer; prev : Extended_Info_Range; next : Info_Range; end record; type Info_Array is array (Info_Range) of Info; data, o : Info_Array; last : Extended_Info_Range := -1; procedure Show is cursor : Info_Range; begin cursor := 0; for count in 0 .. last loop Put (o (cursor).label, 0); if count < last then Put (", "); end if; cursor := o (cursor).next; end loop; New_Line; end Show; f : File_Type; new_prev, new_next, total, zero_position, cursor : Info_Range; rounds : Positive; skip, decryption_key : Integer_64; r : array (1 .. 2) of Integer_64; T0 : constant Time := Clock; begin Open (f, "aoc_2022_20.txt"); Read_Data : while not End_Of_File (f) loop last := last + 1; Get (f, data (last).label); if data (last).label = 0 then zero_position := last; end if; data (last).prev := last - 1; data (last).next := last + 1; end loop Read_Data; Close (f); data (0).prev := last; data (last).next := 0; total := last + 1; if verbosity_level > 0 then Show; end if; Parts : for part in 1 .. 2 loop o := data; -- Play: case part is when 1 => rounds := 1; decryption_key := 1; when 2 => rounds := 10; decryption_key := 811589153; end case; Multiple_Rounds : for round in 1 .. rounds loop Single_Round : for i in 0 .. last loop -- Remove node i: o (o (i).prev).next := o (i).next; o (o (i).next).prev := o (i).prev; -- Find the new neighbours for node i: new_prev := o (i).prev; skip := Integer_64 (o (i).label); if part = 2 then skip := skip * decryption_key; end if; skip := skip mod Integer_64 (total - 1); -- ^ Banana skin here: "mod (total - 1)" and not -- "mod total", because we have one node less! for count in 1 .. skip loop new_prev := o (new_prev).next; end loop; new_next := o (new_prev).next; -- Relink node i: o (i).next := new_next; o (i).prev := new_prev; -- Insert node i: o (new_prev).next := i; o (new_next).prev := i; -- Display: if verbosity_level > 0 then Show; end if; end loop Single_Round; end loop Multiple_Rounds; cursor := zero_position; r (part) := 0; for thousands in 1 .. 3 loop for count in 1 .. 1000 mod total loop cursor := o (cursor).next; end loop; r (part) := r (part) + Integer_64 (o (cursor).label) * decryption_key; end loop; end loop Parts; if Argument_Count >= 2 then -- Compiler test mode. if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & Integer_64'Image (r (1))); Put_Line (+"Part 2:" & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 2215 -- Part 2: validated by AoC: 8927480683 end if; end AoC_2022_20; ================================================ FILE: exm/aoc/2022/aoc_2022_20.txt ================================================ -2312 5492 793 -773 5453 -2076 -1728 -7702 4318 8316 -3366 -3814 9182 -673 -8201 7847 9691 4044 802 -8114 8944 -2438 -3460 -6923 -4847 -7341 2063 -9848 6702 2560 6058 -7669 7315 -6427 5165 3147 -1320 4789 6296 -806 1185 -1445 -982 2759 -8506 -5959 5683 -6623 -8571 -5834 -9022 8729 -7420 -9812 -9162 -240 7302 2221 -4352 -4248 5177 9037 -6880 -2117 9569 -1037 726 2866 -4587 3384 998 9665 3982 3169 4547 612 2857 -2601 -982 -4267 -740 2817 -818 -8005 -3697 497 -8039 -116 8438 -8460 2609 709 3590 1323 2202 -1246 -736 -3992 7811 127 -2609 8314 -5668 -6449 -6512 3972 -5998 -7462 4542 -6350 8424 5046 -3554 6481 -4521 1307 -172 -7391 79 -179 -7320 9750 -5916 8531 5522 5133 -1506 4151 -2793 5448 -2267 998 -6216 3894 -1297 7112 8486 -6030 -1815 -1451 4165 828 8678 -1751 -9528 5056 -9702 9288 8683 -1924 -6171 -7050 -9968 -3909 -9834 -8325 -2528 -2247 -1075 6684 6038 -6309 -3562 2333 3593 -18 -9857 -4318 6923 -5266 1408 -7781 2037 -519 4085 7054 -4111 2817 -5375 870 -8252 4142 3500 -9371 -2040 -7381 6216 7143 -6814 673 3104 -1693 6050 -2416 7112 4114 5367 4566 2560 4361 4131 4337 7876 -3000 -8724 -2088 6785 -5326 -7107 3739 -302 9519 -5331 8759 6867 -9267 4816 -749 -1980 1830 9715 1634 -6922 -288 4436 63 -156 1185 -5004 -9093 -8661 8447 233 -854 3154 -5589 -5490 2321 -1006 3688 6313 4704 6598 430 -7073 -6571 -3768 6203 8453 8735 -4070 8059 -4734 -1827 1330 586 -8858 1938 1366 6031 3744 -7191 8032 3586 -3196 -460 3032 2387 450 1391 -3905 -2774 6690 -9103 8220 -6594 8834 -3559 -9337 2199 -9026 2904 -8552 499 7727 6519 -17 -3625 -302 4611 9129 9756 6869 -2262 -4677 3533 19 5877 5224 3783 5992 -2218 -5097 3956 9335 -5586 -9441 3252 -4307 -1111 6509 -116 -4926 -7394 1270 -1773 6658 3317 -8704 -3692 6482 2451 7241 -350 -5042 -9182 2602 9752 -8475 -5018 -267 -9360 599 917 5210 4388 909 -1063 8311 1831 8235 -9129 -7420 -284 -1940 4079 -7284 -4893 4913 -8602 -59 6105 -4934 1196 -6947 -1508 -8961 2112 -6739 -8401 9750 -3697 85 2240 -5882 -1900 3783 5747 4388 5225 6858 -3799 6119 8592 -3328 4716 -6391 -7721 4813 3223 6303 8780 4400 -7964 8810 8247 8776 -5738 -2655 -2036 9906 -6834 92 6695 1740 29 -9758 -7016 -8170 -7780 4243 -3391 2989 -7678 2154 -4515 4475 8011 -3785 -3518 5532 8387 806 -9546 655 804 -5420 4138 8495 8975 -2559 8202 8268 -6923 1671 -9892 6337 6205 6024 6038 -3289 4626 4356 -3104 7633 9404 -3630 -4041 106 -4493 3651 6983 -5958 819 6105 1910 4645 -1293 -8747 8655 -6928 9025 1984 -9959 -9290 -7834 3588 2967 3048 4730 -8653 -4434 6105 8028 -4909 -7865 -6832 -1267 8129 4131 -9615 -7137 3956 464 -588 5260 2181 -3581 649 8992 -6427 -3292 -5641 -8274 -2283 -3455 1417 7054 3937 -1797 -615 -2526 6210 6222 -6007 -3764 -1743 -3123 9495 8269 3675 1085 -1859 8578 -1240 -4734 1196 1332 -3507 -6268 3380 -6530 3264 -4958 -7533 8869 2666 -6780 7739 -4128 -8229 9624 -8005 -1897 -9773 8000 -419 269 5048 -5962 4319 6834 -9624 -5247 -2683 -9050 -5335 5244 -3052 929 -3922 -4806 -7085 4186 -5127 7790 527 -222 4043 9900 4630 5056 -9425 -2369 -1442 -7949 5228 7449 3945 726 -1722 -3439 -1037 -4998 -5130 5158 -227 -8075 3917 5228 9382 -7582 787 -2895 -7385 9750 -8872 -1263 5877 4398 9200 4061 8059 9960 5756 -3241 -2283 9568 -5852 -3630 -2336 -3596 4649 -7203 4473 -8025 -9991 -8721 1307 -5487 4632 1799 2468 2834 2571 -3894 7319 8466 -7831 -7428 5475 6296 9191 6193 -843 8566 9398 7317 -3984 -1886 -5012 4014 -3554 6002 -5254 8412 -4059 7761 -7363 9025 -1960 1905 -304 -2877 7707 -3120 8969 -545 -9237 885 3830 7085 -8779 9198 4123 517 480 -6380 9713 -2029 -947 -5205 -9126 -4653 5254 3153 2067 7872 -3545 1864 9068 4516 6440 -9167 4281 4859 -6318 -3155 8699 -5310 -38 -4889 -1805 -9405 -1235 3285 1579 1265 -850 259 1513 -1490 7916 -9000 -7515 2756 831 2387 -6922 -6299 8992 3336 4473 1728 1366 -2893 -8891 7818 -3140 2972 1088 2718 9495 64 7527 8638 -8670 6740 -2971 1849 5365 7997 2941 5528 8065 6973 -5858 1355 6359 -7757 -3968 -1985 -3194 1425 -6928 4616 -1912 -5892 -9337 -4007 -1299 5042 3825 -5517 5056 -9180 -4646 -843 6038 7750 -7705 1294 8809 6888 -1634 -8823 -2995 -7983 -7333 -7315 2240 -4881 497 -4026 -6921 714 4513 -2134 -4600 -4863 7388 -6344 -8589 9381 -7674 -9967 -9237 2679 -8598 -6741 7739 -7720 -1899 -5265 -5665 -2580 -8820 8550 9121 -1218 8832 -1776 -4814 -1570 -7969 -6529 8232 -4867 -638 -1263 3918 8720 -6378 -7501 3894 -663 3894 1264 555 -1139 9538 -7029 4909 1751 -6800 7761 6810 6708 -3571 7994 9707 5187 -3084 5458 -5274 -8246 5730 2425 7931 -6800 -6008 -2705 -5151 -6268 -1054 6176 -6809 7683 -4342 -7797 -6430 4127 -3148 7294 6188 8729 3463 3375 5648 788 3996 7650 8952 -7078 -8155 -6166 -3726 -2742 3845 1103 -5164 6507 -2219 4131 9421 -8277 7068 -8046 833 -684 -6160 -8604 -6384 -2081 940 3239 1962 3502 3576 -3320 -335 5644 -200 823 8320 -7803 6209 -7565 1042 769 -5705 7494 -4419 5726 5198 -6879 3377 -6890 -6072 -3633 -100 -8584 2961 -5839 8191 9055 -5330 -3082 -8589 -7126 -9861 7624 8486 -272 -1092 -3047 9349 6014 8554 -2986 1425 -2615 -1855 5442 -8509 9775 -8855 6313 -8060 -102 8809 2374 5400 7789 -6100 -1473 -916 -6715 -1828 -5649 6314 -1946 -895 8774 5894 -8284 3825 8737 500 -1468 2542 -7925 7775 9221 -2916 -9878 -6427 9800 -468 -8699 9798 9424 8910 8582 -8806 -4157 8620 -5136 -952 -9019 -6947 -601 -5789 -9535 6028 -8930 8466 -5689 3254 -4709 4394 2281 3362 2813 -5808 3420 6002 -9398 9653 5728 9204 -4846 -7691 -8087 6772 -451 -2286 2826 5945 -7702 9713 5468 4660 672 -1854 -3970 1905 3685 6425 5102 -7462 1913 6360 -8581 6604 9384 9117 2574 4436 -6263 8516 -2059 6378 -6492 4242 -9681 -6126 436 5520 9528 3885 1227 -8501 1230 -6933 -5230 -9432 -1313 -2136 -1379 1439 -2864 2839 3340 -226 -4206 9121 -9572 8567 -8298 7244 9526 -8506 -7922 -901 -523 -6310 2811 2324 -7384 8812 -916 2580 -2966 9885 -3400 -6277 -5818 -663 -7179 7344 6022 2865 -676 1375 8622 1965 -9990 -4255 5796 -3903 8008 -78 -4997 -460 8437 -6563 -5517 -1827 6257 -5413 -6169 6869 5890 9791 5425 -7310 7249 1175 4417 -527 4115 -834 9427 6924 731 -1537 -4632 -1218 3677 -8488 -946 -5430 580 4976 5132 8448 -3109 4014 -4493 -5671 6507 3688 -9214 -2641 3508 7581 -9640 -2308 3598 4940 -3843 -7364 -1693 2367 2589 9435 -7914 -5655 7388 379 6022 1899 2607 -6226 8992 1231 -8751 -4158 1888 -2145 -5874 -5713 -9526 1060 -3324 -834 8534 -1807 9906 1217 9946 1892 8556 6182 -2868 7988 -1555 -9400 2212 1311 6349 -9405 3703 9120 5284 4672 -8397 -7984 -5319 -7955 -1570 6475 -2479 266 -3865 3550 1313 5476 3052 9659 2696 -8760 6568 -5512 -4938 7835 -6933 1821 5033 3504 7070 -2016 1147 -2652 -4622 -4126 -9118 6462 1563 3285 8275 -8593 -4833 -1318 -6620 -2818 4893 5076 356 -4435 6210 9037 6929 -6950 -6710 -1735 3541 -5278 -1451 8176 885 -9108 -2591 -1165 660 2387 1829 3490 3048 7244 -6423 3571 -5055 -1272 -84 6388 2320 -4569 2382 5900 -7482 7915 5668 9089 9963 -6007 6337 -5863 -6139 -1803 -1863 8283 -8654 -7952 -6938 -5541 484 -8487 -3356 -2433 -9859 -1960 7112 8010 -7200 9261 5926 -2610 -7854 6988 -4258 -9209 -3029 6578 -1779 -6575 9899 4561 7564 -6399 -7750 -1276 -1242 9793 -1650 400 -4830 -9533 6806 2157 -5517 -9506 -1925 -519 5650 -8327 4683 788 7457 -4476 6695 -4255 7292 760 -8423 1603 -4258 6097 -567 5582 1323 -3113 9303 -3025 -8242 6039 8692 2309 -5558 -916 -7193 5906 -9774 8231 491 8404 -9325 -9261 4790 -5419 4394 -2174 -8130 6327 7412 6495 -5814 6741 -6791 9147 -828 -619 1841 1120 -9057 123 430 -3828 6360 5831 -5059 -7599 -6946 -9640 4733 2834 524 -5316 8832 -1566 -5477 -4370 1991 6716 8755 -3455 7821 -90 -8899 -7101 1785 -2925 1299 9571 -8319 8304 -1690 -6509 -5792 4825 6801 -1638 -4783 4784 -5668 4170 7228 -2326 9793 -4041 -9295 7134 -4845 528 3199 -1632 3372 -5856 -2582 7039 -7775 -6401 5747 -6986 2608 5091 -8261 -8431 -1591 -6165 4835 6467 312 9873 -6425 -9224 1633 8856 5961 -4968 8583 -268 -6396 6791 8721 -2141 -2248 -9119 4338 -9103 -3693 -706 -975 3854 -1136 8930 6511 -445 917 -1024 -3782 8406 2624 -9544 -4830 -5255 -9561 -2948 -1011 9056 8291 3320 -5316 1148 -8261 1330 -2145 -9226 -1257 1905 -3227 -6728 -6107 7278 -9645 879 -3758 4980 -7956 6640 4053 -7842 -6749 363 -6904 -3055 -768 7220 -5118 6750 7737 -3422 6328 4844 -2690 1113 -7072 3528 -4331 -5164 -4056 -4821 -982 2502 7885 -8553 9740 5105 -5824 2693 5459 2462 -3001 9783 6766 -9286 -6516 2307 -908 -1325 904 -84 -1526 278 7384 655 -4468 1264 4952 -5002 5700 -9261 -966 -438 -466 -3756 -9867 -2088 4125 1930 9294 -1243 -5604 -2422 -2385 9296 9426 6767 -6467 8846 -1315 7568 4391 85 -2167 -9427 -6613 -2586 2008 4540 9421 -7046 8466 -2939 6699 -8174 3384 -2700 3199 -4011 -8991 -1129 2216 8273 7977 -3962 -2334 -2747 7765 1765 -4471 1863 -6768 -7752 -5945 8593 -2225 2550 9650 8842 465 6133 -952 7479 5645 4520 -8873 4429 9857 -4567 -124 6193 -7916 -1299 1811 -5195 8974 -8604 6126 -7579 -7828 8882 -5002 -6102 3891 -589 -5697 7519 -1335 -311 -6777 5704 1962 -4950 9814 5400 610 -2093 7898 -6492 -1165 -1063 1658 -7184 -3384 5101 4733 1231 9255 -712 4122 4402 5443 3877 7541 4473 -3633 -9959 9260 9177 1788 -5986 -5165 8969 6031 741 -7417 7002 6992 -4374 -8995 2832 2250 2221 -2791 -2287 -9125 -1692 4930 -443 4349 -8602 3553 9117 8304 209 6650 745 1058 -3994 -7437 8476 -7390 -6864 2467 1798 -292 -6487 2954 -3029 1192 -1955 4256 5615 4335 7948 -7963 -831 8499 -1778 5063 2069 610 6032 1447 6898 2154 -6397 7996 -7809 -3279 6789 7245 8794 -7078 -1434 -3953 -3029 7262 -4640 4742 -1063 7790 2320 -1721 6128 -4219 7482 3385 -2949 -6830 -1522 -3530 -9002 -4798 7347 7847 -8651 9432 1612 -5705 -9216 -5384 -2064 7739 7113 6250 7192 2927 7901 -2990 -736 3892 -2641 7870 5061 4500 278 3569 5059 -8721 9991 1219 -1289 -6273 -8618 -9085 6235 -7551 -2850 -7188 -9828 2381 -1298 -5671 -2114 -3312 -5589 -394 8484 -4008 3378 -9841 -3357 6888 4421 -5959 -2719 -5031 1945 5058 1732 8774 -9907 9240 3189 -8103 8526 -7588 6113 -9506 1096 -7420 5688 -3131 -8204 4321 1860 -3439 5902 5484 -7310 7544 -9184 3579 -8311 9400 -2046 3613 2834 -3828 4483 -3687 2474 9175 5682 2134 8178 4669 -8999 4089 3745 6187 -3255 4496 -4086 -5667 -4719 -9530 57 -5557 -1809 4683 -6874 9649 238 -5274 2548 -1610 2406 6760 3829 -6658 -7076 -8907 -8252 4473 -6559 9751 9946 -1815 -4719 6440 -3154 -4584 -8861 5988 -6730 5975 -6449 3127 6406 7501 -4504 -5805 -8832 3352 -3961 -3453 9800 -8757 -9250 5575 -1894 -1130 2529 2060 819 8152 -6329 -6967 -451 -3261 1670 4090 -6879 -638 -5435 2187 3891 5504 4337 3137 -9570 2350 9955 5628 8522 -165 -7442 -5330 8494 -8458 5667 -3922 -5440 -7066 7265 -8704 490 -5609 -768 1537 -7702 5884 -1198 4784 1935 -9959 3985 -1213 -518 -7078 -9683 -4973 -2189 9598 -4616 7220 3335 8211 7294 -5295 4813 -3329 2697 5383 -2611 4052 -9056 5442 -5822 8230 2860 2797 2893 1320 7805 9598 -6575 1307 -3383 7434 7853 -6166 2096 -2921 -8558 2689 -2719 9225 -2812 -7176 6243 -7995 -7186 8770 -953 -3986 9430 -9280 5951 254 9268 1664 6491 8121 -6876 2805 -265 8954 5634 -4938 -6880 7449 -9839 6036 4772 -5325 3763 -3455 -8766 1458 -605 -6746 7846 -8180 8340 9269 7054 -5084 -98 9491 2893 -8571 3179 2972 -9473 1502 9398 -621 1562 -1657 1670 9896 7344 -9187 -2085 -2781 342 -9159 6214 802 -2429 -7600 4489 -7485 -4674 2709 -446 -8240 9394 8159 -4058 5910 -1281 9760 -6626 5440 4697 -5100 6509 4256 -4904 244 1154 -7067 -4251 -4759 5617 -8546 8747 5770 -4909 1447 612 -8622 2866 -2947 -1800 -8985 -3800 -6839 -1256 -8119 6427 8187 -4392 -2980 -7103 -2337 5830 -3644 4052 4591 -2181 6072 6905 5783 -3905 -9064 -3083 4615 -3437 1133 3153 -1922 -4065 -8069 -6436 7889 4440 -7021 -638 -5127 8977 2839 6777 7054 -5443 3666 -9640 -1863 -2244 -8397 6744 9748 5783 7727 -6548 7052 -4846 -7240 8565 -6165 -9038 2975 -6850 -8567 -7842 4297 -474 -5606 -4723 -203 -4902 6313 92 -784 -5997 -2915 -6920 -8873 -5885 85 -3035 8715 3763 -4255 6210 5214 3284 -5662 -585 2621 3569 8826 -9532 -9323 1430 159 -1831 -373 -5837 -6559 2129 -6731 2932 -9463 7930 -5585 9567 2601 -6215 -4804 9927 -8269 -9660 6692 7859 855 -3444 -545 -1924 3776 6273 7774 400 5129 6999 -8423 -243 8011 7236 -555 9279 2752 4931 4728 8293 6421 4497 3458 -8929 9792 -1333 -4216 1379 -6254 8851 9346 8174 5712 1899 4115 4437 -7151 6917 9104 -5838 -1454 779 8637 7494 -7076 7365 3931 -2719 8075 -5323 -7745 9761 -5792 5746 5575 9704 -9334 -8704 9364 -4196 4914 3552 -6741 -7272 3199 6427 -3097 -2195 -3535 -5885 -7161 -4290 -5912 5957 9337 -6472 9037 5573 2384 2474 5497 5889 -9663 -5332 5913 -48 3398 6039 -1025 4567 -1689 -7643 8403 6422 2666 4681 7571 9306 -4140 8668 5961 1728 9600 4567 -9947 7947 2311 7683 4036 -9118 -1440 7701 -718 7252 -5748 8074 9077 1430 309 7223 7241 6924 -1726 2580 323 9592 -147 9734 -6509 -2141 9899 8912 -9095 -1534 -1722 -6731 -4674 -5668 9543 2181 -5971 -4285 -5435 8785 6022 3483 3442 -4311 -9718 491 -234 -6505 -2233 1054 1843 -8170 3725 9367 -9708 2884 575 1466 -4904 -7163 -6509 -9898 -1035 4218 -3782 -7972 4094 -4022 7344 3528 6745 -8677 -564 599 -1588 -638 -2547 7384 -3223 -8978 -3131 2367 38 4294 2227 -4687 -8416 -7749 -901 5156 5381 7208 9451 -1072 -6165 4274 -9330 -5692 -976 8507 -4214 3267 -693 4016 -4859 4131 2624 -2195 -5747 -3433 -5309 4909 -1789 1970 1113 6654 9294 580 2701 -3072 -1058 -450 -3553 8842 -6902 5849 -8210 3129 -4568 7319 9289 1953 -2772 3176 7831 -5215 -7078 -269 -9613 -5990 140 -3349 -1868 -6378 7029 3786 9495 4946 -3908 5746 7246 6543 3375 -6525 3179 4829 -5690 -4458 -5067 3563 -9505 8886 -6046 8975 -9892 4232 -3386 6748 5560 -5068 -4307 8256 -4803 6559 -726 7262 3603 -6032 -1753 1072 -3515 1160 -4265 8809 7319 -2341 -4621 -5593 4672 -7252 7876 -2824 -2708 151 6484 2609 2708 -9044 -7454 4473 -3075 -5664 1659 9212 -8951 -3382 8762 7569 -2142 -3045 -7361 110 6810 1104 -373 -4500 -9051 -3242 2221 5025 -4297 -6710 7853 -6452 7998 -9213 -7520 -6727 5334 1096 678 -4395 7679 -4022 6257 -3939 9591 8016 -4342 8010 5402 1423 8834 6389 9001 5102 3868 -7905 8265 -2083 6772 -8806 -1136 -5612 -5127 -7981 -5655 480 -3419 368 -2090 5293 7052 4686 3386 -708 3991 -684 -2381 4228 -9954 -9993 4285 -6467 6787 -3366 -4653 -3731 -4257 -1246 3925 2320 1536 -3196 -1374 -5465 -7690 -716 1929 859 3442 3500 -6460 7761 5628 -4119 4069 9037 105 9498 8235 -2437 3472 -5420 -6518 3972 -7627 -8503 6050 4393 -8440 1986 2187 -5589 2686 3888 -9356 -543 2822 5302 -7034 -7778 9334 -5462 -267 -6891 -2707 7407 8805 7388 6184 3346 6847 -5971 -417 -3326 -1592 5544 -6800 7034 -5441 -9441 -6987 1815 5783 6926 -4314 -9892 -1500 2904 -1946 -9074 -7659 -4333 -3553 -916 3237 -7151 -6030 -8337 418 -9384 1192 2558 7496 -7729 8273 9305 3827 7519 2133 1879 1001 258 -3963 119 4186 5239 -7204 7704 9534 -8682 -4772 -7978 5929 6107 506 1760 5782 5895 -3687 -78 -7125 -534 -4774 6218 9585 8200 -5340 -9302 3559 8846 3552 1671 -5477 -9118 7790 -3757 8365 7394 8465 7245 3956 -592 2205 -5882 6476 -5732 -6477 6713 4709 4714 7356 -1080 -983 -9975 -8190 -7574 828 -6316 3515 451 1098 5400 238 480 -5998 -4376 1974 9915 -7151 -128 -5130 -4423 8491 3122 7110 -9930 -7341 -1882 -3439 8231 1407 -6444 -4772 -8872 -2853 8031 6313 -9629 4347 -5487 -1799 -1225 8026 6920 4427 3467 -2158 909 8977 -5982 3825 -718 7908 4464 -1220 693 8293 -8873 5243 3511 8604 -5990 -4492 -4091 5688 1240 664 3712 3048 -9240 -5267 247 -2010 5327 -2030 8030 -5240 -3302 480 4323 -8323 -4590 2769 8506 -1556 -1827 -6216 -4879 -156 -1447 5967 -1840 -5838 7409 8444 -5008 -7949 6069 284 -9103 -8612 797 5615 -2375 -9861 2789 5978 -59 4821 7116 4054 2816 -8543 -1099 9062 5718 9635 6353 -3312 1227 2144 5770 9824 -2918 -7958 4640 1036 7693 -951 5293 -4364 6883 -4395 7615 1097 8269 -9907 5813 -5369 4001 -4965 -4567 8939 -145 3003 -6977 8293 1299 9247 -2988 7170 6638 431 -8887 3279 -946 -4148 6039 2067 -282 -71 8031 425 -6890 878 -1532 820 -8918 -5336 1989 -7692 -1915 -684 7818 254 7294 7865 4192 -6782 -6593 -9534 -6708 7805 -6548 -5502 -6471 -3453 -736 -60 450 -2995 4978 3135 1408 7241 -4262 -1352 1200 5332 -3276 -8900 3210 317 1659 -8895 -68 1728 7241 -5572 8605 2181 7379 5184 3720 -7081 -906 8125 -4793 -387 -9056 -6572 5129 9554 -206 3680 -1500 8300 9128 -6752 1001 8338 -2893 3567 314 4180 -7983 5575 4745 -302 5910 5877 9130 -4624 490 -6477 508 -2262 5063 9995 5492 -8571 -2076 -7245 7531 -4395 5668 -8525 9198 5457 5282 -9627 -8023 -4275 -6099 -9415 5771 3678 -6865 417 -1681 -9044 8269 610 -7461 -7621 -4022 5225 -4529 9988 -2569 9810 1996 1283 9364 -7877 6015 -7076 -352 -9273 -3114 -9044 8524 1634 6057 -5687 1947 4940 2461 -5043 -4571 -5986 4391 -9838 6912 -5398 -318 -5024 1465 3817 8656 4389 -4034 4052 7988 -8598 9693 7317 4356 783 -5211 -1854 3219 -3521 -6814 -4709 6055 1394 -10 3384 403 9590 4927 1524 1098 -9975 9585 6222 499 148 -5770 -4801 -8148 -7928 3359 -7612 3226 -4709 1527 -2568 -5296 3739 -9003 -806 1984 2059 7955 7818 5364 793 6822 3946 151 -9630 9630 2324 662 3333 -8448 6754 437 -2029 -4255 6568 8500 -3622 810 9004 8653 1164 -8115 -1858 -2642 611 -7246 -8085 -6299 -4599 5226 -4384 -1024 -4938 -1431 -6083 2496 6922 4660 1912 -8991 -8297 -6895 -9607 1696 6072 -3326 -5078 1355 7649 1118 -3072 -5738 -4741 3892 -647 -6566 -2195 3768 -1397 -4046 -3118 -8531 4909 -6367 5292 -3083 151 -591 3367 -8325 6439 -6505 -7330 2456 8503 -5579 5852 -7902 -667 -3492 -6341 7979 8307 -29 -8265 -2614 -4590 -7186 -3785 -3744 3300 5701 3678 -2580 527 -120 -7978 -5319 7443 -5475 -1506 -7191 -9281 -7356 -2628 7251 -1997 3924 -5266 -8651 9217 5305 9111 -2939 7519 -8554 -5596 -3718 -9826 5615 -3270 7568 -901 -7112 -7598 7930 -1075 2380 -9192 -9157 -9773 -9061 -4003 2896 4243 7496 3191 4741 9293 -8230 9568 5013 -7046 -9040 -3302 2822 -3767 -6571 2286 9978 -5369 -3987 321 -9841 -9334 -4786 1332 2154 350 -1841 -397 238 -1815 -8499 -4930 8627 3968 1148 -2153 -4273 279 119 -3390 -4077 -7011 -2595 140 7960 -6277 6223 4957 -3939 6988 -5028 -9901 1603 -5892 -775 -9280 3171 -1522 5108 4891 3685 4661 -7643 -552 8337 -5832 8644 3003 -9386 6223 8612 787 -3622 9641 3003 -9341 -7802 9602 -3767 -8598 7949 723 -4998 -6073 -5646 4880 -2046 7167 1100 6188 -2993 5320 -4615 -5113 2264 6658 1364 8910 -8873 -9623 -1256 5575 7718 -8815 -8254 4073 2488 -7385 -9406 -1283 -2330 439 -2260 -3460 -1411 1800 -1868 8900 2905 -7883 -8724 -6531 7876 6834 9389 8247 -1522 -2524 7145 -8339 5056 7401 -8273 3776 -6665 8064 8148 2243 -7815 1924 -3212 -6806 4323 904 -4695 9209 -6907 1291 1529 -4561 -7375 -1211 2558 -2141 5043 6989 -5202 -2176 -5916 2884 -6187 -3430 -2237 -1213 5977 -6300 3245 8531 -4257 -9381 802 -78 -4860 7008 -4722 1110 9955 3907 1910 8930 -2195 -3785 5610 5135 3491 7948 3403 -338 1694 -8961 -3504 -8033 -9811 6823 6748 8362 -5673 5260 5914 -809 4578 -2719 2755 -42 1258 1601 767 -347 7552 4349 5549 -9012 -4066 -3864 6657 -4258 7015 5905 3870 -7769 3896 3956 1996 8506 -1060 -5314 6853 -7459 -5834 -9179 9981 -5594 3705 -799 1788 6874 -4405 2345 -5994 -9878 425 3474 323 -4786 -7819 -5507 -8999 1683 -5020 -8423 -9015 -1037 909 -1304 9494 -4815 7341 2170 4724 -9026 -5085 -4041 -4282 8747 2902 5352 3576 -8931 1536 -8880 376 6995 1446 2811 4310 9204 -6879 -9143 -78 -2334 5345 3317 -9839 -8793 -833 4699 -2420 -3265 -8066 3885 -7660 -7341 13 8711 -2510 -8420 -3856 9808 1921 -2644 -6183 -6786 7739 4036 -5541 -9182 4427 7008 -4938 -228 -3505 7569 1683 5763 -728 2236 -943 5351 -8467 101 -7916 -9075 1983 -8025 5674 9528 -2621 6098 8770 4600 6519 -8724 -3047 6462 5293 -9484 8464 106 -2368 -2455 9659 -3489 8326 7198 5617 -1513 -2437 3380 7835 -517 -4778 -6895 -7224 3200 2324 4704 -7740 4029 -4071 723 3889 -5732 -1338 -7655 9258 -4148 -8233 4544 804 9968 -6880 5772 -6405 3637 2752 -5041 6317 1884 -2007 -2908 -8629 -5600 9867 -421 -6378 -5810 7684 3456 -7571 -9877 -5828 -2763 9288 491 8692 -5648 4501 -4434 -569 -3339 1118 -961 516 5412 -9462 8219 2882 7319 -4920 -7027 -3528 1097 4900 8282 4135 4658 8008 -8843 9656 7044 -3992 -5136 -3968 -4330 -3265 9567 -2542 497 -5318 -18 -6056 -3651 9104 -6477 -2719 5268 5570 703 8809 -4719 7949 -2175 3009 6939 9709 4264 -7758 5746 -9630 4579 4909 3571 8199 8743 6349 -5785 1889 1893 4256 -2987 4089 2112 -4104 1333 -3443 -7134 77 4963 4908 -9050 -7842 7564 -9229 -6378 2975 -7823 6418 269 522 -6300 6174 7005 -5378 -7981 -9356 -9072 2569 8999 -6390 -5935 -5057 2360 -8700 -3348 -90 3191 1789 -8654 7768 -6404 -8873 -6821 4562 1085 4429 -9579 -7957 7294 -427 -7934 2968 1508 -6905 -5993 -1688 -8417 1780 9540 -4450 1536 5184 8111 9877 3466 2279 -5254 -6850 6936 -5318 -7691 -6390 5400 6108 8351 -9275 -6229 -5441 -9950 -5475 1480 5686 -8082 -128 9648 5982 9904 1974 -4077 -9764 -4525 -5834 6285 6559 -6806 1577 -7459 7276 839 9633 -7440 9191 4709 -7421 -5043 -2217 -5419 8031 9873 4658 -2961 -3223 3226 2189 6134 1939 -4390 -1323 -240 -8850 6122 7885 1991 2271 6261 -8012 -6213 -3041 4125 6966 -5882 -6915 -5345 -3925 709 978 6321 7461 2433 7315 -4675 -656 -8237 -7938 -340 -5314 -4571 1699 1525 -6613 -2064 4562 6285 4192 -173 7710 -7469 -3785 -2248 4375 8399 -833 -427 5295 -7999 7236 -5517 -5989 -6017 965 -3883 -7937 7707 -1892 -2085 8111 -7516 9569 8043 532 -1663 8001 -1162 9170 -7059 -8235 -6865 -9272 6119 -3662 3870 1339 6589 -4588 -4322 1549 -9520 6393 7102 621 9389 -4111 5768 -3700 3018 -5154 -8234 8634 -2928 -6425 1709 3657 -9595 -8276 -844 -4257 770 -4722 -3718 5091 -8724 7964 5288 8921 -4719 527 -6946 5186 3598 5259 4359 4147 9435 5992 -6929 1058 -9752 -4909 4756 -1902 837 6293 6326 7847 -8692 -9016 8851 8842 8743 1989 -3991 -6232 -9571 425 2666 9009 4745 -1197 2866 -2479 8453 -6310 9490 -1892 -1313 -2941 -5062 -4521 -4219 6337 -2011 7727 -205 2094 2780 6791 3547 -9513 7262 -9526 -1306 8873 342 6483 376 1897 9068 -5133 1822 -6727 -3922 -2009 3515 4391 -3029 2778 7117 8232 6898 -1425 7289 1346 462 -5431 3643 -7627 8974 -5687 -7501 5783 132 1799 -6425 -8416 -8904 8380 -6216 -6391 -5792 -5770 4126 -9622 8842 -2096 2929 -1438 -3156 -2796 -7415 1924 6898 6991 -4968 -8032 998 -3780 1969 8453 2515 -1596 -6004 3195 -5012 4594 141 1449 2834 -5076 5824 34 3463 -736 -5096 691 3876 5463 6703 -1072 3853 -7937 -8593 9037 -2492 1952 2293 -4422 -2151 5214 5234 5988 -8011 4501 8970 8678 8386 4525 8340 -7246 -2570 -5829 2271 -6614 -8375 -4515 9674 -2724 -7871 3973 594 3875 1614 -8339 1879 -7555 5093 6353 -5309 -9118 -7390 0 -7598 -4177 8634 7534 1556 349 -9441 3579 -4653 -2416 -2194 -4484 -6483 -5383 -78 -5205 -1242 813 3590 6240 -3736 -7390 -7632 5321 -6299 -4615 -2210 6188 2372 7060 -5986 -1632 3032 -5612 -5336 -8543 3502 1695 4391 2387 4547 1110 -3353 -545 804 -1809 -5353 7904 8120 5855 1657 -6626 -6422 -4870 -1404 -6229 -3968 2585 2060 -1821 1577 810 -8408 -7540 7897 279 6039 6656 -9330 2591 8567 -5495 7354 7443 8697 -9959 925 3180 -6647 8556 -1018 -1293 9569 -2128 -1431 7483 -3984 -649 -8978 4285 262 -5191 -2759 4835 -5834 1294 -3856 3084 -8885 -2708 -1693 -8948 -6021 1629 3961 2760 2861 -6797 5184 8419 -9162 6810 -8473 9899 9844 -2044 -9103 -3183 -8697 5303 7412 8344 5003 5957 6327 -8799 2425 -5159 1732 7934 5728 -7328 -605 -8552 -6232 -9200 -3586 6145 8498 -2780 649 5957 3744 -9775 7645 7354 1335 4195 -5747 6484 8567 7851 1910 8259 -3384 -9657 2189 -7643 -5612 -3674 -6521 -4128 2187 -3000 -9708 3052 6262 -4863 8010 3371 5220 -38 3744 -3828 -6773 -2962 2887 497 425 7873 4140 8657 2461 -7654 8640 6365 4225 6829 4186 2301 -2793 -6554 7241 -7102 659 -7999 9335 -1223 -7090 6542 -2019 -873 -9624 6293 6039 -6108 8204 2860 5098 -7132 9694 -1973 -1217 -3264 -7112 8296 -8850 4014 -1837 480 -7667 8005 4750 1059 -4798 -187 4728 7007 -2369 505 -590 -1827 9692 -6294 9115 9756 2380 4533 -8557 6450 9019 9514 -6594 7060 2477 2259 -5578 -85 7356 6055 7649 -2742 29 -5146 -7621 -2829 -2427 -3827 6197 9143 -9622 -4062 -6232 -1470 2591 7104 -206 9517 -8918 4658 -7199 -48 2662 6782 -4705 -9459 -3950 -9057 -2526 4866 5611 -7128 4238 1706 -9179 -6611 5615 -3148 5074 -9463 -4435 266 4733 -1242 4407 5334 -2856 -3600 2666 9396 -1224 -7132 1957 -3651 -8843 -8699 -6879 -9957 -648 -8212 6511 -2657 5351 7541 8556 7344 -3734 -4679 -9580 8416 -8 3976 -8397 -2827 3666 -3230 -9044 -9821 -3836 -8100 -1502 -4011 -4569 9761 -8261 4533 9424 -9374 -6630 4941 2496 -1902 1491 -9374 3398 2018 -9983 -6165 1750 -5885 -383 -2319 9426 5058 8016 -8079 -576 7192 5003 -5885 -414 -6455 2511 662 -2997 9240 2670 6145 -6745 -3414 -6450 -2425 -335 2475 3671 -4809 -5888 -3508 4522 -2626 2970 9659 4590 -4730 -4722 -5018 -916 4268 -7102 -2070 -5414 3533 -6170 -2247 -6590 -7211 5153 1360 -2995 -9954 -7684 -2668 -335 9352 -698 -133 -3571 -3419 -4821 -4222 1603 -4835 -2259 1547 -2244 8811 -151 -1201 1008 2212 -739 -9308 -3766 8964 -240 4044 8368 1944 6672 7953 3481 -4273 -3961 -6222 -9274 5345 5834 -4737 9009 -7920 1128 8227 6031 -4925 -1714 -6649 -460 183 9207 -6046 2196 -5435 2797 9783 5909 1103 -6800 9507 -9967 7643 -7489 4104 -8978 8732 8582 8013 -2724 -9453 645 -5489 -3939 -5242 3400 6392 3355 -2111 -6056 -8164 -3053 -6399 1921 -9171 -68 -4051 -5292 -2462 -4215 4733 -1397 47 -5508 425 -1883 -4273 -8058 -3972 7223 5112 2154 -5770 7949 8859 -6140 876 7153 4082 -1025 4462 3629 7006 -1790 2221 -4133 -5881 259 720 -6333 -953 -749 1092 -1037 4657 8842 4075 -163 9342 558 -5932 -2319 -5168 -8259 4266 1592 2389 6351 8556 6039 -248 -6163 -116 7369 -5998 -2572 -5181 -8613 372 -8880 -9597 4453 -9775 -2547 9640 -1404 9001 8351 5364 3377 -5316 7518 1801 7070 -4133 5740 1146 -5307 -9975 -3460 7818 -1809 -6152 -1204 3292 3734 -7803 4001 -5202 5747 1526 -3045 -5540 6697 2618 7086 4230 1282 2755 -5638 -5562 -108 2600 -4321 -2492 -9473 5957 -1133 -892 5765 3675 -6046 5497 -773 7607 1526 -9037 1789 1944 -4342 -5042 -7299 -9663 -472 -6905 -4902 7109 -6946 -9443 1957 -1247 3834 1904 4014 9367 -5834 4013 -3265 -9544 7826 -5557 3747 1848 -2747 1763 7110 9740 -6326 1550 -8806 886 -1692 621 -2318 -2134 8851 -9455 6829 6212 4231 -9032 5475 1265 -266 -266 -7812 831 6041 -787 178 7112 -753 1676 6785 -3034 -7140 -6678 1425 3896 -8604 -4845 -3478 6291 70 8512 -1011 -6948 4547 8822 9089 -3883 8273 6755 2170 -7420 8031 -1800 837 -485 -8679 -3348 5730 9397 -2344 3651 5514 1688 -5743 8640 -8667 -9101 372 -2657 -3782 7262 6058 -7034 -7193 6004 -1135 -2223 -7027 -4662 -1242 2456 -6222 6197 6695 4025 -7363 3533 9713 -6273 -7379 1355 -383 -1882 -9203 7521 -8303 -4640 -240 4398 -3756 5300 2396 9107 6837 9589 -8655 -3455 7931 5288 6212 8644 -4086 -5556 -3605 6591 8482 -7391 7898 821 -9683 -2569 -7078 4879 9921 -9772 -1675 5588 1058 -860 -7392 -3218 5499 6216 4473 6210 -5278 132 -1231 2585 -7112 -3865 4741 1892 4073 4142 3887 -8210 4239 -3057 -1247 -197 -8115 -1883 2029 6337 -5321 -798 7434 2029 -4894 -7469 5746 3214 -2885 9598 -3215 -4772 4645 5263 6055 3744 7774 3461 -4734 6680 -5585 1891 1542 -7905 -2908 -425 9432 1695 -8178 3503 -1293 2028 -9261 -8178 -8058 8489 -7812 -3736 -3056 -6157 8653 -5405 1096 -333 -9319 3339 1335 4123 4547 -4432 4946 -3545 3156 2462 9946 51 -1134 6576 -3436 5617 -6425 -1506 3201 2905 4238 -5132 5409 6349 2760 491 6999 -6552 4265 -9103 6039 -9163 -9496 7860 -3785 13 8842 -4772 -9622 3261 271 -7660 4662 5858 -8431 -8779 -559 9284 9303 8780 3892 -7479 8794 -4622 -5606 3466 -4134 7344 -2691 3375 -1133 -2429 -448 3443 -8201 -3057 6113 -5562 2311 6427 -5692 403 7459 1549 -1563 1954 -9166 -5462 2189 853 8443 -9894 -4630 -2070 -7034 -2206 723 -1228 -2484 2467 7607 5293 870 -2064 2329 -873 9483 -6800 353 2028 8549 8964 9408 9007 -8406 -2484 3870 9519 -5874 5176 -919 -5452 -1890 -9887 3275 2816 7647 -1376 742 5574 2305 -9003 9633 ================================================ FILE: exm/aoc/2022/aoc_2022_20_questions.txt ================================================ --- Day 20: Grove Positioning System --- It's finally time to meet back up with the Elves. When you try to contact them, however, you get no reply. Perhaps you're out of range? You know they're headed to the grove where the star fruit grows, so if you can figure out where that is, you should be able to meet back up with them. Fortunately, your handheld device has a file (your puzzle input) that contains the grove's coordinates! Unfortunately, the file is encrypted - just in case the device were to fall into the wrong hands. Maybe you can decrypt it? When you were still back at the camp, you overheard some Elves talking about coordinate file encryption. The main operation involved in decrypting the file is called mixing. The encrypted file is a list of numbers. To mix the file, move each number forward or backward in the file a number of positions equal to the value of the number being moved. The list is circular, so moving a number off one end of the list wraps back around to the other end as if the ends were connected. For example, to move the 1 in a sequence like 4, 5, 6, 1, 7, 8, 9, the 1 moves one position forward: 4, 5, 6, 7, 1, 8, 9. To move the -2 in a sequence like 4, -2, 5, 6, 7, 8, 9, the -2 moves two positions backward, wrapping around: 4, 5, 6, 7, 8, -2, 9. The numbers should be moved in the order they originally appear in the encrypted file. Numbers moving around during the mixing process do not change the order in which the numbers are moved. Consider this encrypted file: 1 2 -3 3 -2 0 4 Mixing this file proceeds as follows: Initial arrangement: 1, 2, -3, 3, -2, 0, 4 1 moves between 2 and -3: 2, 1, -3, 3, -2, 0, 4 2 moves between -3 and 3: 1, -3, 2, 3, -2, 0, 4 -3 moves between -2 and 0: 1, 2, 3, -2, -3, 0, 4 3 moves between 0 and 4: 1, 2, -2, -3, 0, 3, 4 -2 moves between 4 and 1: 1, 2, -3, 0, 3, 4, -2 0 does not move: 1, 2, -3, 0, 3, 4, -2 4 moves between -3 and 0: 1, 2, -3, 4, 0, 3, -2 Then, the grove coordinates can be found by looking at the 1000th, 2000th, and 3000th numbers after the value 0, wrapping around the list as necessary. In the above example, the 1000th number after 0 is 4, the 2000th is -3, and the 3000th is 2; adding these together produces 3. Mix your encrypted file exactly once. What is the sum of the three numbers that form the grove coordinates? --- Part Two --- The grove coordinate values seem nonsensical. While you ponder the mysteries of Elf encryption, you suddenly remember the rest of the decryption routine you overheard back at camp. First, you need to apply the decryption key, 811589153. Multiply each number by the decryption key before you begin; this will produce the actual list of numbers to mix. Second, you need to mix the list of numbers ten times. The order in which the numbers are mixed does not change during mixing; the numbers are still moved in the order they appeared in the original, pre-mixed list. (So, if -3 appears fourth in the original list of numbers to mix, -3 will be the fourth number to move during each round of mixing.) Using the same example as above: Initial arrangement: 811589153, 1623178306, -2434767459, 2434767459, -1623178306, 0, 3246356612 After 1 round of mixing: 0, -2434767459, 3246356612, -1623178306, 2434767459, 1623178306, 811589153 After 2 rounds of mixing: 0, 2434767459, 1623178306, 3246356612, -2434767459, -1623178306, 811589153 After 3 rounds of mixing: 0, 811589153, 2434767459, 3246356612, 1623178306, -1623178306, -2434767459 After 4 rounds of mixing: 0, 1623178306, -2434767459, 811589153, 2434767459, 3246356612, -1623178306 After 5 rounds of mixing: 0, 811589153, -1623178306, 1623178306, -2434767459, 3246356612, 2434767459 After 6 rounds of mixing: 0, 811589153, -1623178306, 3246356612, -2434767459, 1623178306, 2434767459 After 7 rounds of mixing: 0, -2434767459, 2434767459, 1623178306, -1623178306, 811589153, 3246356612 After 8 rounds of mixing: 0, 1623178306, 3246356612, 811589153, -2434767459, 2434767459, -1623178306 After 9 rounds of mixing: 0, 811589153, 1623178306, -2434767459, 3246356612, 2434767459, -1623178306 After 10 rounds of mixing: 0, -2434767459, 1623178306, 3246356612, -1623178306, 2434767459, 811589153 The grove coordinates can still be found in the same way. Here, the 1000th number after 0 is 811589153, the 2000th is 2434767459, and the 3000th is -1623178306; adding these together produces 1623178306. Apply the decryption key and mix your encrypted file ten times. What is the sum of the three numbers that form the grove coordinates? ================================================ FILE: exm/aoc/2022/aoc_2022_21.adb ================================================ -- Solution to Advent of Code 2022, Day 21 ------------------------------------------- -- Monkey Math -- -- https://adventofcode.com/2022/day/21 -- Copy of questions in: aoc_2022_21_questions.txt -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_2022_21_Pkg; with AoC_Toolbox; -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; -- Interfaces is needed for compiling on both -- HAC and GNAT (64-bit integer: Integer_64): with Interfaces; procedure AoC_2022_21 is use AoC_2022_21_Pkg, AoC_Toolbox; use HAT, Interfaces; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbose : constant Boolean := not compiler_test_mode; T0 : constant Time := Clock; r : array (1 .. 2) of Integer_64; function Search (choice : Data_Type) return Integer_64 is function f (x : Integer_64) return Integer_64 is begin case choice is when mini => return Compute_Mini (part_2, x); when input => return Compute (part_2, x); end case; end f; x1, x2, x, y1, y2, y : Integer_64; procedure Show is begin Put_Line (+" x in [" & Integer_64'Image (x1) & " .." & Integer_64'Image (x2) & "] : " & Integer_64'Image (y1) & ", " & Integer_64'Image (y2)); end Show; begin x := 1; if verbose then Put_Line ("Range extension phase:"); end if; loop x1 := -x; x2 := +x; y1 := f (x1); y2 := f (x2); if verbose then Show; end if; exit when Sgn_64 (y1) /= Sgn_64 (y2); x := x * 2; end loop; if y1 = 0 then return x1; elsif y2 = 0 then return x2; end if; -- From here, y1 and y2 are non-zero, with different signs. if verbose then Put_Line ("Range narrowing phase:"); end if; loop x := (x1 + x2) / 2; y := f (x); if y = 0 then return x; end if; if Sgn_64 (y) = Sgn_64 (y1) then -- The zero is *not* between x1 and x. x1 := x; y1 := y; else x2 := x; y2 := y; end if; if verbose then Show; end if; exit when x1 = x2; end loop; Put_Line ("Non-integer zero..."); return 666; end Search; begin if verbose then Put_Line ("Example: simple computation: " & Integer_64'Image (Compute_Mini (part_1, 0))); end if; r (1) := Compute (part_1, 0); if verbose then for i in 300 .. 303 loop Put_Line (+"Example: difference at root, human = " & i & " : " & Integer_64'Image (Compute_Mini (part_2, Integer_64 (i)))); end loop; Put_Line (+"Example: search minimum: " & Integer_64'Image (Search (mini))); end if; r (2) := Search (input); if verbose then Put_Line ("Some values around the zero:"); for i in r (2) - 3 .. r (2) + 2 loop Put_Line (" x = " & Integer_64'Image (i) & " : " & Integer_64'Image (Compute (part_2, i))); end loop; New_Line; end if; if compiler_test_mode then if r (1) /= Integer_64'Value (To_String (Argument (1))) or r (2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: evaluation . . . . :" & Integer_64'Image (r (1))); Put_Line (+"Part 2: search of zero . . :" & Integer_64'Image (r (2))); -- Part 1: validated by AoC: 286698846151845 -- Part 2: validated by AoC: 3759566892641 end if; end AoC_2022_21; ================================================ FILE: exm/aoc/2022/aoc_2022_21_pkg.adb ================================================ package body AoC_2022_21_Pkg is function Compute_Mini (part : Part_Type; human : Integer_64) return Integer_64 is function Eval (m : Monkey_Mini) return Integer_64 is begin case m is when root_m => case part is when part_1 => return Eval (pppw) + Eval (sjmn); when part_2 => return Eval (pppw) - Eval (sjmn); end case; when dbpl => return 5; when cczh => return Eval (sllz) + Eval (lgvd); when zczc => return 2; when ptdq => return Eval (humn_m) - Eval (dvpt); when dvpt => return 3; when lfqf => return 4; when humn_m => case part is when part_1 => return 5; when part_2 => return human; end case; when ljgn => return 2; when sjmn => return Eval (drzm) * Eval (dbpl); when sllz => return 4; when pppw => return Eval (cczh) / Eval (lfqf); when lgvd => return Eval (ljgn) * Eval (ptdq); when drzm => return Eval (hmdt) - Eval (zczc); when hmdt => return 32; end case; end Eval; begin return Eval (root_m); end Compute_Mini; function Compute (part : Part_Type; human : Integer_64) return Integer_64 is function Eval (m : Monkey) return Integer_64 is begin case m is when rmmz => return 2; when vdjz => return 4; when rqbd => return 3; when zvqw => return 4; when sshm => return Eval (qhnd) * Eval (lrcj); when dtzl => return Eval (rnbs) + Eval (gppj); when gnzq => return 5; when zlpv => return Eval (pmng) * Eval (wgvj); when nqgr => return 4; when tftg => return 1; when fhjc => return Eval (sbpb) / Eval (nhcr); when fwbm => return Eval (jcch) * Eval (qhlj); when wtlq => return 3; when nzhf => return Eval (fjzn) * Eval (bnws); when nqpq => return 2; when jqzv => return 2; when crrj => return Eval (vnbv) / Eval (grww); when glpw => return 8; when cnbg => return Eval (jmbp) * Eval (jnqv); when bdcm => return 2; when bcww => return 11; when wrbf => return 2; when hpvb => return Eval (zswl) * Eval (qpbz); when qffb => return Eval (jvqz) + Eval (qgtf); when mfmc => return Eval (hnbn) * Eval (twwv); when cnzj => return Eval (qqdn) * Eval (pvtb); when wbnh => return Eval (cshj) * Eval (snvw); when swds => return Eval (bmlj) + Eval (scdn); when twtb => return 3; when dlgc => return Eval (gfbw) + Eval (djgh); when bvzn => return 2; when gwpm => return Eval (rrll) + Eval (zshp); when rtnf => return Eval (qbwf) + Eval (bqnn); when sdmb => return 15; when mtjq => return 2; when dpmg => return 3; when drct => return Eval (bvfr) + Eval (rtmh); when zrpj => return Eval (gfml) * Eval (tsms); when gwlm => return 2; when msdr => return 3; when fqbl => return Eval (wbbf) + Eval (pbgr); when zwqw => return Eval (lnqm) - Eval (nzdj); when lbvn => return Eval (zwbh) + Eval (btbn); when dggg => return Eval (bnmf) / Eval (trpv); when bjwg => return Eval (trdj) + Eval (lpqs); when bnzl => return Eval (vfhg) * Eval (pjds); when qtmp => return 2; when llpf => return 2; when zwqn => return Eval (lfhb) + Eval (spcf); when trpt => return Eval (mdrm) * Eval (qdrc); when lzgm => return Eval (jzvg) + Eval (qlzg); when swhh => return 2; when tpnf => return 15; when rgrp => return 7; when zswl => return 3; when gzbv => return Eval (djgb) + Eval (dvwj); when ppfs => return 5; when nfhf => return 5; when pgrc => return Eval (pdmb) * Eval (qgwg); when jjwr => return 6; when fvsf => return 2; when qmvq => return Eval (hlzp) * Eval (zvvd); when twjq => return 2; when twsj => return 5; when mwrc => return 2; when sbpb => return Eval (djpm) * Eval (pfpt); when cbjq => return Eval (ztqg) - Eval (tzls); when mgsl => return 2; when vzgd => return Eval (qmcb) + Eval (wfbz); when qrll => return 2; when slpm => return Eval (fbpz) * Eval (jjwr); when rffd => return Eval (mfmc) / Eval (csdf); when jjbm => return Eval (slpc) * Eval (bncr); when pjds => return Eval (cpqv) + Eval (ldtj); when btfl => return Eval (qvfg) + Eval (lqdf); when sfcv => return 7; when vtnq => return 5; when fzdp => return Eval (fzrd) * Eval (slww); when cwjp => return 9; when mpnj => return 2; when wnbb => return Eval (zssf) + Eval (qnld); when nfgv => return Eval (lzhf) + Eval (mqzw); when pszs => return 4; when chpt => return 2; when bhpw => return Eval (cnbg) + Eval (zrnz); when dfps => return 5; when pzqv => return 3; when fjzz => return 8; when ffqr => return 16; when bqvg => return Eval (lrqh) + Eval (wpdn); when qlmg => return Eval (mpvz) + Eval (wpvg); when lfhb => return Eval (jscq) + Eval (bpnt); when pqqj => return 2; when qhtv => return 5; when wchl => return Eval (ffqr) + Eval (mdnp); when vcwt => return Eval (llfg) + Eval (wjtc); when nfbp => return 2; when bbcn => return 8; when smld => return 2; when mvmj => return Eval (lqdc) * Eval (bhmz); when mqph => return Eval (jjgt) + Eval (vtjg); when brmz => return Eval (mpfm) + Eval (zcgs); when ttdb => return Eval (zncl) + Eval (nqpv); when bcsc => return 6; when frjj => return 9; when jcjf => return Eval (lgpg) + Eval (qmvq); when pmfh => return 3; when drrf => return 9; when lmht => return 7; when sstg => return Eval (vrct) + Eval (wfjn); when swhz => return Eval (zvvp) * Eval (dbvt); when rtpz => return Eval (nnsc) + Eval (zmlh); when qrzq => return 2; when rtmt => return 12; when pmds => return 3; when vfzw => return Eval (jhlw) * Eval (vmzc); when smhv => return Eval (ffnt) * Eval (gtwp); when vdzv => return 5; when btqb => return 3; when wclq => return Eval (rwth) + Eval (drln); when vzrz => return Eval (bsvc) + Eval (vmjn); when ztct => return Eval (zscd) / Eval (lhml); when zvvd => return Eval (tcqz) - Eval (cmnv); when mfrc => return Eval (jmcp) + Eval (lpvs); when sdrn => return 9; when jfvq => return Eval (pgdw) + Eval (vbvt); when qjrs => return Eval (qvpw) + Eval (cpdf); when tnnt => return Eval (psfr) + Eval (hjlz); when fqlp => return Eval (bblh) + Eval (dbfm); when nwhm => return 3; when rlcw => return 2; when rwjc => return Eval (ljzj) + Eval (zdrh); when tfqh => return 5; when crqg => return 3; when nrps => return Eval (lrdn) + Eval (hmfb); when pmng => return Eval (gzrs) + Eval (vtns); when gmzt => return Eval (tlmq) * Eval (bfzd); when fhdz => return 6; when fwzf => return 4; when tzls => return Eval (fnqf) + Eval (fpcs); when pvtb => return 2; when gpdf => return Eval (zslv) * Eval (qwqc); when zcgs => return Eval (jlmb) * Eval (crnb); when clbn => return 2; when wghf => return Eval (fwbm) - Eval (jcjf); when vffj => return Eval (frjp) + Eval (mrtq); when gfbw => return Eval (csfh) + Eval (rlvd); when tzth => return Eval (tvtj) * Eval (bnvg); when vwhb => return 2; when scwp => return 3; when rpbm => return 3; when zdhf => return 2; when fdmf => return 3; when lqdf => return 2; when rndt => return Eval (wtbs) + Eval (lrsc); when jnzr => return 5; when qpqs => return Eval (bcng) / Eval (nwdv); when tmhg => return Eval (vtvn) - Eval (nzbp); when dtfz => return Eval (bdgd) * Eval (dfdl); when pnvc => return Eval (brqb) * Eval (drrq); when mfnh => return Eval (rdhg) * Eval (rmvq); when vjgb => return 3; when czvm => return 18; when qhnd => return 3; when dhfw => return Eval (jmcf) + Eval (vjjw); when nqpv => return Eval (bhvg) + Eval (zmvz); when rhcv => return Eval (ddtd) / Eval (jqzv); when lqqh => return 5; when mspl => return 5; when ngps => return 11; when bcmp => return 2; when nlsw => return Eval (gnjq) * Eval (vzrz); when mhlj => return 4; when bqnn => return Eval (pgrc) - Eval (bwff); when fbqs => return 11; when cnln => return Eval (sqml) * Eval (wlqd); when vjbz => return 5; when vhhz => return Eval (pwpn) * Eval (dsng); when crmb => return 5; when wbgs => return 3; when qhvn => return 3; when lsnd => return 1; when hhcv => return 2; when vmjn => return 12; when fbtc => return 2; when jgnj => return 4; when jmcp => return 2; when mfhg => return 2; when ztdn => return 2; when zttf => return 3; when tjwt => return 16; when lzzh => return 11; when rnns => return Eval (frrn) * Eval (pnmc); when ffnn => return 3; when wpvg => return Eval (qvpv) * Eval (frqq); when wjds => return 3; when nnmh => return 5; when jswz => return Eval (vthd) - Eval (jjrh); when qjqw => return 2; when bndd => return 7; when mdpg => return 2; when wtwb => return 2; when nbfg => return Eval (vwvc) * Eval (rbtb); when nmts => return Eval (pfml) * Eval (jqqs); when nvjf => return Eval (mddc) * Eval (lrbp); when gqgh => return Eval (wzsh) * Eval (tqzv); when btqt => return Eval (qbzv) + Eval (wtrh); when cblz => return 5; when nvpd => return 3; when vldc => return 2; when drhw => return Eval (dngq) * Eval (nmlt); when bpjf => return Eval (ndlf) + Eval (tjwt); when dpgl => return 2; when ggnd => return 3; when qzpn => return 2; when ttvz => return 2; when qwqc => return 3; when zhmb => return 15; when nzdj => return Eval (svvh) + Eval (qplw); when rrnp => return Eval (qrnj) + Eval (hmvq); when mbvg => return Eval (sgzh) / Eval (mdpg); when mlbw => return Eval (jwwv) * Eval (jhzw); when wvfb => return Eval (mvmj) + Eval (phjj); when tzhp => return 15; when zjcn => return Eval (pgfr) * Eval (dgvh); when wbbf => return Eval (ghvn) * Eval (dfrb); when mfsz => return Eval (fpvs) * Eval (lzgm); when bfpq => return Eval (tmhg) * Eval (nvlv); when vpvl => return Eval (blnq) * Eval (jfsr); when pnrv => return Eval (lfrb) - Eval (qwnt); when lbgc => return Eval (bzdh) * Eval (wszm); when pbdd => return Eval (dcpm) * Eval (nrsd); when jsrb => return 13; when bbzt => return 8; when mhdn => return Eval (bsmm) * Eval (rzzg); when jpcd => return 2; when ldzb => return Eval (nqpr) * Eval (qnds); when nmlg => return 2; when pnpc => return 5; when rbqt => return 5; when dsqb => return Eval (mrjc) / Eval (ftqd); when zhqg => return Eval (lpjr) * Eval (zttf); when dphz => return 3; when gbzd => return Eval (ttvz) * Eval (tsjq); when cldm => return 4; when ftbq => return 5; when rzff => return Eval (gdpg) + Eval (cgvs); when tzcd => return 1; when gzwh => return Eval (bjfh) * Eval (qtfp); when qgnb => return Eval (vdgt) + Eval (zwwb); when jzvg => return 5; when qqwz => return Eval (pnwh) * Eval (wlmv); when jbtg => return 9; when rrgh => return 2; when bvfr => return Eval (jzcd) + Eval (gjbv); when mwdl => return Eval (rlcw) * Eval (jffq); when chfs => return Eval (mrlq) - Eval (cgvv); when gwmr => return Eval (hbwh) * Eval (wzdj); when qcml => return 3; when zbhj => return Eval (ctqb) * Eval (hfbg); when zshp => return Eval (wphq) * Eval (hzpr); when pvcs => return 4; when sszh => return 2; when jdsc => return 15; when ndnm => return 8; when lrlz => return 1; when wpbs => return 2; when bcpn => return 7; when glts => return Eval (gpdf) - Eval (vznc); when qnld => return Eval (jrvp) * Eval (smnv); when hrtv => return Eval (bdcm) * Eval (cgnr); when zbbf => return Eval (shtz) + Eval (fvsb); when vvbz => return Eval (bqht) * Eval (zwqn); when vvjg => return Eval (zgzs) * Eval (sbpp); when lrlg => return 10; when zpht => return 10; when ndtz => return Eval (cnzj) + Eval (qsml); when stcv => return 3; when jjrh => return Eval (mlwr) * Eval (dqjz); when hsbr => return Eval (dbcs) / Eval (zngg); when wtrh => return Eval (sclr) + Eval (chsm); when jfqs => return 15; when hjgd => return 12; when hgnr => return 9; when brqb => return 4; when ndsm => return Eval (tmhl) + Eval (ddln); when fjgh => return Eval (cbjl) + Eval (pchr); when tptf => return 3; when njcj => return Eval (ppll) * Eval (psfp); when jjvz => return Eval (vhqz) + Eval (fmvw); when grww => return 2; when jvqf => return 2; when sgvm => return Eval (vhwz) * Eval (gzgm); when zscd => return Eval (dshq) * Eval (tbwl); when mgjl => return 3; when bfgp => return Eval (jbvq) * Eval (ppcl); when mpst => return Eval (zzpd) * Eval (qcnn); when wjzd => return Eval (vwht) * Eval (pzcc); when wqdj => return Eval (zvmv) + Eval (sntb); when csdf => return 2; when cgwj => return 3; when rccr => return 2; when vsgw => return 3; when pvwn => return Eval (fpwz) * Eval (wnjc); when mfql => return 3; when dspn => return Eval (qlvz) + Eval (bcsc); when llcn => return 4; when dcph => return 4; when npcs => return Eval (lrvc) + Eval (mcfr); when wgvj => return 4; when bblh => return 1; when dmrn => return 9; when qbzv => return 1; when lrdn => return 3; when wzfr => return Eval (nltq) + Eval (lrlz); when bwnc => return 2; when dswn => return 11; when bnws => return 2; when cdnp => return Eval (zvst) * Eval (cwjp); when fddw => return Eval (zhgt) * Eval (mfst); when nbbd => return Eval (flvw) * Eval (thlz); when lbzc => return Eval (jfrn) * Eval (gdgd); when sntb => return Eval (bhrb) * Eval (lhgv); when vzts => return 6; when jvfw => return Eval (hlms) + Eval (lwlc); when mqcv => return 2; when jhzw => return 5; when lhpf => return Eval (dqzt) * Eval (fjld); when znjr => return 2; when wrvl => return Eval (pdbt) * Eval (qlvg); when cdwt => return 6; when vtjg => return Eval (stcr) * Eval (bvzn); when dvnh => return Eval (brqv) * Eval (jdmt); when pcgq => return Eval (jtcf) * Eval (qssh); when nhjt => return 2; when pmqh => return Eval (dflc) * Eval (rzsn); when zrwb => return Eval (gtqh) * Eval (fwjg); when zphs => return Eval (bcww) + Eval (sbtd); when nmvn => return Eval (vrpp) * Eval (mdht); when sbvl => return 3; when bcdf => return Eval (rhwm) * Eval (zbhj); when jhwn => return Eval (mgjl) * Eval (tprm); when ftjv => return 3; when ncnm => return Eval (vzcr) * Eval (wqfg); when bgwj => return Eval (qlqt) / Eval (dnwd); when hrbr => return Eval (gvmj) + Eval (vspf); when qljb => return 3; when vdsz => return 3; when nhpf => return Eval (rdpg) + Eval (qrll); when gvfn => return Eval (drnb) / Eval (fhmz); when ppts => return Eval (zhrs) * Eval (lccp); when fvhm => return 7; when rrqr => return 2; when lnqm => return Eval (rwjc) + Eval (vnvr); when qwnz => return Eval (hfbh) + Eval (vdbp); when cgvr => return 3; when lvrc => return 4; when vcfm => return 5; when zhgt => return 3; when nvdh => return 3; when llfg => return Eval (cgcc) * Eval (nqhg); when wjgf => return 2; when nztj => return Eval (wqfz) + Eval (tdlw); when shpt => return 2; when gzmv => return 3; when tqzv => return Eval (rtpz) + Eval (glqr); when pdmb => return 2; when fpcs => return 5; when mwmp => return 6; when hcfs => return 2; when bshp => return Eval (chvq) + Eval (pdbc); when gppj => return 1; when pzpp => return 5; when ltnz => return Eval (dswn) * Eval (tsqc); when wzdj => return 3; when frst => return 5; when scdn => return 6; when fpsh => return 2; when gzwm => return 2; when jmbs => return Eval (lwlb) * Eval (sqcb); when rqsw => return 5; when bnvg => return 3; when tfwb => return 2; when snwm => return 6; when zvrq => return 5; when vnpq => return Eval (djjs) + Eval (rmrj); when cfbh => return 4; when ntnh => return Eval (jvfw) * Eval (jzdn); when jnwv => return Eval (tlnz) * Eval (zqpw); when npvl => return Eval (sbqm) * Eval (zmmd); when tpwq => return Eval (jnll) / Eval (flhf); when flhs => return Eval (qcml) + Eval (zmdq); when pnvd => return Eval (cwvl) + Eval (dgpr); when zvvp => return 3; when fcql => return 20; when jrvp => return 17; when wbvt => return Eval (bftg) + Eval (tlzh); when vwht => return 3; when pzvr => return 3; when qncp => return 3; when bcgz => return Eval (tpjp) / Eval (bngr); when dcbt => return Eval (rctr) + Eval (wltv); when csgr => return Eval (wrvl) / Eval (znjr); when rsdv => return Eval (vcwt) * Eval (mqcv); when fnqf => return 2; when hzrc => return Eval (jdbp) + Eval (jnwv); when cdvw => return Eval (sjfs) + Eval (fzvh); when bsvc => return Eval (pwln) / Eval (nrjc); when tlwr => return 3; when hjmr => return 3; when spjg => return 5; when mqgl => return Eval (mqlt) * Eval (jlnf); when mzzd => return 3; when dqnv => return Eval (mhnm) * Eval (zhqg); when lqcm => return Eval (ffqs) / Eval (zvrq); when sqzp => return 5; when drvt => return Eval (hhws) * Eval (llpf); when ghvn => return Eval (vrjj) + Eval (vfrh); when hfbh => return 16; when wtlg => return 19; when dsgt => return Eval (hhcv) * Eval (npcs); when vvzh => return 6; when sclr => return Eval (dddm) * Eval (nttr); when jqqs => return Eval (znlh) + Eval (ffnn); when zprq => return Eval (jmnj) * Eval (mwqc); when dczh => return Eval (vvvb) * Eval (wcpr); when lpzb => return Eval (bqvg) + Eval (mlgj); when dqsv => return Eval (pmfh) * Eval (zrbc); when hgzs => return 3; when vrpp => return 10; when snbm => return 4; when tdrq => return Eval (hqdv) * Eval (csln); when tbwl => return Eval (sdmb) * Eval (zrfw); when jdmt => return Eval (btwt) - Eval (gwpm); when fzgj => return 4; when vnvr => return Eval (pmqh) * Eval (pwlt); when mcht => return 2; when ztrt => return Eval (vlhc) * Eval (swds); when bncr => return Eval (wpcs) - Eval (pcgq); when nqsl => return Eval (qcfn) + Eval (fsgb); when cclc => return Eval (hjfj) + Eval (cfdl); when ztpd => return Eval (dzlc) + Eval (zcgn); when lfrb => return Eval (rbsf) * Eval (hzjj); when pvfv => return 2; when swpl => return 2; when csnf => return 1; when ptdz => return 2; when nvhn => return 2; when rdhg => return Eval (nnhm) * Eval (wpbs); when jclb => return 2; when cscm => return Eval (lclg) * Eval (mrwz); when fcgj => return Eval (hmrz) * Eval (nwbt); when hgwm => return Eval (mspl) * Eval (rmfv); when rqbq => return 2; when wjtc => return Eval (fszd) + Eval (tpmp); when dpvl => return 8; when nwdv => return 3; when zcgn => return Eval (lzzh) * Eval (brfc); when jvrt => return Eval (bhzq) / Eval (rqsw); when zmdq => return Eval (sdwj) + Eval (mwdl); when rtsd => return Eval (rcmc) + Eval (jtjd); when nqzz => return 11; when dshq => return Eval (rtnf) * Eval (chvn); when mddc => return 2; when rpwz => return 3; when pmlg => return 8; when blmp => return Eval (vwmr) * Eval (ndpf); when hqbb => return 2; when chtt => return 2; when cchg => return 2; when bntz => return Eval (tvrd) * Eval (ncsp); when gvgp => return 3; when vvhm => return Eval (mspb) * Eval (dpgl); when nlcv => return 5; when rwcd => return Eval (qffb) + Eval (nzcv); when rfcq => return 6; when zgdb => return 2; when mggl => return Eval (cchg) * Eval (crcm); when mwjg => return Eval (vjwz) * Eval (vsmt); when rbbh => return 13; when mqlt => return Eval (gwlm) * Eval (mqvg); when ddtd => return Eval (qcnv) + Eval (wjzv); when hpmm => return 3; when cjlm => return 6; when cpdf => return Eval (jjbm) * Eval (mtnb); when gqrp => return Eval (tdrq) + Eval (djrh); when zmtg => return 8; when vwdl => return Eval (hzmn) * Eval (nqms); when ggpn => return 11; when mtfr => return Eval (jlqg) * Eval (dlgc); when nsfm => return 4; when cftm => return 18; when wcdm => return Eval (tsbf) * Eval (wgvv); when jcch => return 2; when zqjp => return Eval (tzhp) - Eval (nldv); when wjmq => return 6; when cbgj => return Eval (mdjm) * Eval (tqfr); when jmnj => return Eval (ppts) + Eval (fqbl); when tlnz => return Eval (vfgt) * Eval (vdjz); when fqjd => return 2; when ngzp => return 11; when trdj => return 10; when qrch => return Eval (nfhf) + Eval (vhtl); when hmrz => return Eval (qjrs) * Eval (rtsd); when rvnh => return 3; when humn => case part is when part_1 => return 4481; when part_2 => return human; end case; when jstb => return 5; when vqlt => return 2; when vlqd => return Eval (ndgh) * Eval (zptr); when vjjw => return Eval (mrlc) / Eval (pvfv); when mnlp => return Eval (svdw) + Eval (mtjq); when jtcf => return 4; when lwlc => return Eval (qqtm) * Eval (cnvb); when jdgq => return 2; when vznc => return 2; when dcfw => return Eval (qvvc) * Eval (wqdj); when fqwz => return Eval (twtb) + Eval (vtnq); when hhbn => return 4; when wrpp => return 14; when mmnw => return 3; when rdpb => return 10; when hcsc => return 5; when nfvj => return 4; when qznt => return Eval (zfjw) * Eval (wfld); when flvw => return 5; when wphq => return 5; when bpwd => return 2; when cbfh => return 2; when bcbw => return Eval (jtvm) * Eval (cdnm); when dvwj => return Eval (zwgg) * Eval (dspn); when tnbt => return Eval (qdfp) * Eval (bpwd); when qlzt => return 12; when rjfh => return 5; when cprt => return 3; when qgwg => return Eval (jrgs) + Eval (sphc); when zpbt => return Eval (swfp) / Eval (mldc); when drln => return 6; when jdcd => return 3; when jzcd => return Eval (nvjl) - Eval (swpl); when sbpp => return 17; when ttwm => return 5; when rdbs => return Eval (wsml) * Eval (drrf); when pfpt => return Eval (pmrt) * Eval (fvsf); when rfbw => return Eval (ntpj) + Eval (vwpq); when bqld => return Eval (zqjp) + Eval (rbzl); when rrmg => return 19; when rbsf => return 3; when mlgj => return Eval (vvgt) + Eval (dmsz); when jfcd => return Eval (bsqn) / Eval (blgf); when sjrh => return 7; when djjd => return Eval (fddw) + Eval (svvq); when jhgd => return Eval (fjnh) * Eval (bbzt); when nlts => return Eval (fjgh) - Eval (cnln); when ppwc => return Eval (lhpf) - Eval (zprq); when gptt => return 2; when bvvl => return 20; when ssnq => return Eval (cfmw) + Eval (wfnm); when gmhz => return 4; when nnsc => return Eval (cvqf) + Eval (vpvl); when zbzf => return Eval (nlth) * Eval (dhfw); when jhvm => return 16; when mrrt => return 7; when pmrt => return Eval (mwrc) * Eval (mnhc); when rddj => return Eval (fbcd) / Eval (tfwb); when wszm => return Eval (hsbr) + Eval (rscq); when pbgr => return Eval (glqw) * Eval (qqnm); when hzlh => return 2; when qnbn => return Eval (jpvr) - Eval (bgzz); when hrcp => return Eval (fjvg) * Eval (vjbz); when dnwd => return Eval (lqrf) * Eval (flhd); when rvlz => return 3; when stcr => return Eval (cblz) + Eval (nfnw); when ptvh => return 3; when vmnc => return 5; when bmwf => return Eval (rpbm) * Eval (cvgt); when jzdn => return 2; when djrh => return Eval (ccjf) * Eval (fqgl); when lwlb => return 5; when bqht => return Eval (cldm) * Eval (btqb); when brfj => return Eval (prbr) + Eval (qqwz); when rlqm => return 2; when mdht => return Eval (jflm) - Eval (trpt); when lbbj => return 2; when blnq => return 6; when chfz => return 3; when sqsc => return 5; when mwrt => return Eval (slnh) + Eval (thcc); when nvrb => return 3; when lgrj => return Eval (qnvn) * Eval (tnbt); when pvcn => return Eval (qhwm) * Eval (smld); when fbgc => return 2; when mqnl => return Eval (drlt) * Eval (bbhp); when bdtp => return Eval (gzpf) * Eval (qdnl); when wdwf => return Eval (fhjc) - Eval (zpbt); when hhjc => return Eval (qbvr) + Eval (fmwn); when jzlv => return Eval (cftm) * Eval (rhtv); when smwb => return Eval (dgbr) + Eval (rbbh); when bhvg => return Eval (lpfz) + Eval (bjnj); when zmmd => return Eval (smsm) + Eval (jfcd); when mdld => return Eval (zzqd) + Eval (bdmw); when qlqt => return Eval (zfbq) + Eval (ntqb); when dgbr => return Eval (sbwd) * Eval (cgvr); when rwsm => return 10; when jnll => return Eval (nztj) * Eval (vzgb); when dbht => return Eval (jdcd) * Eval (rccr); when bhmz => return 3; when mrlq => return Eval (bbjs) + Eval (drdl); when fzdg => return 2; when jbsh => return 2; when svzv => return 2; when zjmw => return 3; when tcgm => return 2; when nzcv => return 6; when rmrj => return Eval (mtsv) + Eval (snlb); when bjnj => return 2; when qsml => return 18; when mfts => return Eval (mwjg) * Eval (pjsp); when ffqs => return Eval (rhcv) - Eval (rrnt); when dbcw => return Eval (gtbs) * Eval (mbvg); when wpcs => return Eval (phbh) * Eval (mnhf); when rvhs => return 2; when qmcb => return 17; when hlms => return 11; when vwpq => return 2; when wslz => return Eval (szhq) / Eval (hstj); when jpvr => return Eval (sflt) + Eval (drvt); when hcdz => return Eval (nfhw) * Eval (qgjf); when svvq => return Eval (twdf) * Eval (rhqj); when lgpg => return Eval (wglc) + Eval (gwmr); when mlwr => return Eval (zfmv) + Eval (hbqm); when hbqm => return 1; when fgbm => return Eval (lltp) + Eval (fwmw); when cjlh => return Eval (btfl) * Eval (mpnj); when tlmq => return Eval (fqwz) * Eval (lwhp); when zzqd => return Eval (vnpq) / Eval (rlqm); when drdl => return Eval (hzlh) * Eval (btqt); when sdjb => return Eval (ssnq) * Eval (gzwm); when ntmt => return 3; when rwth => return Eval (tdjh) + Eval (cstb); when jjgt => return Eval (crqg) * Eval (dmrn); when mpvz => return Eval (ppwc) * Eval (chpt); when qbmm => return Eval (rqpj) + Eval (rfcm); when zdrh => return Eval (csml) + Eval (cvvv); when trft => return Eval (lbbv) * Eval (nlgg); when dqjz => return 7; when gfrq => return 4; when vvgt => return Eval (zrwb) / Eval (rfcq); when tsft => return Eval (sstg) + Eval (ngfs); when gzpf => return 2; when tfpw => return Eval (gmln) * Eval (hqbd); when cddt => return 6; when rlbp => return 1; when ndph => return Eval (ztzq) * Eval (jgzl); when blbc => return Eval (jfvq) * Eval (cprt); when cvhn => return Eval (jdgq) * Eval (llcn); when zncl => return Eval (mwrt) + Eval (dbgp); when rthb => return 2; when jfld => return 4; when gdgd => return 7; when lrsc => return Eval (vdzv) * Eval (czst); when gzgm => return 4; when bhrb => return Eval (pnvc) / Eval (smdh); when bsmm => return 2; when qnds => return Eval (sbvl) * Eval (szmm); when bhzq => return Eval (zhmb) * Eval (qfss); when vwvc => return 17; when qmgt => return 3; when gfml => return 4; when tjqj => return Eval (glpw) * Eval (zsns); when vlmc => return 4; when qlnr => return Eval (ndph) + Eval (twtq); when fvph => return 3; when jgzl => return Eval (drct) + Eval (vwdt); when wnjc => return 2; when ffbb => return 2; when hzmn => return Eval (pgbv) + Eval (rwbg); when rpbj => return Eval (shrh) * Eval (jvqf); when sqmd => return 2; when ndcd => return Eval (sdgs) * Eval (spjg); when mmbs => return 3; when mhbr => return Eval (wggq) + Eval (grcv); when nsqq => return Eval (cvfw) * Eval (ffmp); when wgvv => return 2; when rvmp => return Eval (nnzp) * Eval (dbcw); when dwnz => return 2; when jvtz => return Eval (fctt) + Eval (bfpq); when nzzv => return Eval (jbcl) * Eval (llnl); when cqcg => return 3; when nrvw => return 2; when qqtm => return 3; when fvng => return 19; when phrv => return 3; when tlzh => return 11; when twjs => return Eval (ltnz) - Eval (ltsv); when lhgv => return Eval (nwqz) + Eval (qflq); when rctr => return Eval (mhdn) * Eval (mvnc); when snlb => return 4; when dfgh => return 7; when tvtj => return 13; when flcb => return 2; when nqpr => return 3; when jmbp => return 4; when rcmc => return Eval (bpjf) / Eval (qrzq); when mnpl => return Eval (pbdd) - Eval (qpct); when twcj => return 3; when nlth => return 2; when drrq => return 13; when fszd => return Eval (bmwf) + Eval (qspw); when mlrz => return 2; when jvgd => return Eval (dvnh) - Eval (mpjj); when jtvw => return Eval (nzhf) - Eval (wfnl); when ftvm => return 3; when cgcz => return Eval (njcj) - Eval (bjbr); when dfzw => return 2; when tdhw => return Eval (rzjm) * Eval (qrgn); when qwnt => return 2; when mspb => return Eval (dggg) + Eval (ghtd); when fhmz => return 2; when dqzt => return 5; when brfc => return Eval (dczh) - Eval (tfpw); when hstj => return 2; when rzjm => return 5; when jbcl => return 3; when zhpq => return Eval (gpzn) * Eval (cnmq); when hmrs => return Eval (ltqr) * Eval (hslj); when mtdh => return 8; when lwhp => return 5; when wnvf => return 8; when qqdn => return 3; when wrmw => return Eval (fwrh) * Eval (rbmm); when gzrs => return Eval (jclb) * Eval (zjpc); when nzwc => return 3; when wflc => return Eval (cbgj) / Eval (qllm); when gtwp => return 3; when trbs => return 2; when zsns => return 2; when vvvb => return Eval (wrpp) - Eval (qrsg); when cstb => return Eval (dfps) * Eval (svwg); when gcmv => return Eval (whbb) * Eval (mfnh); when vrjj => return Eval (lbbj) * Eval (jgnj); when rrll => return Eval (scdt) * Eval (zjmw); when wgsb => return Eval (jqrl) * Eval (jlwb); when scdt => return Eval (vlmc) * Eval (qfln); when wqqv => return Eval (nrps) * Eval (pnwz); when szhq => return Eval (nchp) * Eval (ndtz); when tqzf => return 3; when wpqd => return Eval (jqsn) * Eval (przh); when vmzc => return Eval (nhpf) * Eval (gcqh); when pjlz => return 2; when mdjm => return 3; when qgjf => return Eval (pgvq) + Eval (spgw); when qnhq => return Eval (rncj) * Eval (rllb); when hfbg => return 2; when jfsr => return 8; when nfhw => return 2; when cstm => return Eval (rgzs) * Eval (nbcb); when ghvl => return Eval (dbfd) + Eval (qbmm); when tzcl => return 2; when pzzg => return Eval (ltmj) - Eval (mfts); when cdqv => return Eval (dfgh) + Eval (mnlp); when wcpr => return 5; when jdrg => return Eval (qmpm) + Eval (hlmn); when gtqh => return 8; when hlmn => return Eval (rdnj) + Eval (sjcd); when hnqc => return Eval (mfsz) / Eval (hbzt); when sphc => return Eval (vrcl) * Eval (nhfw); when bnlr => return Eval (qhvn) * Eval (vvzh); when dbfd => return Eval (bcnp) / Eval (ffvs); when hpzh => return Eval (snwm) + Eval (rrnp); when ghqp => return 5; when dfql => return Eval (dzwg) * Eval (snbl); when hbzt => return Eval (shwr) + Eval (rthb); when chsm => return Eval (crmb) * Eval (scwp); when lpjq => return Eval (wlpd) * Eval (fcgs); when plfd => return Eval (sqsc) * Eval (hvsd); when vbvt => return Eval (ghqp) * Eval (qmjq); when rdpg => return 7; when vhds => return 12; when rmfv => return 5; when smft => return Eval (crmw) * Eval (msdr); when wlpd => return 2; when cvvw => return 2; when bsqn => return Eval (wlfp) + Eval (sdjb); when svcp => return Eval (jfmb) + Eval (rwsm); when qflq => return Eval (scrz) * Eval (dtfz); when bwwc => return 3; when wqfg => return Eval (qmzt) * Eval (chfz); when lbqn => return 5; when zbhw => return Eval (wcdm) + Eval (hhjc); when jlnf => return 3; when nlst => return Eval (wmzt) + Eval (twjs); when zfjw => return Eval (tbdh) + Eval (rmmz); when wfms => return 2; when fjps => return 5; when djpm => return Eval (pznf) * Eval (qlnr); when snsc => return 2; when hnlj => return 5; when pvfm => return 2; when cwhc => return 3; when blgg => return 15; when jmwl => return Eval (rdpb) * Eval (zpht); when wbsb => return Eval (jcdb) * Eval (ngbz); when jwwv => return 2; when jdsd => return 5; when rsnp => return 3; when rrnt => return Eval (jnnp) * Eval (dmtd); when nfnw => return 2; when mpfm => return Eval (mfrc) * Eval (qrch); when mnzz => return Eval (lwld) + Eval (jbwd); when lfjp => return 3; when qvfg => return Eval (fdmf) * Eval (svst); when mjmv => return Eval (cdwt) + Eval (pzvr); when lclg => return 8; when pcvv => return Eval (rvmp) + Eval (hmrs); when wsml => return 3; when gvbp => return 3; when mpjj => return 10; when vcqw => return Eval (jjjj) * Eval (brmz); when lhvt => return Eval (pmds) * Eval (tqzf); when qpdv => return 15; when mrlc => return Eval (zbhw) * Eval (svzv); when bdmw => return Eval (fpsh) * Eval (hwvf); when vntv => return Eval (npvl) * Eval (mbqs); when cfdl => return Eval (mfhg) * Eval (gzbv); when gvww => return 2; when dqhh => return Eval (gzwh) * Eval (thpg); when mtnb => return Eval (mqph) * Eval (bnfp); when wlfp => return Eval (ntsl) + Eval (lfhp); when zslv => return 3; when lqrr => return Eval (hhbn) * Eval (gmzh); when qfzb => return Eval (nhjt) + Eval (mjmt); when ltzm => return 12; when qcnn => return Eval (mnpl) - Eval (wsnf); when bhvr => return Eval (lflj) + Eval (rfjw); when wnzr => return Eval (jbrp) * Eval (nnmh); when zglw => return Eval (flcb) * Eval (cqmq); when svdw => return 4; when pfml => return Eval (bnlr) + Eval (ndcd); when zpqd => return 2; when fjnh => return 5; when rhqj => return Eval (qrpv) + Eval (ngzp); when szmm => return 3; when ztwb => return 9; when npnf => return 1; when wltv => return Eval (rqfq) - Eval (hncq); when bwff => return Eval (dwdd) + Eval (qhzd); when slnh => return Eval (ljnf) * Eval (tnfz); when ppwz => return Eval (hqbb) * Eval (nlts); when hgls => return Eval (wnzr) / Eval (wwtj); when dbvt => return 3; when wrst => return Eval (qdrg) + Eval (bnfz); when rzzg => return Eval (rpbj) + Eval (fsrm); when prbr => return Eval (hpzh) - Eval (zmtg); when bvdb => return 2; when jlmb => return Eval (cmtm) - Eval (qbjm); when rbpq => return Eval (wnbb) * Eval (glts); when jwjj => return 15; when dhts => return 8; when dcpm => return 3; when qvpv => return Eval (grcn) * Eval (cgwj); when bbhp => return 2; when sjfs => return Eval (ztpd) - Eval (bnzl); when wqpv => return Eval (fzgj) * Eval (rvvn); when sdhj => return 2; when wfbz => return 2; when mdnp => return Eval (gvfn) * Eval (tfqh); when ctjq => return Eval (tgvp) * Eval (wjzd); when mbqs => return Eval (rrmg) * Eval (rnnq); when wcfp => return 3; when ftzm => return 3; when nwbt => return Eval (bhpw) * Eval (bhgh); when bmsf => return Eval (fnws) / Eval (bcmp); when cmnt => return Eval (bvjd) + Eval (lccn); when wqfz => return 4; when jrgs => return Eval (hjgd) + Eval (mpst); when gmzh => return Eval (drhw) / Eval (sdsl); when pnvs => return Eval (bmsf) * Eval (qljb); when gcvn => return Eval (wqqv) + Eval (dqnv); when qbvr => return Eval (ltds) - Eval (vsgw); when phbh => return Eval (snsc) * Eval (flhs); when shtz => return Eval (pnrv) + Eval (pvcs); when smsm => return 4; when gznh => return 7; when tjch => return Eval (ncrt) * Eval (rrgh); when bpnt => return Eval (ccfw) + Eval (dfql); when lljf => return 3; when qfsz => return 2; when dgvh => return 3; when lvbp => return Eval (hdrj) + Eval (trbs); when cdvv => return 4; when qlzg => return 2; when rwbg => return 2; when snff => return 4; when flrw => return 3; when tdnf => return 4; when nzlr => return 2; when ftzc => return 2; when pznf => return Eval (cllb) * Eval (zzcv); when zjvz => return Eval (znfq) * Eval (chlt); when nvjl => return Eval (ngzt) * Eval (wbgs); when qtvv => return 2; when hdff => return 4; when swmh => return Eval (vrbh) + Eval (jdjq); when ghfr => return 2; when ghtd => return Eval (cfzf) * Eval (gnsc); when mfmt => return Eval (cdqv) * Eval (chfs); when pgtq => return Eval (phwc) * Eval (gbgs); when frjp => return 17; when bnfz => return 2; when qfqz => return Eval (mswh) * Eval (slds); when djmr => return 2; when crcm => return Eval (lsnd) + Eval (zbqq); when ngbg => return Eval (jgld) * Eval (lhfr); when sbqm => return 3; when wlqd => return 2; when jfrn => return 3; when jbqf => return Eval (cdvw) * Eval (dnvm); when zhrs => return Eval (pjjj) + Eval (fngd); when lvtv => return Eval (nvjf) / Eval (nmlg); when vclb => return Eval (bbcn) + Eval (jqhr); when qtgd => return 2; when hqbd => return 4; when qqnm => return Eval (nsqq) - Eval (rfbw); when nvjh => return 6; when jcgh => return Eval (pmwl) * Eval (hcqw); when bgzz => return Eval (swsv) * Eval (qldj); when slds => return 2; when lwsn => return Eval (hcfs) + Eval (rswn); when bhgh => return Eval (hcsc) * Eval (mzzd); when bjbr => return 3; when tgvp => return Eval (smft) / Eval (cnhr); when dbfm => return 9; when msmm => return Eval (djmr) * Eval (bshp); when llqs => return Eval (mmps) + Eval (pwqg); when qqpl => return 5; when pfdc => return Eval (mwmp) + Eval (zvqs); when qlvg => return 2; when wzdv => return 3; when glqr => return Eval (qqpl) * Eval (blgg); when vdgt => return 5; when qrnj => return Eval (fjrq) * Eval (nwhm); when fbrf => return 3; when gvmj => return Eval (ngbg) / Eval (vsqt); when nrjc => return 2; when sdsl => return 2; when mqvg => return Eval (tbqq) - Eval (bzqw); when chvq => return Eval (jdsd) + Eval (cgcz); when lrzn => return Eval (gfrq) + Eval (drgv); when crrm => return 2; when pgbv => return Eval (swhz) + Eval (dqld); when brqv => return 2; when gmln => return 2; when wcmz => return 3; when hbhz => return 18; when vrcl => return 5; when hqdv => return 5; when nchp => return Eval (dtzl) + Eval (qpdv); when bfvd => return 7; when nnhm => return Eval (pzpp) * Eval (dwnz); when thpg => return 4; when jpzw => return 3; when vrmt => return Eval (lqrr) - Eval (smrq); when hnbn => return 2; when tsbf => return Eval (lljf) + Eval (mqnl); when nbpq => return 2; when csml => return Eval (lbtn) * Eval (zspm); when cnmq => return 8; when qbwf => return Eval (vvhm) - Eval (dsqb); when jbrp => return 11; when bbzc => return Eval (ffbb) * Eval (lqft); when pgfr => return 3; when fmwn => return 2; when lrvc => return 10; when stqc => return 5; when ngzt => return Eval (rlbp) + Eval (fbjn); when mdrm => return Eval (jhwn) + Eval (lmht); when mrtq => return Eval (rzcm) * Eval (nqgr); when lpvs => return 9; when lqfq => return 3; when rnnq => return 3; when jdfj => return 15; when tqst => return Eval (cjbz) + Eval (rvhn); when dnzc => return Eval (mmbs) * Eval (qlmw); when lwld => return 1; when sgjm => return 8; when bfzd => return 17; when dchw => return 4; when rlrb => return Eval (tftg) + Eval (qbqm); when pchr => return Eval (trft) + Eval (bcbw); when lvhm => return Eval (dhqh) * Eval (dchw); when mswh => return 5; when sdgs => return 5; when snfj => return 1; when sdwj => return 2; when qmqt => return Eval (wttp) / Eval (cgnv); when przh => return Eval (wqlh) + Eval (nqzz); when qrpv => return Eval (sqmd) * Eval (tpdj); when pjsp => return 5; when hpmw => return Eval (zdsr) * Eval (rlrb); when jhlw => return 9; when ntqb => return Eval (gzmv) * Eval (pzzg); when qpct => return 3; when rvvn => return Eval (rrqr) * Eval (wflc); when lmcj => return Eval (szcv) + Eval (lqcm); when bvjd => return 2; when fngd => return Eval (wjds) * Eval (nrvw); when fnws => return Eval (jmwl) + Eval (rtgr); when frqq => return 4; when ltsv => return 3; when cmnv => return 7; when wdqj => return Eval (vhrn) * Eval (hpmw); when cjbz => return Eval (qlzt) * Eval (fqjd); when rqpj => return Eval (tqst) * Eval (ptdz); when lbtn => return 8; when dbgp => return Eval (lbzn) * Eval (jqtj); when qbjm => return 12; when ljzj => return 15; when mrvr => return 3; when nght => return 2; when djff => return 12; when jmqh => return 14; when vcpt => return Eval (ppwz) * Eval (zvqw); when vsqt => return 5; when tfjw => return Eval (bhvr) * Eval (vjgb); when hwvf => return Eval (vszg) + Eval (lvrc); when qgtf => return 6; when mmtj => return 6; when blgf => return 3; when mvmz => return Eval (qpqb) * Eval (cvhn); when svhz => return Eval (jqcf) * Eval (nzzv); when wfds => return 3; when pnmc => return 13; when szvb => return Eval (mdld) + Eval (bfgp); when bnwj => return 2; when dnvm => return Eval (msmm) - Eval (tqfz); when fwrh => return Eval (wdqj) - Eval (dqnp); when cspp => return Eval (mggl) + Eval (rndt); when lltp => return Eval (rwcd) * Eval (wfds); when smrq => return Eval (lrlg) + Eval (bwqm); when rgzs => return 3; when crmw => return Eval (ntmt) + Eval (cjlh); when dncw => return 5; when rvjf => return Eval (mttr) * Eval (frlv); when wlmv => return 4; when fqbj => return Eval (pfdc) * Eval (rqbd); when fwjg => return Eval (vdsz) * Eval (brfj); when gnsc => return 2; when gtwd => return 2; when qdnl => return Eval (nmvn) - Eval (wpqd); when pjjj => return Eval (bnjt) + Eval (fhdz); when ntsl => return 1; when glqw => return 3; when wmzt => return 3; when vjzr => return Eval (swmh) + Eval (svhz); when ncgd => return 3; when bngr => return 5; when qtfp => return 2; when bdqg => return 2; when hzpr => return 5; when tctd => return 13; when jlqg => return 4; when qhlj => return Eval (gcvn) + Eval (bntz); when jtvm => return 9; when szcv => return Eval (jswz) + Eval (lbvn); when sfmn => return Eval (wchl) + Eval (cscm); when lfhp => return Eval (nght) * Eval (wcfp); when root => case part is when part_1 => return Eval (bsbd) + Eval (fcgj); when part_2 => return Eval (bsbd) - Eval (fcgj); end case; when jbwd => return 6; when zrnr => return 2; when hrmz => return Eval (mthn) * Eval (dncw); when rfjw => return 13; when hpdh => return 2; when jqrl => return Eval (pvwn) + Eval (hjmr); when vgsm => return 5; when mvgg => return Eval (nbfg) + Eval (mtfr); when hcqw => return 14; when cdtq => return Eval (rjrt) / Eval (mffc); when spgw => return Eval (wbvt) * Eval (clbn); when wfjn => return 5; when hrtz => return Eval (llqs) * Eval (rvlz); when rzsn => return 5; when fbcd => return Eval (mfmt) + Eval (humn); when vhwz => return Eval (mtwg) + Eval (fbgc); when lvcn => return 4; when grdf => return Eval (dbht) + Eval (sgvm); when pdbc => return Eval (rsnp) * Eval (djqq); when qssh => return 5; when wnjl => return 9; when btwt => return Eval (tzth) * Eval (hrtv); when hplt => return 11; when mwwr => return Eval (bsnq) * Eval (crrm); when smqg => return 14; when dqcj => return Eval (blbc) + Eval (bghp); when ptwr => return 7; when mttr => return Eval (hnqc) * Eval (wfms); when pzcc => return 5; when jscq => return 1; when hzcm => return 4; when tsjq => return Eval (nsfm) * Eval (hpdh); when fsgb => return Eval (vhhz) + Eval (jhgd); when plvw => return Eval (zpqd) * Eval (rffd); when tcqz => return Eval (dqhh) + Eval (mlrz); when mqzp => return 2; when tldn => return Eval (rjfh) * Eval (zwqw); when rwmq => return Eval (tdnf) * Eval (jdrg); when vnft => return Eval (mqrm) + Eval (tjch); when ztqg => return Eval (wtwb) * Eval (bqld); when fjvg => return Eval (snfj) + Eval (gbzd); when nzdz => return Eval (sfcv) + Eval (qtgd); when qrgn => return 5; when tbqq => return Eval (jplv) * Eval (rmzw); when tdjh => return Eval (wrst) * Eval (wnjl); when qwqw => return 5; when pdbt => return 11; when bnmb => return Eval (cvnr) * Eval (nvrb); when lslq => return 1; when twwv => return 19; when rzcm => return 6; when jtjd => return 6; when htgm => return 3; when pjss => return 2; when mrwz => return 12; when djqq => return 4; when jmcf => return 12; when hmqr => return Eval (zrpj) - Eval (nttd); when lqdc => return 5; when gpzn => return Eval (hpvb) + Eval (tpwq); when pgdw => return 4; when mwgb => return Eval (nvdh) * Eval (mrrt); when wggq => return Eval (bgwj) + Eval (tldn); when mwqc => return 2; when bnfp => return 13; when pwlt => return 5; when hlzp => return Eval (phrv) + Eval (hrmz); when qplw => return Eval (ncgd) * Eval (cmnt); when vhqz => return Eval (pgtq) - Eval (ncnm); when zptr => return 3; when gtbs => return 13; when zwwb => return Eval (pqqj) * Eval (dpqz); when hmfb => return 4; when mffc => return 3; when lqgr => return 9; when bcqm => return Eval (vjzr) + Eval (jzlv); when cbdr => return Eval (wbsb) + Eval (cspp); when bssd => return 2; when dmsz => return Eval (vwdl) + Eval (rmqt); when fpwz => return Eval (ltsl) * Eval (fbqs); when rbmm => return 2; when rvhn => return Eval (ttwm) * Eval (tctd); when hqjt => return 7; when bftg => return Eval (ftjv) * Eval (lghm); when ppjl => return Eval (lfpz) / Eval (nlcv); when nzbp => return Eval (chtt) * Eval (hnst); when rwzt => return Eval (ltgf) * Eval (qwqq); when zwgg => return 5; when frlv => return 3; when vmgn => return 1; when tvrd => return Eval (qnhq) + Eval (ldzb); when wfld => return 8; when pnwz => return Eval (stlr) / Eval (fbrf); when ndmd => return 2; when fmbj => return Eval (slmm) * Eval (twsj); when jqcf => return 3; when jqsn => return 15; when wzsh => return 3; when hjqq => return 11; when cvqf => return Eval (mpws) * Eval (sdrn); when wrll => return 2; when vtns => return Eval (jvrt) / Eval (cjvp); when wsnf => return 4; when qfjg => return 1; when rsqz => return Eval (bbzc) - Eval (vfwd); when dddm => return 2; when ftmn => return Eval (wcmz) * Eval (hrtz); when bcnd => return 13; when qgtc => return 3; when vthd => return Eval (zbzf) * Eval (mmnw); when mvnc => return 2; when ndpf => return 10; when pwlh => return Eval (hbhz) + Eval (rtmt); when cfzf => return Eval (rlqh) + Eval (qfrg); when qldj => return 2; when ftqd => return Eval (nssr) * Eval (mqzp); when lhml => return 7; when mrmm => return Eval (pszs) * Eval (cjlm); when crnb => return Eval (ndnm) + Eval (lslq); when qpbz => return 3; when qspw => return 4; when jtrg => return 7; when nwwb => return Eval (hfvj) * Eval (snmq); when rgpt => return 4; when spcf => return Eval (cdvv) * Eval (wpgm); when brqh => return Eval (bndd) + Eval (nbbd); when qfrg => return Eval (hdff) * Eval (qmgt); when ddmr => return Eval (fhzm) + Eval (qvbn); when lpqs => return 1; when zvqs => return 11; when dfdl => return 3; when vnbv => return Eval (ldbp) * Eval (frjl); when bwqm => return 19; when zjpc => return 4; when btbn => return Eval (cvvw) * Eval (hnlf); when bpgp => return Eval (nqlh) - Eval (gqgh); when jbsn => return 3; when tdlw => return 3; when fsrm => return Eval (pzqv) * Eval (zjcn); when rjrt => return Eval (nzwc) * Eval (gcmz); when wpdn => return Eval (rsdv) * Eval (wcfj); when dzvg => return 2; when rdfn => return Eval (rbqt) * Eval (btzg); when zrnz => return Eval (cbjq) * Eval (jmbs); when djgb => return Eval (mrnr) + Eval (ttdb); when pwln => return Eval (vqlt) * Eval (mnrr); when vfgt => return 7; when tbdh => return Eval (dzvg) * Eval (stcv); when jlwb => return 3; when cshj => return Eval (pwgj) + Eval (rpbg); when lzhf => return 5; when hncq => return 11; when nqms => return 5; when lhfr => return Eval (fgbm) / Eval (mstm); when ltdq => return 4; when zssf => return 5; when dqld => return Eval (sjrh) * Eval (zdhf); when grcv => return Eval (pnvs) * Eval (gvgp); when zfbq => return Eval (ggbp) * Eval (plfd); when lmjg => return 4; when lncn => return 1; when qmjq => return 5; when rnbs => return Eval (vtgj) + Eval (dpmg); when mstm => return 2; when pnwh => return 2; when ccfw => return 8; when tsqc => return 2; when gqpj => return Eval (hqjt) + Eval (fwzf); when tnfz => return Eval (qrln) * Eval (nvpd); when rhwm => return 4; when bcnp => return Eval (dcfw) / Eval (nzlr); when fvrg => return 3; when vtgj => return 5; when wwtj => return 5; when slmm => return Eval (crrj) + Eval (bcgz); when mjmt => return 4; when zzpd => return 2; when wttp => return Eval (lbgc) - Eval (gnrj); when qdfp => return Eval (qlvw) * Eval (hmfd); when psfr => return Eval (wfbp) * Eval (wzdv); when rlqh => return Eval (ptwr) * Eval (lvbp); when mgsz => return Eval (qqpt) * Eval (hgls); when cjvp => return 2; when hrjj => return 2; when fjrq => return 6; when qmpm => return Eval (bwwc) * Eval (hcdz); when lddq => return Eval (rjbz) + Eval (ppsl); when snbl => return Eval (vwhb) * Eval (szwj); when bghp => return Eval (wgcm) * Eval (tfdv); when zdnh => return 11; when cbqn => return Eval (ppfs) * Eval (fjps); when pbzb => return 2; when rmzw => return Eval (ftvm) + Eval (mhlj); when qpqb => return Eval (ptnv) + Eval (vhds); when jffq => return 3; when rscq => return Eval (bcdf) + Eval (tfjw); when wjzv => return Eval (vcqw) / Eval (nqpq); when ngbz => return 2; when hdrj => return 5; when slpc => return Eval (jstb) + Eval (lncn); when bmzw => return 5; when cmtm => return Eval (twcj) * Eval (tjqj); when pwqg => return 17; when dgpr => return Eval (bpgp) / Eval (lmjg); when trpv => return 7; when qnvn => return 2; when gcqh => return 3; when bdgd => return 2; when dbcs => return Eval (nrqv) - Eval (zlpv); when nrqv => return Eval (fvph) * Eval (hzrc); when cnvb => return Eval (hrjj) * Eval (lbqn); when cvgt => return Eval (qhtv) * Eval (vgsm); when tqlp => return 2; when sgpj => return 11; when swsv => return 7; when hndh => return 2; when smwv => return Eval (gssz) + Eval (rgrp); when dwdd => return Eval (fzdp) / Eval (gtwd); when jszj => return Eval (gqrp) + Eval (tpnf); when ncrt => return Eval (ntnh) + Eval (mwgb); when rpbg => return 1; when jvsz => return Eval (ndmd) * Eval (hrbr); when ffvs => return 2; when mnhf => return 3; when hbwh => return Eval (ggpn) + Eval (pbzb); when tpmp => return Eval (qjqw) * Eval (hzvm); when nttr => return 3; when ldbg => return Eval (cprm) * Eval (wrbf); when ntpj => return 4; when lbbv => return 3; when vrct => return 2; when lccn => return 5; when nrsd => return 10; when fvzw => return Eval (mwwr) + Eval (vmgn); when vgjq => return 2; when dptm => return 6; when ggbp => return Eval (wbnh) + Eval (jhvm); when qdrg => return 5; when hcpf => return 4; when zrbc => return 3; when tpjw => return Eval (shcg) / Eval (hjmp); when jnqv => return Eval (wwqp) + Eval (jcgh); when fzrd => return 2; when cbjl => return Eval (jdfj) * Eval (bnwj); when bnjt => return 1; when czpd => return 4; when fjld => return Eval (tpjw) + Eval (ghvl); when sbwd => return 4; when rqfq => return Eval (lhmd) * Eval (nfvj); when pwpn => return 3; when ztzq => return Eval (nqsl) - Eval (vzts); when ltqr => return Eval (dqcj) + Eval (qbgj); when nlgg => return Eval (rvhs) * Eval (rqss); when ltsl => return 2; when zgzs => return 3; when mqrm => return Eval (cqcg) * Eval (cbdr); when fhtw => return Eval (fcql) + Eval (brqh); when zdfg => return Eval (blmp) + Eval (qwcl); when dzwg => return 4; when czst => return Eval (smwb) - Eval (pvcn); when ncsp => return Eval (rddj) - Eval (zhpq); when bsnq => return 3; when sflt => return Eval (qtvv) + Eval (ftmn); when vsmt => return Eval (pwlh) + Eval (gztl); when vszg => return Eval (smqg) / Eval (dfzw); when tqfz => return Eval (wmdp) / Eval (mwms); when fhzm => return Eval (lfjp) + Eval (rjtc); when wgcm => return Eval (dsgt) / Eval (tqlp); when zsvh => return Eval (grdf) + Eval (svcp); when hjfj => return Eval (lmcj) * Eval (hndh); when pqsr => return 2; when lrbp => return Eval (wgsb) / Eval (htgm); when twdf => return 2; when jdbp => return Eval (pnvd) * Eval (ghfr); when smdh => return 4; when cjhz => return Eval (pvfm) * Eval (gbtc); when psfp => return 3; when cqmq => return 13; when nvlv => return 17; when lrqh => return Eval (gmzt) + Eval (gmpl); when wqlh => return 16; when qrsg => return 3; when zzcv => return 14; when sgzh => return Eval (mvgg) * Eval (zgdb); when vrbh => return Eval (wqpv) / Eval (gwhs); when drlt => return 5; when shrh => return 13; when qrln => return 2; when hslj => return Eval (mgsz) * Eval (jddd); when mtsv => return 3; when hmfd => return 2; when grcn => return 13; when fctt => return Eval (smhv) * Eval (qzpn); when lhmd => return Eval (vszd) + Eval (nfgv); when rtgr => return Eval (nvhn) * Eval (szvb); when zmvz => return Eval (fqbj) * Eval (swhh); when jdjq => return 4; when vhzf => return 2; when fmvc => return Eval (fjcg) * Eval (dhts); when dzlc => return Eval (rbpq) + Eval (vntv); when fbjn => return Eval (tvrz) / Eval (nvjh); when ppcl => return 3; when jjjj => return 2; when wfnm => return Eval (fvrg) * Eval (tzcl); when dflc => return 2; when ffnt => return Eval (mzfn) + Eval (vcpt); when zbnt => return 3; when dqnh => return 2; when slww => return Eval (stzl) + Eval (pcwz); when djjs => return Eval (ltzm) + Eval (qfjg); when sqml => return 7; when lghm => return 2; when bsbd => return Eval (rzff) * Eval (wdwf); when gwhs => return Eval (czpd) * Eval (jbsh); when zqpw => return Eval (jsrb) + Eval (jwjj); when drgv => return 3; when rswn => return 5; when gnjq => return 2; when sjcd => return Eval (bcpn) * Eval (fvzw); when fzml => return 11; when mthn => return 2; when cgnr => return 4; when ldbp => return Eval (vrmt) + Eval (gptt); when lqrf => return 2; when gjbv => return Eval (djff) * Eval (stqc); when ljnf => return Eval (rtjb) * Eval (wtnp); when hjmp => return 6; when mrnr => return 2; when zspm => return 5; when qlvz => return Eval (gjzv) + Eval (hpmm); when tfdv => return 2; when vtvn => return Eval (hrcp) * Eval (wtlq); when qlmw => return Eval (vcfm) + Eval (pqsr); when hsmp => return Eval (rpwz) * Eval (wclq); when wcfj => return 2; when brst => return 5; when fnrh => return 2; when qhzd => return Eval (fqlp) + Eval (jpzw); when mmps => return Eval (jfld) * Eval (lqgr); when lpfz => return Eval (lqfq) * Eval (wgbc); when bjcs => return Eval (mhbr) / Eval (vgjq); when tbqc => return 2; when qhwm => return 3; when hzvm => return Eval (npnf) + Eval (nhnp); when nqhg => return Eval (tcjb) + Eval (hgzs); when bzdh => return 2; when gbtc => return 3; when wfnl => return 5; when ndlf => return Eval (cdnp) + Eval (ddmr); when nmlt => return Eval (pnpc) * Eval (hnlj); when nhfw => return Eval (tbqc) + Eval (dnzc); when rtbm => return 3; when fbpz => return Eval (sqzp) + Eval (pjrt); when rjtc => return Eval (tjtl) + Eval (wtlg); when vspf => return Eval (bnmb) + Eval (ndsm); when dhqh => return Eval (dhpp) * Eval (zsvh); when ddln => return 1; when lbzn => return 2; when vhrn => return Eval (bjcs) - Eval (vnft); when cgcc => return 6; when cgvs => return 7; when jqtj => return 5; when wqnp => return 12; when dmtd => return Eval (fjzz) + Eval (sgpj); when rlvd => return Eval (vlqd) / Eval (mgsl); when cvvv => return Eval (bqtp) * Eval (pnwv); when rjdp => return Eval (qfzb) + Eval (csnf); when hmvq => return 17; when vjtf => return Eval (lbzc) * Eval (djjd); when gbgs => return Eval (mqfd) - Eval (fmbj); when wgbc => return 3; when vdbp => return 1; when vtdp => return 10; when cgvv => return Eval (bfvd) * Eval (pbhg); when vfhg => return Eval (nlsw) - Eval (qgnb); when pcwz => return Eval (dptm) * Eval (frjj); when zngg => return 4; when scrz => return 2; when tvrz => return Eval (wslz) / Eval (dpvl); when mqzw => return 2; when zfmv => return 10; when gdmv => return 5; when cgnv => return 2; when qlvw => return Eval (rfcv) + Eval (nlst); when fjzn => return Eval (hgnr) + Eval (lqml); when vzgb => return 12; when dsng => return 5; when pbvh => return 3; when qbqm => return 10; when vwdt => return Eval (lgrj) / Eval (pmlg); when lhsw => return Eval (lpjq) + Eval (rdbs); when hzjj => return 3; when jplv => return 3; when zmlh => return Eval (nfbp) * Eval (fhtw); when zwbh => return Eval (sshm) * Eval (rjdp); when mhnm => return Eval (bwnc) + Eval (fzwr); when wmdp => return Eval (tdhw) - Eval (gjmt); when pbhg => return 2; when qmzt => return 9; when dlws => return Eval (bssd) * Eval (rtbm); when rbzl => return Eval (pjlz) * Eval (qfqz); when tpjp => return Eval (jdsc) * Eval (wqnp); when vlgn => return 2; when phwc => return 10; when bcng => return Eval (ctjq) + Eval (bdtp); when cvnr => return Eval (qtmp) + Eval (bmzw); when bmlj => return Eval (fvng) + Eval (czvm); when llhb => return 3; when nbcb => return Eval (rnns) + Eval (ldbg); when ffmp => return Eval (plzd) + Eval (tzcd); when nnzp => return Eval (lhsw) * Eval (tlwr); when szlh => return 2; when gztl => return 11; when mtwg => return Eval (hcpf) * Eval (pjss); when mpws => return Eval (pnfb) * Eval (pbvh); when fqgl => return 3; when qqpt => return 5; when bqtp => return 2; when nttd => return 9; when svvh => return Eval (shpt) * Eval (fmvc); when drnb => return Eval (lqqh) * Eval (mlbw); when ptnv => return Eval (csgr) + Eval (plvw); when wtnp => return 3; when ndgh => return 4; when lrgv => return 2; when nrqr => return Eval (vvbz) + Eval (vfzw); when hfvj => return 2; when ctqb => return Eval (tsft) * Eval (lrgv); when nqlh => return Eval (zdfg) * Eval (sdhj); when nhnp => return 13; when tcjb => return 12; when mnhc => return Eval (szlh) * Eval (pcvv); when jnnp => return 3; when zbqq => return Eval (mtdh) * Eval (frst); when gjzv => return Eval (brst) * Eval (twjq); when shwr => return 5; when gmpl => return Eval (qlmg) / Eval (cddt); when lfpz => return Eval (mvmz) + Eval (hsmp); when tmhl => return Eval (jbsn) * Eval (fhjz); when wglc => return 14; when ppll => return 5; when ccbp => return 4; when jflm => return Eval (cclc) / Eval (rgpt); when mwms => return 2; when svwg => return 4; when qfss => return 10; when tjtl => return 7; when vwmr => return Eval (lvtv) + Eval (tvgm); when cllb => return 3; when nssr => return 3; when qcfn => return Eval (lvcn) * Eval (wjmq); when rmvq => return 2; when rbtb => return Eval (mgmw) / Eval (gvww); when jcdb => return Eval (mjmv) * Eval (zbnt); when cdpw => return Eval (ngps) * Eval (hmqr); when zdsr => return 2; when plzd => return Eval (rvnh) * Eval (sszh); when phjj => return Eval (hzcm) * Eval (bvdb); when bnmf => return Eval (jtvw) * Eval (rdfn); when twtq => return Eval (jbqf) - Eval (ztct); when qwcl => return Eval (jjvz) / Eval (tptf); when ccjf => return 13; when mrjc => return Eval (fnrh) * Eval (cstm); when thlz => return 2; when thcc => return Eval (ljtp) + Eval (ztwb); when fjcg => return 2; when flhd => return 3; when gnrj => return Eval (ppjl) * Eval (mmtj); when hnlf => return 5; when tprm => return 2; when vlhc => return 13; when tvgm => return Eval (gdmv) * Eval (dqsv); when qvpw => return Eval (gqpj) * Eval (jvtz); when vfwd => return 5; when pmwl => return Eval (lwsn) * Eval (lddq); when rzbj => return 17; when rncj => return 5; when znfq => return 2; when rjbz => return Eval (gznh) * Eval (mcht); when hhws => return Eval (vclb) + Eval (ftbq); when qfln => return 3; when ltmj => return Eval (wghf) / Eval (zjvz); when csln => return 17; when snvw => return 3; when ltgf => return 3; when wfbp => return 2; when hjlz => return Eval (qmqt) + Eval (jvgd); when zvst => return 3; when qvvc => return 8; when bjfh => return 3; when mzfn => return Eval (cdpw) * Eval (ftzm); when dqnp => return Eval (bcqm) / Eval (wjgf); when stlr => return Eval (vzgd) * Eval (gvbp); when cvfw => return 3; when rtmh => return 15; when rqss => return 3; when jddd => return Eval (dcph) + Eval (mrvr); when gggh => return 3; when gssz => return Eval (nwwb) * Eval (vmnc); when tsms => return Eval (gnzq) * Eval (rqbq); when lrcj => return 19; when pnfb => return 3; when rtjb => return 2; when zvmv => return Eval (fvhm) * Eval (gmhz); when dfrb => return Eval (fbtc) + Eval (bppp); when mcfr => return 1; when pjrt => return 1; when ltds => return Eval (wrll) * Eval (wnvf); when fvsb => return Eval (qncp) * Eval (cfbh); when nldv => return 4; when cdnm => return 3; when jwqg => return 2; when jvqz => return 1; when sqdd => return Eval (rzbj) + Eval (mqgl); when cwvl => return Eval (jszj) + Eval (rvjf); when qcnv => return Eval (nrqr) + Eval (wrmw); when fhjz => return 2; when svst => return Eval (qgtc) + Eval (snbm); when qdrc => return 17; when cfmw => return 1; when jgld => return 5; when bppp => return Eval (llhb) * Eval (qwqw); when wwqp => return Eval (vjtf) + Eval (rwmq); when cprm => return 4; when fcgs => return 7; when swfp => return Eval (tnnt) + Eval (lvhm); when frjl => return 2; when nwqz => return 1; when mldc => return 3; when mgmw => return Eval (pfvz) * Eval (hjqq); when mnrr => return Eval (vvjg) / Eval (gggh); when hvtv => return Eval (qznt) * Eval (wzfr); when tpdj => return 9; when znlh => return 4; when qbgj => return Eval (mhzn) + Eval (nmts); when cnhr => return 3; when djgh => return Eval (bdqg) + Eval (nzdz); when lccp => return 3; when frrn => return 3; when bbjs => return 7; when gdpg => return 8; when pnwv => return Eval (lhvt) * Eval (ggnd); when vhtl => return Eval (snff) * Eval (vldc); when vjwz => return 2; when qwqq => return 2; when rdnj => return Eval (smwv) + Eval (dcbt); when nltq => return Eval (cbqn) - Eval (lrzn); when fpvs => return Eval (jvsz) / Eval (fzdg); when shcg => return Eval (qpqs) - Eval (snhd); when stzl => return Eval (rwzt) + Eval (mnzz); when rfcv => return Eval (qwnz) * Eval (mfql); when snhd => return Eval (jtrg) * Eval (sqdd); when gjmt => return 3; when btzg => return 5; when vfrh => return 9; when lpjr => return Eval (bvvl) + Eval (rmvt); when nzbz => return Eval (dqnh) * Eval (hplt); when dhpp => return 2; when hvsd => return 3; when ldtj => return 2; when chlt => return 4; when rhtv => return Eval (fzml) * Eval (jnzr); when wpgm => return 5; when csfh => return 2; when mhzn => return Eval (zglw) * Eval (slpm); when wtbs => return Eval (ltdq) * Eval (vhzf); when cpqv => return 15; when dngq => return 2; when vszd => return 12; when pgvq => return Eval (ptvh) * Eval (hgwm); when smnv => return 3; when zrfw => return 7; when jbvq => return 7; when rmqt => return Eval (gcmv) / Eval (vlgn); when pfvz => return 2; when fmvw => return Eval (qnbn) * Eval (jpcd); when jqhr => return 4; when szwj => return 3; when tqfr => return Eval (mrmm) + Eval (bcnd); when rmvt => return 3; when qllm => return 3; when gcmz => return Eval (zrnr) * Eval (vffj); when sqcb => return Eval (sfmn) + Eval (hvtv); when chvn => return 3; when fzvh => return Eval (ztrt) * Eval (nbpq); when sbtd => return 3; when hnst => return Eval (wvfb) + Eval (zphs); when ljtp => return 16; when lqml => return 4; when dpqz => return 3; when pwgj => return Eval (flrw) * Eval (cbfh); when qvbn => return 2; when ppsl => return Eval (dlws) + Eval (bjwg); when jfmb => return Eval (jbtg) * Eval (cwhc); when bzqw => return 2; when nhcr => return 3; when llnl => return 3; when fzwr => return 5; when mfst => return Eval (cdtq) / Eval (qfsz); when flhf => return 3; when whbb => return 8; when rllb => return 3; when rfcm => return Eval (rsqz) * Eval (ztdn); when lqft => return Eval (tcgm) * Eval (nzbz); when snmq => return Eval (jwqg) + Eval (zdnh); when fwmw => return Eval (jfqs) + Eval (sgjm); when ngfs => return Eval (ccbp) * Eval (dphz); when mqfd => return Eval (lpzb) / Eval (ftzc); when lflj => return Eval (vtdp) * Eval (cjhz); when vzcr => return Eval (jmqh) + Eval (zbbf); end case; end Eval; begin return Eval (root); end Compute; end AoC_2022_21_Pkg; ================================================ FILE: exm/aoc/2022/aoc_2022_21_pkg.ads ================================================ with AoC_Toolbox; with Interfaces; package AoC_2022_21_Pkg is use AoC_Toolbox, Interfaces; type Monkey_Mini is (root_m, dbpl, cczh, zczc, ptdq, dvpt, lfqf, humn_m, ljgn, sjmn, sllz, pppw, lgvd, drzm, hmdt); function Compute_Mini (part : Part_Type; human : Integer_64) return Integer_64; type Monkey is (rmmz, vdjz, rqbd, zvqw, sshm, dtzl, gnzq, zlpv, nqgr, tftg, fhjc, fwbm, wtlq, nzhf, nqpq, jqzv, crrj, glpw, cnbg, bdcm, bcww, wrbf, hpvb, qffb, mfmc, cnzj, wbnh, swds, twtb, dlgc, bvzn, gwpm, rtnf, sdmb, mtjq, dpmg, drct, zrpj, gwlm, msdr, fqbl, zwqw, lbvn, dggg, bjwg, bnzl, qtmp, llpf, zwqn, trpt, lzgm, swhh, tpnf, rgrp, zswl, gzbv, ppfs, nfhf, pgrc, jjwr, fvsf, qmvq, twjq, twsj, mwrc, sbpb, cbjq, mgsl, vzgd, qrll, slpm, rffd, jjbm, pjds, btfl, sfcv, vtnq, fzdp, cwjp, mpnj, wnbb, nfgv, pszs, chpt, bhpw, dfps, pzqv, fjzz, ffqr, bqvg, qlmg, lfhb, pqqj, qhtv, wchl, vcwt, nfbp, bbcn, smld, mvmj, mqph, brmz, ttdb, bcsc, frjj, jcjf, pmfh, drrf, lmht, sstg, swhz, rtpz, qrzq, rtmt, pmds, vfzw, smhv, vdzv, btqb, wclq, vzrz, ztct, zvvd, mfrc, sdrn, jfvq, qjrs, tnnt, fqlp, nwhm, rlcw, rwjc, tfqh, crqg, nrps, pmng, gmzt, fhdz, fwzf, tzls, pvtb, gpdf, zcgs, clbn, wghf, vffj, gfbw, tzth, vwhb, scwp, rpbm, zdhf, fdmf, lqdf, rndt, jnzr, qpqs, tmhg, dtfz, pnvc, mfnh, vjgb, czvm, qhnd, dhfw, nqpv, rhcv, lqqh, mspl, ngps, bcmp, nlsw, mhlj, bqnn, fbqs, cnln, vjbz, vhhz, crmb, wbgs, qhvn, lsnd, hhcv, vmjn, fbtc, jgnj, jmcp, mfhg, ztdn, zttf, tjwt, lzzh, rnns, ffnn, wpvg, wjds, nnmh, jswz, qjqw, bndd, mdpg, wtwb, nbfg, nmts, nvjf, gqgh, btqt, cblz, nvpd, vldc, drhw, bpjf, dpgl, ggnd, qzpn, ttvz, qwqc, zhmb, nzdj, rrnp, mbvg, mlbw, wvfb, tzhp, zjcn, wbbf, mfsz, bfpq, vpvl, pnrv, lbgc, pbdd, jsrb, bbzt, mhdn, jpcd, ldzb, nmlg, pnpc, rbqt, dsqb, zhqg, dphz, gbzd, cldm, ftbq, rzff, tzcd, gzwh, qgnb, jzvg, qqwz, jbtg, rrgh, bvfr, mwdl, chfs, gwmr, qcml, zbhj, zshp, pvcs, sszh, jdsc, ndnm, lrlz, wpbs, bcpn, glts, qnld, hrtv, zbbf, vvbz, vvjg, lrlg, zpht, ndtz, stcv, jjrh, hsbr, wtrh, jfqs, hjgd, hgnr, brqb, ndsm, fjgh, tptf, njcj, jjvz, grww, jvqf, sgvm, zscd, mgjl, bfgp, mpst, wjzd, wqdj, csdf, cgwj, rccr, vsgw, pvwn, mfql, dspn, llcn, dcph, npcs, wgvj, bblh, dmrn, qbzv, lrdn, wzfr, bwnc, dswn, bnws, cdnp, fddw, nbbd, lbzc, sntb, vzts, jvfw, mqcv, jhzw, lhpf, znjr, wrvl, cdwt, vtjg, dvnh, pcgq, nhjt, pmqh, zrwb, zphs, nmvn, sbvl, bcdf, jhwn, ftjv, ncnm, bgwj, hrbr, qljb, vdsz, nhpf, gvfn, ppts, fvhm, rrqr, lnqm, qwnz, cgvr, lvrc, vcfm, zhgt, nvdh, llfg, wjgf, nztj, shpt, gzmv, tqzv, pdmb, fpcs, mwmp, hcfs, bshp, gppj, pzpp, ltnz, wzdj, frst, scdn, fpsh, gzwm, jmbs, rqsw, bnvg, tfwb, snwm, zvrq, vnpq, cfbh, ntnh, jnwv, npvl, tpwq, flhs, pnvd, zvvp, fcql, jrvp, wbvt, vwht, pzvr, qncp, bcgz, dcbt, csgr, rsdv, fnqf, hzrc, cdvw, bsvc, tlwr, hjmr, spjg, mqgl, mzzd, dqnv, lqcm, sqzp, drvt, ghvn, hfbh, wtlg, dsgt, vvzh, sclr, jqqs, zprq, dczh, lpzb, dqsv, hgzs, vrpp, snbm, tdrq, tbwl, jdmt, fzgj, vnvr, mcht, ztrt, bncr, nqsl, cclc, ztpd, lfrb, pvfv, swpl, csnf, ptdz, nvhn, rdhg, jclb, cscm, fcgj, hgwm, rqbq, wjtc, dpvl, nwdv, zcgn, jvrt, zmdq, rtsd, nqzz, dshq, mddc, rpwz, pmlg, blmp, hqbb, chtt, cchg, bntz, gvgp, vvhm, nlcv, rwcd, rfcq, zgdb, mggl, mwjg, rbbh, mqlt, ddtd, hpmm, cjlm, cpdf, gqrp, zmtg, vwdl, ggpn, mtfr, nsfm, cftm, wcdm, jcch, zqjp, wjmq, cbgj, jmnj, tlnz, fqjd, ngzp, trdj, qrch, hmrz, rvnh, humn, jstb, vqlt, vlqd, vjjw, mnlp, jtcf, lwlc, jdgq, vznc, dcfw, fqwz, hhbn, wrpp, mmnw, rdpb, hcsc, nfvj, qznt, flvw, wphq, bpwd, cbfh, bcbw, dvwj, tnbt, qlzt, rjfh, cprt, qgwg, zpbt, drln, jdcd, jzcd, sbpp, ttwm, rdbs, pfpt, rfbw, bqld, rrmg, rbsf, mlgj, jfcd, sjrh, djjd, jhgd, nlts, ppwc, gptt, bvvl, ssnq, gmhz, nnsc, zbzf, jhvm, mrrt, pmrt, rddj, wszm, pbgr, hzlh, qnbn, hrcp, dnwd, rvlz, stcr, ptvh, vmnc, bmwf, jzdn, djrh, lwlb, bqht, brfj, rlqm, mdht, lbbj, blnq, chfz, sqsc, mwrt, nvrb, lgrj, pvcn, fbgc, mqnl, bdtp, wdwf, hhjc, jzlv, smwb, bhvg, zmmd, mdld, qlqt, dgbr, rwsm, jnll, dbht, bhmz, mrlq, fzdg, jbsh, svzv, zjmw, tcgm, nzcv, rmrj, bjnj, qsml, mfts, ffqs, dbcw, wpcs, rvhs, qmcb, hlms, vwpq, wslz, jpvr, hcdz, svvq, lgpg, mlwr, hbqm, fgbm, cjlh, tlmq, zzqd, drdl, sdjb, ntmt, rwth, jjgt, mpvz, qbmm, zdrh, trft, dqjz, gfrq, vvgt, tsft, gzpf, tfpw, cddt, rlbp, ndph, blbc, cvhn, zncl, rthb, jfld, gdgd, lrsc, gzgm, bhrb, bsmm, qnds, bhzq, vwvc, qmgt, gfml, tjqj, vlmc, qlnr, fvph, jgzl, wnjc, ffbb, hzmn, rpbj, sqmd, ndcd, mmbs, mhbr, nsqq, wgvv, rvmp, dwnz, jvtz, nzzv, cqcg, nrvw, qqtm, fvng, phrv, tlzh, twjs, lhgv, rctr, snlb, dfgh, tvtj, flcb, nqpr, jmbp, rcmc, mnpl, twcj, nlth, drrq, fszd, mlrz, jvgd, jtvw, ftvm, cgcz, dfzw, tdhw, qwnt, mspb, fhmz, dqzt, brfc, hstj, rzjm, jbcl, zhpq, hmrs, mtdh, lwhp, wnvf, qqdn, wrmw, gzrs, nzwc, wflc, gtwp, trbs, zsns, vvvb, cstb, gcmv, vrjj, rrll, wgsb, scdt, wqqv, szhq, tqzf, wpqd, vmzc, pjlz, mdjm, qgjf, qnhq, hfbg, jfsr, nfhw, cstm, ghvl, tzcl, pzzg, cdqv, wcpr, jdrg, gtqh, hlmn, hnqc, sphc, bnlr, dbfd, hpzh, ghqp, dfql, hbzt, chsm, lpjq, plfd, vbvt, rdpg, vhds, rmfv, smft, wlpd, cvvw, bsqn, svcp, qflq, bwwc, wqfg, lbqn, zbhw, jlnf, nlst, zfjw, wfms, fjps, djpm, snsc, hnlj, pvfm, cwhc, blgg, jmwl, wbsb, jwwv, jdsd, rsnp, rrnt, nfnw, mpfm, mnzz, lfjp, qvfg, mjmv, lclg, pcvv, wsml, gvbp, mpjj, vcqw, lhvt, qpdv, mrlc, bdmw, vntv, cfdl, gvww, dqhh, mtnb, wlfp, zslv, lqrr, qfzb, ltzm, qcnn, bhvr, wnzr, zglw, svdw, pfml, zpqd, fjnh, rhqj, szmm, ztwb, npnf, wltv, bwff, slnh, ppwz, hgls, dbvt, wrst, rzzg, prbr, bvdb, jlmb, rbpq, jwjj, dhts, dcpm, qvpv, bbhp, sjfs, wqpv, sdhj, wfbz, mdnp, ctjq, mbqs, wcfp, ftzm, nwbt, bmsf, cmnt, wqfz, jrgs, gmzh, pnvs, gcvn, qbvr, phbh, shtz, smsm, gznh, tjch, bpnt, lljf, qfsz, dgvh, lvbp, cdvv, qlzg, rwbg, snff, flrw, tdnf, nzlr, ftzc, pznf, zjvz, nvjl, qtvv, hdff, swmh, ghfr, ghtd, mfmt, pgtq, frjp, bnfz, qfqz, djmr, crcm, ngbg, sbqm, wlqd, jfrn, jbqf, zhrs, lvtv, vclb, qtgd, hqbd, qqnm, nvjh, jcgh, bgzz, slds, lwsn, bhgh, bjbr, tgvp, dbfm, msmm, llqs, qqpl, pfdc, qlvg, wzdv, glqr, vdgt, qrnj, fbrf, gvmj, nrjc, sdsl, mqvg, chvq, lrzn, crrm, pgbv, brqv, gmln, wcmz, hbhz, vrcl, hqdv, nchp, bfvd, nnhm, thpg, jpzw, vrmt, hnbn, tsbf, nbpq, csml, cnmq, qbwf, jbrp, bbzc, pgfr, fmwn, lrvc, stqc, ngzt, mdrm, mrtq, lpvs, lqfq, rnnq, jdfj, tqst, dnzc, lwld, sgjm, bfzd, dchw, rlrb, pchr, lvhm, mswh, sdgs, snfj, sdwj, qmqt, przh, qrpv, pjsp, hpmw, jhlw, ntqb, qpct, rvvn, lmcj, bvjd, fngd, fnws, frqq, ltsv, cmnv, wdqj, cjbz, rqpj, lbtn, dbgp, qbjm, ljzj, mrvr, nght, djff, jmqh, vcpt, vsqt, tfjw, hwvf, qgtf, mmtj, blgf, mvmz, svhz, wfds, pnmc, szvb, bnwj, dnvm, fwrh, cspp, lltp, smrq, rgzs, crmw, dncw, rvjf, wlmv, fqbj, fwjg, gnsc, gtwd, qdnl, pjjj, ntsl, glqw, wmzt, vjzr, ncgd, bngr, qtfp, bdqg, hzpr, tctd, jlqg, qhlj, jtvm, szcv, sfmn, lfhp, root, jbwd, zrnr, hrmz, rfjw, hpdh, jqrl, vgsm, mvgg, hcqw, cdtq, spgw, wfjn, hrtz, rzsn, fbcd, vhwz, lvcn, grdf, pdbc, qssh, wnjl, btwt, hplt, mwwr, smqg, dqcj, ptwr, mttr, pzcc, jscq, hzcm, tsjq, fsgb, plvw, tcqz, mqzp, tldn, rwmq, vnft, ztqg, fjvg, nzdz, qrgn, tbqq, tdjh, qwqw, pdbt, bnmb, lslq, twwv, rzcm, jtjd, htgm, pjss, mrwz, djqq, jmcf, hmqr, lqdc, gpzn, pgdw, mwgb, wggq, mwqc, bnfp, pwlt, hlzp, qplw, vhqz, zptr, gtbs, zwwb, hmfb, mffc, lqgr, bcqm, cbdr, bssd, dmsz, fpwz, rbmm, rvhn, hqjt, bftg, ppjl, nzbp, rwzt, zwgg, frlv, vmgn, tvrd, wfld, pnwz, ndmd, fmbj, jqcf, jqsn, wzsh, hjqq, cvqf, wrll, vtns, wsnf, qfjg, rsqz, dddm, ftmn, bcnd, qgtc, vthd, mvnc, ndpf, pwlh, cfzf, qldj, ftqd, lhml, mrmm, crnb, qpbz, qspw, jtrg, nwwb, rgpt, spcf, brqh, qfrg, ddmr, lpqs, zvqs, dfdl, vnbv, bwqm, zjpc, btbn, bpgp, jbsn, tdlw, fsrm, rjrt, wpdn, dzvg, rdfn, zrnz, djgb, pwln, vfgt, tbdh, jlwb, cshj, lzhf, hncq, nqms, lhfr, ltdq, zssf, dqld, grcv, zfbq, lmjg, lncn, qmjq, rnbs, mstm, pnwh, ccfw, tsqc, gqpj, tnfz, rhwm, bcnp, fvrg, vtgj, wwtj, slmm, mjmt, zzpd, wttp, qdfp, psfr, rlqh, mgsz, cjvp, hrjj, fjrq, qmpm, lddq, snbl, bghp, zdnh, cbqn, pbzb, rmzw, qpqb, jffq, rscq, wjzv, ngbz, hdrj, slpc, bmzw, cmtm, pwqg, dgpr, trpv, qnvn, gcqh, bdgd, dbcs, nrqv, cnvb, cvgt, tqlp, sgpj, swsv, hndh, smwv, dwdd, jszj, ncrt, rpbg, jvsz, ffvs, mnhf, hbwh, tpmp, nttr, ldbg, ntpj, lbbv, vrct, lccn, nrsd, fvzw, vgjq, dptm, ggbp, qdrg, hcpf, zrbc, tpjw, jnqv, fzrd, cbjl, bnjt, czpd, fjld, sbwd, rqfq, pwpn, ztzq, ltqr, nlgg, ltsl, zgzs, mqrm, fhtw, zdfg, dzwg, czst, ncsp, bsnq, sflt, vsmt, vszg, tqfz, fhzm, wgcm, zsvh, hjfj, pqsr, lrbp, twdf, jdbp, smdh, cjhz, psfp, cqmq, nvlv, lrqh, wqlh, qrsg, zzcv, sgzh, vrbh, drlt, shrh, qrln, hslj, mtsv, hmfd, grcn, fctt, lhmd, rtgr, zmvz, jdjq, vhzf, fmvc, dzlc, fbjn, ppcl, jjjj, wfnm, dflc, ffnt, zbnt, dqnh, slww, djjs, sqml, lghm, bsbd, gwhs, zqpw, drgv, rswn, gnjq, sjcd, fzml, mthn, cgnr, ldbp, lqrf, gjbv, ljnf, hjmp, mrnr, zspm, qlvz, tfdv, vtvn, qlmw, hsmp, wcfj, brst, fnrh, qhzd, mmps, lpfz, bjcs, tbqc, qhwm, hzvm, nqhg, bzdh, gbtc, wfnl, ndlf, nmlt, nhfw, rtbm, fbpz, rjtc, vspf, dhqh, ddln, lbzn, vhrn, cgcc, cgvs, jqtj, wqnp, dmtd, rlvd, cvvv, rjdp, hmvq, vjtf, gbgs, wgbc, vdbp, vtdp, cgvv, vfhg, pcwz, zngg, scrz, tvrz, mqzw, zfmv, gdmv, cgnv, qlvw, fjzn, vzgb, dsng, pbvh, qbqm, vwdt, lhsw, hzjj, jplv, zmlh, zwbh, mhnm, wmdp, pbhg, qmzt, dlws, rbzl, tpjp, vlgn, phwc, bcng, cvnr, bmlj, llhb, nbcb, ffmp, nnzp, szlh, gztl, mtwg, mpws, fqgl, qqpt, bqtp, nttd, svvh, drnb, ptnv, wtnp, ndgh, lrgv, nrqr, hfvj, ctqb, nqlh, nhnp, tcjb, mnhc, jnnp, zbqq, gjzv, shwr, gmpl, lfpz, tmhl, wglc, ppll, ccbp, jflm, mwms, svwg, qfss, tjtl, vwmr, cllb, nssr, qcfn, rmvq, rbtb, jcdb, cdpw, zdsr, plzd, phjj, bnmf, twtq, qwcl, ccjf, mrjc, thlz, thcc, fjcg, flhd, gnrj, hnlf, tprm, vlhc, tvgm, qvpw, vfwd, pmwl, rzbj, rncj, znfq, rjbz, hhws, qfln, ltmj, csln, snvw, ltgf, wfbp, hjlz, zvst, qvvc, bjfh, mzfn, dqnp, stlr, cvfw, rtmh, rqss, jddd, gggh, gssz, tsms, lrcj, pnfb, rtjb, zvmv, dfrb, mcfr, pjrt, ltds, fvsb, nldv, cdnm, jwqg, jvqz, sqdd, cwvl, qcnv, fhjz, svst, qdrc, cfmw, jgld, bppp, wwqp, cprm, fcgs, swfp, frjl, nwqz, mldc, mgmw, mnrr, hvtv, tpdj, znlh, qbgj, cnhr, djgh, lccp, frrn, bbjs, gdpg, pnwv, vhtl, vjwz, qwqq, rdnj, nltq, fpvs, shcg, stzl, rfcv, snhd, gjmt, btzg, vfrh, lpjr, nzbz, dhpp, hvsd, ldtj, chlt, rhtv, wpgm, csfh, mhzn, wtbs, cpqv, dngq, vszd, pgvq, smnv, zrfw, jbvq, rmqt, pfvz, fmvw, jqhr, szwj, tqfr, rmvt, qllm, gcmz, sqcb, chvn, fzvh, sbtd, hnst, ljtp, lqml, dpqz, pwgj, qvbn, ppsl, jfmb, bzqw, nhcr, llnl, fzwr, mfst, flhf, whbb, rllb, rfcm, lqft, snmq, fwmw, ngfs, mqfd, lflj, vzcr); function Compute (part : Part_Type; human : Integer_64) return Integer_64; end AoC_2022_21_Pkg; ================================================ FILE: exm/aoc/2022/aoc_2022_21_questions.txt ================================================ --- Day 21: Monkey Math --- The monkeys are back! You're worried they're going to try to steal your stuff again, but it seems like they're just holding their ground and making various monkey noises at you. Eventually, one of the elephants realizes you don't speak monkey and comes over to interpret. As it turns out, they overheard you talking about trying to find the grove; they can show you a shortcut if you answer their riddle. Each monkey is given a job: either to yell a specific number or to yell the result of a math operation. All of the number-yelling monkeys know their number from the start; however, the math operation monkeys need to wait for two other monkeys to yell a number, and those two other monkeys might also be waiting on other monkeys. Your job is to work out the number the monkey named root will yell before the monkeys figure it out themselves. For example: root: pppw + sjmn dbpl: 5 cczh: sllz + lgvd zczc: 2 ptdq: humn - dvpt dvpt: 3 lfqf: 4 humn: 5 ljgn: 2 sjmn: drzm * dbpl sllz: 4 pppw: cczh / lfqf lgvd: ljgn * ptdq drzm: hmdt - zczc hmdt: 32 Each line contains the name of a monkey, a colon, and then the job of that monkey: A lone number means the monkey's job is simply to yell that number. A job like aaaa + bbbb means the monkey waits for monkeys aaaa and bbbb to yell each of their numbers; the monkey then yells the sum of those two numbers. aaaa - bbbb means the monkey yells aaaa's number minus bbbb's number. Job aaaa * bbbb will yell aaaa's number multiplied by bbbb's number. Job aaaa / bbbb will yell aaaa's number divided by bbbb's number. So, in the above example, monkey drzm has to wait for monkeys hmdt and zczc to yell their numbers. Fortunately, both hmdt and zczc have jobs that involve simply yelling a single number, so they do this immediately: 32 and 2. Monkey drzm can then yell its number by finding 32 minus 2: 30. Then, monkey sjmn has one of its numbers (30, from monkey drzm), and already has its other number, 5, from dbpl. This allows it to yell its own number by finding 30 multiplied by 5: 150. This process continues until root yells a number: 152. However, your actual situation involves considerably more monkeys. What number will the monkey named root yell? --- Part Two --- Due to some kind of monkey-elephant-human mistranslation, you seem to have misunderstood a few key details about the riddle. First, you got the wrong job for the monkey named root; specifically, you got the wrong math operation. The correct operation for monkey root should be =, which means that it still listens for two numbers (from the same two monkeys as before), but now checks that the two numbers match. Second, you got the wrong monkey for the job starting with humn:. It isn't a monkey - it's you. Actually, you got the job wrong, too: you need to figure out what number you need to yell so that root's equality check passes. (The number that appears after humn: in your input is now irrelevant.) In the above example, the number you need to yell to pass root's equality test is 301. (This causes root to get the same number, 150, from both of its monkeys.) What number do you yell to pass root's equality test? ================================================ FILE: exm/aoc/2022/aoc_2022_22.adb ================================================ -- Solution to Advent of Code 2022, Day 22 ------------------------------------------- -- Monkey Map -- -- https://adventofcode.com/2022/day/22 -- Copy of questions in: aoc_2022_22_questions.txt -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; procedure AoC_2022_22 is use AoC_Toolbox, HAT; subtype Range_x is Integer range 1 .. 150; subtype Range_y is Integer range 1 .. 200; map : array (Range_x, Range_y) of Character; lowest, highest : Point; procedure Adapt_Highest_Value_Point (using : Point) is begin highest.x := Max (highest.x, using.x); highest.y := Max (highest.y, using.y); end Adapt_Highest_Value_Point; procedure Show is begin for y in lowest.y .. highest.y loop for x in lowest.x .. highest.x loop Put (map (x, y)); end loop; Put_Line ('|'); end loop; end Show; procedure Clear is begin for y in Range_y loop for x in Range_x loop map (x, y) := ' '; end loop; end loop; end Clear; cube_side : array (Data_Type) of Positive; function Locate_Cube_Face (p : Point; data : Data_Type) return Natural is q : Point; side : constant Positive := cube_side (data); begin q.x := (p.x - 1) / side; q.y := (p.y - 1) / side; case data is when mini => case q.x is when 0 => return 2; when 1 => return 3; when 2 => case q.y is when 0 => return 1; when 1 => return 4; when 2 => return 5; when others => null; end case; when 3 => return 6; when others => null; end case; when input => case q.x is when 0 => case q.y is when 2 => return 4; when 3 => return 6; when others => null; end case; when 1 => case q.y is when 0 => return 1; when 1 => return 3; when 2 => return 5; when others => null; end case; when 2 => return 2; when others => null; end case; end case; Put ("Locate_Cube_Face issue"); return 0; end Locate_Cube_Face; subtype Cube_Face_ID is Integer range 1 .. 6; procedure Blocks_to_Origin (bo : out Point; face_id : Cube_Face_ID; data : Data_Type) is begin case data is when mini => case face_id is when 1 => bo.x := 2; bo.y := 0; when 2 => bo.x := 0; bo.y := 1; when 3 => bo.x := 1; bo.y := 1; when 4 => bo.x := 2; bo.y := 1; when 5 => bo.x := 2; bo.y := 2; when 6 => bo.x := 3; bo.y := 2; end case; when input => case face_id is when 1 => bo.x := 1; bo.y := 0; when 2 => bo.x := 2; bo.y := 0; when 3 => bo.x := 1; bo.y := 1; when 4 => bo.x := 0; bo.y := 2; when 5 => bo.x := 1; bo.y := 2; when 6 => bo.x := 0; bo.y := 3; end case; end case; end Blocks_to_Origin; procedure Relative_to_Face (p : in out Point; face_id : Cube_Face_ID; data : Data_Type; way : Integer) is side_length : constant Positive := cube_side (data); bo : Point; begin Blocks_to_Origin (bo, face_id, data); p.x := p.x - way * bo.x * side_length; p.y := p.y - way * bo.y * side_length; end Relative_to_Face; procedure Relative_to_current_Face (p : in out Point; data : Data_Type) is begin Relative_to_Face (p, Locate_Cube_Face (p, data), data, 1); end Relative_to_current_Face; verbosity_level : constant Natural := 0; procedure Run (part : Part_Type; data : Data_Type; path : VString; start : Point; d, final : out Point) is dxr, dyr : Real; walking_steps : Integer; c, co : Character; p, left, right, up, down : Point; side_length : constant Positive := cube_side (data); function Inv (coord : Positive) return Positive is begin return 1 + side_length - coord; end Inv; procedure Go is new_face : Natural := 0; rp, np, nd : Point; procedure From_Left (set_new_face : Positive) is begin new_face := set_new_face; np.x := 1; nd := right; end From_Left; procedure From_Right (set_new_face : Positive) is begin new_face := set_new_face; np.x := side_length; nd := left; end From_Right; procedure From_Top (set_new_face : Positive) is begin new_face := set_new_face; np.y := 1; nd := down; end From_Top; procedure From_Bottom (set_new_face : Positive) is begin new_face := set_new_face; np.y := side_length; nd := up; end From_Bottom; procedure Wrap_around_through_Left_Side is begin for x in reverse Range_x loop if map (x, np.y) /= ' ' then np.x := x; exit; end if; end loop; end Wrap_around_through_Left_Side; procedure Wrap_around_through_Right_Side is begin for x in Range_x loop if map (x, np.y) /= ' ' then np.x := x; exit; end if; end loop; end Wrap_around_through_Right_Side; procedure Wrap_around_through_Top_Side is begin for y in reverse Range_y loop if map (np.x, y) /= ' ' then np.y := y; exit; end if; end loop; end Wrap_around_through_Top_Side; procedure Wrap_around_through_Bottom_Side is begin for y in Range_y loop if map (np.x, y) /= ' ' then np.y := y; exit; end if; end loop; end Wrap_around_through_Bottom_Side; procedure Cube_Crawl_through_Left_Side is begin rp := p; -- Point relative to current face. Relative_to_current_Face (rp, data); case data is when mini => case Locate_Cube_Face (p, data) is when 1 => From_Top (3); np.x := rp.y; when 2 => From_Bottom (6); np.x := Inv (rp.y); when 5 => From_Bottom (3); np.x := Inv (rp.y); when others => null; end case; when input => case Locate_Cube_Face (p, data) is when 1 => From_Left (4); np.y := Inv (rp.y); when 3 => From_Top (4); np.x := rp.y; when 4 => From_Left (1); np.y := Inv (rp.y); when 6 => From_Top (1); np.x := rp.y; when others => null; end case; end case; Relative_to_Face (np, new_face, data, -1); end Cube_Crawl_through_Left_Side; procedure Cube_Crawl_through_Right_Side is begin rp := p; -- Point relative to current face. Relative_to_current_Face (rp, data); case data is when mini => case Locate_Cube_Face (p, data) is when 1 => From_Right (6); np.y := Inv (rp.y); when 4 => From_Top (6); np.x := Inv (rp.y); when 6 => From_Right (1); np.y := Inv (rp.y); when others => null; end case; when input => case Locate_Cube_Face (p, data) is when 2 => From_Right (5); np.y := Inv (rp.y); when 3 => From_Bottom (2); np.x := rp.y; when 5 => From_Right (2); np.y := Inv (rp.y); when 6 => From_Bottom (5); np.x := rp.y; when others => null; end case; end case; Relative_to_Face (np, new_face, data, -1); end Cube_Crawl_through_Right_Side; procedure Cube_Crawl_through_Top_Side is begin rp := p; -- Point relative to current face. Relative_to_current_Face (rp, data); case data is when mini => case Locate_Cube_Face (p, data) is when 2 => From_Top (1); np.x := Inv (rp.x); when 3 => From_Left (1); np.y := rp.x; when 1 => From_Top (2); np.x := Inv (rp.x); when 6 => From_Right (4); np.y := Inv (rp.x); when others => null; end case; when input => case Locate_Cube_Face (p, data) is when 1 => From_Left (6); np.y := rp.x; when 2 => From_Bottom (6); np.x := rp.x; when 4 => From_Left (3); np.y := rp.x; when others => null; end case; end case; Relative_to_Face (np, new_face, data, -1); end Cube_Crawl_through_Top_Side; procedure Cube_Crawl_through_Bottom_Side is begin rp := p; -- Point relative to current face. Relative_to_current_Face (rp, data); case data is when mini => case Locate_Cube_Face (p, data) is when 2 => From_Bottom (5); np.x := Inv (rp.x); when 3 => From_Left (5); np.y := Inv (rp.x); when 5 => From_Bottom (2); np.x := Inv (rp.x); when 6 => From_Left (2); np.y := Inv (rp.x); when others => null; end case; when input => case Locate_Cube_Face (p, data) is when 6 => From_Top (2); np.x := rp.x; when 5 => From_Right (6); np.y := rp.x; when 2 => From_Right (3); np.y := rp.x; when others => null; end case; end case; Relative_to_Face (np, new_face, data, -1); end Cube_Crawl_through_Bottom_Side; begin if walking_steps = 0 then return; end if; if verbosity_level > 0 then Put (p.x, 3); Put (","); Put (p.y, 3); Put (" -> ("); Put (walking_steps, 0); Put (") -> "); end if; d.x := +Integer (dxr); d.y := -Integer (dyr); -- top down geometry... loop if verbosity_level > 0 then Put ('.'); end if; nd := d; np.x := p.x + d.x; np.y := p.y + d.y; if d.x < 0 then if np.x < 1 or else map (np.x, np.y) = ' ' then case part is when part_1 => Wrap_around_through_Left_Side; when part_2 => Cube_Crawl_through_Left_Side; end case; end if; end if; if d.x > 0 then if np.x > highest.x or else map (np.x, np.y) = ' ' then case part is when part_1 => Wrap_around_through_Right_Side; when part_2 => Cube_Crawl_through_Right_Side; end case; end if; end if; if d.y < 0 then if np.y < 1 or else map (np.x, np.y) = ' ' then case part is when part_1 => Wrap_around_through_Top_Side; when part_2 => Cube_Crawl_through_Top_Side; end case; end if; end if; if d.y > 0 then if np.y > highest.y or else map (np.x, np.y) = ' ' then case part is when part_1 => Wrap_around_through_Bottom_Side; when part_2 => Cube_Crawl_through_Bottom_Side; end case; end if; end if; -- Check new point if map (np.x, np.y) = '.' then p := np; d := nd; else exit; end if; walking_steps := walking_steps - 1; exit when walking_steps = 0; end loop; dxr := Real (+d.x); dyr := Real (-d.y); if verbosity_level > 0 then Put (p.x, 3); Put (","); Put (p.y, 3); New_Line; end if; end Go; begin p := start; dxr := 1.0; dyr := 0.0; left.x := -1; left.y := 0; right.x := +1; right.y := 0; up.x := 0; up.y := -1; down.x := 0; down.y := +1; if verbosity_level > 1 then Put_Line (+"highest.x: " & highest.x'Image); Put_Line (+"highest.y: " & highest.y'Image); Put_Line (+"side: " & side_length'Image); end if; walking_steps := 0; c := ' '; for pos in 1 .. Length (path) loop co := c; c := Element (path, pos); case c is when '0' .. '9' => if co in '0' .. '9' then walking_steps := walking_steps * 10 + Ord (c) - Ord ('0'); else walking_steps := Ord (c) - Ord ('0'); end if; when 'L' => Go; Rotate (dxr, dyr, Pi * 0.5); when 'R' => Go; Rotate (dxr, dyr, -Pi * 0.5); when others => null; end case; end loop; Go; final := p; end Run; data_line : VString; procedure Data_Acquisition (data : Data_Type; start : out Point) is c : Character; f : File_Type; p : Point; begin lowest.x := 1; lowest.y := 1; highest.x := 1; highest.y := 0; start.x := 0; start.y := 1; Clear; case data is when mini => Open (f, "mini.txt"); when input => Open (f, "aoc_2022_22.txt"); end case; Read_Data : while not End_Of_File (f) loop Get_Line (f, data_line); exit Read_Data when data_line = ""; p.y := highest.y + 1; for x in 1 .. Length (data_line) loop c := Element (data_line, x); if start.x = 0 and then c /= ' ' then start.x := x; end if; p.x := x; map (p.x, p.y) := c; end loop; Adapt_Highest_Value_Point (p); end loop Read_Data; Get_Line (f, data_line); if verbosity_level > 0 then Show; end if; Close (f); end Data_Acquisition; T0 : constant Time := Clock; r : array (Part_Type) of Integer; data : constant Data_Type := input; start, dir, final : Point; facing : Natural; begin cube_side (mini) := 4; cube_side (input) := 50; Data_Acquisition (data, start); Parts : for part in Part_Type loop if verbosity_level > 0 then Put_Line (part'Image); end if; Run (part, data, data_line, start, dir, final); if dir.x > 0 then facing := 0; end if; if dir.y > 0 then facing := 1; end if; if dir.x < 0 then facing := 2; end if; if dir.y < 0 then facing := 3; end if; r (part) := 1000 * final.y + 4 * final.x + facing; if verbosity_level > 0 then Put_Line (r (part)'Image); end if; end loop Parts; if Argument_Count >= 2 then -- Compiler test mode. if r (part_1) /= Integer'Value (To_String (Argument (1))) or r (part_2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Final password after a walk; edges are..."); Put_Line (+" (part 1) wrapped around . . . . :" & r (part_1)'Image); Put_Line (+" (part 2) on a cube's surface . :" & r (part_2)'Image); -- Part 1: validated by AoC: 26558 -- Part 2: validated by AoC: 110400 end if; end AoC_2022_22; ================================================ FILE: exm/aoc/2022/aoc_2022_22.txt ================================================ ...###..#...##................#......#....#........#.....#..#.......#...#.......#.......#..#........ ..........##.........#.#.........#...#....#....#...........#...............#...................#.... ..........................#.#..............##......#.........#.#......##......#.#................... ...................#...........#........#.#....#.................................................... ....#................#..................#.....#....#...........#......#..#..#.........#......#...... ......................##..#.....................#..##...#..........#.......#.#...#.......#..#......# ........#.....#..............#........................#........#......#...#...............#......... #............#..#............#....#....#...#...#.......#........................#................... .............#.##....#...#..#..#...........#.....#...#..............#.#.#..#........................ ..........#........................#.................#..#.....#.......##..#......................... .#.##....#..#............##.................................##.............................##....... ...###....#...#....#.........#.#.....#.........#..#........#..........#........#....#....#......#... .##...................#....................#.............##....#............##.......#..#........... ...............#.......................#........#.................#..##...........#.......#........# .....#..............................#..................##.#.............#..................#...#.... ....#....................................#.......................#...#.....#........#............... ..............#.......................#...........#..............#...............#..#..#....#....... ......#.................##...........#...........#........#............#...#.#..............#..#...# ..............#...#...............#......#.......#...............#..............#...............#... ..........##................#...#..#.......#......#...................#..#...........#............#. ............................#.........#.....#....#.....#.....#......#..#...#.....#...#.......#...... ...##.................#...#....#.#.......#.....................#......#...##..................#..... .#......#...#..............................................#.........#..................#........... ...........................#.#.#.................#.....#.............#.......#..##.................. .............#.......#.............#......#..............#.#...............#........................ ...................#...#...#....#.....#....................#.......#.............#........#......... ......#....#....#........#...........#..................#....#..........................##....#....# .........##..##.#.#......#.#.....#.....................#.#.#..........#....##................#..#... ...#...#.........#..........##.#.............##.#.....#...............#........#.................... .................................#..#...............#.......................#...................#... ..#.......#...#.......#.....#.........................#.#....#..#...........##..#................... ...#...#..............#.......#...#..................#........#...................#...............#. ....#..#....##..#....#....#...........................#............................................. ...#...#.......................#..#...#..#..#................#........#............................. ..........#.......................##...................#.................#......................##.. ....#.#........#....#..#....#........#......#.....#...........................#...............#....# ...................#..................................#........................#.................... ..........#.#...#.............##.........................#........#...................#............. .................#.......................................................#.............#............ ...#..#...#....#..................#..................#.........................#................#.#. ..#..#.........................................................................................#...# .....##.............................#....#.....#.......#.......#.#..............#............#...... .#..........#.....#.......#........#....#..............#................##.......................... ..........#...##...........#.........................#...........#............#.....#.#.#........#.. ........##.#.................#..#...................#...........##..#.......................#....... ..#.............#...#...#...........#.....#..................#..........#......................#.... ..#................###..................#..............#.....................#......#............#.. ...........#.........#.....#.#.#.#................#.............#.#.................#.....#....#.... .......#............#.......#......##.....#.......#.....#.###...............#......#.#.............. .........#.....#.......#....#........#.......##....#................................#............... ..............##..#...#.#.....................#... ............##.........#.......................... ..#.........#......###..#........#...#............ ...##.#......#.................................... .................#....#.#....#............#.#....# .##........#...#........#..........#.............# ................#..#.......#.......#.....#........ ...##........#...#.#............#....#...........# ............#...#...............#.#.......#....... .##............................................... ..........###..................#..#.#....#...#.... ......#...........#....#..#..#........#........... ....#.....#...#..#.#..#................#.......... ........#...#......#...................#.#......#. .#....#......................#..#...#.........#... ..............#............#..............#....#.. ...................#...........#.#........#.#.#... ............#.................##.................. ..#..........................#.#...#.......#..#... ..#.....#.........#.........#..#...#......#....... .........#..........#.#.....#......#...........#.. .....#...........#.#........#......#.......#....#. .#.........##...#...#......#.......#.............# .........................##......#.....#........#. ...#......#.#......#.............................. .........#...........#...........#...#............ ##.............#..................#.#............. #.......................#.#.....#........#........ .....#...........#....................#..........# ........#.#..........#...................#........ ......#.......#..........#...................#..#. #....#................#............#...........#.. ..#...##.#..............................#......... ......##.....#.............#................#..... ....#.....#..............#......#..#..#.#........# #.........#...............##....#.#........#...... ....................#.......................#..... .....................................##........... ........................#......................... ..##....#.......#................#.#..........#... .......#.............#.............#....#...#.#... ....#.#......#.......##.#....#........#........... ..#.....#..#.#.................................... ...........................#.....#......#......#.. .........#.....#........#........................# .......#....#........#...#............#.#......... ...#...#..............#...#...............##...... ..#.......................................#....... .................................................. .........................#..#.............#....... ....#.....#....#......##........#......#..............#.........#........#..............#....#...... ...............##...##..............#......................#................................#....... ......................................#..........#..#.#...#......#..................#............... ....#......................#........................#.............#.......#...............#..#...... ..............................#....###.............#............................##...............#.. ...........................#...#...................#......#......#...........#...............#....#. ..........##............#................#....#................#.......#..........#....#............ #.........#.......#..............#.............#....#.#...#................#.#.....................# ...#...............#...............#.............................#......#...#.......#......##.....#. ..............#...............#...#..........................#..........#......#.....#.............. ................#........................#.........#..........#..........#.............#....#....... ......#................#....#.....................#..#............#...#..#.....................##.#. ...........#....#.....#.....#..#..............#.........#...#...#......#.....................#...... .....#...........#...........#...#.....#.##....#..#.......#........###.#...#..#..........#.##....... ##......#.................#.#........#.............#.........#...................................... ................#....#.#...........................#...................#.#.............#.........#.. #......#......#...................#.#.#.#............#......#.................#.....#............... ##.......#..............#....................................#.....#.........#........#............. .#.....#...........#..#................#.....#..#........#........#............#.....##..#.......... .##........#......................#......#...........##............#...........................#.... ...#..................#........#..#....##.........##........#...#......##..##.......#..........#.... .......................#..............#.......#..#......#.#......#...#........#.................#... .#....#...........................#..#..............##......#.#......#................#............. ...........#.........................#.#................#..................#........................ .......#..............#..............#.....#...........#......##........#.........#...........#..... #..#.......................#.......###......#...##..................................#........#...... ...#...........#..........#..........#.....#...........................#.....#.....#........#.....#. ..................#.#........................#...#...........#...#...................#........#..... .#..........#.#....................#..#...............#.......#...#.......#...#........#..........#. ............................#.................#.#..#...........#..............#..................... .............#........#.#.#............#...............#...........#......................#......... #..........#.......#......#................#.......#.........#.#......#......................#...... .......#.#.............#...................#....#...............##......#...............#........##. #.........#........................................#...#................#..#........................ .............#.#........#.........#....#..................#.........#..#..............#.#.....##.... ...#..........#.............#...#....#.....#....................#....................#.............. .......#................#...........#.............#.#....................#........................#. ..................................#.#......#....#................................#....#............. ....#..#...#..#.#.......#...........#.................................................#....#........ #.....#..#..............#..#.....#.........#...#.....#....#......#..................#........#...... .......#.#............................................#.#......#.#..................##...#..#.....#. ........................#.........................#...............................#................. ..............#..#............................#.....#...#...............#...#...#................... .....#.#................................#..##...............#.....#.#.#..#.............#.#.......... #...........................#....#......#.....#.......#..#..#..................#.............#....#. ...#.....................................#.......................................................... ......#....................................................#....#.......#..#......................#. #............................#..........#...........................................#.##..........#. .....#...#.............#..#...............................#..............#....##.#..#.#............. ..................................#................#...#......#...................#..........#...#.. ...........#..........................#.......#... .......#...#..#........#.......................... ........#..##.##..#.............##..#...........#. ..#.#.......##..#..#.............#.............#.. ......#.....#.........#...##.#...#..#............. ............#..#.............#......#............. .........................##.............#......#.. .#..............................##................ .#.......................#................#....... ....#.#...........#............................... .............................#.........#.......... ...............#..#.#.....##...................#.. ...#..........................#.............#....# ................#.............#............##..... #.......##..#..#....................#............. .........#............#..#.....................#.. ........#...........#...#...#.............#....... ........#........#..#...#..#..#...#............... ....#....#...#.......#...........................# ......#........##....#.#.#........................ ............#....................................# ......##...................#............#.....#... .........#..#.#.#..........#..........#..........# #...........#...#..........#.##............#...... .....#..#.....#......#.....#............#......... ..........................................#....... ...........#..#............#....................#. ......#.....#.....#...#.#......................... ....#.....#....#........##...........#............ ................#.......#....#.............#...#.. ..............#..#.#.#..................#........# .............#........#.......................#... ........#......#.......#.#....#..#................ .......................#..........#.......#.#..... ......#..........#...###.......#.......#.#........ ...............#..#..#..#...#....................# ..#.........#........#.....#........#............. ...#.............#....#...........#............... .......#......#...##............................#. ....................#..##..#..#..#..............#. ......#........................................... ......#........#.......#.........#....#....#...#.. ..............#..#.#........................#..#.. .................#.........................#.#.... ............#................#.................... ..#.....................#......................... ............#..............#...................... ..................#...................#...#....... ......#.##.......#.........................#...... .........#........#...............#.....#......... 9L44R12L3L7L37L27L37R32R15R42R15L41R50R41L47R26L44R26L3L20L2L9L13L45R19L9L26L5R27L44L3R38L38L29R50R28L6R26L40L36R46L22L43L47R16L44R17L44L46L2R25R17R7L35R24L26L24L35R42R28L14R34L4L16R15L23R17R43L34R13R1R35R25R35L21L22L45R50R47R42R12L30R46R31R5R41L27L2L13L38R46L48R11L48L44R17L42L8R48L44R10L38L43L15L26L27L32R24R21R34L47L30R38L36R4L32R44L45R37R42L46R16L30R23L29L25L4L37L29R18R39L44L8R10R29R19R5L5L34L44R1L4R41L26L36R25L48R25L50R32L47L39R39R8L48R43L41L12L43L32L36L14L7R27R28R43R33L5L9R24L30R27R47R30R36R36L6L6R8R2L18R10R42R25L36L33L35R6R26L48R13L14L41L6R19R8L37R19R14L23L47L34R46L11R33L29R5R18L2R14R31R4R15L27L42R50L34L4L47R17L28R6L4R11L25R39L24R2R31R6R12L50R29R1L29R32L2L22L28L35R27R3R22L7R47R47L43R29R29L41L5R44L20L6R41L33L14L39R13R16R8R3R46R39L9R20L43L32L39R43L5R43L34L47R9L8L36L50R30L48R17L4R12L36L36L29R48R11R39R24R27L40L47R31L34R35R4R14R47L38R15R18R16L22L38L11R6R31R8R27R50L26R9L37R24R6L19R6L25R42R6L21L40L10L10L47L22R44R8R26L15R49R30L5R12L36R41R22L4R44L47L5L43L2R18L24L37L28R18R9R32R45R24L6R44R33L48L17R21R21L32R35R38L38R28L45R2L41L24L16L10L37R14R25R44R25L43L10R33L39R16R12R43L35L9L50L2R18L21L3L15R21R4R33L21R12R24L22L15L18R48R36R9R14L18R31L39R8R28L27R48R13R5R9R8R6L30L25L14L26L38L8R24L10L25R6R8R45L36R48R16R11R14R2R36R45L12L27L39R50L26L44L39R41L30R48L27R25R40L28R43R32R46R43R34L40R45L42R5L7R37L44L39L26L42R37R3R38R42R47R16L15R30R18R24R26L46R25R40R44R1R17R4L41R44R44L38L33R48R37L28L23L19R47R28R3L10R6R4R10R17L28R47R21R15R17L29R42L37L44L27R20R31R7L16R33R6R12L40L33R2L25L7L32R16L21R1R36R4L24L15R34R31L10L28R3R41L49L4L49L45R37R19L47R12R27L20L1L7R13R18L17L13L11R1R13L41R34L11R18L34R18L18R44L5L33R42L25R22L6R40R29L17R45R26R3R12R44R49L20R30L32R8R20R8R26L31L24R35L50L33L40L6L4L35L44L45R12R48R13R3L21R9R31R6L15R23L9R12R48R23R11L16R4R40R20L13R35R21L3L30L26L5L10L15L31L23L47R49R10L25L46R2R35L14R23R41L6L3R3L7L49R2L34R42L46L45L37L2L15L4R33R27R30R40R25L43L34L32R8R40L36R32R16L18R32L48R19L12R14L36L16R9R34L44L30L1R7L18L48L12L40R40R14R25R16R36L16L26R47L27L33L7L43L35R40L41L30L19L5R8L49R48R27R19R41L39L36L50L27L49L10R11L34R46L5L28L12L17L47L26L33R18R43R3L2R34R46L39L35L38R35R26R34R8R15R11L44R44L3R19L14R15R42R36L32L35R20L6L25L22L32L24L24R9L4L15R28L17R13L44L17L13L40R36R10R27L35R22L48L38L33R34L26R29L34R43L5L28R49R17L2R13L9R20L26R8L18R40R23L17L25L11L33R15L48L18R11R22L46R15L47L33R31R47R22R10R47R12L48L15R27L44L6R44R36L43R30R39R28R25R32L34R44R29R26R1R11R50R43L42L14R46R3R5L6L38L24R12R49L26L29L40R24L49R9R43L36L33R48R38R33L19L7L21R37R7L32L50R6R15R30R5L14L47L22L30L4R18L36L11L42L3L3R41L48L30L40L6R20R26L45R37L18L41R39R31L18R10R44R9R37R22L22R50R7R20R7R38L34L7R34R14R16L46R35L6R7L50L2L4L5R5R48R29L44R4R2R25R7L18R46L11R8R33L17L47R19R48R11R29L22L11R14L19L13L3L42R38R33R20L44L1R12L18L9L37R3R10L5R49L45R40L10R41L4R9R41R25L40L9L18L45L21R25R2L49L45R39R37L42R24R3L6R38R16R48R36L47L37R49R8R12R27R44R47L28L34L17L46R8L31R16L19L14R28L39R28R40R36R22L45R10L41R22L16L24R7L7R29L5L11R14R6R41R44L49R27R43R42R44R16L20L47R4L12L1R26R9R10R46L19L23R30L29R25R39R7L46R24L34L38R23R10L33L19R32R35R29L13R9L21L32L39L40R18R44L15R22L27R42R7R4R47R26L26R50R20L36L42R36R39L10L26R2R40L5L44R32R12R32R2L24R50L22L37L34L47R10L32R19L36L42L26L12R21L47R44R17L13R23R3R4L12L34L47R13L45R3L28R16R35R6L33R49R36R3R17R43L19R10L39L5L18R19R45R23R23L26L32R11L33R43R45L30R9L11R38L44L38R43L44L39R7L41R6L10R22R41R20R27L22L35L34R10L42R13R5L45R15L20R48R50L16R48L6L24L22R7R23L11R37L9L32L42R30L28L11R1R7R50R2R36L26R13R45R49R19R25R49L10L5R18L50L13R31L41L38R43R14L5R25R22R28L42L8R28L22L21L24L17L27R43L7L30R39R31R48L47L19R13R42L50R17L9L47R19L18R18L42L22R23L41R46L17R20L45R28R45L47R16R12R34R49L31R20L18L6R16R9L32L42L3L40R41R29R22R7R14R37R39R23L20L22L32R12L11L35L50R19L34R11L48L2R11L30L48L19R11R34L32R23R31L1L13R26L3R23R22R36L34R33R43L2R27R48L38R18L50L42L41L19L37R12R41L15R50R36L27R50R31R28R34L29R43R23L30R8R19L46L19R16L18R14L43L45L30R46R18R1R37R15L46L36L22R14R25L5L21L24R48L7R41L32R41R30L6R6L13R34R13R37L47L3L37R33R23R47L49L13R10L12R9L45R44L11L15R26L16L19L48R35R37L29L26L43L19L26R44R45R49R11R38R7R43R37R41L47L47R42L28L24R16R14R40R25R24L1R2L40L11R14L5R4R43L4R4L27R24R13L17L14L25L42L37L47L47L26R11L24R40R8L42R48L9R27L41R37L17R20L31L44R37R39R35R26L12L47L27L7R7L43R35L17R12R25R49L33R16L21R27L20R18R49L20L45L41L50L39R8L35L41L43R36L20R28R15L43L32L25L15R7R42L44L33R45R14R17L45R2L43L29R50L21L46R33L19R18L23R37R3L24L21R18L50R3R16R9L47L33L43R7R42R10L50R4R16R50R22R2L19L42R43L15R11R39R42L45L26L25L12R35L45R12R22R14R37R17R1R19L7R20R50R21R33R31R48L20R4L31L38L28L35L37R5R33L20L28R5R48L12L8R12R43L26R30L7R41L18L41R27L38L5R45L7R22L32L49R6R7R3L31L13R12R2R31L46R12L31L10R4R12L48L33L41R22R25L22R15R17R12L45R36R30L10L46R10R29R23L5L19R18L27L48R36L41R44L1R41R5L23R11R25R50R41R42R50L26L28R31R3L33L25L34L42R3R35R1R50R16R22L10L33R31L41L5L49R4L47R45L4L3L44R16L35L26R27R17L21L43L18R33R15R33R49L49R21R26R37R39L37L23L23R12L49R44L12R39R16L22R12R32L38R11R14R28R6L13L26R12R9L46L34L25R6R5L19L13L18R10R28L8R27L26L15L38L23R35L21R47R7R1R18L10R44L31L43L45R49R20L14R35R15R13L45R30R36L35R42L8R11L1L49L5R14L17R5L33R40L35R43L43R46R40L2R36L47L19R11R1L21L36R2R7L3R48R31R12R19R29L22R47L40R38L7R24L42L5R7R22L43L11L37R38L18R6R1L6L29R39L12L13L29R27R31R24R46L29L28L10L42L37L16L25R4L22L22R10R16L18L42R28L33L14R46R19R42L18R5L11R27L47R10R47L11R1L31L36R24L8R39R21L40L48L39R17L8L45L40L30L39R25L1L11L23L37R10R48L6L48R23L44L46R23R2R44R19R35L35L34L37R24L1R12L38R44L38L3R35L37R7R7R50R21R20R9L7R37R48L23R9L32R11R27R30R20R3R4L21L16R16R6R32R37R22L33L3L19R27L42L24L19L3L11R36R22R20L1R47R22R42L3L26R41R15L44L47L33L35R44R13R39L30R50R45R15L24R45L8R6L33L22R12L23R46R16R45L20R5R21R12L46L45R37R26L19L22R47L41R16L36L5L40L25L20L50L46L36R3L13R14L22R8L8R37R26R47L26L19L6L24R3L41R17R39L20L5L29L27R10R37L26R24L30L41R42L37R20R7L7R49L9L4L19L48R16R7R38L37R48R40R1R1L15R8L22L16R44L38L20R13R9R19L20R28R5R40L2R22R1 ================================================ FILE: exm/aoc/2022/aoc_2022_22_questions.txt ================================================ --- Day 22: Monkey Map --- The monkeys take you on a surprisingly easy trail through the jungle. They're even going in roughly the right direction according to your handheld device's Grove Positioning System. As you walk, the monkeys explain that the grove is protected by a force field. To pass through the force field, you have to enter a password; doing so involves tracing a specific path on a strangely-shaped board. At least, you're pretty sure that's what you have to do; the elephants aren't exactly fluent in monkey. The monkeys give you notes that they took when they last saw the password entered (your puzzle input). For example: ...# .#.. #... .... ...#.......# ........#... ..#....#.... ..........#. ...#.... .....#.. .#...... ......#. 10R5L5R10L4R5L5 The first half of the monkeys' notes is a map of the board. It is comprised of a set of open tiles (on which you can move, drawn .) and solid walls (tiles which you cannot enter, drawn #). The second half is a description of the path you must follow. It consists of alternating numbers and letters: A number indicates the number of tiles to move in the direction you are facing. If you run into a wall, you stop moving forward and continue with the next instruction. A letter indicates whether to turn 90 degrees clockwise (R) or counterclockwise (L). Turning happens in-place; it does not change your current tile. So, a path like 10R5 means "go forward 10 tiles, then turn clockwise 90 degrees, then go forward 5 tiles". You begin the path in the leftmost open tile of the top row of tiles. Initially, you are facing to the right (from the perspective of how the map is drawn). If a movement instruction would take you off of the map, you wrap around to the other side of the board. In other words, if your next tile is off of the board, you should instead look in the direction opposite of your current facing as far as you can until you find the opposite edge of the board, then reappear there. For example, if you are at A and facing to the right, the tile in front of you is marked B; if you are at C and facing down, the tile in front of you is marked D: ...# .#.. #... .... ...#.D.....# ........#... B.#....#...A .....C....#. ...#.... .....#.. .#...... ......#. It is possible for the next tile (after wrapping around) to be a wall; this still counts as there being a wall in front of you, and so movement stops before you actually wrap to the other side of the board. By drawing the last facing you had with an arrow on each tile you visit, the full path taken by the above example looks like this: >>v# .#v. #.v. ..v. ...#...v..v# >>>v...>#.>> ..#v...#.... ...>>>>v..#. ...#.... .....#.. .#...... ......#. To finish providing the password to this strange input device, you need to determine numbers for your final row, column, and facing as your final position appears from the perspective of the original map. Rows start from 1 at the top and count downward; columns start from 1 at the left and count rightward. (In the above example, row 1, column 1 refers to the empty space with no tile on it in the top-left corner.) Facing is 0 for right (>), 1 for down (v), 2 for left (<), and 3 for up (^). The final password is the sum of 1000 times the row, 4 times the column, and the facing. In the above example, the final row is 6, the final column is 8, and the final facing is 0. So, the final password is 1000 * 6 + 4 * 8 + 0: 6032. Follow the path given in the monkeys' notes. What is the final password? --- Part Two --- As you reach the force field, you think you hear some Elves in the distance. Perhaps they've already arrived? You approach the strange input device, but it isn't quite what the monkeys drew in their notes. Instead, you are met with a large cube; each of its six faces is a square of 50x50 tiles. To be fair, the monkeys' map does have six 50x50 regions on it. If you were to carefully fold the map, you should be able to shape it into a cube! In the example above, the six (smaller, 4x4) faces of the cube are: 1111 1111 1111 1111 222233334444 222233334444 222233334444 222233334444 55556666 55556666 55556666 55556666 You still start in the same position and with the same facing as before, but the wrapping rules are different. Now, if you would walk off the board, you instead proceed around the cube. From the perspective of the map, this can look a little strange. In the above example, if you are at A and move to the right, you would arrive at B facing down; if you are at C and move down, you would arrive at D facing up: ...# .#.. #... .... ...#.......# ........#..A ..#....#.... .D........#. ...#..B. .....#.. .#...... ..C...#. Walls still block your path, even if they are on a different face of the cube. If you are at E facing up, your movement is blocked by the wall marked by the arrow: ...# .#.. -->#... .... ...#..E....# ........#... ..#....#.... ..........#. ...#.... .....#.. .#...... ......#. Using the same method of drawing the last facing you had with an arrow on each tile you visit, the full path taken by the above example now looks like this: >>v# .#v. #.v. ..v. ...#..^...v# .>>>>>^.#.>> .^#....#.... .^........#. ...#..v. .....#v. .#v<<<<. ..v...#. The final password is still calculated from your final position and facing from the perspective of the map. In this example, the final row is 5, the final column is 7, and the final facing is 3, so the final password is 1000 * 5 + 4 * 7 + 3 = 5031. Fold the map into a cube, then follow the path given in the monkeys' notes. What is the final password? ================================================ FILE: exm/aoc/2022/aoc_2022_23.adb ================================================ -- Solution to Advent of Code 2022, Day 23 ------------------------------------------- -- Unstable Diffusion -- -- https://adventofcode.com/2022/day/23 -- Copy of questions in: aoc_2022_23_questions.txt -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; procedure AoC_2022_23 is use AoC_Toolbox, HAT; compiler_test_mode : constant Boolean := Argument_Count >= 2; verbosity_level : constant Natural := 0; radius : constant := 200; subtype Range_x is Integer range -radius .. radius; subtype Range_y is Integer range -radius .. radius; lowest, highest : Point; procedure Adapt_Lowest_Value_Point (using : Point) is begin lowest.x := Min (lowest.x, using.x); lowest.y := Min (lowest.y, using.y); end Adapt_Lowest_Value_Point; procedure Adapt_Highest_Value_Point (using : Point) is begin highest.x := Max (highest.x, using.x); highest.y := Max (highest.y, using.y); end Adapt_Highest_Value_Point; map : array (Range_x, Range_y) of Character; procedure Extend_Boundaries (p : Point) is begin Adapt_Lowest_Value_Point (p); Adapt_Highest_Value_Point (p); end Extend_Boundaries; elf : constant Character := '#'; elf_before_move : constant Character := 'x'; elf_after_move : constant Character := '@'; procedure Clear_Map is begin for y in Range_y loop for x in Range_x loop map (x, y) := '.'; end loop; end loop; end Clear_Map; procedure Clean_Map is c : Character; begin for y in lowest.y .. highest.y loop for x in lowest.x .. highest.x loop c := map (x, y); if c in '1' .. '4' or else c = elf_before_move then map (x, y) := '.'; elsif c = elf_after_move then map (x, y) := elf; end if; end loop; end loop; end Clean_Map; elves : Natural; function Count_Empty_Ground return Natural is elf_low, elf_high : Point; begin elf_low.x := radius; elf_low.y := radius; elf_high.x := -radius; elf_high.y := -radius; for y in lowest.y .. highest.y loop for x in lowest.x .. highest.x loop if map (x, y) = elf then elf_low.x := Min (elf_low.x, x); elf_low.y := Min (elf_low.y, y); elf_high.x := Max (elf_high.x, x); elf_high.y := Max (elf_high.y, y); end if; end loop; end loop; return (elf_high.y - elf_low.y + 1) * (elf_high.x - elf_low.x + 1) - elves; end Count_Empty_Ground; type Direction_Set is array (Direction) of Boolean; procedure Show is begin for y in reverse lowest.y .. highest.y loop -- y axis appears bottom -> up. for x in lowest.x .. highest.x loop Put (map (x, y)); end loop; New_Line; end loop; end Show; function Is_Elf (c : Character) return Boolean is begin return c = elf or else c = elf_before_move; end Is_Elf; start : Direction; any_move : Boolean; function Next (d : Direction) return Direction is begin case d is when north => return south; when south => return west; when west => return east; when east => return north; end case; end Next; procedure Do_Round (verbosity_enabled : Boolean) is procedure Do_Half_Round (half : Positive) is elf_look : Direction; is_possible, all_possible : Direction_Set; dest : Point; begin for d in Direction loop all_possible (d) := True; end loop; for y in lowest.y .. highest.y loop for x in lowest.x .. highest.x loop if Is_Elf (map (x, y)) then is_possible := all_possible; if Is_Elf (map (x - 1, y + 1)) then is_possible (north) := False; is_possible (west) := False; end if; if Is_Elf (map (x + 1, y + 1)) then is_possible (north) := False; is_possible (east) := False; end if; if Is_Elf (map (x - 1, y - 1)) then is_possible (south) := False; is_possible (west) := False; end if; if Is_Elf (map (x + 1, y - 1)) then is_possible (south) := False; is_possible (east) := False; end if; if Is_Elf (map (x, y + 1)) then is_possible (north) := False; end if; if Is_Elf (map (x, y - 1)) then is_possible (south) := False; end if; if Is_Elf (map (x - 1, y)) then is_possible (west) := False; end if; if Is_Elf (map (x + 1, y)) then is_possible (east) := False; end if; if is_possible (north) and then is_possible (south) and then is_possible (west) and then is_possible (east) then -- This Elf has enough room around him, -- thus no incentive to move. null; else elf_look := start; Look_Directions : for dir_count in 1 .. 4 loop if is_possible (elf_look) then -- Mark the destination cell. case elf_look is when north => dest.x := x; dest.y := y + 1; when south => dest.x := x; dest.y := y - 1; when west => dest.x := x - 1; dest.y := y; when east => dest.x := x + 1; dest.y := y; end case; Extend_Boundaries (dest); if half = 1 then -- Consider a move in chosen direction: case map (dest.x, dest.y) is when '.' => map (dest.x, dest.y) := '1'; when '1' => map (dest.x, dest.y) := '2'; when '2' => map (dest.x, dest.y) := '3'; when '3' => map (dest.x, dest.y) := '4'; when others => Put ("Bug : " & map (dest.x, dest.y)); end case; else -- Move... but only if there is no other -- Elf planning to move there. if map (dest.x, dest.y) = '1' then any_move := True; map (x, y) := elf_before_move; map (dest.x, dest.y) := elf_after_move; -- We don't put immediately `elf` on -- destination cell. -- The reason is to avoid double-moves -- on adjacent cells (the Elves move all -- at the same time)... end if; end if; exit Look_Directions; end if; elf_look := Next (elf_look); end loop Look_Directions; end if; end if; end loop; end loop; end Do_Half_Round; begin Clean_Map; any_move := False; if verbosity_enabled and then verbosity_level > 1 then Put_Line ("--- after cleanup"); Show; end if; for half in 1 .. 2 loop Do_Half_Round (half); if verbosity_enabled and then verbosity_level > 1 then Put_Line ("--- after half round" & half'Image); Show; end if; end loop; start := Next (start); end Do_Round; procedure Data_Acquisition is p : Point; f : File_Type; s : VString; c : Character; begin Clear_Map; lowest.x := radius; lowest.y := radius; highest.x := -radius; highest.y := -radius; Open (f, "aoc_2022_23.txt"); p.y := 0; elves := 0; start := north; Read_Data : while not End_Of_File (f) loop Get_Line (f, s); p.y := p.y - 1; for i in 1 .. Length (s) loop p.x := i; c := Element (s, i); map (p.x, p.y) := c; if c = elf then elves := elves + 1; Adapt_Lowest_Value_Point (p); Adapt_Highest_Value_Point (p); end if; end loop; end loop Read_Data; Close (f); end Data_Acquisition; T0 : constant Time := Clock; r : array (Part_Type) of Integer; last_round : Integer := 10; begin r (part_1) := 0; r (part_2) := 0; Parts : for part in part_1 .. part_1 loop Data_Acquisition; if verbosity_level > 0 then Show; end if; for round in 1 .. 10 loop if verbosity_level > 0 then Put_Line ("===== Round" & round'Image & " ====="); end if; Do_Round (True); if verbosity_level = 1 then Show; end if; end loop; Clean_Map; if verbosity_level > 0 then Put_Line ("===== 10th Round Evaluation ====="); Show; end if; r (part_1) := Count_Empty_Ground; if not compiler_test_mode then for round in 11 .. Integer'Last loop exit when not any_move; last_round := round; Do_Round (False); end loop; if verbosity_level > 0 then Put_Line ("===== Stable state after" & last_round'Image & " rounds ====="); Show; end if; r (part_2) := last_round; end if; end loop Parts; if compiler_test_mode then if r (part_1) /= Integer'Value (To_String (Argument (1))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"===== Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 3689 -- Part 2: validated by AoC: 965 end if; end AoC_2022_23; ================================================ FILE: exm/aoc/2022/aoc_2022_23.txt ================================================ ###..#####..#....##.#..#...#.#.#..#.##..##...#.#.###.#.###...###.#.... #..#..#.#....#.#.####.#.#.....#..####...####.##.#.#....####...#..#.#.. ...##...#.#####..###......#.#.#..##.#..#..#####.#..###.#.####.#.####.. #.#...#...#.#..##.#.#..#.####...#.#####.###.##....##.###.#.##..####.#. ...##.##..#.##.###..##.####.##.#...##...#.#...#.##.#..##...###.###.... .......#.#..#.#....#....#.....##...#.#...###..#..#.##...#....##...#..# #.##..#.#..#.#####.#.#....##..#..##..###...#.###.####.#.....#..#.#.##. .#####.......###.##.#....#...##.#.#...#.######...##.#.#.###...###..#.. .#.###..#####.##.##...#..##..#.#..#.####.##..###.##..##..##..##..##.#. ..##..###.###.....#...###.#.#...#####.##..######.#.#.#...#..####....#. .#.....#..#........#####.###.##..#.####..#.#.#.###.###.#.....###.....# .#.##....#..#..#..#..#.#.#.....###.##.####.###.#..#..###..##.......### ##.##..###...##....#....#........#.#######....#..#.##..#.##...#.#####. .#####.#.#.######.##....#..###.##......####..#...#.##.######...####.## #..###..#...##.##..#.#.....##...#.##.#.####.###.##....#.###.###...#.## ..##.#...###...#...###.#.#.###.#.####..##..#...#..##...#..####...#.### ###.....#..#....#.#......###..##.#...####...#..########..#.##.....#### ###..##....#.......#..###.#.#..##..#...###.......###....###.##..#..##. #..#.#..#.###....#.##.#.....#.##.##..#.##.###..##..###.##.###..#.##... #..#....#..##......###.######..#..#####.##...#.#..#..##..#.#....####.# .....#...#..####..##..#.#.##..##.###..#.###..#....##.##.##.####....... ...#..#.####....###.#......#..###.##.#.#..##.#..#####.###..###..##.### #.###...#.#####..##.##..#.#....###.####.##.....####..#...#.###.#####.. ..#####.#...#.#..#..#.#.#.#.#......#.##.#.....##....#.##..###..####..# ...#####.#.#..#..###..##.#.##.##...#.##.#.##.#.#.....#.###..####.#.#.. ####....##.##....#.#.###.##..#.#......#....#.###..#.#######.#..##...#. #.#..#..####..#.#...##.#...###.....##.###...#.#.#####.#....###.###.##. #.####.....#........##.#..##..##.###.#.##.#.#.#...##..#########.###..# #.#.#..#########.###.##..###.#...#.##.#..#....###...###.#..##.##.##... .#.#..##.......###.##.#.##......###..#....###.#...###.#.....#.#####... ##.##..#.#..#....####.##..######.#.#..##...#...##.#.##..#.#....#.#.#.# .#..#...#.###....#..#.#.#...#####...#.#####.#.....#.#.##.#...##..##.## .##.#.######.#.####.#..##.#.####.##.##..##.######..#.#######..#.#..##. .#....#.#.###.##.....#..##.#.#####..##..###.##.#...#.#.#....#....###.# .#.#.#..#.....##.#....##.#....###.###......#.#..#.#...##...#..#.###..# ..#..#....##.##...#.#...#......#.#####....###.#..#.#..#..#.####..##### .#.#..#....####..#....##..####.#.#.#...#.##.#..........###.....#..#..# .#.##.#.#.....##.#...###.....#####.##.##......###.#.##..####.##....#.. ...#..##.#..#....#.....##..#.#.##.###.##.#.#..##.#.#...##.#...####...# ##.#.########....#.#..##..#.##...###..#...#.##.###..####.###.......#.# #.##...##..#####..##..###.#..######..###..######..#.#.#..########.#... ##..##..##.##.##...###..#.#.#..#.#.###.#..#...#..#.#....#..##....#..#. ..#####..#.#.##.##.####.#..#.####.#.#.....#....#.##...##.....###....## ##..####..#.###.##..######.#..#.##.##..####..#.##.#.##.#.#.###.#.##... #.#...#..##.##...##....#..#..#.#.#####....#.#.#.###..#..#.#..#....#... #.###....##.........###...###..##.#..#.##.#.....#..#.######..#.###.... #######..###.#..###...#..#####.....#..#...#..##..#....#.#####..###.... .#...###..###....##.##.....#.##.#.###.#.####...#...#.#.##........#.#.# ##..#..#......#.#.###.#.#.#.#....#.#...####.###.##.#.#..###........##. .#..#..#.#.###..#...#..###.##....#........#.#.#.####.#..#.#.####..#.## ..########..#..#..#.####.####.###.#####..#..######..#.#.#....#......#. ###.##..##.####.#.......###.....####.#.#..#.#.#..#.#..##.###...#.##.## .....##..#..#.#.#.####...##..######.#.####..#..##.###......###.#....#. #..###...#..##........#.#.###.##.##..#..#..##.##.#.#..##.#..##.##...#. ..#....#.#.#####.##...#.##.#..##....##.##.#....##..#.######..#.####.#. #...##.#.##.#.#...#.###.#.#.##.....##.###.#...#.#.#####.######.##.#.## #.#.###..#.#..####..###..#####.#.........#..####.##.###.###.#....#.... .#.#...#.#.###..##....#..#.###.#...#.#..###..###..#.##.#.##.#.#...##.. ...##..#.#.#.###..##...#####..##.#.#.####.#...####.#.#..#..##...##.### ...####..###.###.#.#...#.##...#.###...#.#.#.#.#.....#..#...##..##.#... ##..###...##.#.###.##.##..#.#####.###.......##.####..##.....#.#.##..#. ......##.....#...#.###.##.#..#####.#.###....#.#..###.#....##...##.#.## ...#.#.###.##...##.####..##.##..#...#.#.......##..#..#....##...#.#.#.. ..##.....###.....#...#.#.##..###..####.###..###...#..#...#..###...##.. .#.#.#.#..####..#...###.#.#..##.##.#.#..#..##.......#.#..#.####.###.## #..###..###.#.......#.#...##.###.#....#..#.##.#.##.##.####.####.#####. ###.#...#....#.#..##.#.##.##.#.#..##..##..#####.#.#.#.##.....##.##..## ##.##..#....##...###.##..#...#.....#.#..##......#...#.###....#.#..#..# ##..#..###..####.#.#.#.##.#.###.###.##.#.##....##.#.#..#.#..#.#...###. #.##..##.#.###..#.#.####.#...#...##..#..##.###.#.#.......#....##.##... ================================================ FILE: exm/aoc/2022/aoc_2022_23_questions.txt ================================================ --- Day 23: Unstable Diffusion --- You enter a large crater of gray dirt where the grove is supposed to be. All around you, plants you imagine were expected to be full of fruit are instead withered and broken. A large group of Elves has formed in the middle of the grove. "...but this volcano has been dormant for months. Without ash, the fruit can't grow!" You look up to see a massive, snow-capped mountain towering above you. "It's not like there are other active volcanoes here; we've looked everywhere." "But our scanners show active magma flows; clearly it's going somewhere." They finally notice you at the edge of the grove, your pack almost overflowing from the random star fruit you've been collecting. Behind you, elephants and monkeys explore the grove, looking concerned. Then, the Elves recognize the ash cloud slowly spreading above your recent detour. "Why do you--" "How is--" "Did you just--" Before any of them can form a complete question, another Elf speaks up: "Okay, new plan. We have almost enough fruit already, and ash from the plume should spread here eventually. If we quickly plant new seedlings now, we can still make it to the extraction point. Spread out!" The Elves each reach into their pack and pull out a tiny plant. The plants rely on important nutrients from the ash, so they can't be planted too close together. There isn't enough time to let the Elves figure out where to plant the seedlings themselves; you quickly scan the grove (your puzzle input) and note their positions. For example: ....#.. ..###.# #...#.# .#...## #.###.. ##.#.## .#..#.. The scan shows Elves # and empty ground .; outside your scan, more empty ground extends a long way in every direction. The scan is oriented so that north is up; orthogonal directions are written N (north), S (south), W (west), and E (east), while diagonal directions are written NE, NW, SE, SW. The Elves follow a time-consuming process to figure out where they should each go; you can speed up this process considerably. The process consists of some number of rounds during which Elves alternate between considering where to move and actually moving. During the first half of each round, each Elf considers the eight positions adjacent to themself. If no other Elves are in one of those eight positions, the Elf does not do anything during this round. Otherwise, the Elf looks in each of four directions in the following order and proposes moving one step in the first valid direction: If there is no Elf in the N, NE, or NW adjacent positions, the Elf proposes moving north one step. If there is no Elf in the S, SE, or SW adjacent positions, the Elf proposes moving south one step. If there is no Elf in the W, NW, or SW adjacent positions, the Elf proposes moving west one step. If there is no Elf in the E, NE, or SE adjacent positions, the Elf proposes moving east one step. After each Elf has had a chance to propose a move, the second half of the round can begin. Simultaneously, each Elf moves to their proposed destination tile if they were the only Elf to propose moving to that position. If two or more Elves propose moving to the same position, none of those Elves move. Finally, at the end of the round, the first direction the Elves considered is moved to the end of the list of directions. For example, during the second round, the Elves would try proposing a move to the south first, then west, then east, then north. On the third round, the Elves would first consider west, then east, then north, then south. As a smaller example, consider just these five Elves: ..... ..##. ..#.. ..... ..##. ..... The northernmost two Elves and southernmost two Elves all propose moving north, while the middle Elf cannot move north and proposes moving south. The middle Elf proposes the same destination as the southwest Elf, so neither of them move, but the other three do: ..##. ..... ..#.. ...#. ..#.. ..... Next, the northernmost two Elves and the southernmost Elf all propose moving south. Of the remaining middle two Elves, the west one cannot move south and proposes moving west, while the east one cannot move south or west and proposes moving east. All five Elves succeed in moving to their proposed positions: ..... ..##. .#... ....# ..... ..#.. Finally, the southernmost two Elves choose not to move at all. Of the remaining three Elves, the west one proposes moving west, the east one proposes moving east, and the middle one proposes moving north; all three succeed in moving: ..#.. ....# #.... ....# ..... ..#.. At this point, no Elves need to move, and so the process ends. The larger example above proceeds as follows: == Initial State == .............. .............. .......#...... .....###.#.... ...#...#.#.... ....#...##.... ...#.###...... ...##.#.##.... ....#..#...... .............. .............. .............. == End of Round 1 == .............. .......#...... .....#...#.... ...#..#.#..... .......#..#... ....#.#.##.... ..#..#.#...... ..#.#.#.##.... .............. ....#..#...... .............. .............. == End of Round 2 == .............. .......#...... ....#.....#... ...#..#.#..... .......#...#.. ...#..#.#..... .#...#.#.#.... .............. ..#.#.#.##.... ....#..#...... .............. .............. == End of Round 3 == .............. .......#...... .....#....#... ..#..#...#.... .......#...#.. ...#..#.#..... .#..#.....#... .......##..... ..##.#....#... ...#.......... .......#...... .............. == End of Round 4 == .............. .......#...... ......#....#.. ..#...##...... ...#.....#.#.. .........#.... .#...###..#... ..#......#.... ....##....#... ....#......... .......#...... .............. == End of Round 5 == .......#...... .............. ..#..#.....#.. .........#.... ......##...#.. .#.#.####..... ...........#.. ....##..#..... ..#........... ..........#... ....#..#...... .............. After a few more rounds... == End of Round 10 == .......#...... ...........#.. ..#.#..#...... ......#....... ...#.....#..#. .#......##.... .....##....... ..#........#.. ....#.#..#.... .............. ....#..#..#... .............. To make sure they're on the right track, the Elves like to check after round 10 that they're making good progress toward covering enough ground. To do this, count the number of empty ground tiles contained by the smallest rectangle that contains every Elf. (The edges of the rectangle should be aligned to the N/S/E/W directions; the Elves do not have the patience to calculate arbitrary rectangles.) In the above example, that rectangle is: ......#..... ..........#. .#.#..#..... .....#...... ..#.....#..# #......##... ....##...... .#........#. ...#.#..#... ............ ...#..#..#.. In this region, the number of empty ground tiles is 110. Simulate the Elves' process and find the smallest rectangle that contains the Elves after 10 rounds. How many empty ground tiles does that rectangle contain? --- Part Two --- It seems you're on the right track. Finish simulating the process and figure out where the Elves need to go. How many rounds did you save them? In the example above, the first round where no Elf moved was round 20: .......#...... ....#......#.. ..#.....#..... ......#....... ...#....#.#..# #............. ....#.....#... ..#.....#..... ....#.#....#.. .........#.... ....#......#.. .......#...... Figure out where the Elves need to go. What is the number of the first round where no Elf moves? ================================================ FILE: exm/aoc/2022/aoc_2022_24.adb ================================================ -- Solution to Advent of Code 2022, Day 24 ------------------------------------------- -- Blizzard Basin -- -- https://adventofcode.com/2022/day/24 -- Copy of questions in: aoc_2022_24_questions.txt -- Runs in 0.12 second with GNAT. -- Runs in 134 seconds with HAC. -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; procedure AoC_2022_24 is use AoC_Toolbox, HAT; verbosity_level : constant Natural := 0; f : File_Type; s : VString; subtype Range_x is Integer range 0 .. 101; subtype Range_y is Integer range -1 .. 36; subtype Range_t is Integer range 0 .. 700; lowest, highest : Point; inf : constant Natural := Integer'Last / 4; -- Convention: 0-based, y axis appears top -> down. type Blizzard is array (Range_x, Range_y) of Boolean; leftward_blizzard, upward_blizzard, rightward_blizzard, downward_blizzard : Blizzard; best : array (Range_x, Range_y, Range_t) of Natural; procedure Show (time_step : Natural) is begin for y in lowest.y .. highest.y loop -- y axis appears top -> down. for x in lowest.x .. highest.x loop if leftward_blizzard ((x + time_step) mod (highest.x + 1), y) then Put ('<'); elsif upward_blizzard (x, (y + time_step) mod (highest.y + 1)) then Put ('^'); elsif rightward_blizzard ((x - time_step) mod (highest.x + 1), y) then Put ('>'); elsif downward_blizzard (x, (y - time_step) mod (highest.y + 1)) then Put ('v'); else Put ('.'); end if; end loop; New_Line; end loop; end Show; procedure Clear (b : in out Blizzard) is begin for y in Range_y loop for x in Range_x loop b (x, y) := False; end loop; end loop; end Clear; -- Dijkstra shortest path algorithm. -- Code adapted from AoC_2022_12. -- list_length_max : constant := 200_000; -- Adjusted by doubling until no Constraint_Error. subtype List_Range is Integer range 1 .. list_length_max; type Node is record len : Natural; -- Length in space-time pt : Point_3D; -- dimensions: x, y, t pred : Natural; -- This is just for displaying the path. end record; list : array (List_Range) of Node; current, explored : Natural; -- 0 <= current <= explored stats : constant Boolean := True; stats_first_visit : Natural := 0; stats_added_revisit : Natural := 0; stats_rejected_revisit : Natural := 0; function Dijkstra_Algorithm (start : Point_3D; part : Part_Type) return Natural is blizzard_cycle : Positive; cur_pt : Point_3D; cur_len : Natural; procedure Visit (x, y : Integer) is len_to, ins, t : Integer; begin t := cur_pt.z + 1; if (x in 0 .. highest.x -- The valley. and then y in 0 .. highest.y and then not (leftward_blizzard ((x + t) mod (highest.x + 1), y) or else rightward_blizzard ((x - t) mod (highest.x + 1), y) or else upward_blizzard (x, (y + t) mod (highest.y + 1)) or else downward_blizzard (x, (y - t) mod (highest.y + 1)))) or else (x = 0 and then y = -1) -- The "starting block". or else (x = highest.x -- The end (and new start...). and then y = highest.y + 1) then len_to := cur_len + 1; if verbosity_level > 1 then Put (+"x: " & x & ", y: " & y & ", t: " & t & " cur_len = " & cur_len); if best (x, y, t mod blizzard_cycle) < inf then Put (+" old best (x, y, time_step) = " & best (x, y, t mod blizzard_cycle) & ", "); else Put (" not visited, "); end if; end if; if len_to < best (x, y, t mod blizzard_cycle) then -- Improvement on cell (x, y). best (x, y, t mod blizzard_cycle) := len_to; -- -- Insert in a sorted way. -- ins := explored + 1; for i in current + 1 .. explored loop if current < list (i).len then ins := i; -- Insert here. -- Optional: remove another node -- with the same (x, y) and a larger length. exit; end if; end loop; for i in reverse ins .. explored loop list (i + 1) := list (i); end loop; list (ins).len := len_to; list (ins).pt.x := x; list (ins).pt.y := y; list (ins).pt.z := t; list (ins).pred := current; explored := explored + 1; if verbosity_level > 1 then Put_Line (" -> added"); end if; if stats then if best (x, y, t mod blizzard_cycle) < inf then stats_first_visit := stats_first_visit + 1; else stats_added_revisit := stats_added_revisit + 1; end if; end if; else if stats then if best (x, y, t mod blizzard_cycle) < inf then stats_rejected_revisit := stats_rejected_revisit + 1; else Put ("Uh (rejected but = inf) ?"); end if; end if; if verbosity_level > 1 then Put_Line (" -> NOT added"); end if; end if; end if; end Visit; begin current := 0; explored := 0; blizzard_cycle := (highest.x + 1) * (highest.y + 1) / GCD (highest.x + 1, highest.y + 1); if verbosity_level > 0 then Put_Line ("blizzard_cycle" & blizzard_cycle'Image); end if; for t in 0 .. Min (blizzard_cycle - 1, best'Last (3)) loop for x in 0 .. highest.x loop for y in -1 .. highest.y + 1 loop best (x, y, t) := inf; end loop; end loop; end loop; cur_pt := start; best (cur_pt.x, cur_pt.y, cur_pt.z mod blizzard_cycle) := 0; loop cur_len := best (cur_pt.x, cur_pt.y, cur_pt.z mod blizzard_cycle); Visit (cur_pt.x, cur_pt.y); -- Wait in place. Visit (cur_pt.x - 1, cur_pt.y); Visit (cur_pt.x + 1, cur_pt.y); Visit (cur_pt.x, cur_pt.y - 1); Visit (cur_pt.x, cur_pt.y + 1); -- -- Switch to the next best explored point. -- current := current + 1; if current > explored then Put_Line ("No way found."); return inf; end if; cur_pt := list (current).pt; case part is when part_1 => exit when cur_pt.x = highest.x and then cur_pt.y = highest.y; when part_2 => exit when cur_pt.x = 0 and then cur_pt.y = 0; end case; end loop; return cur_pt.z + 1; end Dijkstra_Algorithm; T0 : constant Time := Clock; r : array (Part_Type) of Integer; start : Point_3D; begin Clear (leftward_blizzard); Clear (upward_blizzard); Clear (rightward_blizzard); Clear (downward_blizzard); lowest.x := 0; lowest.y := 0; Open (f, "aoc_2022_24.txt"); Get_Line (f, s); highest.x := Length (s) - 3; highest.y := -1; Read_Data : while not End_Of_File (f) loop Get_Line (f, s); exit Read_Data when End_Of_File (f); -- Discard last line highest.y := highest.y + 1; for i in 2 .. Length (s) - 1 loop case Element (s, i) is when '.' => null; when '<' => leftward_blizzard (i - 2, highest.y) := True; when '^' => upward_blizzard (i - 2, highest.y) := True; when '>' => rightward_blizzard (i - 2, highest.y) := True; when 'v' => downward_blizzard (i - 2, highest.y) := True; when others => Put ("Whut?"); end case; end loop; end loop Read_Data; Close (f); if verbosity_level > 0 then for i in 0 .. 18 loop Put_Line (i, 0); Show (i); New_Line; end loop; end if; start.x := 0; start.y := -1; start.z := 0; r (part_1) := Dijkstra_Algorithm (start, part_1); start.x := highest.x; start.y := highest.y + 1; start.z := r (part_1); r (part_2) := Dijkstra_Algorithm (start, part_2); start.x := 0; start.y := -1; start.z := r (part_2); r (part_2) := Dijkstra_Algorithm (start, part_1); if Argument_Count >= 2 then -- Compiler test mode. if r (part_1) /= Integer'Value (To_String (Argument (1))) or r (part_2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); if stats then Put_Line (+"Firstly visited cells : " & stats_first_visit); Put_Line (+"Added revisited cells : " & stats_added_revisit); Put_Line (+"Rejected revisited cells : " & stats_rejected_revisit); end if; Put_Line (+"Shortest time for..."); Put_Line (+" (part 1) one trip . . . . :" & r (part_1)'Image); Put_Line (+" (part 2) three trips . . :" & r (part_2)'Image); -- Part 1: validated by AoC: 238 -- Part 2: validated by AoC: 751 end if; end AoC_2022_24; ================================================ FILE: exm/aoc/2022/aoc_2022_24.txt ================================================ #.#################################################################################################### #>^<.v^^v>>^>vv..<>>^<>>><><<>^v^>.^<>><<^vv><^<>>vv^v.<.^v><<<>.<<^v.vv<# #<^>v<><.<<^^<>^>v<^vvvv^<.<><^><<^v<^><vv<<>>>^.^<>>>^vvv^><^v^^>>><><<><><.# #>.vv^^^<^>v>vvv>^....v^<>v<><<..vvv<^<^>^<^v^>><^^v.v>>><^.^>vv^^v>v<^^.vv>^^>v>vvv^v><# #.^^<^v^^<^>>^>>^vv>^^v>>.v^>^.v^>vvv^.v.>.>^<^.<^>><^>^^>><><^^^<# #<^<>><>^^>>v.v.v^^>^<>><^>>^^>v<^.^.v<..>>>.>>.<^<^^^>.<>^^.v^>>>v>v>^^v>^><>><<.^.^>vv^^.# #<^^>^v><..v^v<^..<>.^v^>^^>>v^^v.<.^><>^v.^^v>v<^^vv<<^^v<>><>^>^<>>>>^v.>v.><.>v>># #<>.<<^><<>>v><><>^..^v^v^<>>^v.^^>>.v^.v>.v.v<>v.<.vv<<^<>^^^^>>.<<>vv>^>.v^<^>># #<.^<>v>>>.<>v^..v<<>^>^v>>.<>>v<^>^>^<<<..v><<>^>^^>^v>><<>>.^<>>^.^^>>.v<<>vv><.v<.^^^>v.v^v^.>>^^^vvvv<^<^^.^<>v<^.^<>v>>vv<>>^^^>v>><# #>><^<>^<^>v>v^v><^v>v>^>^<>>^v>vv^>^v.<^><.vv^^^<^><..<<<>^>^.^>>>^<>.^<^>^<>^^v>v# #><<>.v>^.<^><^^v><<<<<.^>>.^^v>>^<^<>.^.>>>.>>.^v>v.<^^v^<^<>v<>^^<<^^^<>v>v<^.v<# #.v<<>^^^<<<.^^>vvv^>^v>v><><<.v>v<<<><..>>v>>v><^^>^^.^>v.v..>^><^.<>^<<^<v><<.v<.>^vv.^<<<<<<.v>^^^.^vv<.<<><>>><^<^.^<>^>^<>v.v.v^>^.>vv<>^^>^.>v^<>^>v<>^v>v>>v<>^<<.^<^>.vv.>>^.vv<><# #>>v>>>.v><^^v^>>v>v^>>^^v<>>>>^^v>^><>.v>>v..^>...v<<.<^>v<# #<><^>>v^<^^vv>v.v.<^v.^>vvv<^>v><^>v><><.v>>.^^>><<>.v^<<^.<.^^.vv# #<<^^<<^vvv<<<<.^vv^.><v^><>..^.^^v>v>^^<^v.v>^v><>>^v><<.v>v<>^vv<^v^.^>^>v>^><<.<# #<<>v.v>...^^.<<^>>.<>^^^v>^<^><.v^.>>^>^>vv<<>.>>.v^v><.^v.>^>^><^^v^^v^<# #<^vv^<><<>v><^<>^>v<>.<>>v>v<>v<><<<<.<<.<<>>>><><^v<<<^>v<^<^^<^<..v>.vv># #><^>>>.^.>v<^^>>vv<^<^<^<^v>vv>v^^><.^.^>>.v.>v^.>>^<>^^^>vvv>..v^vv<^v>>v<><><<<^^<^^<># #>^^v<<.<^><><>>v.>.^<>^^vv<<>>>v^<>>><>^<<><.v><.vv^v^.v.>vv^<><.v^>vv.<<<<# #>v<^>>.>>v>v>><^>^>^.^>^>vv>^<<><^v.<>>v>v>^<>><^>^^<>v>v>.<^v^>>>v^>vvv.>.>^<><>.v^vv><>^>># #>><>v^>^>>^>^^>^>^<^>>vv>>>>>>vvv.v>.^v.<^v.vv.v>^>>vv<^^^^>>^v.^v>>v^^<^v<<<.<# #<>vv<^v>v^>^<<>v^>vvvv>v^><^>^v><^><<.^>v^vv.v<<<>..v<^<.vv>.v>^>>>^^v^v^<^v^<^^<.>.>><# #<<<>v.>>><>^<<.<<<<.v^v>v>v>.><>.<^.<^>^^>vv..v.>>.^>^>v<^vvvv>><>^^v<^>v>.# #>.^>^>.vv^v<.>^>v<^v^>.>^<^..v<>>v.v>^.v<^>>^^^v>vv<<^>.v>.vv.^.# #<^v><>.<^v.>v^^^<.<^^<<.^>vv^^<^>vvv^v>v^^>>..v^>.v>v^<^><.>^>>><>^v.<>v.^>>^^vv^<^>vv<^>v.v>>.^.v^.v^<>^.>><^>v>.>>v^<^>.>>^v<<^>^>v^^^^>^v># #<^.>^v>^<>>^.^<>.>..><>.v^..v<<><>>^.^><^^<^^<^v<<^<^>.<><^.>^<^vv^>>>>^^>>><.>^>.<# #.v<>><^^vv^<<<<>><>>v^>v>^^^v<<<<<<>.^v<>.^<><<^vv<^>>v.^>v<^v>^v>>v<^^>vv.^<^>.>.# #>^<.>v^^^><<>^.>vvv>v^<^>v><<<><><.^>>.>vv.^<<<<<^<^>^>v<^^<^<>v<<><>v>>>^<>>>.<<^<^<<# #>^^>.vv^><.>v^><>v><^.^>v^>^v<.^>v>v^v.^<>^v^>vv>>vv># #><>^<^^>^>v<^^v<>>v^>^v.v.v>^^><^<<<<>v>vv^^>.v<><<^><^^<<>>>>^>v>^>><><^>v><^^>># #><<<>^vv.^<>^>>vv^v^v<>vvvv^v<^<^^v><>><<>v^vv<^>v><>><<<^>>^^<^>><>v^v><>v<>>^v>^<>^^>>>>v>>>v<^<<<<>v><^<<^^^<^<>v<>^<^.>>><<^v.<>v^^.>>^^.^>^v<# ####################################################################################################.# ================================================ FILE: exm/aoc/2022/aoc_2022_24_questions.txt ================================================ --- Day 24: Blizzard Basin --- With everything replanted for next year (and with elephants and monkeys to tend the grove), you and the Elves leave for the extraction point. Partway up the mountain that shields the grove is a flat, open area that serves as the extraction point. It's a bit of a climb, but nothing the expedition can't handle. At least, that would normally be true; now that the mountain is covered in snow, things have become more difficult than the Elves are used to. As the expedition reaches a valley that must be traversed to reach the extraction site, you find that strong, turbulent winds are pushing small blizzards of snow and sharp ice around the valley. It's a good thing everyone packed warm clothes! To make it across safely, you'll need to find a way to avoid them. Fortunately, it's easy to see all of this from the entrance to the valley, so you make a map of the valley and the blizzards (your puzzle input). For example: #.##### #.....# #>....# #.....# #...v.# #.....# #####.# The walls of the valley are drawn as #; everything else is ground. Clear ground - where there is currently no blizzard - is drawn as .. Otherwise, blizzards are drawn with an arrow indicating their direction of motion: up (^), down (v), left (<), or right (>). The above map includes two blizzards, one moving right (>) and one moving down (v). In one minute, each blizzard moves one position in the direction it is pointing: #.##### #.....# #.>...# #.....# #.....# #...v.# #####.# Due to conservation of blizzard energy, as a blizzard reaches the wall of the valley, a new blizzard forms on the opposite side of the valley moving in the same direction. After another minute, the bottom downward-moving blizzard has been replaced with a new downward-moving blizzard at the top of the valley instead: #.##### #...v.# #..>..# #.....# #.....# #.....# #####.# Because blizzards are made of tiny snowflakes, they pass right through each other. After another minute, both blizzards temporarily occupy the same position, marked 2: #.##### #.....# #...2.# #.....# #.....# #.....# #####.# After another minute, the situation resolves itself, giving each blizzard back its personal space: #.##### #.....# #....># #...v.# #.....# #.....# #####.# Finally, after yet another minute, the rightward-facing blizzard on the right is replaced with a new one on the left facing the same direction: #.##### #.....# #>....# #.....# #...v.# #.....# #####.# This process repeats at least as long as you are observing it, but probably forever. Here is a more complex example: #.###### #>>.<^<# #.<..<<# #>v.><># #<^v^^># ######.# Your expedition begins in the only non-wall position in the top row and needs to reach the only non-wall position in the bottom row. On each minute, you can move up, down, left, or right, or you can wait in place. You and the blizzards act simultaneously, and you cannot share a position with a blizzard. In the above example, the fastest way to reach your goal requires 18 steps. Drawing the position of the expedition as E, one way to achieve this is: Initial state: #E###### #>>.<^<# #.<..<<# #>v.><># #<^v^^># ######.# Minute 1, move down: #.###### #E>3.<.# #<..<<.# #>2.22.# #>v..^<# ######.# Minute 2, move down: #.###### #.2>2..# #E^22^<# #.>2.^># #.>..<.# ######.# Minute 3, wait: #.###### #<^<22.# #E2<.2.# #><2>..# #..><..# ######.# Minute 4, move up: #.###### #E<..22# #<<.<..# #<2.>>.# #.^22^.# ######.# Minute 5, move right: #.###### #2Ev.<># #<.<..<# #.^>^22# #.2..2.# ######.# Minute 6, move right: #.###### #>2E<.<# #.2v^2<# #>..>2># #<....># ######.# Minute 7, move down: #.###### #.22^2.# #>v<>.# #>....<# ######.# Minute 8, move left: #.###### #.<>2^.# #.E<<.<# #.22..># #.2v^2.# ######.# Minute 9, move up: #.###### #>.# #.<<.<.# #>2>2^.# #.v><^.# ######.# Minute 10, move right: #.###### #.2E.>2# #<2v2^.# #<>.>2.# #..<>..# ######.# Minute 11, wait: #.###### #2^E^2># #2# #.<..>.# ######.# Minute 12, move down: #.###### #>>.<^<# #.v.><># #<^v^^># ######.# Minute 13, move down: #.###### #.>3.<.# #<..<<.# #>2E22.# #>v..^<# ######.# Minute 14, move right: #.###### #.2>2..# #.^22^<# #.>2E^># #.>..<.# ######.# Minute 15, move right: #.###### #<^<22.# #.2<.2.# #><2>E.# #..><..# ######.# Minute 16, move right: #.###### #.<..22# #<<.<..# #<2.>>E# #.^22^.# ######.# Minute 17, move down: #.###### #2.v.<># #<.<..<# #.^>^22# #.2..2E# ######.# Minute 18, move down: #.###### #>2.<.<# #.2v^2<# #>..>2># #<....># ######E# What is the fewest number of minutes required to avoid the blizzards and reach the goal? --- Part Two --- As the expedition reaches the far side of the valley, one of the Elves looks especially dismayed: He forgot his snacks at the entrance to the valley! Since you're so good at dodging blizzards, the Elves humbly request that you go back for his snacks. From the same initial conditions, how quickly can you make it from the start to the goal, then back to the start, then back to the goal? In the above example, the first trip to the goal takes 18 minutes, the trip back to the start takes 23 minutes, and the trip back to the goal again takes 13 minutes, for a total time of 54 minutes. What is the fewest number of minutes required to reach the goal, go back to the start, then reach the goal again? ================================================ FILE: exm/aoc/2022/aoc_2022_25.adb ================================================ -- Solution to Advent of Code 2022, Day 25 ------------------------------------------- -- Full of Hot Air -- -- https://adventofcode.com/2022/day/25 -- Copy of questions in: aoc_2022_25_questions.txt -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; -- Interfaces is needed for compiling on both -- HAC and GNAT (64-bit integer: Integer_64): with Interfaces; procedure AoC_2022_25 is use HAT, Interfaces; f : File_Type; s : VString; i, k, sum : Integer_64; begin sum := 0; Open (f, "aoc_2022_25.txt"); Read_Data : while not End_Of_File (f) loop Get_Line (f, s); i := 0; for j in 1 .. Length (s) loop case Element (s, j) is when '0' => k := 0; when '1' => k := 1; when '2' => k := 2; when '-' => k := -1; when '=' => k := -2; when others => Put ("Whut?"); end case; i := i * 5 + k; end loop; sum := sum + i; end loop Read_Data; Close (f); s := +""; while sum /= 0 loop case sum mod 5 is when 0 => s := '0' & s; when 1 => s := '1' & s; when 2 => s := '2' & s; when 3 => s := '=' & s; sum := sum + 5; -- -2 when 4 => s := '-' & s; sum := sum + 5; -- -1 when others => null; end case; sum := sum / 5; end loop; Put_Line (s); -- Part 1: validated by AoC: 2=-0=01----22-0-1-10 end AoC_2022_25; ================================================ FILE: exm/aoc/2022/aoc_2022_25.txt ================================================ 1=0=01=0=2111-1211 1==21= 20-- 1-=1200=-=0 211==12=2=0111== 2=-10 1221=221=0-1=- 12=02=-12020=12=01- 12112101 20 120120=21=1002-1 10==1-02=1 1=11200001-=-- 1=222-1=012=2 20===1-1102-= 1020 102=-==-=2- 112-2112-00012- 1010=--121 202022=-=2-22= 122==1=1020011=-00 10212==-0 2=--12020=1-0=-2=- 1110-1-2 20==210221=-21--12 1=-02--=22=-122 2=-=0=00=1--1-2=-- 2==2==2- 2=12=1 2=01= 202=20202-000 1=0-=020021022012 2=0-011-=2=-0-=21 1=211 1-=1=11=--010=--- 1000020-12== 2-=122-1211-0= 10=2220122012 2=21-01=212 10111==2=2-12 111 1=2---2211=2011=-- 1--=0000=1-020 2=02-=- 1-011= 12020-0=-1-220100 2-==000=21=1 2-0100000-12-2-= 1-=1 1221=2-1==02-=202 200 122-2-0 10=2101-22 1==-120-1 2=2=2=-11--==-== 2111-=2=-=-2 1-- 1-0=10-0112-12= 10= 2=01=1=-=20= 1= 1211-2=-1= 222= 122=2-1-0 1-2=20-=02122-1 1==-=2===0-=1100--11 12-0=201=10=-= 1=01=2=22-2-1-1 120==222100=0 11=-=--12=2-1101 102=1221=---0==021 2-=-2=202-=-== 100=1=02020-221= 1=0=-220= 1001- 20==2==1-1 1=2-2=2=-12= 10=0--2 10-202-2002=22= 2=2= 1-011=0=-12--- 1002220 2= 1--=2---111 222==2 11100 1=0=201 1--02- 1=11-==0=021 1-=00= 1==12-20-=002001= 1=0=-=21- 1000-1=0-0=1=01-2- 2== 1-0 1=101-0-1 1=0= 11=2==-0-2202-0= 10-0=0=1-002 1-=0210=01120- 1112=2-0-2=-01 1-1=022=21 2=1-2--120 10002--0=220-0-2=12 11002102100 11000-2-12 120=-==1-2-= 21 11 2=121- 1== 1=- 1-=--2=- 2=-10-=0 2200-1- 2=21-1200== 1-102210=002=--112 1-10 122=202=201-=-10-1 2212121=02102 21=2-211=-1-20- 101-=01-1 200012112= 22=21201=22 1-1212=1-=1 1212-==1=01 22==--= 1=-2-1-==020-10-= 1=1210=--00 1=--=1= 2010111-00111-2=2 11=21-0=2-01 21= 1=-0-220 102-=0 1=---0- 1-1122-=121222--0 10110=1-20--1-1 20=--21220-= 1=---22- 2-000===1101= 20- 10== ================================================ FILE: exm/aoc/2022/aoc_2022_25_question.txt ================================================ --- Day 25: Full of Hot Air --- As the expedition finally reaches the extraction point, several large hot air balloons drift down to meet you. Crews quickly start unloading the equipment the balloons brought: many hot air balloon kits, some fuel tanks, and a fuel heating machine. The fuel heating machine is a new addition to the process. When this mountain was a volcano, the ambient temperature was more reasonable; now, it's so cold that the fuel won't work at all without being warmed up first. The Elves, seemingly in an attempt to make the new machine feel welcome, have already attached a pair of googly eyes and started calling it "Bob". To heat the fuel, Bob needs to know the total amount of fuel that will be processed ahead of time so it can correctly calibrate heat output and flow rate. This amount is simply the sum of the fuel requirements of all of the hot air balloons, and those fuel requirements are even listed clearly on the side of each hot air balloon's burner. You assume the Elves will have no trouble adding up some numbers and are about to go back to figuring out which balloon is yours when you get a tap on the shoulder. Apparently, the fuel requirements use numbers written in a format the Elves don't recognize; predictably, they'd like your help deciphering them. You make a list of all of the fuel requirements (your puzzle input), but you don't recognize the number format either. For example: 1=-0-2 12111 2=0= 21 2=01 111 20012 112 1=-1= 1-12 12 1= 122 Fortunately, Bob is labeled with a support phone number. Not to be deterred, you call and ask for help. "That's right, just supply the fuel amount to the-- oh, for more than one burner? No problem, you just need to add together our Special Numeral-Analogue Fuel Units. Patent pending! They're way better than normal numbers for--" You mention that it's quite cold up here and ask if they can skip ahead. "Okay, our Special Numeral-Analogue Fuel Units - SNAFU for short - are sort of like normal numbers. You know how starting on the right, normal numbers have a ones place, a tens place, a hundreds place, and so on, where the digit in each place tells you how many of that value you have?" "SNAFU works the same way, except it uses powers of five instead of ten. Starting from the right, you have a ones place, a fives place, a twenty-fives place, a one-hundred-and-twenty-fives place, and so on. It's that easy!" You ask why some of the digits look like - or = instead of "digits". "You know, I never did ask the engineers why they did that. Instead of using digits four through zero, the digits are 2, 1, 0, minus (written -), and double-minus (written =). Minus is worth -1, and double-minus is worth -2." "So, because ten (in normal numbers) is two fives and no ones, in SNAFU it is written 20. Since eight (in normal numbers) is two fives minus two ones, it is written 2=." "You can do it the other direction, too. Say you have the SNAFU number 2=-01. That's 2 in the 625s place, = (double-minus) in the 125s place, - (minus) in the 25s place, 0 in the 5s place, and 1 in the 1s place. (2 times 625) plus (-2 times 125) plus (-1 times 25) plus (0 times 5) plus (1 times 1). That's 1250 plus -250 plus -25 plus 0 plus 1. 976!" "I see here that you're connected via our premium uplink service, so I'll transmit our handy SNAFU brochure to you now. Did you need anything else?" You ask if the fuel will even work in these temperatures. "Wait, it's how cold? There's no way the fuel - or any fuel - would work in those conditions! There are only a few places in the-- where did you say you are again?" Just then, you notice one of the Elves pour a few drops from a snowflake-shaped container into one of the fuel tanks, thank the support representative for their time, and disconnect the call. The SNAFU brochure contains a few more examples of decimal ("normal") numbers and their SNAFU counterparts: Decimal SNAFU 1 1 2 2 3 1= 4 1- 5 10 6 11 7 12 8 2= 9 2- 10 20 15 1=0 20 1-0 2022 1=11-2 12345 1-0---0 314159265 1121-1110-1=0 Based on this process, the SNAFU numbers in the example above can be converted to decimal numbers as follows: SNAFU Decimal 1=-0-2 1747 12111 906 2=0= 198 21 11 2=01 201 111 31 20012 1257 112 32 1=-1= 353 1-12 107 12 7 1= 3 122 37 In decimal, the sum of these numbers is 4890. As you go to input this number on Bob's console, you discover that some buttons you expected are missing. Instead, you are met with buttons labeled =, -, 0, 1, and 2. Bob needs the input value expressed as a SNAFU number, not in decimal. Reversing the process, you can determine that for the decimal number 4890, the SNAFU number you need to supply to Bob's console is 2=-1=0. The Elves are starting to get cold. What SNAFU number do you supply to Bob's console? ================================================ FILE: exm/aoc/2022/aoc_2022_xx.adb ================================================ -- Solution to Advent of Code 2022, Day $$ ------------------------------------------- -- $ puzzle title here! -- -- https://adventofcode.com/2022/day/$ -- Copy of questions in: aoc_2022_$$_questions.txt with AoC_Toolbox; -- For building this program with "full Ada", -- files hat*.ad* are in ../../../src -- See also the GNAT project file aoc_2022.gpr . with HAT; -- -- Interfaces is needed for compiling on both -- -- HAC and GNAT (64-bit integer: Integer_64): -- with Interfaces; procedure AoC_2022_XX is -- use HAT, Interfaces; use AoC_Toolbox, HAT; verbosity_level : constant Natural := 0; c, sep : Character; asm : String (1 .. 3); i : Integer; f : File_Type; s : VString; bits : constant := 5; subtype Bit_Range is Integer range 1 .. bits; stat_ones : array (Bit_Range) of Natural; type Set is array (Character) of Boolean; group : array (0 .. 2) of Set; procedure Reset is begin for i in group'Range loop for c in Character loop group (i)(c) := False; end loop; end loop; end Reset; type Storage is array (1 .. 100) of Character; type Stack is record top : Natural; s : Storage; end record; sT : array (1 .. 9) of Stack; -- subtype Range_x is Integer range 0 .. 500; subtype Range_y is Integer range 0 .. 500; lowest, highest : Point; procedure Adapt_Lowest_Value_Point (using : Point) is begin lowest.x := Min (lowest.x, using.x); lowest.y := Min (lowest.y, using.y); end Adapt_Lowest_Value_Point; procedure Adapt_Highest_Value_Point (using : Point) is begin highest.x := Max (highest.x, using.x); highest.y := Max (highest.y, using.y); end Adapt_Highest_Value_Point; map : array (Range_x, Range_y) of Character; procedure Show is begin for y in lowest.y .. highest.y loop -- y axis appears top -> down. for x in lowest.x .. highest.x loop Put (map (x, y)); end loop; New_Line; end loop; end Show; procedure Clear is begin for y in Range_y loop for x in Range_x loop map (x, y) := ' '; end loop; end loop; end Clear; T0 : constant Time := Clock; r : array (Part_Type) of Integer; begin r (part_1) := 0; r (part_2) := 0; Parts : for part in part_1 .. part_1 loop Clear; lowest.x := 1; lowest.y := 0; highest.x := 1; highest.y := 0; Open (f, "mini.txt"); -- "input.txt"); -- aoc_2022_$$.txt Read_Data : while not End_Of_File (f) loop Get (f, asm); Get (f, i); Get (f, sep); Get (f, c); Get (f, sep); Get_Line (f, s); end loop Read_Data; Close (f); if verbosity_level > 0 then Put_Line (+"bzz bzz "); end if; r (part) := 0; end loop Parts; if Argument_Count >= 2 then -- Compiler test mode. if r (part_1) /= Integer'Value (To_String (Argument (1))) or r (part_2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: bla bla:" & r (part_1)'Image); Put_Line (+"Part 2: bli bli:" & r (part_2)'Image); -- Part 1: validated by AoC: -- Part 2: validated by AoC: end if; end AoC_2022_XX; ================================================ FILE: exm/aoc/2022/gen_jumbo_day_1.adb ================================================ -- Translation of gen_jumbo_day1.py: -- -- import random -- random.seed(42) -- -- with open('day1_jumbo', 'w') as fd: -- for i in range(10_000_000): -- for j in range(random.randint(3, 10)): -- fd.write(str(random.randint(1, 8) * 1000) + '\n') -- fd.write('\n') with HAT; procedure Gen_Jumbo_Day_1 is use HAT; fd : File_Type; begin Random_Seed (42); Create (fd, "day1_jumbo.txt"); for i in 1 .. 10_000_000 loop for j in 1 .. 3 + Rand (7) loop Put_Line (fd, (1 + Rand (7)) * 1000, 0); end loop; New_Line (fd); end loop; Close (fd); end Gen_Jumbo_Day_1; ================================================ FILE: exm/aoc/2023/aoc_2023.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the Advent of Code 2023 examples. -- -- Some programs work with both HAC and "full Ada" compilers like, -- GNAT some (titled *_full_ada.adb) work only with "full Ada". -- project AoC_2023 is for Source_Dirs use (".", "..", -- For the AoC_Toolbox package "../../../src"); -- GNAT's access to the HAT package. for Exec_Dir use "."; for Create_Missing_Dirs use "True"; type AoC_Build_Mode_Type is ("Debug", "Fast", "Fast_Unchecked"); AoC_Build_Mode : AoC_Build_Mode_Type := external ("AoC_Build_Mode", "Debug"); type AoC_Styles_Checks_Type is ("Level_0", "Level_1", "Level_2"); AoC_Styles_Checks : AoC_Styles_Checks_Type := external ("AoC_Styles_Checks", "Level_1"); for Main use ("aoc_2023_25.adb", "aoc_2023_24.adb", "aoc_2023_23.adb", "aoc_2023_22.adb", "aoc_2023_21.adb", "aoc_2023_20.adb", "aoc_2023_19.adb", "aoc_2023_18.adb", "aoc_2023_17.adb", "aoc_2023_16.adb", "aoc_2023_15.adb", "aoc_2023_14.adb", "aoc_2023_13.adb", "aoc_2023_12.adb", "aoc_2023_11.adb", "aoc_2023_10.adb", "aoc_2023_09.adb", "aoc_2023_08.adb", "aoc_2023_07.adb", "aoc_2023_06.adb", "aoc_2023_05.adb", "aoc_2023_04.adb", "aoc_2023_03.adb", "aoc_2023_02.adb", "aoc_2023_01.adb"); case AoC_Build_Mode is when "Debug" => for Object_Dir use "obj_debug"; when "Fast" => for Object_Dir use "obj_fast"; when "Fast_Unchecked" => for Object_Dir use "obj_fast_unchecked"; end case; Common_Compiler_Options := ("-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatwCijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ"); -- Don't quit, write ali/tree file even if compile errors Style_Checks_1 := ("-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens -- "-gnatye", -- Style: check e:end/exit labels present "-gnatytc"); -- Style: check t:token separation rules, c:comment format (two spaces) Style_Checks_2 := ("-gnatye", -- Style: check e:end/exit labels present "-gnaty2"); -- Style: check indentation case AoC_Styles_Checks is when "Level_0" => null; when "Level_1" => Common_Compiler_Options := Common_Compiler_Options & Style_Checks_1; when "Level_2" => Common_Compiler_Options := Common_Compiler_Options & Style_Checks_1 & Style_Checks_2; end case; Fast_Options := ("-Ofast", "-gnatn", "-ffunction-sections"); Fast_Unchecked_Options := ("-Ofast", "-gnatpn", "-ffunction-sections"); Debug_Options := ( -- "-gnateV", -- Validity check for parameters, GNAT > 4.6, redundant with -gnatVim ? "-gnatVa", -- Turn on all validity checking options "-gnato", -- Enable overflow checking in STRICT (-gnato1) mode "-g", "-fno-inline", "-fstack-check" ); package Compiler is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Compiler_Options & Debug_Options ; when "Fast" => for Default_Switches ("ada") use Common_Compiler_Options & Fast_Options; when "Fast_Unchecked" => for Default_Switches ("ada") use Common_Compiler_Options & Fast_Unchecked_Options; end case; end Compiler; Common_Linker_Options := ("-g", "-Xlinker", "--stack=0x20000000,0x200000"); -- ^ Absent that, GNAT-compiled programs using lots of recursion -- die with error code 16#C0000005# (Windows, Access Violation) -- - no Ada exception, no trace-back... package Linker is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Linker_Options; when "Fast" | "Fast_Unchecked" => for Default_Switches ("ada") use Common_Linker_Options & ("-s", "-Wl,--gc-sections"); end case; end Linker; package Binder is -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks for Default_Switches ("ada") use ("-Es"); end Binder; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-j0"); end Builder; end AoC_2023; ================================================ FILE: exm/aoc/2023/aoc_2023_01.adb ================================================ -- Solution to Advent of Code 2023, Day 1 ------------------------------------------ -- Trebuchet?! -- -- https://adventofcode.com/2023/day/1 -- Copy of questions in: aoc_2023_01_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_01 is use AoC_Toolbox, HAT; -- total : array (Part_Type) of Natural; -- procedure Read_Data is -- input : constant VString := +"mini.txt"; input : constant VString := +"aoc_2023_01.txt"; -- c : Character; f : File_Type; s : VString; first_digit : array (Part_Type) of Boolean; n1p, n2p : array (Part_Type) of Digit_Type; procedure Test_Word (pos : Positive; n : Digit_Type) is res : Integer := -1; begin case n is when 0 => if Index (s, "zero", pos) = pos then res := n; end if; when 1 => if Index (s, "one", pos) = pos then res := n; end if; when 2 => if Index (s, "two", pos) = pos then res := n; end if; when 3 => if Index (s, "three", pos) = pos then res := n; end if; when 4 => if Index (s, "four", pos) = pos then res := n; end if; when 5 => if Index (s, "five", pos) = pos then res := n; end if; when 6 => if Index (s, "six", pos) = pos then res := n; end if; when 7 => if Index (s, "seven", pos) = pos then res := n; end if; when 8 => if Index (s, "eight", pos) = pos then res := n; end if; when 9 => if Index (s, "nine", pos) = pos then res := n; end if; end case; if res >= 0 then n2p (part_2) := res; if first_digit (part_2) then n1p (part_2) := n2p (part_2); first_digit (part_2) := False; end if; end if; end Test_Word; procedure Process_Digit (n : Digit_Type) is begin for part in Part_Type loop if first_digit (part) then n1p (part) := n; first_digit (part) := False; end if; n2p (part) := n; end loop; end Process_Digit; begin for part in Part_Type loop total (part) := 0; end loop; Open (f, input); while not End_Of_File (f) loop for part in Part_Type loop first_digit (part) := True; end loop; Get_Line (f, s); for i in 1 .. Length (s) loop c := Element (s, i); case c is when '0' .. '9' => Process_Digit (Ord (c) - Ord ('0')); when 'z' => Test_Word (i, 0); when 'o' => Test_Word (i, 1); when 't' => Test_Word (i, 2); Test_Word (i, 3); when 'f' => Test_Word (i, 4); Test_Word (i, 5); when 's' => Test_Word (i, 6); Test_Word (i, 7); when 'e' => Test_Word (i, 8); when 'n' => Test_Word (i, 9); when others => null; end case; end loop; for part in Part_Type loop total (part) := total (part) + 10 * n1p (part) + n2p (part); end loop; end loop; Close (f); end Read_Data; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; if compiler_test_mode then if total (part_1) /= Integer_Value (Argument (1)) or total (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & total (part_1)); Put_Line (+"Part 2: " & total (part_2)); -- Part 1: validated by AoC: 52974 -- Part 2: validated by AoC: 53340 end if; end AoC_2023_01; ================================================ FILE: exm/aoc/2023/aoc_2023_01.txt ================================================ two934seven1 8825eightknfv sevenoneqbfzntsix55 foursqpqvv192rdrbtcccfourone 9jpzhpxqthreelmrnlhfqmn4 onedpsckg3xdhmgtsixthreefivejlncszkxeight 4twofour 7eighttwo17fournsmrznntgjrdpkdjvx 573 ninethree3 3gngzkpkgrf qeightwo2xjvfkfiveone twoonej26 sgoneightfoureight5sevenjzsqghg bnrb36xtjd7four9 threepprhsff3prbpfivesevenseven4 38sevennineninemnfzklttkxnine3 8mllzkfqklhonefivemv4 onedcqlqcrzn66three 1fourjthreefc2gbtbdzsix eight7two4258 4hmfzdzf 26dsmdzznm7 plckvxznnineh34eight2 dhrvd4eightgxznhqmh 5fxhhkghvm3nineshpcxhtwo6fourhrktpbq qklhmhmdlgeighttwoonetwo52five 86threemmpchhzdvsvxfzrj 9clvchpgrslnkhdmfkjmlrvgnf 8ncpdtspfivethree gtbtkqcgvh8945 sevencrkbt3btljpdpgstlf 8nine37bpkmtghhnc2hnreightwohvs 5qxmsrthreempcmpdcnnv41 8threezrxhxgx4g jhsb3onep1 eight71rnz 7p16lrxktlr6 8one5fivelvdbjzz 1nine2twodhnineonesixkqfcbgdlfg four8sixfourfive pjdmt4one8sdsdhhqxlqgzpk6qrtdvxm sixzfourkdpmnn92qbjkjqfqpn 42threefiveh 5fhgzt8threemzhblb6 bbc3kxhvbfrn8four6five 91fknhthreefour six9fttmqpninethreevhgtrxklbvxbljsp1 four5five1471mtfv 3bjkggcntwo3ptmjhmthree7 four2eightone threedrzktlgbz4five dmpgttqfivekcdjbf49six 9bplkkgrxgjqjqb3seven 4861sx4six hjzmxtxvxkkpbvgpvmgb4two8bqxlvponesq lkxxtkctlphjfivepjlrg1 xszdbbvxjrfxs2vrmmbfourpzcfmgppk33eightwors 966fourflbfsk3 1bskshtjseven5qlbjhqgzhbzxvlxsvtcmmzseven 56two28cbhfsdcjsix2four 6s5qcmvjltqeightslhnzmvbfvcmxj twosevenjxk6lhrkknnkq kjkj2lkkldqbgzhglmthree9 ftxhnpms1onetwoxg2 three9sixsevenmrgggztckzgzv7 stvgmjgnine2vvsnjhlzkstwo5szsbvzjdzb v6 threetwolscvhrlmm3r two17kblkphfninefour6six1 one6fiveeight9sixjzljjfknrhkzxr dgpqm43xthreekxgspjzrzcsix 2two8fourpppb2 fiveseven5four 5rttwofivefnmbkn8nine2eight 43threeninelgnpzrdtbc1lbkjkvqrdcd 1seventx nctwonefourjzgskmxjmq2 rpzpht2tdxczzfthreeseven two1seven 6bjztkxhsixkgnkroneightht 9mqzkgmv4vxqrpf4 49hlj 46gv 75sixfddn75 eight87xzjkdpnnjjfqeight 9pfcdhxbcrnpsnmvkqnsqsninedgtlmmc5 xmfbn34 99lvrrndpqcnhznn qsmxhxfph24three lql25 8five1dhrkm twoninefourcxksqfmn1 7eightdclrvn one2seveneight3ninemcpnmonetwo 33fivefivenftbczsdstlxzbp 9r97five 5fivessskxvnt6qqbkkqrggxg9gsdtbptpn threesjdpjdkczjgthree6 twojqm86 bttrx15qfznmdncnz5 ppckphrtzhstd3xvthzrxxlrrjtk qkm6ckeight7gnmqkltz6jsrgjhbck zdjjjlpmjtphbjpm9threeskqrphxbfqqeightone konesix1three four24391rzxtffour hsevenfive36fqrbjpfj7 dxdcssixbcnp8two639 hnvg2 sixeighthmqkjjsix6tbvdhzone2vsn dfzlxq7pjmq5 5n3 twovjcgxdsdngt2smfxfqxeight ftpjlnvg5qshclfzqtc2eightninefivecsrgk zzgsjsjffpvcgfmjtnpkrsqlmpzlt9four 4btrhpznzr8oneightg pph2one 5seveneighteight 31sfrfrcgmseven four7bdqgrhfive3 nbrzbggpseven9prthjvknq 3sixonefourh fourgkrpkzdmhtwoseven6txplz four84ldbhnkxjph 6eightonesrb gnmckftk62jgsjxzpk bzctx9onetmcnzhxkrtchjgqxv66 1three5 27two 34eightwox 6ndgrbmfkfive2ksxfbnjbl7fkrm kxpz4gjmgcgzzq63five nfvmfrbc151one8nggsdqvm 4clnctseven5nsn5 hcrpbvqmmdbstlxccthkththreebm6 gdnmh6cslzhjhdl8nine sevenninethreefive4bgknpbnine 2sevent6three1 2jbrmdxgpnine7 nshlgtbkmcmgkmqone3 dklhc9sevenrxxzzxltsnlltqcjrbgprnx gmrjhlvzppmklnl39 kv86eight3dcdpp6pmdzcvsix fiveseven2sevensix6952 3xrtthnsevenjxsxpzvc 256nmzrlzbczv 4dp7onesixvpcf 25onesevenonexvnst4smvlfszcrv lcxncproneseven37five ninezjsrptfivenhsqxrdz7one cscdmnfrcxfqdtkmhkldgjlxdjqsxslhdzvvt4 sixfnjnfkqm67blkmnqtwo fivethree7 2five5ninegcmqbkpp61npkpml9 3qktrxninefour qdhmxstwo44two 21nine rbnineone3xppvtbmv3sevenvxkkgmgklg mcvzplmpvptwo38 sv176threeone 5vksixqsccgdkrrfourcgnpsfxbvj xxtwone6eight threeonespkbnsj9onesevenpz5 fivenncrfvhfdsevengxzkxbkrklgsfvllrkbx4 69kp1seven8dqkrx dmb9ccghdjjpjxfivehtwo4 6nhgdkpdone tfvqdqdqcszxbrdmmrninesct2 8sevenfour2eight8rskc cpmgffcvln9sjdsgfivesix5rppfsfmmqtffive 5two7 7threecrkljthreetwo 6qgqzsdhprd 959zgjscgtm fourtwoppfrdqgtseven9 8bbchvoneeightr gtddrb1rznsdjtonethree5four 8rrskfzlmlbrsninezdzpt3 6njhmkpp4onefive8two 4cqpnkcxjtwoqzqmjnqccfs256hcnqpfm nineeightseven62sixhlxlps dtqplzzf87threecthree mqptgzjxddxgxpjr5 9194jbjjktwofive five514foursevendzxlh2 6nineeight85zvx four8gsgrstfmdv99hpkfgptzqkhsmgsnlggrseven 9three298 3fpttzk35 rbtckzonexkqmfxrnsbsrkqbq66sixkcqfzjfour sixkdcrrrppcsix399fccnsbhfxvfiveft xfjxbfvmbxbf3twokkcfrbcfbmkmhghsbzf 9sixonesix3lqqf9 eight3fourgcmp xjccxkhkvgltzqslmseven5twoqhcmpsixeightnine 62eight8 hzhccdkxb336 gcsbmkdfmqvxtfj81 two445nine xhrkgql8six41nine1 5dnlcsjb jdqdg8gtgrctwo4fourthree five4five 3threecggvthjv6 sevenzrjzqhgtvtqvkp3three5sixhxdmfour 2249eight6 drt5trhdjqf3fourfourkfour4 5oneone1 threeseven5six 45bclsgsqx 6ggfjqls rhpmhfournrzg418onevlkcxxdrd fcvgszpsixthreegqqctvdqnfrbnlbmknlvgfour1 twoxvrhmxjbbn2eight 27eighteightsevensix6six veightwosix54bcvvtcgbqfzprp7four2 9kthreeqntgvbb34693 zxcdmfg48ftlhk 1mhcctbmbzmfivefourtwo3 two6vxsdfhgstslsix threesixmzhvfqsix5xhrhrvsfh7kpcrsp oneggkztrmsgrthree536three 7seveneight81ronesix sixllrjlqtffqvtdjqhctt66four3twoone 2zxqpgmgz 7rfngpqkqgfivetwojf vvbfnnine3ngv 59sixninelmhmqchlthkbpthree33 1three6seven1seven5qntpbnsfour 7nfzfsdxzfive8fjvllc4 56seven5seven 1fivegqbrdgths four32vmhvnk hvdjnmpqvqbnrcrclkgkrfseven6lgrvthv 28xngctrvmnc4ntvxhmxfsj13 onep1onecjjmxxtd 9eightwof hzgmtfdj8nine7seven eightseven3 fivepnhlninefive1lcftks 122ninelrgmdgmqzd zjsix3 7rffvg9hbjpx 3h76 fouronessbhxlcclkzmnnbksixlcdqtf3 4fivesix228five sixrlthree1bzhddfbkrgxpgxfivef dxgqnkqfgq8 onemcfourbmkhh5px fmtqjcbxznine3three qzkcxvnffg1gmhplhlffgtwo3onevg7five twokj7xv63six four58 fvjeightwosixrbrgnmrrmdtwomseven69seven 5fivefour 6pg8twomrqfzkxrthree9 7xqtqfrpprlvhnthree l35sevencreight4 threechpctdgtq8fxspqtnvggkxtmeighteighthdgngnmc one16twosix threetwofour3eight1pvgcthree 229 ngcnthreeone7hqbbntqxeightkgtc qtgkz1ntone68 nine2seven two1jjccnlrqlsdfvtgjmmhh5prfpcc onesixvtbjgdqmtg1eight 77qkvdszsp9ctqndxzrjc rnldvcmks74355 fourkljgznpqntwofoureightlc3zmljfnqnr 8threetbv6cdjjbtmmxcfour4qlqjql jfkvbvjxjzk7 7eight8vhsdrd onezdgffrmz2 eightseven8 7gjdsevenjsdkljn2fv kmst4 3five8smctrhdhfninelzbrszmbdm fiveseven4ninevdfive3 8jg6nine4jmmsbpbnskoneqxgjrphhf mgfourfour3hgmrzkntjm2hxrrfsghnone ninecqmg72 ldthtljblpl3fiveonervtxnxczfx2 9sevencsevennscmbjgthree 7lnj9four fgtwonexmkvkcgpq36sixsmfnxjs qgmfmnh6twoeight 56sqrseven 183877 ntt1seveneight513 7three6dzdrs 8sixsevenfour mzfhdnhseven4eightvjsdnxlonenfzlcxr sixzdczsbtq29one4eight6 jmxcbmktjzeight5fivenhtzfsdqbx four2rvlppone258 fivezvlqr236nine 262 58six2nineone5 twoeighttwo3ktzhmdvlx 64nsjgqsqkhfqmfk foursx18 gklzjvvv93zzmzgpn onenmcvr6 qsnmlbmlr6 sbtwonesevenfourhgltwofzhzmbsrfm6two 8fdhxeighttpcjkkmgsgnpnvsix2eighttwo 5pvxnxxdfourfour75 85vtsgkn1kfzkszmbld4cpgrqsfive sdbzkzp1dq5lk 28161twodfznxckr xfpgnrlfour61 kzkkp65qtqfppc7f9 twospplzdrdfvsixsnldtwotwo29six 9fpbm 3one83dlvdr 9rvbtwo25sixkzlxfkg9 8jbmfbfsxrnxk7oneninesix 3798 jhcqmfive9 nine35 596 nvzztnine2vhhchqkzfjzmkgjbzlxhvtdhddnr 5bltnjlmt12threenh2 eight5sevenninepgxvhflb4eightmxv xtrct7fournfivefourfive dhbpsnpxsglnt5vsnclxhnntt61two twoonekntsmsd81fourfourfive gpnceightdx5pklsp79x four5fszlnphhxvhgbmfcdkdbgbc7 xbxtjllpr9threeninesixbbtkn6 p7 nine644two5 5zzzlmspbcx9vfdllvqtl8five four2bxmrthree 7rhgfnzqbpgmpnfz threejhfmbmxzp469 74ninebmtpfkzbcg5nine fflpg34two25lvnmxvqlv jtqtnthxqflp2onesix39 9sevenninefd8qpfiveseven 28mb5 lflcphkxqqnzhd2five 3seven4fftnss ninezxhxqxxpblm9 4ninevgpmxxmqlf8 sevenfiveonesevenfjccpmnnninesix3nine qmkvt6pxbdcbrcsrgppzptzchkmone 2sixone 6dzskdbknpsix twonpqfsvbmqgeight23ct 4sevensxdzsfbmmmdrdjtpbh sxkpmmhsix9five7 fnxtgfrltwo67threepvbsixzvj 54jmvmdbkltqsixtmccscsixeight 6fivefourrbshbc82jrfm2 dhlpvhzhms6 419bhbcdsvftxfvvkxcxprksjs4 sqrq17nine 84rjcbktz8hrplcqsvhqqnnqnsevencjhone gkmljdk2dgrlptkxdsix3four599 cnjpf818sevennine 8cvg 3jqbbpfpxmpkrhfoursix 9zkrhbmzkbzlcnxlgdsixthree8 nine9kvxeight2zqvzhgjzjz fourbglmlqzgvzhjrmz2nzqxlqseven seven4five8nine44eight onegnine6 qeightwosixfivesevenzmjfrqvnsbnqlt7four eightvrshp9xnxlgqcnninegvbj ninelpbvs9three8ltzvxnd4 nmnlzone3grqbzcdnpxsbcbzxn4fjptnsrqsqgsdcv 18fourcqfive1gccxg gfglone6bqsqjmlftcqpqmmqmglskzfourvkhd9 5cxgkn1g 29seven9ppr fiverkmhxvnbp3lvpeight1one 77four5dsdqzvt gvvpbone23 twolrjs56one six2745six kbxplzpsixsevenseven5one3 threexzrcfgffkjsix9zgdseven56 onetrqcfl6 three23nine four2mv xzfnzkmeightthn6twotwoeightqmf hxxxldcvj99three5qgmllbtrsq 6zcszjbrzjpgrvfivemnzkpbq2six 6zvtsixone73three threeflxtwo5fivefhbjptgfjmgbhpmbjmsv 5nineeightfourd five26five7sixthree1three fzvsixsix3mxxhseven twoccxdqqkdvc2two9ps6threefour 447lkkoneonefour6rx 8seveneightwox sgjv21 soneightkmtps8onesixvpsdcfbbz 8pzrtoneffhg mmzeight631 5fonefive foursgx8fiveltczmccpzx sevensdbhnpmjninetwovlv1three 64qrjdtpxbxdbcqmmlqtnine6sevenfxhcrjnine 1seventhree ktmfour3 fournine8skzxtftwo9h9 bjq8 mrshhhzsixcxsxxmbh1bone9fivelsplqv 7threezvgxdvrthree7227 znnvfive5mctxdfive3j4 five2three8 gdtdqc9nine1 three3eightgnsxrmbmxld9six zsgmcpxxvseven7onetwoseven6 8n3919hfiveoneightf 3rfrzmlfsjxthreefour dnnshdvxdl6onendg27 66lpbz sevenlkjpxthree5 8clqlplvljone5hfh81 fourldvjsixfourfour5xrmcnf 9nine2 4one1 4vzjgncrztvstcf9one4 four37 4sixlqpnqxqtrhpc3 8threejzg znxccm8 one8eighteightkcvnqjpsp6nine fivesixgc74oneseventhreesix 5twohshtsdtqk2 hzmchfourvzjgnt2threetwo5cgfld one9three836one8nk ssslsdftjfgkpzkln5 xhsxxkzk1x2tzbjthsnsix 8nineeight3njq ninethree5eightbfour2 five56sixclxjqsjseven8eight three3cninenz lt3onevpkgsixsix 4pkbmgtwo6zmvn71eight7 2eight6cdd83 5kvp3zhzq vtcmdkkcmnmf1two nine2nponeoneseven xm1twofoursevenfoureight ggkvsljtddcmznlxlqb4one32oneightppn onehdq785 vzthreezjbdrlvhglbbcvlfk5 eight9smt1sixsevenckqxlbvdzone one7fdcbzjtfhbps9oneonetfftbneight 3sixfgqbsngnd1zmqbxfllbp roneight28one8fpzmkhvdhbqlrfive 4five2four453ttlvfqxb five2four413hhnts8six xlfpxbzrbphb3one eightone8nineeight 1zprfttxqmtbhzckcfoursix2threenine 7sixzqrjxn92pnbfxzbrnmvrnpjpdone pvlfeight1xkgrvczlcfvvl8kzcktkjbj four7phjzlzn3two3two9seven 1tkcdvdtj7nqfsrnmfzghmkrqeight 36fourxfdgrprrdgmjczxb five5fivefdkgnkfgd5 5seven5sxlkbldznz53three8tmkzlrt 8dkxkfvjkprxtjlh5tjvjm2glkpbmhjd seventwo3 bgssljzld2one5seventhree4 sixfourrqzdbdhhhc7lkxqbtsseven55 6threegtwo7fivesrbvfk 2mpxkrtjphdseven 14seven9dkk 85dmtjqkchp7two4 hvqfbchqhpbggrqhf4ps dzdknbdceight72fourcmfvsrzt xmvgjjfourfourmjmkh5onefive8 qdfreighteightninecdxrtdbd7 mxlhxlbvbndqfzmseven34four 432three5vqhmjzgvghnhhg ghczftpkttwo4sixoneone4brf kbbzcpsqsl7qdlgff5fourfive6jk v8nxzpjxntcbtwonrcgztsthree1eightpfdsp 7zjdzbnrpltfivemgcsjzrdjskhfmbgvlr5dl 9kpbzzr 8386six3mzh3 41nineeightfive twotwo5threebvgmmhqrlqltqmndhveightsix2 58drxrgkklm 8two48six3sixthtwo eight88msfnone87nine four5lvxfhktrconexqzqvl six8mrlccbeightonejnzbdkm4one oneseveneight366xzqmnmfvvrph joneight7nine7five 5fourtwo26onefivegsnbcjj cpjnvhnzxsevendbnblfkpx44lzn88 zfmdcsfkktwogxmrsbtwo2six78 ninetwo59foursevenoneightsx vjbbphb5dddvksevenpmnmtjvzdvxkkbcqxbb 9ccgtrznm4 zplpfivesixkjfdvrv6rfmqk hfxhpsxgxjfdbfmjb6one threethree9 six3seven seven286 bnkrghgbkzdz29two31 gvlzrhntvseven3 twosevengdkzgv6 rddtz12five9znvtsljztbztprthreeszkfhh nfivesevenhfpklnxqb4nineonermtfsk zzz2onegpthree4fdnqxrtcnh8 4xchnsevenxnkbrdpzsnine6 hveightwofourfive8 8one3 7chfpsbh1two two2eight5gchbxqvrmdfqvghtnjssix1 zfbeightwo3 qhjnfxpfoursix9five 8fourrbrrjqqph five5threethreezfvskmsv76 sixvtjnktt4 5cndcht2fivebdnxcnzzmfninenineqzktj qfzclldsvzvcdqfxhtqqtknine527 onefjrmmfqvgnxnjdtkdmk25zghnp hvddcjnoneeightnine9eight 9lxpszk 17fourfiverfnbmkrxlvone qxvdlrxq89vf qeightwotwo2 rzmxzgnzljzssnxscvv9seven2kbnineseven sevenseven8 rkhkone8four zn68 5pvfjmjxthreeninevtj88 51dtwo5ngvxnmjeightgbhzxbd two6kxkvscbxcg34six3 qbn1 hgxgtwoqtmsqbv3 threethreejmtjk18two sixone4fourseven6zcgpdqps fiveqptd8gtjfour1twothree 89fivefive4 sixvnvmdmfeightcbbvbrkffqstwo7 three4fivefive5klxvsbhslzsix29 two9sixhncrcvxmf rsp146 eight2jtvps 7four6 77p1znpskm bbdvfhqmxddlsvdpmtvctnine135 dlclxtkxk85bn bxbjslnrfk6 51zfrtvmcbkkrnd7 27fivetwobbssnklg twojxdksqkm9ninejninekcbdgnsq3 nineninebsbd8 sevensevenggddbfxqrmonethree744 srtbzcbsmfivetwothreejvzjzxqm1tjnjldcxnine nbsix32 25144spnmfvvj1dxpqmhsldk 5two4mrqnpxzs7foursevensevenr fourk9zszmnbvmkdrz lpqseven2seven hcjgtjcxh1dskx ssrnf2ninenine6ngbhfhdqsnine cz82jhmgn14cktblcl kxjzflkkbx53nine62one hbcnpbmfour1two ckjksxthree346pjtr ccslpmqnine27twodr cptwo5twoggmrjvl15eight 4vlktln5kqfsnvrbjbszqzclmnkxseventhreefive one2eightwopp 2sixsixone5 klvsngvv38tcxvhpdhh5 fivefllgljkdg9ndlkpbmgbrndqbpxqdk 7ppkvstbtnvseventhreessd1three9 threepnrcmb3 thrqrcmzpzt7nine1three jvgrqgbcshhlnqrl2vrlppxbnjfrdtwofbsdvt rnhninezxbrlmnlczqnneightsix9one ghvqdxkqqfthree17 dthreeseven2 rkxfthree7nmfive6 6vhnh 13brdgbrdsvthreethreerttfkr ninelgfdc7 88z9vzscqthkgnhmztjnhthreeseven 1nine3mtgrfive8nine1 thh5fivezfmtlsnvtdkfour34 26six6cbjdssevenq2tl gxxnhsxqvjcvssrbrhbst6sixvcchxstbpb1ppqdbx vninexhkjkmzvhfpvcd7ninezzldthree 2twozknrxvcsj 3193spfourxcbdnf 84six4vc1eightsix zljb46four6six sixfive2seven1 1fbmq9fourmhbzzkhctp6ninenine onefourtworckjqzhqseven5seven five973knlxmtmdone8prtqlsltwo 2ncgbgpq 3eightthreepknbcs58three6 6fivesrgqxhnzfouroneqpmgpmzgfoureight mphrj33five 8sixfives26sdscdjtpchmh four64mtlxmnsjbtdkpmf4 onefivenine9nine81two vfc9nqttbmbdkonegclxcgbxkx87t sqnzdrcs8sevensix6sixdjcmk6 7npppqmrmblzjqckk8fourbpxlbtwonine nbkklkvpl2smlqbh 37eighttwo17fh77 eight7ninekkbvtwo eight18cmzzdpgl5 sixdc17nine9ghzpdpnxcbxvztcrd fourfivelrmch54 jbqbpzxbbdfiveeight9jnzfdh5xfmhhrkrkds 146two6fourclmcllhl 222dqgtptqqn gvhninesevenfiveonefcvnlmfcvjvf5 9xgljlphcxeightfivehpdlfrmd1fmqhrnvbzboneightjd 8sf3five6eight zrprbc8 gqb6sixninerpsrpnlldteightgn 2jdlxzk hfrbqn4zbpxqb81tlfxgxdvzz91 qtdnxgmjjstlc1nndsnbbcdm6nine z7twonezp two17sevenljskthntjzxpkjrkc fivelvfive948 sninehxqlkmv7oneonedbdvztzgh8 2fourxcrkrcvn clh4four5htj hdkx4eighteightsix1kgtbb nlbsqhkltvmzs2njschfbmsl3fivensztjtwobxkfn fnrg3837five vxcldjmjxxcqntqcqnninefivestbbjvptfvkbr9onetwo 4six7two 8five5sevenslfqtblfiveone 26ninemhvqkjgcvflplncfsixtwo 7eight523 9fiveplfdp1qhqhj15t three3eightrzvccr4h 9vhmkkjfhtfjtwotwotkfvlhvs vxoneightczdfl4 3one2 threeeightfive2four gksfxtb4 1jjgdldklznbktwo59 761sxvprrzj2kxsmlmtpbqseven 681q 84ctsbf1six fivetwomfgplcfgfive7one1vgbz rfnqnnmsdcj6foureightfjfkphqpktwo 9vntpmfsevensevenfour 7zvchbn6two9five fourseven7 2lvtkkbhtjeightfour89 5nine5threemgsd 933nxone5threeone 2dtbbmghgxvkmtvnlgsxjlgbc 1mcrlzhvzrc2 ftwonegsndgxmbzn6one 916vfvzvh8twolvhvlc34 dtk7eight6c6 kbhjg6qkdgh8rqlmstq4 eightseven8 bhlhcphznb92two q8d 375sevenvhrhkbtbvncmqqmpxdhqzzggvr 9onefour1nhmjb hqckpzrvgmgqjmvsrjhqx8twodgxkbh 5grdsbtp6onezrkdvpdqt2 tdgkr4 foureight24 ktds45zvjd eighttwo58lldklbmxn91fvlqllnxl threefive3bdmfbrhfklhxjvdgjxbp1 hqpfgvk56oneone8 two32fivetwo1nklfhjfffthree 77jggmjkbqone 6fckfqeight fivetwo8 7five7threethreeb twosvbzfmv1fourtwoeightsixfive ninehninebgjnknth5bhzqlvthree6 onefrdv3one1 five35 four3three3six9four55 xbssqpvjnine9six9threefivetwomjdvmpxrh ctroneighttwofive3npxgbhfsix1rjnl 8ckbzlmsbfxdn 51gckxqqbnkntmvx1ltfmdvnlcjnine eight7gkql5 sixjghxscppnfive23284 eight7pgqxvsix 46eightrjhgdmvf5 four4bmjzzjqp1rv523twonevm 3sixseven81oneeightwocr sixmmnqkrfplg7ztrpsixone4six 1sixfive5nhrq9 six8threeoneckbvqc9mzhb6nine 33sixdfzmds12jcvfour6 1cdlflvqhrkqpktdnnsx7six8eight7 8four18 tpfourvblonez8six fourone2smjpvclnine 99zdtdpbbvhnninefourvzfmzbscdldhxtcjfh fzjeightwoeightnineseven6 twonine2 fourseven1eight 2x3one qbjc1jtnbpdbr2six3 sglmt84five5nine sixnljjqh4foursix 4nxjgs79six lhkpzgzjr3z7 onefourflllxbtkpvgfive2 sixrdr1twoeight165 1dxvjdhzb76915 44pxzzttvdc185txvrpxq 4fourfgllhzfz nxssptkdldkpchnseven9522nine nine7fivefivefffvqpvsqzsvnvlzfvfs2seven bzphzhgf2xrlqjgonefour3bclmhtlzbmddrq vsxf7eightzzndgfourfour rqbhb14eightthreethreevkjzhjlkcmfive sbkrlm3nine zkzlqfbzscndtlmn14four9bsscd six33 1gbcgnpfnseven7plppdqone3smljtjlkhj 9jsmdjshtzm92stx9onesd 51four4two3one1 bxkpcpcntkflxccsixseven1threengtrrp 4dsdllkqnpxglbseight 7threetd3onefour 3vcnzndxfhfzvncfivefllrqvndtx964x nineeight1eightgqnzfhqkzgvfvctwo1 6fourthreeseveneight eighteighttrhtplssvjnnkkreight4sixoneseven 43hqrtctwotwo kcxfvhjksix3six2jbkrlmtwoseven 43sevenpvqh9eight7xcbvnckrkshdx sixfive3745three hmxfmzqdpfzjjzdxsix8472qcpbrsgx3 threelnzgs96five1 1dftdbtgjrpfive3cztvmxkcxh pmrfive4jxfxq1 eightclrzz981492 mscl2eight3 twovb8four7sevenfourkmzpdmpgxj 59onefourxnmptgtcone 6gsvxlbqspvzpsq eightthreesixtworcmpjkfvnsevenseven1six ghmflkhprkthsix9 441fourfcvxonefourhg5 four795seven tone11 22seven9two 5seventwo2 fiveone6h 936sevensixnine1lkp 62kvhcg six19 td25 9two2four4fourmeight one6twosevencrthreeseven97 1kttqbqkzvvr7265six 65rzmfpfqjtzb11m1eight seven1rrhpxjqtp plktlvxkpkndhx66fivefivexkh tttwonefournine9oneonesplmp5d gkbl1fbn3two97onetwo 1seventqngll dqfiverscjjrk7 4sixfour4onethreecvbj 24x6qhgtsxtrfh h6 fourfour3three 8hrdbnvxgndthhpmrgm ggzjfour8pxdlpx rnsixnine9fivensxfzzgzlseven sqzseven7 rcpkzht5 jxhtrkzl7eight3eightn68eight eightfive24 kgxv7kclnsscsmqtnmv foursix2chgckldprp3zqntzscxfc sixsixfourone3tnbpxbmgqccncgxxnine oneeightkgsbdthreefivepvrsktvhrnine5s 4vtpzghfsj 7four1lttzxpzcbtqqdthreek five76 vlqvvdhhnfzfssvthree3ccsdjhgc3seven 2nine8six lddxjsczqkd26g5jpvdlfour 1twotwofcl sltfz55knrfvhhbbeightsevenninesevenfour 27155bvv dxjzmftwo2vnljlsthree3three twoqdpzhjhbzksix49dhdfq three2fivenineqbxkgfivefour qnpsfq8twoonevsjffive9 gqvvmhxgx6gdsqmgccrmzrzltwo81szbnbkxt 2one1czgjvtcgxfivenqsfourthreethree ppcspzrnnssvnht9hdfoursix mmqrzdkmt7sjqgsrq9rhxpgpsixgkjflnht 57foursixfive4fourfive tjrfj3qldspjklvdtcb6ninefivejmbntcthree cgjnhsixsixsixfive7 eightqdqgjppcfive7fivexznfsmtk fivefive864scrf six95five17threeslktfgd 77mrrjzc1cbnkxfkxcdmxsmtwonet sxmsjccjrseven45 kjpsn1eightccctxthreevvffseveneighttwo 5twoneqr 3threemvlqpvhdqgtqseight jqrxrqlz93ninesmppvdhtxk5five8 threesixsntqreight593nine9 fouroneznpfive6qmn8 eightfive3sixxrrjgzlb gds345twotwotnjrnhjxdz 27nprk7 eight1three2onefourcfctvmhnqlfour 1fourvjgkpdrsj4kd2ncd nine85ncsqbrmdtxbtrjxgztq twonineeightonerdnkjkrbpsbzcpone5 nine8lkkvxfvlsixseven 49three9 jqmzthzjjseven5 seventwo9z7four5twohstlzjx bzvbvsix7 2five4 fourthreesevenfour2nine1fivezspphbmjv 7skjhonejhklktvzjflnineonemmgvnnine pmgxshqpjhn9qptllp 2nine5 fourqpzjrtttssthsxsq1jkrlnkk eight53njhcfhbjfthree3ksgrrj cgmvkqlcgzgfqxmgkfdzxxnxjgsd6eighttvggmfbdvztwo onefour8txkkpvfourzbhpsnrzleightseveng 49z2six591one 768five xgkfonethreexnlcptbgxhnine4fivetwosix 6ghccxxjponelmxeight4 3ninedlkvcbfmd2ktmjxsgdgr 3threefourxcgnxhkqkjbdzb 49eight44rlhg83gktmtm fnbnnpvcthrsjxnqdn9 ldrfhknine3394lgvseightwoj zmpsc3lzlkmqjc5eightthree llpmmfsmt8llknhrn onedvc3sixxx9four 148eightq6 95one9sevenfourfour79 one9eight78gnrthxbn 95xzzlpjzqdtonezfntwo6sixf eight1sevenn8bgnmnxbmdk 1sixseventhree2 twogjprzznd9sixsevencpfbh1 gnbtwomtltppkxxtwonlfxsbzjtt4bjlfxlqhlx three5oneoneqd3bcjgl pzngtc2four4811 nnlqscgg8nine7vst4three fourcdqc7vvqhpgqlkjsevenfivefiveseven 5sixtwo9sixqmxxgjvjqjtworlzpv 6dkknsmfmnq 2two74five7 four3vvfskp qqvpdttrfiveseven6 tbgeight8eightsix976 sevenninetwo3jdone three6seven7nine82 fxffmkjn2sevensix 5xzbf4bjqfrfourpjhscxz 5eighttwoeight7fivex1bnfpr 1j3262 two1fvxchkcdtqctph vgnrqn4three plzrk3tmqpxnhpkq6four four5eightone6threedbnjkvjvzxl bxcqcdnjjsz66gnxbhcct2nfhqlbs twovvqb9pxrxkmflzqeight 86 eight9eightsevenone2 dclk16seven lzs15four 265ninetzpnbxzllkq ttldqsnineffpplcxmbvknkmtdbzlsix7sbkvqhn77 eightgxzcjvgmtgzc9gndqxbxnsktvp mpqxldjnfive1pzvxbqqtwonine gzbczdrqkmtm3lzrhnf mlbsfqvrrtcrvhjjbs5 fiveljrcn27 bvnxlsfmv6eightnine3rhsb five5five eight31zztkhrznmkbx2kvzl4eight fvccqgfzsqfour453125frz xxf5threefourtq58 stvfjpj1ggnzgcfzldd2hbxmbgtftpskbtqmgv 11cbcps6 dltxch6onenzsmqbfn4onezkdntjzpc4 4eightthreej7lpqbvzz sevenlgonexmrmtfhqpfourp7 hjjdgtldrfivednsfdnmn24vtqgxk 41tnjbxk2gghb 2eightwotg eightkvhkzfivesixtcnpsxssvveight2 59dnmmpone6mzqlnf8dvnone kfvqrgv87trlninedf 85bnxlhdrmjt zvzxt4pzlnbb jfour6lpvvvbdn76tbblfqtwo lnqpscgkone1 mcnfzmvzkxp1 threeseven9onepvqhgdxcxmhtkxxvlhqrnine sixrzrjcmbpppcvf1bvbhblrmz 6tzthree7sevenlm9 four3gkqrmpgnjltwo threetctttrh3 ctcfljkgm7bcphzxzjj7sb43zdkvkddktwo sixzjkxlfourhqtwonbslgpt9vljz1 sgz5 vrrfjbjpsevenzbqcnthreelhxjqmdd2 sfmjnbnnpvthreedbsh7six5 twovdjqdtrxg5 nineeight7five 4xlpdvlvonekqmqvcqjsevennsd fiveblbxxjcbhxvnkfd9one7twoninebj xdxp54sixseventwo onefive7 ppgsqgjfourfourfivegtbrlkdvs1jl twotwoeight6sqlmffdm2three cvszcvq8eight 79three 44fivembtdfivetwones zqkthreefoureightthreethree2five 74twotwo six6fnjz1plxb19 mkfj72nine seven1nine5fourqsgrj 5fntdgbzkjfhxlqrzcq7 six9lgddrhjc9 1zfzp7 2lmncxvxbbsix7jbjrjsnvx1nine 6eightseven3 5vsqhnone xoneight3j 1gxvbbhfdmsthxgrvnm sixthreeone13 2three8bzbbd 3dsix1 24kmxnlpqxgpsevenfoursixfour fqpzqphmczcvlf2mxqvxnfqxthreeone eight789eightnhsh67 zznxlmhgr3eight beightwolgnb4997fgx35dt four1dsgpfzltwo57threefivetwo xnjjvmlkkgsht99 1sixhhqkx9 eightdhmgqjflthone44eight 9ftzbdsdkd9plrrtwo vhbvd8h txxonemsfshdrpc15onefive1four qgbd4eightrqxlznbjqxmxgmbrnvh7jkd eighteighttwofive5jsqkgm 89hn 3lzfjpcthreeonenine hkpc2sixdfldx1 3two72jbxttzfcv mmkjmmlvcxxvtwo25nine2 8751gphkmsvsjhvkzfc one8kmcktvzgdninegkl twokpxphkbjctqdcvf63one3prfive twotsxhbppfjcpkdfourfiveseven8sixn 3fouronebnclssixfour6eight cmdgcsix1 2eighttdqsjdrtwolmvpxqgxhd5five one7ninefivesevenqvpf5xmccsseven 2n7xbptnkxzcninedhhpdcsqkc 5n 1kfv4821 pslpmthreethreeone29tlmgj sixsevenlhn1 nine9twoqrdgdxxfsevenmjseven rkrdlnjknine62 f3 6zzrfxdxseventhree 265one seven3lbcvjxqhhdpzkttqsixjzzjjbclfq1fiveeightwojx seightwoone8qxcfgszninesvfcnxc68 strqnb5eightbpnkcjdz6 fiveninebtpbpjqbgx2bmjrgmprnd sixgtxr2fourrdkjg fivebxsevensixone872dlx ================================================ FILE: exm/aoc/2023/aoc_2023_01_questions.txt ================================================ --- Day 1: Trebuchet?! --- Something is wrong with global snow production, and you've been selected to take a look. The Elves have even given you a map; on it, they've used stars to mark the top fifty locations that are likely to be having problems. You've been doing this long enough to know that to restore snow operations, you need to check all fifty stars by December 25th. Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck! You try to ask why they can't just use a weather machine ("not powerful enough") and where they're even sending you ("the sky") and why your map looks mostly blank ("you sure ask a lot of questions") and hang on did you just say the sky ("of course, where do you think snow comes from") when you realize that the Elves are already loading you into a trebuchet ("please hold still, we need to strap you in"). As they're making the final adjustments, they discover that their calibration document (your puzzle input) has been amended by a very young Elf who was apparently just excited to show off her art skills. Consequently, the Elves are having trouble reading the values on the document. The newly-improved calibration document consists of lines of text; each line originally contained a specific calibration value that the Elves now need to recover. On each line, the calibration value can be found by combining the first digit and the last digit (in that order) to form a single two-digit number. For example: 1abc2 pqr3stu8vwx a1b2c3d4e5f treb7uchet In this example, the calibration values of these four lines are 12, 38, 15, and 77. Adding these together produces 142. Consider your entire calibration document. What is the sum of all of the calibration values? --- Part Two --- Your calculation isn't quite right. It looks like some of the digits are actually spelled out with letters: one, two, three, four, five, six, seven, eight, and nine also count as valid "digits". Equipped with this new information, you now need to find the real first and last digit on each line. For example: two1nine eightwothree abcone2threexyz xtwone3four 4nineeightseven2 zoneight234 7pqrstsixteen In this example, the calibration values are 29, 83, 13, 24, 42, 14, and 76. Adding these together produces 281. What is the sum of all of the calibration values? ================================================ FILE: exm/aoc/2023/aoc_2023_02.adb ================================================ -- Solution to Advent of Code 2023, Day 2 ------------------------------------------ -- Cube Conundrum -- -- https://adventofcode.com/2023/day/2 -- Copy of questions in: aoc_2023_02_questions.txt -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_02 is use HAT; r : array (1 .. 2) of Integer; procedure Read_Data is input : constant VString := +"aoc_2023_02.txt"; -- c, sep : Character; game : String (1 .. 4); -- The string "Game". id, n : Integer; f : File_Type; s : VString; valid : Boolean; max_r, max_g, max_b : Integer; begin Open (f, input); while not End_Of_File (f) loop valid := True; max_r := 0; max_g := 0; max_b := 0; Get (f, game); Get (f, id); Get (f, sep); while not (End_Of_File (f) or else End_Of_Line (f)) loop Get (f, n); Get (f, sep); s := +""; while not End_Of_Line (f) loop Get (f, c); exit when c = ',' or c = ';'; s := s & c; end loop; if s = "red" then valid := valid and n <= 12; max_r := Max (max_r, n); elsif s = "green" then valid := valid and n <= 13; max_g := Max (max_g, n); elsif s = "blue" then valid := valid and n <= 14; max_b := Max (max_b, n); end if; end loop; if valid then r (1) := r (1) + id; end if; r (2) := r (2) + max_r * max_g * max_b; end loop; Close (f); end Read_Data; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (1) := 0; r (2) := 0; Read_Data; if compiler_test_mode then if r (1) /= Integer_Value (Argument (1)) or r (2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (1)); Put_Line (+"Part 2: " & r (2)); -- Part 1: validated by AoC: 2176 -- Part 2: validated by AoC: 63700 end if; end AoC_2023_02; ================================================ FILE: exm/aoc/2023/aoc_2023_02.txt ================================================ Game 1; 4 green, 2 blue; 1 red, 1 blue, 4 green; 3 green, 4 blue, 1 red; 7 green, 2 blue, 4 red; 3 red, 7 green; 3 red, 3 green Game 2; 1 blue, 11 red, 1 green; 3 blue, 2 red, 4 green; 11 red, 2 green, 2 blue; 13 green, 5 red, 1 blue; 4 green, 8 red, 3 blue Game 3; 9 red, 2 blue; 4 blue, 2 green, 1 red; 7 red, 4 blue, 3 green; 3 blue, 6 red; 9 blue, 4 red; 3 red Game 4; 5 blue, 11 green, 3 red; 6 green, 3 blue, 7 red; 17 blue, 9 green; 1 red, 5 blue, 3 green; 6 red, 7 blue, 4 green Game 5; 3 green, 7 blue, 7 red; 6 green, 3 red, 4 blue; 7 blue, 4 red Game 6; 1 green, 3 blue; 2 blue, 9 red; 2 green, 13 blue, 11 red; 7 red, 12 blue, 1 green Game 7; 2 blue, 6 red, 12 green; 7 red, 8 blue, 6 green; 7 blue, 3 green, 7 red; 5 blue, 9 green, 13 red Game 8; 13 blue, 1 green; 3 red, 9 blue; 3 red, 4 blue; 2 red, 3 blue, 1 green; 1 green, 15 blue, 4 red Game 9; 1 green, 5 blue, 11 red; 2 red, 1 blue; 2 red, 5 blue Game 10; 8 red, 20 green; 12 green, 1 red, 2 blue; 5 red, 3 blue, 7 green; 4 red, 19 green, 6 blue; 3 blue, 4 red, 14 green; 9 red, 15 green Game 11; 7 green, 4 blue, 14 red; 7 red, 8 green; 6 blue, 6 red; 5 blue, 10 red, 11 green; 12 red, 2 green Game 12; 4 blue, 5 green, 8 red; 2 green, 4 blue, 7 red; 4 blue, 3 green, 2 red; 2 red, 4 green Game 13; 7 blue, 8 red; 5 green, 15 blue, 2 red; 7 green, 3 blue, 12 red Game 14; 4 green, 16 red; 6 red, 2 green; 5 red, 1 blue, 3 green; 1 blue, 1 red, 2 green Game 15; 3 green; 2 blue, 1 red, 2 green; 6 blue; 3 blue, 1 red, 2 green; 2 red, 1 green Game 16; 13 green, 3 red; 9 green, 1 blue; 4 blue, 1 red, 18 green; 2 red, 3 blue, 7 green; 17 green, 2 red, 3 blue; 12 green, 2 red Game 17; 2 blue, 4 green, 3 red; 2 red, 5 green, 11 blue; 5 green, 15 blue, 2 red; 3 green, 13 blue; 6 blue, 2 green, 2 red; 8 blue, 1 red Game 18; 6 red, 4 green, 7 blue; 2 red, 3 green, 12 blue; 3 red, 6 blue, 6 green; 9 red, 10 blue; 6 green, 4 blue, 2 red; 12 red, 12 blue, 9 green Game 19; 3 blue, 2 red, 3 green; 16 red, 3 blue, 5 green; 2 red, 6 green; 3 green, 2 blue, 15 red; 2 blue, 13 red, 1 green Game 20; 2 blue; 1 green, 5 blue, 2 red; 3 blue, 2 red, 1 green; 1 red, 2 blue Game 21; 15 green, 13 blue, 4 red; 9 green, 6 red, 19 blue; 6 blue, 1 green, 1 red; 1 red, 11 green, 9 blue; 3 red, 14 green, 8 blue Game 22; 3 blue, 10 red, 1 green; 2 red, 6 green; 9 green, 3 blue, 4 red; 2 blue, 4 green Game 23; 5 red, 2 green, 5 blue; 4 green, 12 red, 2 blue; 3 green, 8 red, 4 blue Game 24; 1 green, 16 red, 3 blue; 10 red, 1 blue; 2 blue, 1 green, 7 red; 12 red, 1 green; 14 red, 1 green; 1 blue, 8 red, 1 green Game 25; 8 blue, 9 red, 6 green; 2 blue, 4 green, 8 red; 1 green, 9 blue, 2 red; 14 red, 4 blue Game 26; 4 blue, 3 green; 1 red, 3 blue; 6 red, 2 green, 6 blue; 5 green, 2 red; 5 blue, 5 green; 6 red, 1 blue Game 27; 6 green, 9 blue; 1 red, 6 green, 8 blue; 3 green, 1 blue, 1 red; 3 red, 4 blue; 2 red, 2 blue; 4 red, 3 green, 7 blue Game 28; 5 green, 2 blue; 5 blue; 1 red, 4 blue, 3 green; 1 green, 2 red Game 29; 1 green, 2 red, 4 blue; 1 green, 2 red, 1 blue; 9 red, 6 blue Game 30; 1 green, 1 red, 5 blue; 13 blue, 4 green, 2 red; 10 green, 11 blue; 9 green, 2 red, 12 blue Game 31; 4 red, 5 blue; 8 blue, 1 red, 1 green; 4 red, 5 green; 3 green; 9 blue, 2 red, 7 green Game 32; 5 blue, 4 red, 5 green; 10 red, 10 green, 5 blue; 10 red, 12 green, 6 blue; 8 red, 1 blue, 13 green; 6 green, 14 red, 2 blue Game 33; 9 green, 6 red, 4 blue; 1 red, 2 blue, 13 green; 4 red, 4 green, 5 blue Game 34; 1 blue, 1 red; 9 green, 14 red, 1 blue; 3 blue, 7 green Game 35; 1 red, 11 green, 5 blue; 1 red, 5 blue, 17 green; 19 green, 6 blue; 4 green, 7 blue; 10 blue, 7 green Game 36; 9 green, 6 blue, 4 red; 8 blue, 13 green, 1 red; 5 blue, 5 green; 15 green, 1 red Game 37; 1 green, 9 red, 1 blue; 14 green; 11 green, 6 red Game 38; 2 blue; 9 green, 1 blue, 8 red; 4 green, 1 blue, 3 red Game 39; 7 red, 7 blue; 3 green, 6 blue, 2 red; 3 green, 4 red Game 40; 5 blue, 2 red, 6 green; 6 blue, 10 green, 4 red; 8 green, 6 blue; 3 green, 2 blue; 2 red, 14 green Game 41; 5 red, 14 blue, 3 green; 3 red, 3 blue, 7 green; 19 blue, 15 green, 6 red; 5 green, 18 blue; 1 green, 7 red, 9 blue; 14 green, 10 blue, 1 red Game 42; 2 red, 3 green; 2 blue, 3 red; 15 green, 1 blue; 2 blue, 15 green, 1 red; 7 red, 15 green Game 43; 4 green, 6 red, 9 blue; 4 green, 3 red, 18 blue; 6 green, 7 blue; 4 red, 7 blue; 8 blue, 7 green, 1 red; 5 red, 14 blue Game 44; 2 green, 11 blue; 1 green, 5 red, 8 blue; 4 green, 17 blue, 4 red Game 45; 6 blue, 3 green, 2 red; 8 green, 12 blue, 3 red; 13 blue, 11 green; 13 blue, 9 green; 2 blue, 3 green, 3 red; 2 blue, 10 green Game 46; 14 blue, 12 green, 3 red; 2 green, 1 red, 10 blue; 5 red, 7 green Game 47; 15 blue, 1 red; 1 red, 14 blue; 1 red, 16 blue; 3 green, 8 blue Game 48; 1 green, 3 blue, 1 red; 8 blue, 2 red, 8 green; 14 red, 4 green, 11 blue Game 49; 6 red, 5 blue, 2 green; 3 red, 11 blue; 1 blue, 14 green, 6 red Game 50; 7 red, 7 blue; 7 blue, 7 red; 13 blue, 1 green, 2 red; 7 green, 5 red, 9 blue Game 51; 4 blue, 9 red, 1 green; 16 red; 2 blue, 6 red; 11 red, 6 blue Game 52; 4 green, 4 blue, 9 red; 5 blue, 4 red, 16 green; 16 green, 3 red Game 53; 2 green, 12 red; 2 red, 5 green, 15 blue; 9 blue, 17 red, 9 green; 2 blue, 6 red, 4 green Game 54; 2 red, 3 blue, 5 green; 8 green, 3 blue; 9 green, 3 blue, 3 red; 1 blue, 4 green Game 55; 6 green, 11 blue, 12 red; 10 blue, 6 red, 13 green; 7 green, 9 blue; 10 green, 20 red, 7 blue; 9 green, 14 red, 8 blue; 14 green, 15 red Game 56; 1 green, 8 red, 1 blue; 1 green, 3 blue, 13 red; 5 red, 3 blue; 5 blue, 16 red; 12 red, 4 blue Game 57; 7 green, 5 blue; 13 blue; 1 red, 11 green, 4 blue; 1 red, 7 green, 5 blue Game 58; 14 blue, 6 green, 9 red; 7 blue, 1 green, 11 red; 3 red, 9 blue, 6 green; 4 green, 2 red; 2 blue, 6 green; 11 blue, 1 red Game 59; 6 red, 1 blue, 5 green; 4 green; 15 green; 7 red, 1 blue, 12 green; 7 red, 1 blue, 3 green Game 60; 3 blue, 6 red, 2 green; 7 green, 6 red, 4 blue; 3 green, 1 red, 4 blue; 3 red, 1 green; 9 red, 5 green, 4 blue Game 61; 1 green, 3 blue; 1 red, 2 green; 1 green, 2 blue, 2 red Game 62; 10 green, 15 blue, 14 red; 11 blue, 11 red, 16 green; 5 red, 5 green, 12 blue Game 63; 2 blue, 5 red; 7 blue, 2 green, 2 red; 2 red, 1 blue Game 64; 9 blue, 12 red, 4 green; 5 blue, 13 red; 1 red, 2 green, 7 blue Game 65; 4 blue, 8 red; 13 green, 8 blue, 5 red; 1 green, 5 blue, 7 red; 11 red, 7 blue, 10 green Game 66; 8 red, 17 blue; 1 green, 9 red, 7 blue; 12 red Game 67; 14 blue, 12 green, 3 red; 12 green; 9 green, 13 red, 15 blue; 2 red, 10 green, 1 blue Game 68; 11 blue, 14 green; 14 green; 9 blue, 7 green, 1 red; 9 blue, 7 green; 17 green, 2 blue; 4 green, 4 blue Game 69; 4 blue, 14 green, 6 red; 11 red, 7 green, 10 blue; 4 red, 8 blue, 8 green; 7 green, 6 red, 7 blue Game 70; 12 red, 16 green, 11 blue; 16 green, 15 blue, 5 red; 10 blue, 1 red, 12 green; 9 red, 8 blue, 4 green; 2 green, 8 red, 3 blue Game 71; 8 red, 1 blue, 5 green; 12 green, 7 red; 11 green, 1 blue, 7 red Game 72; 5 green, 15 red; 7 green, 3 red, 4 blue; 10 red, 1 green; 6 blue, 15 red, 3 green Game 73; 1 green, 5 red, 1 blue; 6 red, 3 blue, 6 green; 11 red, 1 blue Game 74; 5 red; 1 blue, 3 green, 3 red; 2 green, 7 red; 1 blue, 2 red; 3 red, 1 green Game 75; 13 blue, 20 red, 10 green; 3 green, 5 blue, 14 red; 9 red, 13 green, 7 blue; 1 blue, 15 red, 2 green; 11 blue, 2 green, 17 red; 11 red, 13 blue, 13 green Game 76; 9 red, 7 green, 2 blue; 7 red, 2 blue, 8 green; 4 blue, 3 red, 9 green; 4 red, 1 green; 1 red, 2 green, 3 blue Game 77; 5 red, 2 green, 15 blue; 12 green, 4 red, 2 blue; 10 blue, 6 red, 9 green; 7 blue, 3 green; 16 blue, 4 red, 5 green Game 78; 11 blue, 3 green, 19 red; 3 blue, 1 red; 8 red, 14 blue, 3 green; 8 blue, 8 green, 16 red; 8 blue, 14 red; 12 blue, 11 red, 2 green Game 79; 10 blue, 5 red, 1 green; 3 blue, 13 red; 15 red, 1 green; 4 red, 6 blue, 1 green; 1 green, 6 blue Game 80; 7 red, 1 green, 1 blue; 1 blue, 4 red, 3 green; 2 red, 2 green; 7 red, 1 blue, 1 green; 2 red, 1 green, 3 blue Game 81; 12 green, 2 red, 8 blue; 1 green, 1 blue, 1 red; 7 blue, 1 red, 11 green; 1 red, 12 blue, 4 green Game 82; 18 red, 5 blue, 4 green; 6 green, 11 red; 11 green, 18 red, 5 blue; 4 green, 17 red, 4 blue; 5 blue, 14 red, 15 green Game 83; 4 red, 6 blue, 6 green; 9 red, 4 green; 8 green, 7 blue; 2 blue, 9 red, 13 green; 2 blue, 9 green, 11 red Game 84; 15 blue; 4 green, 1 red, 15 blue; 2 green, 16 blue; 3 green, 14 blue; 16 blue Game 85; 3 red, 7 green, 8 blue; 3 blue, 17 green, 7 red; 13 green, 4 blue; 6 blue, 8 green Game 86; 16 green, 6 blue; 12 blue, 9 red, 11 green; 17 green, 4 blue, 8 red Game 87; 6 blue, 3 green, 13 red; 13 blue; 12 red, 2 green, 1 blue Game 88; 6 red, 2 blue; 16 red, 13 blue, 1 green; 2 green, 11 blue, 2 red; 12 blue, 9 red, 1 green; 5 blue, 2 red, 2 green; 18 red, 3 blue Game 89; 6 green, 5 blue; 4 green, 4 blue; 3 red, 5 blue Game 90; 3 green, 8 blue; 2 green, 7 blue, 9 red; 8 red, 2 blue, 4 green; 1 green, 3 red, 7 blue; 4 blue, 4 green, 2 red; 9 red, 3 blue, 3 green Game 91; 9 red, 12 green, 1 blue; 11 green, 9 red, 2 blue; 1 blue, 8 red, 4 green; 6 red, 9 green; 2 blue, 10 red, 1 green; 2 blue, 15 green, 13 red Game 92; 3 green, 11 red, 16 blue; 8 blue, 1 red, 6 green; 4 green, 1 red, 5 blue Game 93; 9 blue, 3 red, 13 green; 2 red, 9 blue; 3 blue, 17 green, 5 red; 4 green, 8 blue Game 94; 2 blue, 3 red, 9 green; 4 blue, 1 red, 6 green; 8 green, 2 blue; 4 green, 2 blue, 7 red Game 95; 5 green, 3 blue; 4 blue, 3 green, 8 red; 3 green, 4 red, 3 blue; 2 blue, 4 red; 9 blue, 5 red, 3 green Game 96; 11 green; 10 green, 5 blue, 11 red; 5 blue, 13 red, 15 green; 10 green, 1 blue, 11 red Game 97; 5 green, 6 blue, 1 red; 7 green, 1 red; 5 blue; 3 blue, 1 red Game 98; 1 blue, 5 green, 7 red; 3 red, 5 green, 1 blue; 4 blue, 8 green, 2 red; 4 green, 1 blue, 6 red Game 99; 12 blue, 8 green; 2 green; 3 red, 7 green, 5 blue; 1 green, 1 blue, 2 red Game 100; 4 blue, 14 red; 12 red, 1 blue; 2 red, 2 blue; 8 red; 14 red, 2 blue, 1 green; 3 blue ================================================ FILE: exm/aoc/2023/aoc_2023_02_questions.txt ================================================ --- Day 2: Cube Conundrum --- You're launched high into the atmosphere! The apex of your trajectory just barely reaches the surface of a large island floating in the sky. You gently land in a fluffy pile of leaves. It's quite cold, but you don't see much snow. An Elf runs over to greet you. The Elf explains that you've arrived at Snow Island and apologizes for the lack of snow. He'll be happy to explain the situation, but it's a bit of a walk, so you have some time. They don't get many visitors up here; would you like to play a game in the meantime? As you walk, the Elf shows you a small bag and some cubes which are either red, green, or blue. Each time you play this game, he will hide a secret number of cubes of each color in the bag, and your goal is to figure out information about the number of cubes. To get information, once a bag has been loaded with cubes, the Elf will reach into the bag, grab a handful of random cubes, show them to you, and then put them back in the bag. He'll do this a few times per game. You play several games and record the information from each game (your puzzle input). Each game is listed with its ID number (like the 11 in Game 11: ...) followed by a semicolon-separated list of subsets of cubes that were revealed from the bag (like 3 red, 5 green, 4 blue). For example, the record of a few games might look like this: Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green In game 1, three sets of cubes are revealed from the bag (and then put back again). The first set is 3 blue cubes and 4 red cubes; the second set is 1 red cube, 2 green cubes, and 6 blue cubes; the third set is only 2 green cubes. The Elf would first like to know which games would have been possible if the bag contained only 12 red cubes, 13 green cubes, and 14 blue cubes? In the example above, games 1, 2, and 5 would have been possible if the bag had been loaded with that configuration. However, game 3 would have been impossible because at one point the Elf showed you 20 red cubes at once; similarly, game 4 would also have been impossible because the Elf showed you 15 blue cubes at once. If you add up the IDs of the games that would have been possible, you get 8. Determine which games would have been possible if the bag had been loaded with only 12 red cubes, 13 green cubes, and 14 blue cubes. What is the sum of the IDs of those games? --- Part Two --- The Elf says they've stopped producing snow because they aren't getting any water! He isn't sure why the water stopped; however, he can show you how to get to the water source to check it out for yourself. It's just up ahead! As you continue your walk, the Elf poses a second question: in each game you played, what is the fewest number of cubes of each color that could have been in the bag to make the game possible? Again consider the example games from earlier: Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green In game 1, the game could have been played with as few as 4 red, 2 green, and 6 blue cubes. If any color had even one fewer cube, the game would have been impossible. Game 2 could have been played with a minimum of 1 red, 3 green, and 4 blue cubes. Game 3 must have been played with at least 20 red, 13 green, and 6 blue cubes. Game 4 required at least 14 red, 3 green, and 15 blue cubes. Game 5 needed no fewer than 6 red, 3 green, and 2 blue cubes in the bag. The power of a set of cubes is equal to the numbers of red, green, and blue cubes multiplied together. The power of the minimum set of cubes in game 1 is 48. In games 2-5 it was 12, 1560, 630, and 36, respectively. Adding up these five powers produces the sum 2286. For each game, find the minimum set of cubes that must have been present. What is the sum of the power of these sets? ================================================ FILE: exm/aoc/2023/aoc_2023_03.adb ================================================ -- Solution to Advent of Code 2023, Day 3 ------------------------------------------ -- Gear Ratios -- -- https://adventofcode.com/2023/day/3 -- Copy of questions in: aoc_2023_03_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_03 is use AoC_Toolbox, HAT; -- -- r : array (Part_Type) of Integer; -- procedure Read_Data is -- input : constant VString := +"mini.txt"; size : constant := 12; input : constant VString := +"aoc_2023_03.txt"; size : constant := 142; -- f : File_Type; c : Character; -- subtype Row is String (1 .. size); t : array (0 .. 2) of Row; -- Window of 3 rows. -- type Gear_Info is record adjacent_numbers : Natural; ratio : Natural; end record; type Gear_Row is array (1 .. size) of Gear_Info; g : array (0 .. 2) of Gear_Row; -- procedure Clear (gr : in out Gear_Row) is begin for j in gr'Range loop gr (j).adjacent_numbers := 0; gr (j).ratio := 1; end loop; end Clear; -- n : Integer; procedure Mark_Gear (i, j : Natural) is begin if t (i)(j) = '*' then g (i)(j).adjacent_numbers := g (i)(j).adjacent_numbers + 1; g (i)(j).ratio := g (i)(j).ratio * n; end if; end Mark_Gear; -- cur : Integer := 1; j1, j2 : Integer; sym : Boolean; -- procedure Analyse is prev_1 : constant Integer := (cur - 1) mod 3; prev_2 : constant Integer := (cur - 2) mod 3; begin j1 := 2; loop if t (prev_1)(j1) in '0' .. '9' then j2 := j1; loop exit when t (prev_1)(j2 + 1) not in '0' .. '9'; j2 := j2 + 1; end loop; -- Now t (cur-1)(j1 .. j2) contains a number -- n := Integer'Value (t (cur-1)(j1 .. j2)); Nice to have in HAC... n := 0; for j in j1 .. j2 loop n := n * 10 + Ord (t (prev_1)(j)) - Ord ('0'); end loop; -- Now, we look at symbols around the number. sym := False; for j in j1 - 1 .. j2 + 1 loop c := t (prev_2)(j); -- 2 rows before if not (c = '.' or c in '0' .. '9') then sym := True; Mark_Gear (prev_2, j); end if; c := t (cur)(j); -- Current row if not (c = '.' or c in '0' .. '9') then sym := True; Mark_Gear (cur, j); end if; end loop; -- Previous row (being analysed): left and right character. sym := sym or (t (prev_1)(j1 - 1) /= '.') or (t (prev_1)(j2 + 1) /= '.'); Mark_Gear (prev_1, j1 - 1); -- Left Mark_Gear (prev_1, j2 + 1); -- Right if sym then -- Add numbers with an adjacent symbol: r (part_1) := r (part_1) + n; end if; j1 := j2 + 1; else j1 := j1 + 1; end if; exit when j1 >= size - 1; end loop; -- Collect the complete gear info for j in 2 .. size - 1 loop if g (prev_2)(j).adjacent_numbers = 2 then -- Sum the gear ratios r (part_2) := r (part_2) + g (prev_2)(j).ratio; end if; end loop; end Analyse; begin -- Clear the window for i in 0 .. 2 loop for j in 1 .. size loop t (i)(j) := '.'; end loop; Clear (g (i)); end loop; Open (f, input); while not End_Of_File (f) loop for j in 2 .. size - 1 loop Get (f, t (cur)(j)); end loop; -- Analyse the *previous* row. Analyse; cur := (cur + 1) mod 3; Clear (g (cur)); end loop; Close (f); for j in 1 .. size loop t (cur)(j) := '.'; end loop; Analyse; end Read_Data; -- compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 539590 -- Part 2: validated by AoC: 80703636 end if; end AoC_2023_03; ================================================ FILE: exm/aoc/2023/aoc_2023_03.txt ================================================ ..224.....487...................718.....................378............................................284........310......313..........311. ....*..............................*744....486*485......*......741......@...359.#666...439................*925....*......$..+........@...... .235................758..440...........................251....*......262.....*..........*......................752......774.......515....... .........705%..@746........+..942*591.347.470...#..257.........637...........793.......299..../.....813....509......464......&.........688.. .....82................................*.../..901.....*..................836.....&............814...*........*..............80...17*....*... .../...*...679.661.....299...........222.............875.....213...161............964...894.........998.....310....258.85...........735.586. .650..23..#......*.......................................760*........@./........................202...................*.....339............. ..............598......#.....536....702*.........705..........793......957............./........*...935...........965....................... ..................*.357...+.....@.......242.......*......283..*...=956.......118.......959...184...*..............*....401*527.....348...161 .63=...955.523..77......978.846....849..........699..........790........=911.*.....87...............486.........914..............=.......... .........*.........842......*.......*..................*127....................844...*....946.......................235...209@...710.735.... ...........@.........*.....144....226....298........560.....253.........431......*...586.......723..../...482.......&...................*... ...........871../918........................+....................329*......%.....906.............*...350.....@...............365.......361.. ......................536............................+..793..........664.....739................507......289.....256%...73..*............... .356..834..............*.........96.939..............28.+....=..............*...........................*................$.553..........526. ...*...*.............501..746....*..-.......=.................890.....+...701..............807........447......97$..%...........58......$... .891....346...699...........*.421......+....666......198*791......340.433............#...%...*.......................316........*.....%..... ..............%........81.984...........462....................../..........116...711....963...$................380.......745...85....224... .........370......923..@.....................563...........188+.........326*...................67.815..............*582..................... .........*........-........#530.........489........59...................................................#.....57.........100.*.......441*161 .637*....961...........118...........21*...........@..216+.........................+....432*.*309..64....992.......81......=.781.644........ .....324.........126......*166...............&...................385*..............233............*................*..436...........*517.... .88*.........390*................355..335...372....+254..............294...$589........&..803/.....38..-...........56..$.................... ....235.-.........+196...948....*........-................359.........................398.............608..../.................145..346..... ........915.................-.485.945.................936*................114.............118...............490.536..............*.%........ .663........61.......856..........+....343....859...............*345.......*...=862............711.............................313.....606.. ........23...$.....@..................*......................316.....529.362.............49......................307*791.................... 225...............281...#..222.....@..283..............675............*.........911*90..-.....914..%39....509............................... .......797*....$........23..../...895.............67.......164.896.....554.....................*............=..............460........181... ...........211.474...............................@...........*....*201..........911.717.#....192.75..679...........$.........*.........=.... ....355.........................&.....................678.650......................*.....128.....*.....*.........925..230...105............. ....*.......409#.......*897.....698....427.........+....*.......*...............................313...670..521.......*....&.............*308 ...838..335.................367........-..........325....233...224...950......688.....199.774.........................793.108........501.... ...........*..102..924.349...+..595....................................*................&..............395+.....................753......... .........318...*......*........*....676...759.154...................524...........908.........694.211................173...........*214..424 ....458........403...........958.98....*........*..............688......957...488..+...........*.../....................................*... .......*.............591...............218.....203.....196$.......+....*........*......................765......971......./....927*741..227. ......592..%60.$.....*.....885/....287...............................474.........409......226.174.......@........*.....230.................. ...............162.169.................510..962..............17......................32@..*...*.................225....................-.... .....880...................201.....823*........*...914.724.........89...&.......267=.....717.54.436..........60...............&.........69.. 710........601....306.287.....+.........65...308....&...=.../......*.....926..................................*........278.415......-....... ..............*..*......&..........241.%...................827../.265.............662.678......@...#......@.....$......-............734.144. .............424..434.....701.....*........380*731.............24.................*...&........973..741....728..357......................... ........304.................*...881................238.....740.........947........587...22...........................271*........603....@... ...................266.....918....................*..........+.519.617..*...826..........*............./268..974.........486.376....*.295... ...939.........363.*...............378..........302....586........*....740...=..........380........931...........................12......... ...*..........-.....387...............*..588..............*..../...............315...................-...712..491.........956.....#......... .180.454...................104..661...91...*.............811....370......471...-....419....804..........*...................*............... .....*.......@../464........%..*............243.....578...................&..........*...........604..250.....784....750....998............. .....245....165.................771...................&.......#.691...768....654....261.........................*.......*............566.... 441..................91.....194.......643...932*............379.#....$.......*.................86.............940..263.638...........*...... ...+.............%.../.......#.........*........344...795..................991..........544....*..................*..........767...266...... .......-..708..727.....191$......*.....698....=...................990................+.....*....308.......@......325.........*.........44... ...18.397....=.....93.........649.900.........62....-........322.....*.......@......339....619..........404..........540........./....*..... ..../...............%............................742............*...........196................874.205........96#..............203.224...... .........704...727.................496.......*........135....769........./.................%....&....*.../..=.........757................... ........*........*..424..........&........714.5........*...........@....884...............114.......674.144..83..........*302...........%... ........29....179..*............104..................531....629.455..................473......300....................254..............640... ..................296.......................................................1........*.......%..............548........*.....103............ ....381...........................365#..713.282.......%744....................../....709...#...=...431...$.*......*.....837.....*9.....*.... ......*.90.....347.179#...................%.......359..........92............304...*.....923.446.......385.699.....749..............193.206. ....922.+.......*.......-197.....................*.......128........273....@.....758..............439...................650*54.736#......... ................817..-..........152..594..949..807.......$...224...*.....124............889.......=...................................625... ....139....667......239........*...........*.......387........%..806........../...........*..788....632...........=8......584-......*.%..... ...........*.................280...........11.........*726............181......761..-....66.....%....-................64...........14....... ............742.736.725..........708.667..........332.......828*750......-.........425.......................944.....*...................926 .719...110...........*.....348...=..........121......*........................................*.......961.....*.......971...........+....... ..../.....*629........830..*............91....&..241..491...930............561................889....*....710.333..............163...311.... ......%...................252.../..................*...........*270.......................165.....208.......*..................../.......694 ...914...126...267.183........952..$645......414.822................................69.......-..........=..112.464..267....359..........*... .............7*..........................806.../.....931.....*.....355..............*....928...........854.........-..............*993...101 439.897...........%...........8......381...*........*....748..987....*............437.......*....954.......................*................ .......*595....783........49.....110.$...675...8...60.....=........981........&..........730....*.............336.......120.790..........386 ............90..............*212...*..........*.......985.....153........*..12...912*383......665.....754.....-.....................950..... ......790#.*........896@.........773....777..581..514*....910.....5.....579.............................=.......#.....................*..... ...&.......496...........347..............*...............*...................../............................790..............334......912.. 692............609....&.......694..........693...213....620......695......871..385.......82..........785.......................*..163....... .........#....*......984.........*.................=............*.......................................*.545...-............978.....*...... ......971...477.............465......196*313..........447.......766......49.......126*480.............798......792..359*193...........837... ................157...........+..................773.=..............752$....................447*565..........................*53............ .384%..........@.........449............470..749...@.........@792..............138..527.......................339.....299.505...........287. ......691........700........@......96..........*........721*.....................@....*...942......845........*......-.........713.......... .....*......260/...*...........................491..452.....336.......................73....+..960..........238...........163$..&...=.@..... ....689.............831...282....709.960.............=.............204............................#..............59...97..........199..111.. ........................$........../........-....498......................557....&...........972............450............................. .............653........476...398.........619...*.....*280..923..............*31..691.........*........=...*.....67......782................ ..............*....%..........*.........+......268...........&........428....................408....740....576....*.......*.........$....... ....-../...734......317.114.332...795...743.........................-..=..908...........381.......................914...420.*647....528..... ..284.825...............*......................721/.=929.........324.....*....167.561...*.....815*466....................................... ..............389..304.480.......851..@....585..............942%......#.496....*....-.53................170....938*..........518............ ........368..*.....@..............*....941..+.......*...............930.........364.......522......................59.........+....$....652. ...........+.963...................949...........828.784......860............*......420.....*..................*......548...........310.*... .....476...............*...............=...94.+..................&........589.833....*..426.940.....&.....959.993.&88....................398 .......*................624....917...838..*...664.......721........................833...$.......672......$............19................... ....350.......................&....=..............333.................707....................................240..336....=...746.263..$463.. .........................-.........220.....663...../.............*849..#..631.....712....=.../...308.580.............*..........*........... .78@......../..........422....444.............*...............281............*...*....447..37.......*................814.................... ........./...788...810.........&..............369..985....-................92................................684...............74........... ......279.........*......128/....464........#...../......944........978...............163..984*5.@............+.......165......*....285..... ..................889.............*.......969........................%.......5......&....$........272....................*......374......... .........&..............@948..*..13.358........796.............632............*....789........91*..............*66........152............... ........508...+..............3...........544.....$.517.....703....*774.......434............/....794........932............................. ...$...........241.....74...........974..*...954............*.......................375..772...........218.........414...........*366....252 .501..566...............*..........*....599.....#........256.....468@..942.101.........*..........156...*.............*.......998........... ...../.............263.312....+..767..............#.........................*...&95..838.162=.....+....130.........583..544.......176....... ............................936......826.......421.......-139.......982...893.......................*..................*........./.......... .284.....=724...................661.$....694........85..........438.............51...............616.698.*36.....262......357+........224... ....@..........491........+........................@......193......*596...........%../844...387.................$.....132.........%......... .......84..............362.................................*..98..........&................*....14....394..........$..............56........ .........*432.....512................704......424.............*............74........196%..875...*.....*............132.......229........... ..............723*.........568........*..108........672......55.172...217.........................289.427........................*.......... .........#795.........214....*.336...94....*....988................%..&.............*86......*...............838&.......540.......902....... .922...........288........719.....*........845...&..558......#...................524......195.704.....................................77.... ...*....842....../...166........883...-................*503..451..305../....600............................900..280.....*169...586.......... 751....*.........../.*......944......116....416.........................877....*....418...194........644..*....=.....244..........#.....354. .......118......208...................................788...................826........$....$...207.....@..152...........893*608.......&.... ..948.......................203../....206.............*....341./977.916.........49...#........@....-............+385........................ ...*......266.................*...607...@.990......964..............-..........*.....340...697........62..............526.....-............. ..675.....*..........612....604.............*..............492.884...........212...............*157....*...679.........*....706...716%.518.. ......103.749..989...*...................739..............$......=..=..................212..684.....35.......*.........785..............+... ..343*......../.......680.....................*423.................476....&....420..............241..*......532.....+.......864$.....&...... ..................826........403..311...60.451.............+...........562....../.......306.......*..............420..................321... ...241..............*...........+..=....@......*240.......845....@.........740.................968..389.177*...................640.......... ......*82...........963...211%...............38...............901.....404.........&..253..............-.....37.........218.501...*....320... ....*...........................#215...264......298........................*970..801....*....569...............3.......*......%..859.*...... .136.818...212...........91*72........*.........-...750.....775*728.29.270...............984.&...371..........*.........639..........670.... ...........*.../959................438.....524......*...943.........*................755...................162.................446#......... ..........290.............751................*.....557..*...483.............421.........*............189.%................/................. ....................9.786..-......835.......978........445.%..........350........860..662.......#...*....354........*.....682............... .117..57+....441...*....+............................................../............*.........88....142..........%.927...................... ...*...........*..402....................874.....734.926$../...............*633......219.84/............662...205...................334..... ...981........367........338...332/.........=......*......119....375#.334.......146..............%.....$................384.............-511 ........165................=....................666.....................#..614.....-..%744..617.887.......848*.............................. ...........*.203.593...158....*..........152..............+817.....866.......&...............*......../.......904........701.165.80......... 404..977.93..*....*....*...396.281......*....953....*................*.........116..97.70=..179....107..338................$...*....622..... ......=.....445........................382.....*...672................859......*...%....................&..........-.571......717....*...... ..................240............175..........808..............225..........988............/604..............232.448..*..651......769....... .........569*....*........975*.....*....968..............585.....*................26.................................394....@.142........... ......*......498..969.........360.666...%.........................919.......360........-.*.........%...................................484.. ...407................886...................................84......................933...101....58........839..425......................... ================================================ FILE: exm/aoc/2023/aoc_2023_03_questions.txt ================================================ --- Day 3: Gear Ratios --- You and the Elf eventually reach a gondola lift station; he says the gondola lift will take you up to the water source, but this is as far as he can bring you. You go inside. It doesn't take long to find the gondolas, but there seems to be a problem: they're not moving. "Aaah!" You turn around to see a slightly-greasy Elf with a wrench and a look of surprise. "Sorry, I wasn't expecting anyone! The gondola lift isn't working right now; it'll still be a while before I can fix it." You offer to help. The engineer explains that an engine part seems to be missing from the engine, but nobody can figure out which one. If you can add up all the part numbers in the engine schematic, it should be easy to work out which part is missing. The engine schematic (your puzzle input) consists of a visual representation of the engine. There are lots of numbers and symbols you don't really understand, but apparently any number adjacent to a symbol, even diagonally, is a "part number" and should be included in your sum. (Periods (.) do not count as a symbol.) Here is an example engine schematic: 467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598.. In this schematic, two numbers are not part numbers because they are not adjacent to a symbol: 114 (top right) and 58 (middle right). Every other number is adjacent to a symbol and so is a part number; their sum is 4361. Of course, the actual engine schematic is much larger. What is the sum of all of the part numbers in the engine schematic? --- Part Two --- The engineer finds the missing part and installs it in the engine! As the engine springs to life, you jump in the closest gondola, finally ready to ascend to the water source. You don't seem to be going very fast, though. Maybe something is still wrong? Fortunately, the gondola has a phone labeled "help", so you pick it up and the engineer answers. Before you can explain the situation, she suggests that you look out the window. There stands the engineer, holding a phone in one hand and waving with the other. You're going so slowly that you haven't even left the station. You exit the gondola. The missing part wasn't the only issue - one of the gears in the engine is wrong. A gear is any * symbol that is adjacent to exactly two part numbers. Its gear ratio is the result of multiplying those two numbers together. This time, you need to find the gear ratio of every gear and add them all up so that the engineer can figure out which gear needs to be replaced. Consider the same engine schematic again: 467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598.. In this schematic, there are two gears. The first is in the top left; it has part numbers 467 and 35, so its gear ratio is 16345. The second gear is in the lower right; its gear ratio is 451490. (The * adjacent to 617 is not a gear because it is only adjacent to one part number.) Adding up all of the gear ratios produces 467835. What is the sum of all of the gear ratios in your engine schematic? ================================================ FILE: exm/aoc/2023/aoc_2023_04.adb ================================================ -- Solution to Advent of Code 2023, Day 4 ------------------------------------------ -- Scratchcards -- -- https://adventofcode.com/2023/day/4 -- Copy of questions in: aoc_2023_04_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_04 is use AoC_Toolbox, HAT; -- r : array (Part_Type) of Integer; -- procedure Read_Data is -- input : constant VString := +"mini.txt"; margin : constant := 8; winners : constant := 5; candidates : constant := 8; input : constant VString := +"aoc_2023_04.txt"; margin : constant := 10; winners : constant := 10; candidates : constant := 25; -- sep : String (1 .. 3); card_id : String (1 .. margin); -- A string like "Card 214: " winning : array (1 .. winners) of Positive; copies : array (0 .. winners) of Positive; n, won_1, won_2, cur, next : Natural; f : File_Type; begin Open (f, input); for j in 0 .. winners loop copies (j) := 1; end loop; cur := 0; while not End_Of_File (f) loop Get (f, card_id); for j in 1 .. winners loop Get (f, winning (j)); end loop; Get (f, sep); won_1 := 0; won_2 := 0; for i in 1 .. candidates loop Get (f, n); for j in 1 .. winners loop if n = winning (j) then if won_1 = 0 then won_1 := 1; else won_1 := won_1 * 2; end if; won_2 := won_2 + 1; end if; end loop; end loop; r (part_1) := r (part_1) + won_1; r (part_2) := r (part_2) + copies (cur); -- Spread the copies of the cards: for i in 1 .. won_2 loop next := (cur + i) mod (winners + 1); copies (next) := copies (next) + copies (cur); end loop; copies (cur) := 1; cur := (cur + 1) mod (winners + 1); end loop; Close (f); end Read_Data; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 23750 -- Part 2: validated by AoC: 13261850 end if; end AoC_2023_04; ================================================ FILE: exm/aoc/2023/aoc_2023_04.txt ================================================ Card 1: 29 21 67 44 6 13 68 15 60 79 | 75 44 60 30 10 68 40 70 36 79 3 13 64 15 4 46 21 22 67 47 73 86 29 53 6 Card 2: 15 61 5 39 42 79 4 81 72 89 | 74 79 20 81 72 85 25 76 36 49 51 18 34 90 57 17 11 24 89 73 19 37 61 54 2 Card 3: 75 31 33 22 49 70 37 98 92 94 | 1 87 73 92 57 94 84 10 5 79 69 74 96 37 40 55 18 21 85 93 71 49 70 22 39 Card 4: 76 59 23 34 55 41 47 92 58 5 | 16 70 56 19 79 30 85 58 88 75 71 5 8 64 12 23 9 46 34 4 94 37 48 82 47 Card 5: 48 77 74 18 44 34 71 38 67 1 | 8 78 73 19 39 50 11 54 69 37 79 18 66 77 52 94 74 34 71 1 48 85 67 95 93 Card 6: 1 30 41 34 51 23 64 14 18 74 | 38 98 13 67 39 65 1 29 28 75 95 71 60 88 20 86 59 63 36 3 15 57 58 4 42 Card 7: 70 27 20 85 2 34 55 49 24 5 | 19 20 15 48 70 26 89 7 55 44 76 53 63 49 93 68 23 59 72 73 52 41 9 11 94 Card 8: 64 17 56 38 85 53 88 22 51 92 | 22 10 37 24 65 25 63 82 64 5 1 88 17 73 39 78 53 36 71 92 23 9 85 33 38 Card 9: 99 7 22 85 41 15 84 10 42 34 | 16 52 65 26 95 37 28 44 21 36 13 89 48 51 71 83 49 86 9 12 33 32 61 72 73 Card 10: 19 86 25 64 6 95 74 55 68 12 | 51 46 95 84 27 87 7 12 18 81 19 66 33 26 94 16 97 86 74 31 55 6 30 60 85 Card 11: 45 6 14 25 88 1 5 26 91 28 | 10 42 34 19 28 18 91 47 71 29 66 94 43 82 65 70 3 30 64 52 83 27 85 4 60 Card 12: 33 47 56 8 42 95 24 15 83 93 | 93 56 53 95 43 55 73 77 67 47 81 27 3 19 15 79 46 7 42 54 91 10 24 6 5 Card 13: 2 18 45 43 56 82 7 23 16 4 | 70 56 74 4 83 23 98 57 20 86 87 30 28 89 77 37 75 10 41 58 32 21 35 84 66 Card 14: 33 91 58 32 75 37 88 51 83 8 | 92 35 91 56 10 75 52 64 97 16 58 9 26 15 86 99 13 69 70 6 40 12 51 93 95 Card 15: 18 94 82 39 93 70 90 85 37 91 | 29 94 68 22 47 4 64 1 37 75 90 95 54 56 12 48 80 6 40 38 55 2 30 49 92 Card 16: 78 98 80 34 43 51 90 25 26 59 | 83 31 37 79 54 99 98 96 27 16 50 36 4 15 14 80 2 6 33 81 3 24 92 52 45 Card 17: 6 74 89 4 22 95 54 97 28 99 | 32 24 60 83 89 62 79 82 91 25 43 40 52 23 50 71 6 86 64 51 58 63 36 1 41 Card 18: 28 73 36 17 42 26 15 79 13 80 | 11 24 85 84 93 63 42 16 7 19 1 38 44 54 98 59 88 91 35 81 82 95 77 30 26 Card 19: 45 38 16 35 25 72 97 19 96 46 | 21 9 83 49 93 50 92 88 62 46 4 61 69 85 82 51 43 86 81 47 20 53 15 84 91 Card 20: 36 9 7 26 53 48 25 66 76 59 | 90 16 20 79 27 40 86 77 41 15 67 52 34 51 95 64 29 2 47 57 58 24 4 50 84 Card 21: 26 89 64 53 45 95 32 90 24 65 | 80 46 34 33 8 19 94 47 5 21 9 68 73 29 48 82 26 36 4 15 10 74 14 42 79 Card 22: 95 78 69 14 44 54 97 58 66 43 | 75 95 64 54 3 53 20 69 86 22 52 23 59 31 78 45 61 90 50 66 76 63 91 38 79 Card 23: 46 59 36 40 60 10 38 72 20 91 | 21 40 99 22 27 20 57 59 76 78 10 85 97 71 98 1 24 6 72 58 60 36 38 63 46 Card 24: 75 92 32 12 23 89 48 35 28 95 | 23 75 59 58 25 70 18 48 27 92 35 32 53 83 89 64 79 87 10 68 28 30 95 61 78 Card 25: 64 30 37 36 70 35 26 75 80 7 | 11 10 28 40 64 94 31 98 73 57 70 8 88 30 20 80 85 75 92 14 37 27 77 41 76 Card 26: 9 15 4 90 10 67 44 72 3 20 | 64 41 96 2 69 73 61 67 84 58 34 13 3 46 99 48 55 79 31 38 75 12 8 76 32 Card 27: 48 15 97 86 38 37 75 64 27 10 | 96 85 54 88 80 64 11 70 37 50 86 24 75 63 15 3 48 27 17 65 83 97 22 74 10 Card 28: 15 48 89 62 35 81 17 77 16 28 | 92 22 2 78 74 80 12 85 73 42 17 38 11 46 79 69 65 82 47 28 30 62 96 76 66 Card 29: 97 84 88 6 87 4 9 23 43 39 | 64 35 18 36 33 32 39 61 63 93 84 23 49 3 31 60 81 97 17 37 57 79 74 30 65 Card 30: 83 80 61 52 28 84 98 91 79 57 | 62 40 82 31 8 23 95 2 71 93 48 36 43 39 32 87 81 60 18 6 64 90 26 47 85 Card 31: 98 40 94 66 28 32 46 88 36 24 | 4 50 3 21 61 57 63 85 39 11 27 52 7 96 25 91 34 95 71 76 67 23 22 19 99 Card 32: 58 64 75 63 21 77 74 47 71 87 | 71 82 95 17 6 18 14 87 63 65 39 97 79 2 90 21 48 15 23 33 62 67 31 57 88 Card 33: 35 53 67 16 68 20 60 39 47 13 | 71 38 80 7 94 95 44 18 27 64 86 23 81 46 31 56 52 73 97 37 58 29 79 40 6 Card 34: 8 44 93 30 31 81 10 51 1 96 | 73 99 72 32 36 53 28 44 42 29 48 19 34 15 92 75 60 97 39 78 63 43 4 91 95 Card 35: 74 83 62 26 55 81 84 90 53 2 | 77 3 75 54 71 32 18 21 56 70 65 61 4 96 31 72 11 35 6 91 64 38 87 73 30 Card 36: 51 54 86 95 90 64 41 18 83 9 | 2 45 4 92 1 62 50 63 78 44 27 58 94 74 30 59 36 71 79 93 52 77 66 80 65 Card 37: 94 67 88 44 25 18 99 14 63 89 | 17 89 32 71 18 63 19 85 88 91 65 25 14 30 75 48 94 72 99 9 67 36 44 16 62 Card 38: 59 19 11 51 28 64 91 93 60 85 | 93 95 35 84 58 12 15 85 28 56 59 94 27 6 29 51 41 18 22 7 19 11 13 97 4 Card 39: 19 47 29 82 31 27 44 66 67 45 | 1 36 31 67 11 54 8 3 45 56 66 73 27 47 53 14 86 82 30 29 44 60 77 7 19 Card 40: 93 99 27 65 16 26 72 42 71 76 | 16 96 72 68 15 27 89 26 51 29 69 65 98 93 37 22 99 76 50 91 88 71 47 32 42 Card 41: 23 42 80 53 72 98 95 11 21 93 | 47 80 4 30 23 27 82 3 58 93 66 54 35 8 2 53 14 42 75 61 7 17 36 45 89 Card 42: 8 28 34 38 71 92 60 51 23 80 | 60 12 15 67 47 97 86 26 90 80 85 54 92 31 64 98 7 55 66 9 82 1 10 35 34 Card 43: 77 83 18 61 56 78 46 48 80 45 | 41 61 93 45 16 9 38 51 11 48 99 22 3 27 56 66 46 24 80 78 83 75 77 67 18 Card 44: 43 88 33 17 40 90 5 9 94 42 | 97 42 37 62 32 92 43 64 29 88 40 45 18 58 14 36 46 94 77 82 87 52 71 17 9 Card 45: 26 76 46 27 66 8 63 67 2 99 | 11 76 8 80 62 46 92 67 74 18 54 2 63 9 99 66 57 27 26 51 58 73 12 50 59 Card 46: 47 77 74 14 85 90 60 17 53 54 | 98 6 96 8 67 24 74 50 97 7 42 81 20 17 26 16 1 3 62 92 41 90 83 78 44 Card 47: 52 48 72 1 47 55 36 91 89 82 | 35 62 93 40 36 47 43 82 48 72 89 13 69 99 1 52 2 97 18 55 24 86 9 91 90 Card 48: 76 75 21 23 91 58 26 7 86 16 | 6 27 86 85 75 21 24 9 46 84 79 89 65 69 53 10 64 28 74 66 43 20 67 99 87 Card 49: 13 53 58 15 69 68 19 30 48 43 | 13 48 1 41 68 93 34 43 26 15 53 17 91 51 50 19 6 79 39 61 47 30 96 69 58 Card 50: 24 44 29 16 92 57 86 76 88 3 | 46 30 10 55 4 6 48 41 21 8 67 64 59 13 72 77 22 19 15 27 7 66 84 96 1 Card 51: 90 36 71 21 76 64 86 79 48 98 | 76 64 53 42 71 59 23 90 9 79 98 27 48 91 13 96 7 21 5 36 33 8 6 86 31 Card 52: 98 86 23 13 94 8 4 16 96 58 | 23 11 32 34 37 28 76 87 96 42 99 67 35 98 26 36 81 8 65 33 24 60 25 43 45 Card 53: 81 16 7 78 24 48 84 26 42 61 | 81 78 90 18 24 96 62 61 65 38 54 3 84 26 73 30 6 43 20 49 10 36 8 16 89 Card 54: 30 80 89 63 7 25 39 68 37 27 | 46 92 78 50 14 33 9 3 95 81 88 98 67 90 94 29 60 39 21 79 11 75 64 61 23 Card 55: 87 43 58 6 69 78 56 19 64 16 | 87 48 69 53 77 26 31 2 78 19 73 57 76 23 70 44 29 13 80 56 92 82 79 45 12 Card 56: 6 45 94 77 64 44 74 1 22 37 | 63 45 97 2 13 12 62 11 58 46 4 79 70 53 49 24 68 56 87 34 99 32 67 92 28 Card 57: 34 1 73 9 87 21 65 39 37 69 | 83 86 41 18 13 32 10 73 75 39 96 52 30 31 63 20 48 33 23 58 17 85 82 71 68 Card 58: 41 16 68 44 72 62 34 39 81 79 | 78 87 16 27 1 73 68 60 95 59 42 14 89 92 83 94 75 50 6 3 8 48 26 13 76 Card 59: 45 57 86 29 44 51 6 42 88 31 | 22 13 59 94 83 5 66 17 78 92 64 3 72 8 10 2 12 52 27 79 54 58 18 39 70 Card 60: 78 56 95 89 68 18 98 42 44 52 | 76 20 51 71 12 22 3 54 70 84 7 39 64 87 86 30 4 83 15 74 37 94 21 82 13 Card 61: 18 84 14 96 43 38 85 73 71 53 | 92 98 94 23 32 5 30 58 51 68 78 47 75 36 61 89 34 81 35 37 80 44 93 76 69 Card 62: 73 61 14 52 47 97 93 29 40 37 | 94 27 73 29 47 71 52 22 61 81 93 65 78 35 79 75 99 97 72 14 40 2 30 37 55 Card 63: 34 13 11 98 36 78 96 31 74 20 | 14 20 85 57 84 88 96 36 50 13 78 34 82 28 62 98 11 52 33 74 55 90 61 31 93 Card 64: 98 23 79 37 7 21 14 83 12 87 | 86 30 64 90 34 52 97 42 69 81 79 59 63 36 8 21 44 23 13 87 98 76 49 56 37 Card 65: 11 73 35 16 6 27 63 9 74 51 | 54 84 35 11 49 19 91 6 32 73 99 26 53 16 63 27 9 51 7 85 58 59 33 78 74 Card 66: 98 95 7 47 92 66 97 11 62 71 | 14 95 11 62 20 4 42 90 51 99 58 97 60 47 71 7 76 66 30 98 57 36 35 92 94 Card 67: 33 36 32 60 74 54 41 27 88 93 | 22 82 86 58 30 13 9 61 2 15 80 66 5 29 77 78 53 72 24 89 19 12 1 7 73 Card 68: 1 56 31 24 87 4 49 57 72 91 | 61 40 82 34 55 27 57 73 24 31 47 4 90 6 56 91 1 49 32 98 75 72 94 87 63 Card 69: 95 32 15 58 27 45 79 23 6 98 | 69 63 18 95 91 8 48 7 38 10 75 26 61 2 12 34 62 22 81 94 67 40 14 25 52 Card 70: 98 80 82 66 65 41 42 27 94 77 | 77 41 98 27 42 80 79 62 33 63 82 34 14 61 81 94 59 51 52 65 71 57 39 12 66 Card 71: 69 34 98 15 16 82 49 44 10 19 | 43 96 17 53 89 76 94 45 5 81 29 77 83 75 11 60 87 67 47 22 64 88 18 59 1 Card 72: 77 18 36 40 80 63 65 14 29 55 | 79 58 7 4 38 85 63 53 65 91 89 2 14 44 55 20 40 26 84 80 35 57 76 74 18 Card 73: 63 23 39 12 22 35 48 40 84 75 | 79 61 40 58 23 48 75 97 87 4 81 29 84 68 63 51 74 53 35 39 33 24 22 12 60 Card 74: 35 81 48 36 33 42 82 6 30 31 | 35 31 6 82 59 98 97 53 78 96 46 64 94 79 23 14 74 13 16 56 48 47 81 41 32 Card 75: 62 43 47 1 15 50 77 14 85 4 | 70 46 16 69 85 3 30 96 62 99 27 47 59 49 26 9 57 1 50 73 94 97 28 20 29 Card 76: 95 35 81 12 94 26 61 41 38 29 | 45 16 82 99 40 32 17 86 29 91 21 63 67 19 36 20 2 71 50 89 9 44 8 90 85 Card 77: 74 85 93 55 27 86 16 54 73 82 | 13 3 19 49 11 62 68 7 2 77 25 79 71 61 81 29 84 47 78 32 91 34 15 43 20 Card 78: 73 62 42 85 54 15 6 95 97 47 | 30 33 51 1 6 47 72 31 5 97 54 17 2 65 49 38 78 82 27 21 36 22 42 24 18 Card 79: 20 51 62 17 82 37 90 45 98 95 | 20 2 90 40 43 71 60 62 75 16 77 14 6 15 17 52 8 95 32 66 54 45 84 61 70 Card 80: 64 26 54 2 9 18 92 30 97 48 | 30 64 61 7 37 83 89 36 5 46 17 59 87 51 88 50 15 1 71 35 43 11 14 95 28 Card 81: 63 57 72 69 11 90 85 30 64 71 | 37 77 13 9 61 60 23 54 62 64 7 56 48 1 85 73 41 68 29 10 3 92 35 12 26 Card 82: 33 40 45 39 19 41 57 81 73 30 | 97 62 18 89 17 73 46 63 30 6 59 93 82 69 76 39 13 38 23 8 51 57 68 27 48 Card 83: 92 96 72 5 13 6 45 52 57 54 | 56 14 63 29 19 39 62 76 34 91 43 61 42 27 72 71 89 25 99 23 6 12 7 97 30 Card 84: 24 62 78 70 93 79 31 95 51 71 | 83 64 12 11 59 29 39 53 26 45 28 74 41 9 89 15 13 37 79 68 95 8 57 96 77 Card 85: 71 31 76 93 84 57 72 48 73 74 | 51 11 53 68 87 67 31 91 92 15 24 65 58 2 82 42 18 97 61 7 10 47 75 38 27 Card 86: 9 2 73 47 29 25 53 43 32 22 | 46 15 56 94 80 77 16 12 51 23 78 74 71 35 57 96 41 26 62 63 67 17 61 70 99 Card 87: 68 37 86 81 50 77 79 76 52 57 | 3 23 65 50 28 29 97 20 48 37 52 38 82 31 66 8 81 86 68 92 79 57 18 76 77 Card 88: 35 62 52 81 69 49 50 17 84 44 | 96 75 35 39 47 9 88 79 97 13 21 12 2 31 53 67 71 99 77 24 45 84 40 51 94 Card 89: 87 64 77 62 95 22 21 34 40 49 | 82 6 52 87 34 49 86 63 72 40 22 77 56 62 10 37 64 67 21 73 99 91 2 95 17 Card 90: 95 78 72 12 23 42 45 73 31 22 | 78 7 10 22 47 29 73 31 97 40 12 15 50 16 87 42 95 45 81 63 69 79 37 23 92 Card 91: 37 80 51 67 32 59 40 8 38 25 | 38 8 26 1 20 67 80 54 40 51 85 21 3 37 52 32 14 66 13 25 15 23 59 56 48 Card 92: 87 51 29 92 17 55 18 88 73 33 | 33 37 62 7 19 29 16 57 87 18 60 17 93 73 39 92 63 32 48 65 13 51 70 55 1 Card 93: 31 40 98 94 45 46 44 83 78 10 | 31 40 68 21 97 45 11 59 98 17 55 10 71 37 46 93 96 78 32 76 39 44 83 48 56 Card 94: 50 66 26 72 1 77 41 19 97 81 | 49 59 53 42 86 54 6 35 33 91 85 15 12 45 92 38 96 77 73 65 95 46 50 48 19 Card 95: 2 20 92 4 66 97 30 87 17 14 | 20 2 29 46 97 72 93 60 89 39 6 94 12 13 33 96 30 59 1 5 53 22 83 77 78 Card 96: 30 73 25 16 48 86 50 54 33 41 | 21 33 26 45 86 37 41 16 48 13 60 58 28 61 76 54 96 25 50 95 2 67 65 68 73 Card 97: 54 37 39 24 21 62 26 35 25 2 | 10 11 97 16 39 73 35 55 40 93 87 21 14 90 41 36 61 63 13 23 86 96 6 12 38 Card 98: 25 28 75 32 58 13 4 26 43 71 | 86 33 30 28 4 54 26 21 56 75 17 79 69 58 24 13 81 60 32 84 71 18 10 25 43 Card 99: 25 86 74 99 26 98 38 59 18 73 | 99 95 10 24 4 20 91 14 46 78 53 34 98 41 73 84 22 43 45 57 86 26 25 74 59 Card 100: 58 62 97 63 96 95 2 78 17 11 | 59 20 7 2 43 37 28 69 77 33 1 64 63 82 17 51 42 41 75 95 25 83 14 32 22 Card 101: 84 10 35 37 61 80 65 77 13 92 | 87 80 77 7 58 62 26 35 24 96 37 15 36 91 65 84 83 76 32 94 78 31 6 59 48 Card 102: 93 24 66 34 86 79 18 68 14 21 | 65 28 80 40 99 67 31 58 71 34 21 19 50 84 64 70 98 74 68 29 87 41 14 5 89 Card 103: 11 24 96 69 54 77 33 80 87 34 | 77 63 24 56 58 26 93 86 94 27 33 96 36 92 75 49 43 16 54 29 87 81 28 80 34 Card 104: 13 73 49 36 89 35 76 54 66 83 | 71 41 81 72 61 83 70 76 67 64 26 88 19 10 20 16 35 45 12 73 38 66 92 74 79 Card 105: 18 74 53 37 19 30 72 84 41 86 | 24 49 23 36 61 12 56 64 85 15 66 40 94 76 2 69 67 38 45 9 48 21 99 20 60 Card 106: 39 64 95 30 75 41 17 63 84 94 | 54 41 95 55 74 69 17 85 46 27 6 25 83 93 56 48 49 76 22 61 33 34 31 84 37 Card 107: 42 15 62 4 44 48 14 82 97 70 | 19 9 28 77 70 83 71 85 4 76 38 89 30 21 87 65 13 29 97 31 27 64 74 54 93 Card 108: 81 38 35 41 74 87 65 46 50 17 | 79 11 58 34 88 35 93 26 84 71 53 56 16 97 77 94 67 54 62 2 90 98 63 28 61 Card 109: 29 11 71 84 90 94 1 23 54 88 | 84 77 12 87 14 35 49 89 75 63 37 64 10 1 91 97 98 25 86 3 27 57 58 50 96 Card 110: 29 68 4 60 82 97 38 72 78 75 | 33 50 61 25 44 8 13 46 87 83 49 74 76 39 66 36 6 70 73 81 64 18 24 30 79 Card 111: 13 86 29 24 16 78 88 98 46 93 | 72 87 69 34 76 56 66 35 81 7 36 95 8 15 53 11 25 99 74 9 67 30 85 91 82 Card 112: 33 68 45 62 50 42 38 58 22 34 | 4 78 35 42 50 79 52 77 27 75 38 58 34 68 30 62 39 40 33 22 19 37 15 3 45 Card 113: 59 45 81 42 67 36 32 86 66 6 | 42 62 21 14 38 33 55 36 18 78 49 37 6 10 44 19 73 77 97 1 67 43 25 81 13 Card 114: 79 82 15 39 3 7 24 71 93 61 | 93 37 3 47 24 31 29 61 68 40 71 34 58 82 79 7 50 83 98 80 74 30 39 18 15 Card 115: 11 93 43 52 49 88 28 14 55 39 | 55 28 43 1 16 93 42 49 78 31 11 84 52 3 15 72 88 39 14 85 89 36 19 58 8 Card 116: 18 16 75 88 25 62 33 22 97 98 | 40 38 23 34 37 56 68 80 16 75 81 22 85 12 61 4 27 69 1 83 26 98 76 78 29 Card 117: 77 39 53 44 81 90 98 52 38 5 | 80 90 69 20 61 35 4 18 83 39 56 36 95 44 98 81 76 23 60 43 38 17 77 55 51 Card 118: 13 20 72 41 52 73 17 86 2 84 | 10 22 75 54 33 46 9 18 64 27 56 72 42 67 70 1 2 71 94 40 35 73 55 83 68 Card 119: 48 52 33 58 7 56 71 89 10 18 | 7 66 69 5 70 58 84 92 71 89 57 52 37 18 21 31 12 75 62 79 56 30 26 48 11 Card 120: 83 74 37 86 32 14 68 60 6 49 | 31 36 83 40 39 47 24 49 68 27 15 82 60 13 38 89 91 85 46 86 37 74 32 6 22 Card 121: 24 66 45 22 23 36 70 43 11 80 | 9 56 26 33 8 73 4 18 72 69 78 30 17 96 95 89 12 45 91 77 84 28 79 50 19 Card 122: 74 83 69 12 24 60 61 62 70 76 | 91 24 60 43 84 80 53 16 50 71 61 70 83 33 92 4 59 68 99 31 74 67 22 2 36 Card 123: 13 79 14 97 25 94 53 99 12 61 | 96 40 67 80 79 1 56 22 25 83 2 72 43 28 64 14 66 65 4 94 59 31 11 21 19 Card 124: 9 37 93 79 63 83 85 8 34 91 | 28 31 27 69 17 56 15 34 16 90 25 81 4 52 36 68 93 55 97 2 58 10 66 41 14 Card 125: 9 13 1 15 34 77 14 27 69 45 | 11 28 31 76 39 44 47 96 93 5 91 80 17 68 87 98 24 71 34 36 63 72 49 70 30 Card 126: 55 85 91 63 19 25 99 48 20 16 | 32 73 77 81 15 19 86 21 29 49 26 33 24 34 69 42 79 11 40 85 18 1 48 90 52 Card 127: 41 35 53 27 30 82 23 56 58 84 | 79 9 46 95 32 11 56 82 49 19 72 8 7 13 93 1 67 33 66 18 12 59 28 98 96 Card 128: 78 89 61 31 74 19 81 22 24 90 | 94 7 10 52 76 13 51 23 48 79 34 4 66 45 30 82 96 84 16 5 81 57 37 83 35 Card 129: 76 15 41 7 79 4 73 12 88 92 | 64 8 58 70 29 56 87 94 59 48 71 53 22 39 81 36 26 45 63 6 54 27 20 47 62 Card 130: 9 37 30 6 69 20 72 91 22 50 | 83 91 40 50 72 26 94 29 18 1 65 7 79 31 98 47 63 77 97 89 84 60 82 6 61 Card 131: 4 84 24 97 12 27 68 40 71 21 | 69 6 81 50 18 88 59 54 29 32 71 3 8 75 41 68 4 17 99 79 20 27 24 40 21 Card 132: 18 17 10 91 62 28 19 97 26 80 | 20 11 95 18 9 38 5 2 97 62 12 30 72 79 86 81 37 7 45 41 17 16 34 52 51 Card 133: 2 20 42 44 38 99 78 83 25 30 | 3 59 84 66 12 30 14 76 20 78 45 97 42 79 99 8 16 91 2 40 38 56 89 81 90 Card 134: 38 53 13 31 62 39 15 92 6 5 | 38 84 31 1 11 66 12 50 9 35 41 10 20 89 54 82 63 46 39 43 91 32 90 86 34 Card 135: 52 5 88 6 18 45 16 19 23 9 | 82 50 3 21 23 64 96 5 17 6 53 36 78 44 66 31 72 15 79 27 86 88 48 18 81 Card 136: 21 80 86 17 5 8 27 85 31 7 | 49 18 54 7 2 84 44 43 95 40 87 24 17 81 78 56 30 79 9 71 46 76 33 29 85 Card 137: 46 28 18 88 71 63 78 58 50 33 | 75 20 53 56 30 64 10 11 47 59 91 24 67 76 8 1 43 37 87 52 16 39 84 69 89 Card 138: 1 95 44 97 17 20 46 40 3 18 | 43 64 44 29 36 61 95 62 50 41 10 72 67 5 82 42 70 55 3 30 24 12 78 81 47 Card 139: 87 57 36 27 16 3 53 79 66 69 | 83 16 77 41 50 87 8 66 5 91 30 61 82 38 67 24 96 11 17 89 36 45 65 12 27 Card 140: 45 94 91 85 24 52 16 76 96 75 | 15 35 87 57 23 56 68 97 70 17 3 83 89 60 11 95 79 5 63 80 66 30 72 25 2 Card 141: 32 34 70 25 16 98 59 64 69 62 | 87 34 22 96 20 19 8 9 61 68 35 28 75 16 88 42 77 6 43 85 14 66 44 67 36 Card 142: 72 73 81 37 90 31 83 91 95 32 | 82 14 62 45 77 31 17 46 20 36 92 8 1 74 42 84 26 60 88 48 66 95 18 85 30 Card 143: 23 94 85 5 75 22 39 80 34 58 | 73 40 64 54 42 56 93 26 94 33 71 55 82 72 31 2 59 60 29 41 15 17 76 99 52 Card 144: 1 26 98 7 44 92 87 6 37 24 | 13 39 11 95 3 93 74 43 8 60 30 40 15 5 78 19 57 99 64 16 83 90 80 63 4 Card 145: 69 82 7 40 94 28 75 85 74 10 | 98 36 56 86 95 9 16 20 49 6 24 84 83 15 17 57 19 72 89 34 4 2 61 77 44 Card 146: 9 69 16 74 25 27 11 79 20 10 | 85 69 27 31 21 4 7 13 9 20 37 11 43 83 10 74 16 48 56 79 33 58 96 70 25 Card 147: 75 14 66 51 86 50 34 57 16 18 | 83 4 68 1 38 84 73 58 86 76 74 66 75 72 44 22 26 87 34 60 95 14 45 40 90 Card 148: 59 44 21 64 50 60 71 43 11 86 | 66 64 44 85 90 16 74 60 71 6 32 21 91 24 95 36 89 77 7 50 27 86 22 65 43 Card 149: 64 70 95 44 86 90 19 87 47 15 | 98 9 14 82 17 67 25 60 26 10 95 5 81 39 76 85 52 43 49 23 27 99 50 19 6 Card 150: 82 35 98 97 53 81 83 96 92 25 | 92 30 57 88 81 68 22 98 82 24 35 53 96 50 36 51 55 83 34 25 56 14 46 54 97 Card 151: 68 82 83 72 49 5 78 25 4 9 | 4 27 79 49 68 84 34 78 32 82 21 3 77 86 5 48 33 11 53 19 62 26 52 57 87 Card 152: 64 91 43 65 86 72 35 45 60 97 | 45 62 72 22 41 96 43 76 64 86 92 73 2 21 77 91 27 35 63 71 65 10 97 60 36 Card 153: 13 82 94 65 49 61 32 31 48 97 | 7 86 75 65 89 22 51 49 77 81 97 37 61 24 34 82 57 6 46 84 12 70 63 94 13 Card 154: 51 18 36 95 83 99 7 13 9 31 | 95 54 32 48 15 63 85 51 76 36 6 39 73 58 84 27 99 87 31 50 46 9 52 13 18 Card 155: 73 26 15 84 93 70 91 54 92 12 | 22 92 54 6 67 36 13 15 93 89 55 5 70 71 26 9 16 27 91 21 25 73 82 12 84 Card 156: 66 88 92 46 57 48 80 40 3 28 | 80 53 66 78 71 95 3 24 90 62 57 64 46 48 88 4 26 31 28 63 19 32 40 23 92 Card 157: 14 98 81 93 3 94 39 32 12 25 | 58 30 88 8 54 18 50 78 52 36 68 73 74 9 79 49 39 35 15 86 2 10 3 44 65 Card 158: 72 40 66 34 87 20 54 79 69 16 | 53 65 38 67 51 75 99 39 66 76 21 79 77 13 93 48 17 88 85 35 47 58 72 8 83 Card 159: 10 83 69 13 53 41 39 37 55 74 | 9 27 90 53 52 2 42 3 62 37 32 61 35 39 95 36 83 26 69 28 29 71 77 16 54 Card 160: 63 90 68 4 36 61 56 49 64 32 | 36 18 19 37 42 2 23 39 26 40 96 33 55 94 31 51 54 67 89 76 86 95 24 68 11 Card 161: 38 7 25 30 8 39 9 34 19 28 | 3 10 86 85 13 73 61 9 31 43 40 74 60 67 83 70 57 78 81 63 34 27 8 28 97 Card 162: 61 38 82 86 51 16 9 17 69 60 | 81 82 12 80 46 65 97 16 49 72 73 71 92 18 1 88 30 26 66 60 74 54 34 13 8 Card 163: 61 58 38 73 62 21 25 71 49 44 | 79 21 93 85 90 65 36 78 74 94 24 20 39 14 13 63 75 99 42 28 55 40 86 38 89 Card 164: 25 83 54 70 30 76 50 3 36 21 | 86 3 59 66 9 92 81 48 1 71 6 65 69 50 13 25 88 72 32 2 99 70 61 7 58 Card 165: 98 70 26 66 7 42 78 93 84 60 | 30 31 38 22 11 25 10 75 46 41 72 60 40 65 37 33 63 51 36 52 76 73 32 58 79 Card 166: 92 53 96 58 8 65 80 90 88 23 | 9 77 98 21 34 60 31 14 44 26 81 90 91 45 69 99 50 12 36 55 8 48 47 24 54 Card 167: 14 88 33 30 20 99 64 48 60 5 | 68 2 58 90 63 36 12 94 9 71 96 10 29 1 91 53 67 17 85 8 49 57 69 25 59 Card 168: 32 18 96 90 74 64 4 86 25 85 | 98 27 95 22 54 40 59 82 19 10 91 87 60 66 45 43 16 72 47 92 62 29 73 88 93 Card 169: 3 47 80 78 17 68 20 36 54 87 | 75 52 73 43 45 29 53 10 65 89 84 37 90 13 15 40 76 91 88 74 9 7 4 22 1 Card 170: 28 89 99 67 32 94 21 65 83 1 | 94 2 11 52 27 56 87 1 33 68 99 17 28 44 65 49 83 4 67 32 89 59 23 96 82 Card 171: 20 76 49 15 91 67 50 97 96 3 | 70 21 96 8 22 34 67 41 48 20 33 56 47 29 37 3 14 63 17 32 51 76 12 52 65 Card 172: 56 58 86 18 16 79 41 67 12 42 | 20 80 89 33 38 76 48 37 64 57 45 27 36 86 58 41 73 50 7 83 51 43 99 97 17 Card 173: 15 48 73 6 92 20 50 75 8 32 | 7 55 3 79 44 85 35 30 12 81 60 33 80 56 59 84 70 98 65 61 51 45 99 38 29 Card 174: 30 50 22 15 20 99 34 28 72 56 | 20 15 99 28 8 50 40 30 83 56 7 10 74 68 39 58 67 70 47 35 38 37 34 22 72 Card 175: 41 77 9 57 1 24 48 6 92 61 | 75 24 61 92 22 84 76 20 88 1 6 14 74 12 59 71 40 77 41 68 57 64 58 9 63 Card 176: 18 83 76 28 68 52 50 99 67 90 | 28 99 50 65 90 67 83 76 7 66 38 81 60 36 51 18 27 40 52 56 80 68 91 43 61 Card 177: 95 28 89 86 65 42 41 44 92 21 | 93 28 22 86 97 18 14 84 7 42 66 72 33 95 76 69 49 59 45 98 26 57 67 1 24 Card 178: 61 7 31 44 69 71 41 65 27 1 | 41 57 75 32 61 4 1 2 65 64 71 81 87 60 67 47 31 69 29 99 45 43 84 15 28 Card 179: 80 61 21 75 10 86 36 84 71 43 | 77 80 82 43 84 63 99 21 93 86 60 46 61 36 76 19 3 69 57 75 71 10 13 20 95 Card 180: 66 16 8 74 36 9 51 40 20 42 | 82 16 8 51 36 32 20 11 79 13 9 3 97 98 33 68 69 29 66 5 7 25 42 40 74 Card 181: 36 32 49 85 15 6 4 56 1 62 | 80 77 45 83 35 62 9 48 43 17 36 27 32 85 11 89 15 49 56 6 47 1 4 22 20 Card 182: 15 30 92 9 78 16 38 8 12 34 | 98 52 60 24 80 87 46 13 5 54 23 49 97 89 39 48 40 86 7 32 3 69 81 41 8 Card 183: 83 16 69 4 53 41 11 65 6 81 | 12 92 35 51 67 71 55 14 73 1 74 80 82 17 94 43 23 78 63 66 96 30 7 61 29 Card 184: 19 92 71 25 97 80 69 96 3 52 | 98 96 56 69 58 13 65 37 19 3 16 71 43 10 14 21 18 92 97 80 38 25 87 66 57 Card 185: 38 95 97 10 59 93 98 37 43 81 | 12 34 18 2 14 48 35 86 27 96 82 23 37 21 61 63 68 9 17 69 13 5 43 10 32 Card 186: 39 40 17 54 99 94 43 46 28 92 | 82 53 71 25 24 51 97 11 33 16 63 41 9 42 69 88 5 96 73 70 21 95 15 47 19 Card 187: 87 31 45 8 75 30 7 62 22 79 | 86 72 36 8 60 63 40 7 38 65 11 29 92 2 28 59 14 19 87 35 91 12 16 41 57 Card 188: 97 21 10 3 26 27 15 37 75 62 | 17 16 67 74 76 5 90 95 37 25 33 84 40 10 23 12 98 79 27 3 66 82 97 54 58 Card 189: 89 21 23 2 19 93 12 67 58 88 | 66 79 21 16 78 5 12 30 88 83 58 1 6 45 76 95 46 39 31 77 33 19 7 51 69 Card 190: 82 94 59 34 86 52 85 29 41 63 | 64 78 89 34 12 22 68 24 30 46 18 84 86 73 23 58 21 8 1 25 42 74 67 62 38 Card 191: 71 80 45 39 12 15 24 83 53 33 | 96 23 86 70 52 57 37 75 35 82 61 13 5 87 62 54 16 85 32 53 63 66 30 22 67 Card 192: 29 54 14 10 45 83 59 50 95 77 | 60 33 93 82 73 78 4 91 65 29 70 16 69 40 64 36 22 26 77 34 8 17 49 63 99 Card 193: 62 71 81 41 93 98 42 73 34 96 | 89 86 51 60 8 87 34 72 35 45 43 67 38 28 46 24 95 97 47 77 20 80 74 2 85 Card 194: 13 3 2 66 96 63 94 17 43 4 | 70 82 54 83 77 40 6 38 11 9 7 19 68 1 84 92 56 97 80 75 49 33 27 34 23 Card 195: 92 7 61 33 40 95 63 6 96 93 | 41 80 64 81 63 40 57 33 49 24 95 26 89 61 39 92 74 6 1 31 93 29 7 48 56 Card 196: 51 16 52 67 39 57 82 71 76 94 | 61 69 82 70 25 52 56 28 31 19 65 16 13 59 74 90 1 99 88 44 85 91 6 62 54 Card 197: 87 32 97 31 84 79 24 99 62 12 | 80 3 35 12 32 66 81 62 22 8 20 30 95 61 93 16 73 51 96 15 31 84 19 24 58 Card 198: 93 38 58 96 22 29 97 84 56 25 | 5 84 42 56 25 22 10 97 41 58 96 38 64 88 35 93 54 29 81 19 30 91 62 8 47 Card 199: 34 58 6 57 29 99 79 47 94 37 | 61 86 4 23 97 47 9 35 53 34 30 13 25 56 79 89 81 93 8 18 91 43 16 80 90 Card 200: 87 43 48 95 20 10 51 89 35 21 | 74 75 20 87 50 68 89 12 78 35 10 43 21 95 48 41 51 52 84 42 2 9 26 17 29 Card 201: 97 38 88 9 17 29 34 64 20 72 | 39 79 30 17 78 72 4 5 20 95 60 69 28 62 32 85 43 38 87 12 96 7 27 10 6 Card 202: 10 77 45 36 43 32 73 75 47 41 | 32 84 45 21 83 87 62 47 10 43 64 7 75 49 42 61 77 19 73 41 23 44 37 27 60 Card 203: 97 44 48 40 2 31 28 27 83 73 | 58 82 83 99 17 40 97 96 95 90 72 69 63 21 14 59 62 2 84 6 48 35 93 27 55 Card 204: 64 66 23 63 79 99 49 44 39 69 | 12 62 92 9 51 43 31 36 42 20 48 99 16 46 81 93 57 50 32 97 59 73 14 76 10 Card 205: 28 52 50 53 43 32 98 97 61 72 | 62 16 18 71 8 44 11 36 59 41 1 57 84 24 15 56 19 81 55 26 30 85 94 52 75 Card 206: 93 90 72 22 44 52 8 75 68 73 | 74 33 10 97 99 11 25 36 27 87 79 47 81 95 6 91 55 34 59 67 92 56 23 98 24 Card 207: 29 92 17 56 98 84 96 71 13 61 | 68 80 1 66 36 30 46 58 40 12 3 10 82 25 74 97 61 53 56 22 95 57 86 63 11 Card 208: 22 30 79 95 51 11 54 23 29 78 | 6 95 18 29 26 54 12 34 87 40 77 90 73 7 5 22 97 43 81 14 33 59 82 23 20 Card 209: 58 1 51 44 83 17 70 95 26 66 | 79 62 91 74 25 53 68 87 23 96 88 93 27 21 61 24 75 57 92 46 97 38 59 64 42 Card 210: 31 59 3 38 30 69 84 24 48 20 | 82 87 98 38 13 64 63 55 68 49 8 26 76 58 81 22 54 31 3 80 84 4 52 53 41 Card 211: 99 37 92 70 2 88 33 84 63 9 | 50 24 57 65 51 15 21 12 7 23 49 77 60 71 67 56 90 69 95 96 18 81 93 82 53 Card 212: 38 22 26 25 62 17 71 88 31 86 | 66 64 9 75 74 35 15 33 56 59 98 70 94 73 24 13 20 27 78 28 6 79 51 90 97 Card 213: 67 96 40 18 19 51 28 23 36 47 | 61 99 58 43 95 81 16 24 65 9 54 4 87 84 32 42 69 64 45 52 20 72 13 66 62 Card 214: 11 74 92 36 26 68 78 73 5 80 | 67 15 3 22 46 41 87 64 53 89 52 85 99 61 84 31 28 86 77 19 75 1 9 72 82 ================================================ FILE: exm/aoc/2023/aoc_2023_04_questions.txt ================================================ --- Day 4: Scratchcards --- The gondola takes you up. Strangely, though, the ground doesn't seem to be coming with you; you're not climbing a mountain. As the circle of Snow Island recedes below you, an entire new landmass suddenly appears above you! The gondola carries you to the surface of the new island and lurches into the station. As you exit the gondola, the first thing you notice is that the air here is much warmer than it was on Snow Island. It's also quite humid. Is this where the water source is? The next thing you notice is an Elf sitting on the floor across the station in what seems to be a pile of colorful square cards. "Oh! Hello!" The Elf excitedly runs over to you. "How may I be of service?" You ask about water sources. "I'm not sure; I just operate the gondola lift. That does sound like something we'd have, though - this is Island Island, after all! I bet the gardener would know. He's on a different island, though - er, the small kind surrounded by water, not the floating kind. We really need to come up with a better naming scheme. Tell you what: if you can help me with something quick, I'll let you borrow my boat and you can go visit the gardener. I got all these scratchcards as a gift, but I can't figure out what I've won." The Elf leads you over to the pile of colorful cards. There, you discover dozens of scratchcards, all with their opaque covering already scratched off. Picking one up, it looks like each card has two lists of numbers separated by a vertical bar (|): a list of winning numbers and then a list of numbers you have. You organize the information into a table (your puzzle input). As far as the Elf has been able to figure out, you have to figure out which of the numbers you have appear in the list of winning numbers. The first match makes the card worth one point and each match after the first doubles the point value of that card. For example: Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 In the above example, card 1 has five winning numbers (41, 48, 83, 86, and 17) and eight numbers you have (83, 86, 6, 31, 17, 9, 48, and 53). Of the numbers you have, four of them (48, 83, 17, and 86) are winning numbers! That means card 1 is worth 8 points (1 for the first match, then doubled three times for each of the three matches after the first). Card 2 has two winning numbers (32 and 61), so it is worth 2 points. Card 3 has two winning numbers (1 and 21), so it is worth 2 points. Card 4 has one winning number (84), so it is worth 1 point. Card 5 has no winning numbers, so it is worth no points. Card 6 has no winning numbers, so it is worth no points. So, in this example, the Elf's pile of scratchcards is worth 13 points. Take a seat in the large pile of colorful cards. How many points are they worth in total? --- Part Two --- Just as you're about to report your findings to the Elf, one of you realizes that the rules have actually been printed on the back of every card this whole time. There's no such thing as "points". Instead, scratchcards only cause you to win more scratchcards equal to the number of winning numbers you have. Specifically, you win copies of the scratchcards below the winning card equal to the number of matches. So, if card 10 were to have 5 matching numbers, you would win one copy each of cards 11, 12, 13, 14, and 15. Copies of scratchcards are scored like normal scratchcards and have the same card number as the card they copied. So, if you win a copy of card 10 and it has 5 matching numbers, it would then win a copy of the same cards that the original card 10 won: cards 11, 12, 13, 14, and 15. This process repeats until none of the copies cause you to win any more cards. (Cards will never make you copy a card past the end of the table.) This time, the above example goes differently: Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 Card 1 has four matching numbers, so you win one copy each of the next four cards: cards 2, 3, 4, and 5. Your original card 2 has two matching numbers, so you win one copy each of cards 3 and 4. Your copy of card 2 also wins one copy each of cards 3 and 4. Your four instances of card 3 (one original and three copies) have two matching numbers, so you win four copies each of cards 4 and 5. Your eight instances of card 4 (one original and seven copies) have one matching number, so you win eight copies of card 5. Your fourteen instances of card 5 (one original and thirteen copies) have no matching numbers and win no more cards. Your one instance of card 6 (one original) has no matching numbers and wins no more cards. Once all of the originals and copies have been processed, you end up with 1 instance of card 1, 2 instances of card 2, 4 instances of card 3, 8 instances of card 4, 14 instances of card 5, and 1 instance of card 6. In total, this example pile of scratchcards causes you to ultimately have 30 scratchcards! Process all of the original and copied scratchcards until no more scratchcards are won. Including the original set of scratchcards, how many total scratchcards do you end up with? ================================================ FILE: exm/aoc/2023/aoc_2023_05.adb ================================================ -- Solution to Advent of Code 2023, Day 5 ------------------------------------------ -- If You Give A Seed A Fertilizer -- -- https://adventofcode.com/2023/day/5 -- Copy of questions in: aoc_2023_05_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_05 is use AoC_Toolbox, HAT, Interfaces; type Mapping_Rule is record dest_start, source_start, length : Integer_64; end record; max_list : constant := 50; type Mapping_List is array (1 .. max_list) of Mapping_Rule; type Map_Type is record top : Natural; list : Mapping_List; end record; type Relation is (seed_to_soil, soil_to_fertilizer, fertilizer_to_water, water_to_light, light_to_temperature, temperature_to_humidity, humidity_to_location); map : array (Relation) of Map_Type; seed : array (1 .. max_list) of Integer_64; top_seed : Natural; procedure Read_Data is -- input : constant VString := +"mini.txt"; input : constant VString := +"aoc_2023_05.txt"; -- seed_header : String (1 .. 7); f : File_Type; begin top_seed := 0; -- Open (f, input); while not End_Of_File (f) loop Get (f, seed_header); while not End_Of_Line (f) loop top_seed := top_seed + 1; Get (f, seed (top_seed)); end loop; Skip_Line (f); for r in Relation loop map (r).top := 0; Skip_Line (f, 2); while not End_Of_Line (f) loop map (r).top := map (r).top + 1; Get (f, map (r).list (map (r).top).dest_start); Get (f, map (r).list (map (r).top).source_start); Get (f, map (r).list (map (r).top).length); exit when End_Of_File (f); Skip_Line (f); end loop; end loop; end loop; Close (f); end Read_Data; procedure Walk_down_Maps (x : in out Integer_64; start_rule : in Relation) is offset : Integer_64; begin for r in start_rule .. Relation'Last loop for li in 1 .. map (r).top loop if x in map (r).list (li).source_start .. map (r).list (li).source_start + map (r).list (li).length - 1 then offset := x - map (r).list (li).source_start; x := map (r).list (li).dest_start + offset; exit; end if; end loop; end loop; end Walk_down_Maps; procedure Walk_up_Maps (x : in out Integer_64; start_rule : in Relation) is offset : Integer_64; begin for r in reverse Relation'First .. start_rule loop for li in 1 .. map (r).top loop if x in map (r).list (li).dest_start .. map (r).list (li).dest_start + map (r).list (li).length - 1 then offset := x - map (r).list (li).dest_start; x := map (r).list (li).source_start + offset; exit; end if; end loop; end loop; end Walk_up_Maps; r : array (Part_Type) of Integer_64; lowest_1, lowest_2 : Integer_64 := Integer_64'Last; procedure Lowest_Location_Part_1 is x_down : Integer_64; begin for s in 1 .. top_seed loop x_down := seed (s); Walk_down_Maps (x_down, seed_to_soil); lowest_1 := Min (lowest_1, x_down); if s mod 2 = 1 then lowest_2 := Min (lowest_2, x_down); end if; end loop; r (part_1) := lowest_1; end Lowest_Location_Part_1; procedure Lowest_Location_Part_2 is procedure Test (start_point : Integer_64; r : Relation) is -- We use the fact that the optimal path (the path that goes from a -- seed to the minimal location number) touches the left bound of -- at least one range (of those explicitly stated in the Almanac, -- including seed ranges, or of implicit ones: for each transition -- level, between two explicit ranges, or from 0 to the first range, -- or from the last range to the infinity). -- Proof (Reductio ad absurdum): -- ----- -- Let s -> L(s) the function that associates stem s -- to its location following the Almanac's rules. -- Assume we have sm such as L(sm) is minimal, but the path -- from sm to L(sm) doesn't touch any left bound. -- In that case, sm - 1 is in the same seed range as sm and -- in the same seed-to-soil source range as sm; the soil number -- for (sm - 1) is the same soil-to-fertilizer source range as -- for sm, and so on. The path from (sm - 1) down to the -- location number is the same as the path from sm, but shifted -- by - 1 at each level. -- So, L(sm - 1) = L(sm) - 1. -- Therefore, L(sm) is not the claimed minimum. QED. x_up, x_down : Integer_64 := start_point; begin -- 1) We check if x_up in source can stem from any seed range. -- The test assumes injectivity in the whole mapping. -- Otherwise we could have cases where the Walk_up_Maps' result -- is in no seed range but some way down from some seed range -- could still lead to start_point. if r > Relation'First then Walk_up_Maps (x_up, Relation'Pred (r)); end if; for s_idx in 1 .. top_seed loop if s_idx mod 2 = 1 then if x_up in seed (s_idx) .. seed (s_idx) + seed (s_idx + 1) - 1 then -- Ok, x_up (now, a seed number) is in the considered seed range. -- 2) We follow x_down down to category "location", -- like for part 1. Walk_down_Maps (x_down, r); -- x_down is now a location number. lowest_2 := Min (lowest_2, x_down); exit; end if; end if; end loop; end Test; begin -- The case with the left bound of seed ranges is already -- treated by Lowest_Location_Part_1. for r in Relation loop for li in 1 .. map (r).top loop -- Test left bound of explicit range "li" for category "r": -- Note: this test is sufficient to find the solution -- for data aoc_2023_05.txt, but is certainly due to luck. Test (map (r).list (li).source_start, r); -- Test left bound of the implicit range that is right -- after the explicit one: Test (map (r).list (li).source_start + map (r).list (li).length, r); end loop; -- Test the remaining implicit range, which starts with 0. Test (0, r); end loop; r (part_2) := lowest_2; end Lowest_Location_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Lowest_Location_Part_1; Lowest_Location_Part_2; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 261668924 -- Part 2: validated by AoC: 24261545 end if; end AoC_2023_05; ================================================ FILE: exm/aoc/2023/aoc_2023_05.txt ================================================ seeds: 2041142901 113138307 302673608 467797997 1787644422 208119536 143576771 99841043 4088720102 111819874 946418697 13450451 3459931852 262303791 2913410855 533641609 2178733435 26814354 1058342395 175406592 seed-to-soil map: 1270068015 1235603193 242614277 13415696 1478217470 21049126 825250550 1160341941 75261252 3786189027 1971702238 242038712 3191605340 3433644052 172752250 2389904665 3088515862 345128190 0 1499266596 13415696 1197451933 0 72616082 2139929050 1721726623 249975615 900511802 222541761 147014452 1047526254 72616082 149925679 34464822 980591812 179750129 2735032855 2631943377 456572485 3364357590 3606396302 421831437 214214951 369556213 611035599 1721726623 2213740950 418202427 soil-to-fertilizer map: 226793587 358613369 356867344 0 1838890301 226793587 2741010192 0 358613369 2257843811 715480713 173982825 3099623561 1264222741 3082010 1810570233 2912833547 326150077 4038242924 3815312886 256724372 2431826636 3268919687 279247493 866869902 1671637223 167253078 3102705571 889463538 374759203 1615333950 2646894858 125679350 2136720310 1550513722 121123501 3477464774 2772574208 140259339 1034122980 2065683888 581210970 2711074129 3238983624 29936063 583660931 1267304751 283208971 1741013300 3548167180 69556933 3815312886 4072037258 222930038 fertilizer-to-water map: 2197389106 1911800263 305927673 3117278994 244526473 20512291 2957263700 4069704360 136102838 1536592951 2749121858 245216219 3093366538 840656765 23912456 815267737 2718368501 30753357 3137791285 3392529258 82147206 3770129899 390297301 198889495 2168252150 2217727936 29136956 770420674 2367771416 44847063 3304122356 4205807198 44047643 94626393 318562852 71734449 2518697514 2262245627 10899396 1967704281 265038764 53524088 846021094 2994338077 264934624 1215514867 3881882833 187821527 1781809170 2556752263 100818318 1882627488 1690877042 85076793 208796777 631622731 209034034 2583608714 3508227847 39876494 519341481 1587040614 19652563 599791964 104559149 139967324 3430004623 1246915338 340125276 1110955718 0 104559149 2623485208 3548104341 333778492 1403336394 3259272701 133256557 0 2273145023 94626393 2529596910 1857788459 54011804 166360842 589186796 42435935 3219938491 1606693177 84183865 2165362153 3505337850 2889997 2021228369 2412618479 72557496 538994044 2657570581 60797920 739759288 3474676464 30661386 417830811 1154801218 92114120 509944931 864569221 9396550 2093785865 2485175975 71576288 3969019394 873965771 280835447 2503316779 2246864892 15380735 3348169999 1775953835 81834624 water-to-light map: 3059617387 1101868951 93963271 2772853640 2098642805 169363292 193287974 683814429 1482323 3780234682 1734000399 364642406 194770297 193287974 490526455 3550500423 902417243 199451708 3466829263 2268006097 83671160 3379471616 2976813583 87357647 2283311570 2369871058 489542070 3768145932 1195832222 12088750 1202605712 3064171230 1080705858 2942216932 2859413128 107440729 3749952131 2351677257 18193801 3049657661 2966853857 9959726 902417243 1433811930 300188469 3153580658 1207920972 225890958 light-to-temperature map: 1088722200 1345179841 10000894 4202170199 3029124889 92797097 3016749137 3130683307 53232372 534766220 331633133 9297796 190275035 286706851 44926282 3069981509 1355180735 96127340 1579189291 3913052943 379484702 3918942962 3793498681 21754451 262413801 377451173 88614642 2452226090 2443004441 143726844 1958673993 2586731285 188604820 2595952934 3815253132 97799811 882433672 754981589 206288528 608195463 3121921986 8761321 393888178 145828809 140878042 3166108849 1530740045 97835767 351028443 139489318 6339491 3410232629 961270117 222147493 2449796439 4292537645 2429651 2401067597 1890048598 48728842 3263944616 2376148398 66856043 3330800659 1451308075 79431970 3632380122 2019388074 205952206 1548873457 1323582243 21597598 2693752745 2225340280 142089882 357367934 340930929 36520244 0 493278299 50785717 768194739 645497224 68742488 2876584504 1183417610 140164633 235201317 466065815 27212484 1570471055 2367430162 8718236 2147278813 2775336105 253788784 874238988 3335153634 8194684 2835842627 714239712 40741877 3838332328 1938777440 80610634 50785717 0 139489318 616956784 3183915679 151237955 836937227 608195463 37301761 1098723094 3343348318 450150363 3940697413 1628575812 261472786 temperature-to-humidity map: 3865679795 3411240257 137388137 0 569718370 128927628 2284256983 1093255418 349419361 2189606444 2745948834 16886013 3861728218 3796217004 3951577 700036088 2134161201 67667679 2639129496 1078899666 14355752 4003067932 4146768977 27598493 569558723 2311178479 130477365 4125126694 3887925067 11822916 1884679865 1442674779 129657290 2633676344 1572332069 5453152 862461784 1577785221 531688422 4030666425 4120171499 26597478 195554894 115268399 39538402 235093296 235252943 334465427 2132287170 698645998 57319274 4158735055 3550090086 136232241 2206492457 157488417 77764526 3562496130 3899747983 220423516 2653485248 2201828880 109349599 2014337155 154806801 2681616 1580787383 2536413861 97415145 3453031511 3880534101 7390966 1394150206 2633829006 45492562 4057263903 3686322327 7821024 4157273363 3548628394 1461692 3460422477 3694143351 102073653 4136949610 3800168581 20323753 1678202528 872422329 206477337 1556099825 2109473643 24687558 128927628 2679321568 66627266 2017018771 0 115268399 4065084927 3820492334 60041767 3411240257 4253176042 41791254 767703767 2441655844 94758017 1439642768 755965272 116457057 3782919646 4174367470 78808572 humidity-to-location map: 347042062 4204488573 2962316 877642375 2878291222 23518224 3638916554 3484768713 5466055 2890676240 3280663590 83564486 201731623 3228655138 52008452 1692198890 1946017811 25211210 1717410100 1270737209 92827656 3598929376 3630765534 39987178 2226479211 1578430526 262844314 687169155 3670752712 117494406 3884728324 1515480569 62949957 3494186405 1841274840 104742971 2753482998 2630924017 120642845 572458731 2235388494 114710424 3947678281 3490234768 140530766 3433348031 3167816764 60838374 350004378 2406580589 222454353 804663561 1442501755 72978814 4132461733 2901809446 35781203 4088209047 2937590649 38937925 1441554453 2350098918 56481671 3644382609 201731623 240345715 2489323525 1971229021 264159473 2974240726 3086380958 81435806 4127146972 3364228076 5314761 901160599 4207450889 87516407 988677006 442077338 350976352 1498036124 3369542837 115225876 1810237756 3788247118 416241455 1613262000 1363564865 78936890 253740075 2993078971 93301987 3055676532 894954785 375782424 1339653358 793053690 101901095 2874125843 2976528574 16550397 3431458956 2629034942 1889075 4168242936 2751566862 126724360 ================================================ FILE: exm/aoc/2023/aoc_2023_05_questions.txt ================================================ --- Day 5: If You Give A Seed A Fertilizer --- You take the boat and find the gardener right where you were told he would be: managing a giant "garden" that looks more to you like a farm. "A water source? Island Island is the water source!" You point out that Snow Island isn't receiving any water. "Oh, we had to stop the water because we ran out of sand to filter it with! Can't make snow with dirty water. Don't worry, I'm sure we'll get more sand soon; we only turned off the water a few days... weeks... oh no." His face sinks into a look of horrified realization. "I've been so busy making sure everyone here has food that I completely forgot to check why we stopped getting more sand! There's a ferry leaving soon that is headed over in that direction - it's much faster than your boat. Could you please go check it out?" You barely have time to agree to this request when he brings up another. "While you wait for the ferry, maybe you can help us with our food production problem. The latest Island Island Almanac just arrived and we're having trouble making sense of it." The almanac (your puzzle input) lists all of the seeds that need to be planted. It also lists what type of soil to use with each kind of seed, what type of fertilizer to use with each kind of soil, what type of water to use with each kind of fertilizer, and so on. Every type of seed, soil, fertilizer and so on is identified with a number, but numbers are reused by each category - that is, soil 123 and fertilizer 123 aren't necessarily related to each other. For example: seeds: 79 14 55 13 seed-to-soil map: 50 98 2 52 50 48 soil-to-fertilizer map: 0 15 37 37 52 2 39 0 15 fertilizer-to-water map: 49 53 8 0 11 42 42 0 7 57 7 4 water-to-light map: 88 18 7 18 25 70 light-to-temperature map: 45 77 23 81 45 19 68 64 13 temperature-to-humidity map: 0 69 1 1 0 69 humidity-to-location map: 60 56 37 56 93 4 The almanac starts by listing which seeds need to be planted: seeds 79, 14, 55, and 13. The rest of the almanac contains a list of maps which describe how to convert numbers from a source category into numbers in a destination category. That is, the section that starts with seed-to-soil map: describes how to convert a seed number (the source) to a soil number (the destination). This lets the gardener and his team know which soil to use with which seeds, which water to use with which fertilizer, and so on. Rather than list every source number and its corresponding destination number one by one, the maps describe entire ranges of numbers that can be converted. Each line within a map contains three numbers: the destination range start, the source range start, and the range length. Consider again the example seed-to-soil map: 50 98 2 52 50 48 The first line has a destination range start of 50, a source range start of 98, and a range length of 2. This line means that the source range starts at 98 and contains two values: 98 and 99. The destination range is the same length, but it starts at 50, so its two values are 50 and 51. With this information, you know that seed number 98 corresponds to soil number 50 and that seed number 99 corresponds to soil number 51. The second line means that the source range starts at 50 and contains 48 values: 50, 51, ..., 96, 97. This corresponds to a destination range starting at 52 and also containing 48 values: 52, 53, ..., 98, 99. So, seed number 53 corresponds to soil number 55. Any source numbers that aren't mapped correspond to the same destination number. So, seed number 10 corresponds to soil number 10. So, the entire list of seed numbers and their corresponding soil numbers looks like this: seed soil 0 0 1 1 ... ... 48 48 49 49 50 52 51 53 ... ... 96 98 97 99 98 50 99 51 With this map, you can look up the soil number required for each initial seed number: Seed number 79 corresponds to soil number 81. Seed number 14 corresponds to soil number 14. Seed number 55 corresponds to soil number 57. Seed number 13 corresponds to soil number 13. The gardener and his team want to get started as soon as possible, so they'd like to know the closest location that needs a seed. Using these maps, find the lowest location number that corresponds to any of the initial seeds. To do this, you'll need to convert each seed number through other categories until you can find its corresponding location number. In this example, the corresponding types are: Seed 79, soil 81, fertilizer 81, water 81, light 74, temperature 78, humidity 78, location 82. Seed 14, soil 14, fertilizer 53, water 49, light 42, temperature 42, humidity 43, location 43. Seed 55, soil 57, fertilizer 57, water 53, light 46, temperature 82, humidity 82, location 86. Seed 13, soil 13, fertilizer 52, water 41, light 34, temperature 34, humidity 35, location 35. So, the lowest location number in this example is 35. What is the lowest location number that corresponds to any of the initial seed numbers? --- Part Two --- Everyone will starve if you only plant such a small number of seeds. Re-reading the almanac, it looks like the seeds: line actually describes ranges of seed numbers. The values on the initial seeds: line come in pairs. Within each pair, the first value is the start of the range and the second value is the length of the range. So, in the first line of the example above: seeds: 79 14 55 13 This line describes two ranges of seed numbers to be planted in the garden. The first range starts with seed number 79 and contains 14 values: 79, 80, ..., 91, 92. The second range starts with seed number 55 and contains 13 values: 55, 56, ..., 66, 67. Now, rather than considering four seed numbers, you need to consider a total of 27 seed numbers. In the above example, the lowest location number can be obtained from seed number 82, which corresponds to soil 84, fertilizer 84, water 84, light 77, temperature 45, humidity 46, and location 46. So, the lowest location number is 46. Consider all of the initial seed numbers listed in the ranges on the first line of the almanac. What is the lowest location number that corresponds to any of the initial seed numbers? ================================================ FILE: exm/aoc/2023/aoc_2023_06.adb ================================================ -- Solution to Advent of Code 2023, Day 6 ------------------------------------------ -- Wait For It -- -- https://adventofcode.com/2023/day/6 -- Copy of questions in: aoc_2023_06_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_06 is use AoC_Toolbox, HAT; function Find_Records (total_time, distance : Real) return Natural is -- Solutions of: -- -- distance = (total_time - t) * t -- ^-time for running ^-speed -- -- where t is the time of pressing the button -- sqrt_discriminant : constant Real := Sqrt (total_time ** 2 - 4.0 * distance); t1 : constant Real := (total_time - sqrt_discriminant) * 0.5; t2 : constant Real := (total_time + sqrt_discriminant) * 0.5; begin return Natural (t2 - 0.5) - Natural (t1 + 0.5) + 1; end Find_Records; r : array (Part_Type) of Integer; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := -- Example: -- Find_Records (7.0, 9.0) * -- Find_Records (15.0, 40.0) * -- Find_Records (30.0, 200.0); Find_Records (62.0, 644.0) * Find_Records (73.0, 1023.0) * Find_Records (75.0, 1240.0) * Find_Records (65.0, 1023.0); r (part_2) := Find_Records (62737565.0, 644102312401023.0); if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 393120 -- Part 2: validated by AoC: 36872656 end if; end AoC_2023_06; ================================================ FILE: exm/aoc/2023/aoc_2023_06_questions.txt ================================================ --- Day 6: Wait For It --- The ferry quickly brings you across Island Island. After asking around, you discover that there is indeed normally a large pile of sand somewhere near here, but you don't see anything besides lots of water and the small island where the ferry has docked. As you try to figure out what to do next, you notice a poster on a wall near the ferry dock. "Boat races! Open to the public! Grand prize is an all-expenses-paid trip to Desert Island!" That must be where the sand comes from! Best of all, the boat races are starting in just a few minutes. You manage to sign up as a competitor in the boat races just in time. The organizer explains that it's not really a traditional race - instead, you will get a fixed amount of time during which your boat has to travel as far as it can, and you win if your boat goes the farthest. As part of signing up, you get a sheet of paper (your puzzle input) that lists the time allowed for each race and also the best distance ever recorded in that race. To guarantee you win the grand prize, you need to make sure you go farther in each race than the current record holder. The organizer brings you over to the area where the boat races are held. The boats are much smaller than you expected - they're actually toy boats, each with a big button on top. Holding down the button charges the boat, and releasing the button allows the boat to move. Boats move faster if their button was held longer, but time spent holding the button counts against the total race time. You can only hold the button at the start of the race, and boats don't move until the button is released. For example: Time: 7 15 30 Distance: 9 40 200 This document describes three races: The first race lasts 7 milliseconds. The record distance in this race is 9 millimeters. The second race lasts 15 milliseconds. The record distance in this race is 40 millimeters. The third race lasts 30 milliseconds. The record distance in this race is 200 millimeters. Your toy boat has a starting speed of zero millimeters per millisecond. For each whole millisecond you spend at the beginning of the race holding down the button, the boat's speed increases by one millimeter per millisecond. So, because the first race lasts 7 milliseconds, you only have a few options: Don't hold the button at all (that is, hold it for 0 milliseconds) at the start of the race. The boat won't move; it will have traveled 0 millimeters by the end of the race. Hold the button for 1 millisecond at the start of the race. Then, the boat will travel at a speed of 1 millimeter per millisecond for 6 milliseconds, reaching a total distance traveled of 6 millimeters. Hold the button for 2 milliseconds, giving the boat a speed of 2 millimeters per millisecond. It will then get 5 milliseconds to move, reaching a total distance of 10 millimeters. Hold the button for 3 milliseconds. After its remaining 4 milliseconds of travel time, the boat will have gone 12 millimeters. Hold the button for 4 milliseconds. After its remaining 3 milliseconds of travel time, the boat will have gone 12 millimeters. Hold the button for 5 milliseconds, causing the boat to travel a total of 10 millimeters. Hold the button for 6 milliseconds, causing the boat to travel a total of 6 millimeters. Hold the button for 7 milliseconds. That's the entire duration of the race. You never let go of the button. The boat can't move until you let you of the button. Please make sure you let go of the button so the boat gets to move. 0 millimeters. Since the current record for this race is 9 millimeters, there are actually 4 different ways you could win: you could hold the button for 2, 3, 4, or 5 milliseconds at the start of the race. In the second race, you could hold the button for at least 4 milliseconds and at most 11 milliseconds and beat the record, a total of 8 different ways to win. In the third race, you could hold the button for at least 11 milliseconds and no more than 19 milliseconds and still beat the record, a total of 9 ways you could win. To see how much margin of error you have, determine the number of ways you can beat the record in each race; in this example, if you multiply these values together, you get 288 (4 * 8 * 9). Determine the number of ways you could beat the record in each race. What do you get if you multiply these numbers together? --- Part Two --- As the race is about to start, you realize the piece of paper with race times and record distances you got earlier actually just has very bad kerning. There's really only one race - ignore the spaces between the numbers on each line. So, the example from before: Time: 7 15 30 Distance: 9 40 200 ...now instead means this: Time: 71530 Distance: 940200 Now, you have to figure out how many ways there are to win this single race. In this example, the race lasts for 71530 milliseconds and the record distance you need to beat is 940200 millimeters. You could hold the button anywhere from 14 to 71516 milliseconds and beat the record, a total of 71503 ways! How many ways can you beat the record in this one much longer race? ================================================ FILE: exm/aoc/2023/aoc_2023_07.adb ================================================ -- Solution to Advent of Code 2023, Day 7 ------------------------------------------ -- Camel Cards -- -- https://adventofcode.com/2023/day/7 -- Copy of questions in: aoc_2023_07_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_07 is use AoC_Toolbox, HAT; type Hand_Kind is (high, pair_1, pair_2, three, full, four, five); subtype Hand_Type is String (1 .. 5); type Hand_and_Bid_Type is record hand : Hand_Type; bid : Positive; rank : Positive; kind : Hand_Kind; -- Caching the result of the Kind function -- on the hand field. end record; -- row : array (1 .. 1000) of Hand_and_Bid_Type; top : Natural := 0; -- procedure Read_Data is input : constant VString := +"aoc_2023_07.txt"; f : File_Type; begin Open (f, input); while not End_Of_File (f) loop top := top + 1; Get (f, row (top).hand); Get (f, row (top).bid); end loop; Close (f); end Read_Data; r : array (Part_Type) of Integer; label : constant String (1 .. 13) := "AKQJT98765432"; joker : constant := 4; -- Just the position of 'J'. function Kind (h : Hand_Type; p : Part_Type) return Hand_Kind is count : array (1 .. 13) of Natural; sorts, count_max : Natural := 0; begin for i in count'Range loop count (i) := 0; end loop; for c in 1 .. 5 loop for i in count'Range loop if h (c) = label (i) then count (i) := count (i) + 1; end if; end loop; end loop; for i in count'Range loop if count (i) > 0 and then (p = part_1 or else i /= joker) then -- If the joker is used, we need *not* to count its sort! sorts := sorts + 1; end if; if p = part_2 and then i /= joker then count (i) := count (i) + count (joker); end if; count_max := Max (count_max, count (i)); end loop; case count_max is when 5 => return five; when 4 => return four; when 3 => if sorts = 2 then return full; else return three; end if; when 2 => if sorts = 3 then return pair_2; else return pair_1; end if; when others => return high; end case; end Kind; -- Card labels for tie break of part 2, where the index' value matters. label_part_2 : constant String (1 .. 13) := "AKQT98765432J"; function Stronger (h1, h2 : Hand_and_Bid_Type; p : Part_Type) return Boolean is -- NB: "not stronger" can mean "equal"... k1, k2 : Hand_Kind; index_1, index_2 : Positive; card : Character; begin k1 := h1.kind; k2 := h2.kind; if k1 > k2 then return True; elsif k1 < k2 then return False; else -- Tie: both hands are of the same kind. for c in 1 .. 5 loop for i in label'Range loop case p is when part_1 => card := label (i); when part_2 => card := label_part_2 (i); end case; if h1.hand (c) = card then index_1 := i; end if; if h2.hand (c) = card then index_2 := i; end if; end loop; if index_1 < index_2 then -- The lower the index, the higher the value. return True; elsif index_1 > index_2 then return False; end if; end loop; Put ("Equal! "); -- NB: equal hands don't happen on my data. return False; end if; end Stronger; procedure Do_Part (p : Part_Type) is t : Natural := 0; begin for i in 1 .. top loop row (i).kind := Kind (row (i).hand, p); row (i).rank := 1; for j in 1 .. i - 1 loop -- Compare to previous hands: if Stronger (row (i), row (j), p) then row (i).rank := row (i).rank + 1; else row (j).rank := row (j).rank + 1; end if; end loop; end loop; for i in 1 .. top loop t := t + row (i).rank * row (i).bid; end loop; r (p) := t; end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; for part in Part_Type loop Do_Part (part); end loop; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 252656917 -- Part 2: validated by AoC: 253499763 end if; end AoC_2023_07; ================================================ FILE: exm/aoc/2023/aoc_2023_07.txt ================================================ 467K3 95 JK5QK 838 44664 725 8QAK3 134 53A3A 945 7QQJ7 164 J8J89 236 38QAT 166 Q7944 755 35333 526 5J787 482 4K769 829 37773 960 QJ78K 282 3J39Q 326 TJ2QQ 255 J4338 337 QK3KK 187 5K8KQ 380 93785 500 795JT 382 Q399Q 391 99J99 206 T5555 716 Q7Q8Q 990 QQJJQ 346 34344 332 K4J44 763 2A36T 974 77757 461 55446 907 99JJ9 962 K29KQ 177 99666 961 688KK 249 5A558 767 TT6K2 630 5Q4A4 872 JTKQ4 969 A5AAA 421 JAA4Q 680 55K69 29 96ATJ 144 3Q462 523 73646 203 5A96A 550 K84TQ 4 7278T 406 KQQT5 395 54567 197 T53TA 355 AQA99 601 88KQQ 968 55J5J 727 73TJ9 466 99799 843 324QQ 36 84AAA 190 7J366 511 JK938 667 KKQJQ 762 722J4 110 9TKT9 84 33JJ3 458 6K444 498 4279T 23 K5T28 467 3KKKK 871 KQAQK 492 44AKK 865 5638T 932 A89AK 24 29K92 403 A69K6 596 KKK84 400 QA748 616 55AAA 504 9255Q 684 56646 330 6J6J7 222 A59J5 370 3AA4J 940 K9K38 302 2AK58 735 68K4K 422 95599 324 8K88J 987 845Q5 478 72KQ7 263 8TJ83 751 96TTQ 935 AQ6AQ 445 QKQQA 321 A5644 769 QQ5QJ 801 AA574 436 333QQ 605 J5982 71 QT8A5 956 2Q46A 982 J3773 317 3KK93 485 3A76A 926 338JJ 502 8KAQ6 737 KKK28 520 644Q5 850 2T6TT 397 34JA7 549 743J7 747 34843 103 6KKKK 204 Q2J22 548 JKKKK 995 42446 704 8732A 238 TT9J2 109 4758T 33 TTTT7 914 787J7 647 59T59 62 9Q989 985 T886J 554 543QJ 75 77637 857 8888T 83 92T52 939 9832A 620 3TT39 81 84353 18 A8Q8A 824 T4597 425 K3635 949 KAAA2 320 42224 243 AA8A3 565 KK63K 114 TT3TT 133 33T77 141 J868J 774 422QT 369 24T2K 344 KK3Q3 8 424J2 967 8J6J6 666 K6927 887 36666 366 78KT8 867 AT66T 761 72AT6 155 2Q6QQ 440 64J64 594 A2JT8 578 QQAJQ 383 8Q333 963 9A22A 503 K86K6 55 66899 899 4744J 210 72K54 860 KQKK4 723 6TK62 607 9J955 652 A45A5 766 4J333 744 5K555 277 7777J 657 7853A 147 75QQQ 356 T6T93 818 8T342 643 498A7 232 96A2A 471 J55KK 583 KJ7Q6 849 36A36 707 23655 290 K444K 371 5858K 688 KJK8J 258 Q3699 910 79T64 864 KAQ44 536 T4TJ5 239 8KK88 589 42AA4 127 QQ4Q4 746 J9868 472 95493 170 JK6T5 428 KAATA 775 TK3KT 886 36633 858 67767 590 86A2Q 175 J7J7J 659 7J457 796 55335 65 9288A 664 88899 499 7TKTA 327 6QJ36 701 K7KQK 943 QQAQ2 681 Q9948 444 85923 335 82832 283 TQ5QT 92 TK8A3 191 A957K 614 8877T 623 5JTT9 253 2K626 248 757Q7 817 JJ6T5 827 KJ796 367 895AQ 608 AA666 950 TT4T2 135 QQQKK 600 A9KK9 925 49AA7 972 73TAT 60 5K49Q 74 AAJ6A 753 42222 470 J99KK 722 A9AA9 514 36636 581 7T5Q9 690 TTK7K 496 277J4 665 782TQ 662 3AK57 734 29KJ7 343 72726 378 67656 541 22A29 229 JJ5AA 336 QTTJQ 979 J73K6 473 55AK9 19 46466 610 8AAK4 408 27227 181 55525 214 444Q4 505 65K55 506 KJ84T 529 82225 250 59TKA 32 83J53 178 599K4 988 55TTT 759 59999 431 T44A4 828 A888T 874 J3533 619 9979K 981 KK998 101 64965 799 9A999 934 9A299 942 5KKKA 862 4A865 802 64QQ4 837 ATATA 98 6TJQ7 807 K6997 585 57T5T 457 JT66T 938 JJQK9 105 JJ278 804 JJ5AQ 661 Q2597 930 AAQAQ 31 5A974 427 TTQQK 868 7KT7T 730 K4999 112 A8KAQ 672 6AQQ6 447 32J32 297 4QA2J 915 T2Q3Q 712 34KQT 121 98379 617 487QK 44 55TAJ 909 6686T 28 22922 805 T846A 556 J5A6A 399 55Q55 347 8488J 593 JKKTT 708 8288J 768 JKK66 1 22999 586 85398 334 77KK6 782 K34JJ 674 39K4K 653 QA6K3 720 78878 715 QA9Q4 745 3333J 226 3TT32 686 44999 401 A2J32 531 Q65A9 905 J6AA7 194 8J888 163 7JT74 624 JKKAK 568 239J2 919 AA4AA 52 222JJ 184 546AQ 894 K2KK9 631 45TQ2 375 TTTT2 146 26Q77 989 9866K 851 T3332 292 66469 758 48J48 889 4A4QA 185 J6626 68 46T4A 660 83T52 151 7T7T7 407 73758 479 63A44 291 66QT6 875 6645J 738 94Q97 638 T5KT5 411 TJ3J3 866 QT6TQ 842 A448A 433 556JJ 533 T3TKT 161 6JT43 265 T5TTT 393 K7KK4 386 53J6A 845 K7777 756 63399 685 J85AQ 87 88585 906 QJTQQ 270 TKKTK 131 3J3JQ 797 K7Q34 836 K4499 362 53555 651 9888T 435 2J299 557 8J999 964 96TQ2 293 8KTJ8 137 KA6Q7 442 2J6KQ 900 446A4 294 AJAA3 671 Q427T 116 9JQ99 398 59929 392 822J8 192 Q92Q7 420 KKJK6 171 TAJ37 487 8A2J5 10 22TTT 220 33623 111 7Q7AJ 491 A3JJ2 650 J4J23 299 396KA 896 K3K3J 486 QKKKK 20 9A2AJ 713 746K4 56 96996 885 JTK77 312 Q8888 826 3T4AJ 771 97977 219 9354K 788 5Q5KK 455 T3734 325 TK26A 156 7AAAA 924 KJ622 183 5QTAQ 642 AAAAQ 488 TTTJT 953 Q2222 145 4A9TJ 245 TT3JK 588 J5555 284 94AQT 193 97325 196 74A8J 37 24AAA 847 22A32 381 4KJ59 542 T6QK4 673 77877 922 Q2Q66 49 66688 792 9T9T9 918 J8878 552 6A63A 221 AA559 780 9T47Q 300 AKKA4 501 33QQ4 64 6K375 965 T7Q43 82 3689Q 569 A6A3A 462 T5Q3J 689 49Q99 895 KA262 490 87497 13 4449A 973 92453 430 5QA5A 149 69666 247 K6AJA 992 A4444 729 44494 298 J5993 927 26662 555 4J6A5 613 KK77K 855 73222 315 2A2J2 719 K7KT7 43 98T64 998 23282 528 449T7 130 6QK24 424 AAAA3 179 JA42K 53 6A6KK 211 J55JJ 742 J5T93 304 TQA23 358 8J257 240 39393 522 68A38 450 QQAK8 970 J77QT 341 T68AA 242 99933 310 425KA 69 99A9J 535 J35JK 113 4A37T 360 63333 791 78J5T 34 46T46 883 T8JQ3 50 KKKK5 519 T29J8 640 KKK88 646 3A32A 228 7A77T 57 2QQ2J 971 7Q777 438 5J545 21 T4AAJ 432 QQJAA 570 KJ79J 853 T3JKA 359 676K6 724 4TATT 931 JKKT2 629 J338T 469 9939J 743 85A93 241 945TA 363 5JK5A 493 Q5JT5 815 76378 12 T3T53 157 JAA24 732 55757 200 K727J 115 259KK 510 2J739 786 288AA 598 QJ233 100 QQ56Q 25 6333J 702 86797 839 47T77 361 K4823 3 6K446 54 94J75 543 QQQQA 980 55J66 923 AQT55 645 55593 314 J6776 379 J23T6 102 7K7K7 911 JQ5A3 227 KK66K 279 AJJAQ 396 JA252 39 555KK 714 KJ56K 637 KJ64K 928 6Q66Q 85 TJTT2 273 K634J 854 66662 576 6Q6J6 212 KAAT2 696 76663 793 T3AQ3 632 2J994 966 TTTJA 63 4QJQ4 165 AAAJ8 331 TT666 158 2KKA2 453 54444 563 7KK88 675 47777 832 6JJQ9 475 55275 876 63489 794 7K7Q3 208 6J585 820 3Q89T 524 92AK2 6 66JK9 655 7J4KQ 139 666A5 711 4JTK9 117 88AJA 368 34T5T 602 9933J 278 97Q63 448 A5555 892 QJ7A2 726 5KKJ2 917 A5238 108 33343 663 K33T3 285 6Q655 937 38383 880 47834 252 QJA49 692 A6926 547 48Q8Q 288 72J86 107 5T5T9 449 2JK25 305 667T6 136 7JJ88 429 Q5KQK 394 ATAAA 952 66949 296 TT222 933 AQ4AK 948 KQJJ7 209 3465K 709 74775 126 8TJ6T 402 82Q3J 816 Q7855 354 JJ3KK 9 22223 351 2K7TA 831 555AA 984 83539 168 444T4 140 4A8Q4 693 JA8AK 890 29QTQ 308 KJKKJ 389 A86AK 649 J898T 14 A6AAA 352 2J222 176 A4669 958 333K8 635 T4269 844 J4Q54 603 44AAA 349 QT575 413 AA2J2 859 7T395 648 K3Q68 251 7T2T2 790 QQQ33 446 428A4 879 36J2Q 434 69955 991 7J5A4 812 QQ445 789 7A69A 93 4K979 537 K6K73 518 45555 79 45A6A 833 KAAA5 307 48887 80 KK2KK 38 ATJJ5 11 5K325 388 42TJA 353 66J3T 611 A758A 728 TJT77 644 5JQQ2 898 9KQT2 404 K42A2 303 Q6QTA 124 58Q5J 670 K6JTJ 409 T3333 731 J73JK 463 4A288 452 79AAJ 41 2K7T7 15 7AAA7 888 44J94 286 8938K 328 TKKKA 633 22JT7 577 QQQQ7 683 66665 89 T72J4 955 J66J6 877 99433 509 9K92J 776 JQ7Q2 78 A6T2Q 122 69Q6A 153 J5JQ5 218 25KAJ 416 7A47A 513 62T26 1000 96449 281 KKTKK 977 35642 921 9K4K9 778 J4244 993 JJAAA 573 7AA27 626 A685T 376 4JA9A 957 T886T 267 737J7 538 999KK 579 75KK7 76 Q737Q 809 Q3393 901 2734Q 754 J2T9K 216 89859 695 63343 35 7JK7K 700 8828A 765 29AT5 615 Q838Q 410 A3235 622 TKJKQ 810 45454 224 77737 869 JA9T9 333 2772K 276 5535A 350 TT5QT 821 46JKJ 986 9T8KK 125 6JAJ7 595 74647 464 499A4 612 4KT7A 22 J3233 891 44555 959 8KQ8A 271 33443 182 37373 27 88828 997 Q2Q22 189 3635A 373 T66TT 717 A4469 207 2T2KT 749 4244Q 90 9234T 348 33TJ3 289 QAA63 562 2A2A2 199 J6JK7 929 TT99J 234 T3JQ2 798 65Q66 154 JTTJT 975 22699 705 Q6Q6Q 618 99929 811 389J6 920 585Q5 852 A2255 477 TJTJJ 30 K5AK5 772 2QQ3Q 323 6888J 454 7J8K3 609 J463J 572 32323 223 686J6 534 Q25J4 47 29996 882 TTQ8Q 944 42265 480 2JQ96 287 QQ868 517 AK447 994 8J3Q3 897 42QK5 489 A8A88 384 3AT3A 941 44T8T 88 QQ8QQ 787 488TJ 996 6KK66 313 2J262 764 K6KK5 275 K572T 893 7T7QQ 215 76965 773 59575 800 586QJ 309 QQQQ4 721 9A9A4 40 8JJJJ 128 QATA6 162 K6TAQ 415 95JJ8 72 9TQ97 319 2AK22 61 T2TJ2 465 T5274 195 Q4587 266 J97QT 441 52384 17 Q7J77 414 QQQ6Q 903 4444J 532 QQKQQ 904 QJ467 16 25525 785 ATA8A 205 65542 261 9QKKK 512 48844 231 JTJAK 99 QJ8AT 571 68A88 878 5353J 94 2Q33Q 311 KJJ69 946 J83A8 634 QQT6Q 884 KK74J 374 77474 781 38888 527 29457 329 52452 73 2K776 256 QJQQQ 268 J24K6 913 42K88 861 29QQQ 733 4J546 806 K2K98 841 Q4644 697 44K94 834 QAAQT 830 J666T 750 3T335 437 9594T 694 8QQQ3 682 88887 269 J3KKQ 641 99993 551 2K437 699 75775 710 5963J 870 TTKT5 582 2Q82A 439 KJ4Q9 301 Q3558 152 32333 999 T77TT 599 3T6JT 627 2J3T5 560 25442 86 8888K 257 5QJ45 96 QQ7AA 658 88JJ8 863 98948 202 2QJ3J 803 J6488 66 59559 160 JJKK7 484 7J223 254 68889 364 555J9 822 KKAAA 525 K7557 5 3Q33A 814 2384J 587 KK8Q2 777 494K2 426 2TJ22 507 QQQ2Q 698 7229T 954 JJ757 142 2882A 530 KKTQT 539 72222 621 99A5A 736 22887 936 3377Q 779 6A6J6 740 A7AAJ 840 44JJ4 2 QQTQT 51 6666A 669 T9279 908 K9J7Q 856 2AAAJ 748 J3K25 947 TT65T 377 KK2K6 752 K7KKK 150 9J6J8 120 72AK6 656 TT6TT 757 QQ9TT 412 3AA3J 365 84477 783 KK4K2 591 AK79J 654 J77J7 951 Q7664 606 7QQ59 59 J2725 795 96989 417 7TT64 387 47JJK 91 228AA 201 AJJ63 902 A5AKJ 123 37Q33 741 8J358 483 Q88QQ 508 43A33 340 Q9QQQ 516 232JT 148 666J6 159 38363 97 42285 322 4Q944 233 TT4TT 342 K8TQA 566 KJKK2 213 QJQJJ 339 5K932 559 86888 494 2QQJQ 70 7A772 167 5659T 881 T43A6 186 A2Q22 739 55K95 679 2T5QQ 262 47797 419 52522 357 2J734 597 AA3Q3 678 3Q9A3 567 KJAAJ 813 K8794 495 7JT77 198 4KT2A 564 55QQ5 497 5K558 272 T2A25 318 K58Q2 825 7KKJK 628 6A6A7 676 J7T96 706 A4A96 625 6KTQ7 372 JAAJ3 916 99699 106 Q7Q77 468 8Q88J 545 2A2J8 983 777A7 246 329TA 546 38388 48 KKKQQ 316 KKKK8 460 33K8Q 77 A9A29 691 8J859 237 A9599 540 23J67 390 JT43J 668 8J8JQ 338 JQQQ8 456 K9KKK 129 8KJ8K 67 7555Q 169 9QJQ9 459 7A8Q9 718 7J765 760 94744 173 AA35A 264 QKQQ5 423 A6JJ9 819 4AA44 848 88385 180 A4T7Q 259 7J757 584 A96T3 474 JJJJJ 42 9K372 604 J333Q 118 J7A37 451 Q4447 515 QQ77Q 274 73333 553 6747J 521 J56K2 405 KKJJQ 575 QT86A 592 75A73 476 29925 295 A778A 823 AAAAJ 580 TT99T 636 QQ3JQ 235 A8778 244 K6638 784 87Q5A 574 99499 46 AK7Q7 172 KKK33 443 38J88 345 7976K 58 59669 558 6659J 217 7557J 143 5549K 306 J3982 639 J249A 677 55955 418 QQQQT 7 77A47 770 66K4K 104 Q9T5A 976 2673Q 230 Q75TK 26 JKJ9K 225 9TAAT 188 55JQA 119 9Q9Q9 385 24K42 260 T9222 873 99989 45 88448 544 T9784 808 43454 846 TA674 174 3T3AT 687 38929 561 22QQK 912 KQJQQ 978 23223 481 J7772 835 3999Q 703 74K44 280 4K444 138 KJ53K 132 ================================================ FILE: exm/aoc/2023/aoc_2023_07_questions.txt ================================================ --- Day 7: Camel Cards --- Your all-expenses-paid trip turns out to be a one-way, five-minute ride in an airship. (At least it's a cool airship!) It drops you off at the edge of a vast desert and descends back to Island Island. "Did you bring the parts?" You turn around to see an Elf completely covered in white clothing, wearing goggles, and riding a large camel. "Did you bring the parts?" she asks again, louder this time. You aren't sure what parts she's looking for; you're here to figure out why the sand stopped. "The parts! For the sand, yes! Come with me; I will show you." She beckons you onto the camel. After riding a bit across the sands of Desert Island, you can see what look like very large rocks covering half of the horizon. The Elf explains that the rocks are all along the part of Desert Island that is directly above Island Island, making it hard to even get there. Normally, they use big machines to move the rocks and filter the sand, but the machines have broken down because Desert Island recently stopped receiving the parts they need to fix the machines. You've already assumed it'll be your job to figure out why the parts stopped when she asks if you can help. You agree automatically. Because the journey will take a few days, she offers to teach you the game of Camel Cards. Camel Cards is sort of similar to poker except it's designed to be easier to play while riding a camel. In Camel Cards, you get a list of hands, and your goal is to order them based on the strength of each hand. A hand consists of five cards labeled one of A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, or 2. The relative strength of each card follows this order, where A is the highest and 2 is the lowest. Every hand is exactly one type. From strongest to weakest, they are: Five of a kind, where all five cards have the same label: AAAAA Four of a kind, where four cards have the same label and one card has a different label: AA8AA Full house, where three cards have the same label, and the remaining two cards share a different label: 23332 Three of a kind, where three cards have the same label, and the remaining two cards are each different from any other card in the hand: TTT98 Two pair, where two cards share one label, two other cards share a second label, and the remaining card has a third label: 23432 One pair, where two cards share one label, and the other three cards have a different label from the pair and each other: A23A4 High card, where all cards' labels are distinct: 23456 Hands are primarily ordered based on type; for example, every full house is stronger than any three of a kind. If two hands have the same type, a second ordering rule takes effect. Start by comparing the first card in each hand. If these cards are different, the hand with the stronger first card is considered stronger. If the first card in each hand have the same label, however, then move on to considering the second card in each hand. If they differ, the hand with the higher second card wins; otherwise, continue with the third card in each hand, then the fourth, then the fifth. So, 33332 and 2AAAA are both four of a kind hands, but 33332 is stronger because its first card is stronger. Similarly, 77888 and 77788 are both a full house, but 77888 is stronger because its third card is stronger (and both hands have the same first and second card). To play Camel Cards, you are given a list of hands and their corresponding bid (your puzzle input). For example: 32T3K 765 T55J5 684 KK677 28 KTJJT 220 QQQJA 483 This example shows five hands; each hand is followed by its bid amount. Each hand wins an amount equal to its bid multiplied by its rank, where the weakest hand gets rank 1, the second-weakest hand gets rank 2, and so on up to the strongest hand. Because there are five hands in this example, the strongest hand will have rank 5 and its bid will be multiplied by 5. So, the first step is to put the hands in order of strength: 32T3K is the only one pair and the other hands are all a stronger type, so it gets rank 1. KK677 and KTJJT are both two pair. Their first cards both have the same label, but the second card of KK677 is stronger (K vs T), so KTJJT gets rank 2 and KK677 gets rank 3. T55J5 and QQQJA are both three of a kind. QQQJA has a stronger first card, so it gets rank 5 and T55J5 gets rank 4. Now, you can determine the total winnings of this set of hands by adding up the result of multiplying each hand's bid with its rank (765 * 1 + 220 * 2 + 28 * 3 + 684 * 4 + 483 * 5). So the total winnings in this example are 6440. Find the rank of every hand in your set. What are the total winnings? --- Part Two --- To make things a little more interesting, the Elf introduces one additional rule. Now, J cards are jokers - wildcards that can act like whatever card would make the hand the strongest type possible. To balance this, J cards are now the weakest individual cards, weaker even than 2. The other cards stay in the same order: A, K, Q, T, 9, 8, 7, 6, 5, 4, 3, 2, J. J cards can pretend to be whatever card is best for the purpose of determining hand type; for example, QJJQ2 is now considered four of a kind. However, for the purpose of breaking ties between two hands of the same type, J is always treated as J, not the card it's pretending to be: JKKK2 is weaker than QQQQ2 because J is weaker than Q. Now, the above example goes very differently: 32T3K 765 T55J5 684 KK677 28 KTJJT 220 QQQJA 483 32T3K is still the only one pair; it doesn't contain any jokers, so its strength doesn't increase. KK677 is now the only two pair, making it the second-weakest hand. T55J5, KTJJT, and QQQJA are now all four of a kind! T55J5 gets rank 3, QQQJA gets rank 4, and KTJJT gets rank 5. With the new joker rule, the total winnings in this example are 5905. Using the new joker rule, find the rank of every hand in your set. What are the new total winnings? ================================================ FILE: exm/aoc/2023/aoc_2023_08.adb ================================================ -- Solution to Advent of Code 2023, Day 8 ------------------------------------------ -- Haunted Wasteland -- -- https://adventofcode.com/2023/day/8 -- Copy of questions in: aoc_2023_08_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_08 is use AoC_Toolbox, HAT, Interfaces; subtype Pos_Type is String (1 .. 3); type Pair is record left, right : Pos_Type; end record; subtype Para_Range is Integer range 1 .. 10; type Multi_Pos is array (Para_Range) of Pos_Type; starter : Multi_Pos; para_top : Natural := 0; direction_list : VString; map : array (Upcase_Alpha, Upcase_Alpha, Upcase_Alpha) of Pair; procedure Read_Data is -- input : constant VString := +"mini.txt"; input : constant VString := +"aoc_2023_08.txt"; -- c : Character; pos, l, r : Pos_Type; fill_1 : String (1 .. 4); fill_2 : String (1 .. 2); f : File_Type; begin Open (f, input); Get_Line (f, direction_list); Skip_Line (f); while not End_Of_File (f) loop Get (f, pos); if pos (3) = 'A' then para_top := para_top + 1; starter (para_top) := pos; end if; Get (f, fill_1); Get (f, l); Get (f, fill_2); Get (f, r); map (pos (1), pos (2), pos (3)).left := l; map (pos (1), pos (2), pos (3)).right := r; Get (f, c); end loop; Close (f); end Read_Data; r : array (Part_Type) of Integer_64; procedure Do_Part_1 is c : Integer_64 := 0; i : Positive := 1; pos : Pos_Type; begin pos := "AAA"; while pos /= "ZZZ" loop if Element (direction_list, i) = 'L' then pos := map (pos (1), pos (2), pos (3)).left; else pos := map (pos (1), pos (2), pos (3)).right; end if; i := i + 1; if i > Length (direction_list) then i := 1; end if; c := c + 1; end loop; r (part_1) := c; end Do_Part_1; procedure Do_Part_2_Brute_Force is c : Integer_64 := 0; i : Positive := 1; pos : Multi_Pos := starter; goal : Boolean; is_left : Boolean; begin loop goal := True; for p in 1 .. para_top loop goal := goal and then pos (p)(3) = 'Z'; exit when not goal; end loop; exit when goal; is_left := Element (direction_list, i) = 'L'; for p in 1 .. para_top loop if is_left then pos (p) := map (pos (p)(1), pos (p)(2), pos (p)(3)).left; else pos (p) := map (pos (p)(1), pos (p)(2), pos (p)(3)).right; end if; end loop; i := i + 1; if i > Length (direction_list) then i := 1; end if; c := c + 1; end loop; r (part_2) := c; end Do_Part_2_Brute_Force; cycle_observation_max : constant := 100_000; procedure Do_Part_2 is i : Positive; pos : Pos_Type; cycle : Integer_64 := 1; overall_cycle : Integer_64 := 1; begin for p in 1 .. para_top loop i := 1; pos := starter (p); for count in 1 .. cycle_observation_max loop if Element (direction_list, i) = 'L' then pos := map (pos (1), pos (2), pos (3)).left; else pos := map (pos (1), pos (2), pos (3)).right; end if; i := i + 1; if i > Length (direction_list) then i := 1; end if; if pos (3) = 'Z' then cycle := Integer_64 (count); exit; end if; end loop; overall_cycle := LCM_64 (overall_cycle, cycle); end loop; r (part_2) := overall_cycle; end Do_Part_2; verbose : constant Boolean := False; brute : constant Boolean := False; procedure Show_Cycle (p : Para_Range) is c, old_c : Natural := 0; i : Positive := 1; pos : Pos_Type := starter (p); is_left : Boolean; begin for count in 1 .. cycle_observation_max loop if pos (3) = 'A' or pos (3) = 'Z' then Put_Line (+pos & " " & c & " delta: " & (c - old_c)); old_c := c; end if; is_left := Element (direction_list, i) = 'L'; if is_left then pos := map (pos (1), pos (2), pos (3)).left; else pos := map (pos (1), pos (2), pos (3)).right; end if; i := i + 1; if i > Length (direction_list) then i := 1; end if; c := c + 1; end loop; end Show_Cycle; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; if verbose then for p in 1 .. para_top loop Show_Cycle (p); end loop; end if; if brute then Do_Part_2_Brute_Force; else Do_Part_2; end if; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 12737 -- Part 2: validated by AoC: 9064949303801 end if; end AoC_2023_08; ================================================ FILE: exm/aoc/2023/aoc_2023_08.txt ================================================ LRRRLRRRLRRLRLRRLRLRRLRRLRLLRRRLRLRLRRRLRRRLRLRLRLLRRLLRRLRRRLLRLRRRLRLRLRRRLLRLRRLRRRLRLRRRLLRLRRLRRRLRRLRRLRLRRLRRRLRLRRRLRRLLRRLRRLRLRRRLRRLRRRLRRRLRLRRLRLRRRLRLRRLRRLRRRLRRRLRRRLLRRLRRRLRLRLRLRRRLRLRLRRLRRRLRRRLRRLRRLLRLRRLLRLRRLRRLLRLLRRRLLRRLLRRLRRLRLRLRRRLLRRLRRRR DBQ = (RTP, NBX) NFX = (PXX, PLG) VBK = (BRV, DKG) BRS = (HLR, VBX) DDK = (SPR, TCR) FTS = (LJB, MDJ) BLH = (DFM, GGG) PCC = (GQR, RHD) QKN = (VVR, GBL) KHN = (FNB, LLT) HTD = (NPJ, BTL) FPL = (BRX, XQD) RCJ = (QKN, XPD) XRN = (RMQ, LQB) HGM = (VPV, SVR) RFG = (TLM, KPH) SSG = (QGC, KJV) LPA = (QQN, GNF) SVN = (VLM, BDX) VPF = (TTR, RNQ) VNK = (DSX, MCZ) KMS = (XNN, MTB) RLS = (NHX, CRT) VRS = (VBX, HLR) TVK = (MKG, NKB) CKH = (DFF, XPV) KBS = (LJC, PRS) JMT = (FPT, DLX) LRV = (QCD, RLF) TMM = (VPF, GKD) HKH = (PRS, LJC) GSM = (SVH, KRP) SLG = (PTL, SNJ) GVS = (DSN, CKH) QGC = (HKS, DFP) RFT = (VVQ, GMF) FDF = (JKV, JKV) MRL = (PKS, TKS) HBN = (BDX, VLM) CFB = (PPV, QVS) TFJ = (KGN, JND) HLB = (PFV, JXR) RFJ = (SKL, QCN) PQH = (KGN, JND) HGR = (FKL, XHR) CTB = (HNQ, HNQ) XMN = (CJV, LKQ) JVX = (FSS, CRC) SFH = (MXD, RHN) BRK = (QPL, DJB) HBX = (DSN, CKH) RFL = (VXB, FNF) GXP = (LHR, SMV) CHK = (NLQ, VCR) QPG = (HHL, KHB) VBC = (NFV, FST) QJF = (JXL, JJC) XKQ = (PCS, BSH) SKS = (SNN, QSN) GJJ = (VVG, XPR) DJP = (SJM, DNR) DQF = (MHG, BKZ) MSB = (BRX, XQD) PQR = (TLL, RVS) XGB = (RMT, HGF) HBD = (PFD, FDN) NSN = (RFJ, NJT) SNJ = (MVG, DBQ) NMV = (SKG, TDJ) PTN = (TNR, SSG) SBG = (CVH, LMJ) RDT = (SVQ, JTT) MRC = (BKF, QMJ) JKV = (CTB, CTB) CTX = (QHL, BDV) SQM = (DNR, SJM) MVG = (RTP, NBX) KKJ = (TQP, PST) QKX = (BRD, SFT) VFV = (NTL, VMQ) LXK = (SSL, MFR) HDH = (VPS, MJH) RTP = (CGJ, XJC) BXQ = (FLN, FLN) GKD = (TTR, RNQ) GPP = (SNN, QSN) GDQ = (JLS, TND) LTF = (GXP, TVB) GVB = (LSV, FRL) JCF = (HGR, GMX) VCR = (JTR, MCM) XJC = (DGP, XML) XKA = (SFC, CHQ) LJL = (VPX, PMS) CPH = (PCQ, QKX) VPV = (TFP, NJN) TDJ = (PRV, DBK) JGQ = (TPX, NMV) LJS = (GDQ, QPV) VHN = (CBJ, PFQ) JHT = (XHM, NRK) ZZZ = (HJS, LRV) KJV = (HKS, DFP) HNT = (XXT, KJT) RHD = (KQH, TMD) JKG = (HXJ, MGF) SPL = (TTB, STB) MBD = (CQK, NHH) TPX = (TDJ, SKG) HRC = (LBB, JLR) QHN = (JHT, THC) SPM = (DDG, MBK) MFG = (JBD, GSM) MHR = (PTN, HVB) RLF = (GMG, TDQ) XBQ = (KKN, QTN) GLB = (DHS, SXC) PRV = (PGC, NSK) SJD = (BXQ, GHF) THC = (XHM, NRK) GBL = (GGR, HTK) MDK = (JXX, DBD) NJT = (QCN, SKL) LLG = (KBL, LXK) RVS = (DDB, QRV) LHR = (LPL, TGJ) TBD = (NNB, CQH) DSN = (DFF, XPV) QQN = (HRV, PTT) XPP = (GSJ, RDT) CBJ = (JQL, RBX) RBX = (CNV, NKQ) DDG = (NBS, KTV) XNN = (TMC, GCG) DSX = (CGR, SGM) DFB = (RCJ, KJK) XTG = (RFG, XSD) PKQ = (DBD, JXX) XPD = (GBL, VVR) FFC = (JLR, LBB) GMG = (KFH, PTP) QHJ = (SHM, FKM) MXD = (XGB, LTX) SGM = (FTS, GXX) LTX = (RMT, HGF) RNQ = (SPL, DKH) NHF = (VXC, HRS) KFR = (JXR, PFV) NRP = (XNN, MTB) VDR = (LDL, JCP) FSS = (KXJ, GKL) QVS = (MKN, BLH) SNN = (SBM, PNH) VXB = (LLG, BHP) BPK = (QVS, PPV) SMV = (TGJ, LPL) CXF = (XKV, PVR) PGC = (NBJ, KCK) VLG = (DDG, MBK) FKL = (HFC, XPP) KFC = (XNM, CNR) FCC = (BRK, GLT) HQC = (JKV, JHQ) QQV = (CPG, HQD) VVG = (XGJ, XGJ) SVK = (HVH, HNJ) XQT = (LQX, HNT) JDB = (PXM, THR) JHR = (XRF, DHN) HRS = (TFJ, PQH) SVQ = (XHX, QNG) KGN = (FCV, SBH) GJX = (MFG, LMS) NBJ = (GVB, RMS) VQJ = (JPB, PDF) TKX = (JMT, LGM) FLL = (GTX, HKP) MFT = (FKM, SHM) JCP = (SSP, VMD) LPC = (KCD, JDB) XHR = (XPP, HFC) FKM = (DLL, XBQ) MGF = (NFX, MQS) JXJ = (MMP, CBT) DFP = (TGM, RHV) SSM = (NTC, TMT) DLX = (PXF, SBG) NNB = (TNT, MMF) QNG = (RHP, QBT) FLR = (CJK, QRL) RCP = (KKG, NTD) GJV = (SLG, DGN) FDN = (TBR, QDT) JTG = (RFT, PRC) LGM = (DLX, FPT) QDT = (CXV, SGD) HKP = (BLB, PCL) GXB = (MNH, GXT) QDS = (LTF, FDX) LMJ = (GJV, HVV) TDQ = (PTP, KFH) SGD = (HTT, PNR) XPV = (BPM, CPH) PTP = (MKL, KSP) DKG = (DKK, KNQ) QCN = (XTD, GQM) LSV = (GDK, VVD) MLG = (RLS, RKG) GMX = (FKL, XHR) QSN = (PNH, SBM) CHQ = (KSB, CXF) RHN = (LTX, XGB) LVX = (JSF, MLT) XHM = (FLR, QVK) NCJ = (CPG, HQD) MQV = (HBD, LDK) VVD = (QBV, FKF) QCD = (GMG, TDQ) GTH = (DLJ, DQF) KFH = (KSP, MKL) NFC = (PKQ, MDK) NCD = (FNB, LLT) MKG = (HNS, DDK) BTV = (KBS, HKH) QGL = (QTF, CVS) DDB = (DVF, HXV) PXF = (CVH, LMJ) NFV = (XMN, BQR) DGN = (SNJ, PTL) HHL = (PHC, QQJ) XPR = (XGJ, LVQ) PCQ = (BRD, SFT) MMT = (RDS, SRS) DMR = (GJM, BQS) QPL = (XNQ, CMN) PDF = (JBH, CTX) CVR = (STX, MBQ) LPL = (SFL, PHQ) FXX = (PNX, PQL) KLS = (NHG, CHF) NHX = (TMN, JLJ) NND = (QHN, XBR) JTT = (QNG, XHX) LML = (FDX, LTF) PCS = (LKV, LXX) SRV = (KCD, JDB) NSK = (NBJ, KCK) MRF = (NKP, JKG) VPX = (NSN, SMB) GFT = (FPL, MSB) DFM = (XKQ, PPQ) PPQ = (PCS, BSH) JJC = (JHR, RQG) JBH = (BDV, QHL) KNQ = (KNP, MRL) TBS = (NTD, KKG) JXL = (RQG, JHR) GKL = (MJC, QBM) BQR = (LKQ, CJV) DGP = (VNT, JRB) DKR = (VBJ, GVF) JXN = (BXD, XLT) TVG = (HGR, GMX) XSD = (TLM, KPH) RMT = (GXB, DPT) FRL = (VVD, GDK) PNX = (NCD, KHN) VGK = (CNR, XNM) MQB = (KSF, LJS) KDC = (MSB, FPL) GCD = (CXS, PCC) XML = (VNT, JRB) TBL = (GCV, HDH) BRV = (DKK, KNQ) JKS = (XXB, ZZZ) TMC = (MDQ, QJF) TNT = (NQJ, SSM) FLF = (XSD, RFG) JRB = (FDF, HQC) PTL = (DBQ, MVG) BGQ = (KFR, HLB) XTD = (VRS, BRS) QXX = (SJD, CSH) FRX = (BQS, GJM) PQL = (NCD, KHN) LKV = (PNK, DKR) HQS = (VVG, XPR) VPQ = (NTL, VMQ) THR = (CBV, CVR) FST = (BQR, XMN) DMD = (CVS, QTF) HXV = (RCP, TBS) STM = (RFX, BFR) JTR = (JTL, JXN) FLG = (PFQ, CBJ) CKM = (KFB, HTP) NCT = (KJK, RCJ) DKH = (STB, TTB) QGA = (CGR, SGM) XNQ = (HJM, MLG) RGF = (LFN, FGC) QBV = (VPJ, RMN) QKJ = (KFC, VGK) CSB = (FDL, FDL) HFK = (DHS, SXC) SVP = (NPJ, BTL) GGR = (XTG, FLF) XKV = (NDH, JXJ) BMR = (FRX, DMR) VVQ = (BFN, TVK) HJM = (RKG, RLS) RLK = (PDF, JPB) DCX = (HNQ, BRZ) TBG = (RTL, SML) RMS = (FRL, LSV) FCV = (STM, HTC) SPR = (TBL, JGG) BHP = (LXK, KBL) NPJ = (XLV, PQR) NKF = (TBD, DKP) PDK = (JTK, JTK) PFQ = (RBX, JQL) LBB = (SVP, HTD) GTX = (BLB, PCL) SBH = (HTC, STM) BFR = (RJN, BTN) TCR = (TBL, JGG) MQS = (PXX, PLG) FRG = (XXB, XXB) STX = (XQL, HGM) HNJ = (HBN, SVN) SSL = (RDL, NST) HJS = (QCD, RLF) KBL = (SSL, MFR) CXS = (RHD, GQR) DFD = (NFP, FCC) VBJ = (HFK, GLB) DKP = (NNB, CQH) QSK = (TKX, CQT) BNV = (JTK, GTH) NBH = (LVX, GQB) QBM = (VNC, VPK) DBD = (HHR, RVQ) DFF = (BPM, CPH) LQX = (KJT, XXT) FGC = (QKQ, QSK) PXM = (CBV, CVR) JHQ = (CTB, DCX) NJN = (BGQ, FBP) TLL = (DDB, QRV) XSN = (THS, KJQ) KXJ = (QBM, MJC) GSC = (TQG, QXX) QJP = (PQL, PNX) PHH = (MXD, RHN) SSC = (NQX, FCH) XDF = (NLQ, VCR) BRD = (MQV, FRQ) AAA = (LRV, HJS) PTT = (FFC, HRC) VKF = (BFG, TGQ) HHA = (FLG, VHN) CNR = (TQX, VDV) TGM = (FLL, TNV) GLT = (DJB, QPL) MBK = (NBS, KTV) JPB = (JBH, CTX) RHP = (SQM, DJP) CHF = (CLQ, JGQ) FTL = (PRC, RFT) SKL = (XTD, GQM) RBN = (SPM, VLG) HGF = (GXB, DPT) BQS = (NSP, BTV) XHX = (RHP, QBT) CGR = (GXX, FTS) BLB = (QJP, FXX) CRT = (JLJ, TMN) PLG = (SLC, PDD) HRV = (FFC, HRC) MCM = (JXN, JTL) JGH = (MFG, LMS) NSP = (KBS, HKH) MFR = (NST, RDL) GMF = (TVK, BFN) SML = (LJL, XFP) MPL = (RDS, SRS) QHP = (SPM, VLG) FCH = (GDC, XRN) NRQ = (FTL, JTG) HMB = (CRC, FSS) KPH = (BNH, SLK) SRS = (MQB, GCN) RQM = (TGQ, BFG) FLN = (CSB, CSB) BSH = (LKV, LXX) CRC = (KXJ, GKL) CJV = (XDF, CHK) CGJ = (DGP, XML) SFL = (GJJ, HQS) PMR = (VPF, GKD) QTN = (MMT, MPL) KJQ = (RLK, VQJ) PBJ = (LFN, FGC) BTL = (PQR, XLV) SBX = (KFC, VGK) QQJ = (PDK, BNV) BRZ = (GNF, QQN) JTL = (XLT, BXD) SKG = (PRV, DBK) RQG = (DHN, XRF) DRC = (SFC, CHQ) TJQ = (NQX, FCH) PKS = (TMM, PMR) TRP = (GVD, FBL) LKQ = (XDF, CHK) RTL = (XFP, LJL) PPV = (MKN, BLH) MTB = (GCG, TMC) FPT = (PXF, SBG) LDK = (FDN, PFD) TND = (PPX, SVK) VPK = (NHF, JDX) HTP = (NKF, RPV) PMS = (SMB, NSN) GGG = (XKQ, PPQ) DLL = (KKN, QTN) JXX = (HHR, RVQ) KSF = (QPV, GDQ) XQD = (FGK, BNJ) RJF = (CSB, KTM) GCN = (KSF, LJS) JKP = (LML, QDS) XFP = (VPX, PMS) DPT = (GXT, MNH) DKK = (KNP, MRL) NKB = (DDK, HNS) CJK = (GSC, GBQ) NLM = (LDL, JCP) VMD = (DFD, XFM) NBX = (XJC, CGJ) PRS = (NLM, VDR) RMQ = (FRG, FRG) XNM = (TQX, VDV) LJC = (VDR, NLM) PHQ = (GJJ, HQS) KXN = (KHB, HHL) BXD = (CKM, XVL) KFB = (NKF, RPV) NFS = (PRL, RFL) RJN = (SFV, RRG) GQM = (VRS, BRS) KQH = (VBC, BSJ) DNR = (BMR, LJQ) HHR = (LPC, SRV) DLJ = (MHG, MHG) SMB = (RFJ, NJT) RHV = (FLL, TNV) NTD = (HBX, GVS) VNT = (FDF, HQC) PRC = (GMF, VVQ) FBP = (HLB, KFR) KTM = (FDL, LRZ) TQP = (QGL, DMD) SBM = (QPG, KXN) QVK = (CJK, QRL) XRF = (RGF, PBJ) NDH = (CBT, MMP) GVL = (RTL, SML) LRZ = (VHN, FLG) CQH = (MMF, TNT) SLK = (TJQ, SSC) QBT = (SQM, DJP) FNF = (LLG, BHP) STB = (KMS, NRP) HVV = (SLG, DGN) RFX = (BTN, RJN) MKL = (GVM, LVP) VDV = (BPK, CFB) CBT = (GJX, JGH) PPX = (HVH, HNJ) NQJ = (TMT, NTC) MJH = (MHP, XQT) LTA = (KLS, BFV) CSH = (BXQ, GHF) HTK = (XTG, FLF) VNC = (JDX, NHF) BFG = (MRC, NKK) KKG = (GVS, HBX) PNK = (GVF, VBJ) XXB = (LRV, HJS) DVF = (TBS, RCP) PNR = (NCJ, QQV) QKQ = (CQT, TKX) TTR = (SPL, DKH) BTN = (RRG, SFV) VLM = (PHH, SFH) TQG = (SJD, CSH) MHP = (LQX, HNT) NQX = (GDC, XRN) TQX = (BPK, CFB) TVB = (LHR, SMV) MBQ = (XQL, HGM) HXJ = (MQS, NFX) DHN = (PBJ, RGF) BFN = (MKG, NKB) PVR = (JXJ, NDH) QRL = (GBQ, GSC) GJM = (NSP, BTV) KQV = (NHH, CQK) KNP = (TKS, PKS) PDD = (FND, JKP) GXT = (VKF, RQM) XDC = (FTL, JTG) MMF = (SSM, NQJ) BFV = (CHF, NHG) DHS = (PHX, PHX) VXC = (PQH, TFJ) XLV = (TLL, RVS) PXX = (SLC, PDD) GVD = (DRC, DRC) THS = (VQJ, RLK) DBK = (PGC, NSK) KHB = (PHC, QQJ) TKS = (PMR, TMM) SVR = (NJN, TFP) HNQ = (QQN, GNF) MKN = (GGG, DFM) KRP = (NFM, NFC) SHM = (XBQ, DLL) NTL = (NCT, DFB) NRK = (QVK, FLR) HXL = (DSX, DSX) KSB = (XKV, PVR) NKK = (BKF, QMJ) MHG = (KLS, BFV) PNP = (XBR, QHN) CLQ = (TPX, NMV) RSG = (XDC, NRQ) BPM = (PCQ, QKX) PHC = (PDK, BNV) TNR = (KJV, QGC) XQL = (VPV, SVR) MHV = (QTS, RSG) XBR = (THC, JHT) BDX = (PHH, SFH) TBR = (CXV, SGD) RVQ = (SRV, LPC) NFM = (PKQ, MDK) FBL = (DRC, QSZ) TLM = (BNH, SLK) NHH = (SKS, GPP) FKF = (RMN, VPJ) XVL = (HTP, KFB) NHG = (CLQ, JGQ) FGK = (NBH, KBX) VMQ = (DFB, NCT) LXX = (DKR, PNK) SMJ = (QGB, NFS) LVP = (KDC, GFT) QGB = (PRL, RFL) BRX = (BNJ, FGK) BDV = (MRF, RXX) SJM = (BMR, LJQ) GBQ = (TQG, QXX) JXR = (XJT, CVX) TMN = (XSN, PQM) CQT = (LGM, JMT) CPG = (QHP, RBN) BKZ = (BFV, KLS) VVR = (HTK, GGR) XFM = (NFP, FCC) CVH = (GJV, HVV) VPS = (XQT, MHP) MDJ = (QHJ, MFT) SNF = (QTS, RSG) NKQ = (HMB, JVX) PRL = (FNF, VXB) CMN = (MLG, HJM) JQL = (NKQ, CNV) QSZ = (CHQ, SFC) HLR = (MHV, SNF) RDL = (TBG, GVL) GVM = (KDC, GFT) KTV = (CKK, VBK) SLC = (JKP, FND) QHL = (MRF, RXX) KKN = (MPL, MMT) TNV = (HKP, GTX) QMJ = (TVG, JCF) BSJ = (NFV, FST) BNJ = (NBH, KBX) XXQ = (GCD, CMQ) TGQ = (NKK, MRC) SVH = (NFC, NFM) LQB = (FRG, JKS) GNF = (HRV, PTT) PFV = (CVX, XJT) JTK = (DLJ, DLJ) KSP = (LVP, GVM) PFD = (TBR, QDT) MLT = (KSQ, KKJ) GVF = (HFK, GLB) JLS = (PPX, SVK) TBK = (CMQ, GCD) LJB = (QHJ, MFT) KSQ = (PST, TQP) SXC = (PHX, TRP) TTB = (NRP, KMS) VBX = (MHV, SNF) CXV = (PNR, HTT) XCT = (NFS, QGB) JBD = (KRP, SVH) JDX = (HRS, VXC) BNH = (TJQ, SSC) HQD = (RBN, QHP) RXX = (NKP, JKG) NTC = (NND, PNP) QTF = (TVQ, MHR) JND = (FCV, SBH) RDS = (MQB, GCN) FDL = (FLG, VHN) TGJ = (SFL, PHQ) KBX = (GQB, LVX) GQR = (TMD, KQH) LMS = (JBD, GSM) VPJ = (SMJ, XCT) LVQ = (HXL, VNK) GDK = (QBV, FKF) KCD = (PXM, THR) JGG = (GCV, HDH) NFP = (BRK, GLT) SFV = (TBK, XXQ) KJK = (QKN, XPD) CVX = (SBX, QKJ) GCG = (QJF, MDQ) FNB = (VFV, VPQ) CBV = (STX, MBQ) PNH = (QPG, KXN) HFC = (GSJ, RDT) GHF = (FLN, RJF) CKK = (BRV, DKG) LFN = (QKQ, QSK) MNH = (VKF, RQM) MMP = (GJX, JGH) HVB = (SSG, TNR) TMD = (BSJ, VBC) QTS = (NRQ, XDC) TVQ = (PTN, HVB) HTT = (QQV, NCJ) PQM = (KJQ, THS) XJT = (QKJ, SBX) PST = (QGL, DMD) XXT = (MBD, KQV) PCL = (QJP, FXX) MJC = (VPK, VNC) QPV = (JLS, TND) JLJ = (PQM, XSN) BKF = (TVG, JCF) SFT = (FRQ, MQV) XGJ = (HXL, HXL) JSF = (KKJ, KSQ) RMN = (XCT, SMJ) RPV = (TBD, DKP) XLT = (CKM, XVL) DJB = (CMN, XNQ) KCK = (GVB, RMS) LLT = (VFV, VPQ) CVS = (MHR, TVQ) NBS = (VBK, CKK) LJQ = (DMR, FRX) HKS = (TGM, RHV) HTC = (BFR, RFX) LDL = (VMD, SSP) QRV = (HXV, DVF) NST = (TBG, GVL) GQB = (JSF, MLT) KJT = (MBD, KQV) GSJ = (SVQ, JTT) FDX = (TVB, GXP) SSP = (XFM, DFD) FRQ = (LDK, HBD) JLR = (HTD, SVP) HNS = (SPR, TCR) MCZ = (SGM, CGR) GCV = (VPS, MJH) MDQ = (JJC, JXL) RKG = (NHX, CRT) TMT = (NND, PNP) SFC = (KSB, CXF) CQK = (SKS, GPP) FND = (LML, QDS) HVH = (HBN, SVN) CNV = (HMB, JVX) CMQ = (CXS, PCC) NLQ = (JTR, MCM) GDC = (RMQ, RMQ) PHX = (GVD, GVD) NKP = (HXJ, MGF) RRG = (XXQ, TBK) TFP = (BGQ, FBP) GXX = (LJB, MDJ) ================================================ FILE: exm/aoc/2023/aoc_2023_08_questions.txt ================================================ --- Day 8: Haunted Wasteland --- You're still riding a camel across Desert Island when you spot a sandstorm quickly approaching. When you turn to warn the Elf, she disappears before your eyes! To be fair, she had just finished warning you about ghosts a few minutes ago. One of the camel's pouches is labeled "maps" - sure enough, it's full of documents (your puzzle input) about how to navigate the desert. At least, you're pretty sure that's what they are; one of the documents contains a list of left/right instructions, and the rest of the documents seem to describe some kind of network of labeled nodes. It seems like you're meant to use the left/right instructions to navigate the network. Perhaps if you have the camel follow the same instructions, you can escape the haunted wasteland! After examining the maps for a bit, two nodes stick out: AAA and ZZZ. You feel like AAA is where you are now, and you have to follow the left/right instructions until you reach ZZZ. This format defines each node of the network individually. For example: RL AAA = (BBB, CCC) BBB = (DDD, EEE) CCC = (ZZZ, GGG) DDD = (DDD, DDD) EEE = (EEE, EEE) GGG = (GGG, GGG) ZZZ = (ZZZ, ZZZ) Starting with AAA, you need to look up the next element based on the next left/right instruction in your input. In this example, start with AAA and go right (R) by choosing the right element of AAA, CCC. Then, L means to choose the left element of CCC, ZZZ. By following the left/right instructions, you reach ZZZ in 2 steps. Of course, you might not find ZZZ right away. If you run out of left/right instructions, repeat the whole sequence of instructions as necessary: RL really means RLRLRLRLRLRLRLRL... and so on. For example, here is a situation that takes 6 steps to reach ZZZ: LLR AAA = (BBB, BBB) BBB = (AAA, ZZZ) ZZZ = (ZZZ, ZZZ) Starting at AAA, follow the left/right instructions. How many steps are required to reach ZZZ? --- Part Two --- The sandstorm is upon you and you aren't any closer to escaping the wasteland. You had the camel follow the instructions, but you've barely left your starting position. It's going to take significantly more steps to escape! What if the map isn't for people - what if the map is for ghosts? Are ghosts even bound by the laws of spacetime? Only one way to find out. After examining the maps a bit longer, your attention is drawn to a curious fact: the number of nodes with names ending in A is equal to the number ending in Z! If you were a ghost, you'd probably just start at every node that ends with A and follow all of the paths at the same time until they all simultaneously end up at nodes that end with Z. For example: LR 11A = (11B, XXX) 11B = (XXX, 11Z) 11Z = (11B, XXX) 22A = (22B, XXX) 22B = (22C, 22C) 22C = (22Z, 22Z) 22Z = (22B, 22B) XXX = (XXX, XXX) Here, there are two starting nodes, 11A and 22A (because they both end with A). As you follow each left/right instruction, use that instruction to simultaneously navigate away from both nodes you're currently on. Repeat this process until all of the nodes you're currently on end with Z. (If only some of the nodes you're on end with Z, they act like any other node and you continue as normal.) In this example, you would proceed as follows: Step 0: You are at 11A and 22A. Step 1: You choose all of the left paths, leading you to 11B and 22B. Step 2: You choose all of the right paths, leading you to 11Z and 22C. Step 3: You choose all of the left paths, leading you to 11B and 22Z. Step 4: You choose all of the right paths, leading you to 11Z and 22B. Step 5: You choose all of the left paths, leading you to 11B and 22C. Step 6: You choose all of the right paths, leading you to 11Z and 22Z. So, in this example, you end up entirely on nodes that end in Z after 6 steps. Simultaneously start on every node that ends with A. How many steps does it take before you're only on nodes that end with Z? ================================================ FILE: exm/aoc/2023/aoc_2023_09.adb ================================================ -- Solution to Advent of Code 2023, Day 9 ------------------------------------------ -- Mirage Maintenance -- -- https://adventofcode.com/2023/day/9 -- Copy of questions in: aoc_2023_09_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_09 is use AoC_Toolbox, HAT; -- -- input_name : constant VString := +"mini.txt"; m : constant := 3; n : constant := 6; input_name : constant VString := +"aoc_2023_09.txt"; m : constant := 200; n : constant := 21; type Row_Type is array (1 .. n) of Integer; data : array (1 .. m) of Row_Type; procedure Read_Data is f : File_Type; begin Open (f, input_name); for i in 1 .. m loop for j in 1 .. n loop Get (f, data (i)(j)); end loop; end loop; Close (f); end Read_Data; r : array (Part_Type) of Integer; verbose : constant Boolean := False; procedure Do_Parts is check, val, left, right : Integer; last : Positive; -- ____ -- | / -- | / <- diff -- | / -- |/ diff : array (0 .. n) of Row_Type; begin r (part_1) := 0; r (part_2) := 0; for i_data in 1 .. m loop for j in 1 .. n loop diff (0)(j) := data (i_data)(j); end loop; for round in 1 .. n - 1 loop check := 0; for j in 1 .. n - round loop val := diff (round - 1)(j + 1) - diff (round - 1)(j); diff (round)(j) := val; check := check + abs (val); end loop; last := round; exit when check = 0; end loop; left := 0; right := 0; for i in reverse 0 .. last loop right := right + diff (i)(n - i); left := diff (i)(1) - left; end loop; if verbose then -- Out of curiosity: we want to plot the data with the extrapolated values. Put (left); for j in 1 .. n loop Put (data (i_data)(j)); end loop; Put (right); New_Line; end if; r (part_1) := r (part_1) + right; r (part_2) := r (part_2) + left; end loop; end Do_Parts; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Do_Parts; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 1884768153 -- Part 2: validated by AoC: 1031 end if; end AoC_2023_09; ================================================ FILE: exm/aoc/2023/aoc_2023_09.txt ================================================ 25 43 75 138 255 455 773 1250 1933 2875 4135 5778 7875 10503 13745 17690 22433 28075 34723 42490 51495 15 22 50 114 229 410 672 1030 1499 2094 2830 3722 4785 6034 7484 9150 11047 13190 15594 18274 21245 25 37 45 57 103 257 670 1617 3564 7271 13964 25633 45561 79327 136917 237555 421062 774117 1488793 2987794 6182124 3 17 54 120 230 425 791 1489 2829 5466 10872 22355 47064 99648 208537 426194 845159 1622279 3014202 5428018 9491866 25 47 77 111 155 235 402 724 1251 1932 2462 2054 -809 -8433 -23232 -45063 -64008 -43580 115154 646196 2060426 9 15 39 95 208 426 851 1716 3546 7461 15730 32813 67431 136877 276189 557604 1131039 2306127 4713741 9615035 19476706 1 -6 -8 15 106 342 853 1867 3810 7496 14449 27435 51408 95395 176521 328632 620115 1188930 2308050 4502051 8746226 12 17 22 27 32 37 42 47 52 57 62 67 72 77 82 87 92 97 102 107 112 17 18 18 15 3 -16 -9 122 585 1754 4236 8949 17211 30840 52265 84648 132017 199410 293030 420411 590595 -4 10 52 139 306 624 1231 2386 4556 8546 15682 28057 48850 82728 136341 218920 342988 525194 787280 1157191 1670338 -1 9 22 33 37 29 4 -43 -117 -223 -366 -551 -783 -1067 -1408 -1811 -2281 -2823 -3442 -4143 -4931 12 25 38 51 64 77 90 103 116 129 142 155 168 181 194 207 220 233 246 259 272 4 13 46 121 263 512 939 1685 3051 5677 10848 20953 40109 74975 135876 238622 407970 684713 1140118 1904165 3218119 9 5 4 10 27 59 110 184 285 417 584 790 1039 1335 1682 2084 2545 3069 3660 4322 5059 11 17 31 60 115 216 406 790 1625 3499 7665 16678 35706 75431 158678 335480 716439 1544189 3341367 7207300 15395413 1 3 12 42 111 241 458 792 1277 1951 2856 4038 5547 7437 9766 12596 15993 20027 24772 30306 36711 8 14 20 26 32 38 44 50 56 62 68 74 80 86 92 98 104 110 116 122 128 2 17 45 90 167 309 573 1045 1844 3125 5081 7944 11985 17513 24873 34443 46630 61865 80597 103286 130395 3 5 8 25 83 230 541 1117 2066 3459 5278 7432 10045 14499 26326 62366 167432 451676 1172223 2907858 6925638 15 31 53 81 115 155 201 253 311 375 445 521 603 691 785 885 991 1103 1221 1345 1475 24 43 79 142 248 434 777 1425 2670 5120 10065 20208 41107 84069 172095 352295 721984 1483393 3057187 6314066 13037102 13 27 44 74 134 244 434 784 1532 3314 7658 17954 41277 91663 195742 402030 795687 1521173 2815992 5059618 8842760 -5 6 26 65 149 320 644 1246 2412 4831 10091 21583 45992 95545 191119 366158 671073 1177364 1980064 3196213 4955871 14 20 31 51 92 179 352 674 1274 2485 5189 11576 26705 61603 139298 306401 655034 1363686 2771955 5514593 10757022 8 20 31 43 76 193 546 1449 3498 7798 16438 33501 67151 133785 266032 527840 1042692 2046618 3989373 7731849 14939606 -2 13 44 108 239 501 1024 2092 4340 9158 19454 40995 84625 169752 329602 618857 1124426 1980243 3387144 5639046 9156835 15 23 45 84 135 188 234 271 307 357 431 510 507 210 -796 -3231 -8249 -17597 -33807 -60424 -102273 19 24 29 34 39 44 49 54 59 64 69 74 79 84 89 94 99 104 109 114 119 16 22 33 66 144 295 567 1067 2029 3920 7606 14625 27670 51529 95095 175938 330930 640746 1285035 2662828 5646480 18 20 33 73 155 290 482 725 1000 1272 1487 1569 1417 902 -136 -1891 -4594 -8516 -13971 -21319 -30969 9 23 52 101 177 296 489 820 1443 2739 5588 11845 25103 51840 103061 196560 359941 634551 1080492 1782893 2859637 23 37 52 75 129 267 593 1301 2757 5675 11489 23130 46640 94494 192307 391989 796663 1606149 3197006 6258585 12016967 5 25 58 104 163 235 320 418 529 653 790 940 1103 1279 1468 1670 1885 2113 2354 2608 2875 7 22 47 94 178 326 611 1226 2620 5742 12503 26703 55923 115304 234789 472363 937173 1828238 3496871 6544044 11967856 -2 6 24 52 90 138 196 264 342 430 528 636 754 882 1020 1168 1326 1494 1672 1860 2058 15 36 70 118 185 296 529 1079 2385 5385 12023 26230 55766 115612 234193 464886 907519 1748686 3336864 6320194 11893675 18 42 88 181 356 667 1211 2170 3871 6868 12079 21090 36899 65655 120396 228459 445184 877830 1725338 3341795 6334262 10 26 46 67 86 100 106 101 82 46 -10 -89 -194 -328 -494 -695 -934 -1214 -1538 -1909 -2330 1 1 13 54 148 337 710 1457 2948 5823 11054 19900 33617 52703 75349 94627 93771 38693 -133381 -530574 -1330094 7 18 39 90 201 408 744 1225 1831 2482 3009 3120 2361 72 -4662 -13065 -26729 -47678 -78437 -122106 -182439 7 0 1 27 100 247 500 896 1477 2290 3387 4825 6666 8977 11830 15302 19475 24436 30277 37095 44992 0 0 1 1 -1 -2 7 42 127 297 606 1144 2068 3653 6370 10999 18786 31654 52479 85443 136477 24 34 41 55 97 200 413 808 1490 2610 4381 7097 11155 17080 25553 37442 53836 76082 105825 145051 196133 6 4 19 65 166 375 815 1766 3846 8378 18116 38645 80997 166359 334236 656234 1259234 2365352 4364329 7951905 14404284 11 12 16 29 58 106 167 221 229 128 -174 -803 -1924 -3746 -6527 -10579 -16273 -24044 -34396 -47907 -65234 14 27 63 147 328 703 1456 2923 5710 10912 20507 38030 69668 125958 224316 392676 674574 1136073 1874991 3032965 4810960 13 25 30 25 4 -32 -43 124 895 3293 9553 24231 56132 121576 249820 491898 934777 1723609 3096048 5434165 9341508 8 16 42 96 184 318 544 1000 2022 4316 9216 19077 37959 73044 137896 260121 498946 984006 1997384 4140260 8659152 4 20 57 125 234 394 615 907 1280 1744 2309 2985 3782 4710 5779 6999 8380 9932 11665 13589 15714 18 36 76 154 300 567 1040 1845 3158 5214 8316 12844 19264 28137 40128 56015 76698 103208 136716 178542 230164 6 17 34 72 167 394 893 1903 3804 7167 12812 21874 35877 56816 87247 130385 190210 271581 380358 523532 709363 16 17 14 0 -26 -49 -17 202 891 2575 6106 12709 23985 41967 69541 111931 180570 301613 532678 993222 1916376 24 36 60 106 189 342 632 1188 2268 4418 8811 17901 36591 74202 147651 286411 540048 989424 1763038 3060468 5185497 14 21 28 35 42 49 56 63 70 77 84 91 98 105 112 119 126 133 140 147 154 8 14 15 5 -26 -94 -224 -454 -840 -1462 -2431 -3897 -6058 -9170 -13558 -19628 -27880 -38922 -53485 -72439 -96810 9 8 8 30 120 366 922 2039 4103 7680 13568 22856 36990 57846 87810 129865 187685 265736 369384 505010 680132 2 3 14 59 175 416 867 1692 3257 6397 12943 26699 55168 112478 224162 434708 819124 1500167 2673372 4642595 7869461 14 22 53 124 254 464 777 1218 1814 2594 3589 4832 6358 8204 10409 13014 16062 19598 23669 28324 33614 4 15 31 65 143 306 624 1245 2523 5296 11418 24688 52364 107501 212409 403590 738582 1305213 2233849 3713307 6011197 20 29 45 77 136 238 423 800 1644 3609 8197 18762 42564 94764 205819 434557 890356 1769397 3411997 6390651 11641728 2 -5 -12 -3 49 194 530 1239 2632 5201 9676 17085 28815 46672 72938 110423 162510 233191 327092 449485 606285 27 48 74 110 170 277 463 769 1245 1950 2952 4328 6164 8555 11605 15427 20143 25884 32790 41010 50702 15 28 57 105 168 238 317 459 883 2244 6224 16734 42234 100024 223888 477248 975079 1919332 3654603 6753375 12143460 16 34 66 112 172 246 334 436 552 682 826 984 1156 1342 1542 1756 1984 2226 2482 2752 3036 10 12 26 68 166 373 788 1585 3050 5626 9966 16994 27974 44587 69016 104039 153130 220568 311554 432336 590342 9 33 82 178 362 705 1335 2492 4623 8529 15576 27982 49192 84353 140901 229272 363749 563457 853518 1266378 1843318 10 8 21 71 194 447 915 1718 3018 5026 8009 12297 18290 26465 37383 51696 70154 93612 123037 159515 204258 2 17 51 109 205 370 663 1197 2198 4121 7853 15039 28573 53302 96997 171651 295170 493529 803471 1275833 1979589 12 20 44 98 202 398 780 1550 3128 6369 12986 26380 53305 107260 215363 431941 864440 1720854 3393084 6597914 12607128 21 51 110 218 400 684 1110 1765 2865 4914 8996 17324 34313 68700 137643 274332 541473 1054089 2016438 3779482 6927242 18 32 46 60 74 88 102 116 130 144 158 172 186 200 214 228 242 256 270 284 298 -8 -12 -10 0 23 86 280 848 2350 5938 13767 29549 59223 111662 199265 338185 547820 849040 1260436 1791654 2432615 18 35 57 78 83 57 7 -3 196 939 2801 6684 13917 26369 46575 77875 124566 192067 287097 417866 594279 6 9 15 24 43 93 223 543 1291 2952 6450 13437 26706 50758 92556 162502 275676 453379 725025 1130430 1722549 11 12 20 55 160 420 998 2194 4525 8817 16309 28822 49187 82417 138630 239583 431979 812594 1572886 3074249 5969622 13 20 31 46 58 58 47 59 217 882 3020 9022 24420 61383 145852 332290 734422 1589037 3386318 7129763 14840179 -3 3 20 48 87 137 198 270 353 447 552 668 795 933 1082 1242 1413 1595 1788 1992 2207 16 30 55 106 201 363 639 1146 2154 4216 8355 16318 30907 56397 99051 167742 274692 436338 674335 1016706 1499149 18 37 74 140 247 401 590 765 826 655 298 511 4079 18621 62034 172324 424330 956761 2014010 4008334 7609119 11 17 23 29 35 41 47 53 59 65 71 77 83 89 95 101 107 113 119 125 131 21 34 52 89 171 342 674 1282 2364 4316 8023 15535 31590 67018 146244 323350 715118 1566195 3372779 7110296 14643524 4 14 29 52 97 209 496 1173 2618 5440 10559 19298 33487 55579 88778 137179 205920 301346 431185 604736 833069 17 23 38 66 104 143 181 269 628 1909 5729 15718 39484 92203 203086 427013 865693 1706967 3299762 6300778 11967458 6 15 27 46 88 204 522 1314 3104 6852 14277 28419 54586 101887 185616 330825 577506 987893 1656495 2723580 4392948 8 13 24 43 71 112 173 263 401 662 1333 3330 9154 24851 63700 152696 343334 728747 1469918 2834485 5252601 15 28 54 115 244 488 911 1597 2653 4212 6436 9519 13690 19216 26405 35609 47227 61708 79554 101323 127632 21 36 66 119 213 398 801 1708 3700 7863 16095 31536 59150 106491 184688 309687 503791 797542 1231992 1861413 2756499 11 37 85 163 276 427 625 916 1462 2699 5608 12133 25777 52401 101242 186154 327061 551593 896855 1411255 2156290 -8 3 34 100 228 459 847 1467 2465 4216 7711 15396 32890 72420 159609 346723 738050 1537353 3134140 6255932 12229220 8 19 35 63 128 277 592 1224 2460 4835 9301 17465 31908 56597 97402 162730 264288 417987 644999 972979 1437464 -6 -10 -20 -45 -104 -225 -441 -771 -1154 -1267 -94 4992 20051 58048 145352 333842 723414 1503576 3029356 5957273 11483438 14 23 37 65 133 309 745 1746 3887 8218 16642 32656 62862 120056 229382 440113 847236 1629345 3112587 5874795 10909747 5 -2 -10 -5 46 203 566 1294 2628 4921 8693 14759 24538 40772 69130 121701 224611 434984 879612 1844031 3975938 3 21 52 98 164 258 391 577 833 1179 1638 2236 3002 3968 5169 6643 8431 10577 13128 16134 19648 7 8 19 43 82 153 318 734 1746 4081 9271 20562 44795 96170 203655 425577 878602 1795615 3640864 7335774 14692157 21 30 39 48 57 66 75 84 93 102 111 120 129 138 147 156 165 174 183 192 201 -4 8 31 65 110 166 233 311 400 500 611 733 866 1010 1165 1331 1508 1696 1895 2105 2326 18 41 91 193 391 753 1374 2377 3912 6153 9293 13537 19093 26161 34920 45513 58030 72489 88815 106817 126163 -4 -13 -21 -20 7 104 372 1011 2374 5033 9857 18102 31513 52438 83954 130005 195552 286735 411047 577520 796923 10 21 38 65 122 269 649 1560 3571 7704 15715 30537 57037 103464 184452 327378 585520 1064159 1969964 3700241 6997588 11 25 53 95 151 221 305 403 515 641 781 935 1103 1285 1481 1691 1915 2153 2405 2671 2951 19 27 37 67 155 366 799 1594 2939 5077 8313 13021 19651 28736 40899 56860 77443 103583 136333 176871 226507 9 15 21 27 33 39 45 51 57 63 69 75 81 87 93 99 105 111 117 123 129 3 2 4 8 26 103 342 932 2177 4524 8588 15172 25280 40121 61102 89808 127967 177398 239940 317360 411238 0 7 22 49 97 192 400 861 1834 3753 7294 13453 23635 39754 64344 100681 152916 226219 326934 462745 642853 11 5 1 12 65 214 560 1278 2651 5111 9287 16060 26625 42560 65902 99230 145755 209417 294989 408188 555793 -3 -7 -1 22 71 172 404 980 2426 5953 14170 32348 70514 146728 291973 557166 1022875 1812401 3108953 5177706 8393585 4 9 33 104 270 605 1221 2293 4106 7135 12171 20508 34208 56463 92075 148077 234520 365453 560125 844440 1252698 3 13 32 65 140 331 798 1866 4176 8959 18520 37081 72229 137365 255798 467604 841455 1496343 2644958 4686847 8416272 -4 9 37 80 138 211 299 402 520 653 801 964 1142 1335 1543 1766 2004 2257 2525 2808 3106 5 0 -5 -5 5 30 75 145 245 380 555 775 1045 1370 1755 2205 2725 3320 3995 4755 5605 25 43 78 151 294 549 981 1731 3161 6185 12948 28136 61426 132001 276787 565292 1125873 2191223 4175226 7799525 14296726 9 23 54 104 171 247 318 383 521 1055 2904 8310 22339 55989 132571 300568 658990 1406445 2934993 6008892 12105512 7 15 24 30 43 106 335 996 2636 6286 13755 28035 53838 98287 171784 289079 470565 743825 1145458 1723212 2538453 0 -1 10 60 204 537 1214 2494 4829 9024 16499 29689 52623 91728 156909 262961 431374 692597 1088832 1677434 2534998 17 40 84 169 335 649 1215 2194 3851 6665 11565 20397 36818 68040 128383 246740 482281 956726 1918286 3863249 7757949 24 34 37 44 77 177 417 926 1945 3956 7950 15941 31926 63720 126631 251103 498806 996122 2002039 4041362 8157171 10 7 20 65 159 334 677 1412 3045 6604 14025 28763 56755 107970 199046 358139 634506 1118355 1982836 3573131 6593957 -5 -9 -13 -17 -21 -25 -29 -33 -37 -41 -45 -49 -53 -57 -61 -65 -69 -73 -77 -81 -85 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 5 9 28 84 209 461 953 1906 3755 7374 14556 29001 58243 117200 234373 462165 893353 1686439 3103444 5564706 9726413 -3 0 6 27 91 255 623 1366 2741 5106 8928 14781 23331 35305 51441 72416 98749 130676 167994 209871 254619 19 35 54 75 105 168 319 665 1404 2927 6101 12983 28438 63494 141816 311463 665149 1373687 2739636 5282855 9880339 9 21 42 94 206 409 729 1184 1806 2730 4424 8196 17247 38823 88604 199621 440159 948983 2002842 4141990 8396292 2 10 25 52 109 229 473 974 2037 4330 9220 19343 39571 78721 152826 292003 555888 1069234 2103267 4256230 8838981 7 13 27 53 113 265 622 1380 2878 5733 11118 21281 40438 76213 141843 259416 464465 812301 1386533 2310293 3760759 2 4 18 66 183 417 835 1536 2679 4547 7696 13317 24160 46931 98382 220159 513320 1214890 2860322 6614548 14921901 20 42 89 187 375 705 1247 2114 3529 5965 10401 18760 34661 64809 121837 230509 441382 860016 1706553 3431097 6926055 -6 5 41 118 257 497 927 1758 3479 7170 15084 31669 65309 131290 256992 491376 923096 1716263 3182439 5926360 11139249 15 28 50 104 234 511 1047 2038 3883 7461 14703 29703 60831 124753 254153 512771 1025137 2036155 4031423 7980034 15819960 10 6 9 29 78 167 305 517 915 1884 4505 11474 29080 71443 169472 389344 869428 1891498 4013213 8306107 16769254 10 9 13 26 47 67 72 60 80 301 1119 3310 8237 18119 36370 68016 120198 202769 328993 516354 787483 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 22 49 104 198 350 603 1059 1958 3838 7824 16114 32786 65193 126523 240683 451628 840658 1556967 2868476 5240830 9450668 16 39 79 153 287 511 853 1343 2046 3153 5181 9391 18683 39591 86823 193521 433828 970699 2153123 4705917 10086151 5 16 35 58 78 83 57 -1 -19 264 1480 4880 12692 28852 61020 126369 267104 588917 1350257 3159230 7390503 18 28 39 54 85 169 397 952 2164 4623 9465 19094 38871 80748 170523 361426 758214 1557966 3116451 6052430 11406697 3 5 19 48 91 146 221 356 666 1430 3272 7505 16736 35857 73572 144631 272957 495859 869521 1475942 2431473 30 41 45 51 93 250 668 1574 3282 6229 11158 19698 35791 68696 138673 286929 592006 1195521 2341043 4430925 8107113 11 22 53 115 230 453 910 1857 3765 7436 14155 25883 45496 77075 126252 200617 310191 467970 690545 998803 1418714 5 15 35 70 138 276 563 1187 2595 5777 12747 27296 56104 110310 207651 375293 653489 1100211 1796915 2855610 4427414 13 15 18 28 59 132 275 532 1003 1974 4268 10067 24633 59605 138881 308521 652641 1317921 2550134 4747030 8532991 19 31 39 37 30 50 187 653 1901 4825 11071 23493 46792 88380 159515 276757 463799 753731 1191799 1838725 2774658 4 -4 -5 12 63 178 426 964 2108 4408 8686 15974 27291 43265 63797 88353 118140 162456 252973 471660 1000479 8 26 56 102 170 269 420 688 1275 2754 6596 16260 39305 91285 202677 430899 880826 1739482 3334372 6231134 11396188 11 23 35 47 59 71 83 95 107 119 131 143 155 167 179 191 203 215 227 239 251 17 23 29 48 111 275 640 1382 2809 5447 10163 18332 32055 54435 89918 144706 227249 348823 524201 772424 1117679 5 12 24 46 90 177 332 567 849 1058 963 297 -884 -1191 4419 29378 104397 293136 718466 1604688 3343062 10 24 38 53 80 146 294 583 1116 2156 4430 9770 22312 50621 111465 236805 487438 980612 1946642 3844527 7595464 4 -1 2 29 103 254 519 942 1574 2473 3704 5339 7457 10144 13493 17604 22584 28547 35614 43913 53579 5 3 8 25 54 90 123 138 115 29 -150 -457 -932 -1620 -2571 -3840 -5487 -7577 -10180 -13371 -17230 19 30 46 85 184 416 929 2025 4306 8935 18119 36059 70900 138785 272218 537010 1065858 2123285 4228117 8378734 16457241 4 12 21 29 29 14 -11 -8 139 735 2539 7342 19120 46167 104805 225519 462686 909470 1719953 3141179 5558519 12 17 33 83 215 524 1191 2554 5245 10458 20461 39545 75752 144023 272029 511254 958606 1799275 3392061 6437763 12305329 10 26 62 133 273 562 1163 2376 4720 9059 16803 30264 53379 93309 164006 293873 541334 1024736 1976820 3839359 7420837 26 38 50 62 74 86 98 110 122 134 146 158 170 182 194 206 218 230 242 254 266 17 33 59 102 172 282 448 689 1027 1487 2097 2888 3894 5152 6702 8587 10853 13549 16727 20442 24752 14 31 60 120 251 526 1063 2037 3692 6353 10438 16470 25089 37064 53305 74875 103002 139091 184736 241732 312087 23 39 58 80 105 133 164 198 235 275 318 364 413 465 520 578 639 703 770 840 913 21 45 93 181 329 569 959 1612 2762 4916 9199 18122 37251 78725 168410 359900 760925 1581649 3221326 6423446 12558361 -5 -6 8 60 185 441 929 1831 3495 6640 12841 25616 52734 110904 234974 495463 1031149 2108352 4226908 8307194 16017545 13 24 53 117 244 473 854 1448 2327 3574 5283 7559 10518 14287 19004 24818 31889 40388 50497 62409 76328 23 40 64 104 189 396 894 2017 4403 9279 19055 38564 77656 156620 317410 646440 1319635 2688726 5441230 10887612 21461091 15 35 59 84 104 107 73 -29 -252 -702 -1606 -3439 -7137 -14428 -28318 -53774 -98651 -174915 -300219 -499894 -809422 0 7 22 50 96 165 262 392 560 771 1030 1342 1712 2145 2646 3220 3872 4607 5430 6346 7360 2 12 37 84 178 378 809 1720 3572 7147 13653 24792 42771 70275 110468 167082 244466 346870 474873 614196 707420 19 35 73 159 337 676 1293 2416 4518 8558 16368 31226 58654 107477 191174 329545 550709 893437 1409811 2168185 3256407 9 10 18 54 150 354 744 1462 2789 5290 10064 19142 36094 66946 121586 215974 375689 641674 1079510 1794198 2953294 -8 -9 1 44 170 476 1137 2452 4909 9283 16817 29640 51840 92218 171054 335896 696763 1501852 3296020 7246003 15797579 27 37 57 108 228 494 1063 2249 4674 9561 19276 38271 74625 142426 265316 481736 852989 1476613 2510427 4218046 7056162 0 4 9 15 22 30 39 49 60 72 85 99 114 130 147 165 184 204 225 247 270 24 41 71 123 206 329 501 731 1028 1401 1859 2411 3066 3833 4721 5739 6896 8201 9663 11291 13094 16 28 54 121 284 652 1429 2986 6003 11753 22654 43318 82532 157006 298461 566931 1075374 2034406 3832134 7174207 13325792 9 2 -1 22 122 403 1062 2465 5288 10752 20979 39509 72072 127838 221613 377857 638023 1073610 1808547 3056140 5177882 8 6 -4 -16 -3 97 412 1212 3075 7218 16131 34785 72949 149641 301604 599185 1175500 2278885 4365104 8255185 15396599 -1 0 -2 -4 0 18 58 136 333 985 3169 9798 27930 73457 180383 418770 928688 1983079 4101909 8255993 16225829 10 7 18 60 154 341 715 1481 3050 6188 12243 23483 43588 78348 136624 231626 382546 616549 971064 1496222 2257150 -2 2 23 87 236 541 1124 2188 4054 7204 12329 20381 32628 50711 76702 113162 163198 230518 319483 435155 583340 -4 -5 -9 -13 -5 34 136 384 1018 2657 6697 15957 35657 74824 148234 279010 502008 868135 1449755 2347351 3697623 16 14 9 16 60 175 409 841 1620 3040 5669 10554 19528 35649 63805 111523 190024 315570 511153 808580 1251012 -10 -17 -26 -37 -50 -65 -82 -101 -122 -145 -170 -197 -226 -257 -290 -325 -362 -401 -442 -485 -530 -2 -3 2 27 101 292 744 1727 3700 7387 13866 24671 41907 68378 107728 164595 244778 355417 505186 704499 965729 14 19 26 35 46 59 74 91 110 131 154 179 206 235 266 299 334 371 410 451 494 7 12 28 64 131 242 412 658 999 1456 2052 2812 3763 4934 6356 8062 10087 12468 15244 18456 22147 14 28 39 55 110 281 718 1708 3804 8057 16389 32139 60822 111236 197437 343264 594082 1047282 1927607 3762071 7762782 5 25 56 98 154 234 364 613 1160 2436 5396 12008 26111 54967 112318 225021 448287 900835 1843624 3848550 8143064 10 35 77 139 224 335 475 647 854 1099 1385 1715 2092 2519 2999 3535 4130 4787 5509 6299 7160 7 14 17 19 45 153 454 1150 2598 5424 10768 20884 40634 81060 167480 356960 774538 1685999 3640496 7744350 16177032 0 2 19 63 160 370 813 1711 3477 6920 13712 27414 55642 114484 237295 492021 1015343 2080463 4232825 8563395 17259507 12 41 89 163 277 462 780 1342 2329 4016 6810 11357 18909 32508 60437 125397 287091 694318 1698939 4095063 9606004 21 27 27 26 46 130 358 886 2028 4432 9463 20008 42069 87719 180272 362870 712127 1359001 2519699 4540166 7958576 16 12 8 10 25 61 127 233 390 610 906 1292 1783 2395 3145 4051 5132 6408 7900 9630 11621 4 20 49 89 144 249 517 1225 2979 7045 16029 35280 75762 159850 332827 685291 1396165 2814424 5613910 11087815 21714227 6 22 55 114 213 377 658 1168 2136 3996 7513 13954 25311 44583 76124 126064 202810 317634 485355 725122 1061305 1 3 7 17 57 186 511 1189 2411 4377 7310 11626 18478 31019 56865 112353 229233 464339 912461 1721971 3111595 27 41 63 115 229 447 829 1486 2678 5049 10112 21147 44734 93211 188424 367222 689245 1247657 2183589 3705179 6112227 22 38 68 121 204 333 552 971 1841 3684 7487 14956 28841 53475 96109 170733 308506 583836 1174568 2492081 5448060 1 14 38 81 162 330 694 1461 2976 5757 10528 18293 30599 50369 84163 147660 277931 559352 1175870 2512485 5345816 2 6 10 14 18 22 26 30 34 38 42 46 50 54 58 62 66 70 74 78 82 10 23 57 123 244 483 982 2019 4099 8102 15522 28868 52407 93688 166813 299382 546656 1019041 1932855 3699937 7079518 ================================================ FILE: exm/aoc/2023/aoc_2023_09_questions.txt ================================================ --- Day 9: Mirage Maintenance --- You ride the camel through the sandstorm and stop where the ghost's maps told you to stop. The sandstorm subsequently subsides, somehow seeing you standing at an oasis! The camel goes to get some water and you stretch your neck. As you look up, you discover what must be yet another giant floating island, this one made of metal! That must be where the parts to fix the sand machines come from. There's even a hang glider partially buried in the sand here; once the sun rises and heats up the sand, you might be able to use the glider and the hot air to get all the way up to the metal island! While you wait for the sun to rise, you admire the oasis hidden here in the middle of Desert Island. It must have a delicate ecosystem; you might as well take some ecological readings while you wait. Maybe you can report any environmental instabilities you find to someone so the oasis can be around for the next sandstorm-worn traveler. You pull out your handy Oasis And Sand Instability Sensor and analyze your surroundings. The OASIS produces a report of many values and how they are changing over time (your puzzle input). Each line in the report contains the history of a single value. For example: 0 3 6 9 12 15 1 3 6 10 15 21 10 13 16 21 30 45 To best protect the oasis, your environmental report should include a prediction of the next value in each history. To do this, start by making a new sequence from the difference at each step of your history. If that sequence is not all zeroes, repeat this process, using the sequence you just generated as the input sequence. Once all of the values in your latest sequence are zeroes, you can extrapolate what the next value of the original history should be. In the above dataset, the first history is 0 3 6 9 12 15. Because the values increase by 3 each step, the first sequence of differences that you generate will be 3 3 3 3 3. Note that this sequence has one fewer value than the input sequence because at each step it considers two numbers from the input. Since these values aren't all zero, repeat the process: the values differ by 0 at each step, so the next sequence is 0 0 0 0. This means you have enough information to extrapolate the history! Visually, these sequences can be arranged like this: 0 3 6 9 12 15 3 3 3 3 3 0 0 0 0 To extrapolate, start by adding a new zero to the end of your list of zeroes; because the zeroes represent differences between the two values above them, this also means there is now a placeholder in every sequence above it: 0 3 6 9 12 15 B 3 3 3 3 3 A 0 0 0 0 0 You can then start filling in placeholders from the bottom up. A needs to be the result of increasing 3 (the value to its left) by 0 (the value below it); this means A must be 3: 0 3 6 9 12 15 B 3 3 3 3 3 3 0 0 0 0 0 Finally, you can fill in B, which needs to be the result of increasing 15 (the value to its left) by 3 (the value below it), or 18: 0 3 6 9 12 15 18 3 3 3 3 3 3 0 0 0 0 0 So, the next value of the first history is 18. Finding all-zero differences for the second history requires an additional sequence: 1 3 6 10 15 21 2 3 4 5 6 1 1 1 1 0 0 0 Then, following the same process as before, work out the next value in each sequence from the bottom up: 1 3 6 10 15 21 28 2 3 4 5 6 7 1 1 1 1 1 0 0 0 0 So, the next value of the second history is 28. The third history requires even more sequences, but its next value can be found the same way: 10 13 16 21 30 45 68 3 3 5 9 15 23 0 2 4 6 8 2 2 2 2 0 0 0 So, the next value of the third history is 68. If you find the next value for each history in this example and add them together, you get 114. Analyze your OASIS report and extrapolate the next value for each history. What is the sum of these extrapolated values? --- Part Two --- Of course, it would be nice to have even more history included in your report. Surely it's safe to just extrapolate backwards as well, right? For each history, repeat the process of finding differences until the sequence of differences is entirely zero. Then, rather than adding a zero to the end and filling in the next values of each previous sequence, you should instead add a zero to the beginning of your sequence of zeroes, then fill in new first values for each previous sequence. In particular, here is what the third example history looks like when extrapolating back in time: 5 10 13 16 21 30 45 5 3 3 5 9 15 -2 0 2 4 6 2 2 2 2 0 0 0 Adding the new values on the left side of each sequence from bottom to top eventually reveals the new left-most history value: 5. Doing this for the remaining example data above results in previous values of -3 for the first history and 0 for the second history. Adding all three new values together produces 2. Analyze your OASIS report again, this time extrapolating the previous value for each history. What is the sum of these extrapolated values? ================================================ FILE: exm/aoc/2023/aoc_2023_10.adb ================================================ -- Solution to Advent of Code 2023, Day 10 ------------------------------------------- -- Pipe Maze -- -- https://adventofcode.com/2023/day/10 -- Copy of questions in: aoc_2023_10_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_10 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 20; nx3 : constant := 60; input_name : constant VString := +"aoc_2023_10"; n : constant := 140; nx3 : constant := 420; map : array (1 .. n, 1 .. n) of Character; si, sj : Positive; procedure Read_Data is f : File_Type; c : Character; begin Open (f, input_name & ".txt"); for i in 1 .. n loop for j in 1 .. n loop Get (f, c); if c = 'S' then si := i; sj := j; end if; map (i, j) := c; end loop; end loop; Close (f); end Read_Data; r : array (Part_Type) of Integer; type State is (clean, path, outside); visited : array (1 .. n, 1 .. n) of State; visited_x3 : array (1 .. nx3, 1 .. nx3) of State; path_length : Natural := 0; procedure Do_Part_1 is i, j : Positive; iii, jjj : Natural; i3, j3 : Integer; p : Character; procedure Go is begin i := iii; j := jjj; visited (i, j) := path; path_length := path_length + 1; end Go; begin for i in 1 .. n loop for j in 1 .. n loop visited (i, j) := clean; end loop; end loop; for i in 1 .. nx3 loop for j in 1 .. nx3 loop visited_x3 (i, j) := clean; end loop; end loop; i := si; j := sj; p := map (i, j); main : loop scan : for ii in -1 .. 1 loop for jj in -1 .. 1 loop if abs (ii) + abs (jj) = 1 then iii := i + ii; jjj := j + jj; -- Try next move on iii, jjj i3 := 1 + (iii - 1) * 3; j3 := 1 + (jjj - 1) * 3; if iii in 1 .. n and then jjj in 1 .. n and then visited (iii, jjj) = clean then case map (iii, jjj) is when '|' => if (ii = 1 and then (p = 'S' or else p = '|' or else p = 'F' or else p = '7')) or else (ii = -1 and then (p = 'S' or else p = '|' or else p = 'L' or else p = 'J')) then Go; -- Draw on 3x3 square. Here we have: -- -- .#. -- .#. -- .#. -- visited_x3 (i3, j3 + 1) := path; visited_x3 (i3 + 1, j3 + 1) := path; visited_x3 (i3 + 2, j3 + 1) := path; exit scan; end if; when '-' => if (jj = 1 and then (p = 'S' or else p = '-' or else p = 'L' or else p = 'F')) or else (jj = -1 and then (p = 'S' or else p = '-' or else p = '7' or else p = 'J')) then Go; -- Draw on 3x3 square visited_x3 (i3 + 1, j3) := path; visited_x3 (i3 + 1, j3 + 1) := path; visited_x3 (i3 + 1, j3 + 2) := path; exit scan; end if; when 'L' => if (ii = 1 and then (p = 'S' or else p = '|' or else p = 'F' or else p = '7')) or else (jj = -1 and then (p = 'S' or else p = '-' or else p = '7' or else p = 'J')) then Go; -- Draw on 3x3 square. Here we have: -- -- .#. -- .## -- ... -- visited_x3 (i3, j3 + 1) := path; visited_x3 (i3 + 1, j3 + 1) := path; visited_x3 (i3 + 1, j3 + 2) := path; exit scan; end if; when 'J' => if (ii = 1 and then (p = 'S' or else p = '|' or else p = 'F' or else p = '7')) or else (jj = 1 and then (p = 'S' or else p = '-' or else p = 'L' or else p = 'F')) then Go; -- Draw on 3x3 square visited_x3 (i3, j3 + 1) := path; visited_x3 (i3 + 1, j3) := path; visited_x3 (i3 + 1, j3 + 1) := path; exit scan; end if; when '7' => if (ii = -1 and then (p = 'S' or else p = '|' or else p = 'L' or else p = 'J')) or else (jj = 1 and then (p = 'S' or else p = '-' or else p = 'L' or else p = 'F')) then Go; -- Draw on 3x3 square visited_x3 (i3 + 1, j3) := path; visited_x3 (i3 + 1, j3 + 1) := path; visited_x3 (i3 + 2, j3 + 1) := path; exit scan; end if; when 'F' => if (ii = -1 and then (p = 'S' or else p = '|' or else p = 'L' or else p = 'J')) or else (jj = -1 and then (p = 'S' or else p = '-' or else p = '7' or else p = 'J')) then Go; -- Draw on 3x3 square visited_x3 (i3 + 1, j3 + 1) := path; visited_x3 (i3 + 1, j3 + 2) := path; visited_x3 (i3 + 2, j3 + 1) := path; exit scan; end if; when 'S' => if (ii = -1 and then (p = '|' or else p = 'L' or else p = 'J')) or else (jj = -1 and then (p = '-' or else p = '7' or else p = 'J')) or else (ii = 1 and then (p = '|' or else p = 'F' or else p = '7')) or else (jj = 1 and then (p = '-' or else p = 'L' or else p = 'F')) then if path_length > 1 then -- Avoid immediate return to Start. -- put("back!"); Go; -- Draw a cross on 3x3 square visited_x3 (i3, j3 + 1) := path; visited_x3 (i3 + 1, j3) := path; visited_x3 (i3 + 1, j3 + 1) := path; visited_x3 (i3 + 1, j3 + 2) := path; visited_x3 (i3 + 2, j3 + 1) := path; exit scan; end if; end if; when others => null; end case; end if; end if; end loop; end loop scan; p := map (i, j); exit main when p = 'S'; end loop main; r (part_1) := path_length / 2; end Do_Part_1; verbose : constant Boolean := False; -- PPM picture output, adapted from AoC_2022_12. -- procedure Dump_PPM is d : File_Type; i, j : Integer; begin Create (d, input_name & ".ppm"); Put (d, "P6" & Chr (10)); Put (d, nx3); Put (d, ' '); Put (d, nx3); Put (d, Chr (10)); Put (d, "255" & Chr (10)); for i3 in 1 .. nx3 loop for j3 in 1 .. nx3 loop i := (i3 - 1) / 3 + 1; j := (j3 - 1) / 3 + 1; case visited_x3 (i3, j3) is when clean => if visited (i, j) = clean then -- "inside" tile Put (d, Chr (230)); Put (d, Chr (255)); Put (d, Chr (110)); else -- partly "inside" tile Put (d, Chr (160)); Put (d, Chr (240)); Put (d, Chr (190)); end if; when path => Put (d, Chr (0)); Put (d, Chr (0)); Put (d, Chr (0)); when outside => if visited (i, j) = outside then -- "outside" tile Put (d, Chr (255)); Put (d, Chr (255)); Put (d, Chr (255)); else -- partly "outside" tile Put (d, Chr (220)); Put (d, Chr (220)); Put (d, Chr (220)); end if; end case; end loop; end loop; Close (d); end Dump_PPM; procedure Do_Part_2 is procedure Flood_Fill (i, j : Integer) is -- Taken from aoc_2022_18. begin if i in 1 .. nx3 and then j in 1 .. nx3 and then visited_x3 (i, j) = clean then visited_x3 (i, j) := outside; Flood_Fill (i - 1, j); Flood_Fill (i + 1, j); Flood_Fill (i, j - 1); Flood_Fill (i, j + 1); end if; end Flood_Fill; c : Natural := 0; i3, j3, sq : Natural; begin -- Flood fill the outside part, starting -- from the (1, 3) point of the detailed map. -- The big path never touches the detailed map's border -- (otherwise, the path would not be closed). -- Consequently, the set outside the path is connected -- and we are fine starting with the (1, 3) point only. -- Why not (1, 1)? It is to handle the case where the -- start point (S), drawn as a cross, is in the top left corner. -- Flood_Fill (1, 3); for i in 1 .. n loop for j in 1 .. n loop sq := 0; i3 := 1 + (i - 1) * 3; j3 := 1 + (j - 1) * 3; for ii in 0 .. 2 loop for jj in 0 .. 2 loop if visited_x3 (i3 + ii, j3 + jj) = outside then sq := sq + 1; end if; end loop; end loop; if sq = 9 then -- The entire 3x3 square is marked as "outside". -- Then it is neither an inside tile, nor a tile with -- the giant loop on it. -- In the latter case, we have, for instance for a 'L', -- only 8 squares set as visited: -- -- OpI -- Opp -- OOO -- -- O = outside, set by Flood_Fill -- p = path of the giant loop, set by part 1 -- I = inside; not set. -- c := c + 1; visited (i, j) := outside; -- This is just for the visualisation end if; end loop; end loop; -- Inside = surface - path's length - outside. r (part_2) := n * n - path_length - c; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if verbose then Dump_PPM; end if; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 6897 -- Part 2: validated by AoC: 367 end if; end AoC_2023_10; ================================================ FILE: exm/aoc/2023/aoc_2023_10.txt ================================================ |J.7F7-L--77F7-J-F-77FF-7FLLJ7F-J-F---7-J-L-FJ-FJFJ7-7-FF--L7.L--|.FJ-J77FFF|77-7F-7-FFL7-|7-F7-L7F7FF7.|----LL-77FF.F--F-J-LFFL-F-LF7--F-FL L.---7FF--LJ7J7..L7LFJ.||FJL|LJ.|77.LJ|F|||7J|.|7|JJFF-L--F-|7..L.F-J7JLL--7|J|7.|L-7-7J|F-7-L|J|||-F7F-FJ|..|LFJLJ.-.|||JJ-LFL.||.L|L-JLJJ. .|L|7|FJJ7L-7F777L|FLJ-FFL-FL-7FJ.|F-LLLJ||.L--77J7-FLJ.L-F-F-7.LFLJ-|L||..77.|F77-L7JL-7JFJ7|FF-L7-LL--|-L.|-7L-J|7..L7||.LFJ7L7JF7.7J7-7-| LFF--7F|FJLLLJL|7J||.LF-JLL|J.|77F-J7.LJ-|--7F7|L7--|.L.7J||F7L7L7F|FF7-J|7||7F||J7-7.LJJ7J--L7JL7||.LL-||L77||-LF-7FF7L--F-LFJJJF|L7L---JJ| .LL|L7JF|||..L7|.FF-77|||77.LL7-JJJLL.F..LF-FJLL-L7L|7|F|FF7F7JF7JF7|||7--|7FFFJ|FF7F777..F-J-|.LJ|FFF-7FF.|L-J.FJ.|7LJ.L7|FLFJJF||LL.|.|J.J JJL7F|FL-77-L-7F7-|.|F-JJL777L|FLJ..|---FF..|.L-7FF||-LFF7||||-|JFJ|FJ|J7L|JFFL7L7||||-F7FJL7L777LJ-|JF||J7F-J77||.L|7J--J|L.-.77FJ.L7-7L.-L FF.LJ-JLFJ|-|F-|JF77-F7JF|JF7||7J7F-7.LFJL-77.L7|F7F77.FJ||||L7JF|FJL7|F|F7F---JFJ||||-77LL-|7|FJ-|..F--7|FF7|L-F-J..|J|.LF||F-.LJ|7.|.||||. LJ.|FJ|-|JJJ|LL--|JL-LJ7L||L-LF7LFF7F77JJ7JF7-F-7||||F7L7LJ||FJFFJL--JL7F-7L7F-7L-JLJL7.7||F77JJF-J--LJL-F-7F7.||7F7-7-L7F-7L|J-F|L7LL-F-L7. LLF--JFF.L.F|J.|LL----F77JF7||LL-FJLJL7.F7.|L7|FJ|LJ|||-L-7LJ|F7L-7F---JL7L7LJFL7F----J-F7FJL7JF|LJJ-.F-J|FJ||F7F777.|LLFJLL-J-|FJ-|L|-|.L|7 ||||-F.F7.FF--7L-J7.J.LJJ7L|-7.LFL-7F-JF-LFL7||L-JF-J||F7-L7FJ|L7-|L-7|LF|FJ7FL.||JF7.LFJLJF-J.F|-LJ|.LFFJL7|||LJ|F7-F..7J7.FJ.|J..LLJJ||-7. FFL.FF-F7.F|-..-.7FJ7.J7LL-LFL-7-|FJL7-|J-F7||L--7L--JLJ|7FJL-JFJFJF-J-.FJ|F7JLFJ|FJL77L--7|JF7F77L|F77LL-7|||L7FJ||7F.F7L|JLFJJ|.7--7.JJ|.| --JF|J7L--FJLLJL-|-||-.L-|.FJJLJFF|F-JF-7FJLJ|F7FJF-----JFL7F-7|FJFJF7LFL7|||FFJFJL-7L7.F-JL7||||FFF77-LF-J||||||FJL--7|L-7JJ|-FL-J.FF-JL7JJ L7FJ.LF77||.7F|FFJ.L7.F-F|.JJ..F7|||F7|FJ|F-7LJ|L7|F--77F-7LJ7|||FJFJL77FJ|||FJFJF7|L7L7L-7FJ||||FFJ|77|L-7||L7|||F---JL7FJ..|-FF7L-|.J-7JF- -|F-77L77FF-JLJ-|FFJF.7FLL7.FF-JL-JLJ||L7LJFJF7L-J||F7L7L7L7F-J|||-L7FJFJFJ|LJFJL|L--JFJF7|L-JLJL7L7|77-L-|||FJ|||L-7F--JL7F77FF|.-JF7|F7FFL FJ|-.-7|FJJFFL7JL-L7|-LL-|L-FL-7F7F7FJ|FJJ|L-JL7F-JLJL7|FJFJ|F7LJL7FJL-JFJ-L7FJJFL---7L7|||F7F---J.||F7|-FJLJL-J||F7|L--7FJ||F77JJ||L|LFJ|J. JJJJ.|FLJLFL7L|-7|LF|7LLLJ|7F.LLJLJ||FJ|JF7F7FFJL7F7F-J||FJ7LJL-7FJL---7|F7F|L-77F7F-JFJ||||LJF7F7F|LJL7FJF--7F-J||LJF7FJL-JLJ|-J|FJ7LF.L|J- L|FFJJJJ..L7.F|.F77.|J-F7F|F|7FF-7L|||FJFJLJL7L7FJ||L7FJ||-F7F7L||.F7F7||||FJF-JFJ|L-7L-JLJ|JFJ||L7L--7|L-JF7||F-JL7FJ||F-----JL7-|J..L7||.. F-7|7J|JFF-77L-7FF|-||.|.F7F-7LL7L-JLJ|JL-7F-JFJ||||FJL-JL7||||FJL7|||LJLJLJFJF7L7|F-JF7F-7L-JFJL7L-7FJL7LFJLJLJF--JL7||L-7F7F7F77|-.77FLF-| .L|LJ-FJ|L-7L.L-.L|.F--FL||7-F7|L---7FJF7J|L7.L7L7||L----7|||||L-7LJ|L7F7F7FJ7||FJ||F7||L7L---JF7|F-J|F7L7L--7F-JF-7FJLJF7LJLJLJL7-.FJFL|J.L 7L|J-FL--7.-...L77L-JLF7J|L7F||F----JL7||FJFJF7L7|||F--7F||||||F7L-7L-J|||LJF7||L7|LJ||L-JF7JF7|LJL-7LJL7|F7FJ|F7L7|L7F7||F7F7F--J--.F-J|JFJ |J|7..J|F77.77-FJF--F-J|FJFJF||L--7F7FJ||L7L7|L-J|||L-7|FJLJ||LJ|F7|F--JLJF7|||L7||F-JL77FJL7||L-7F-JJF-J|||L7||L7||L||LJLJ|||L-7|FLL|F-7||J L-|L-J.7-J|-LJLJ-|JLL-7LJFJF7|L7F7LJ||F||FJFJL--7LJL-7||L--7||F-J|LJL----7|LJ||FJ||L-7FJFJF-J||FFJL--7L-7|||||LJFJ||FJL77F7LJL-7|777L|LJLF7. LFLJ...L7.L7.F7J7F.FLL|F7L-JLJFJ||F-JL-JLJFJF7F7L-7F-J||F7FJLJL-7L7F--7F7||F7LJL-JL7J||7L7L7FJ|FJF---JF-JLJL7L-7L-JLJF-JFJL7F7LLJL|7-F.|-J77 FF-FL-7LJ.L|77|FF|JJ7LLJL7F--7|FJ|L----7F-JF|LJL7L|L-7|LJLJF-7F-JL||F7LJLJLJL-7F---JFJ|F7|FJ|FJ|FJF-7FJF7F7FJF7L7F7F7L--JF7LJL--77|J.|LF-L7J -F-F-JJ7L-FLJ7F|F-7||-|F7LJF-J||FJF-77FJL--7L-7FJFJF-JL----JFJL7LFJLJL7F7F7F7FJL--7-|FJ|LJL-JL7|L7L7|L-JLJ|L-J|FJ|LJL----JL-----JF777L7J--J| JJ.LFLL------J7-JLF-FF7||F7L-7|||FJFJFJF--7|F-JL7L7L7F7F7F--JF7L7L7F--J||||||L7F--JFJL7L----7FJ|FJFJL-7F--JF--JL7L--7F7F7F7F7F7F-JL-7||.-J-7 FJ-FFF7J-JF|.|JL||LF7||||||F-JLJ|L7L7L7|F7LJL--7|||FJ||||L7F-J|FJFJL7F7|||LJL7|L7FFJF7L7F7F-JL7||F|F--JL--7|F---JF--J|LJLJLJLJLJF---J7J.LJ|| --F-|JJ.|-|7-7.FJF-J||||LJLJF--7L7|FJ-|LJL7LF77||FJ|F|LJ||LJ-FJL7L7FJ||||L--7|L7|FJFJL-J||L--7LJL7|L7F7F7FJLJF7F7L---JF--7F7F--7L7|FLJL7|LFJ .|..L77FF-JJF-777L-7LJ||F---JF7|FJ|L-7|F--JFJL-J|L7|FJF-JF77FJF-JFJ|J||||F77||FJ||FJ7F-7|L7F7|F--J|FJ||||L-7FJLJL-----JF7LJ|L-7L-J-F-J-FJ||| -L7.F-FFJ||LL7|F-77L-7|LJF7F-J|||FJF-J||FF7L---7L7||L7L-7|L7L7|F7L7|FJLJ|||FJLJFJ||F7L7||FJ|LJL7F7||FJ|||F7|L7JF7F7F---JL-7|F7L----7LJLJ7L-7 L7|J7|J||F-7FJLJFJF--JL7FJ|L-7||||FJJFJL-J|F7F7|FJ||-|F-JL7|FJLJ|FJ||F--J||L--7|FJ||L7|LJL7L-7FJ|LJ|L7LJ|||L7L-JLJLJF-----J||L7F---J7.FFLJ|| LF|-77-L7L7|L--7L-JF7F7||FJF-J|||||F7L7F-7||LJ|||FJ|FJL7F7||L--7LJFJ|L7F7||F7FJ|L7|L7||F7FJF7||LL-7L7L-7|||FJF7F-7F7L--7F7LLJFJL--7.77F7|F-. F7L-JJLFLJ|L7F7L--7||||LJL7L-7|||||||FJL7LJL-7LJ||FJL7FJ||||F7FJF-JL|FJ|LJ|||L7|FJL7||LJ|L7|LJL7F7|FJF-J||||FJLJJLJL--7LJL7F7|F---J7J-JL77.L F|-.||FFL-L7LJL---J|||L-7FJF-JLJ|||||L-7L7F7|L-7|||F-J|FJ|||||L7|F7FJL7L7FJ|L7||L-7||L7FL7||F--J|||L7L-7||||L7F------7L7F7LJ|LJF--7JF7.LJF-7 .LJF-7J..JFL--7F-7FJLJF-JL-JF--7|||||F7|FJ||F7J||||L-7|L7|||||F||||L7FJL||.|FJ||F7|||FJF7||||F7J|||FJF7|||||FJL7F---7|.LJL--JF7|F-J.|7FLFL-7 ||.-7|.L|FF.|FJ|.S|LF7L----7|F-JLJ|||||||FJ|||FJ|||F7|L7||||||FJ|||FJ|F-JL7|L7|||||||L7|||||||L7|||L7|LJLJLJL--JL7F7LJF7F-7LFJLJL--7JJ7.--7| J7FL-J77L-J.LL-JFJ|FJL----7||L-7F7LJLJ|||L7LJ|L7|||||L7||LJ||||FJ|||FJL-7FJL7||||||LJFJ|||||LJFJ|||FJL7F7F7F7F7F-J||F7|||FJFJF7F7F7|.FL7LFJJ |L|7||7-|J.FJLF-JFJL-----7|LJF7||L---7LJL7|F7L7||||||FJ|L-7LJLJL7||||F-7|L7FJ||LJ|L-7L7|LJ|L-7|FJ||L7FJ|LJLJLJLJF7|||LJ||L-JFJLJ||LJ7-|.FJL. F7|FF|J---L|.FL7FJF--7JF7|L7F||LJF---JF--JLJL7LJ||LJ||FJF-J|F---J|LJ||J|L7|L7|L7FJF7L7LJF-JF-J||F||FJL7L---7F7F7|||||F-J|F--JF-7LJ||J7LF7--F |LL|.LL--7.7-F7||JL-7L7||L7L7|L7JL---7|F7F7F7L7FJL-7||L7L--7L7F7FJF-JL7|FJL7||FJL7|L7|F-JF7|F-JL7||L7FJFF-7||||||LJLJL-7||F7LL7L7F-77||||F|. L...--LL.LF-7||LJF7LL7LJL7L7|L7L--7F7|LJ||||L7||F7FJ||7L7F-JF||||.L-7FJ|L7FJ||L7FJ|FJ|L-7|LJL7F7|LJ-LJF7L7|||LJLJF-7F7FJ|LJ|F7|FJ|FJ--FJL-77 .-F-.-7LF-L7||L--JL77L7F7L-JL-JF-7LJLJF7||||FJ|LJ||FLJF-J|F-7LJ|L7F-JL7|FJ|FJ|FJL-J|FJF-JL-7-||||F-7F7|L-JLJ|F7F-J7||LJFJF-J|LJL-JL-7|L7F-J7 FJL7.F7-LF-J|L----7|F7LJL7F----J7L-7JFJ|||||L7L7FJL7F7|F7LJFJF7L-JL-7FJ|L7|L7LJF--7|L7|F7F7L7LJLJL7LJ|L---77||LJF-7|L--JFJF-JF------JF7|L7JL |--|FL7|JL-7|F7.F7||||F--J|F----7F7L-JFJLJ||FJFJL-7|||LJ|F7L-JL7F---J|J|FJL7|F7L-7LJFJ|||||FJF----JF7L----JFJL--JFJL----JFJF-JF7|F---JLJFJ.| L7F|7JLF7||||||FJLJLJLJF7FJL---7LJL---JF7LLJL7L-7FJ||L--J||F-7FJ|F7F7|FJL-7|LJ|F-JF7L7LJ|||L7|F7F--JL7F---7|F-7F7L--7|F-7L7L--JL-JF-7F-7L-7J LLFJLJFJ|F-JLJ|L---7F-7|LJF----JF7F--7FJL--7LL--JL-J|F7F-JLJFJL7LJLJ||L-7FJL7FJ|F7|L7L-7|||FJLJLJF---J|F--J|L7||L7F7L7L7|FJF-7F7F-JFJ||L7FJJ .|..L-L7|L-7F7|-F-7LJJLJF7L-7F7FJLJF7LJF---JF--7LF-7LJ|L---7L-7L-7F-JL7FJL7L|L7||||FL7FJLJ||F7F7FJF7F-JL---JFJ|L7||L7L-JLJFJ7LJLJF7L7L-7LJJJ FF|-FLFJL-7|||L7L7L7F7F-JL-7LJLJFF7||F7L-7|FJF7L7L7L--JF-7FJF-JF-JL-7FJL7FJFJFJ||||F-J|F-7|||LJ|L-J||F--7F7FJ|L-JLJ7|F--7FJF7F7F-JL7|F7L-7-7 FFJF|LL--7LJ|L7L7|FJ||L---7|F----JLJLJL--JFJFJL-JFL7F-7L7|L7|F7L7F--JL-7LJFL7L7|||||F7LJFJLJ|F7|F7LLJL-7LJLJ|F---7F7LJ7FJ|7|LJLJF7FJLJ|F7|7F .FJ-F---7L--J|L7LJL7||F7F-JLJF7F7F----7F-7L7L7F7F7|LJ7L7||FJ|||FJ|F7F-7|F--7|FJLJLJ|||F7L--7LJ|LJL-----JF-7F7|F--J|L--7L7L7L7F--J|L--7||LJ-L F|F-L--7L7JF7F-JF-7||||LJF7F7|||||F---J|FJFJFJ|||L-7FF7LJ||FJ|LJFJ||L7LJL-7LJL-7-F-J||||F--JF-JF7F7F----JFJ|||L---JF-7L7L7L7|L--7L7F-JLJ7JFL F7-L|JJL7L-J|L--JFJLJ|L--JLJLJLJLJL-7F-JL7|FJ.|||F-JFJL-7LJL7L7J|FJL7L-7F-JF7F7L7L7FJ||||F--JF7|||||F----JFJLJF7F-7L7|FJ|L7LJF--J|LJ7L|FF.F| 77J-|F7.L--7|F7F7L--7||F7F7F--------J|F--J|L-7||||F7L7F7L7F-JFJFJL-7|F7||F7|LJ|FJ|LJFLJLJL-7FJLJ||LJL-----JF--JLJFJFJLJF7-|F7L------77|F77FF |JJ7L-.LF--JLJLJL7F7|L7||||L--7F-----JL---JF-J|LJLJL7||L7||F7L7|F-7|||||||||F-JL7F7F----7F7LJLF7LJFF7F7F7F7L---7JL7L---JL7LJ|F7F----J-7J.7-- ||.|-|-L|F7F7F-7FJ||L7|||||F7FLJF----7F-7F7L--JF7F-7LJL7LJLJ|FJ||FJ|||||||LJL7F7||LJF-7FJ||F7FJL7F-JLJLJLJL7F--JF7L7F----JFFJ|||7F7JJJ|J7LL| F|J|.F.F||LJLJFJL-JL-JLJLJLJ|F7FJF--7|L7|||F-7FJ||FJF-7L---7||FJ|L7|||||LJFF-J|||L7FJ-|L-JLJ|L-7|L--------7||F--JL7|L7F7F7FJFJ|L-J|L||FF77L| JL||7.FLLJ7F--JF-7F7F---7F-7|||L-JF-J|FJ||||7LJJLJ|FJ-|F---JLJ|FJLLJ||LJ.F-JF7|LJFJ|F-JF-7F7L--JL---------JLJ|F--7|L7LJLJ|L-JLL7F7L--77JLFL| |.JJL7J..F-JF-7|FJ|||F7FJ|-||||7F7L-7LJFLJ|L-----7|L7FJL---7F7LJF---JL--7L-7|LJF7|FJ|F7L7||L7F7F7F7F7F-------JL-7LJ7|F--7|F-7F7LJ|F-7L7-F7|| F7L-J|F-FL-7|JLJL7|||||L-JFJLJL-JL--JF7F-7|F-----JL7|L7F7F-J||F-JF7F-7F7|JFJL7FJLJ|-||L-JLJFJ|LJLJLJ||F------7F7L7F7|L7FJLJFJ|L7LLJ.L-JJL|-- JJ7.F7|L|J.LJF--7LJLJ|L-7FJF7F7F-----JLJFJ|L-77F7F7LJJ||||F7||L--J||FJ|LJFJF7||F-7|FJ|F----JFJF----7LJL--7F-7||L7LJ|L-JL7F7L7|FJF-77J.|7.LJ. |.FF|77|F----JF7L----JF7LJFJ||LJFF------J-L-7L-JLJL7F-J||LJLJL-7-LLJL7L7L|FJ|||L7LJL-JL----7|7L-7F7L--7F7LJFJLJLL7FJF7|L||L7LJL7|FJ|JF7|7F|7 |-L-L-JFL7F--7||F7F7F7|L-7L7LJF-7L-7F7F7F7F7L-7F---JL7FJ|F-7F7FJF-77FJFJJLJJLJ|FJF-7F7F-7F7|L7F7LJL--7LJL--JF7JF7||J|L7FJL7|F-7LJL-77|LJJ--- |.|L|L-7JLJ|7LJLJLJLJ||F-JFJF7L7|LFJ|LJLJLJL-7|L---7FJ|||L7|||L7L7L7L7L777J-FFLJ.L7|||L7||||FJ|L-----JF-----JL7||LJFJFJ|F7|||FJF---JL||7.L|7 J-77|J|||.|F7JF-----7LJL-7|FJL-JL7L7|F-7F7F--JL----JL7L7|FJ||L7L-JFJ-L7L-7-|FF----JLJL-JLJ|LJFJF------JF--7F7FJ||F7|FJ7||LJLJL-JF7JJ.|--77LL L-J|J.7-|7L|||L----7L-7F7|||F--7FJ7LJL7|||L--------7FJFJLJFJ||L7F7|J-FJF7|J|JL-----7F7F--7|F7L-JF7F----JF7LJLJ7|LJLJ|F7LJ.F-7F7J||.|7J-LFL.| |L7JF-|LLJJ|L---7F7L-7|||LJLJF7|L7F---J|||F7F---7F-J|FJF-7L-J7L||LJ||L-JLJ7J|-F-7F-J|LJF-J|||F7FJLJF----JL--77FJF7F7LJL7F7|FJ|L-JL--77.|J|.| L..LF--7|F-L---7LJL--JLJL----JLJFJL---7||LJLJF7FLJF-JL7L7|-J7F.||FLJ77J7|.-.|7|FJL--JF7L-7LJ|||L---JF------7L-JFJ||L7F7LJLJL-JF-----J-F.F77| .77.|FJ-F7|J|JLL7F7F7F7F7F7F-7F7|F----JLJF---JL--7L--7L-JL7||.FLJ-|F-F.7.F---FJL-7F--JL--JF7|||F7F-7L----7J|F7FJJLJFJ||F7F7F-7L----7J..L||.- 7.F||L7LL7J||J||LJLJLJ||LJLJ7LJ||L-------JF---7F7L--7|F7F7L-77.|LFFJJL-J.J7|LL-7FJL7F7F---J|LJ||LJFJF---7L7|||L---7|FJ||LJ|L7|F-7F-JJFFJL777 J-FJF.LF|||-||FF7F--7LLJ-F--7F7||F----7F--JF7F||L---JLJLJL7FJ--JJF-..L--L-7-F--JL--J|LJF7|FJF-JL-7|7L--7L-JLJL----JLJFJL-7|FJ|L7LJLL-L.77LLF .F7JLF|.L|.FF7FJLJF7L7LF7L-7LJLJ|L---7LJF--JL7LJF--7F----7||7J-|-J|-.L-|LF--L7F7F---JF7|L7L7|JF--JL7JF7L-7F7F7F---7F7L7F-J|L7L7|JL7L7F|JL-|J 7LLJFF7FF7-L||L---JL7L-JL77L---7L----JLFJF--7L-7|F7LJF7F7|LJ-.F|--JL7.L|J.LJ-||LJFF7L||L7L-JL7L---7L-JL--J|||LJF-7LJL7LJF7L7L7|L7--7LJ.FL|.L J-|LF7L-F7FFJL--7F7.L---7|F7F--JF7F7LF7L7|F7L--J||L--JLJLJ.LJFL|.F|FJFFLF-F|.LJF--JL-JL7|F--7L7F7.L7F-----JLJF7L7L---JF-JL7|FJ|FJFF|-LJ77L-. FJJ7|||.|L7L--7FJ|L-----J||LJF--JLJL-JL-JLJL-7F7||F------77J-J-F.L7JFJ|J|7|LFLJL7F7F--7|LJF7L7LJ|F7LJF----7F-JL7L-7F--JF--JLJ-||JL-.F|L--JL7 L..F7F7FL7L7F-JL7L------7|L-7|FF----7F7F7F---J|LJLJF---7FJ.7..FF7.LF|-FF7-FJJ.7LLJLJF7|L7FJL7L-7||L--JF7F7|L--7|F7LJF-7|FF--7-||-..|-7.|.FLF .L|LLJLLLL7LJF-7L7F7F---JL--J|FJF7F7|||||L----JF---JF7F|L---7-|LJ77LJ7FLJJJ--7|-|F--J|L7|L-7L-7||L-7F7|LJ|L-7FJLJ|F7L7|L-JF7L7||J-F|J|-J.7JL F---|7J|.L|F7L7L7LJ|L-----7F7|L7||||LJLJ|F7F7F7L----JL7L----JL|J|J|LL-F-J|L--|JFFJF-7L-JL--JF7LJL--J|LJF7L7FJL-7FLJ|FJ|F7FJL-JLJJ7L7.7|.-JFL LJ.FL7.J-FLJL-JJL-7|F-7F77LJLJ.LJ||L-7F7LJLJLJ|F7F7F-7L-7LF7JFF-77JF.|.F.|-|FF7FJFJFJF----7FJL-7F--7L7FJL-J|F-7L--7LJJLJ||F7F7||7|F|7LF-JFJ7 L..JJ.JJ.F7F7F7|F7||L7||L7F--7FF7LJF7LJL-7F--7|||||L7|F-JFJ|FL|FJJF|-F-7-F---J|L7L7L-JF---J|F--JL7FJFJL--7FJL7L-7FJF7F7FLJ|LJL-7JJ-F77|-77LJ |-|.77JJFJLJLJ|FJLJL7|LJFJL-7|FJL--JL----J|F-JLJLJ|FJLJF7L7L7||L7|F7JL7|.L--7FJ-L-JF-7L7F7FJL7F7FJL7|F7F-JL-7L-7|L-JLJL---JF---J.|F||FJ7LJ-J J-J7JL.-L-7F-7|L---7|L-7L-77||L-----------JL-7F7F7|L7F-JL7|FJFJFJF||F-J|F7-FJ|F-7F7L7|FJ|LJ-FJ|||F-J||LJF7F7|F7||F7F---7F-7L---7.|7JL|.J7.L7 .F7|7JF|J.LJFJL7F7FJL--JF7L-J|LF7F-----------J||||L-JL--7LJL7L7|F-J|L7FJ||FL7|L7||L-JLJFJF-7L7|||L7FJL--JLJ|LJLJLJ||F-7|L7L7F7FJ7L--||7.L7.L .L-LJ-7JLFF7L-7|||L----7|L7F7L7||L----7F------JLJL-7F7F7L--7L7|||F-JF||||L7FJ|FJ|L-----J7L7|LLJLJ.LJF7.F7F7L--7F7|LJ|FJL-JJLJLJ---J.77F7J|FJ -J.F|7.|FFJL--JLJL-----J|FJ|L7LJL-----J|F---7F-----J|||L-7||FJ||||LFFJ|FJFJL7|L7L7F-7-F---JL7F-77F7FJ|FJLJL7F7LJL7-FJL7.F7FFF7-FJ|..--J|.LJJ |F-7F|JF-L7F7F----7F7F--JL7||L7F-------JL--7||F-7|F7||L-7|FJL7||||F7L7|L7|7FJL7L7|L7L7L----7|L7|FJ|L7|L--7.LJL--7L-JF-JFJL--JL7|L|-FJ|FJJJ7. |.J-.7L-7LLJ||F---J|LJ7F7LLJF7LJF7LF7F7F---JLJ|FJFJLJ|F7|||F-J|LJ|||FJL7|L7|F-JFJ|JL7|F7|F7||FJLJFJFJL7F7L---7F7L--7L--JF-----JF7J..FLJ.LLFJ |7LF|L7JF---J|L7F7FJF--JL-7FJL--JL-JLJLJF-----JL7|F--J||||||F7|F-J||L-7|L7LJL-7L7L-7||||FJLJ|L--7L7L-7LJL----J|L--7L7F--J.F7F7L||--77..L.7J| 7-F---7-L----JFJ|||FJF7F-7|L--7F7F------JF------J|L7F-J||||LJ|||F-J|F-JL7L-7F-J-L-7LJLJ|L--7|7F7L7L--JF7F7F--7|F--JJLJF--7|||L-JL7|J|F-|.J-J F7L--7|F7F-7F-JFJ||L7|LJJ||F7FJ|||F--7F--JF-7F7F-JFJL-7LJLJF-J|||F-JL7F7|F7|L7F--7L7F-7L---JL-JL-JF7F-J||LJF-J|L--7F7FJF-J|LJF---J7-FJ7|..|. L|J.FJ|||L7LJF7|FJ|FJ|F--JLJLJFJLJL-7|L--7|FJ|LJF-JF7FJF--7|F-J||||F7LJ|||||FJL7FJ-LJFJF7F7F-7F7F-JLJF7LJF-JF7|F--J|||FJF7|F7L-7F7F-7--7-|77 F7--L7LJL-JF7|||L7|L-JL-7F7F-7|F----JL--7LJL-JF7L-7||L-J7FJ|L-7|||FJL7FJLJ|||LFJL7F7JL-JLJ||FJ|||F---J|F7L7FJ||L---JLJL7|LJ||F-J|||FJ7J|.LFJ ||-LJL7F--7||||L7||7F---J|||.LJL----7F7||F7F--JL--J||F7F7L7L7||LJ|L7FJL-7FJ|L7|F-J|L7JF7F7LJL-J|||F7F7LJL-J|FJ|F----7F-J|F-JLJ|FJLJL77F|7.7J JJ7L-LLJ-FJ|||L-JLJFJF7F7|||F-------J|L7LJLJF-7F-7FJ|||||FL7L7L7FJFJL7F7||FJFJ|L7FJFJFJLJL7F7F7LJ||LJL7F---JL-JL---7||F7||F7F7FJF---JJF--FJ| ||F-|.LF-JFJLJF----JFJ||LJLJL----7F7-|FJF7F7L7|L7|L7LJ|||F7L7L7|L7L7FJ|LJ|L7L7L7||FJ7L--7FJ|LJ|F7LJF--J|F--7F------JLJ|LJLJ|||L7|F7-|-|.|JL| F7|F77.L-7L--7L7F---JJ||F-7F7F--7LJ|FJL-JLJL-J|FJL-JF-J|||||L7|L7|FJL7|F7L-JFJFJLJL-7F--JL-JF-J||LFJF7FJL-7LJF7F7F7F77|F7F7LJL-JLJL-77|.|.F- LF-----7J|F--J|LJ7F7F7LJL7|||L7FJF7LJF7F7F----JL7F--J7FJLJ|F7|L7|||F-JLJL--7L7L--7F-JL-----7L7F|L7|FJLJF--JF-JLJLJ||L-J|LJL---------J7LLL7J| LL----7|7LJJF777F7|LJ|F7FJLJ|FJ|FJL--JLJ|L7F7LF7||F7F7L7F-J|||FJ|LJL--7F7F-JFJF--JL7F--7FF7L7L7|FJLJF77L---JF7F--7LJF-7L7LF7F-7F-----77J-J-| F7.|FL||F77FJ|F7|||F-J|LJF-7LJFJL------7L7||L7|LJ||LJ|FJL7FJLJL7|F7F--J|LJF7L7L7F--JL-7|FJ|FJFJ||F7FJ|F7F---JLJF7L--JLL7L-JLJFJ|F---7|7FF-L| L-LF--JLJL7L7LJLJLJL7FJF7L7L-7L-----7F7L7||L7||F-JL7FJL-7|L-7F-J||LJF7LL--JL7L7|L-7F-7|||FJL7L-J|||L7LJ|L----7FJL----7LL-----JFJL--7||-.|..F |FLL7F-7F7L-JF7F---7|L7|L-JF-JF7F7F7LJL-JLJFJLJ|F-7|L-7|||F7|L7FJ|F7||F7F---JFJ|F-JL7LJ|||F7|F--J||LL-7L7F-7FJL7F----JF7F--7F-JF7F7|LJ-LF7F- FF-FLJL||L7F7|||F--JL-J|F--JF7|||||L-7F7F7FJF--J|FJ|F7L7||||L7LJFJ||||||L---7|FJ|F7J|F-J|||LJL-7.||F77L7LJ7|L--JL7F7F7|||F-J|F-JLJLJJL7J.L-. |LF-.F-JL7LJ||LJ|F---7FJL7F-JLJLJLJF7|||||L7|F--JL7LJL7|||||||F-JFJ||LJL77F-J|L7||L7||F7||L-7F-JFJ|||F7L--7L7F7F7LJLJLJLJL--JL----7J--J.-L.L --|-FL7F-J|FJ|F7LJLF-JL-7LJF7F-----JLJ|LJ|FJLJF7F-JJF7||||||FJL-7|FJL--7L7L-7|7|LJFJ||||||F-JL-7L7||LJ|F--JFJ|||L-7F7F7F7F-7F7F7F7|FL.FJJJ.| .|.L|.||F--JFJ||7F7L-7F-JFFJLJF--7F--7|F7||F7FJLJF-7|||LJ|||L7F-J||F7F7|FJJFJL7L-7L7|||LJ|L-7F-JFJ||F-JL-7.L-J|L-7LJ||LJ|L7LJ||LJLJJ7F-7.-LJ FLJ77.LJL-7FJFJL-JL--JL-7FJF7FJF-J|F-JLJ||LJ||F7||FJ||L-7|||J||F7||||||||F7L7FJF7|FJ|||F-JF7||F7L7|||F7F7L--7FJF-JF-JL-7L7L-7LJ7JJ|--7LL7-|. F-LJ|J.JJFJ|LL---7F7F7F-JL-JLJFL-7||F-7FJL7FJ||L7|L7|L7FJ||L7|||||||||||||L7|L7||||FJ|||F-JLJ|||FJLJ|||||F--JL7|F7L----J7L-7L7F7F-7J..LL|.LJ 7..-7LJ7FL-JF7F-7||LJLJF7F7F---7FJ|||FJ|F-JL7||FJL7LJF||JLJFJ|||||||||LJ||7||FJ|LJ|L7|||L--7F|||L7F-J|LJ||F7F7|LJ|F-------7L-J|||FJF7-.F7-|| |.FF--LJ.|JF|||FJLJ-F--JLJLJF-7LJFJLJL7|L-7FJ|||F7L7F-JL--7L7|LJLJ|||L7FJL7||L7L7FJFJLJL7F7|FJ||FJ|F7|F-JLJLJ|L--J|F------JF--JLJ|FJ|.FFJFL7 77.LJ.|7L77FJLJL--7FJF7F7F--JF|F7L-7F-JL7FJL7|||||FJL7F7F-JFJL---7|||FJL7FJ||LL7||FJF-7FJ|||L7||L7||LJ|F7F---J-F--JL-------JF7F--J|FJ-FJLF-| |||--7LLJ|LL--7F-7|L-JLJ||F---J||F7||F7FJL7FJ||||||F-J||L7FJF-7F-J||||F7|L7||F-J||L7L7LJFJ||FJ|L7|LJF-J||L-----JF7F7F7F7F-7FJ|L7F7|L7-7-F--J FFLJL|-L.7JFLFJ|FJL--7F7LJL7F7FJ||LJLJ|||-||7||LJ||L-7|L7|L7|FJL-7||LJ|LJFJLJL7FJ|FJFL-7|FJ||FJF||F-JF7||F7F-7F7|LJLJ||LJFJL7L7LJLJFJ.J7L7J7 L.|7.|.|.||FLL-JL7F-7LJL---J||L7||F---JL7FJL7||7FJL-7||FJ|F||L-7FJLJF-JF7L--77LJ-||F7F-J|L7|||F7LJ|F-JLJ|||L7|||L--7JLJF7L--J-L--7FJ77|7.JF7 |7.FJ-F|FJ|F-F-7FJ|FJF7F7F7FJL7|LJL7F-7FJL7FJ|L7|F7FJ||L7L7LJF-JL--7L-7||F-7|F---JLJ||F7L7LJ|LJL-7LJF---J||FJLJ|F--JF--JL-------7||F7-F77FJ7 J-F|JL||-L7--L7LJFJL7|||LJ||.FJ|F--J|L||F-J|JL-J||||FJ|FL7L-7L-7F-7|F-J||L7|||F7F7F7|||L7L7FL7F-7|F-JF7F7||L7LFJL---JF7F7F7F-7F-J|LJL7JJ|J-7 ||LL7-JLLLL7|LL-7L-7||||F-JL7L-JL--7L7||L-7L---7||LJL7L7FJF7|F-JL7||L7FJ|FJLJ||||LJ||LJ7L7L-7LJ|LJL7FJ||LJ|FJFJF7F7F-JLJLJ||FJL-7L---J7-|JF| FJ7-|-|7|LLFL-.FJF7|LJ||L-7FJF-----JFJ|L7FJF-7FJ|L--7|FJ|FJ||L-7FJLJ-LJ7||.F-J||L7FJL--7FJF7L--7F--J|FJ|F-JL7L7|LJ|L-----7||L7F7L7LF|-7-.7JL ||F7JF-7-J.|-.F|FJ|L7J||F-JL7|F7F-7FJJL7|L7L7LJFL7F7||L7||7||F-JL-7F7F--JL7L--J|FJL7F7FJL7||F-7||F-7||FJ|F7FJFJL-7L7F-7F7|LJFJ||FJF-77JLF||7 LJJ7.LJ||F|.|.F|L7|FJ7LJL-7FJLJ||FJL-7||L7L7L7LF-J||||FJLJFJ|L-7F-J|LJF7F7L---7LJF-J||||FJ|LJFLJ||-LJLJJ||LJFJF7FJ.|L7||LJF7L7||L77LL-F-|J-F .|LJFJF7FL7.|F-JFJLJ--F---JL-7.LJL7F-JFJFJ-L7L7L--JLJ|L--7L7|F7||F7L--J|||F---JF-JF7||L7L7L-7F7FJL7.F---JL-7|FJ|L-7L7||L7FJL7||L7L7..|LF.||L F7F---|J-7.LLL--J|LL7.L-7F--7|F---JL-7L7L7F7L7L7F--7FL7F7L7LJ|LJ||L7F--J||L-7F7L-7|||L7L7|F7||LJF7L7L--7F7FJ||FJF7L7||L7||F-J|L7L7L-77.|.7-| |-|-|F7|F-7.|-|JF77LL7LL||F-J|L7F7F7FJFJFJ|L7|FJL-7|F7||L7|F-JF7LJFJL7F7||F7LJL-7LJLJFJFJ||||L7FJ|FJF--J||L7LJL7||FJ||||LJL-7|FJF|F7|--L7F7| |7|-LJ.-J.F-|.J.JL-.|LF.LJL-7|FJ||||L7L7|LL7LJL-7FJLJ|||FLJ|F-J|F7|LFJ|||LJ|F7F-JFF--JFJ|LJLJFJ|F|L7L-7FJ|FJ-F-J|||FLJFJF-7FJ|L-7LJLJJ|F-L7- F7L..F||7.|FJ-FL--|---J7L|J.LJL-J||L7|FJ|F-JF7F7LJF7FJLJF7FJ|F-J||L7|FJ|L-7||||7F7L--7|F-----JFJFJFJF7|L7|L-7|F-J|L-7FJFJFJL7L-7||LJ.FFF7||. |J.L7L7J7FJL7J|J-LLFJ.LL-77..|.F-JL7||L7|L7FJ|||F-JLJF7L|LJFJL7FJL-JLJ|L7FJ|||L-JL-7FJ||F-7F-7L7L7L-J|L-J|F7|||F-JF-JL7L7L--JJ|LJJJ7FL-J7|7L L-J--7|LF7L---FF.F||J.JF-|.J77FJF7FJ||FJL7|L7||||F---J|FJF7L7FJL----7F7L|L7||L7F-7FJL7|||FJL7L7|L|F-7L--7LJLJLJ|F7L-7FJFJ.|-|-L.LLJFFJ|.F7-. LF.-7|JFL---|FLJFF|JJF.F.|FLF-JFJ||FJ|L-7|L7||||LJF-7FJL7|L7|L-7F-7FJ||7|FJ||FJ|J|L-7LJ||L7FJ-||FJ||L7F7|F7F7F-J||F-J|FJLF-7-7-F|.FF|-7FL|J7 F|F|L.-JJL7|F77L-JFJ.LJJFL--L7FJFJ|L-JF-J|FJ|||L7FJFJ|F-JL7|L7FJL7|L-J|FJL7||L7L7|F-JF7|L7|L-7||L7L-7|||LJLJ||F7||L-7|L7-J||FJ--.FF7|FF7-L.F F-7J-JJF7.-|.FJFL7JFL|J-|J|FL||7L7L7JFL-7||FJ|L7|||L-J|F-7||FJ|F7||F--JL7FJLJLL7||L--J||FJL7FJLJFJF7|LJ|F-7FJ|||||F7||FJJ.|7L|J.FL--F-7--LJJ JJ|7F.F77-LJF-7L7LJ|.77.|.LL-LJF-JFJ7|.FJ|||FL7||L-7F-JL7LJ|L7|||||L--77|||LJ|.LJ|F--7|||FFJ|F7-L7|LJF7||L||FJ|LJ||||LJJF7.FJ|7-F-|.LJL|.|L7 |-77||LL7FLLL.F|FJ-|FJ.7F7.F|F-JF-J.F.FL-J|L-7LJ|F-J|F7FJ-FJFJLJLJL7F7L7||FJF7-LFJL7-LJ|L7L7||L--JL--J||L7LJL7L7|LJLJJL-JJF77|77LF77J|--7-|7 7F7-|-JF7J|.L|--JJ.FJ.7LF7-|FL--JJLJJ|.LF-JF-J7J||JL|||L-7L-J7L77LLLJ|FJ|L7JF77.L-7L-7LL7|-||L7F7F7F7FJL7L--7|FJ7|J|F||.|JL|L|-7.J.L7-FJF-J7 F-L-LL7-LJ|7.|J.L|F|FF7FLL7.JFLJ.F7|F7.L|F7|J||-|L7-LJ|F-JJ.F-JF-.LLF|L7L7L-J|FFF-JF7|JFLJ.LJL||LJ||LJJFJF7FJLJJF|7.JLF-JJLL-|L-J|LFL.LLJJ.7 |JL77FL7J.|-.|L7-JJLJJJL7.--||7.FLFFJ|7.LJLJ-LLFJFJ-L.LJJ.|F|L7|.L77LL-J7L---J77|F-JLJFFJFFL|-LJJLLJJ|||FJ||F7.||LLF--7F|JF|-F7J.L-FJ.L-7|-| --LL-|7LFJLL-|-|L|.FL7LLF7|F7LJ-7.LL-LF.FJ||.L|L-JJJL-L7LF7J--|-77L7JJ|LF|-JF|LFJ|LJ7FLF7-|J|FLLJ-|J|--LJFJLJ|7LJ-||.FL--FJ-7|LFF.-.F|J.J7-| L-|LFLJ7|.FLF-7|7JL|7F-F7|FL7FJ..7-LL-J-|FFF--J|J|JFF|-7.FJ|..|-F|J|LFJFF7FL|LFL-J77|7.L--|7.L777.LJL-JLLL---J-77F-J-JF7-|.JF7.FJ-J7|L--L--L |--.FJFJ|L|-7F|..7.LF-..|7FJL|L-LL7F7|L|.|.|L7JF7J7-F---.--77.|-LJ-J||--JJ|7|F7J7|F|FJ7.J-L-LFL-J-|.|JFJJ7LL|.|L-F|J..F|7F7F777.7-7F-J77..FJ L7L-|JFLF7|7L|..L7-FJLF-JLJ7|L.||.7L-F.LF7-7.|FJ|.||J|7J7..F-7-FJ||.J7FLJ7LLJ7J|FFJ|L----7JF7LJLJLF7|FJ|F7.L-7-J-JJ.|-LJFF-|J.---7L7.|FJ-FL7 |L7J.|.L|J|F.L-.JJFJ|F|.L|.L-FJ||-|7F--.FF-7-|7-F7F--FF-J7.JL|-J7.L-LLJL--7J|JF|7|L|LFJ|.--J-JFJ.F--|L--777.LJ|7F||F7.F7||7|.F7..|.L-LJJ.L.| FJ-J-77..J7JF-JJJJLFJ|7--7-|.LJ|J.JJ-7-FFJ|.L||F7J|.|L|7|L77||LL-7|7F|||.F|7-----FJ|.||L7JFJ77|.-|7||FF|L7F7.-J-F-|L77FJ-|-|7L-JF77JLL7J|..| LJ.LF-FJ-L7-7JJL--F7-LFJ-L.7.L-J-|-L--.F7LJ---JJJ-L-FLLJ-.L|J|.L.L7-L7-F-LJLJ-|-|L-|--JJ|LJ-L-JFJL-JJL7-|LL7JJJL-LLFLFLJLJJLL-J-JL-.LLF-J--J ================================================ FILE: exm/aoc/2023/aoc_2023_10_questions.txt ================================================ --- Day 10: Pipe Maze --- You use the hang glider to ride the hot air from Desert Island all the way up to the floating metal island. This island is surprisingly cold and there definitely aren't any thermals to glide on, so you leave your hang glider behind. You wander around for a while, but you don't find any people or animals. However, you do occasionally find signposts labeled "Hot Springs" pointing in a seemingly consistent direction; maybe you can find someone at the hot springs and ask them where the desert-machine parts are made. The landscape here is alien; even the flowers and trees are made of metal. As you stop to admire some metal grass, you notice something metallic scurry away in your peripheral vision and jump into a big pipe! It didn't look like any animal you've ever seen; if you want a better look, you'll need to get ahead of it. Scanning the area, you discover that the entire field you're standing on is densely packed with pipes; it was hard to tell at first because they're the same metallic silver color as the "ground". You make a quick sketch of all of the surface pipes you can see (your puzzle input). The pipes are arranged in a two-dimensional grid of tiles: | is a vertical pipe connecting north and south. - is a horizontal pipe connecting east and west. L is a 90-degree bend connecting north and east. J is a 90-degree bend connecting north and west. 7 is a 90-degree bend connecting south and west. F is a 90-degree bend connecting south and east. . is ground; there is no pipe in this tile. S is the starting position of the animal; there is a pipe on this tile, but your sketch doesn't show what shape the pipe has. Based on the acoustics of the animal's scurrying, you're confident the pipe that contains the animal is one large, continuous loop. For example, here is a square loop of pipe: ..... .F-7. .|.|. .L-J. ..... If the animal had entered this loop in the northwest corner, the sketch would instead look like this: ..... .S-7. .|.|. .L-J. ..... In the above diagram, the S tile is still a 90-degree F bend: you can tell because of how the adjacent pipes connect to it. Unfortunately, there are also many pipes that aren't connected to the loop! This sketch shows the same loop as above: -L|F7 7S-7| L|7|| -L-J| L|-JF In the above diagram, you can still figure out which pipes form the main loop: they're the ones connected to S, pipes those pipes connect to, pipes those pipes connect to, and so on. Every pipe in the main loop connects to its two neighbors (including S, which will have exactly two pipes connecting to it, and which is assumed to connect back to those two pipes). Here is a sketch that contains a slightly more complex main loop: ..F7. .FJ|. SJ.L7 |F--J LJ... Here's the same example sketch with the extra, non-main-loop pipe tiles also shown: 7-F7- .FJ|7 SJLL7 |F--J LJ.LJ If you want to get out ahead of the animal, you should find the tile in the loop that is farthest from the starting position. Because the animal is in the pipe, it doesn't make sense to measure this by direct distance. Instead, you need to find the tile that would take the longest number of steps along the loop to reach from the starting point - regardless of which way around the loop the animal went. In the first example with the square loop: ..... .S-7. .|.|. .L-J. ..... You can count the distance each tile in the loop is from the starting point like this: ..... .012. .1.3. .234. ..... In this example, the farthest point from the start is 4 steps away. Here's the more complex loop again: ..F7. .FJ|. SJ.L7 |F--J LJ... Here are the distances for each tile on that loop: ..45. .236. 01.78 14567 23... Find the single giant loop starting at S. How many steps along the loop does it take to get from the starting position to the point farthest from the starting position? --- Part Two --- You quickly reach the farthest point of the loop, but the animal never emerges. Maybe its nest is within the area enclosed by the loop? To determine whether it's even worth taking the time to search for such a nest, you should calculate how many tiles are contained within the loop. For example: ........... .S-------7. .|F-----7|. .||.....||. .||.....||. .|L-7.F-J|. .|..|.|..|. .L--J.L--J. ........... The above loop encloses merely four tiles - the two pairs of . in the southwest and southeast (marked I below). The middle . tiles (marked O below) are not in the loop. Here is the same loop again with those regions marked: ........... .S-------7. .|F-----7|. .||OOOOO||. .||OOOOO||. .|L-7OF-J|. .|II|O|II|. .L--JOL--J. .....O..... In fact, there doesn't even need to be a full tile path to the outside for tiles to count as outside the loop - squeezing between pipes is also allowed! Here, I is still within the loop and O is still outside the loop: .......... .S------7. .|F----7|. .||OOOO||. .||OOOO||. .|L-7F-J|. .|II||II|. .L--JL--J. .......... In both of the above examples, 4 tiles are enclosed by the loop. Here's a larger example: .F----7F7F7F7F-7.... .|F--7||||||||FJ.... .||.FJ||||||||L7.... FJL7L7LJLJ||LJ.L-7.. L--J.L7...LJS7F-7L7. ....F-J..F7FJ|L7L7L7 ....L7.F7||L7|.L7L7| .....|FJLJ|FJ|F7|.LJ ....FJL-7.||.||||... ....L---J.LJ.LJLJ... The above sketch has many random bits of ground, some of which are in the loop (I) and some of which are outside it (O): OF----7F7F7F7F-7OOOO O|F--7||||||||FJOOOO O||OFJ||||||||L7OOOO FJL7L7LJLJ||LJIL-7OO L--JOL7IIILJS7F-7L7O OOOOF-JIIF7FJ|L7L7L7 OOOOL7IF7||L7|IL7L7| OOOOO|FJLJ|FJ|F7|OLJ OOOOFJL-7O||O||||OOO OOOOL---JOLJOLJLJOOO In this larger example, 8 tiles are enclosed by the loop. Any tile that isn't part of the main loop can count as being enclosed by the loop. Here's another example with many bits of junk pipe lying around that aren't connected to the main loop at all: FF7FSF7F7F7F7F7F---7 L|LJ||||||||||||F--J FL-7LJLJ||||||LJL-77 F--JF--7||LJLJ7F7FJ- L---JF-JLJ.||-FJLJJ7 |F|F-JF---7F7-L7L|7| |FFJF7L7F-JF7|JL---7 7-L-JL7||F7|L7F-7F7| L.L7LFJ|||||FJL7||LJ L7JLJL-JLJLJL--JLJ.L Here are just the tiles that are enclosed by the loop marked with I: FF7FSF7F7F7F7F7F---7 L|LJ||||||||||||F--J FL-7LJLJ||||||LJL-77 F--JF--7||LJLJIF7FJ- L---JF-JLJIIIIFJLJJ7 |F|F-JF---7IIIL7L|7| |FFJF7L7F-JF7IIL---7 7-L-JL7||F7|L7F-7F7| L.L7LFJ|||||FJL7||LJ L7JLJL-JLJLJL--JLJ.L In this last example, 10 tiles are enclosed by the loop. Figure out whether you have time to search for the nest by calculating the area within the loop. How many tiles are enclosed by the loop? ================================================ FILE: exm/aoc/2023/aoc_2023_11.adb ================================================ -- Solution to Advent of Code 2023, Day 11 ------------------------------------------- -- Cosmic Expansion -- -- https://adventofcode.com/2023/day/11 -- Copy of questions in: aoc_2023_11_questions.txt -- -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_11 is use AoC_Toolbox, HAT, Interfaces; -- -- input_name : constant VString := +"mini"; n : constant := 10; input_name : constant VString := +"aoc_2023_11"; n : constant := 140; gala_max : constant := 500; gala_top : Natural := 0; pt_compact, pt : array (1 .. gala_max) of Point; empty_row, empty_col : array (1 .. n) of Boolean; new_x, new_y : array (1 .. n) of Integer; procedure Read_Data is c : Character; f : File_Type; begin for xy in 1 .. n loop empty_row (xy) := True; empty_col (xy) := True; end loop; Open (f, input_name & ".txt"); for y in 1 .. n loop for x in 1 .. n loop Get (f, c); if c = '#' then gala_top := gala_top + 1; pt_compact (gala_top).x := x; pt_compact (gala_top).y := y; empty_col (x) := False; empty_row (y) := False; end if; end loop; end loop; Close (f); end Read_Data; r : array (Part_Type) of Integer_64; procedure Expand_Universe (new_gap : Positive) is begin for xy in 1 .. n loop new_x (xy) := xy; new_y (xy) := xy; end loop; for xy in reverse 1 .. n loop if empty_col (xy) then for idx in xy .. n loop new_x (idx) := new_x (idx) + new_gap - 1; end loop; end if; if empty_row (xy) then for idx in xy .. n loop new_y (idx) := new_y (idx) + new_gap - 1; end loop; end if; end loop; for i in 1 .. gala_top loop pt (i).x := new_x (pt_compact (i).x); pt (i).y := new_y (pt_compact (i).y); end loop; end Expand_Universe; procedure Do_Part (p : Part_Type) is begin case p is when part_1 => Expand_Universe (2); when part_2 => Expand_Universe (1_000_000); end case; for i in 1 .. gala_top - 1 loop for j in i + 1 .. gala_top loop r (p) := r (p) + Integer_64 (Dist_L1 (pt (i), pt (j))); end loop; end loop; end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; for p in Part_Type loop Do_Part (p); end loop; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 10173804 -- Part 2: validated by AoC: 634324905172 end if; end AoC_2023_11; ================================================ FILE: exm/aoc/2023/aoc_2023_11.txt ================================================ .......................#.........#...............#....................................#..............#......#...............#............... .#........#.................................................................#.........................................................#..... .............................#..............................................................#..............................................# ...............#.....................................#..........................................................#......#.................... .......#....................................#.............#..............#......#..............................................#............ .......................................#.................................................#.................................................. ..........................#......#...........................................................................#.............................. ...................#........................................................#............................................................#.. .......................................................#.........#..........................#......................#................#....... ...........#........................#.................................#..................................................................... ...............................#..............#......................................#............#..........................#.............. ..#..................#..................................................................................#.......#........................... .........................................#.................................................................................................. ...........................#...............................................................#.........................#...................... ...................................................#............#..........................................#...............#............#... ...........................................................#.............#.................................................................. ...........#.........................................................................#...................................................... ......................................................................................................#...........................#......... ...#..............#..........#...................#......#..........#.............................#...............#........................#. .....................................#........................................#............................................................. ........................................................................................#................................................... ..........#..................................................................................................#.............#..........#..... ........................#............................#...................................................................................... ....#....................................#........................#.................................#....................................... .................................................#..........................#.............................#................................. ............................#...................................................................#..............................#...........# .................#..........................................#..........#.................#.................................................. ......................................................................................................#............#........................ ........................#..........#............................#..........................................................#................ ................................................................................#..............................#............................ .......#......#..........................................................................................................................#.. ............................................................................#...................................................#........... ...................#.............#.....#...............#................................................#.........#......................... ..#.......................................................................................#................................................. ............#..............................#.........................#............#.............#........................................... ....................................................#.........................................................#............#................ .....................#.......................................#.......................................................................#...... #.........................................................................#............#.................................................... ......#..............................#........................................................................................#............. ........................#.....................#............................................................................................. ..........................................................#...........#......#.......................................#...................... ...#.........................#....................................................................#......................................... ..................................#...........................#....................#......#...............#................................. ..................................................................................................................#...................#..... ......................................................#.......................................#.........................#................... .........#...........#............................................#......................................................................... ............................................................................................................................................ ..............#.............#....................................................#.......................#......................#.......#... ...................................#........................................................................................................ ............................................................................................................................................ ...#.............................................#..............................................#........................................... ........#................#.....#..........................#.................#..............#......................#......................... ..................#....................................................................................................#.................... ...............................................................#.....#...................................................................... ....................................................................................................#........#.............................# ..........#...................................................................#.....#...............................................#....... ...#....................#............................#.....#.........................................................#...................... ............................................................................................................................................ .............................................#....................................................#......................................#.. ...................................................................#......................................#.....................#........... ................#...............#.......................................................#................................................... .........................................................#...................................#....................#......................... ...#.............................................#...................................................................................#...... ...................#..........................................#................#.............................#.............................. .....................................................................#.....................................................#................ .........#.....................#.......................................................#.........#..................#....................... .........................................................................................................#........................#......... ...........................#...............................................................#............................#................... ...............#.................................................#.......................................................................... ..#...................#..............................#.....#...............#..........................#.........#........................... ............................................................................................................................................ ..........#.................................#............................................................................................... ..................#....................#..............................................................................#..............#...... .........................................................#..................................#..................................#............ ..............................#...............................................#..............................#.............................. #.............#...................................#......................................................................................... .................................................................#.....................#...............#.................................... ......#...................#...........................................#..................................................#.................. ...........#.......#...................#......................................................#............................................. ..#.................................................#.........#.....................#....................................................#.. .................................#.................................................................#..................#..................... ..........................................................................#...............#...................................#............. ............................................................................................................................................ #.........#..........................#.................#.................................................#.................................. .....#..........#............#....................................................#...........................#..................#.....#.... ............................................................................................................................................ .........................#.......#.........................#.........................................................#...................... ............................................................................................................................................ .......#...............................................................#.................#..................#............................... ............................................................................................................................................ ...........................................#.........................................................#...................................... .........................................................#...................#................#................#....................#....... .#...........................#.......................................................#...................................................#.. .....................................................................#..................................................#................... ...........#.......#................................#..........#............................................................................ ........................#.......#.........................................#.....#.......................#................................... .....#.....................................#........................................................................#.........#............. ...................................................................................................................................#........ ...............#..................................#........................................#.......#........................................ .....................................#..................................#................................................................... .....................#.....#.........................................................#.........................#............................ ...........#..........................................................................................................#..................... .......................................................#.................................................................................... .............................................................#.....#............................#.......................................#... ...#.......................................................................#.......#....................#................................... ...........................................#.................................................................#.....................#........ .........................#.................................................................................................................. ............#......#..............#.................#......................................................................#................ .......#......................................#....................................................#...............#........................ ......................................#.................#..........#......#................................................................. #........................................................................................#.................................................. ............................#.................................#....................................................................#.......# .......................................................................................................#.................................... .........#.....#.....................................#..........................................#........................................... ....................................................................................#...........................#........................... .......................#.........#.........................................................#..................................#............. ...........................................#......#........#.............................................#............#..................... ......................................................................#............................#........................................ ......#......................#...................................#.............#..............................#.....................#....... ...............#...................................................................................................#........................ .......................................................................................................#.................................... ....................................................................................#......#................................................ .........................................................#........................................#........#....................#.......#... .........................#.........#...............#.....................#.................................................#................ ...................#..............................................#......................................................................... ........................................#......................................................#............................................ .....#..............................................................................................................#.........#............. .....................................................................#...................................................................... ............#...........................................#...........................#....................................................... .#.......................#............#..........................#.......................#...............................................#.. ..............................................#.....#.....................................................#......#..............#........... ...............#............................................................................................................................ .............................................................#........#.....#..............................................#................ ..........#......................................#...................................................................................#...... ..#.....................#......#.........#............#.............................................#...............#....................... ............................................................................................................................................ .......#..................................................................................................#................................. ............................#.............................#..............................#................................................#. ............#......................................................#.......#.............................................#.....#............ ..................#................................................................................................#........................ ================================================ FILE: exm/aoc/2023/aoc_2023_11_questions.txt ================================================ --- Day 11: Cosmic Expansion --- You continue following signs for "Hot Springs" and eventually come across an observatory. The Elf within turns out to be a researcher studying cosmic expansion using the giant telescope here. He doesn't know anything about the missing machine parts; he's only visiting for this research project. However, he confirms that the hot springs are the next-closest area likely to have people; he'll even take you straight there once he's done with today's observation analysis. Maybe you can help him with the analysis to speed things up? The researcher has collected a bunch of data and compiled the data into a single giant image (your puzzle input). The image includes empty space (.) and galaxies (#). For example: ...#...... .......#.. #......... .......... ......#... .#........ .........# .......... .......#.. #...#..... The researcher is trying to figure out the sum of the lengths of the shortest path between every pair of galaxies. However, there's a catch: the universe expanded in the time it took the light from those galaxies to reach the observatory. Due to something involving gravitational effects, only some space expands. In fact, the result is that any rows or columns that contain no galaxies should all actually be twice as big. In the above example, three columns and two rows contain no galaxies: v v v ...#...... .......#.. #......... >..........< ......#... .#........ .........# >..........< .......#.. #...#..... ^ ^ ^ These rows and columns need to be twice as big; the result of cosmic expansion therefore looks like this: ....#........ .........#... #............ ............. ............. ........#.... .#........... ............# ............. ............. .........#... #....#....... Equipped with this expanded universe, the shortest path between every pair of galaxies can be found. It can help to assign every galaxy a unique number: ....1........ .........2... 3............ ............. ............. ........4.... .5........... ............6 ............. ............. .........7... 8....9....... In these 9 galaxies, there are 36 pairs. Only count each pair once; order within the pair doesn't matter. For each pair, find any shortest path between the two galaxies using only steps that move up, down, left, or right exactly one . or # at a time. (The shortest path between two galaxies is allowed to pass through another galaxy.) For example, here is one of the shortest paths between galaxies 5 and 9: ....1........ .........2... 3............ ............. ............. ........4.... .5........... .##.........6 ..##......... ...##........ ....##...7... 8....9....... This path has length 9 because it takes a minimum of nine steps to get from galaxy 5 to galaxy 9 (the eight locations marked # plus the step onto galaxy 9 itself). Here are some other example shortest path lengths: Between galaxy 1 and galaxy 7: 15 Between galaxy 3 and galaxy 6: 17 Between galaxy 8 and galaxy 9: 5 In this example, after expanding the universe, the sum of the shortest path between all 36 pairs of galaxies is 374. Expand the universe, then find the length of the shortest path between every pair of galaxies. What is the sum of these lengths? --- Part Two --- The galaxies are much older (and thus much farther apart) than the researcher initially estimated. Now, instead of the expansion you did before, make each empty row or column one million times larger. That is, each empty row should be replaced with 1000000 empty rows, and each empty column should be replaced with 1000000 empty columns. (In the example above, if each empty row or column were merely 10 times larger, the sum of the shortest paths between every pair of galaxies would be 1030. If each empty row or column were merely 100 times larger, the sum of the shortest paths between every pair of galaxies would be 8410. However, your universe will need to expand far beyond these values.) Starting with the same initial image, expand the universe according to these new rules, then find the length of the shortest path between every pair of galaxies. What is the sum of these lengths? ================================================ FILE: exm/aoc/2023/aoc_2023_12.adb ================================================ -- Solution to Advent of Code 2023, Day 12 ------------------------------------------- -- Hot Springs -- -- https://adventofcode.com/2023/day/12 -- Copy of questions in: aoc_2023_12_questions.txt -- -- HAC 0.26 "nice to have"'s detected in this exercise: -- * Replace_Element for VString -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_12 is use AoC_Toolbox, HAT, Interfaces; -- Each data row has two lists: -- - a list of spring conditions -- - a list of sizes of contiguous groups of damaged springs -- -- Here we set for HAC a maximum for the second list (HAC knows -- only constrained array types): max_sizes : constant := 100; -- Size of a contiguous group of damaged springs: subtype Size_Type is Natural; type Size_Array is array (1 .. max_sizes) of Size_Type; type Row is record code : VString; -- No actual limit in storage size : Size_Array; sizes : Natural; -- Number of sizes end record; map : array (1 .. 1000) of Row; top : Natural := 0; -- Idea: on a given list of spring conditions of length x -- (possibly truncated from the right), and a list of contiguous -- groups of damaged springs, of length y (also possibly truncated -- from the right), if the contents of the lists are intact, the -- result of the problem for the truncated pair is unique, -- so we can memoize it. max_length : constant := 120; -- Spring conditions type Memo_Type is array (1 .. max_length, 1 .. max_sizes) of Integer_64; memo, zero : Memo_Type; unknown : constant := -1; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2023_12"; -- procedure Read_Data is c, sep : Character; i : Integer; f : File_Type; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop top := top + 1; map (top).code := Null_VString; loop Get (f, c); exit when c = ' '; map (top).code := map (top).code & c; end loop; i := 0; loop i := i + 1; Get (f, map (top).size (i)); exit when End_Of_Line (f); Get (f, sep); end loop; map (top).sizes := i; end loop; Close (f); for i in memo'Range (1) loop for j in memo'Range (2) loop zero (i, j) := unknown; end loop; end loop; end Read_Data; r : array (Part_Type) of Integer_64; verbose : constant Boolean := False; procedure Do_Part (p : Part_Type) is -- We erode the pair of lists from right to left, so the -- index 1 remains through recursion. function Count (r : Row; are_remaining_lists_intact : Boolean) return Integer_64 is head : Row; -- `head` is a copy of `r` with at least the last item of the spring -- condition list removed. len : Natural; c : Integer_64; procedure Expected_Size_One is begin if len = 1 then -- The current code (condition list) is just a lone "#". if r.sizes = 1 then -- ^ A single '#' is expected and has been found. c := 1; else -- This group is OK, but there are other series of "#" -- expected left to current one -> not a solution! c := 0; end if; elsif Element (r.code, len - 1) = '#' then c := 0; -- We have a trailing "##", but size 1 is expected. else head := r; -- We have a possible separator ('?' or '.') left -- to the len-th element. -- Fine, just drop last element of the list. head.sizes := head.sizes - 1; -- Remove the separator and the last '#'. Delete (head.code, len - 1, len); -- We do a recursive call with the knowledge that -- contents of both shortened lists are again intact. c := Count (head, True); end if; end Expected_Size_One; procedure Expected_Size_Two_or_More is begin if len = 1 then -- The current code (condition list) is just a lone "#", -- but we expect >= 2 of them, only in the current group! -- -> Not a solution! c := 0; else case Element (r.code, len - 1) is when '?' => head := r; -- Shorten expected string of ###'s by one '#'. head.size (head.sizes) := head.size (head.sizes) - 1; -- Exclude the '?' = '.' case since 2 or more -- '#' are expected in current group. Concretely, -- the trailing "?#" becomes "##". Delete (head.code, len - 1, len); head.code := head.code & '#'; c := Count (head, False); when '.' => -- Element of size >= 2 expected, but size 1 found. c := 0; when '#' => head := r; Delete (head.code, len, len); -- Shorten expected string of ###'s by one '#'. head.size (head.sizes) := head.size (head.sizes) - 1; c := Count (head, False); when others => Put ("??? [1]"); end case; end if; end Expected_Size_Two_or_More; begin len := Length (r.code); if len = 0 then if r.sizes = 0 then -- List exhausted return 1; else return 0; end if; end if; -- From here we know that length l is >= 1. if are_remaining_lists_intact and then r.sizes > 0 then c := memo (len, r.sizes); if c /= unknown then return c; end if; end if; case Element (r.code, len) is when '.' => head := r; Delete (head.code, len, len); -- The last '.' (an operational spring) can be removed -- without changing the result. c := Count (head, are_remaining_lists_intact); when '?' => head := r; Delete (head.code, len, len); -- Cases when '?' is a '.' : c := Count (head, are_remaining_lists_intact); head.code := head.code & '#'; -- Cases when '?' is a '#' : c := c + Count (head, False); when '#' => if r.sizes = 0 then -- We have at least one guy in the condition list, -- but the size list is exhausted -> not a solution. c := 0; elsif r.size (r.sizes) = 1 then -- Last element on the size list is a size = 1. Expected_Size_One; else -- Last element is a size > 1. Expected_Size_Two_or_More; end if; when others => Put ("??? [2]"); end case; if verbose then Put (r.code & " "); for i in 1 .. r.sizes loop Put (r.size (i), 0); Put (','); end loop; Put_Line (" comb:" & c'Image); end if; if are_remaining_lists_intact and then r.sizes > 0 then memo (len, r.sizes) := c; end if; return c; end Count; begin r (p) := 0; for line in 1 .. top loop memo := zero; r (p) := r (p) + Count (map (line), True); if verbose then Put_Line ("-------------------------------------"); end if; end loop; end Do_Part; procedure Prepare_Part_2 is orig : VString; begin for line in 1 .. top loop -- Apply the unfolding, literally, as explained: -- - replace the list of spring conditions with five copies -- of itself (separated by ?) orig := map (line).code; map (line).code := 4 * (orig & '?') & orig; -- - replace the list of contiguous groups of damaged springs -- with five copies of itself. for i in 1 .. 4 loop for j in 1 .. map (line).sizes loop map (line).size (map (line).sizes * i + j) := map (line).size (j); end loop; end loop; map (line).sizes := map (line).sizes * 5; end loop; end Prepare_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Do_Part (part_1); Prepare_Part_2; Do_Part (part_2); if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 7007 -- Part 2: validated by AoC: 3476169006222 end if; end AoC_2023_12; ================================================ FILE: exm/aoc/2023/aoc_2023_12.txt ================================================ #?#???????#?.? 3,1,2,2 .??.##.?#????.??#? 2,2,1,2,4 .?.??#?##??#????.. 8,1 ??????????#.. 6,1 .#.##????.??.? 1,6,1 ?#??#???.??.??? 3,1,1,1,1 ?#???????#? 2,1,5 ##?#??#?????.??? 5,1,4,2 ????.?#??.# 2,1,1 ???????##?????##???? 1,1,11,3 .####??.??#??????#? 6,6,1 ??#..##?...?#. 2,3,2 ..??##?#?#???#??.??. 12,1 ??.?#???#? 1,3,1 ??.#??????????#.??? 4,1,1,3,1 ???##??.?##? 5,1,2 ???..???..?. 1,1,1,1 .?????#?#??? 1,1,1,1 ##???????????# 5,3,2 ??..????###?#?.? 1,8 ????????#???.##?? 1,2,1,2,3 ????##.?#????.? 1,4,2,1,1 ##???#.##?.#????? 2,2,3,2,3 ?????.????? 2,3 ?#?#??.##???.?#?. 3,5,2 ?#?..?##???#?????? 1,12 .??#?????????.?.#.? 11,1,1,1 ???????????#??????. 7,1,1,3,1 ??????????#?????## 1,1,2,1,1,6 .##?.##?????????? 2,4,1,1 ??#?##????? 5,1 ??#????????????? 5,2,2 ?#.#??##??#???#????? 1,2,13 #??.????#.?? 1,2,2,1 #.#?#???????.???#. 1,4,1,1,1,4 ????#??..?.. 2,1,1,1 .??.#????#?????????? 3,8 ?...#??..??.?? 3,1 ?????#?.?.? 2,2,1 ..?...#?#????#?#???? 4,5 ??.?#???#? 2,2 .?#?#.???..?? 3,3 .??.#???#?? 2,3,2 ???##??#??#.?..???? 4,4,1,2 ?????????. 4,1 ????.???.#??# 4,2,4 ?????.?##?#??##?#.?? 4,4,5 ??#?????????????#?# 1,6,1,2,2,1 #??.??????#..#??#? 1,1,3,1,1,2 ???#????.???? 5,3 ????#????#? 1,2,2 ?#.?.??.?.?????#?? 2,1,1,2,1,2 ???.???#??.?? 2,3 ?.??#?#???#?.????#?? 1,3,1,3,2,2 ?.??.??#?????.? 2,3,2 ??##??????????? 3,3,3 ???##?.#???????? 1,3,2,1,1 ?.???#????????##. 1,2,1,1,3 .?#.##????##??. 2,3,5 ????#??#?.?# 5,1,2 ..?.??????..? 1,6 ##??..????#?#?# 3,1,6 ?#?.?#????.?#?#???? 2,2,1,5,1 ????###??..??#. 7,1 ??..??..?? 1,2,1 .?.?.?#??????#??. 1,9 ???????.#?#??????. 2,3,5,2 .##?????#?## 4,1,1,2 ?#?#.???#?#???? 3,7,1 #??.??.?#??????? 2,1,8 ?#???#?#??#.?? 8,1,1 ?#??????.?#???? 6,2,2 ##.?????.??? 2,1,3,2 ??????.?#? 1,3,3 .?..?#?#?#. 4,1 ??#?????.??#???? 1,4,3 .?#??#??.??#. 5,2 ?.#?.????? 2,1,1 #?###?????#?.?#? 6,5,2 #??#?.?#???????.??? 5,1,2,2,1,1 ..???#?#??????#.?#?? 12,3 ?????.??#??????? 2,1,6 #??.#??#?#? 3,1,4 ???.?????#?#.????? 2,7,3 ???.?.#?#?? 2,3 ???..?????##? 1,1,3 #?.???#???#??????. 1,2,7,1 ????.????#?#??#??? 1,1,9 ??#?.?#?#???###???? 1,1,10,2 #??????????.##?? 1,1,1,2,3 .?.?????.???????? 1,5 ???#?##???????? 1,7,1,1 ?????????#??? 1,1,1,4 ???.??#.????? 1,1,1,2 .???.???..???. 1,3,1 ????????#??#?? 3,1,1,3 ????.?..#?#??? 2,1,3 #?#???????#??.? 4,2,2,1 ?????###??? 1,6 ???.?#?????? 1,2,4 ?##????????????. 6,2,1 ??##?????..??????? 9,1,1,3 ???#?#???.#. 7,1 .????#????????#.? 5,7 ##?#???????????.??# 5,2,5,1,1 ??????#?.???#?? 1,1,3,4,1 .??#???##??...??.? 10,1,1 .???.??#????????? 2,2,7 ????.????###? 1,1,1,4 #?#??#?##????##? 1,1,11 ???.#??????#..?#??# 2,3,1,1,1,2 ?????#?#???#?? 1,5,1,2 ???##.?##?#?????.? 1,2,4,1,2 ??????##??. 1,4 ?#??.?????? 2,1,1 ?#?#???###?#?????#?? 14,2,1 ???#?.#???#?.? 1,1,1,3 ???.???#?#.#?# 1,5,3 ??.#??#????#. 2,2,4,1 ??#?#?..?. 3,1 ?????#????#.????#?# 1,2,4,1,1,4 ?.???#.??? 1,2,1 .???.???#??.? 1,1,2,1 .??????.???? 2,3,1 #.##?????? 1,2,2 .#?#??#???? 3,3 ??#??.#??????????##? 1,3,1,1,7 .?#.???????##? 1,2,1,4 #.???#..#..???.?# 1,2,1,2,2 ?#???.??##.?? 4,2 ??..?????.????#.?? 2,2,1,1,1,1 ??????.?#.##?? 2,1,1,3 #???.?.??? 1,1,1 .?##??????#? 3,5 ???#.##???. 1,2,1 ##??######.????#.?? 10,1,1,1,1 .?.??#?.#. 1,2,1 ???????##?.??? 3,3,3 .?.#.?.##?#.??? 1,1,2,1,1 .??#???#?????????? 1,10 ??.?#.?.?? 1,2,1 ??.?#???.??#? 5,2 #??#???#?##????#?? 5,10 ?#???#??#?#?? 2,7 ??###????????#??#?. 5,12 ??.???#????. 1,6 ??#?#???#.???? 1,3,1,3 ???????#?? 4,2 ??#?.??#???#??#. 1,1,5,1 ??.#.?.??? 2,1,2 ??##???#??????. 1,6,1,1 ?#????#..????#??? 1,2,7 ?#??#??#??#?.? 3,1,5,1 ??#?.#????.# 1,1,3,1 #???#?????????.??? 13,3 ##?.???????#???# 2,2,5,1 ?#.????.????. 2,1,1,1 ???#.??.???? 1,1,1,2 ?#???#???#?????#? 2,8,1 ?##?.????????.??#? 3,6,4 ?????##??.?#?????? 2,2,8 ??.?##?#???# 1,5,1,1 ?.??#???##??#???# 12,1 .#.#???#????????? 1,12 ???.?#.???#.???#. 1,1,1,3,2 .#??#??.??? 1,1,1 ?#???#?..? 2,1,1 ?#????.?#? 1,3,3 ???##??#?#???? 2,6 #????##???#????????# 2,8,6 ?.?###?..#????# 1,4,2,2 ????#?#...#?#?? 1,2,1,1,1 .#???????#? 1,1,2 ???.??.#.?? 1,2,1 .??##?#?????????? 6,4 ?#?#?..#??###?.? 1,2,1,5,1 .#.??????#?????????? 1,7,1,1,1,1 ???.???#?.#.?? 1,1,1,1 ##..#.?##??? 2,1,6 ?.???.???#??#?#??#.? 1,3,1,6,2,1 ?#?##?????????????? 1,3,7,1 ?#???????.????#.???. 8,4,1 ???#..#??#??? 1,1,1,4 ##???????? 5,1 ???###.?#??..???#? 4,4,1,2 ?.?#??###.??????# 1,6,1,5 .?????????# 7,1 ?.#.?????? 1,1,1 ??#?.#??#??#? 3,7 ??#?.????#?#??? 3,1,1,1,1 ?.#???????.#??? 1,1,2,2,2 ???????#???..? 1,1,3,1 ?#???#???.#???#??.?# 1,1,3,1,5,2 ?.?####.???? 1,4,1,1 ??#???#?????#?.? 7,1,1,2 .#?#????.???????.? 5,7,1 ???#.????#?#?????. 1,1,11 ???.#??????#??#? 2,1,1,6 .?#?????.#. 3,1,1 .???##.?????.?? 5,1,2 ??#????.??.??##?? 6,2,5 ????????#???? 3,4 ???.?..?#?#?? 1,1,1,2 ?????.?.?????##?? 1,1,1,1,7 ?????#####???.?. 10,1,1 ??????..#?#??? 2,2,3,1 .???.??.?? 1,1,1 ??##..??.?#??.?? 3,1,3,2 ??????#..??.? 3,1,1,1 #???#??#?????? 1,4,2,1 ??#????..#????#?#??? 2,1,9 .?????.?????.#??? 3,1,2,2,1 ?#.#?.??.???? 2,1,1,1 ?..?#??#.?#? 1,2,1,2 ??.???#####? 2,1,5 .#?#?.??.?? 4,1,2 ???.#?#?#.#??.??#??? 1,3,1,1,1,4 ???#????.??.? 1,4,1,1 .?.?.????##???. 1,6 .???.????? 1,1 #?????#??#??#?.?? 1,1,4,3,2 ????.?#??#??##???. 2,8 #?.??#????##??#?.## 2,5,6,2 #.#.???#?#?#.??.??. 1,1,1,5,1,1 ????#?.????#?# 6,5 .???##?????.???.? 7,3 ???#????##?#?.???#?? 11,2 ?#???#????#???.?#?? 7,2,1,1,1 ???#?????#?..?? 7,1,1 ?##?#???????????#??. 4,1,4,1,2 ???????#???.#????. 8,3 .??#?.?.?.##?????? 1,1,1,6,1 ???#.???#.?.##? 2,1,1,1,3 #??#??????#????.? 1,2,6,2,1 .??#?#?.????.?? 5,1,1 ???????#?? 4,3 ?????.?#????#?????.? 1,11 ???##?##?##????#???# 2,2,5,1,2,2 ???.???#??#??#??#?? 3,1,1,5,1,1 ##???.??#??#? 2,1,6 ?#??????#?????#?? 10,2 ???##?.?.?? 1,3 .???????##??#.#??#? 3,5,1,5 .#???..##?? 3,4 ????.#??.??.? 1,1,2,1 ?#?..???#??#?.?### 1,1,4,4 #..??#..?.??###?#??? 1,2,1,5 .##.#?..#? 2,2,1 ??#?#?#??#??#..? 5,4 ???.?.???#???##? 1,9 ?????????#??##?##? 1,1,13 .??????#????. 2,4 .?#.??#???. 1,2,1 ????????????? 10,1 ####????????????.#?? 7,1,2,2,2 ??#.#??????? 2,3,1,2 #??????#?#.?.. 4,4 .?#??#.?#??#??#??? 4,1,6 #??#.?.?##.?#??? 4,2,4 ?#?##????.#??.???. 5,1,1,1,1,1 ???..?#???#???###? 1,1,8 ?###???.??. 6,2 ?##?..??????? 3,6 ?????##?????###.? 6,3 #.??????????##?#??? 1,1,1,2,1,6 ??????.????? 2,1,1 ??#???????.??????? 8,3 ???????????##?? 4,1,3 ??.????????#?# 2,1,8 ???#?#.##?????.? 1,1,1,7,1 #??##?#??##?#????#? 7,6,3 ####?#???###??#??.?? 4,7,2,1,1 #?.?#.??.#?? 1,1,1,1 ???#??????#?.?????? 1,1,3,3,2,1 ???.????#?. 3,6 ??????.?######?? 5,7 ?#??##??#??????. 1,12 ???#?#####?#?..??#. 10,1 ?#.?#.????#? 1,1,2,2 ??.?.????#?#.?.?#.? 2,7,2 ??#????.?????#.?? 1,1,2,6,2 ??#???.??????????? 1,7 ??.?.?.????. 2,1,2,1 ??#?????????#??#???# 1,1,2,5,4,1 ###..##?#??????? 3,11 ?#????#?#??#? 2,4,2 .??..##?#?..????? 4,3,1 ????.????? 3,1,1 .???????????.????# 2,4,1,1,1,1 ??#?#???.??# 5,3 ???????#.?#?#?##?##. 4,1,9 ....???#??#???? 7,1 ?.??#??.?#?????.# 1,1,1,7,1 ?????.?#??? 3,3,1 ??#???????.??? 5,3 .???#????????#??.? 4,1,6 ..?.?????. 1,2 .??????????#?????#? 11,3 ?.?????#??????? 1,9 .?????##??.?? 6,1 ?#?.??#.?? 1,2,1 #????????????? 1,6,3 .??????..???#??. 4,1,1 ??????????????. 1,1,1,3,1 ?.???????. 1,2 ?#?????..??.???. 2,2,1,2,1 #????#???? 4,3 ?????????????. 8,2 .?##.??#.??#.?? 3,1,1,3,2 ???????##???????#? 10,5 ????#??????.?.?? 7,1,1 ?????????#????#.?# 1,1,1,2,1,2 ??#.?##????.??? 2,6,2 .??#???.???????.#? 6,1,1,1,1,2 #?#?.?????#???? 4,6,2 ?##?????#????#?#.#? 2,1,1,6,1 ????????.??????#. 4,1,1,1,1 ??.?#????#.#? 1,4,2,1 ???#.???#? 3,1,2 ?##???????#?? 2,1,4 ?.?.??#?.#??.?????# 1,1,1,3,6 ???#?????#?#?.?###? 1,1,1,2,1,5 ?.##??##?#??#???## 6,1,7 ?.?.????.?# 1,2 ????.#??#??#???? 1,1,9,1 ?.?#????.????#?.. 5,1 ?.??????????#??? 2,7 #???#?##?????.? 5,2,3,1 #????????. 5,3 ??#??#??#? 1,3,1 ???#???#?##?###.?? 3,8 ?#????#????#??# 2,9,1 ?.??#??.?.??#?? 1,4,4 ??#?#?#?#?? 3,6 ?#?.?.?##??.###?#? 2,4,5 ????#???.#??.??.??? 7,2,2,1 ?#?????#???.#?? 9,1,1 #?.?#.#?#???????. 2,1,6,1 ?????#?????? 2,1,2 .???#???.? 5,1,1 .?#???.????? 4,1,2 ???????##???? 3,1,2,2 ?????##???? 4,2 .???#????????## 2,1,1,1,2 ?????????.?#. 3,5,2 ?.???.???#????#??#? 1,3,9,2 ?#???????.??#??????? 2,1,1,1,3,4 ??#??#??#..#???.#?? 8,1,1,1,1 ????.?#????.#?.??? 3,2,1,1,2 ??.?#??????# 1,5,2 ?????.?.????? 3,1,4 ???#?????..?..? 9,1 ?????????#?.?. 2,1,1,3 #.??#??????.#??. 1,1,7,1,1 ??#.??#??????#..???? 3,3,2,1,2 .#???????????# 5,1,1,1 ?.?..?????. 1,3 ?????#?#????.??? 3,5,1 ???#???#?.??#?##??? 3,1,2,1,1,4 ??.?#????? 1,4,1 ?..#?.??###. 1,5 ???##?..???? 6,2 #.??.???#?#.#????? 1,1,3,1,1,1 ??#??#???#??#?? 6,3,2 ???#???????##?#??. 2,3,7 ?????.??.??# 1,1,1,1 ?#??#?###? 2,5 ?#?#?#?.?.#?#?.?? 5,3 ??.??#.????? 1,1,1 ?#.?#.#?##??#???#?? 2,1,5,2,2,1 ..?????.??.???..#??? 1,2,1,2,4 .???#?????.???????. 1,4,2,1,3 ???#?????.#???#..?. 4,5 ???#?????##?#?# 3,1,2,1,1 ??#???.??????? 3,3 ??.??.???#??? 1,1,1,2 #???????##.?#?. 1,2,5,1 ???#???.?? 5,1,1 ?.###?##????????? 1,8,1,1 ?##???#??????##. 11,2 .???#?????#??? 3,3 .##?#?#???? 4,5 ??#??????? 1,6 ???##??.??.? 2,4 .??#??##.??.???# 2,3,1,1,1 ???#???#???????? 12,1 #.?#???##????????#? 1,1,13 ?????#????.?#???#? 1,1,4,7 ?????#???????#????? 8,3 ?#??#.????????. 5,3,1 ?##?#?.#?????? 5,6 ?.??#??#.???#.????# 1,3,1,1,1,2 ???.???##????.??#??? 1,2,2,2,5 ??##?#????????.?.# 8,1,1,1 ???##??..?##.?...?. 2,2 #.?.?.????.????#?#?# 1,1,1,9 ??.????#?????? 1,10 .??.##.?#? 2,1 ?#??????.#.? 2,3,1,1 ??????.???. 1,1,1 .???.??..#? 2,2,1 ??.??????.????. 4,3 #.?#?????.. 1,2,3 ??#??#????#? 5,4 ??#?????.?. 2,2,1 ??#?#??..##?#???#?. 6,9 ?#??#??#####.???#? 5,5,4 ???#?..??#??#?### 2,8 .???#.???????#????.? 3,1,6,1,1 ???#?????#????## 5,2,4 #?#?.?????.????? 1,1,3,1,2 ?????#??????.?#???. 4,4,1,1,1 ##????#?.???????. 8,1,1 ???.??#????#????#? 1,1,1,1,4,3 #?#?##??#????????? 9,6 ?#???????????? 5,1,1,2 ?.?????#?.??. 5,2 ??.??..????#? 1,1,1,4 ??#?.?#?#??.?? 2,6 .???..?.?..? 1,1,1,1 ??#...??##?????.??? 1,1,4,3,1 ??#.#?????????????? 1,1,1,8,1,1 ?##??#???????# 2,1,3,1 ?#??#.??..?#?? 4,1,2,1 ?#?????#????.. 3,3 #??#???###??#?????? 2,2,6,2 #?#??#???? 1,4,2 .???.?.?#? 2,2 ??#??##?.?? 6,1 #???#??.#??# 1,4,1,2 ???????#??? 2,1,1 ?##????????????? 2,2,5 .##?#?.?#? 5,2 ???????##.???#????? 8,3,1,1 ?...??.?.. 1,1 #????#?##????? 1,7,1 ?.?..##?#.??##?#?.? 4,5 ??.??.????????# 1,2,1,5 #??#??#??###?????##? 1,4,12 ??#.?#???.?????#?# 2,3,3,4 ???###?.?? 1,4 ?#????#???. 2,3,1 ?##?#.????#??##.#. 5,2,6,1 ?#?#??.????#??# 4,1,5,1 ????.#.????????##?. 1,1,1,2,6 .???..??#?..??..#??? 1,1,4,1,2,1 ????##?##?##.???? 11,1 ??.???#?#?#????.#??. 1,9,1,1 .???#??.????? 1,1,1,3 ??.???#??# 2,1,4 ??????.??? 1,1,1 ?#?#???????.???.?#? 6,2,2,2 #???#?##??#????#? 1,2,10 ?.##??.??.?#???#?.?? 2,1,2,7,2 .????#..???? 1,3,1,1 ?.?#??????????#???? 3,9 ???#????#.?.? 4,1,1,1 .???.#????. 1,1,2 ?#?##?????? 2,3,3 ????????##??? 1,5 ???###??.?#????#?? 1,4,8 ?.?#????.???.#.?.# 1,5,3,1,1,1 ?????##???#?.???#?? 2,4,1,2,2,2 #????.?.#.?#??? 1,2,1,1,1 ??#?.#?#####????.?? 1,1,8,2,1 ??????#???.#?.. 1,1,1,1,2 .??.##?.??.#????.??? 2,2 ?#??#??#??.??#.???# 1,5,1,1,1,4 .?##?.?#???? 2,3 ????#?#??????..#? 2,5,3,2 ????????#????#..? 10,1,1,1 #?????#???????.??#? 8,1,2 #??###???.????###??? 1,6,1,7 ?????.?.??# 2,1 ??.???..#????. 2,2,2,2 #?.#???..#..? 1,4,1 ?#???##?.#???????#?? 7,10 ?????#?#????#??? 9,1 ????????##?.###?? 1,1,4,5 .???#??#.? 1,4,1 ?????.??#???. 1,3 ???#.??###?#???#???? 2,10 ..#??#.???#??.?. 4,1 ??????#?#??.??.???. 1,2,1,3,1,1 ?##??#?????? 7,1 ?.?#???.??????????? 1,1,2,4,1,1 ??????.?##??? 1,3 ?.?.????##?.????? 1,5,3 ?.#???##?#????#?#.?? 1,2,8,1,1,1 ??.?##???.#.?.?#???# 1,6,1,1,1,1 ??#??????..# 4,1,1 ?.#?.???#??#????#? 1,5,1,2,1 ?###.??#???#.?#?# 3,1,3,1,3 ??#??##????#.??? 3,4,1,1 #?##?#####?#?#??. 1,12,1 ?##??#????#??..?#?? 4,1,6,2 ?????..???? 1,1,1 ????#?????#?? 4,3 ???#?#???#?? 1,1,5 ??#????????????? 4,5,2 ?##???##?#??.???#? 10,1,3 .???#??????????#???. 4,2,7 #????#???#??#?#?.?? 8,2,1,1,1 ?.??#??#??? 1,7 ??????#.????? 2,3,5 ###??..?????#??? 5,1,5,1 ?#?????#?.???.?? 1,4,1,2 ???#???#????????..?# 1,7,1,1,2 ?###???#?????#? 8,2 .?.???#??? 1,1,3 #####???#???#?? 5,4,2 .?#?#?.?.??? 4,1,2 ?????????#??#.?.?#?? 3,6,2 .?###?##?????????# 4,2,4,2,1 #?????###???????#??? 1,13 .#?#?????#?. 3,1,1 .?#?#???#????#.#.? 1,1,6,1,1 .##??#??#?##?.?.#?? 3,2,5,1,1,1 .?#??#.??#?#??#?#??? 5,3,4,1 ??.????.?.##???????? 2,3,6,1 ?#?##??###.??#???#?? 2,2,4,1,1,1 ?#.#..????#?#?#??#?? 1,1,1,1,5,2 ??##????#????..# 3,2,2,2,1 ??.???#?..? 1,2,1 ?##?????#. 3,2 #?#??????.??##.?? 9,4 .?????#????? 6,1 ?.?.????#? 1,1,1 ???###??#?...??#??#? 1,4,2,1,1,1 .??#?????..?#? 4,1,1,2 ??.#?...#?##.?#???# 1,1,4,1,1,1 ????.?.????? 1,1,1,1 ????#????#.?. 8,1 ??#?.?#?##.?. 3,4 ?#????#.##??..?? 1,1,1,4,1 ???????#??????.? 1,1,3 .?????##..? 1,4,1 .??.####???? 1,7 .##??.???.?#?.?? 2,1,3,2,1 #???#?#?????#.. 1,1,7,1 .?.?#????????????? 1,4,6,1,1 ???.#?????? 2,3,1 ?##????..?##??#. 2,2,6 ?#.??#??.??#?# 1,2,2,1 .#??#..?#?????. 4,2 ??#???????#?.???? 3,6,1,1 .??.??.????### 1,1,5 #.?#.#????????????? 1,1,12,1 ??#????#????.??#?#? 4,1,2,1,1,4 ??????????##? 1,2,4 ##???#??????.???#??? 7,3,2,1,2 ??.???.#?##... 2,4 .#??#???#????####?# 10,6 ???#??.????? 1,1,1,1 .?#?????#???? 3,2 ???#???.?.#???## 2,3,1,6 ?#???..???? 4,2 ??#??.???.# 2,2,1 ??????##?##?#?.?. 12,1 ???#???#?.????.?? 2,6,1,1,1 #?.???.???????##?#?? 1,1,1,1,10 ?????.?##?#???? 3,5 ?????#.???#?? 4,3 ?##??????... 4,1 ?##??#?.????#.#? 3,1,2,1,2 .?.?????#. 1,1,4 ??????#?.? 3,3 #.?#?#.?##?????? 1,1,1,6,1 ?#?.?#?..??. 1,2,1 ???????#?? 3,2 ??#???????#.# 3,2,2,1 ..???.#????.??#??? 3,2,1,1,1,2 ?#?###????.#.???? 7,1,1,1 ??#.?.##?.???.. 3,2 ?????#??..#..??? 3,3,1,3 ???##???????? 6,1 ????#????? 1,1,1 ?#?##.??.??# 4,1,1,1 ?#?.??##??.?#??#?# 2,3,2,4 ????????????#? 2,7,2 ?????#?#.????? 1,3,1,1 .??.????###??? 1,6,1 ?.?#???.#?. 4,1 ???#?#?#?#????.? 11,1,1 #??.??????###???#?## 1,1,1,1,3,6 ?????.#?##?..?? 4,4 .??#?#????.?#.??? 4,1 .?#.?#???#??##??? 2,2,7 .#????.?????##?##### 1,1,1,13 ???.??.##?.#? 1,2,3,2 ???#?.???.? 2,2 ?##??###????#?#? 3,10 ?????#????##?#?..??? 7,6 .#?##.??#???? 4,5 ?.???????#??#? 1,2,1,5 ??.#.#?#??###?? 2,1,1,1,5 ?.???#???#?? 5,3 ???#?##.????#??.??? 1,5,3,2,1,1 ?#??.###????#???# 1,5,2,1 .???.???????#???. 1,1,6 ?##.#???#.#??? 3,5,1,1 .???????.?#?#? 1,1,2,4 ??.?.??#.? 2,1,1 ???#??#..#?????. 1,2,1,2,1 .???.??????.#?.? 1,2,2,2,1 ..?????.????.#??#. 1,2,2,1,1,1 ?#???.????? 1,1,3 ?##???#??#??????? 10,3 ??????????.???#? 3,3,1,5 ??...?????????.. 1,3,4 #???###?#??..#??#?. 7,2,5 #.#..#??????#?#????# 1,1,15 ?.??#?..????#?.? 2,5 ????????.?? 1,6,1 ??.???.???.#?#.? 2,2,1,1,3 ..#..??##?? 1,4 ##??#??????.#?? 8,2 ?????.?#?.? 2,2 ##.???#??????. 2,5,2 ???##??.?#?#?? 3,5 #.?????#????#?? 1,9 #??##?.?#????#????? 1,2,10 ?..?..??#???? 1,6 ??.???#?#?# 1,5,1 ??####??#? 4,1 ?.????????????.? 1,3,1 ???.??????#..#?.?? 2,1,3,2,1 ????#??.???????#???? 6,8 ??#.?#?#??#?.???? 1,1,1,3,3 .##??????.##????? 5,5 #??..???#.#? 2,3,2 ?.???.??#??????#???. 1,2,6,2,1 ?.?#?????? 5,1 ??????#?#????. 1,9 ?????.#??.?.?#?.# 2,3,3,1 ????##?#??.??#?. 5,3,3 ?.??????.#. 1,2,1 ?.##?.??.# 2,1,1 ????#???.????#? 3,2,1,2 .????##??# 1,5 ?????#?.#..## 2,1,1,2 ??.###?????.???. 7,2 ????????.?.?.#??.??# 7,1,1,1,1,1 #??##????#??? 8,1,1 ##????#?#?##?#?.??. 2,11,1 ???#???????????#?? 6,5 ?.???..#??.??.?.#?? 2,1,1,2,1,3 ?.??.?##????? 1,2,2 .??#???#?????#? 6,2,2 ..?????#.. 1,1 ?##?..????. 4,1 ??#????????#?? 2,9 ??????.???###? 4,6 ????..#???#? 1,2,2,3 ??##?.??#???# 5,2,3 #.??????..?. 1,1,2,1 .#.???.??#.?#?#?. 1,2,1,1,4 .??.?.??#???????? 2,1,2,1,3 #???#.??..?#.???? 5,2 ???.???.?.#? 2,1,1,1 ?.#??.???#??. 1,4,1 ????##?#?#???#???.? 14,1,1 ???.??##?#?#? 1,8 ???????.?##?.??? 3,1,3,1,1 #???#???.???.???? 1,5,1,2 ?????#???#?#?#? 8,1,1 ??#?#???.#? 6,1 .??????????.?##???#. 8,3,2 ??.##.?..?. 2,1,1 .???????#???#?#???? 12,3,1 ??#???.???# 5,1,1 ?##?#?##???? 3,6 ??.#???.????#?. 1,1,1,2,2 ???.#?#????#?#?# 3,1,1,3,1 ...?#.?????#? 2,2 ??..?#.?#???## 2,1,2,2 ????#????.???. 1,6,1 .???#.#?#?#?. 4,1,1,2 .??????#??##??#?# 1,5,4 ??#?.??????#?? 1,1,8 ??#??.#?#?????# 1,1,2,1,1 ?#????#???????# 1,1,1,6 ?##??????#. 2,1,1 ????.?????#?.?# 1,1,6,1 ?###??????#?#?. 4,8 .??.?.??????#. 1,1,2,1 ?#.???#????.? 1,3 ?#???.#?????#?#??? 1,1,1,8 ?#.????????.#?? 1,7,1 ?????????#...?? 1,6,2 #?.?#??#????.#???.?? 2,5,1,1,1,2 ??????..#?. 2,1,1 .??###?#??. 4,1,1 #????#??##???? 10,1 ??#??#?###? 3,1,3 ????.??????#.?##?? 1,1,1,2,1,5 ??#?.?.?#?? 2,1,1 ##.?###??? 2,3,1 .?.??..?#?.?? 1,3,1 .#?????.#???? 3,2,2,1 ??.?#??.?#???#??? 1,2,2,5 #??.???#????##? 1,1,1,1,2 ???????###.? 3,3 ????????.. 1,2,1 .?#?##?.#??#??.?? 5,5,1 ???????#?#. 4,4 ??#?#???.?? 5,2 ?.?#??#?#?#????? 1,10,1 ?...#????? 2,1 ???..????..?.?#? 2,1,1,1,2 ..?#?????#???# 9,1 ???.#??.?#?.?##???? 3,3,2,3,1,1 ??#???#??#???#..#.? 5,4,1,1,1,1 .?#.??#??#?#. 1,1,1,3 ..?.???##????.??.?? 5,1 .??.????#??..#???.?? 1,1,5,2,1,1 ##????##.#???? 3,3,2,1 ????##.???#?????#??. 1,2,1,3,6 ..???##.#?.??#?#?#? 4,1,8 .?#.????#??#?##??#?? 1,2,2,1,7 ?#?#.?#????#??? 2,1,3,2,1 ?.?##?#?#?????????? 10,2,1 ?????###????????..? 1,6,2,1,1,1 ???#.??#.???##.?## 1,1,1,1,4,2 ????..?#?###? 3,6 ??#.#???.?.? 1,1,1,1 ???????????#?????#. 6,4,2 ...?#??????.?. 4,1 ?##???????.?.??.#. 9,1,1,1 ?#?#?##???...? 3,2,2,1 .##?.?..#??????#? 2,1,1,3,1 #??##??#?#?????.?? 5,7,1 ??#?????#?.?#.# 1,1,5,1,1 ???.?#???#?.?? 3,6,1 ?.???#????? 4,1 ?#..??.??? 1,1,1 ?.#???.??? 1,3,1 #?#????#???? 1,1,3,3 ?#??????????.? 2,4 #???????.??. 1,1,1,1 ??.?#??#??..??.?## 1,6,1,2 ????#??#?# 3,2,1 ??.#?#..??#???? 1,1,3,2 .#?...??#????.????#? 1,3,2,6 #?#?.#..?.??.?.?#?? 3,1,1,2,1,3 #????.??##? 1,4 ?.?.???????#?. 2,1 #??#..?#????#???.?.? 1,1,10,1,1 #????????#?.?... 6,3,1 ????###????? 5,2 #??.?????. 3,4 ?.?????????#?#.??? 6,3,2 ?????..?.? 3,1 ??#??##??.???. 4,3,2 .?.????#?? 1,2 ??#??.????.? 3,2,1,1 ????#??.??##? 7,3 ?????#..???? 4,1 ?.??#??##? 3,3 ??.???.?#? 1,3 ??.#?.?#..?? 1,2,1,2 ??..?#???. 2,4 .#.???#???###?#??.? 1,1,2,3,1,1 ?.##???#???.?????.? 8,4 ????.??.#???.#??? 1,1,4,1,1 .??#?#?...#?.??? 3,2,1,1 ??.?????#??# 2,1,4,1 ???#??#???#?# 3,7 ?.??#..?????#????#? 1,1,1,2,7 #?.??.#?.?#?.???###? 2,1,1,2,1,3 #????#?#??.???. 1,6,1,1,1 ????.???#???#?????? 1,2,6 .?.???????#???.??? 9,2 ?##??.??##. 2,3 ?#?????#???.#???##? 3,3,1,4 #??????#?###???#?? 2,13 ???#??#???????? 6,1,1 ??#??##????? 1,3,1 .??..#??#? 1,1,2 ?.??###???#.?????. 8,2 #..???#??.???? 1,1,3,1 ??????.??? 2,1,1 ?#???.???# 1,1,1 ?###??.?????# 6,1,1,1 ??????????? 1,1 ?##???#????????#.?#. 4,1,7,1 .?.#??.??#?#? 3,3 ????.#?.?# 1,2 ?#??.????.???.? 4,3,2,1 .???#??#???#?.???..? 3,3,3,1,1 ???.???.????#???#? 1,1,1,1,8 ????#??#?.?## 7,2 #??????.???#?#??#? 6,7,2 .???..?#?# 1,3 ?????#?#?#?#?????? 12,1 #?..?.????????#??? 2,1,1,1,2,1 ??#???...??#??? 1,5 ?.??????#.??? 3,2,1 .?#.?#..??.#??? 1,2,3 .??????#?#...?#?.? 5,2 ??.???#??#? 1,1,2 ???#??#?????#?##???? 8,4,1 .#??#????????.????. 6,3,3 .#?#?.?.#??.?? 4,2 ?#???##??##???? 2,10 ???.???????#?? 2,1,3 ?#???#?##??.#?? 4,5,1 ???????????????#??? 4,1,1,1,2,2 ??#???#?#??????#? 2,5,6 ??#?.??#..?#??? 3,1,1,5 ?#???#.???.#..# 2,2,1,1,1 #???????##??.#?.? 1,1,1,3,2 ?????#??###??? 2,7 #????????##.?.??. 2,7,1 ?.??#?..???#?#????. 3,10 ??????#?..???????.? 5,2 ???#????????????? 1,1,2,2,3 ????.#???#?.. 1,6 ??.??.#??#????????? 1,2,9,3 ????.?..##??? 1,1,2,1 ?#?#????.?#??#??? 8,5 ##?#???#???#?#.??? 5,2,4,2 ??.??#?????#? 1,3,1,2 ??.???#?.##? 1,2,2 ..??.?????# 1,6 ?##??#???#??? 3,2,3,1 ?????#???#?###?##??? 1,2,13 #?#?#??????#.??#?? 12,3 ???.???#?????????? 2,6 #??##????????????# 10,2,1,1 .?.?.???????? 2,1 .?????????##????? 1,4,7 #????#?##?? 1,5 ??.??#??????..#?. 1,1,2,4,2 #..???..?.#?? 1,1,1,2 .#??#?#?.?.????? 1,4,1,3 #?????????.???#??? 7,1,4,2 #???##?#??# 2,5,1 ????.#.?..?#?#. 1,1,4 ?#???#?#?????????? 1,1,1,1,4,1 ??????..???????. 1,2 #????#?.??##.????#? 2,3,4,1,4 ??###???#?.???####? 9,4 ?.?#?#??.?#??## 6,2,2 ?#?.????#???#.?#.? 1,1,5,2 ?.??.???.??? 1,1,1,1 .??#?????#?? 5,2 ????.?.?#...? 1,2 .?#...?#??#?#??#?#? 2,12 ???.?????##?? 1,9 #?#??????.????? 7,1,2 ???#??..#?. 1,2 ???????#?.?.???. 9,1,1 #???#???????# 1,1,1,5 ???#?????? 3,2,1 .##.?????.?.#?????? 2,2,1,1,1,2 .????..##?#?##????# 1,1,10,1 ??#?????#???#?.???# 1,2,1,2,2,1 ##??.?#?#?##?.???.?. 3,7,2 .#???..???????? 4,4 ?#?##.?.?? 5,2 ??#??..?.??? 3,1,1 ?.#.??#????#??????# 1,1,1,1,10 ????.#?#???? 1,3,1 ????..???#?#?#???? 1,1,1,6,1 .###???????#????.?? 3,8 .#??????.. 1,1,1 ???.??#??????. 2,1,3,1 ?#??#?.?????##???.?# 6,1,2,1,1 .??.#?????.??????. 5,6 .???.#?##? 1,1,4 ???????.?##? 3,1,2 .?#??#????? 5,1 ??????#??.##??#?. 7,6 .????..????## 1,1,2,2 ?..#?.##?#?#????#?.. 2,8,2 ??##.????????#?? 3,5,2 #?????????##?.?? 2,1,1,3,2 .?#?.#?????##???? 2,2,7 .?.?????????## 1,1,9 ?????.?#??. 3,3 ?#?#??..?? 1,1,2 ?.??.?#??.#????.#??? 1,1,2,5,1,2 ???.?.?##????# 1,1,8 ???##???##.???.? 5,1,2,1,1 .????????#???###? 3,8 ???#??#??.??## 5,1,1,2 #.????????.#? 1,4,1,2 ?????????? 4,1 ##?#?.???#?#???.?? 5,1,3,1,1 ??.?#????. 1,1,1 ???.?.?????#?????#. 1,1,1,6,1 ?.?????..?### 1,1,1,4 ??##???##???#??.??# 8,1,1,1,1,1 ?.#??#??##?.?.?.???? 1,1,5,1,1,4 ?.??##?.???.? 4,1 ..?#?????? 3,1 ????#??.?????#???#.? 5,1,1,3,3,1 ???????##?#?.#?????? 2,5,1,4 ??.?#??#??#?????##? 1,11,2 .???????.???###?? 1,1,2,5 .???#??#????##??? 6,5 ##?#??.??#.. 2,2,1 .???.????? 2,1,1 ?...??.?.?#?###?##?# 1,1,1,1,8 ??????#?#?#??#.?... 2,9 ??????###???.#???# 1,4,2,1 .?..??.???.# 1,2,1,1 .???..?#??#?#??. 1,9 ???.????###?? 3,6 ?##????###???.. 2,8 ???#?#.??#?? 5,4 ??##?###???#???????? 9,1,1,1,1,1 ?..###??????????.? 1,3,2,4 #??##????###??????? 14,2 ?###?#??#??#??.???# 4,2,5,1,1 ??.###?#???.. 6,1 #?#?#?..??#? 1,1,1,4 ?#.???#??.#???##???? 2,1,2,2,6 .?##.?##??#?????..? 2,8 ????.?#.?.?? 2,2,1,1 #??.??????#? 3,1,5 ??.#???.??#?#? 2,1,1,5 ???.??#?????? 2,1 ???.?????#?.#. 1,3,1,1 ??..??..???????? 1,1,2 ??????#?????#???? 9,2 ??????#???#? 1,1,7 ???#???.????..? 1,3 ?????.???## 1,4 .##???.##??.???.?#. 4,2,1,3,2 .#?#?.??????????? 4,4,2,1 ?#???.???. 5,1 ?##????..##?..?#? 7,3,2 ????????????? 5,1,1,1 .??#??#????????????? 1,1,1,5,1,1 ???.???#??. 1,5 ???.??.#.???. 3,1,1,1 ???...?#?? 2,2 .?.#??##.??.?? 5,1 ?..????.?#?##?# 1,4,7 .#.??????. 1,5 .??????#...?? 3,1,1 .????#..?.????? 5,2 #?#???????#???##?.. 9,7 ###???????#.????#??# 3,1,4,3,1,2 .?.##????#???#??? 1,4,7 ??????????#???#? 1,4,1,4 ??#??#.##????#? 5,3,3 ??.?##???????.?.#?? 1,3,1,1,1,2 .?#???#?#?????#??##? 7,7 #..??.???#?????. 1,1,1,5 ??.#.?#???##??.# 1,1,9,1 ???.??#??????##???? 1,4 ???.???#??.?#????#?? 1,4,7 #???#??#?#.#??.?# 2,7,3,1 .??.???????#??#? 1,1,9 .?#?.????.???? 2,2,4 .????.#????.?? 1,1,3,1 ??????#????#?...?? 12,1 ?##???#????#?#?.#??? 9,1,2,2,1 ??##??..#.? 5,1 .???.?.???????.. 2,2,4 #???#?.?????#? 6,1,1,1 ??#??#.?#?. 3,2,2 ?.??????#?#??#?????? 1,12 ?....??????# 1,2,1,1 .?????#?????#.?.# 1,6,1,1,1 ????#?####???????? 1,10,1,1 ??#?.??.?? 2,1 ?.?.#.?.????#???.? 1,3 .#?.#?#???#??#?? 1,3,1,3 ..?#???..?????.? 4,2,1,1 ??###?#???.?????#..? 8,6,1 ???.?#???##???#? 2,10 ?##??#???????????? 10,1,2 ????#???.??? 3,1,2 ?.???.????????#????? 3,1,7,1 .?.?#??#???? 5,1 ?..???#?.?????? 4,1,1 ??#?#?.???.##?### 2,2,2,6 .???.?#?#?#???# 1,1,7 ???#??..#???. 4,1,1 ?#.????.????#??.. 2,2,7 ????????#.?#.? 1,5,1 ?.?#..??#??? 1,1,3 ?????#???????#???#. 6,1,1,3 .#.??#??.?# 1,4,1 .##??.?##?#. 2,5 ????##??#?#?#?#?#?# 1,15 ?#?.#?.##?#?????##? 2,1,6,4 ..?????#?##???. 9,1 ????.#?###???????? 1,7,1,1 .?#????????.??????? 9,4 ?.?#??#???????# 4,1,2,1 ???#?#?????.?##??# 8,6 ?#????#??. 1,2 .??????.?.# 5,1,1 ?##??#.???#??.? 5,1,1,1 ?.?????????#? 1,1,1 ================================================ FILE: exm/aoc/2023/aoc_2023_12_questions.txt ================================================ --- Day 12: Hot Springs --- You finally reach the hot springs! You can see steam rising from secluded areas attached to the primary, ornate building. As you turn to enter, the researcher stops you. "Wait - I thought you were looking for the hot springs, weren't you?" You indicate that this definitely looks like hot springs to you. "Oh, sorry, common mistake! This is actually the onsen! The hot springs are next door." You look in the direction the researcher is pointing and suddenly notice the massive metal helixes towering overhead. "This way!" It only takes you a few more steps to reach the main gate of the massive fenced-off area containing the springs. You go through the gate and into a small administrative building. "Hello! What brings you to the hot springs today? Sorry they're not very hot right now; we're having a lava shortage at the moment." You ask about the missing machine parts for Desert Island. "Oh, all of Gear Island is currently offline! Nothing is being manufactured at the moment, not until we get more lava to heat our forges. And our springs. The springs aren't very springy unless they're hot!" "Say, could you go up and see why the lava stopped flowing? The springs are too cold for normal operation, but we should be able to find one springy enough to launch you up there!" There's just one problem - many of the springs have fallen into disrepair, so they're not actually sure which springs would even be safe to use! Worse yet, their condition records of which springs are damaged (your puzzle input) are also damaged! You'll need to help them repair the damaged records. In the giant field just outside, the springs are arranged into rows. For each row, the condition records show every spring and whether it is operational (.) or damaged (#). This is the part of the condition records that is itself damaged; for some springs, it is simply unknown (?) whether the spring is operational or damaged. However, the engineer that produced the condition records also duplicated some of this information in a different format! After the list of springs for a given row, the size of each contiguous group of damaged springs is listed in the order those groups appear in the row. This list always accounts for every damaged spring, and each number is the entire size of its contiguous group (that is, groups are always separated by at least one operational spring: #### would always be 4, never 2,2). So, condition records with no unknown spring conditions might look like this: #.#.### 1,1,3 .#...#....###. 1,1,3 .#.###.#.###### 1,3,1,6 ####.#...#... 4,1,1 #....######..#####. 1,6,5 .###.##....# 3,2,1 However, the condition records are partially damaged; some of the springs' conditions are actually unknown (?). For example: ???.### 1,1,3 .??..??...?##. 1,1,3 ?#?#?#?#?#?#?#? 1,3,1,6 ????.#...#... 4,1,1 ????.######..#####. 1,6,5 ?###???????? 3,2,1 Equipped with this information, it is your job to figure out how many different arrangements of operational and broken springs fit the given criteria in each row. In the first line (???.### 1,1,3), there is exactly one way separate groups of one, one, and three broken springs (in that order) can appear in that row: the first three unknown springs must be broken, then operational, then broken (#.#), making the whole row #.#.###. The second line is more interesting: .??..??...?##. 1,1,3 could be a total of four different arrangements. The last ? must always be broken (to satisfy the final contiguous group of three broken springs), and each ?? must hide exactly one of the two broken springs. (Neither ?? could be both broken springs or they would form a single contiguous group of two; if that were true, the numbers afterward would have been 2,3 instead.) Since each ?? can either be #. or .#, there are four possible arrangements of springs. The last line is actually consistent with ten different arrangements! Because the first number is 3, the first and second ? must both be . (if either were #, the first number would have to be 4 or higher). However, the remaining run of unknown spring conditions have many different ways they could hold groups of two and one broken springs: ?###???????? 3,2,1 .###.##.#... .###.##..#.. .###.##...#. .###.##....# .###..##.#.. .###..##..#. .###..##...# .###...##.#. .###...##..# .###....##.# In this example, the number of possible arrangements for each row is: ???.### 1,1,3 - 1 arrangement .??..??...?##. 1,1,3 - 4 arrangements ?#?#?#?#?#?#?#? 1,3,1,6 - 1 arrangement ????.#...#... 4,1,1 - 1 arrangement ????.######..#####. 1,6,5 - 4 arrangements ?###???????? 3,2,1 - 10 arrangements Adding all of the possible arrangement counts together produces a total of 21 arrangements. For each row, count all of the different arrangements of operational and broken springs that meet the given criteria. What is the sum of those counts? --- Part Two --- As you look out at the field of springs, you feel like there are way more springs than the condition records list. When you examine the records, you discover that they were actually folded up this whole time! To unfold the records, on each row, replace the list of spring conditions with five copies of itself (separated by ?) and replace the list of contiguous groups of damaged springs with five copies of itself (separated by ,). So, this row: .# 1 Would become: .#?.#?.#?.#?.# 1,1,1,1,1 The first line of the above example would become: ???.###????.###????.###????.###????.### 1,1,3,1,1,3,1,1,3,1,1,3,1,1,3 In the above example, after unfolding, the number of possible arrangements for some rows is now much larger: ???.### 1,1,3 - 1 arrangement .??..??...?##. 1,1,3 - 16384 arrangements ?#?#?#?#?#?#?#? 1,3,1,6 - 1 arrangement ????.#...#... 4,1,1 - 16 arrangements ????.######..#####. 1,6,5 - 2500 arrangements ?###???????? 3,2,1 - 506250 arrangements After unfolding, adding all of the possible arrangement counts together produces 525152. Unfold your condition records; what is the new sum of possible arrangement counts? ================================================ FILE: exm/aoc/2023/aoc_2023_13.adb ================================================ -- Solution to Advent of Code 2023, Day 13 ------------------------------------------- -- Point of Incidence -- -- https://adventofcode.com/2023/day/13 -- Copy of questions in: aoc_2023_13_questions.txt -- -- HAC 0.26 "nice to have"'s detected in this exercise: -- * Unsigned_X and logical operators on it. -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_13 is use AoC_Toolbox, HAT; maxi : constant := 31; subtype Max_Range is Natural range 0 .. maxi; map : array (Max_Range, Max_Range) of Boolean; row, col : array (Max_Range) of Integer; m, n : Integer; procedure Prepare_Binary_Numbers is a : Natural; x : Positive; begin for i in 1 .. m loop a := 0; x := 1; for j in reverse 1 .. n loop if map (i, j) then a := a + x; end if; x := x * 2; end loop; row (i) := a; end loop; for j in 1 .. n loop a := 0; x := 1; for i in reverse 1 .. m loop if map (i, j) then a := a + x; end if; x := x * 2; end loop; col (j) := a; end loop; end Prepare_Binary_Numbers; function Calc_Ref_Code (old_rc_to_avoid : Natural) return Natural is sym : Boolean; ref_code : Integer; s1, s2 : Integer; begin -- Find vertical reflection: for j in 1 .. n - 1 loop sym := True; for jj in 0 .. n loop s1 := j - jj; s2 := j + jj + 1; exit when s1 not in 1 .. n or else s2 not in 1 .. n; sym := sym and then col (s1) = col (s2); exit when not sym; end loop; if sym and then j /= old_rc_to_avoid then return j; end if; end loop; -- Find horizontal reflection: for i in 1 .. m - 1 loop sym := True; for ii in 0 .. m loop s1 := i - ii; s2 := i + ii + 1; exit when s1 not in 1 .. m or else s2 not in 1 .. m; sym := sym and then row (s1) = row (s2); exit when not sym; end loop; if sym then ref_code := 100 * i; if ref_code /= old_rc_to_avoid then return ref_code; end if; end if; end loop; -- Hummm... No reflection found ? return 0; end Calc_Ref_Code; r : array (Part_Type) of Integer; bit_flipping_method : constant Boolean := True; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2023_13"; -- procedure Read_Data_and_Solve is f : File_Type; s : VString; rc, rcs : Natural; mem_row, mem_col : Integer; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop m := 0; n := 0; loop Get_Line (f, s); exit when Length (s) = 0; m := m + 1; n := Length (s); for j in 1 .. n loop map (m, j) := Element (s, j) = '#'; end loop; exit when End_Of_File (f); end loop; -- -- Map is loaded. -- Prepare_Binary_Numbers; rc := Calc_Ref_Code (0); r (part_1) := r (part_1) + rc; -- -- Part 2: after the correction on the mirror -- there are one *or two* reflection lines! -- So, if we go for correcting the smudge and -- check the new reflection line, we have to be -- sure that we don't report the old line! -- -- Variant: we could cumulate 1-bit differences -- in a variant of the function Calc_Ref_Code and -- spot *the* new reflection with an aberration of -- exactly 1. This would save the double loop below. -- Smudge : for i in 1 .. m loop for j in 1 .. n loop -- Test flipping the bit on cell (i, j) of the map. if bit_flipping_method then mem_row := row (i); mem_col := col (j); -- All this would be easier with Unsigned_X and an "xor" mask... if map (i, j) then row (i) := row (i) - 2 ** (j - 1); col (j) := col (j) - 2 ** (i - 1); else row (i) := row (i) + 2 ** (j - 1); col (j) := col (j) + 2 ** (i - 1); end if; rcs := Calc_Ref_Code (rc); exit Smudge when rcs > 0; row (i) := mem_row; col (j) := mem_col; else map (i, j) := not map (i, j); Prepare_Binary_Numbers; rcs := Calc_Ref_Code (rc); exit Smudge when rcs > 0; map (i, j) := not map (i, j); end if; end loop; end loop Smudge; if rcs = 0 then Put ("New axis not found !!!"); end if; r (part_2) := r (part_2) + rcs; end loop; Close (f); end Read_Data_and_Solve; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data_and_Solve; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 33728 -- Part 2: validated by AoC: 28235 end if; end AoC_2023_13; ================================================ FILE: exm/aoc/2023/aoc_2023_13.txt ================================================ #..#.#........# #..######..#### .##..#.#.##.#.# #..##.......... ######........# #..####......## .##.##.#...##.# ..######. ..######. ....#..## ##.....## ##..#...# ..##..... .#..#.#.. .#..###.. ..##..... ###..#....#####.. .#........#.#.### .#........#.#.### ###..#....#####.. #.#.#####....#### .#.###..####.#..# #..#..#.####...#. #..#..#.####...#. .#.###..##.#.#..# ..###..######.. ...#####.##.### ##....#..##..#. ##.......##.... .#.##..#....#.. #########..#### ..###.##.##.##. ..##.#.######.# #####.#.#..#.#. ..##.##..##..## ###.########### ..#...###..###. ..#.#.#.####.#. ###.#.########. ...#.##.#..#.## ..#.### .###..# .###..# ..#.### .#..#.. .##.#.# ####.## #.##.## #.#..## ####.## .##.#.# .#..#.. ..#.### ....#..#.#... .#.#..#..##.. .#.#..#..##.. .#..#..#.#... ..####...##.. ..####.#.#.## .#..##..#.#.. #..#..##..### .###.##.###.# .###.##.###.# #..#..##..### .#..##..#.#.. ..####.#.#.## .##.#.##. ..##.#### ..####### ###...... ..##.#### ....##..# ###.#.... .....#### ###.#.##. ....#.##. ..####### ...##.##. ##..##### ##..##..# ..#...##. ...###..# ..###.... ....#..#######..# ......#.#.###.##. .##.#.#..#...#..# #########.##..... ####..##.##..#..# ######.#....##..# ####..#...#...##. .##.##.....#.#### .##.##..##.###..# #..####.##..##..# .##..###.#..##..# #..##...#####.... #..####.#.#.#.##. .##..#..##..##### #..#.#...#.#..##. ######..########. ....###.##...#..# ...#..#........ .#.#..#.#.##.#. ..#....#..##..# .#..##..#....#. ..######......# ...#..#..#..#.. ...#..#........ #...##...#..#.. .##.##.##....## ...#..#...##... #..####..####.. ..#.##.#......# ..#.##.#......# ###....###..### #........####.. ...##..##.#.# .##.#####.### ##.#....####. #.#....#.#..# .#..#.#...#.# .#..#.#...#.# #.#....#.#..# ##.#....####. .########.### ...##..##.#.# #.#.###.....# #.#.###.....# ...##..##.#.# ....#.#.##. ....####### ######....# #..#....### #..#..#..#. ####...##.. #..#...#..# #..##..#..# ####...##.. #..#..#..#. #..#....### .#..##..##..#..#. ..#...##...#..... ##...####...##### #.##......##.#..# #.##......##.#..# ##...####...##### ..#...##...#..... .#..##..##..#..#. .#..#.##.#..#.#.. .##...##...##.#.# .#...#..#...#.#.. #.#........#.#... .#...####.#.#.#.# #.##.####.##.##.. #............##.# ##...####...##... #............#### #..#.#..# ####..... .##.##..# .##.#.##. #####.##. .##.#.### #..#.#..# ###..##.####..### ###..##.####..### ##..###.#.#...### #.#.#..##..####.# #.#..#...#..###.. ..#....####.#.### #..#...##.###.#.. .###......####.## #..#.#...######## #.##.#..#...#.. .#...#.....#... #.#..#.#.##.### .#####.#.#..#.# .#####.#.#..#.# #.#..#.#.##.### .#...#.#...#... #.##.#..#...#.. #.#.#.###.####. #..###....###.. #..###....###.. #...##......##. ..###..#..#..## ###.#.##..##.#. .##.####..####. ..###..#..#..## ...#...####...# ###....#..#.... ###....#..#.... ...#...####...# ..###..#..#..## .##.####..####. ###.#.##..##.#. ..###..#..#..## #...##......##. .##.####..####. ....##.####.##. .#...##.##..#.. .....#.## ...###.#. ...###.#. .....#.#. ..#.##### ..##..##. ...#...#. ..##.#.## ####..... .....##.# ##.##.### ####.#... ##...##.# ..#..#....#..##.. #.#.#.#####..#### ..#....#..#..#..# .##.############# ##.###.#..#..#..# ...#.##.##.##.##. .#.#..##.#.##.#.# ..#..#..########. ##.####.##....##. #####.#..#.##.#.. #.####..#.#..#.#. #.####..#.#..#.#. #####.#..#.##.#.. #.#....## #...#..#. .##..#..# .#.#..### ##.#..### .##..#..# #...#..#. #.#....## .#.#....# .#.###### ##.#..#.. ##..##### ...#.#... ...##.... ...##.... ...#.#... ##..##### ##..##### .#.##.... .#.#..##. .....#..# .##.##### .######## .....#..# .#.#..##. .#.##.... ##..##### ..#.#.##. #.#.##.#.##...... .###..###...#.##. .#......#.###...# .#......#.###...# .###..###...#.##. #.#.##.#.##...... #.#.##.#.#......# .###..###.###.#.# ####..####.##.##. #.#.#..#.###.#### .#.####.#...#.#.. .##....##....#.#. .##.##.##.###.#.. .#.#..#.#.#.#.#.. #.#.##.#.#.#####. ..##.###### ##.#.#####. ##.#.#####. ..##.###### ..###..##.. ....###..## .#.#....... ####.#####..##### #......#......#.. ....#..#......#.. ....#..#......#.. #......#......#.. ####.#####..##### ...#............. ...#####.#..#.### .###..###...####. #.##..#........#. .#.#.#..##..##..# ..#.#..#.####.#.. #.#..##..#..#..## ######.###... #..#.#.#.##.. ....#.##..... #..#..#.###.. ...#.#...#### .....##.##### .##..#..##... #..#.#.###### #######.#.### .####..## #.#...#.. ...###.## .##..#.## .##.###.. .######.. ...#..#.. #.#..#.## .#####... ####.#.## .###.#### .###...#. ..#....## .#.###### ##..##... ##..##... .#.###### .##....##....##.. .###...##...##### ##.####..####.### ..##.##..##.##... ##..#.#..#.#..### ....#..##..#..... .#..###..###..#.. #.#...#..#...#.## ...#.######.#.... #.##........##.## #.#.#.####.#.#.## #..##.#......## #..##.#......## ..##.###.#...## .#........##.## ..########.#... ##.#.#..##..... #.#..#...#..### ##...###.#.#.## #..#..#.##.#.## #..##.....##### ##.#.#####.#### .###..#..#..#.. ....##....###.. ###.#.###.####. .#...##.#..#... .##.##.##.... ..#....#..### .#..##..#..## #..#..#..#... ##......##### .#..##..#.#.. ###.#######.. ##########... ###....####.. ..#.##.#..### #.######.###. ..........#.. ..........#.. #.######.###. ..#.##.#..### .##...##.#### #.###.#.#.... ....#.#.##..# #########.##. .##..#.#..##. ....##..##..# #..#.#..##..# .##.##...#### #..#....#.... #..#..#..##.### #.###..##...### ##.###....#.#.. #.##..#.##.#### .#..######.#.## #.##.##..#..#.. ##..###....#... ##..###....#... #..#.##..#..#.. .#..######.#.## #.##..#.##.#### ##.###....#.#.. #.###..##...### #..#..#..##.### ####..###.#.... #.#.###....##.. ..###.###...### ####.###.#### ###..#.#####. #.###..####.. #.##...####.. ###..#.#####. ####.###.#### ..##.###..#.. #....##.#.### #.##.#..##.## #.##.#..##.## #....##.#.### ..##.###..#.. ####.###.#### .#.#....# .#.#....# .#.#####. ###...#.. ...###.## ....#.#.# ....#.#.# ...###.## ##....#.. .#.#####. .#.#....# ##.#####... #..#..##... ###...#..## ....#.###.. #.#..#..### #.#..#..### ....#.###.. #.#...#..## #..#..##... ##.#####... ...##...### .#...##.### ...#..#.... ###...##..##... ##..#.#.##.#.#. ..##..######..# ###.##.####.##. ...#.###..##### ##.###.#..#.### ##.####....#### ...#.#..##..#.# ..#...#....#... ###.##########. ##..##.####.##. ###.#.#.##.#.#. #####..#..#..## #.##.##.##. #.#.#..#.#. #.#.#..#.#. #.##.##.##. #.##.##.##. #####..#### .#.#.##.#.# ....##.#... ##..####..# .##......## .#........# ####......##..# #####.###.##... ....####...#### .#......##.#... ####.#.#..#.### ##....#.#.#..#. #..#.###..#..## #..#.###..#..## ##....#.#.#..#. ####.#.#..#.### .#......##.#... ....####...#### #####.###.##... ####......###.# ##....####.#.#. ...####.###.... ...####.###.... ..##...##..##.# ..##...##..##.# ####..#.#..#... ..##..####.#.#. ..##.#...###..# ##...###..#.### ##..########..# .#.##.#...#..#. ...##.#.#..##.# #########.##..# ..#.##.#.##.... ..#####...##.#. ##...##..#.#... ........#.# #.....###.# ##....##### #..##..##.. ..#..#..### .#....#..#. .#....#..#. ..##.## .#.##.. #.###.. ..#..## ####.## .####.. #.##... ....### ...#... ##..### #...### ##.#....######..# ..##.#.##....#### ##...#..#....#..# #.###..#####.#..# #####..###...#### ..#.######.###..# ...#.#.####..#..# #...#..##.#...... ...#...#...###### ...#...#...###### #...#..##.#...... ...#...####..#..# ..#.######.###..# ####.##.# .#..#..#. #..#.##.# .##...... #..##..## ....#..#. .##.####. ####.##.# ....####. .##..##.. ....#..#. ....####. ####....# ....####. ....####. ....####. .##.#..#. #.######.###.## #..#..#..#....# .#......#.##... .#..##..#.####. #..####..#.##.. ##..##..######. .#.#..#.#.##### .#.#..#.#..##.# .#.#..#.#.###.# .###.###. #.#.....# #.#.#.#.. .##.##..# ...#.#.## #..#.#.## .##.##..# #.#.#.#.. #.#.....# .###.###. ...##.##. ..#####.# ..#####.# ...#.####..#.#### ##........#.#.#.# ..###...#.##..... ..###...#.##..... ##........#.#.#.# ...#.####..#.#### #..##.#...####### ....#.##.....#..# ###.##.#.#..##..# ...####.#.#...#.# ..#.#..####....#. ....#.####...#### ###.#..#..#..#.## .....#######..#.. ....##......#.##. ##.#####.....#..# ###..##.##...###. #..##.##### #..##.##### .##.#.##... #...##.###. #..##.###.# #######.#.# #.#..#####. #.#..#####. #######.#.# #...#.###.# #...##.###. ..#.####.##..##.# .#.##.#####..#### #.#.###.#.####.#. ###..###........# #...##..#......#. #..###.#.######.# .###...########## #.#.#.#.##.##.##. ######...##..##.. #.......#......#. #.###.#####..#### ###...##.#.##.#.# #.##..#####..#### ..###.#...####... .#.....##.#..#.## ##....##.#.##.#.# #.....##.#.##.#.# #..#.##....## #..#.##.....# ######.###... ##########.## .##..#.....#. #..#....##.## ......##....# ........#.... ....##.##.#.. .......#.#..# ......##..#.. .##..#.###### .....#.#.###. ...#.#..### ...#.#..### .##....#### ###...#.### ....#..#.#. ....####... ...#.#...## ####.####.# ....#.##.#. ..###..##.. .#.######## .###....### ..#..#####. ####...#.## ####...#.## ..#..#####. .###....### .#.######## ..###...#.. ##..#...#.. .#.....#..# ########..# .#.##.#.... .#.##.#.... ########..# .#.....#..# #..##.. ..#..#. .###### ..####. ..####. ##....# .#.##.# .#.##.# ##....# ..####. ..####. .###### #.#..#. #..##.. #.#..#. .##...##.## ..##.##.### ###...##... ....#..##.. ....#..##.. ###...##... ...#.##.### .##...##.## ..#....#.## .###..##.## .##....###. .##....###. .###..##.## ..#....#.## .##...##.## .....#.##...#..## #.#...###..###### ###.#...#.#.##### ###.#...#.#.##### #.#...###..###### .....#.##..##..## #####.#.###.#..## ##.#.####..###### #.##.###.#....... ###.#..#..# ..#.#..#.#. ..#.#..#.#. ###.#..#..# ...#.#..##. ###..#.###. ..#..###.#. ##.#.#...#. .#.###..#.. ###.##..### ..#....#.#. ##.#.##.#.# ..#...#...# ....#.#...# ..#..#.#### .##.####.##.####. .##.####.##.####. ..#....##..##.... #...###......###. ..#.#.#.#..#.#.#. ##..##.#....#.#.. #.#.##.#.##.#.##. #....###....###.. ........####..... .#.#.....##.....# ###.##...##...##. #.#####.##.## ...#...#..... .##.#.##..### .###.##...### #..#..##....# ..###...#.##. ..###...#.##. #..#..##....# .###.##...### .#..#.##..### ...#...#..... #.#####.##.## #.#####.##.## .#.#.#..#..##.. .#....##.###..# ###..##.#.##.## .#####.#######. .#####.#######. ###..##.#.##.## .#....##.###.## .#.#.#..#..##.. ########....#.# #..##.##.##.#.. #..##.##.##.#.. ########....#.# .#.#.#..#..##.. .#....##.###.## ###..##.#.##.## ..#..##.... #..#....##. ##.##...... ###...#.##. #.#..###### #.##....##. .##.#####.# ..##.#.#..# ..##.#.#..# ..##..##.....###. #.#....#.#..#.#.. #...##...####...# ..#.##.#..##..#.# .###..###....###. ##.####.######.## ..######..##..### #........####.... #.#.##.#.#..#.#.# ####..####..####. ##.####.######.## .#......#.##.#... #..####..#..#..## .#.####.#.##.#.## .###..###....###. ...####...##...## #...##...#..#...# #.#..#..# .###.##.# .###.##.# #.#..#..# #.##..### .####.##. .###..#.# ##.#..### .#.#..... .#.#..... .#.#..### .###..#.# .####.##. #...###.#.##.#### ##..##.###..##..# ..##...###...#..# #.##.###.##...##. #.##.###.#....... ..##....#..##.... ......###....#..# .#.....##.... .#.....##.... ......#..#... #..#...##...# #.#.#..##.##. ##..##....##. ##.#.##..##.# ####.##.. .##..#... .##..#... ####.##.. ####..#.. #..#..#.# .....#.## #..#.##.. .....#..# #..#.#.#. ....###.# #####.#.# ####..... ####.##.. ....#..## ..#.###.. #..##.#.. ....##.## ..#....#. ..#...... ....##.## .....##.. ##.#.##.# #...#.##. #..#.##.# .#.##.### .#..##.#. .#..##.#. .#.##.### #..#.##.# #...#.##. ##.#.##.# #.##########.## .#..######..#.. ####.#..#.##### ###.#.##.#.#### ...#..##..#.... .##.#.##.#.##.. ..#..####..#... #.#........#.## ..###.##.###... ..#...##.#.#... ###...##...#### #.#.#.#.. ####.##.. .#....### .#....### ####.##.. #.#.#.#.. .#####... .####..#. ..####... .#....... #..###### #..#......#.. #####....#### #.###.##.###. #.###.##.###. #####....#### #..#......#.. ###.######.## #.##########. ..###.##.###. .#..#.##.#..# .#...#......# #.#..####..#. ###.##..##.## .####..######## #.##.#..###.... ..##..#.#..##.. .#..#...#...... .####...##.#### ##..##########. ##..##..#..##.# ##..##..#..#### ##..##########. .####...##.#### .#..#...#...... ..##..#.#..##.. #.##.#..###.... .####..######## ######....###.# ..##..#.#.#.### .#..#.....##.#. ......#..#. .......##.. ##..##....# ######....# ######....# #.##.#....# #.##.#....# #.##.###### ...#....... ##..#..#..###.. ##..#..#..###.. .###....###..#. #...####...#### ####.##.#####.# ...##..##...##. .##..##..#....# .#..#.##..###.#.# #....###.#.##.##. #....###.#.##.##. .#..#.##..###.#.# ######.#.#...#.## .......##.#.#.... #########..#..... .#..#...#...###.# .####.###.#....## #....##.##..#...# #......##.####..# .#...#.###.## ..######..... ###..###.#### #...##.#...## .#####.#.##.. .##..#..#.#.. #.##...###.## ##..#.###.### ###..#...#### #..#..##..... ...##..#.#### ...##..#.#### #..#..##..... ###..#...#### ##..#.###.### #.#....###.## .##..#..#.#.. .#..##.#..#.#.#.. ...##..##....#.## ..#......#......# ..##....##....#.. .##..##..##.....# #.#..##..#.#...#. #.#..##..#.#...#. ##..... .....#. .###.#. .###.#. ....##. ##..... #..##.# #....## #....## #..##.# ##..... ##..### ..###.. ##.#.## .####.. ..#.#.. .#.##.. .#..... .#..... .#.##.. ..#.#.. #####.. ##.#.## ..###.. ####.##.....###.# #####.......#..#. #####.......#..#. ####..#.....###.# #..####..#.#.##.# .##..#..........# ######..#.##....# #..####...###...# ####..#..###..... .......#.##.##... ....##.###.##..#. #..##..###...#.#. ....#...#.##...## .##........##.... .....#.####..##.# #..#..#..#.#.#..# #######.#.#.#.... ##.##.##. #.#..#.## #.#..#.## ##.##.### .#....#.. ##.##.### .##..##.. .#....#.# #.####.## .######.# .#.##.#.# .#.#..#.#.##. #..#..#..#### ..#.##.#..##. ##..##.###### #..#..#..#### .##....##.... #..#..#..#### #.##.####.####### ..#.#...###.####. .#.#....##...##.. ..#.###.##..####. ##.#####..#.#..#. .##.##.######..#. .##....#.#..####. ...#..##.##.####. ...#..##.##.####. #.#..#. .##..## ###..## ###..## .##..## #.#..#. .#.##.# #.#..## .#....# ...#.....#.## ..#.#.#....#. #####..##.##. ####...##.... #####.#.#..#. ..####..###.# ..#.#...#.... ..####..##... ...####.#.### ##.##.####..# ##..#....#.## ##.###....#.# ..##.#....### ..##.#....### ##.###......# ##..#....#.## ##.##.####..# .##.#..#.##.. .##.#..#.##.. ..#######...# .####..####.# ..########... #.###..###.#. #...#..#...#. #####..#####. .###.##.###.. #######...... ....#...####. ####.#.#....# .#.#..##.##.# ####.###....# #.###.#.#..#. ...#.####..## .##.###...... .#..###.#..#. .#.#.##..##.. ..#..##...... #.......#..#. ##...##..##.. .###......... .##.......... ##..####. .###.##.# #..#....# #..#....# .###.##.# ##..#..#. ###...... #..#.##.# ...#.##.# ######..... #..###..### ####..##..# #####..#..# #..#....##. .##...#.... ####..##..# ######..... .##..#..##. ..###.#.####.#.## ##.##..#....#..## ..#..###....###.. .....##......##.. ....#.#..##..###. ##.#...#.##.#...# ..##...#....#...# ..#....#.##.#.... ####..#.####.#..# .########..#### #...##...##...# #.##..##.##.##. ##..###.####.## #..####..##..## ##..##..####..# ..##..##....##. ...####......## #...##...##...# #.#....#.##.#.. .#.####.#..#.## ..##..##....##. .########..#### ##.#..#.####.#. #..#..#..##..#. ##..#.... ###...### .###.#..# ..###..## ..#...... ##.#....# ##.#....# ####.#. #..#... ###.### ...##.. .#...## ##.#.#. ##.#.#. .#...## ...##.# ###.### #..#... ####.#. ##.##.. ###..## .....## .....## ###..## #####.###....## .######.#.##.#. ..####..######. ##....###.##.## ...##...#.##.#. .######...##... #......##....## .#.##.#........ ..#..#..#.##.#. ###..###.####.# #.####.##.##.## ..#..#......... ..####......... ###..###......# .##..##.#.##.#. ###..#####..### ...##...##..##. #...#.### .#.##..#. #....###. ....###.# #.######. #.######. ....###.# #....###. .#.##..#. #...#..## ...#...#. ...#...#. #...#..## .#.##..#. #....###. #.#.... #####.# .####.# .##..## ......# ###.#.# ##.#.## ...#..# ...#..# ##.#.## ###.#.# ...#..# .##..## .####.# #####.# #.#.... #.#.... ...##.# ###.#.# ...#.#. ..#.#.# ..#.#.# ...#.#. ###.#.# ...#..# ##.#.## ####.## ...#... ##..... ...#.#. ##.###. ####... .#.#.#...##.. .#.#.#...##.. .##..##.##..# #.###.###.#.. #########..#. ..##..#..##.# ...##...###.# ###.####.###. .#####.#.##.# .#####.#.##.# ###.####.###. ..###...###.# ..##..#..##.# .####...... .####..#..# #.####.#..# .####..#..# ..##..##..# .#..#...... #.##.#.#### .#..#..#..# .#..#.##### #.##.##.... .#..#.##..# .######.##....# #.####.#..#..#. .#....#...####. ##########....# ........##....# .#....#.#.#..#. #.......###..## .#.##.#.##.##.# #..##..##.####. ###..#####....# .######.##....# ##....###.#..#. ..........#..#. .##..###.## ####.##..## ######.##.# #..#...##.. .##..#....# #..#...##.. .##..###### ####.###### .##..###### ..#.### #.#.### ..#.### #.##### .##.#.. ##...## #.#..## #..##.. ...#### ......##... .#..#.##.#. ##..##..##. .#..#.##.#. #....####.. .####....## #....#..#.. #....####.. ######..### ##..#####.. #.##.####.# ##...#....#.. ...##......## ##.#.#....#.# .############ .############ ##.#.#....#.# ...##......## ##...#....#.. #....#####... ..###.####.## #............ #.#..##..##.. .#.#.######.# #.##......#.##### .#.#..####.#####. ##..##.##.##.#..# ..##.##..#.#.#.#. ..##.##..#.#.#.#. ##..##.##.##.#..# .#.#..###..#####. #.##......#.##### ..#......#..#.### ########.#...#.## ########...##.### ####......#.##..# #.##.#.###..####. #.##.#.###..####. ####......#.##..# ================================================ FILE: exm/aoc/2023/aoc_2023_13_questions.txt ================================================ --- Day 13: Point of Incidence --- With your help, the hot springs team locates an appropriate spring which launches you neatly and precisely up to the edge of Lava Island. There's just one problem: you don't see any lava. You do see a lot of ash and igneous rock; there are even what look like gray mountains scattered around. After a while, you make your way to a nearby cluster of mountains only to discover that the valley between them is completely full of large mirrors. Most of the mirrors seem to be aligned in a consistent way; perhaps you should head in that direction? As you move through the valley of mirrors, you find that several of them have fallen from the large metal frames keeping them in place. The mirrors are extremely flat and shiny, and many of the fallen mirrors have lodged into the ash at strange angles. Because the terrain is all one color, it's hard to tell where it's safe to walk or where you're about to run into a mirror. You note down the patterns of ash (.) and rocks (#) that you see as you walk (your puzzle input); perhaps by carefully analyzing these patterns, you can figure out where the mirrors are! For example: #.##..##. ..#.##.#. ##......# ##......# ..#.##.#. ..##..##. #.#.##.#. #...##..# #....#..# ..##..### #####.##. #####.##. ..##..### #....#..# To find the reflection in each pattern, you need to find a perfect reflection across either a horizontal line between two rows or across a vertical line between two columns. In the first pattern, the reflection is across a vertical line between two columns; arrows on each of the two columns point at the line between the columns: 123456789 >< #.##..##. ..#.##.#. ##......# ##......# ..#.##.#. ..##..##. #.#.##.#. >< 123456789 In this pattern, the line of reflection is the vertical line between columns 5 and 6. Because the vertical line is not perfectly in the middle of the pattern, part of the pattern (column 1) has nowhere to reflect onto and can be ignored; every other column has a reflected column within the pattern and must match exactly: column 2 matches column 9, column 3 matches 8, 4 matches 7, and 5 matches 6. The second pattern reflects across a horizontal line instead: 1 #...##..# 1 2 #....#..# 2 3 ..##..### 3 4v#####.##.v4 5^#####.##.^5 6 ..##..### 6 7 #....#..# 7 This pattern reflects across the horizontal line between rows 4 and 5. Row 1 would reflect with a hypothetical row 8, but since that's not in the pattern, row 1 doesn't need to match anything. The remaining rows match: row 2 matches row 7, row 3 matches row 6, and row 4 matches row 5. To summarize your pattern notes, add up the number of columns to the left of each vertical line of reflection; to that, also add 100 multiplied by the number of rows above each horizontal line of reflection. In the above example, the first pattern's vertical line has 5 columns to its left and the second pattern's horizontal line has 4 rows above it, a total of 405. Find the line of reflection in each of the patterns in your notes. What number do you get after summarizing all of your notes? --- Part Two --- You resume walking through the valley of mirrors and - SMACK! - run directly into one. Hopefully nobody was watching, because that must have been pretty embarrassing. Upon closer inspection, you discover that every mirror has exactly one smudge: exactly one . or # should be the opposite type. In each pattern, you'll need to locate and fix the smudge that causes a different reflection line to be valid. (The old reflection line won't necessarily continue being valid after the smudge is fixed.) Here's the above example again: #.##..##. ..#.##.#. ##......# ##......# ..#.##.#. ..##..##. #.#.##.#. #...##..# #....#..# ..##..### #####.##. #####.##. ..##..### #....#..# The first pattern's smudge is in the top-left corner. If the top-left # were instead ., it would have a different, horizontal line of reflection: 1 ..##..##. 1 2 ..#.##.#. 2 3v##......#v3 4^##......#^4 5 ..#.##.#. 5 6 ..##..##. 6 7 #.#.##.#. 7 With the smudge in the top-left corner repaired, a new horizontal line of reflection between rows 3 and 4 now exists. Row 7 has no corresponding reflected row and can be ignored, but every other row matches exactly: row 1 matches row 6, row 2 matches row 5, and row 3 matches row 4. In the second pattern, the smudge can be fixed by changing the fifth symbol on row 2 from . to #: 1v#...##..#v1 2^#...##..#^2 3 ..##..### 3 4 #####.##. 4 5 #####.##. 5 6 ..##..### 6 7 #....#..# 7 Now, the pattern has a different horizontal line of reflection between rows 1 and 2. Summarize your notes as before, but instead use the new different reflection lines. In this example, the first pattern's new horizontal line has 3 rows above it and the second pattern's new horizontal line has 1 row above it, summarizing to the value 400. In each pattern, fix the smudge and find the different line of reflection. What number do you get after summarizing the new reflection line in each pattern in your notes? ================================================ FILE: exm/aoc/2023/aoc_2023_14.adb ================================================ -- Solution to Advent of Code 2023, Day 14 ------------------------------------------- -- Parabolic Reflector Dish -- -- https://adventofcode.com/2023/day/14 -- Copy of questions in: aoc_2023_14_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_14 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 10; input_name : constant VString := +"aoc_2023_14"; n : constant := 100; -- type Map_Type is array (1 .. n, 1 .. n) of Character; map_data, map : Map_Type; procedure Read_Data is f : File_Type; begin Open (f, input_name & ".txt"); for i in 1 .. n loop for j in 1 .. n loop Get (f, map_data (i, j)); end loop; end loop; Close (f); end Read_Data; r : array (Part_Type) of Integer; function Count_Load return Integer is res : Integer := 0; begin for i in 1 .. n loop for j in 1 .. n loop if map (i, j) = 'O' then res := res + n - i + 1; end if; end loop; end loop; return res; end Count_Load; procedure Roll_North is iii : Integer; begin for i in 1 .. n loop for j in 1 .. n loop if map (i, j) = 'O' then -- Roll the rock! iii := 0; for ii in reverse 1 .. i - 1 loop if map (ii, j) = '.' then iii := ii; else exit; end if; end loop; if iii /= 0 then map (iii, j) := 'O'; map (i, j) := '.'; end if; end if; end loop; end loop; end Roll_North; procedure Roll_South is iii : Integer; begin for i in reverse 1 .. n loop for j in 1 .. n loop if map (i, j) = 'O' then -- Roll the rock! iii := 0; for ii in i + 1 .. n loop if map (ii, j) = '.' then iii := ii; else exit; end if; end loop; if iii /= 0 then map (iii, j) := 'O'; map (i, j) := '.'; end if; end if; end loop; end loop; end Roll_South; procedure Roll_East is jjj : Integer; begin for j in reverse 1 .. n loop for i in 1 .. n loop if map (i, j) = 'O' then -- Roll the rock! jjj := 0; for jj in j + 1 .. n loop if map (i, jj) = '.' then jjj := jj; else exit; end if; end loop; if jjj /= 0 then map (i, jjj) := 'O'; map (i, j) := '.'; end if; end if; end loop; end loop; end Roll_East; procedure Roll_West is jjj : Integer; begin for j in 1 .. n loop for i in 1 .. n loop if map (i, j) = 'O' then -- Roll the rock! jjj := 0; for jj in reverse 1 .. j - 1 loop if map (i, jj) = '.' then jjj := jj; else exit; end if; end loop; if jjj /= 0 then map (i, jjj) := 'O'; map (i, j) := '.'; end if; end if; end loop; end loop; end Roll_West; procedure Do_Part_1 is begin map := map_data; Roll_North; r (part_1) := Count_Load; end Do_Part_1; verbose : constant Boolean := False; procedure Do_Part_2 is -- Empirical constants: cycle_observation_rounds : constant := 120; load_max : constant := 120_000; -- `mem` is used for detecting cycles in load values. -- Note (possible trap in this puzzle): we are -- *not* interested in cycles in rock layout or -- in loads measured within a full rotation! -- mem : array (1 .. load_max) of Natural; step : Natural := 0; cycle : Positive; overall_cycle : Positive := 1; total : constant := 1_000_000_000; rest : Integer; procedure Check is l : Integer; begin step := step + 1; l := Count_Load; if mem (l) in 1 .. step - 1 then cycle := step - mem (l); overall_cycle := LCM (overall_cycle, cycle); if verbose then Put_Line (+" Step: " & step & " load: " & l & " deja vu at step: " & mem (l) & "; length " & cycle); end if; end if; mem (l) := step; end Check; begin map := map_data; for i in mem'Range loop mem (i) := 0; end loop; if verbose then Put_Line ("Check cycles"); end if; for count in 1 .. cycle_observation_rounds loop Roll_North; Roll_West; Roll_South; Roll_East; Check; end loop; if verbose then Put_Line (+"Overall cycle: " & overall_cycle); end if; rest := total - cycle_observation_rounds; rest := rest mod overall_cycle; -- Now we warp x * `overall_cycle` if verbose then Put_Line ("Remaining steps : " & rest'Image); end if; for count in 1 .. rest loop Roll_North; Roll_West; Roll_South; Roll_East; end loop; r (part_2) := Count_Load; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 113078 -- Part 2: validated by AoC: 94255 end if; end AoC_2023_14; ================================================ FILE: exm/aoc/2023/aoc_2023_14.txt ================================================ .OO..##.###..#O.O..O#.OOO.....#..O##O#.OO...O..##.O.O.......##O...O...O#O.O.#..O..O.#O..OO...#...... ....OO..#.#...O#.O..#O..#OO...OO..O......O#........O...#..OO..#.#.O#..OO...O####.O...O.O.#.O..O.O..O .O#.......O.OO#OO##O#O..O.O....#.OO..O...O.OO........O..#...O.O......##....O.....##.O.#.#.O..O...... ..##.#.....#..#.O#O...O..O...OOO.##O.O##...O#.OO.#....OOO.OO.#O.O.O#...OO.OO.....O#..#...O...OO#...O OO..#..OO#..#..O..#O..O.O##O#OOO.#...OO.#....#..#....O.####O.##..O......#O..OOO#O.#...#.O...OO...OO# #.O.#O.#.#..O.#.............#.#.OO......#.O.O##O###........#.....#.....#.....O.O.OO.O....O.......O.# O#...#...........#..OO...O..#.....#...O.#.......O#.....##O#.OO##.......#..O......#..O..O.#O.#.#..O.# OO...O##..O.#.......O#.........OO#..O..#O..#OO.O........#.O.O.O....OO#...#.#.#O...##O.#OO.#.....#..O #OO...O...O...O....O...............O.#O..OO##O##O.....#.##...OO.O.#.##.##.O..#..#.O..#.#..O......... .O..O.#...##..#.#OO....#.O#...OO#.......O..OO.#...OO##..O..O...O.O...O.#.O#.....O..OO.O.#.OO..#.##.. ...OO.O.O.O#....#...O...#....OO.#O.#O..O.OO..OOO.O....#O.#...#.O#.O............#......O.O....#OO##.# ...#O......#O#..O....#.##..O.O.O#..#O.#O...O...#..#O..##.O#..O#....O##.O.#OOO.#........O##.OO.O..OO# #OOO....#O...O.O....O.......O...O..#....##.#..#.O#O#.O#....#.#.#O#....#.#.....##.#O..OOO....#.O..... #OO.O...#O.O....O..#..O.#....#....O#..O...##..#..OO#.....#O.O#O..O....#OO....##OO....#...OOOO.OO###. O..#..O#.O.#..OO.#.OO...O..O......#........#O......O.OO.#....#..O#O.......OO##O..##OOOO.#.#OOO.....O ...#OO.#OO.O.##.O#.OO#...#..#.O##O#...#.#O...#.....#..O..O....O.OO.O.#..O.#.O...#.O#..O....O.#...O#. #....O.....O.O...#..O....#..O..O.OO...#....O..O...#.....#...#....O.#.OO...OO#...O....#O.O..O.OO.O..O ..O#.....#O#....#.....OOO.#.......OO.O..#.#....#O......O.#.O.#..O...#.O...O..O.##O.O#O..#.O......#.# ....#O#.#..O#.OO.#.#.O.#......#OO...O#OO.........OOO..##...#..##O#..OOO...O..O..O##O...#..#.O.O..#.. ..O#.O.......OOO..##..#...#....#.#..#O.OO..O..##..OO#.O...O..#OO...##O.#O..OO.....#O..#.....#O.....# ...OO.O.#.O.O..##O#...OO...##.O..OOO##.O.O.#..#.OO..O...O.#....O.O.....O##.#O.O.O#.#.......OO#...... O...#.O...O...#..OO...O..#..#........O...#...#......O#.#.....O.#.........#.#......O#O.O.........#... .......O#...#...........O.#O#.O#.#.O.O..O..OO.#......##.OO..#......OO#....#O#OO.O.#..O#..O.OO..O..## .O.....O.#.........O...O...O...O...OOOO..O....OO....#.#....O#.#..#.OO.OO....#.......#...#OO.....O.OO O....OO....O..O.OO.###..O##.OO.#......O.O...##...#O...O..O...##.O.O...O....O.#OO.....O.....O.O.OO.OO #O......OO....##..O..###.O....#.#.#.OO.............O.O.OOOO#.O.O..#O...O#..O......O.O.O.#.#.......O. O#O.....#...#..O#.#....#..###..O..O...#....O....##.....#...O#.#.O.O......O..OOOOO....OO..#...#.OO#.. ..O........OO....##...#O.....#.O.....O#.O..#.O.#.O......O#...OOO....O...#..OO....O..#...O.O..##..... O...O..O.O....O.OO.O.OO..OO...#O...O.#.O..#O...#...#...O..##...#...OO#.....##..O#O.O....#.....OO#..O ...O#O..O..##.OO.......#.#O...O..#.#...#.O.#O##OOO.OOO...#.....O....##.....OOO.....O..O.O#.O....O... O#..#O.O....#.........O#.OO#...OO......#......O.#...............O##OO.....O.....O.O..##..O#....#.OO. #O..O.OO....##O......O.O...O#O..#.O..........O....#........O#.#..O..O............#..#...OO#.###..#.# ...#...#.#O....O.O.....OO.O.O...O.#.#.O...OO..O#....O#O......O.O..##.#.O.....#..O.O.#.#O...O.#...... .O...O#.O.......O.#....O.#...#.#..#O.....#..#..#.#O#..#.......O..#.#..O.OO.#OO.OOO..O....#.....OO#.O O#.#..#.O..O..#O.......O.#..#....#.O..#...#......O...O##....O..#...O....#O..#.....OO.O.O#..O.#..#O.. #.#.....O...#O.#..O...#O..##..#O..#O...O.#OO...#....OO#..O.#O#O........OOO...O##..#..OO.O.O.O.O..... ..OO...#..OOO.O#..#...O..O.......O.#.#.O#.##OO....#..O....#..#.O.#O...O.O#O........O#OOOO#.#..O#.#.. .O....#.O#OOO.....O.#O............O...O#...O...O..O.#..O.O.....O#.O....O......O...O.O..OOO..O.##.O.. #...#........#..........###.O....OO.#.....#OOOO.OO#.OO...##...OO...O#.......O...#.#..#O..#.....#O#O. O.O.#...O.#.....OO...O.O#......#........#..O...O..O.#..OO#.....#...O.##O#....O#..O#...##.O.O.#.#.... ............OO.....O........##O.O...#..#.O.#...OO..#.O.#O.............O..#O.....#...O.#....O..O#..#. .#..#.O.#......O..O##O.O.#..O..#O.O..O.O........O.......#.#.#O.#..O...O...O....O.O#...#..OO..O....OO #..#..O....OO#.#.O.#......O...O.O#O...O#...O...#...#O.#....#..#O...O...........#.#.#..O##..#........ ..O......O.#.OO.#O...O..#O...OO.#.....##...#.#....O....OO.#O.O.#....OO..#....#.#...#.O.....OO#..O... #..........#...O.O....##....OO..O..O..#...#..###....##..O#..#.........#.....O#...#.#.......#.##.##O. ###.O.#..#.O.O.O..O..O...O...#O...O##.#..#O..O...#....O.....#..##......OO.#O...O#..O.O.O......#...OO ....O#........O.O#.O#O#...O.......#..O.#..#........O.....O#..O..O.OOO....OO.....#....O#.#..O.....##. #.#O...#.O#O..#.#OOOO#.......#....O...O#.##.O....#..O.......O.##.#.OO...O...#O..O..#O.#......O.O.##. .#O...OO#......O...#..##............O...##...O.#O....#..OO......O.O##OO..OO....##O.##..O............ O.O..OO.O.#.#....#..O.O.O.OOO...OO..#....O....O.#.#....#.O#.#.....O#O...O.OO..O.#O.#..OO#.O#........ #..#.O.##.##...#OO..O...OOOO#O##..#...#.##....#O.#O#.O.O#.#.O#...#.OO.......O........O..#.#.OOO#.... ##....O...O#....O...O.#OO.O..O.....O#O#.#...OO.........#.......O.#.#..O..#O...#..O.#...#.##...O..O.O .........O...O.O...#..O.O..OO.#...O.#.O........O.O.O....O...O..O..........O....O......O..#O.O..#O... .......#.#....O#OOO.O.O..O.##...O..###.......O#.##...O.O....#.OOO..O...#.#.......#O.OO...O...OO.O... .O...O...O....#.O.#...#..##O....#..O....O#..O.#.O..#...........#..O..##OO.......##..#.....O#...O#..# ...O....O....#....O..####.#O#.....#O.O..#..#O.OO...#...O.##.#.#....#...O...O..#.....OO.O....#..O..O. .OO#.#...#....O.#O#.##....OO............O.....#.OO#O.#O.#..#...#.O....O.O..#..##.......O..O.#..##O.O O...#.........#.O....O..O.....#.......#.OO...OO.#O#.#...OOO.O.O#.O.#...#O......#....O.......#.O.#.O. .....O.............O.#..#.#..#.#...#..OOO....#.OO.O...O..#.##O.#O...O.O.OO......#....OO..O.......... O....#....#.#....#.........#...O.O#....OO.#..#O..#....OO...#....O...O#...O.......OOO...#......#...#O ..O..##O.#O.OOO..#..O.#....#.OOOO..O.O.....##O.....O.#.O.###..##....O..OOOO..#.#OO.O.OO.#O#..#...#.O O#...O......#..#.....#..##.#OO#O#.....O...##....OO...O##...O....O.#...#O..#.O#..#O.O..#...#...OOO..O O...##.O..O..O#....#..O........O....O#...O..O......O...OO...OO.#OO.O..#....O#O....O..#..#..OO.OO.... O..#.#O....O..O.O..O#...O.O...O..#.#.#..##.#O......#...OOO.#O...#..O.....O###O.....#.......O#.O.O... OOO#..#.#...O...O..O.O..O#O.....#O.#..O....O...O.#..O.#...O#.......#.....#O.#.#..O...##..#.....O...O O#...O#....O.#.#......O.....O.##.......#.O.......#.#.#...#..#O....##O......O..O.#.#..O..#..O.O#O.O.. O.O...O##.O#.....O......#...O.#...O.O..#........O..O..O#.O..OO#O.OO.........O...O..#.O......O...O#.O ..#......OO.#....O...O..O..##...#O#O#O..O..O......O..O.#O#..O......O..........OO..OOO#..#.OO....O... .......##......#.O..#....#.O#O..O#...O#....O.OOOO..#.O.O..O..O..O.........O...O#...O..#O..#.#..O...O .O#..OOOO.O......#O......OOO#.#.O.#O...##...O.O...##.O#.O.#.......#.......##...#O.O...#.#..O..##O..O ....OO......#.#.....O.#.OOO.O#.#...O.##.O..OO....#OO..O..O.O.O#..OO....O.O..#.O.##..O...OO..OO..OO#. ........#O.....#....O#.#OOO.O...........OO....#.#.....OO#..#OO..#..#.....O#O..OO..OO..O......#..O.O. O#O....#.#......O#...#.##O..OO.O.....#O..#..O..O......O##..#OO...OOOO.....O#....O..O.....OOO...#O..O ...O..#..O......OO.#.....#.O...O.O.#.O..OO..#....#...#....O.#O.O...O.O......O......O..#...#O###.OO.. #O###.....#....#.#O..#...#O..OO....#.O...#.##OO.#.#.#.....#....O.###...#....#.#...O.......O...O..#.O ..#..O.O..#.........O#..OOOO###..O##.#........O...#.#O#..#...O...O#....O..#.#...O.O..OO.....O....... #...O..#.......O........O....#.O......#...##.##......O.....O.##.O..O.....##...#OOO..O...O##.O.O..... ......#.OO....###.......#.###..OO#.OOO#O#.OOO#..O....OO........#...O...O#.OO.#....O#.......#..#..#.. #..#OOO....#.#.O.O..........#O....O#...O..O..#...O....O#..##.O..O.#O...#.#.#..O..O.O.#O..O..O...#.#. .#...O.O##.....#..O.....OOO.#.....#OOO#.#..O.....O.#.O.O.#.#.O.O#.........O....#...#O.O##.##..O.O#.O OOO...#O.OO....#.OOO..O....O.OO.O.#.O.#.#...#....OO........O..#..OO....#O....#.#O##.OO#O#.##OO.O.O.# ...O#..OO.....O#...#O........O....O#O....OO...#....O###..##.O..#..#.#..O..#O.OO..O........##O#.#..OO .O...#..#....O.##...#.........##.#..O.O.....#.##..O.#O.#..O#...#....#.#.........##.O...O...OO#..O..# O....##.O...O........O#..#...OO#O..OO..#.........##......O.......OO..O...O.O..#..........#.O..#...O. ###.#.........#OO....##...O#...O....O........#...#.O.#O.#.....##..O..#O.##......#.#.O.......O...O... ..#.OOOO..O......O#O.O.#.O.#..#.O...O..O.O..##O.O.......#...O#..#..O.#.#.O#.##...O......#.#...#..... O.#.OOO.#......O....O..O...O#........#....#.......#O..O.OO..#.O#.OO..#.OOO..#O.....#OOOO..#......... ##.O...####OO#...O#.OO...O...O.......O...OO..####...OOOO..O##O....OOO....#..O.O........O....#.#.#O.. O.O....O...O#...O.#....O.....OO#O#OO..O##.O..O...O.#.....#O...O..#O...O#.....O##...O.OO...#......... ....#OO..OO..#O#......O#.O..#O..#..OO..#....#.....#.....O.O..O#....O.O..O.#..O#O###O....O...OO...#.# #..OO.##O..OO.O..O...#....O.....##O..#............##.O.#...O.#O..#O..#...#...O.O....#O.....O.....O.. ..O#..#...##.#.#.O#.OOO.O#.#....OO.#....#...#...#.....#O.....O..O...O.....#.O.O.O#...#O.#...##.O..O# #....#.O...O#...##O.#....O........O...O#.#.#...#O#..O..O.#O.....O..O....#....O.O#O#....#O#..#......# .O.O#.........O.....##.O.#..............O...#.#OOO.O.OO..O..O..O##....#.......OO....O....#OO#..OO... ##.O#...OO...O.O...........O..O.##O..#.#...#..O..#.##....#..###O..##........OOO.#.O.#......#......#. #......O#..O#.#.#..#O##..OO#O...##O.#...#.OO...#.O..O##O.O...........O.##...###O..#.#.O.O..OO.O..O.. #.....#.##.O.O.#....O..#O......O.O#...#..O.#O#OO...#.OO...O.O##.O...O.......#...##....#O.....O.##O#. ...O.OO.O...O#..OO.O....#.#.O....O...#..#O.O..OO.#....O.O#.O#..O..O...O..O........#..#..#..#..OO.O#. .#O.O....#....#.OO.#.O...O......O....O#.....##...#O...##...#.#OO..O#O..O##.#.#..O...O.....#..O##.O.. OOO....OOOO...#.#...#.....###...O......O.#.O.....O...#.O##...##O.#.#...O....O.O...#.O...#O....O..... ================================================ FILE: exm/aoc/2023/aoc_2023_14_questions.txt ================================================ --- Day 14: Parabolic Reflector Dish --- You reach the place where all of the mirrors were pointing: a massive parabolic reflector dish attached to the side of another large mountain. The dish is made up of many small mirrors, but while the mirrors themselves are roughly in the shape of a parabolic reflector dish, each individual mirror seems to be pointing in slightly the wrong direction. If the dish is meant to focus light, all it's doing right now is sending it in a vague direction. This system must be what provides the energy for the lava! If you focus the reflector dish, maybe you can go where it's pointing and use the light to fix the lava production. Upon closer inspection, the individual mirrors each appear to be connected via an elaborate system of ropes and pulleys to a large metal platform below the dish. The platform is covered in large rocks of various shapes. Depending on their position, the weight of the rocks deforms the platform, and the shape of the platform controls which ropes move and ultimately the focus of the dish. In short: if you move the rocks, you can focus the dish. The platform even has a control panel on the side that lets you tilt it in one of four directions! The rounded rocks (O) will roll when the platform is tilted, while the cube-shaped rocks (#) will stay in place. You note the positions of all of the empty spaces (.) and rocks (your puzzle input). For example: O....#.... O.OO#....# .....##... OO.#O....O .O.....O#. O.#..O.#.# ..O..#O..O .......O.. #....###.. #OO..#.... Start by tilting the lever so all of the rocks will slide north as far as they will go: OOOO.#.O.. OO..#....# OO..O##..O O..#.OO... ........#. ..#....#.# ..O..#.O.O ..O....... #....###.. #....#.... You notice that the support beams along the north side of the platform are damaged; to ensure the platform doesn't collapse, you should calculate the total load on the north support beams. The amount of load caused by a single rounded rock (O) is equal to the number of rows from the rock to the south edge of the platform, including the row the rock is on. (Cube-shaped rocks (#) don't contribute to load.) So, the amount of load caused by each rock in each row is as follows: OOOO.#.O.. 10 OO..#....# 9 OO..O##..O 8 O..#.OO... 7 ........#. 6 ..#....#.# 5 ..O..#.O.O 4 ..O....... 3 #....###.. 2 #....#.... 1 The total load is the sum of the load caused by all of the rounded rocks. In this example, the total load is 136. Tilt the platform so that the rounded rocks all roll north. Afterward, what is the total load on the north support beams? --- Part Two --- The parabolic reflector dish deforms, but not in a way that focuses the beam. To do that, you'll need to move the rocks to the edges of the platform. Fortunately, a button on the side of the control panel labeled "spin cycle" attempts to do just that! Each cycle tilts the platform four times so that the rounded rocks roll north, then west, then south, then east. After each tilt, the rounded rocks roll as far as they can before the platform tilts in the next direction. After one cycle, the platform will have finished rolling the rounded rocks in those four directions in that order. Here's what happens in the example above after each of the first few cycles: After 1 cycle: .....#.... ....#...O# ...OO##... .OO#...... .....OOO#. .O#...O#.# ....O#.... ......OOOO #...O###.. #..OO#.... After 2 cycles: .....#.... ....#...O# .....##... ..O#...... .....OOO#. .O#...O#.# ....O#...O .......OOO #..OO###.. #.OOO#...O After 3 cycles: .....#.... ....#...O# .....##... ..O#...... .....OOO#. .O#...O#.# ....O#...O .......OOO #...O###.O #.OOO#...O This process should work if you leave it running long enough, but you're still worried about the north support beams. To make sure they'll survive for a while, you need to calculate the total load on the north support beams after 1000000000 cycles. In the above example, after 1000000000 cycles, the total load on the north support beams is 64. Run the spin cycle for 1000000000 cycles. Afterward, what is the total load on the north support beams? ================================================ FILE: exm/aoc/2023/aoc_2023_15.adb ================================================ -- Solution to Advent of Code 2023, Day 15 ------------------------------------------- -- Lens Library -- -- https://adventofcode.com/2023/day/15 -- Copy of questions in: aoc_2023_15_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_15 is use AoC_Toolbox, HAT; function HASH (s : VString) return Natural is h : Natural := 0; begin for i in 1 .. Length (s) loop h := ((h + Ord (Element (s, i))) * 17) rem 256; end loop; return h; end HASH; r : array (Part_Type) of Integer; data : VString; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2023_15"; -- procedure Read_Data is f : File_Type; begin Open (f, input_name & ".txt"); Get_Line (f, data); Close (f); end Read_Data; procedure Do_Part_1 is c : Character; s : VString; begin r (part_1) := 0; for i in 1 .. Length (data) loop c := Element (data, i); if c = ',' then r (part_1) := r (part_1) + HASH (s); s := Null_VString; else s := s & c; end if; end loop; r (part_1) := r (part_1) + HASH (s); end Do_Part_1; verbosity : constant Natural := 0; -- 0, 1, 2 procedure Do_Part_2 is -- On our data, there are 4000 rules, 530 distinct labels and -- 239 used boxes, so there is an average of ~2.22 labels per box. -- Consequently, we choose a rigid array structure for storing -- lenses. We would use a linked list if there were much longer -- sequences per box. type Lens_Type is record label : VString; focal_length : Positive; end record; type Slot_Array_Type is array (1 .. 5) of Lens_Type; type Box_Type is record slot : Slot_Array_Type; slots : Natural; used : Boolean; -- For statistics in verbose mode: has had slots > 0 at least once. end record; box : array (0 .. 255) of Box_Type; -- Just for statistics in verbose mode: rules : Natural := 0; used_boxes : Natural; used_slots : Natural; rule : VString; procedure Process is c : Character; lens : Lens_Type; i : Positive := 1; b : Natural; found : Boolean; begin rules := rules + 1; lens.label := Null_VString; loop c := Element (rule, i); exit when c not in 'a' .. 'z'; lens.label := lens.label & c; i := i + 1; end loop; b := HASH (lens.label); if c = '-' then found := False; for s in 1 .. box (b).slots loop if box (b).slot (s).label = lens.label then found := True; for t in s .. box (b).slots - 1 loop box (b).slot (t) := box (b).slot (t + 1); end loop; box (b).slots := box (b).slots - 1; -- Lens with label was removed, we can safely leave the loop. exit; end if; end loop; if verbosity > 1 then if found then Put_Line ("Removed"); else Put_Line ("Nothing to remove"); end if; end if; else -- "=n" case. lens.focal_length := Integer_Value (Slice (rule, i + 1, Length (rule))); found := False; for s in 1 .. box (b).slots loop if box (b).slot (s).label = lens.label then found := True; box (b).slot (s).focal_length := lens.focal_length; end if; end loop; if found then if verbosity > 1 then Put_Line ("Replaced"); end if; else if verbosity > 1 then Put_Line ("Added"); end if; -- Append new lens. box (b).slots := box (b).slots + 1; box (b).slot (box (b).slots) := lens; box (b).used := True; end if; end if; end Process; c : Character; begin for b in box'Range loop box (b).slots := 0; box (b).used := False; end loop; for i in 1 .. Length (data) loop c := Element (data, i); if c = ',' then Process; rule := Null_VString; else rule := rule & c; end if; end loop; Process; if verbosity > 0 then used_boxes := 0; used_slots := 0; for b in box'Range loop if box (b).used then used_boxes := used_boxes + 1; used_slots := used_slots + box (b).slots; end if; end loop; Put_Line (+"Rules: " & rules); Put_Line (+"Boxes used: " & used_boxes); Put_Line (+"Slots used (distinct keys) on final state: " & used_slots); end if; r (part_2) := 0; for b in box'Range loop for s in 1 .. box (b).slots loop r (part_2) := r (part_2) + -- "focusing power": (1 + b) * s * box (b).slot (s).focal_length; end loop; end loop; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 513172 -- Part 2: validated by AoC: 237806 end if; end AoC_2023_15; ================================================ FILE: exm/aoc/2023/aoc_2023_15.txt ================================================ kzb=5,zzvx-,bdld=7,qprd-,zf=1,cb-,jplf=7,kcgf=6,fpllc=6,jmvh=2,xdz-,zxxf-,qjzd-,rk=8,xjqkf=6,rq-,plx=3,kr-,lrpgnl=8,clgs-,hf-,dlk-,kjndtt-,rp-,lk=5,cbgx=1,trfd=7,sc=5,zxxf=5,qbb=2,gpq=9,pvl-,dxd=1,nlptg=2,xm-,vhb=6,drj=4,gslt=6,clx-,sclb-,pgc=2,gqp-,blq=3,dsssjs-,ffv=5,zvlc-,xpvr-,xz=5,trjxl-,nsnx=8,rlfkx-,vk-,bq=3,dff-,qcg-,qzz-,sclb-,zp-,tf-,thq=4,kptg-,qtqhll-,fr=7,hz=3,pz=4,bvvs=9,bv=9,cbq=4,sshzn-,bbp=5,bqx-,nvf-,pjh=5,jkds=4,nbvb-,zdt-,psn=7,cbntnn=3,vcqxm=2,ss=4,plh=3,bbp=2,rq-,kh=7,txcvg-,cc=4,ngv-,kt=7,xczxrm-,qk=3,pptx=1,khx=3,xzs=2,vcz-,kptg-,gvl=3,zd-,mc-,skq-,dq=3,pj=2,ssm-,znl=1,svvs=8,lp=5,rrq=1,mvxp=7,pll=1,kbvgv=3,cnp-,kd-,xk=9,ljzpb-,xff=8,czf-,npqjbg-,fx=8,bb-,xff=1,pptx=3,xbhx-,pl=2,zlt=8,kjndtt-,nbdt=5,kp=3,xltd=5,dxd=4,fv=3,nqdb=7,fj=8,jspg-,hdh-,ffv-,kp=8,vrjr=8,hlh-,pjx-,dxd=8,frg=4,xph-,gsfc=4,hlk=9,pl=9,jvtfs-,xtrn=7,rs=6,rxs-,bt=7,hs-,tgr=9,qcl-,kn-,pvx-,kzb-,qcg=6,blq=7,fdh-,ccd-,ljnrz-,sg=8,ft=7,ph-,nmsc=5,gn-,mn-,rvjg-,rlfkx-,xpcm-,lk-,mfs-,kqg=9,bxn=8,llrs=7,pll=4,xvz=6,blknq=2,kx=7,bnfgrx=7,qf=1,gx-,chlqr=9,ngv=3,cssn-,jzbx=2,rq=9,bgt=6,nzs-,cnp-,dq-,ntt=8,gvl=5,zp-,svvs=5,tf-,trfd=9,mr=1,pjx=6,tx=6,zgt-,js-,xbz-,kvr=9,cbgx-,pvl=2,qz=7,nsr-,vjzjnn-,qfx-,tvfx=1,hz=6,tx=5,gvxmb=9,jqt-,rfk=1,ssm=2,ss=9,tpdq-,bb-,hlk=8,qd-,dlk=4,kdgrc-,prb-,dcsn=5,mbpn-,hm=5,mpc=8,tn=7,xxmdx=8,hdh=3,nqdb-,dsssjs=7,brdh-,klz=9,jpx-,hv=9,frnx=2,hh=5,jmvh-,ps=2,mng=2,xz-,ljm-,znl-,cc=4,qjzd=1,ht-,zb-,cl=4,jkds-,hz=4,cc-,ld-,dzz-,tl-,dg-,qprd=5,nlttf=8,mnkkl-,tzp-,ksq-,xllc-,xjqkf-,dthkz-,rh=9,xd=6,jpx=5,dthkz-,xzs=2,xpz-,zdv=4,jggftj-,dghgvv=3,zlr=3,gtbfk=8,rd=6,sv-,qcg=1,pmqcz-,fsbtv-,rp=6,hmvnp=1,tkj=3,nsr=6,bvvs=2,jxqr=1,tvgf=2,gfx=7,ngv=7,xff=1,qmh=7,xxmgh-,xb=9,rq-,sc=9,kl=4,tl=8,szb=1,lzmk-,kkt-,tc=1,nzk=4,xkmfp=9,zhjlhc=8,cssn-,gp=2,xm=7,lrpgnl-,xkp=4,ftf-,dghgvv-,tc-,xgsl-,plx-,rrq-,qcl=4,tcx=3,xxmdx=6,gkj-,rcv-,zxxf-,gz-,qz-,fblp=2,mj=8,rf-,nf=4,ss-,zm-,kn-,jpk=2,vxzj-,czz=5,jmk-,rp-,fb-,pvx=2,zgg-,dt-,jmvh-,rd=2,jkds=1,dzz=3,xjsxmj=9,rsjt-,dthkz-,rs-,kqg=1,qzz=2,cbntnn=8,nlttf=8,nj=2,jgjl=1,fv=1,nq-,sg-,tzp=6,rfk=1,fpllc-,tx=1,mng-,rd=5,pz=9,js-,ljzpb=3,gd-,qkcjt=4,jdfq-,jxqr=3,rlm=1,gsq-,dghgvv=2,fpllc=4,rvjg=8,hlh=2,bj=6,rtc-,qcg=3,nb-,dm=8,xbhx-,sdv=5,vlq-,nnjs-,nbdt=2,kjp=4,lxcf=1,ffv=5,zgg-,rq=3,zm-,bzcq-,nff-,bgt=6,hb-,rp=9,bq=5,hst-,jvtfs-,clx=7,hf-,gjz-,lrpgnl=8,gncb=6,xxb-,jzgh-,rmkm=8,bnfgrx-,ksh=6,zbbb-,nhh-,vfvj-,xdp=2,jmk-,txcvg=2,fsbtv=4,nhp-,nzk=7,fsbtv=2,jb=5,jfr-,jpx-,xjxx=3,km=6,qzlpc-,ljm-,tc=6,llrs=8,bln=2,tl=8,rrq-,vfvj-,vjzjnn=8,pvl=9,jtf=3,fj=2,rd-,jrm-,jtf-,hq-,nnjs-,fr=6,nzs-,xp=7,jbt-,lk-,vxzj-,gjz=6,gsfc-,dthkz=1,thq=3,vhb=7,vzj=3,qf=5,mm-,kknx-,nj-,bzz=3,vd=2,tcx=3,fxz=7,ds-,mvl=7,rvq-,czf=6,lmj-,xkp-,ksh=4,gkj-,hv-,vcqxm=1,tnbz-,jspg=3,xxmdx=6,sf-,gqtb-,rsjt=1,rth-,zvlc-,fxz=5,cgplp=6,zhjlhc=4,hmp-,dghgvv-,zm=2,jzgh=9,ntt-,nlttf=7,zf-,ztbmk=2,kqb=5,vrtgm=7,ksh=3,bv-,rvm-,nlttf=5,kcgf-,ts-,sclb-,fdh=7,gfbcgk-,fpllc-,jplf-,hz-,zbbb-,brdh-,zb=7,pj=6,hm-,mnkkl=4,hlk-,kjndtt-,pdz=2,qk=1,pmqcz=9,xpcm=7,rd-,cxbjsc-,xff-,rvq-,qs=7,nbvb=1,lp=2,cmn=1,dsssjs-,ght=2,npj-,nbn=5,rp-,jpx-,cn-,mnkkl=9,bjsq-,kn=2,gslt=7,tvfx=5,mhd-,dm=1,rckh-,rnx=4,lr-,gvjd=6,xbz-,kl=4,jn-,gfx=1,rh=9,hp=7,zf=1,gvl=8,gmnmd-,zgt=6,xm-,rvq-,gpq-,gq-,qf=8,qjzd=5,zrf=5,qs=1,fqg=8,gd-,tvgf-,nff=5,zf=4,xgsl=4,xkp-,jdfq=2,ftcs=8,gvjd=1,xgzfv=8,rnx=9,skq=5,bch=5,kcgf=9,qk=7,sk-,clg-,xh=5,hh-,bfv=8,kkn=7,ftf=8,sc=3,qzlpc-,nbn=9,sl-,lcs-,zcj-,ph-,zdt-,xph-,zxxf-,jzgh=5,tvgf=5,xnrqz=7,nj=5,tzp=1,mpx=4,pz-,sshzn-,fqg=1,xdvm=7,skq-,qcg-,rsjt=5,hqdgdx-,fz=9,mrx=7,lr-,rnx=9,hc-,skq-,gkj=5,jb-,bvvs=2,tx-,qh=4,ll=6,ssd-,dq=2,hh-,pjx-,kqg-,ftcs-,bsp-,nqdb-,zgg-,mpc=8,pmqcz-,kjp=8,gslt=8,rckh=6,fqg-,zp=2,zlt-,ljm=8,gz-,tvfx-,txcvg=1,rvjg-,xm=6,htsz-,ccd=7,ck-,hc=7,pvx=1,rp-,ftf-,kkt=5,qmh=2,vn=8,trc=1,vcqxm=9,hb-,hq-,gvjd-,kvr-,fdh=2,qprd=6,nq-,ffv=2,ld=2,thf=9,xzs=2,ssm=4,trjxl=2,qcg=6,hst-,hjn=7,cc-,xkmfp=7,pn=8,vn-,nlttf-,mhd-,tkj-,mnkkl=9,zlt=2,mr=1,xxb-,dsssjs=5,clg=8,jspg=8,qknkv=9,nzs=2,mpc-,jtf-,jq=9,kv-,nhh=7,bsp=5,xk-,gmnmd=9,mc=1,mnkkl-,gn-,jt=7,qjzd=7,cc-,xl=2,bjsq=2,qr=2,svvs-,zvdgs=6,pvl=3,pvcq-,sbplc-,nbdt-,hh-,rsjt-,dcg-,dxh-,dlk=5,tn=3,tgr-,clg=2,kkt-,hv=7,nxr-,jvtfs-,hddp=5,hs-,lr=6,lmj-,mrx=2,fj=2,rr=6,ksh=9,sg=3,xpz-,hmp-,tgr-,zl=9,rrq-,fv-,hdh-,czz-,plh-,jk=3,qzz=9,gjx-,xdvm=5,jmrx-,tzp-,qfg=8,clg-,blknq=6,plh=6,bmmhfl=5,gk-,rq=7,qgh=5,ph=7,qs-,ll-,ss=5,vjsv=2,kvr=7,xtrn=9,tkj-,brdh-,lnx-,hdh=8,frh=5,fblp=9,pptx=9,rtb=9,tpdq=6,jqt=5,ljnrz-,hh-,rsjt=8,nsr=9,dxh-,ck-,bldd-,jkqqkc=1,qtqhll=2,czf=7,ts-,bgt=6,hh-,qk-,ccd-,gvxmb=2,lnx=8,zdv=7,jggftj-,gvjd=3,hlk=8,vjzjnn-,nmsc-,jqt=1,gvjd-,hz-,vnnpcp-,svd=5,gqp-,xbl=8,rghth-,dm-,nmsc-,mbp=9,frg=1,xs-,frnx=1,sf-,xkqjv-,kkt-,sk-,vhb-,ljdr=1,zlr=2,jgs-,hh=4,zhjlhc=2,gd-,rr-,tx-,rtsm=3,lzmk-,gfx-,sv-,ttjs=3,pgc=5,vhb=5,xpz-,jcvt-,mmqxv=2,vjsv-,xzs=1,gsq-,mm=4,fx=7,jb-,xvz-,brdh=2,mbp-,rvq-,brdh-,gd-,gg-,bjq=1,pks-,tc-,cmn-,qfq-,btxb=5,nqdb=4,kkn-,zrf-,zgg=7,rr-,gjx-,bqpn-,rvjg-,bzc-,ksh=6,jrm-,qkcjt=7,xgzfv-,zvlc-,fblp-,qs=6,lp=3,pptx=2,cbgx=1,gjz=7,xgzfv=3,cl=3,bvvs-,vbl-,zs=7,tj-,hs-,vlq=2,kjp=1,qz-,tkj-,jmvh-,xxmgh=7,xh=3,hf-,kzb=2,hp=3,nsg=4,tx-,kqg-,dg=4,rd-,gsq=4,bjsq-,rsjt-,nsnx=4,sshzn=7,lrpgnl=4,vk=8,qjzd=7,kx=2,zxxf=7,hddp=4,kkn-,xkmfp-,hs-,brdh-,jt-,qs=9,xpvr=5,sckkk=2,hmp=1,mmqxv-,ljm=6,tl-,sk-,hc=3,jxqr=4,dq=5,kl-,xbl-,npj=2,fzg-,jk=1,zdv-,xxmdx=6,jt-,zhjlhc-,trc=1,qhdn-,kzb=9,rghth=3,mhnjv=3,rs-,pll-,blq=2,dff-,pvcq=5,ft-,tvfx=6,kqqcsn-,bxn-,ssm=9,sr=8,sg-,dg=4,rfk=7,nnp-,xm-,ts=7,xgzfv=1,sz-,mvxp-,rx-,trfd-,ljzpb=6,jggftj=7,tsj=5,ltsl=3,rqnbh-,zzvx=2,rxs=6,bt-,xgsl=2,tgr-,vmz=2,ltsl=6,rf-,zbbb-,pn=4,jpk=4,bt=4,xjqkf=1,pks=5,xr-,mbpn=6,jkqqkc=2,fdh-,zh=3,ts=8,zgt-,qsc-,dxd=3,cfczf=7,bq-,xxb-,rs-,cssn-,lmj=8,bvvs-,hh-,jzbx=3,pfk-,nsg-,rtb-,rr=6,fv=7,jxqr=2,qsg=6,pz-,pfk-,btp-,dxd=8,nzs=2,splpbg-,qfq-,plh=2,pgc=7,xxmgh=2,njj-,bxn=4,nff=4,bb=3,vn=7,bzc=5,jxqr=2,llrs=3,zm=7,lxcf-,xb=5,kzs=8,xr-,bch=4,ght=7,rx=1,blq-,pmqcz-,kv-,nzs-,xh-,blknq=7,gzgqz=3,cl=7,xpz-,kqg-,zpb=4,zdv=3,trc-,vhb-,czf-,pl-,zv-,txcvg=5,jq-,ss=1,ccd=2,fblp-,rk=9,rq=7,qkcjt=1,tj=6,kt-,qfx=2,bgt=6,pps-,hh-,lls-,zzvx=4,brdh-,dlk-,rr=1,cfczf=1,gvxmb=8,trfd=2,qmpx=7,rfk-,tf-,hg=1,nnjs-,vzj-,qcg-,hmp-,nbn=5,rcv=1,hf-,ttjs-,nff=7,zd-,tv-,npj=3,ght-,pvl-,fdh=1,pps=5,xkqjv-,sz=4,xpvr=6,hqdgdx=1,qkcjt=7,vgb-,jplf=9,zxxf-,zd-,blq=3,xxb-,qk-,mr-,dxd=5,bsp=1,ffv-,mpc-,kv=7,tn=3,vplj=3,pjx=3,cpn=7,fv=5,ph=1,pgc-,vb-,nq-,cc=8,zvlc=5,fr-,gvxmb-,lbmz=9,blq-,gsq=1,nvf=8,jmvh=4,xzm-,xvz-,vrjr-,qtqhll=1,xqb=1,rsjt=3,rxs=4,gmnmd=3,jcvt-,zm=8,pvl=5,lrpgnl=1,gp=8,xtrn-,trfd-,fktrxp-,jn-,fj=7,kknx-,hf-,kdgrc=5,vxzj=6,dff-,gk-,tnbz-,gvl-,kx=5,sb=1,vrjr=2,bqx=2,bfv-,fqg=5,kvr-,dq-,gzgqz=5,pfk=7,rqnbh=8,xktvp=7,pqxlsr-,sc-,fr-,jq-,qf=2,splpbg=7,znl=9,nzk=2,jgs-,vb=9,trjxl-,qzz-,trfd-,zvdgs=1,tnbz-,pll-,xd=1,xvz=8,nmsc=8,ds=2,bqpn=6,ftcs-,kcgf=9,xqb=5,pptx-,lr=1,nq-,xm-,mvl-,qh=5,qsc=6,dzz-,xk=4,klz-,pps=5,tnbz-,zv-,mvxp-,lcs-,hlh-,km-,bq-,lmj=1,nzs-,tjg=2,vj=7,vj-,sclb-,tv=5,lbd-,khx-,jpk-,rk=1,tpdq=3,nvf-,rtc-,xd-,mhnjv=7,xph-,xdz=3,kvr-,dmz=1,xpz-,fpllc=8,cmn=5,sr=2,fktrxp-,gqp-,cnp-,dvrg=7,tvfx=6,ssd=3,rxs=6,bx-,gmnmd=6,hs=4,gjx=9,tzp=9,qbb-,plh=3,hdg=3,nbdt=2,jpx-,skq-,ztbmk=9,bjq=7,cn=9,fv=8,rr=5,gg=2,mt=5,hlk=6,mfs=8,rf=5,btp=2,zh-,dc-,sdv-,hf-,rx=6,kzs-,kl=4,mvl-,sz-,fxz=7,mnkkl=3,zdv-,ts=9,lp-,klz-,rqgb=9,llrs-,rq-,kqb=8,pr-,vcqxm=9,rrq=8,tv=9,dmz-,bdld-,ft=9,zdt=8,fpllc-,hlh=3,bch=7,vrjr-,zxxf=4,xs-,zdt=3,cssn=8,trc=4,ttjs=8,hz-,ztbmk=7,svvs=3,rf=9,gslf-,kdgrc-,gf=4,zgg-,xjxx=4,jcvt=4,lrpgnl-,zxxf=8,lqptdz=9,skq=2,ccd=7,vlq-,dmz-,xl-,fpllc-,rh=3,dcsn=4,xb-,gslt-,hmp-,qsc=4,qprd=3,cmn-,dc-,jfr-,sb=9,sb-,zpb-,vbl=5,xltd=8,hq-,sr=8,nsnx=8,rckh-,sz=8,nvf-,vd-,qzz=2,nbvb-,rnx=5,ksh=7,gkj=6,jzbx-,pl=4,gfbcgk=6,sshzn=5,tpdq=7,nkbtq-,ds-,bln-,ph=2,bgt=5,blknq-,sk=8,qhdn=9,tv-,jplf-,rk=3,pptx=3,cc=7,pvx=5,kr=3,gsfc=9,pfk=9,pfk=5,rvm=5,lcs=7,khx-,vcqxm=2,ph=7,frg-,nlttf-,xnrqz=3,rs-,qsc=9,sr-,qjzd=6,jmk-,qtqhll=4,frnx=8,plh=6,fj-,bb=8,fzg-,clx-,ph-,mr=9,tjg=1,zv-,kvr-,frnx-,xjqkf=1,pll-,mbpn=2,qd=8,svd=6,hm-,mt=1,zpb-,xkqjv-,rtb-,nkbtq=7,fqg=3,qprd=8,kqqcsn-,jspg-,dmdp-,qfx=3,rs-,xjxx=1,xzm-,vbl-,kzb=6,gg=9,tgr=7,zxxf=3,jkds=8,fqg-,mrx=9,dmdp=5,qp=5,kr=2,gtbfk=2,bgt=9,bch=7,nxr-,qk-,bgt=3,jk-,cl=7,pmqcz-,xktvp-,mhm-,gx=1,mvl=9,tsj=6,nq=5,zhjlhc-,jtf-,qk=4,zlt=2,zhjlhc=7,qz-,mhd=8,qzlpc=5,xzm-,vrtgm-,zgg=2,rtb=7,nhp-,dff-,bgt=6,cp-,xxmgh-,dk-,jpx=4,vcz-,ps=4,tvfx-,mmqxv=8,sg=7,jcvt=6,dk=5,dff=3,nhp=5,ssm=8,xbl=5,mvl=3,gvl-,qf=9,nqdb=6,gk=1,sf=6,bqx=6,fr-,svvs-,gqp-,hjn=7,sdv-,xgsl-,spm=6,qjzd=2,rd=4,xb=5,btxb-,fblp=5,jzgh=7,fv=3,mhm=7,xz=8,jggftj=9,ft-,zlt=9,kg=1,mh=1,xgsl=7,bsp-,vd=8,bbp=8,rrq=4,dt-,ksq-,vplj=1,lls=4,lp=7,tjg-,nbdt-,hddp=6,mvl-,ngv=1,gfbcgk-,xph-,kptg=9,tx-,nsnx=2,sr=2,tvgf-,rvq-,sclb=9,bfv=9,pr-,rtc=2,mmqxv-,dcsn-,rghth=7,fr=1,bsp-,nhp-,ltsl-,plh=2,xdvm=1,hq-,pps=7,sclb-,xvz=4,gqtb-,ght=4,vgb-,xh-,nnjs-,vplj-,kkn=3,psn=2,jt=3,xb=2,fdh-,splpbg=1,pvl-,mbp-,pj=4,qk=1,ffv-,qz-,tsj=3,dxh=5,zh-,xtrn=5,frh=1,ffv-,mfs=1,fr=7,ssd-,rnx=8,btxb-,vbl-,kzs-,mhd=9,qs-,dghgvv-,cbgx=5,cl=6,lls=3,zp-,ttjs-,ssm=2,sb-,zmd=7,tn-,npqjbg-,vxzj=9,vmz-,pps-,lls-,zlr=1,bln=4,kvr-,zh-,zb-,hp=2,cbntnn=3,hf=6,jspg=7,bzcq=4,jzbx-,kd-,vn=6,cbgx-,kd=5,skq-,xp-,rr=3,lls-,npj-,xr-,vhb-,sckkk-,gpq=2,kknx-,spm-,ht=3,dxd-,pqxlsr-,sc-,hddp-,pps-,vrtgm-,mng=4,cc-,gvl=2,tz-,drj-,hqdgdx=2,thf=5,hv=1,nlttf-,kt-,xgsl-,pps=6,ht-,rx=5,xd-,qm=4,nq-,ntt-,gsfc=2,fk-,mfs=4,nkbtq=3,cmn-,clx=7,btxb-,nlttf-,zlt-,fqg=9,zlt=6,rsjt-,xczxrm=4,sdv=8,dm-,plx=5,gsfc-,xm-,nmsc-,nnp-,vjzjnn=8,gkj-,hjn-,kp-,rc=7,vjsv-,jzbx-,dmdp-,cbgx-,vn=2,nxr=5,xph=2,kt-,khx-,rc-,qsg=2,pll-,gqp=1,xkmfp=3,rc-,jrvc=5,zzvx-,qcl-,st=5,vlq-,bmmhfl-,rnx-,rfk=5,vk=7,jrm=1,qh-,pps=8,ld=7,xph-,dff-,jt-,tkj-,nlptg-,tkj=6,xkmfp-,dv=8,gncb-,rvjg-,hs=9,hdg=7,lk=2,ftf-,cp-,rr-,zgg=4,htsz=4,xff-,gqp=3,rcv-,ll-,dxh=8,sv=6,psn=6,chlqr-,kl=2,gz=3,jdfq-,hqdgdx=6,sk=1,mvl-,qp=8,xqb=5,dg-,jgs=4,gg=3,bxn=1,cfczf-,nzs=2,xllc-,rfk-,zv=6,zgg=3,xdp=2,jspg-,tvgf-,rk=3,sshzn-,mmqxv=6,ljzpb-,rrq-,kqb-,tgr=6,nhp=1,tv-,xbhx-,xltd=9,sbplc-,xqb-,nsg-,pdz=8,lzmk-,rmbn-,qsg-,cssn=9,xbl=3,hs-,mgdmqf-,vplj=5,jb=9,zgt-,ksh-,nhp-,kqqcsn=1,vk-,jnth=3,kn-,jzgh=1,qcl=5,tj-,jrvc=8,bzz-,xjxx-,kqb-,gf=8,rlfkx=9,mng=8,gz-,kkt-,rxs-,qr=8,rqgb=8,bfv-,xkqjv=5,hz-,fv=6,kd-,cp=3,pdz=4,zzvx=4,gzgqz=4,ksh-,btxb-,kcgf=2,xdp-,xd=6,zgg=4,ftcs=3,vgb=8,nsr=3,vk-,ltsl-,nhp=3,gtbfk-,nqdb-,gmnmd=6,nsnx=2,frh-,mhm-,mm-,txcvg=7,blknq=7,qknkv=2,mbpn-,dcg=6,pqxlsr=5,qzlpc-,cxbjsc=6,rqgb=9,bjq=3,zpb=9,kzb=2,ck=1,ljdr-,nnp-,dg=8,qcl=7,xktvp=4,zlr-,mldh=3,bv-,clg-,kqg-,ds=6,xktvp-,tjjbp-,vbl=4,npqjbg=1,brdh=1,xm-,nzk-,zdt-,jtf=5,ljdr=4,frnx-,js=7,xxmdx-,bsp-,dm-,sc-,hp-,lr=4,rq=2,kzb=8,jxqr-,tv=2,vfvj=3,qknkv-,jbt-,rvq-,zvlc-,pdz=6,dk=1,pdz-,pvx-,pg-,hb-,ll=7,zxxf-,ttsz=8,szb-,ht-,qf=3,rmbn=7,ltsl=9,btxb-,qtqhll=6,zl-,gn=1,cgplp-,xnrqz=7,mm=6,xjxx=5,rmbn-,cbq=6,ftf-,nqdb=6,xk-,dmz-,mvxp-,rsjt-,dghgvv=6,gqtb=3,xxmdx-,vrjr-,hg-,mhd-,pvl=5,nnp-,qzlpc=4,xzm=3,mfs=7,kcgf-,kkt-,rvq=6,tkj=1,qkcjt-,zvlc=1,rnq=1,vjzjnn=8,sv=5,zpb-,xbhx-,jgs=9,drj=2,zv=8,ll-,jpx=2,pjx-,frnx=6,lk=1,xh=9,sz-,brdh=3,bsp=8,ljm-,tkj=3,npj-,tc=7,rs=3,rvm=1,zf=3,xxmdx-,xzm=4,gvjd-,rx=1,ntt-,dvrg-,gslt=4,bjq=6,nmsc=5,kn-,ntt-,qh=1,rth=5,vgb=8,fb=1,xl=2,jtf-,hjn-,vplj=3,gx=5,vcz=5,fktrxp=4,bln-,pptx=3,gqp=3,xbhx-,rmkm-,klz=1,nvf-,ts=4,thf=2,jkqqkc=5,mhm=8,hddp-,frnx-,bmmhfl=5,dm-,jqt-,nnjs-,lk=4,bx-,zxxf-,fr-,mrx=1,mgdmqf-,jk-,zd=5,cc-,dghgvv=1,qknkv=4,ksh-,bb-,qkcjt=8,xkqjv-,zmd=4,llrs-,kknx-,qknkv=2,kg-,zgg-,ftf-,pvl-,skq-,fsbtv-,nbvb-,clgs=1,hmp-,qs=1,dcsn-,mpc-,sl=2,sl-,mfs-,fxz=2,fdh=5,zjb-,jk-,vjsv=9,js-,rnx-,qkcjt=3,fzg=5,gtbfk=5,xm=2,cpn-,tx=1,cb-,zlr-,hq-,mpc=8,thq-,gq=8,hc=1,hst=4,jpk-,ztbmk=3,kp-,tl-,fktrxp-,dlk=8,bqpn=2,gsks=1,lmj-,tkj=1,jqt-,gzgqz-,ds-,blq-,frh=1,ght-,pl-,nj=1,rsjt-,dmdp=6,vlq-,hjn=6,skq=9,rvq-,bqpn-,zlr=1,nsr-,mrx-,qhdn=3,mvl=1,zmd-,jzgh=1,tnbz-,nj=7,svd=6,xbz-,vfvj-,dq=8,gz-,pvcq-,xtrn=5,svvs=4,pks-,klz=2,trjxl=9,rp-,rvjg=3,rvq=2,ftcs-,cbq-,dmz-,rnx-,hg=5,zmd=2,ljm=7,bv=2,qknkv=3,svvs=1,kdgrc=5,vjzjnn-,gn=4,gjz-,vplj-,jt-,dm-,qzlpc=3,rh=3,psn=3,qb=6,rqgb-,dvrg=3,mlb-,cl-,kjp-,rq=3,nnjs-,pg=7,jrvc=6,cnp-,kqb-,bj-,gfx-,zvlc-,dmdp-,blz=7,jfr=8,trfd-,ld=6,mfs=9,jggftj=7,mhnjv-,bq=6,vk=1,xgsl-,kptg=8,pj=1,ht=5,dsssjs-,qf-,thq=8,xkmfp-,lqptdz-,kqb-,fdh=4,fsbtv-,cxbjsc=1,qhdn-,nf-,js=4,gjz=3,rs=4,qsg-,kbvgv-,psn-,jmrx-,kr-,xbhx-,fpllc=7,svvs-,blq-,jzbx-,kqqcsn-,tv-,xph=3,cbntnn-,tvgf=1,lmj-,zdv-,cbq-,xk=9,hz=5,ht=2,dthkz-,dcg-,zxxf=7,xjsxmj=2,bln-,fktrxp=7,sv=1,txcvg-,kx=4,bqpn=6,nhh-,cgplp-,pgc-,zgt-,gqtb-,sbplc=1,nzs-,zbbb=5,jzgh-,gvl=6,hjn-,tv-,xkp=2,rr-,jfr-,rxs=9,mnkkl=1,tsj-,pfk=6,zgg=8,fx-,zvdgs-,vj=6,pn-,jggftj-,vjsv=1,mr=6,pfk-,jzgh-,trc-,nsg=3,tjg-,kbvgv=6,ssd=9,ljdr=8,htsz-,clx=1,xdvm=5,kzs=8,sr=2,xkqjv=4,mm=2,btp-,qb=4,xgsl=7,hdh=5,cxbjsc=7,kx-,pptx=2,pjh-,hlh=6,cc=9,jvtfs-,sclb-,kvr=5,kv-,jt=7,jplf=3,klz-,frg-,jmrx=1,vplj=2,pgc=3,zxxf-,ltdl-,pgc=6,qcg-,txcvg=9,sz=3,kvr-,mpx=3,rc=4,xqb-,nb=1,bqpn=3,xxb-,dcg=3,fb=2,kg-,gvl-,cbq=3,czf=1,rvm-,ffv=8,pps=5,ttjs=2,mn=6,jtf-,tjjbp=4,jtf-,szb=3,gk-,vxzj-,bv-,nq=9,rk=3,kzs=2,lnx-,ljm-,tnbz=7,bzcq-,bdld-,zpb-,xjsxmj=8,zcj-,nqdb=6,mxd=6,pvl-,hf=2,blz=2,cbgx=8,gq=5,ps-,pptx-,mh=9,xpvr=2,ttjs=7,fqg-,kqb=5,pl-,jrvc=8,hlh-,vhb-,xvz-,trfd-,zjb=6,gt-,jq=3,bgt=5,jkds=5,fz-,xqb-,fblp-,skq-,tcx=6,hb=7,rp=6,jpk=8,vk=5,gmnmd-,jt-,jbt-,zbbb=3,kqqcsn=1,vbl=9,bj=7,fj=3,gjx=8,vjzjnn-,zm-,vk=1,bjq=1,xgzfv=9,mfs-,hc=5,kg=7,xff-,hb=4,bzz-,jfr=3,sb-,qjzd-,khx=3,ttsz=4,qcg=4,sb-,xm=5,hv-,rvm-,rrq=7,tvfx-,dff=3,bbp-,zgt=5,ht-,nbvb=2,dmdp=4,sg=5,nlptg-,vcqxm-,dvrg=7,dff-,vjsv=4,ll-,bqx-,vcqxm=7,kkt=1,hf-,pks-,xdvm=2,ph-,nq=1,nf=2,pz-,nhp-,rvjg-,tzp=7,dt-,nfppt=4,xqb-,zzvx=8,vcqxm-,bx=7,xh=2,mhm=7,xp-,ljnrz=6,cn=1,blq-,qgh-,gvl-,sbplc=7,pps=5,bj=8,gf-,mc-,xgzfv=8,rk=3,lqptdz=2,bq=3,dv=8,zd=9,mnkkl-,jnth-,jplf=5,kv=4,gjz-,kknx-,dkpn=7,fqg-,zpb-,gzgqz=6,mh=3,tgr-,kr-,qr=4,mpx=9,jnth=7,qp=9,plh-,nqdb-,gsks=3,cb=4,xczxrm-,vjzjnn-,nbdt=5,svvs-,sshzn-,dcg-,lnx-,qmh=5,jx=2,mlb=5,rxs-,ght=9,xgsl-,mpx=5,kg-,czf=7,js-,gt=7,sr=9,rh=3,ll-,kv-,dthkz=8,ztbmk=5,dghgvv-,ttsz-,zgt-,dcsn-,cp-,mxd=5,jgjl=3,pj-,lnx-,jgjl-,vnnpcp-,czz=2,tj-,nf=2,htsz-,rvjg-,ds=5,xxmgh=9,cfczf=1,gvl=1,dsssjs-,fj-,jxqr-,kr=5,qd=8,znl=1,ngv-,mvxp=3,gk-,nqdb=3,kd-,cpn-,mxd-,drj-,blz-,xllc-,rcv=3,bx=7,cl-,kptg-,zvdgs=2,znl=9,kg-,hst-,zjb-,blz=3,dk-,tnbz=6,ds-,dff=2,pfk-,fx-,kr-,jzbx=7,ht=4,gx-,jn=4,hddp-,zhjlhc=1,xjqkf-,vbl=7,jspg=9,lbd-,mhm-,trjxl=2,pqxlsr=5,bfv=6,xb=8,ccd=9,rckh=5,xr-,kptg-,jcvt=9,jzgh-,skq-,mgdmqf=7,mlb=7,js=1,lnx-,hmvnp=4,dcsn-,kn-,jxqr-,nbn=6,vnnpcp=6,nsr-,lxcf-,jdfq=5,vrtgm-,sshzn-,vlq=1,mt-,gmnmd-,kzs-,gvjd-,blz-,zl=1,zm=1,qcl=9,kn-,zd=3,hf-,rqgb=8,tf=6,mbp=2,vj-,pz-,hv-,jx=6,xkqjv-,sc=6,xxmdx-,rlfkx-,ph-,cgplp=3,zjb-,xzm-,qmh=6,thq=8,fx=3,mm=5,nbn-,ld-,mlb=6,lbd-,xktvp=6,nsnx-,ds=5,nsnx=8,jspg-,nsr=7,kr-,bvvs-,zrf-,nzs-,xff-,nnp-,kbvgv=2,mbp-,vcz=7,rfk-,rghth=7,rxs-,js=7,tf=9,jggftj=3,kh-,fb=4,xczxrm-,nsnx=5,lnx-,mm-,kjp=9,nnp-,ksg-,qz-,dm=1,vhb=2,gzgqz-,fr-,vjzjnn=2,tkj=1,tcx-,hb=8,mhb=8,rnq=5,bb-,vfvj=4,xs=8,zs=3,pvx-,sshzn-,fqg-,nq-,bzh-,clg=4,fr-,bfv-,frnx=5,xpz-,rk=2,htsz-,km-,xkp-,ld-,hf=4,fz=8,dk=4,rfk=9,cbgx-,ck=7,kr-,mldh-,fzg-,qknkv-,ld=1,gqp-,fqg=8,qhdn-,rs=8,dzz-,xltd=3,mmqxv-,ftf=8,tvgf-,dmz-,zb=3,lmj-,rr-,pvcq=4,vplj=8,zl=7,frnx=9,bvvs=1,czz-,dthkz=8,htsz=5,fj-,mbp=7,vrjr=2,jfr-,bqx-,qbb=9,kdgrc-,bjsq-,gvjd=9,tz=3,ll=9,nnjs=3,kn-,ffv-,jfr-,nlptg-,tl-,rk=9,thf-,gncb=9,xdvm=8,qzz=9,zpb-,tpdq=3,hlh=1,xbhx-,xczxrm=6,lls=3,ksq-,fk-,ft=4,gncb-,nmsc-,vzj=7,nb=5,hg=6,tvgf=7,cn=6,mbp=6,nb=1,cgplp-,pqxlsr=6,prb=7,cbq-,rckh=3,rrq=8,rlm=9,mccv-,vhb-,ttsz=1,km-,hb-,thq=7,jgs-,nb=2,lr-,sclb=8,lk=7,ltdl=7,rsjt=2,rs=4,dzz=1,qtqhll-,bx-,jmk=3,dxh-,fsbtv-,ksg=1,rghth=5,gjx=9,bqx=7,xgsl-,nbdt=8,jvtfs-,sv=3,ksg=9,dcg=6,zjb=2,vrtgm=7,svvs=2,xk=4,gd=7,mc-,qhdn=4,kknx=1,tsj=3,xvz-,rth-,pqxlsr=2,jq-,qsc-,jkds=7,bsp=6,ph-,zvdgs=9,splpbg-,rfk=8,hddp-,zv-,ht-,vd-,cssn=6,bvvs-,kx=3,xpz=2,npj-,jfr-,rc=4,trc=5,gslf=2,kd-,dvrg-,rckh=2,kbvgv=4,jzgh=6,nd=5,zlt=8,sf-,zcj=1,bdld-,zlt-,vrjr-,dlk-,zgg=2,cl=7,bq=5,kcgf=8,zvdgs=5,ntt=3,dzz-,hc=9,pr=7,tx=9,khx-,pz-,xzm=4,sg-,mbp=3,nhh=8,sv-,qgh=4,nd=4,nlttf-,mfs=3,rnx-,thf-,zvlc-,xxmdx-,gvjd=3,qd-,kdgrc-,gslt-,fpllc-,qmpx-,cgplp=8,rvm=7,mpx-,bzh=8,jvtfs=7,zdv=2,vcqxm=2,mnkkl=8,hp=8,xllc=9,hst=7,gslf=7,jgjl-,jdfq=2,jvtfs=8,plx-,lk=5,jnth=9,bdld=1,hqdgdx-,rp=8,kx=8,pgc=5,gslf=4,qtqhll=1,mbp-,xktvp=4,jpk-,ssm=4,ljm-,hv=1,kqg=4,mgdmqf=1,mpc=4,lxcf=9,jmvh=3,rh=7,km-,zxxf-,hm-,jmrx-,nxr-,bzc=9,cxbjsc-,vgb-,bqx=3,tnbz=1,jrvc=3,qzlpc-,mn=6,sg=1,dk=3,szb-,lr=2,jvtfs-,kkt=8,ljnrz=4,nvf-,vb=4,ljm=4,cp=7,czf-,sshzn-,nmsc=5,kzb=5,bgt-,hqdgdx=9,htsz-,rp-,xkmfp=5,gpq=2,hq-,zpb-,vplj-,hb=3,klz=3,cb=5,xdvm=1,cc=7,vbl=2,dg=1,rk-,bzh=1,szb=6,xxmdx-,tnbz=2,pl-,rq=1,zxxf=7,tl=9,gvxmb-,qfg-,qmh-,bvvs=2,xxmdx-,cc=2,sg-,dg-,rckh=6,hdh=6,nb=1,nbn-,zlt-,rrq-,htsz-,nfppt=3,jrm-,rtsm-,lzmk=3,fr=9,lk-,tn-,dthkz-,gfx=4,rmbn-,gmnmd=3,hh-,mc-,vbl-,prb-,tf-,blz=2,rghth=4,rghth=9,hlh=9,txcvg-,mr-,gvxmb-,kvr=9,zh-,dcsn-,znl-,sg-,qzlpc=5,rtsm-,bj-,tpdq-,tz-,qd=9,rnq-,czf=5,skq=3,bnfgrx-,vlq=9,jpx=1,gzgqz=2,fdh=7,cn=6,xk=8,qzz-,zl=2,fr-,fktrxp=9,hv-,js-,pjx=9,pptx=4,bjq-,dzz-,zcj=4,xph=2,rmbn=2,psn-,zf=9,tl=7,xh=4,blq=3,pks-,rh=2,dg=4,mj-,gsq-,kx=1,kptg=6,lqptdz=3,cpn-,xxmgh=8,kjndtt=3,jxqr-,rvjg=1,frg=3,qb-,rc=9,xllc=8,fdh-,nsnx=5,kptg-,gsks-,pvl=8,ghdhl-,ghdhl=3,ksh-,jqt=8,nzk-,bzz=8,splpbg=1,qknkv-,cssn=9,mt-,sb-,sg-,nnjs=8,dk=2,fz=8,xpvr=2,dzz=9,qk=1,qh-,dxd=2,bbp-,prb=1,pptx=5,svvs-,xjsxmj=8,ht-,rckh-,rqgb-,kbvgv=9,ds=7,rrq=7,hh=8,jtf-,zlt-,nlptg-,ngv=5,jkqqkc=8,pz=7,kkt=2,zb-,bldd-,xpz=6,dc-,bgt-,rk=5,nd=1,zb=3,rc=4,vj=2,jdfq-,ztbmk-,frg=1,vfvj=9,st=2,mpc-,hst-,mrx=5,qknkv-,ksq-,jdfq-,tn-,bch=6,mvl=4,bjq=9,ksh=5,kx=8,jt-,szb=9,nnp=6,xl-,dcsn=7,rx-,jrvc=5,dcg=8,bj-,gmnmd-,ts=4,dlk=7,rq=5,hh=5,zlr=8,vcz=3,xtrn=1,xkqjv-,qjzd-,pz-,chlqr-,rh=1,cl-,xh=4,ljm-,xgzfv=6,kv=5,tn=6,ds=1,gz=2,vgb=4,jn=9,svd-,bdld=3,bch=3,xd=6,sdv-,qzz=8,bvvs-,zgg=1,sc-,xllc=5,jkqqkc=9,frg-,xkmfp=1,kqqcsn=6,xdz=1,xzs-,gpq-,qcg-,pr-,jn=5,mbp-,frnx-,gp=1,kbvgv-,gpq=7,hg-,tn=1,nlttf=3,jrvc-,nxr=1,qhdn-,mldh-,lqptdz=1,jzbx-,tkj=8,lcs=4,pg-,xdp=8,czf-,zlr=5,rfk-,nb-,rk-,sc-,mr=7,kvr=2,dq-,ph=6,hh=2,qgh=7,vcqxm-,hjn=7,mhd=7,bldd-,xdvm-,kjp-,vnnpcp=5,kbvgv=7,sz=9,btxb-,zhjlhc=9,bx-,xbz=3,blknq-,qk-,nhh-,rcv-,zgg-,xvz-,zxxf-,txcvg=7,kqqcsn-,zzvx-,fsbtv=3,nbvb=6,hst=5,qz-,dkpn=3,gz=8,mng=7,pl-,nbdt=3,brdh-,gk=8,tgr-,hf-,pr-,mpx-,vb=4,ftf-,rs-,dxh-,ssd=4,zl=9,hg=3,ztbmk=6,mn-,npj=6,qkcjt=4,zv=3,xjxx-,mpx=9,kh-,dcsn-,xh-,xs=3,kknx-,qfq-,mhm=8,dcg=1,rnx-,gsq=3,xjsxmj=5,nvf-,hmvnp-,ksq-,ksg-,ph=9,st=2,xz-,dg-,sb-,znl=6,bzh=2,dc-,bb-,tz-,zh=4,rxs-,rnv=5,vrjr=5,rqgb=1,kh=4,nqdb=6,qhdn=1,jbt=3,bj-,fzg=6,znl=5,bqpn=8,qtqhll-,dlk=2,qbb-,mpc=2,qsc=5,ljzpb=7,mr=4,hv-,jfr-,jqt-,fktrxp-,qd-,blz-,xpvr=7,psn=9,jzgh=2,xbhx=2,ttjs-,mt-,cbq-,jgs=3,tv-,frnx-,zbbb-,kknx-,rvm=5,ltdl=6,kh=9,mbp-,ssm-,mvl=8,ss-,fblp=6,rth-,qb=1,tz-,mc=3,bln-,fpllc=9,rth=4,skq-,rc-,vlq=5,pdz-,nzs-,kl-,bzc=1,bldd-,jq=8,qmh-,frnx-,vzj=2,dcg=6,dthkz=1,dxh-,rnq=2,rlm=8,clgs=4,rnx-,xs-,lp=3,sf-,fx-,dvrg=8,mlb=1,rfz=9,mm=1,xr=2,fx=6,cpn-,pjx-,xpz=6,xjxx-,jx=4,btp=6,qfq-,kkt-,jplf-,ltsl=3,tcx-,fktrxp-,kp-,jx-,jspg-,bgt-,dxd-,cl-,czf-,cbq=3,xxb-,jzgh=2,zvlc=6,cnp=3,bv=7,gfx-,rd-,zgt=5,xz-,bnfgrx-,pj=9,ck-,zbbb-,jmk=1,kvr-,trc-,vnnpcp=3,kd-,bxn-,pmqcz=1,nmsc-,svd-,kr=9,jxqr-,qz=4,dcg=1,nb-,xnrqz-,fblp-,qd-,rq=4,gz=4,hb=7,skq-,qb=5,dthkz=5,cmn=2,kt-,xktvp-,npj=1,kv=3,mhnjv-,rvjg-,jgs-,jfr-,sk=3,gzgqz=6,cl=2,kqb-,dm-,jzgh-,ntt-,qzz=6,kd=9,xjsxmj-,jkds-,cssn-,rth=7,jx=4,gslf=4,frh=4,xxmdx-,zlt=1,pdz-,zrf-,mvl=7,frg-,kp=9,ftcs=6,zdt-,qs-,cxbjsc=5,hqdgdx-,jpx=3,xdvm=7,trjxl-,nf=3,ftf-,xdz=4,mpc=3,zm-,zzvx=4,pvcq=3,rr=4,mxd=8,fr-,xxmdx-,sc=6,fj-,rtc=3,tpdq-,fb=9,lls=2,czf=9,vnnpcp=6,mvl=9,rsjt-,xqb-,dsssjs=3,kx=3,gvxmb-,gf-,xjxx=9,km-,btxb-,mh=6,vjzjnn=1,czz-,fktrxp-,fxz-,vfvj=2,nmsc=2,dthkz=1,nf-,rq-,gslf=1,nlptg=3,pjx-,bt=5,zgt-,pr-,xjqkf-,jnth-,bq=9,lk-,pvx=5,js=4,zlt-,vcz-,tcx-,pqxlsr-,ht=1,pj=9,dff=7,txcvg-,cp-,xczxrm-,mpx=8,lqptdz=2,pgc=9,cc-,ffv-,xllc-,mh-,pjx=3,ltdl-,gvxmb-,nbdt=4,qf=6,hddp-,khx-,rcv=6,hb-,jzbx-,sclb=2,mrx-,nd=3,njj=8,hg=4,fr-,ksq-,thf-,drj-,nzk-,bdld=1,jn-,gtbfk=5,jpx-,nj=4,mccv-,pps=4,zdt-,ntt-,kl-,mhm-,jkds=2,cb-,dxh-,nqdb=3,jmrx-,lbmz-,splpbg=2,kqb=3,ght-,nzs=5,ffv-,zdt-,tsj=2,gx-,fx=2,mvl=1,rtb=2,sr-,vrtgm-,jbt-,plx-,lls=1,cssn-,mnkkl=8,jt-,nsnx-,bch=9,lqptdz=1,fk=6,zp=3,dq-,jplf=1,mj-,zhjlhc-,frnx-,xqb-,fpllc-,gkj-,khx-,zmd=8,qhdn-,ksq=7,hz=2,nlttf-,gzgqz-,zgg-,jxqr-,mvxp-,xdz-,zd-,ps=2,lbd=2,jggftj=4,nq-,jvtfs=9,tjjbp=4,gz=1,rtc=9,xzs=5,nq=9,dsssjs=1,rmbn-,kptg=8,gfx-,pz-,gncb=6,pj-,jmk-,hf-,rnv-,gqp-,kt-,fr-,ttjs-,fxz=1,jqt=7,zp-,jkds-,mbp=6,vmz-,qzz-,nsr-,xz=9,zrf=4,dlk-,xff=8,jkqqkc-,npqjbg=7,mng-,hv-,bzz=2,mng=2,nq-,bnfgrx-,ssm=6,btp=5,sshzn-,sdv-,rp-,mgdmqf-,nbn-,vrjr-,mvl=1,mmqxv-,zd=7,cc-,cb-,dt-,pfk-,vrtgm=6,kknx=4,vhb-,frnx=7,rqnbh=2,cfczf=5,mc=7,jx-,nxr=9,jx=4,zzvx-,vjzjnn-,nb-,ttjs=4,kjndtt=6,xbl=9,rghth=4,nvf=2,rvq=3,xgzfv=7,mh=8,vbl=5,ngv-,qzlpc=3,pll=3,tkj-,kcgf=8,cp=8,hh-,jkqqkc-,rmbn-,ffv-,psn-,fr=3,btp=8,xdp-,bzc-,kbvgv-,pg=7,rh=7,nzs-,gqtb=1,tkj=3,tj-,lmj=7,kjp=3,xbl=7,ljnrz-,qknkv-,dcg-,xpvr=9,xltd=5,rh-,nmsc=9,xvz-,fx=9,rrq=9,ksg=6,zd-,tcx=1,khx-,dmdp-,mfs-,qfg=5,ght=1,ghdhl=6,qfg-,tvgf-,cnp-,pmqcz-,nsnx=2,qbb=2,rx-,rqgb=7,sf-,qk-,jggftj-,cl-,jmk=9,lk=5,zd-,sckkk=3,xjxx=8,qm=6,bdld-,jpx-,jrm=8,nhh-,zlr=3,rmkm-,jggftj-,gjx-,xxmdx-,xxmgh=2,nzk-,cn=3,jdfq-,vbl-,cssn=5,jrm=4,zgt=5,gvxmb-,ts-,pqxlsr-,jkqqkc=4,sr-,thq-,qgh=1,vjzjnn-,bfv-,hjn-,xllc=9,vn-,gt-,qsg=5,qmh=5,gq=2,bgt-,nbdt=2,kqb-,nb-,hlh=3,sbplc-,bdld=3,bzcq-,zd-,jtf-,st=6,mmqxv=1,dm-,dmz-,rq=9,fzg=2,tnbz=3,jgs-,bq=8,skq=8,vfvj=6,nhp=3,cbgx=8,mhm=7,sdv=4,vmz-,pg-,zbbb-,xllc=6,tnbz=2,qz-,rd-,kv-,zrf-,tnbz=4,gq-,nj=2,mh-,mfs-,trc-,xbl=4,ght=8,vlq=8,hp=8,cbgx=1,clg-,ksq-,bq=7,jrvc-,pqxlsr=3,rf-,skq=8,cpn=1,jqt-,kl=2,nfppt=6,kjp-,cp-,jzgh-,cn=9,xr=8,cbgx=1,kl-,vxzj-,cfczf-,rtb=6,qzz=2,gjz=1,tcx-,rr-,bxn-,sf-,qsg=6,vbl-,fr-,bqx=8,cp-,mhd-,rtb-,vk=2,nsr=9,xp=5,ltsl=6,fb=6,pgc-,zl=5,xdvm-,fz=4,gd=8,sckkk=7,pmqcz-,dvrg-,dq-,hmvnp-,trc-,xkmfp=8,mccv-,dxh-,thf-,cgplp-,xvz=3,dk-,sv=9,jqt=3,kd=2,xd-,pdz=9,bsp-,trjxl=3,ftf-,rp-,nzs-,ftcs=2,sckkk-,mrx=7,prb-,ccd=9,pn=8,fdh=7,gfx=7,jtf=7,cc=6,chlqr-,rfz-,gtbfk=7,bvvs=8,qgh=8,psn-,nlptg-,ts=6,jvtfs=1,dlk-,qf=4,qmh=6,thf-,pfk-,rxs-,jnth=1,zrf-,mm-,xm-,rth-,xzm=1,rx-,lrpgnl=4,cxbjsc-,xbl-,gtbfk=1,rs-,gz-,vzj-,fr-,dmz=3,pvx-,spm=2,xdp-,vbl-,xjqkf-,xnrqz=7,ttsz-,qz=8,gjx=9,fqg=7,tpdq=3,gg=2,lrpgnl=9,pvcq-,xbhx=3,gt=2,hq=8,mvl-,zmd=9,qzz=1,zl-,mc-,pvcq-,nff-,nhp-,blq-,lxcf=6,ck-,cbntnn-,zm-,xpz=1,jcvt-,plx=5,rth-,xllc=6,ph=7,cfczf=1,xl=6,mldh=3,rnv-,ssd=2,xnrqz-,npj-,nhh=4,lxcf-,qknkv=9,qm-,km=6,fx=2,sk=4,dvrg-,pptx-,bt=4,zgt-,mbpn=6,nff-,frg-,vgb=6,nlptg-,nj-,thq-,xdz-,ttsz-,xd-,gfx-,mhd-,ccd-,fx-,vrjr-,jfr=1,dm=8,xnrqz-,ksh-,gtbfk=8,gslt=3,zv=9,dvrg=1,rs=3,ccd-,plx=4,nsnx=8,prb-,rnq-,dthkz-,gsks=2,sg=7,ljnrz-,gtbfk-,tcx-,jq-,ngv-,rr-,sbplc-,dm=3,dlk-,zvlc-,pr-,rfk=8,xxmgh-,lrpgnl-,kjp-,hst=6,kl-,qsg-,htsz-,ss=5,bv-,rtsm-,gvl=4,jrm=5,bch=4,xff-,tsj-,jqt=3,czf-,hs=2,mccv=1,vd=6,tvgf=7,splpbg=5,rlfkx=7,xzm=5,gncb=8,hdg=8,pg=3,psn=3,hmvnp=6,xdp-,gqp-,lcs-,jrm=6,jmrx=7 ================================================ FILE: exm/aoc/2023/aoc_2023_15_questions.txt ================================================ --- Day 15: Lens Library --- The newly-focused parabolic reflector dish is sending all of the collected light to a point on the side of yet another mountain - the largest mountain on Lava Island. As you approach the mountain, you find that the light is being collected by the wall of a large facility embedded in the mountainside. You find a door under a large sign that says "Lava Production Facility" and next to a smaller sign that says "Danger - Personal Protective Equipment required beyond this point". As you step inside, you are immediately greeted by a somewhat panicked reindeer wearing goggles and a loose-fitting hard hat. The reindeer leads you to a shelf of goggles and hard hats (you quickly find some that fit) and then further into the facility. At one point, you pass a button with a faint snout mark and the label "PUSH FOR HELP". No wonder you were loaded into that trebuchet so quickly! You pass through a final set of doors surrounded with even more warning signs and into what must be the room that collects all of the light from outside. As you admire the large assortment of lenses available to further focus the light, the reindeer brings you a book titled "Initialization Manual". "Hello!", the book cheerfully begins, apparently unaware of the concerned reindeer reading over your shoulder. "This procedure will let you bring the Lava Production Facility online - all without burning or melting anything unintended!" "Before you begin, please be prepared to use the Holiday ASCII String Helper algorithm (appendix 1A)." You turn to appendix 1A. The reindeer leans closer with interest. The HASH algorithm is a way to turn any string of characters into a single number in the range 0 to 255. To run the HASH algorithm on a string, start with a current value of 0. Then, for each character in the string starting from the beginning: Determine the ASCII code for the current character of the string. Increase the current value by the ASCII code you just determined. Set the current value to itself multiplied by 17. Set the current value to the remainder of dividing itself by 256. After following these steps for each character in the string in order, the current value is the output of the HASH algorithm. So, to find the result of running the HASH algorithm on the string HASH: The current value starts at 0. The first character is H; its ASCII code is 72. The current value increases to 72. The current value is multiplied by 17 to become 1224. The current value becomes 200 (the remainder of 1224 divided by 256). The next character is A; its ASCII code is 65. The current value increases to 265. The current value is multiplied by 17 to become 4505. The current value becomes 153 (the remainder of 4505 divided by 256). The next character is S; its ASCII code is 83. The current value increases to 236. The current value is multiplied by 17 to become 4012. The current value becomes 172 (the remainder of 4012 divided by 256). The next character is H; its ASCII code is 72. The current value increases to 244. The current value is multiplied by 17 to become 4148. The current value becomes 52 (the remainder of 4148 divided by 256). So, the result of running the HASH algorithm on the string HASH is 52. The initialization sequence (your puzzle input) is a comma-separated list of steps to start the Lava Production Facility. Ignore newline characters when parsing the initialization sequence. To verify that your HASH algorithm is working, the book offers the sum of the result of running the HASH algorithm on each step in the initialization sequence. For example: rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 This initialization sequence specifies 11 individual steps; the result of running the HASH algorithm on each of the steps is as follows: rn=1 becomes 30. cm- becomes 253. qp=3 becomes 97. cm=2 becomes 47. qp- becomes 14. pc=4 becomes 180. ot=9 becomes 9. ab=5 becomes 197. pc- becomes 48. pc=6 becomes 214. ot=7 becomes 231. In this example, the sum of these results is 1320. Unfortunately, the reindeer has stolen the page containing the expected verification number and is currently running around the facility with it excitedly. Run the HASH algorithm on each step in the initialization sequence. What is the sum of the results? (The initialization sequence is one long line; be careful when copy-pasting it.) --- Part Two --- You convince the reindeer to bring you the page; the page confirms that your HASH algorithm is working. The book goes on to describe a series of 256 boxes numbered 0 through 255. The boxes are arranged in a line starting from the point where light enters the facility. The boxes have holes that allow light to pass from one box to the next all the way down the line. +-----+ +-----+ +-----+ Light | Box | | Box | ... | Box | -----------------------------------------> | 0 | | 1 | ... | 255 | +-----+ +-----+ +-----+ Inside each box, there are several lens slots that will keep a lens correctly positioned to focus light passing through the box. The side of each box has a panel that opens to allow you to insert or remove lenses as necessary. Along the wall running parallel to the boxes is a large library containing lenses organized by focal length ranging from 1 through 9. The reindeer also brings you a small handheld label printer. The book goes on to explain how to perform each step in the initialization sequence, a process it calls the Holiday ASCII String Helper Manual Arrangement Procedure, or HASHMAP for short. Each step begins with a sequence of letters that indicate the label of the lens on which the step operates. The result of running the HASH algorithm on the label indicates the correct box for that step. The label will be immediately followed by a character that indicates the operation to perform: either an equals sign (=) or a dash (-). If the operation character is a dash (-), go to the relevant box and remove the lens with the given label if it is present in the box. Then, move any remaining lenses as far forward in the box as they can go without changing their order, filling any space made by removing the indicated lens. (If no lens in that box has the given label, nothing happens.) If the operation character is an equals sign (=), it will be followed by a number indicating the focal length of the lens that needs to go into the relevant box; be sure to use the label maker to mark the lens with the label given in the beginning of the step so you can find it later. There are two possible situations: If there is already a lens in the box with the same label, replace the old lens with the new lens: remove the old lens and put the new lens in its place, not moving any other lenses in the box. If there is not already a lens in the box with the same label, add the lens to the box immediately behind any lenses already in the box. Don't move any of the other lenses when you do this. If there aren't any lenses in the box, the new lens goes all the way to the front of the box. Here is the contents of every box after each step in the example initialization sequence above: After "rn=1": Box 0: [rn 1] After "cm-": Box 0: [rn 1] After "qp=3": Box 0: [rn 1] Box 1: [qp 3] After "cm=2": Box 0: [rn 1] [cm 2] Box 1: [qp 3] After "qp-": Box 0: [rn 1] [cm 2] After "pc=4": Box 0: [rn 1] [cm 2] Box 3: [pc 4] After "ot=9": Box 0: [rn 1] [cm 2] Box 3: [pc 4] [ot 9] After "ab=5": Box 0: [rn 1] [cm 2] Box 3: [pc 4] [ot 9] [ab 5] After "pc-": Box 0: [rn 1] [cm 2] Box 3: [ot 9] [ab 5] After "pc=6": Box 0: [rn 1] [cm 2] Box 3: [ot 9] [ab 5] [pc 6] After "ot=7": Box 0: [rn 1] [cm 2] Box 3: [ot 7] [ab 5] [pc 6] All 256 boxes are always present; only the boxes that contain any lenses are shown here. Within each box, lenses are listed from front to back; each lens is shown as its label and focal length in square brackets. To confirm that all of the lenses are installed correctly, add up the focusing power of all of the lenses. The focusing power of a single lens is the result of multiplying together: One plus the box number of the lens in question. The slot number of the lens within the box: 1 for the first lens, 2 for the second lens, and so on. The focal length of the lens. At the end of the above example, the focusing power of each lens is as follows: rn: 1 (box 0) * 1 (first slot) * 1 (focal length) = 1 cm: 1 (box 0) * 2 (second slot) * 2 (focal length) = 4 ot: 4 (box 3) * 1 (first slot) * 7 (focal length) = 28 ab: 4 (box 3) * 2 (second slot) * 5 (focal length) = 40 pc: 4 (box 3) * 3 (third slot) * 6 (focal length) = 72 So, the above example ends up with a total focusing power of 145. With the help of an over-enthusiastic reindeer in a hard hat, follow the initialization sequence. What is the focusing power of the resulting lens configuration? ================================================ FILE: exm/aoc/2023/aoc_2023_16.adb ================================================ -- Solution to Advent of Code 2023, Day 16 ------------------------------------------- -- The Floor Will Be Lava -- -- https://adventofcode.com/2023/day/16 -- Copy of questions in: aoc_2023_16_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_16 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 10; input_name : constant VString := +"aoc_2023_16"; n : constant := 110; map : array (1 .. n, 1 .. n) of Character; type Tile_Beam is array (Direction) of Boolean; clean_tile : Tile_Beam; type Beam_Map_Type is array (1 .. n, 1 .. n) of Tile_Beam; beam_map, clean_beam_map : Beam_Map_Type; procedure Read_Data is f : File_Type; begin for d in Direction loop clean_tile (d) := False; end loop; Open (f, input_name & ".txt"); for i in 1 .. n loop for j in 1 .. n loop Get (f, map (i, j)); clean_beam_map (i, j) := clean_tile; end loop; end loop; Close (f); end Read_Data; procedure Show_Beams is ct : Natural; begin for i in 1 .. n loop for j in 1 .. n loop ct := 0; for d in Direction loop if beam_map (i, j)(d) then ct := ct + 1; end if; end loop; case ct is when 0 => Put ('.'); -- No beam when 1 => for d in Direction loop if beam_map (i, j)(d) then case d is when north => Put ('^'); when east => Put ('>'); when south => Put ('v'); when west => Put ('<'); end case; end if; end loop; when 2 => Put ('2'); -- Beams in two directions when 3 => Put ('3'); -- Beams in three directions when 4 => Put ('4'); -- Beams in four directions when others => null; end case; end loop; New_Line; end loop; end Show_Beams; procedure Progress (partial_state_beam_count : out Natural) is procedure Offspring (i, j : Positive; d : Direction) is begin case d is when north => if i > 1 then beam_map (i - 1, j)(d) := True; end if; when east => if j < n then beam_map (i, j + 1)(d) := True; end if; when south => if i < n then beam_map (i + 1, j)(d) := True; end if; when west => if j > 1 then beam_map (i, j - 1)(d) := True; end if; end case; end Offspring; begin partial_state_beam_count := 0; for i in 1 .. n loop for j in 1 .. n loop for d in Direction loop -- There can be up to four different -- beams through cell (i, j). if beam_map (i, j)(d) then partial_state_beam_count := partial_state_beam_count + 1; -- ^ This count will miss propagation of beams onto cells -- on a row < i or a column < j. -- But on next call to `Progress`, they will be in. case d is when north => case map (i, j) is when '/' => Offspring (i, j, east); when '\' => Offspring (i, j, west); when '-' => -- Flat side of a splitter Offspring (i, j, east); Offspring (i, j, west); when others => Offspring (i, j, north); end case; when east => case map (i, j) is when '/' => Offspring (i, j, north); when '\' => Offspring (i, j, south); when '|' => -- Flat side of a splitter Offspring (i, j, north); Offspring (i, j, south); when others => Offspring (i, j, east); end case; when south => case map (i, j) is when '/' => Offspring (i, j, west); when '\' => Offspring (i, j, east); when '-' => -- Flat side of a splitter Offspring (i, j, east); Offspring (i, j, west); when others => Offspring (i, j, south); end case; when west => case map (i, j) is when '/' => Offspring (i, j, south); when '\' => Offspring (i, j, north); when '|' => -- Flat side of a splitter Offspring (i, j, north); Offspring (i, j, south); when others => Offspring (i, j, west); end case; end case; end if; end loop; end loop; end loop; end Progress; function Energized_Count return Natural is c : Natural := 0; ct : Natural; begin for i in 1 .. n loop for j in 1 .. n loop ct := 0; for d in Direction loop if beam_map (i, j)(d) then ct := 1; exit; end if; end loop; c := c + ct; end loop; end loop; return c; end Energized_Count; r : array (Part_Type) of Integer; verbose : constant Boolean := False; procedure Spread_Beams is bc, old_bc : Natural; begin old_bc := 0; loop Progress (bc); exit when old_bc = bc; old_bc := bc; end loop; if verbose then Show_Beams; end if; end Spread_Beams; procedure Do_Part_1 is begin beam_map := clean_beam_map; beam_map (1, 1)(east) := True; Spread_Beams; r (part_1) := Energized_Count; end Do_Part_1; procedure Do_Part_2 is begin r (part_2) := 0; for x in 1 .. n loop for d in Direction loop beam_map := clean_beam_map; case d is when north => beam_map (n, x)(d) := True; when east => beam_map (x, 1)(d) := True; when south => beam_map (1, x)(d) := True; when west => beam_map (x, n)(d) := True; end case; Spread_Beams; r (part_2) := Max (r (part_2), Energized_Count); end loop; end loop; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; if not compiler_test_mode then -- HAC is too slow on Part 2, which is basically 440x Part 1, -- with different entrance points and directions. -- -- GNAT (fast mode) takes 7 seconds. -- HAC (VM) takes an estimated 7920 seconds, or 2.2 hours -- that is, a factor 1131 ! Do_Part_2; end if; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 7996 -- Part 2: validated by AoC: 8239 end if; end AoC_2023_16; ================================================ FILE: exm/aoc/2023/aoc_2023_16.txt ================================================ \........-.........\................................|..................-.............\../......-.............. ........|....\.../...-...............\.........\...........-......-.......\...../.....................-.../... .......--.......|.-..-..........................\....../..../........-............/.........|........|........ .................................../.........................|....|.....\............./..........|...../..\\.. .........\................|..../.........................................-......|........................|.... .|............-....|.....-.....|...............-.............-....................................\........... ...|.....-.|........\....|....................|....|......-.../..............|.....\.../...................... ..../.-......|................/.....\......................................./.........-.....-..............-.. ............|.\.............|...\...................|............-|.................|...............\......... ..-...............\............./.......\......\....-..........\.|.....|.........-........\................... ...|.................\./.....\.......-.........-................\-.....................\.............../...... ..................................-.../.........../...|...........................-\............\|.\......../. ..../.....................|..\.|............./....|......................\.........../.\...................... ......-/.............|-.../.....|...........././..\...........................\.......\..................|...| -.........................|.....\...................|.\.......|.....//..........|..........|........./.......- .......-........../.......\.........|..../........-.-|....../....../....-......../..-......................... ..-/.....-..//......./.....|.............-....|............/.........\....|........|.............\.....-.....- .....-........|.-.|........-.....................-/...\..................................-.|.-.|.\.../-.\..... .......................\....|.|....\....................-../........................../|-..................... ..........|.......-.../..\........................./.....................|\..................\......./.-...../ ...............-................................\............-...../.............\........-.......\........... .....................\.......\......\..\......-................................./...../.../................... ...|......................-.......................|.............-.....-.-...-...|........-.........\........|. .................../-.........../............-.......-\........|....................|......./..-......|....... .../........|...../...................|/.......................|.........../..|........./../.../..........|... ..|......-.......|./..|../....................-...............|......................../................|..... ..|.........-............|/..\....................//.......-.../.....................................-..../... ............\............|..\../................./......\\...............|...../-./..........\................ ...................././/../.|.|......\................................|..|......|........../.........|./...... ...........|..................-............-.\................./.................................|...-....\... ........-........|................../.................................../........|...........-.|......./...... ..\..|\./....\.-......./........\..-.....-.|..\.............|........|.......|...................\..........\. .|\\.......\......../.......................|...\...\......../.............|./....|...........-......\........ ...\........\...../.....||...../.......\............-.........................\./..........\.............-..-. ......|.|.../....................-..././......|.\......|../.......|.....|......|................./.-.......\.. ...........................................-....|............................|..............-.-/....\......... .....|/.../.....\.......-.........|........................-......\.......................-....-.............. ..\..........-............\..........|.......................-...|....\.......|............/.......\.-........ .......|............................................-...-|........||..\................./......\.............. ......-....|................................-...../......\.........................\.\/.....................\/ ...................\.................|..|.........|...|................-..\................................... ..|........-...../........|....\|........./.......|-............/.-.........../......../...../.....\.../...... ../.../...\..............|..-..............\./.................-...\.|.................................../.... /...-................................................\............|......|............................|....... ..................\\/\.......-.............../................./.......|.....\.-......-\..-................... ./......\-......./...|.....................................|...........................|..........-../.....\.- .................-...-............|................/.......-...............-...|........-........|..|......./. ......../....-......\.................\/..\..|...........\\-.../............/.\..............|\..|............ ................|.....|-...../..|....-..........|............................./......./.../.........\.|....|.. ..-.......-./......................................\........./..........................................-..... ........\....|.........--....-...................................................|..\|...............\./../... -...\...........-........................\.............\.|.../......|..-...............\..|................... ...........\....-.\......../...../\...\.....|...................................\..../|......-........-....... ................|...........\............../..................\\........|-..............|..../....|........... /.......|........................|...-......-.....-....|..\......-....\-../......\............................ .-....../....../.........................../...................................../........-................... .....................-..\.//...............\/..|.|.../.................../..../.....................|........\ .\........-....................|............................./.........-.-................\.-.-/.......\...... ....|.......-....................|.....|.........................../................/.....................-... ..................-.....-.|....................../../.-...../...\..........\...\-......-...|.......\...\...... ......\...../................./..........\............................-....|||.../....................../..-.. \......\.\..............................|...........|...........-..../......../....-.......................... ........||......\.......\.\/....|.../................|....../...........\...............................\..... .......-\....|.--......./../.\............-/\....../.../.....-...........-\................|.................. ...............|.......\...-..//......\/......................................./................./..../....\/. .............|......../.........../.........\......|..../.......-................|.....././................... ..|......./.............................\....../.........-..../............|...\.\..........................\. ....-....\.....................-...........................\.......\\............|.................-...\..../. ............./............-........./.........../..\.............|............................../......-...... ...../...|.../.|......./|.............../\.....|.............................-...........\.-.-......\./....... .........|..........................\...................\...............|\......|/...../........../.....-..... ..-.....\....-..|........-............\...-.............../..........|.........|.........\/.....\/....-...\... ....|.........\............../..........|..............-|.........-...........|/..-......................\.... ....|.....-.|..........|..|......../..............|...........|/.....|.............\.......|...............|.. .............\.......\.................../...................||..........//........................../....././ ............................|.....\..-|........-..........\..-......................../......................\ .................................\.....................-..|.......\/...........................--............. ....\........|||...........||..........\\./||.........../\.-./-....\......./.../............\................. ...........................-.....|.............\.-.........../................\....../...........\.......-.... ...-.\....//.\....|..............|\.|..............|.........-.....................................\.......... ............-..../...............\...|......|..-...................../.........-........\.//............\...|. ....../..............-..................../..........-..........................|...........\......../........ .....|....................|.|...\.....|........-..............-..-....\/............../....................... ............|......-........-............................-|-../.-..............-...../..........\.........../. ..|...../.......|....\.\.........-./..................\.......|.......-.|.|...................../.-..|...\.... \.|..................-..|................./....\.............-...........|...........|/....................../ ..\............/....../.|.../............./........./..................|.-\.||.|....|..................-..-... .....|....................|..../............/....\\\..../-...\......./......-.............||.................. \......-..-........-..|...............|......../..-............\........................-.....\............... .............-................\...........\..-........-....-....\...................................|....|.\.. /..................................../....\.-...\....\..../.........--.....................|...../............ ...|........./........../....................................................................../.............. .|-...|........\..........-/..........-.........-.-..\.|........./........|........-.......................... .\................|../................-...\.............|.............../.......\............\......|......... .......|...\.......\.............../|.....|.....\............/.....|..|............................/.....\.... ..../....../..................\-...../........|.....\............................................../.......... ................|.\..........................-........../..........\.................|................/....... ...............\......-.-....\.|..\................................................|-|..-\..../.../........... /.........|..|...........|.........\......................\........|............................\...-..|./.... ......../..../...........|........\..../.......|............-|...........................|../......|./.......- .....................................|./...../.........../.-..../................./..../...................... /................................./......../.-../-.....\............../....|......\..|.......\.....-.......... .......-........................................./......|..../.............................-./..|.-........... ............../..................|....|............-.......-..|./.|.../......-..................|.........../. ..\.\..........................-...............-......../..........\.......|...../..................|\.\...... .......................|.....\..-.............\......|.......-.............................\.../.............- ............|........./.............|..........|\................../..\....-..\...\........................... ......|.......................\................./......................-.............|.................../|..- ........-..\..-/|-..-......./.............-.............../.......-.....-..-.|./............................/. .........|............/....................../..|..-...\.........../......|........................|....\..|.\ ================================================ FILE: exm/aoc/2023/aoc_2023_16_questions.txt ================================================ --- Day 16: The Floor Will Be Lava --- With the beam of light completely focused somewhere, the reindeer leads you deeper still into the Lava Production Facility. At some point, you realize that the steel facility walls have been replaced with cave, and the doorways are just cave, and the floor is cave, and you're pretty sure this is actually just a giant cave. Finally, as you approach what must be the heart of the mountain, you see a bright light in a cavern up ahead. There, you discover that the beam of light you so carefully focused is emerging from the cavern wall closest to the facility and pouring all of its energy into a contraption on the opposite side. Upon closer inspection, the contraption appears to be a flat, two-dimensional square grid containing empty space (.), mirrors (/ and \), and splitters (| and -). The contraption is aligned so that most of the beam bounces around the grid, but each tile on the grid converts some of the beam's light into heat to melt the rock in the cavern. You note the layout of the contraption (your puzzle input). For example: .|...\.... |.-.\..... .....|-... ........|. .......... .........\ ..../.\\.. .-.-/..|.. .|....-|.\ ..//.|.... The beam enters in the top-left corner from the left and heading to the right. Then, its behavior depends on what it encounters as it moves: If the beam encounters empty space (.), it continues in the same direction. If the beam encounters a mirror (/ or \), the beam is reflected 90 degrees depending on the angle of the mirror. For instance, a rightward-moving beam that encounters a / mirror would continue upward in the mirror's column, while a rightward-moving beam that encounters a \ mirror would continue downward from the mirror's column. If the beam encounters the pointy end of a splitter (| or -), the beam passes through the splitter as if the splitter were empty space. For instance, a rightward-moving beam that encounters a - splitter would continue in the same direction. If the beam encounters the flat side of a splitter (| or -), the beam is split into two beams going in each of the two directions the splitter's pointy ends are pointing. For instance, a rightward-moving beam that encounters a | splitter would split into two beams: one that continues upward from the splitter's column and one that continues downward from the splitter's column. Beams do not interact with other beams; a tile can have many beams passing through it at the same time. A tile is energized if that tile has at least one beam pass through it, reflect in it, or split in it. In the above example, here is how the beam of light bounces around the contraption: >|<<<\.... |v-.\^.... .v...|->>> .v...v^.|. .v...v^... .v...v^..\ .v../2\\.. <->-/vv|.. .|<<<2-|.\ .v//.|.v.. Beams are only shown on empty tiles; arrows indicate the direction of the beams. If a tile contains beams moving in multiple directions, the number of distinct directions is shown instead. Here is the same diagram but instead only showing whether a tile is energized (#) or not (.): ######.... .#...#.... .#...##### .#...##... .#...##... .#...##... .#..####.. ########.. .#######.. .#...#.#.. Ultimately, in this example, 46 tiles become energized. The light isn't energizing enough tiles to produce lava; to debug the contraption, you need to start by analyzing the current situation. With the beam starting in the top-left heading right, how many tiles end up being energized? --- Part Two --- As you try to work out what might be wrong, the reindeer tugs on your shirt and leads you to a nearby control panel. There, a collection of buttons lets you align the contraption so that the beam enters from any edge tile and heading away from that edge. (You can choose either of two directions for the beam if it starts on a corner; for instance, if the beam starts in the bottom-right corner, it can start heading either left or upward.) So, the beam could start on any tile in the top row (heading downward), any tile in the bottom row (heading upward), any tile in the leftmost column (heading right), or any tile in the rightmost column (heading left). To produce lava, you need to find the configuration that energizes as many tiles as possible. In the above example, this can be achieved by starting the beam in the fourth tile from the left in the top row: .|<2<\.... |v-v\^.... .v.v.|->>> .v.v.v^.|. .v.v.v^... .v.v.v^..\ .v.v/2\\.. <-2-/vv|.. .|<<<2-|.\ .v//.|.v.. Using this configuration, 51 tiles are energized: .#####.... .#.#.#.... .#.#.##### .#.#.##... .#.#.##... .#.#.##... .#.#####.. ########.. .#######.. .#...#.#.. Find the initial beam configuration that energizes the largest number of tiles; how many tiles are energized in that configuration? ================================================ FILE: exm/aoc/2023/aoc_2023_17.adb ================================================ -- Solution to Advent of Code 2023, Day 17 ------------------------------------------- -- Clumsy Crucible -- -- https://adventofcode.com/2023/day/17 -- Copy of questions in: aoc_2023_17_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_17 is use AoC_Toolbox, HAT; input_name : constant VString := +"aoc_2023_17_questions"; n : constant := 13; skip_header : constant := 20; -- GNAT runs this program on the actual problem data in 1.55 seconds, -- while HAC takes forever. -- -- input_name : constant VString := +"aoc_2023_17"; -- n : constant := 141; skip_header : constant := 0; inf : constant Natural := Integer'Last / 4; map : array (1 .. n, 1 .. n) of Natural; procedure Read_Data is c : Character; f : File_Type; begin Open (f, input_name & ".txt"); if skip_header > 0 then Skip_Line (f, skip_header); end if; for y in 1 .. n loop for x in 1 .. n loop Get (f, c); map (x, y) := Ord (c) - Ord ('0'); end loop; end loop; Close (f); end Read_Data; -- Dijkstra shortest path algorithm. -- Code adapted from AoC_2022_12. -- -- The following definitions belong to the Dijkstra algorithm, but -- we keep them less local because of the visualization. list_length_max : constant := 500_000; subtype List_Range is Integer range 1 .. list_length_max; steps_max : constant := 10; type State_Type is record pt : Point; dir : Direction_or_Nil; steps : Natural; end record; type Node is record len : Natural; state : State_Type; pred : Natural; -- This is just for displaying the path. end record; list : array (List_Range) of Node; current, explored : Natural; -- 0 <= current <= explored best : array (1 .. n, 1 .. n, Direction, 1 .. steps_max) of Natural; verbose : constant Boolean := False; function Dijkstra_Algorithm (start, finish : Point; part : Part_Type) return Natural is cur_len : Natural; cur_s : State_Type; s : State_Type; -- Test state derived from current state. procedure Visit (dir : Direction) is len_to, ins : Integer; new_node : Node; vec : Point; -- Jump over x, y positions that represent invalid states: jump : Positive; begin if cur_s.dir /= nil and then dir = Opposite (cur_s.dir) then -- Avoid gaming the rules by going back and forth (U-turns). -- Turns must be 90 degrees. return; elsif dir = cur_s.dir then -- Same direction s.steps := cur_s.steps + 1; jump := 1; else -- New direction: turn. case part is when part_1 => s.steps := 1; jump := 1; when part_2 => s.steps := 4; jump := 4; end case; end if; -- The number of steps in a single direction is limited: case part is when part_1 => if s.steps > 3 then return; end if; when part_2 => if s.steps > 10 then return; end if; end case; s.dir := dir; case dir is when north => vec.x := 0; vec.y := -1; when east => vec.x := +1; vec.y := 0; when south => vec.x := 0; vec.y := +1; when west => vec.x := -1; vec.y := 0; end case; s.pt.x := cur_s.pt.x + jump * vec.x; if s.pt.x in 1 .. n then s.pt.y := cur_s.pt.y + jump * vec.y; if s.pt.y in 1 .. n then len_to := cur_len; for count in 1 .. jump loop len_to := len_to + map (cur_s.pt.x + count * vec.x, cur_s.pt.y + count * vec.y); end loop; if len_to < best (s.pt.x, s.pt.y, dir, s.steps) then -- Found a better path to target state s. best (s.pt.x, s.pt.y, dir, s.steps) := len_to; -- -- Insert in a sorted way. -- ins := explored + 1; for i in current + 1 .. explored loop if len_to < list (i).len then ins := i; -- Insert here. -- Optional: remove another node -- with the same state and a larger length. exit; end if; end loop; for i in reverse ins .. explored loop list (i + 1) := list (i); end loop; new_node.len := len_to; new_node.state := s; new_node.pred := current; list (ins) := new_node; explored := explored + 1; end if; end if; end if; end Visit; begin current := 0; explored := 0; for x in 1 .. n loop for y in 1 .. n loop for d in Direction loop for s in 1 .. steps_max loop best (x, y, d, s) := inf; end loop; end loop; end loop; end loop; -- Startup state (without a direction) is not visited again. -- best (start.x, start.y, nil, 1) := 0; cur_s.pt := start; cur_s.dir := nil; cur_s.steps := 1; cur_len := 0; loop for d in Direction loop Visit (d); end loop; -- -- Switch to the next best explored point. -- current := current + 1; if current > explored then Put_Line ("No way found."); return inf; end if; cur_s := list (current).state; exit when cur_s.pt.x = finish.x and then cur_s.pt.y = finish.y; cur_len := best (cur_s.pt.x, cur_s.pt.y, cur_s.dir, cur_s.steps); end loop; if verbose then Put_Line ("Final. Dir = " & cur_s.dir'Image & "; steps =" & cur_s.steps'Image); end if; return best (cur_s.pt.x, cur_s.pt.y, cur_s.dir, cur_s.steps); end Dijkstra_Algorithm; procedure Show_Path is char_map : array (1 .. n, 1 .. n) of Character; i, j, len : Natural; pt : Point; begin for y in 1 .. n loop for x in 1 .. n loop char_map (x, y) := Chr (map (x, y) + Ord ('0')); end loop; end loop; -- Display optimal path, back from the end (E). i := current; len := list (i).len; while i /= 0 loop j := list (i).pred; pt := list (i).state.pt; Put_Line (+"Node " & i & ": " & pt.x & ", " & pt.y & "; steps: " & list (i).state.steps & ", towards " & list (i).state.dir'Image & ", cumulated heat loss: " & len); len := len - map (pt.x, pt.y); if i = current then char_map (pt.x, pt.y) := 'E'; else for k in 0 .. list (i).state.steps - 1 loop -- Backtrack the steps. case list (i).state.dir is when nil => char_map (pt.x, pt.y) := '*'; when north => char_map (pt.x, pt.y + k) := '^'; when south => char_map (pt.x, pt.y - k) := 'v'; when east => char_map (pt.x - k, pt.y) := '>'; when west => char_map (pt.x + k, pt.y) := '<'; end case; end loop; end if; i := j; end loop; for y in 1 .. n loop for x in 1 .. n loop Put (char_map (x, y)); end loop; New_Line; end loop; end Show_Path; r : array (Part_Type) of Integer; procedure Do_Part (part : Part_Type) is start, finish : Point; begin start.x := 1; start.y := 1; finish.x := n; finish.y := n; r (part) := Dijkstra_Algorithm (start, finish, part); if verbose then Show_Path; end if; end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; for p in Part_Type loop Do_Part (p); end loop; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 638 (example: 102) -- Part 2: validated by AoC: 748 (example: 94) end if; end AoC_2023_17; ================================================ FILE: exm/aoc/2023/aoc_2023_17.txt ================================================ 122122122221111223212131233223113223121333442231421433142332434134225233545342212211333112344344134442142433223412123123222112313121212221212 222211221221231312321313313211342343411142324132123121134452332445155511344312331454432211221131443421221311311132313213121113133212212121121 122122222123123112133333323222434211131132342432414314214452412531552132441122435121513351133144143322231342334223133211113332223112112212121 121121122123221323133133124121313314444133314314111435332133355334444335454224312242224554224323414441121443212123222111111321321211121211212 221122211323221232131333113424242413333242343434255431431524222114514555335533141355541521354112112323124134232112232412122113112231321212221 122112113332111112211312241113114222334131115345325525553252224253442114313554141223521124145541224124314212142143231424133222231131333222211 212212213321332113123242342411311111433442125134332211522512512135134454413433131555542522225543342113244321143124141111333313212212211321211 111222113233231131222412143432342332212424325445154122325221333315223121441513551143423434221424535543443413414433343312211133122213311321111 121122211212132122314144412132113122134521143321315442521141334521433553332314111441535455212441221412133441223422412413323113211321312211211 121123313221131212422134134333321412515231255135114131115445421335451435423235211523233534133251531525332444243321231442133141331131331111311 111321111323223132223324141431314353242311313155433331232415512425453645632225443423445133351122555413323232212313234221111112322131222113221 213213233232223221144222214333434454513214544423255231433153443662543666342462636543433334445414545114133442433314231223211422211322312332323 111221112223232243122122321421212241245125114454522522365543465656546642224263635556542642232214554245131431244342333332222233433111112222223 233312212113123412143231124323422244335132153244522426656525464342366364422443356424233464621455534322155241541431411413441431421111131232332 233211113333131421333443321151351344444113423244242646332566664266222556455466524354242644245335555232234433443223513323443142441123222111133 312111233113311341414414431232342323214531455545553566654635256333552425266345422365656324526326425541151541544212511221434432244122222322313 131332122131314111114323133241451244423521311354233425236524622465555445536565342435565336563325432514153221123314214123332331434141311113222 231231311222331412324132154121355133321532234534343363466266542355662434334363442553244224224352564632515513424333425211241232312424422121332 223313133214123314124342111353115332512446333635346644355425364423236256333435432425526444236666362464331343231251553453142224341133421111313 332113123232234221124212545411551211254546423543323364625245243255345523262644624325265253334354625244354135354511121431232413344232242213122 233323232121141443421251534243342514544532562336364566523455335463363576553654232523234463556234455234422132255555211315532434442233422312122 212132232144234422134245243255112345524352552542455453443225565345577474547767565755345256433554633653546641242421312111522223434442124231223 123321413434131222234421344553411334245226356625435233656577566553337746744743635774375326542552543223464223514114435131312133323313214422112 331311433212424412324553455113141542523236246546552444375543467447566434346775647346346635636355362654525644235533342342445333422114144332112 122313422432333243535141412111226566244363245465533665553657737566555564475644565467446545343254254632336563243412543535354334143232242421231 222334443144224321514322454123462643226424362235574733446377737444643675636375653456655733776543463333422646536453112544535215124231432144411 113442144242323332354154544325335642225352265663373764434446653675433547735435365476647645647754432256565226223651115542155254311121212212243 113313124143434211345425154435326642625564656457346447377547765676634654653357374643773357345446635533456564663622454441423212422234234322433 313222242331414514413444255555253253234656227456433775577557745353634344377335436455677376744456367564626234525346523413234531444111124123231 234124424214211524123352224626233325345524664473373535773347657456436565357553375563677455675434564622453556536223343312211135132434143343241 314223324221211151133432356545644332443347777536754354374665345545747757547557536636455566356777634676343653623666253552425151125111313124133 411432414444422443515413332323655623663677673645546774756743445545884584744568887546563435746377776743354365536655346324314234524212431312341 112244323223411445151512662434565532454734755653547347767358748877755884777648584548653743775573637777554466525633426251432231415131122244131 331212134433452323233434542562336565263344644744333575576784744686467788544678847876764347776556673434767726536235644342145154533443223141311 144223143322414541141526263242263466435443573476757354555687486788744755578445677587574655755664654345446634545543225643112344243425544243214 211211133311315353455524632446523366777546655477466388688487754875444878458554748868687674647735745546477555655535423234422322223422214122332 233323332451434545112243556662225233665445763747333558657577647644677878675688446866665464776546644334363437442454266655343334213213321233324 231312413341215423223635646634566355537566476444388687576655766687788565766688684447666678646537343553547554455643546642542312435344351423122 313223325341552155426532255526425546547737657655545485445645644747875684466476788564646675675847676434367747353455636325554111223444524434421 313123233242152334525566532545665344375473366755655487584557568465585847744686484446444487557857766336674354743262456225534442324142434414413 431431124241141212263254643262673746433375466588677858465664875557485554584766657847458665474787474354537364577626364443552224431324243433213 221321314531554134523344446564537455733736634687688755447577544887569678585677447464647885478768547636453463633633542243445235152222312232431 131134115135241554536422256224464564746667668658758478867875658586995598966779877578558658875764747577336564337734346462264545123321353322413 123421114152115123452565655566657355443454564546865774587649578598978599655999858585447488774785576553346375767545452523653445151135523321234 224422431425553423622462325637343634776737677744464464467598696979997867696898756585984566476466885674336435355455753322323433232411545155312 414311352435124263223444455635745467476664887464785748566656865567786877787658858859777744487568656867536377353476452346262556224511521225443 223114153345343246554656663354535563567585655685876555979689788777855688765667896889786657586464687878477477365356743325236635311242532412242 123122325432225325522362544773453743736464578484748658666665985899785775886888579795689885885854847748647737737467434332235334651541341553334 443352143214532263453554427657664436735458865786676655579768896689789986987959875959755569877767477557544556336777576453644354561324451251512 121452413251312242546332336633337373756788687555766968565968979666787997968597868556877586876656485877786653354633564442463442362541244125224 424124541535452643445252476377676354374875445574885857878987987657655556889585555975795677966654647686757575436656633742254463335251221312344 442231145454245523353645554743563557867448558568969796957867599569966898697686599585997577896864466476674577455436764545262645522432355145213 233354114345336444533456437343457777658566566456877668559598895867796987768986685767756566857885755778745887467765644633562255433431234351143 324253342114343544244534675743375535768786586887668888886795977869879878866769698876985686759796678654768474747557563442633532665644452515454 114221444443244223644424366376364386648564655896586789898968767796786977779787696888599798697978788567677757666633534565646253566451334212454 231324515512325242535245455467675768588854567989787886666878776967999767878879879979996998665685875667865886455364335677254455642324552234125 123335241124524366456344746675645476445445564767797955968577686666686667788996777698895868778677795767786486845454354747562263264622152553142 231312152241525364542236367736373868458667666779885897585667886777666696769996697899878976676998677778578677886463537647626326654663511112343 331331513311444364256353367734745744545664856969878699566968868997779887978889766677897775886779767476578544443633553536436626625345313454421 311541535146254465342645333566578678568468487678685879887799978886979689787667788999676767566578997656474678758355474646655262523522152524231 451251515414632223243357445374375787644478567996798579778668797886877698979789768899788686758566669664576746684677667734554226323432313522344 312435235356534526643344674354564688886666767659955698886877689967676778876696679986799865887856759577778867444534473534334252443642442551112 315222511556322242562347537534678876487554978596598969689897699688888889888986769669666697798777697575588744547554556557366454224542353433353 425515431314443324446456745644487668777765897686895879799686896697779989879978988786779898678757569666776745678873556477463454524525151442254 131431325313553226425634656745565844664566576586556979796877886679989997978989987667666976655865988864865656775744335663443624652436424325531 331152143452533542664477374777485676554479868958665977868688897897877887987997896899887967697857559567767655574573444337555653226566254113133 255253351164333322455334454735364887645786757955765868767899867977879879977989877699786799988987876687644786656753774437344362634226212342223 341325252336244465354535753473368785645846688777855996896698888778787787899797988879866967688798779898487758847847636774576563352656341411335 412155212433254555566676547343356768875455868866568967667697889887999797977897778886989999666596889665865858768577775545342446542456534425541 511435114262464254434567436757745848466689665575568686766977899878799887898799787898779988976858986899585846555764436555672646532255213214135 235135235456433443255643733544444586687565798557565898666868877777977789899899879876896676779975778859887665874733467535353655622336411132154 355221152564242253526675554634758687685569665798667968999689998977799898988999979779689668679588596899447685845873474455345566623253441453525 144515535232354443223644466635648545558655587768758978796698887978797979888787877966889799779769775868488586668456563746574453352624611541545 551231142423244223353464335537757654777546558756665779688789797788977778887898799779869666789859799879888488746454467775676436542263235131445 522543525436556635654735466736586558485855979659958799699677767777888978797789788897897666867797599969877576665645734356433246526233343135513 151215345452433662463573567646376747544748576798589888998677769787877978877777789996788667685586578587576868646874634436646454265322235432555 433212251254262522364635745743388864886455758886698968977779666988789797997788796966768678966878888568484854776463757346645435553465313553322 544132151312562323225767567633447447857689758975596889667789979987779877897889989898776888859758688957655588855443657477473565664543214423442 132533522454443664563553646546584784544867596878765666877698877999897889777999778796867869999695998698466685875766733646335435456534133231411 431142312344522524452477637567588555474688958959868596969676998879978987898797688989986866685975656554558746687865453566353535655653123241131 115455114346263343465744776567338855564648579889569857869987778876889788878798697766868979689999857858778884466774336433572662363526312322114 124423142232246442653755647363365877767867897756668575996866767687886889987789797967798969958756997668547678466746454443532323233226355235342 232532223216264564333443766675555444844655458885595987989996679699766776878888988667899876985589999645778885546437665576535456356642433242555 112435522536545326463444747756576778855777776896885578668967866998798767676789699776896967799668777756457777786345647437625425325262514152431 141255321434436364434567776573475764878488487879687685758897897779699968677997799868976688657969896464844867884637443556366336564243454535311 111534441325652665664446566674344848447887547897677867968687879976698878888786777988968776987886586777846485554346366733556533552624123255542 331325221254333336643467375367454374854656644655685976999896866669778968799896969778656688787659777756487844455477337464434225235431353141243 341524514145465442443636437655366665675574545698896886987596668976999767966898986968989897676696584865466667744656347443222636656523455235322 341525245521446332553646463474543665645656476868786995857565776787899669777798866678799789599766976878545456745456454434636642446454544134545 431212551454443563543546343347764754885487858649897676956988866779787687876869767655985559587576884558657678673546353755553635464253522311355 442223245413436353365545777475454566548786775558887889575775659867997769898976857796586996998585458867454784433544534336365626436443542114324 412521114534256333553563253657345445578574748884966896579999556586986787688875965656899886565886687664654576346373446346533345342425144253542 141134244215513433356245255736645756358576765676879558578887759589655659999659597659886999786666675568584467535654753662245545242244331433321 241124212314412324422333464566774476578555555746885867968668765795577777868559659587655575959755765465874737343774753562366426635525432324422 344321454522543342555342656764553677656744757674764785995877578857988666675575567558595899998445857848587745663745377424322622225412211551113 142321545532451526325642547477757566378565868764557568666866966798869875698666797598566858655664457575664364367637463545662436345233543455244 121325132533225424534264663333575675777477784764655885796558579879565689959755565968888854567464467584664756436763454322643335345134533322241 411132145535425426545646566554747547667358468876885854897898696965559797959659888786656978844765445685537747477534546535554653641345413535442 443224242533213122545543223635733774363436887564777678764996786677557569568788669698974787688878444488767765436347462324543446414522545514322 213112524141422325632222556463336333457753845647454658644865977989779789559688975897475844844766754565777344463664552224425654444353122512221 123443432412252524564255362252736643346755588866445576656678748669985758875867768544564467884874488756735576653545464556263343231123111522321 211323341425143324532535522334757677737474375667554654845878448789676575559565755844675457876474846747646757737465642253334234224155335533414 111432111251144512226623533254237535754663575485675544765887485484567486767488478777444576487475875457644745443735442644555544454253133512231 333132344143445411444242323553364644365464444367778676886556648654665466444744454655845865464564536636477763643554632323522555531534144331442 244323122552131443225544335344342767763474577436866475644768574755456444465858447688468646585854777676374647546452622455344222113421143212122 342231141215552514353236463563632665374337734364468865868546455888557547486866488867574884486876376443635754362234234533421223244453342434434 123124122115243354253633543434444367464463677335536567748475445854678657857686778754875678554764764344744356753232324645543552134132232311413 412322222335233534224524645543263436773564533357454384844565855787755756655857656556775447657356465376444574535325643655232224413244242422241 442124331351453453124232352455644554433457574575654367447547444644484764557787767678565583555446344647463335334565544545134555514343421111212 222431312412133313414544343363225345263337357477543357466876456578557875877564574776863577563645546533577734644235445653433223115555413123221 131142311424325131231415626545565522454765756454433633355654786445568748857677555746773554366765445745554525326622254363353251441122313112432 332332333141444153453342266254436226562646347634565634766375744666754755757747473453555467576445474576726532225334562353311455111253244421433 224444231141243443114221246563325466323637576764337656757766755435564377745535757444554644733745543766455355553252536334133443232223133343211 133433133133432512223141551334545556423623267367767544777346476677533345447344753644364546563644456424436232554434623334555321531422132144432 113233124412224451124113215455646254646222225767467475745657746436546455745637665743555573675466735433654535623522543143541252412133344213133 113313113211312333511154552344363326562554546537466665744576457647554346656734756374654377776545545235644646664262515124413312421141213121323 322222421342222214252232215221435422626363454264634545634676663446357773673747573356657377576367455445624632655425434255223522324111123233143 111322131331343245153453232455262354632243324442567445464764374563466356563433437566763536645436456656653443332235534125521522233144343121221 133324123332312444331234225442144255265352646244532253575445466747744556753756534345533443534236655362622225363354323122255134344334341431222 313314123434442124331334115143441553656224434463336433763645464656564773553454765757377755433623554654556242621253142342224422433444142414222 113232423231443231215512312555324225222535255224542442362635577345446476355436667773376632652343234523454234432555442151434342333334234331133 111221111223233443443513121412314425366244523343343363346542377465367435774664773666342342464454634465656364152515332142331234424343341113332 123123131422312322244134515214441154254626336325442536544262626326425654545246352322256622345565455425654132445343443221334443442344332131132 321223131221322223424321343535452552544643563425665663523652322466242442625366465252244445533355526523361235252141251151443433442124111112311 311312213323313332331111342422441335255544255533622536525426325635454556233265652646556652264344664363441313232433113353213111311112332132131 212322231122222112122432215115412133452444143534343236642464362242254462346523633246526625322335356435211312122232452444222133334414213221113 121221313222313433332143242344531312422454351362665223243633332665344332342636353543543423256355435554115254431122425211324233313242312232111 223221132233331323111144312125545255234555545132336362242365466543245433652666455322542425323335251452515243245532544124442343122333331333321 123222322233243112214113133123524333145353344253232643624253565332666444256556343643323223636624214313113234353353412132443232224331221321323 112223231132232214112441124433412223131511441332144236555624533625326635255544253436325565225422351433334314423411343224222323242312111312133 211131221333311111213411432341224154123123133213515431566564646662444222522324253444522622244144454154425142324341144331421244443223213213232 222111122132232224442324344124122123145224125132335155435126345534565663625452325465323554352221224252232244354223233123243143132312331212232 222133212113123231111224134212122153524554333333545213311153115535525423242642442243225422214244542445413325424323323121312422322132222332312 222123213213213232321331324114422443445312325135244243412455434334354311235235431455431554343125142511555353431333143213323143311121132322311 211213333322113111322243441224441224331423432342354253312145451242413254113552255541333211122424333322523224332234331241223323323322333212221 211112231331213122221322142211314421423152552133251424314431245455332235144212425512331213434225534511323334233142443124423132222322322222121 212122111211312312131311212444422113421122214351134125323221441453341253521324413552232513235135452552141234211333233413213333331112111112211 111211211233232221231332234241143232142124231314152232241153452525451125324423425353544334544233125321313124222331431212222231121213322221221 121211112132133312113121214332221431322243421112211153533111512234544332113252332432432345454334113213213231341443334233123121231132132122112 111222121232211113231212313332413312441232221142313113334242353313211241554252255321445435111412223321342124431124242322212121111113121121121 222121122221132313332132311231324312421333341214231343251244511153233344424212224145455513442444314313441334222211132131211221133322212122212 ================================================ FILE: exm/aoc/2023/aoc_2023_17_questions.txt ================================================ --- Day 17: Clumsy Crucible --- The lava starts flowing rapidly once the Lava Production Facility is operational. As you leave, the reindeer offers you a parachute, allowing you to quickly reach Gear Island. As you descend, your bird's-eye view of Gear Island reveals why you had trouble finding anyone on your way up: half of Gear Island is empty, but the half below you is a giant factory city! You land near the gradually-filling pool of lava at the base of your new lavafall. Lavaducts will eventually carry the lava throughout the city, but to make use of it immediately, Elves are loading it into large crucibles on wheels. The crucibles are top-heavy and pushed by hand. Unfortunately, the crucibles become very difficult to steer at high speeds, and so it can be hard to go in a straight line for very long. To get Desert Island the machine parts it needs as soon as possible, you'll need to find the best way to get the crucible from the lava pool to the machine parts factory. To do this, you need to minimize heat loss while choosing a route that doesn't require the crucible to go in a straight line for too long. Fortunately, the Elves here have a map (your puzzle input) that uses traffic patterns, ambient temperature, and hundreds of other parameters to calculate exactly how much heat loss can be expected for a crucible entering any particular city block. For example: 2413432311323 3215453535623 3255245654254 3446585845452 4546657867536 1438598798454 4457876987766 3637877979653 4654967986887 4564679986453 1224686865563 2546548887735 4322674655533 Each city block is marked by a single digit that represents the amount of heat loss if the crucible enters that block. The starting point, the lava pool, is the top-left city block; the destination, the machine parts factory, is the bottom-right city block. (Because you already start in the top-left block, you don't incur that block's heat loss unless you leave that block and then return to it.) Because it is difficult to keep the top-heavy crucible going in a straight line for very long, it can move at most three blocks in a single direction before it must turn 90 degrees left or right. The crucible also can't reverse direction; after entering each city block, it may only turn left, continue straight, or turn right. One way to minimize heat loss is this path: 2>>34^>>>1323 32v>>>35v5623 32552456v>>54 3446585845v52 4546657867v>6 14385987984v4 44578769877v6 36378779796v> 465496798688v 456467998645v 12246868655 This path never moves more than three consecutive blocks in the same direction and incurs a heat loss of only 102. Directing the crucible from the lava pool to the machine parts factory, but not moving more than three consecutive blocks in the same direction, what is the least heat loss it can incur? --- Part Two --- The crucibles of lava simply aren't large enough to provide an adequate supply of lava to the machine parts factory. Instead, the Elves are going to upgrade to ultra crucibles. Ultra crucibles are even more difficult to steer than normal crucibles. Not only do they have trouble going in a straight line, but they also have trouble turning! Once an ultra crucible starts moving in a direction, it needs to move a minimum of four blocks in that direction before it can turn (or even before it can stop at the end). However, it will eventually start to get wobbly: an ultra crucible can move a maximum of ten consecutive blocks without turning. In the above example, an ultra crucible could follow this path to minimize heat loss: 2>>>>>>>>1323 32154535v5623 32552456v4254 34465858v5452 45466578v>>>> 143859879845v 445787698776v 363787797965v 465496798688v 456467998645v 122468686556v 254654888773v 432267465553v In the above example, an ultra crucible would incur the minimum possible heat loss of 94. Here's another example: 111111111111 999999999991 999999999991 999999999991 999999999991 Sadly, an ultra crucible would need to take an unfortunate path like this one: 1>>>>>>>1111 9999999v9991 9999999v9991 9999999v9991 9999999v>>>> This route causes the ultra crucible to incur the minimum possible heat loss of 71. Directing the ultra crucible from the lava pool to the machine parts factory, what is the least heat loss it can incur? ================================================ FILE: exm/aoc/2023/aoc_2023_18.adb ================================================ -- Solution to Advent of Code 2023, Day 18 ------------------------------------------- -- Lavaduct Lagoon -- -- https://adventofcode.com/2023/day/18 -- Copy of questions in: aoc_2023_18_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_18 is use AoC_Toolbox, HAT, Interfaces; verbose : constant Boolean := False; -- input_name : constant VString := +"mini"; n : constant := 22; start_1 : constant := 2; input_name : constant VString := +"aoc_2023_18"; n : constant := 822; start_1 : constant := 250; -- type State is (clean, path, inside, outside); map : array (1 .. n, 1 .. n) of State; procedure Clean_Map is begin for y in 1 .. n loop for x in 1 .. n loop map (x, y) := clean; end loop; end loop; end Clean_Map; procedure Read_Data_Part_1 is c : Character; i : Integer; f : File_Type; pt : Point; begin Clean_Map; pt.x := start_1; pt.y := start_1; Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get (f, c); Get (f, i); for count in 1 .. i loop map (pt.x, pt.y) := path; case c is when 'U' => pt.y := pt.y - 1; when 'D' => pt.y := pt.y + 1; when 'L' => pt.x := pt.x - 1; when 'R' => pt.x := pt.x + 1; when others => null; end case; end loop; Skip_Line (f); end loop; Close (f); end Read_Data_Part_1; type Vector_Values is array (1 .. n) of Integer; type Ordered_Vector is record top : Natural; val : Vector_Values; end record; procedure Insert (v : in out Ordered_Vector; value : Integer) is ins : Positive; found : Boolean := False; begin for i in 1 .. v.top loop if v.val (i) = value then found := True; exit; end if; end loop; if not found then ins := v.top + 1; for i in 1 .. v.top loop if v.val (i) > value then ins := i; exit; end if; end loop; for i in reverse ins .. v.top loop v.val (i + 1) := v.val (i); end loop; v.val (ins) := value; v.top := v.top + 1; end if; end Insert; procedure Find (v : in out Ordered_Vector; -- ^ "out" is not needed, we just force -- a by-reference parameter passing on HAC. value : Integer; index : out Positive) is begin for i in 1 .. v.top loop if v.val (i) = value then index := i; return; end if; end loop; index := Integer'Last; end Find; trx, try : Ordered_Vector; procedure Read_Data_Part_2 is c : Character; sep : String (1 .. 2); dummy, i, j, x1, x2, y1, y2 : Integer; f : File_Type; s : VString; old_pt, new_pt : Point; begin Clean_Map; new_pt.x := 0; new_pt.y := 0; old_pt := new_pt; trx.top := 0; try.top := 0; -- Register start point (coordinates: 0,0). -- We need some detailed pixellisation around each point. for dxy in -1 .. +1 loop Insert (trx, dxy); Insert (try, dxy); end loop; Passes : for pass in 1 .. 2 loop Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get (f, c); Get (f, dummy); Get (f, sep); Get_Line (f, s); Delete (s, 8, 8); i := Integer_Value (+"16" & s & '#'); -- Read hexadecimal part. j := i / 16; case i rem 16 is when 0 => new_pt.x := new_pt.x + j; -- Right when 1 => new_pt.y := new_pt.y + j; -- Down when 2 => new_pt.x := new_pt.x - j; -- Left when 3 => new_pt.y := new_pt.y - j; -- Up when others => null; end case; if pass = 1 then -- Register a point (if it is a new point). for dxy in -1 .. +1 loop Insert (trx, new_pt.x + dxy); Insert (try, new_pt.y + dxy); end loop; else -- Draw a line in the index map if new_pt.y = old_pt.y then -- Horizontal Find (trx, old_pt.x, x1); Find (trx, new_pt.x, x2); Find (try, new_pt.y, y1); for x12 in Min (x1, x2) .. Max (x1, x2) loop map (x12, y1) := path; end loop; else -- Vertical Find (trx, new_pt.x, x1); Find (try, old_pt.y, y1); Find (try, new_pt.y, y2); for y12 in Min (y1, y2) .. Max (y1, y2) loop map (x1, y12) := path; end loop; end if; -- old_pt := new_pt; end if; end loop; Close (f); end loop Passes; if verbose then Put_Line (+"TRX " & trx.top); for tx in 1 .. trx.top loop Put_Line (trx.val (tx)); end loop; Put_Line (+"TRY " & try.top); for ty in 1 .. try.top loop Put_Line (try.val (ty)); end loop; end if; end Read_Data_Part_2; procedure Show is trunc_n : constant Integer := Min (70, n); begin Put_Line ("Map: -------------------"); for y in 1 .. trunc_n loop for x in 1 .. trunc_n loop case map (x, y) is when clean => Put ('.'); when path => Put ('#'); when outside => Put ('o'); when inside => Put ('i'); end case; end loop; New_Line; end loop; end Show; r : array (Part_Type) of Integer_64; procedure Do_Part (p : Part_Type) is c : Integer_64 := 0; procedure Flood_Fill (x, y : Integer) is -- Taken from aoc_2023_10. begin if x in 1 .. n and then y in 1 .. n and then map (x, y) = clean then map (x, y) := outside; c := c + 1; Flood_Fill (x - 1, y); Flood_Fill (x + 1, y); Flood_Fill (x, y - 1); Flood_Fill (x, y + 1); end if; end Flood_Fill; width, height : array (1 .. n) of Positive; begin if verbose then Put_Line ("Part " & p'Image); Show; end if; Flood_Fill (1, 1); if verbose then Show; end if; case p is when part_1 => r (p) := Integer_64 (n * n - c); when part_2 => -- We need to compute the "real" surfaces c := 0; for ix in 1 .. trx.top loop if ix = trx.top then -- Last "big pixel" has width 1 (a decision) width (ix) := 1; else width (ix) := trx.val (ix + 1) - trx.val (ix); end if; end loop; for iy in 1 .. try.top loop if iy = try.top then -- Last "big pixel" has height 1 (a decision) height (iy) := 1; else height (iy) := try.val (iy + 1) - try.val (iy); end if; end loop; for iy in 1 .. try.top loop for ix in 1 .. trx.top loop if map (ix, iy) = outside then c := c + Integer_64 (width (ix) * height (iy)); end if; end loop; end loop; r (p) := Integer_64 (trx.val (trx.top) - trx.val (1) + 1) * Integer_64 (try.val (try.top) - try.val (1) + 1) - c; end case; end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data_Part_1; Do_Part (part_1); Read_Data_Part_2; Do_Part (part_2); if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 53300 -- Part 2: validated by AoC: 64294334780659 end if; end AoC_2023_18; ================================================ FILE: exm/aoc/2023/aoc_2023_18.txt ================================================ L 6 (#53eec0) U 8 (#02fce3) L 3 (#23fe80) U 5 (#114c73) L 9 (#2d94d2) U 8 (#522163) L 7 (#2d94d0) D 9 (#3170e3) L 10 (#461852) D 4 (#1b4773) L 4 (#31d4f2) U 5 (#126143) L 7 (#810822) U 8 (#1a3e33) L 10 (#7437d2) U 8 (#3cc1c3) L 2 (#19f202) U 7 (#179353) R 6 (#6f6c02) U 9 (#52b813) R 2 (#2dd912) U 5 (#1f3a91) L 8 (#759782) U 6 (#1f3a93) L 3 (#46f342) U 7 (#4af7c3) R 4 (#481352) U 6 (#2fe7c1) R 8 (#5f5c12) U 7 (#2fe7c3) R 9 (#6f6dc2) U 4 (#438993) R 2 (#53c320) U 7 (#3ef223) R 3 (#534410) D 9 (#3ef221) R 7 (#10f8e0) D 9 (#1a8023) R 4 (#202f00) U 8 (#25bc33) R 5 (#7974b0) U 10 (#3c49e3) L 8 (#7974b2) U 4 (#28ee03) L 3 (#1f1182) U 5 (#258013) L 10 (#628bf2) U 2 (#65d2d3) L 4 (#16d082) U 5 (#248833) L 3 (#3fc122) D 5 (#072e53) L 11 (#114cd2) U 2 (#125843) L 3 (#095f22) U 5 (#627533) L 3 (#095f20) U 11 (#3148b3) L 7 (#317ca0) D 11 (#462e83) L 7 (#1e5990) U 6 (#2b0333) L 7 (#41b1e0) D 10 (#615cb3) R 5 (#08d330) D 10 (#79b2a1) R 6 (#3eaff0) D 10 (#105bd1) R 6 (#1daf70) D 7 (#487ff1) L 3 (#4de290) D 3 (#7db061) L 8 (#050970) D 5 (#494181) L 3 (#04ba50) D 3 (#2bbcc1) L 3 (#0ddc20) D 7 (#706f21) L 12 (#48c5d0) U 5 (#78abe3) L 8 (#3915a0) U 5 (#238003) L 3 (#2e0660) U 6 (#357a61) L 5 (#261990) U 7 (#7328a1) L 4 (#05ef52) U 4 (#08ab51) R 9 (#3d0ab2) U 4 (#3fb2d1) R 3 (#4a3642) U 6 (#135301) L 12 (#471722) U 6 (#3f4bd1) L 2 (#471720) U 5 (#460601) L 3 (#4d5e42) U 6 (#128f11) L 10 (#6b4bf0) U 3 (#0f2641) R 6 (#156a00) U 7 (#0f2643) R 6 (#59d890) U 9 (#4a4c61) R 5 (#250590) U 3 (#2f7f33) R 10 (#1506b0) U 9 (#27e5b3) R 6 (#23e040) U 5 (#338fa3) R 5 (#376040) U 6 (#3bb513) R 4 (#55b290) D 6 (#5e2183) R 7 (#3700d0) D 4 (#5d6c13) R 4 (#06baa2) U 10 (#497451) R 6 (#34a832) U 6 (#548e43) R 6 (#1d0420) U 7 (#1d0f63) R 9 (#1d0422) U 3 (#3f0db3) R 3 (#4e46c2) U 9 (#409131) R 7 (#0d0472) U 4 (#1ea4b1) R 5 (#0d0470) U 7 (#517571) R 7 (#37e962) D 6 (#497453) L 2 (#0280b2) D 7 (#0696b3) L 6 (#23e042) D 11 (#2e38c3) R 6 (#1506b2) D 4 (#2f7ad3) R 2 (#138810) D 9 (#0ef623) R 5 (#3f85f0) D 9 (#025be3) R 5 (#5f7582) U 4 (#3ec8c3) R 6 (#1d0ed2) U 7 (#18cf03) R 3 (#7c8450) D 7 (#4270a3) R 6 (#4c3d70) U 3 (#096283) R 10 (#3eb860) U 9 (#123503) R 9 (#36bf60) U 5 (#3a02f3) L 6 (#252a80) U 3 (#09b603) L 7 (#490872) U 4 (#4d1863) L 6 (#4494b2) U 5 (#2c7f23) R 7 (#1995b0) U 7 (#112853) R 4 (#17e290) U 4 (#749f03) R 4 (#3d7b60) U 4 (#85c751) L 12 (#1ea980) U 3 (#291c63) L 2 (#2460f0) U 4 (#6d7e81) R 6 (#052f30) U 12 (#2ed441) R 4 (#8608d0) D 12 (#3821c1) R 4 (#64d260) U 6 (#0ee041) R 2 (#60c110) U 2 (#22b951) R 9 (#118860) D 9 (#4efe01) R 3 (#118862) D 10 (#42fb01) R 7 (#1aacb0) D 8 (#57cb53) L 7 (#666d50) D 10 (#4f10f3) R 5 (#1fd020) D 5 (#1ba6f3) R 5 (#863d72) U 4 (#393123) R 7 (#206020) U 4 (#39ac13) L 7 (#642fe2) U 7 (#1cfa03) R 7 (#642fe0) U 9 (#45acb3) L 7 (#344b20) U 5 (#3fd1e3) R 4 (#475320) U 2 (#85a693) R 3 (#11fee2) U 5 (#830cd3) R 5 (#4d89b2) U 8 (#14bc13) R 7 (#4d89b0) D 4 (#76f4b3) R 12 (#11fee0) D 5 (#664543) L 12 (#1229d2) D 4 (#296263) R 4 (#502192) D 8 (#3b65d1) R 5 (#11aa02) D 7 (#37b981) L 7 (#5c8cc2) D 12 (#1cf031) R 7 (#1a4692) D 4 (#640eb1) R 3 (#105a10) D 8 (#260951) R 2 (#6493b0) D 4 (#03a4b1) L 9 (#5edd52) D 10 (#1b89d1) L 7 (#0b2252) U 7 (#7decf1) L 8 (#0aee22) D 7 (#709b41) L 7 (#5bf6d2) U 5 (#2e8673) L 4 (#340202) D 5 (#8a9631) L 8 (#1ea852) D 7 (#8a9633) R 7 (#38f1e2) D 9 (#076423) R 4 (#06dd12) D 5 (#2c2803) R 3 (#1069f0) D 7 (#676e03) R 12 (#1069f2) D 4 (#419313) R 5 (#5d0a32) D 3 (#1ee113) R 7 (#3a1ce0) D 5 (#7e1e83) R 3 (#19f960) D 6 (#2e97f3) R 6 (#209d20) D 10 (#13dc73) R 3 (#7ad010) D 8 (#3d56a3) R 5 (#0011d2) D 4 (#38a891) R 5 (#356642) D 5 (#065e33) R 7 (#36cea2) D 8 (#065e31) R 7 (#403c22) D 9 (#38a893) L 11 (#389522) U 7 (#506df3) L 9 (#042020) D 7 (#3a1463) L 4 (#841670) D 6 (#1ec383) R 8 (#027ec0) D 10 (#364483) R 4 (#2c21b0) D 4 (#1f7111) L 5 (#44d720) D 6 (#5e4e61) R 5 (#44d722) D 3 (#2a5381) R 4 (#039440) U 9 (#067b53) R 4 (#449850) U 4 (#4314d3) L 4 (#2692f0) U 4 (#4314d1) R 4 (#659580) U 6 (#067b51) R 4 (#3240d0) D 9 (#547a73) R 4 (#598c10) D 7 (#3a8603) R 7 (#5d2660) D 4 (#4c8ea3) L 7 (#4c4f50) D 9 (#08ed81) R 5 (#6ad850) U 4 (#535cc1) R 6 (#1e0c02) U 3 (#6db991) R 3 (#1e0c00) U 3 (#118b41) L 4 (#1f5db0) U 6 (#0f0c11) R 4 (#1015c2) U 6 (#829e11) R 4 (#1015c0) U 3 (#051531) R 7 (#4c4da0) U 9 (#1b2601) R 4 (#129bb0) U 4 (#049701) R 9 (#894f30) U 5 (#46be91) R 6 (#021aa0) U 6 (#1f1831) R 4 (#170ec0) U 9 (#38cfd1) R 5 (#267550) U 3 (#7a31d1) R 6 (#155f60) U 7 (#80dc51) R 7 (#1c20f0) U 5 (#0e9461) R 4 (#498740) D 6 (#01add1) R 4 (#0b8ca0) U 6 (#7e7a41) R 7 (#4ce290) U 4 (#2086e1) L 5 (#4559c0) U 3 (#6bd593) L 10 (#1c0000) U 3 (#6bd591) R 10 (#540970) U 2 (#383a23) L 10 (#185b40) U 5 (#4240b3) L 9 (#520e40) U 4 (#29b043) R 9 (#47f830) U 7 (#43dc53) R 7 (#1f44b2) U 9 (#0ae9f1) R 3 (#602012) U 11 (#0ae9f3) R 5 (#32fcf2) U 6 (#481843) L 3 (#3ae230) U 9 (#283893) L 5 (#21ff10) D 9 (#283891) L 5 (#55b440) U 6 (#480913) L 5 (#383a90) U 8 (#0b1143) L 5 (#3a2930) U 3 (#5ad163) R 11 (#3d20a2) U 2 (#16b3b3) R 12 (#2b20e2) U 4 (#5808a3) L 8 (#0f5990) U 5 (#12c943) R 4 (#58e7f0) U 5 (#1eedf3) R 10 (#7a5930) U 3 (#2ef693) R 10 (#02f430) U 7 (#35b991) R 7 (#4b0e40) D 6 (#35b993) R 10 (#463450) D 8 (#296b13) L 10 (#440580) D 3 (#440183) R 8 (#1b38d0) D 10 (#43e2d3) L 8 (#2e4850) D 5 (#48c283) L 9 (#50a6a0) D 5 (#6adf71) L 8 (#047f02) D 4 (#2db381) R 7 (#6b0ac2) D 6 (#585c51) R 10 (#674822) D 4 (#2ee9d1) R 5 (#25db62) U 11 (#7e8e71) R 5 (#23ae62) D 11 (#3aed01) R 3 (#53ae72) U 4 (#0d2571) R 3 (#476c40) D 7 (#2143e1) L 6 (#7cbb22) D 2 (#311da1) L 7 (#7cbb20) D 6 (#38fed1) L 5 (#476c42) U 6 (#1a2e71) L 5 (#583fb2) D 2 (#2eff51) L 3 (#48a100) D 11 (#1426e1) L 6 (#2b2c40) D 2 (#535e31) L 8 (#1bcf60) D 12 (#5d2851) R 4 (#4f14c0) D 11 (#062bf1) R 7 (#047222) D 7 (#449c11) R 3 (#52dd12) D 6 (#538d13) L 7 (#490b82) D 8 (#538d11) R 3 (#0b68e2) D 8 (#449c13) L 4 (#32edd2) U 2 (#067f81) L 5 (#12ce72) U 13 (#259801) L 4 (#2650f2) D 5 (#29bdd3) L 3 (#7cee92) D 10 (#29bdd1) L 3 (#2f78c2) D 8 (#7b1753) R 6 (#46fad2) D 11 (#7b1751) R 6 (#170562) U 11 (#2119f1) R 5 (#11ae82) D 6 (#814a91) R 2 (#0fc390) D 3 (#5e3f21) R 10 (#043cc0) D 7 (#2ae8a1) R 4 (#3eabd0) D 7 (#33eb71) L 13 (#67bbb0) D 6 (#5345d1) R 13 (#06ba30) D 3 (#762c81) L 5 (#25ef60) D 6 (#170e13) L 10 (#58aaf0) D 6 (#170e11) L 3 (#5a3550) D 7 (#695e01) L 4 (#138370) U 8 (#0eab11) L 5 (#359090) D 8 (#3e2791) L 7 (#359092) D 8 (#4526c1) R 6 (#335fb0) D 3 (#259813) R 7 (#7123d0) U 5 (#0efb81) R 5 (#6245d2) D 5 (#56cc91) R 4 (#384f62) D 5 (#1bf021) R 6 (#145fe0) U 8 (#01c6b1) R 6 (#1617c0) D 10 (#4832e1) L 3 (#701d90) D 6 (#0cf2a1) L 3 (#2bcf40) D 3 (#19b033) L 7 (#1302b2) D 12 (#6761e3) L 7 (#1302b0) U 12 (#579253) L 3 (#482030) D 8 (#259811) L 8 (#5b9720) D 9 (#495741) L 6 (#443092) D 6 (#53ea41) L 5 (#1d2d22) U 6 (#28fe21) L 5 (#079352) D 5 (#3e1a71) L 3 (#8ab872) D 4 (#169531) L 10 (#093742) D 5 (#53cfc1) L 6 (#394902) D 5 (#031c71) R 9 (#042602) D 10 (#386101) R 4 (#095682) D 6 (#272ac1) R 10 (#56c552) D 4 (#4b7e91) R 12 (#4f5732) D 9 (#19ec31) L 3 (#371552) U 6 (#361081) L 6 (#22fc02) D 6 (#57bc91) L 7 (#3d2182) D 7 (#094ef3) L 6 (#018e22) D 8 (#529c93) L 7 (#018e20) D 9 (#31e193) L 2 (#0f3a52) D 12 (#32ff41) L 5 (#5b0fb2) D 3 (#5d51c1) L 6 (#13b1a2) D 5 (#374ec1) L 13 (#3b9e72) D 4 (#174083) L 12 (#1dd322) D 5 (#7d6003) L 9 (#1acb22) D 4 (#4aade3) L 10 (#4de282) D 5 (#23a8e3) R 4 (#676a62) D 3 (#4b56c1) R 5 (#83d302) D 7 (#230001) R 6 (#017252) D 6 (#32ff43) L 2 (#08e202) D 4 (#09c633) L 13 (#206970) D 7 (#7c3473) L 8 (#206972) D 7 (#057673) L 11 (#1b1d72) U 10 (#61afe1) L 2 (#5608c2) U 2 (#616c21) L 4 (#3c0562) U 7 (#616c23) L 6 (#530aa2) D 6 (#3cc191) L 3 (#086e42) U 6 (#3f6001) L 5 (#115072) U 3 (#689eb1) L 7 (#444cf0) U 11 (#32b1e1) L 7 (#444cf2) U 7 (#38d3d1) L 4 (#22f312) U 5 (#623d73) R 4 (#38b942) U 4 (#4333a3) L 5 (#0ca750) U 2 (#32b8a3) L 8 (#151332) U 10 (#3dd1e1) L 4 (#4de562) U 2 (#574101) L 5 (#26c592) U 2 (#116471) L 7 (#0bb092) U 13 (#07dff3) R 3 (#45c262) U 4 (#5a4843) R 7 (#45c260) U 10 (#444f23) R 6 (#12fd52) U 4 (#36d293) L 8 (#528cf0) U 9 (#1e3a43) R 5 (#55df10) U 3 (#3c4b53) R 2 (#0ca752) U 10 (#23b003) R 7 (#38b940) D 2 (#24c403) R 6 (#41b532) D 7 (#0d07a3) R 7 (#4893c2) D 8 (#7ded93) R 9 (#288282) D 5 (#1d4c71) R 2 (#441c82) D 3 (#6da8c1) L 6 (#209002) D 5 (#1bdfe1) L 8 (#42a410) D 4 (#48f551) R 4 (#42a412) D 9 (#269be1) R 7 (#4572f2) U 9 (#8452c3) R 3 (#077832) D 6 (#3b4b83) R 2 (#5137e2) D 4 (#4bca13) R 10 (#46aee2) U 7 (#1c3673) R 4 (#1f3030) U 7 (#0196f3) L 4 (#5d0f30) U 2 (#5fe723) L 9 (#17aa10) U 7 (#0fcb63) R 13 (#03fd50) U 3 (#0138a3) L 4 (#064d42) U 4 (#008751) R 5 (#37ea32) U 3 (#4ff661) R 13 (#51faf2) U 6 (#0ef911) L 3 (#14c232) U 6 (#4c22b1) L 7 (#099d22) D 6 (#5625d1) L 8 (#42ee42) U 5 (#1c4a71) R 5 (#40d180) U 5 (#041b51) L 5 (#386ed0) U 8 (#041b53) L 5 (#15c0f0) U 8 (#436731) L 9 (#0b8222) U 4 (#31f073) L 13 (#7b1c72) U 8 (#31f071) L 7 (#0862b2) U 5 (#34f5d1) L 8 (#2c0f82) U 2 (#03ba21) L 6 (#493052) U 12 (#319093) L 7 (#240372) U 8 (#7053e3) L 4 (#2a5bf2) U 6 (#296e63) ================================================ FILE: exm/aoc/2023/aoc_2023_18_questions.txt ================================================ --- Day 18: Lavaduct Lagoon --- Thanks to your efforts, the machine parts factory is one of the first factories up and running since the lavafall came back. However, to catch up with the large backlog of parts requests, the factory will also need a large supply of lava for a while; the Elves have already started creating a large lagoon nearby for this purpose. However, they aren't sure the lagoon will be big enough; they've asked you to take a look at the dig plan (your puzzle input). For example: R 6 (#70c710) D 5 (#0dc571) L 2 (#5713f0) D 2 (#d2c081) R 2 (#59c680) D 2 (#411b91) L 5 (#8ceee2) U 2 (#caa173) L 1 (#1b58a2) U 2 (#caa171) R 2 (#7807d2) U 3 (#a77fa3) L 2 (#015232) U 2 (#7a21e3) The digger starts in a 1 meter cube hole in the ground. They then dig the specified number of meters up (U), down (D), left (L), or right (R), clearing full 1 meter cubes as they go. The directions are given as seen from above, so if "up" were north, then "right" would be east, and so on. Each trench is also listed with the color that the edge of the trench should be painted as an RGB hexadecimal color code. When viewed from above, the above example dig plan would result in the following loop of trench (#) having been dug out from otherwise ground-level terrain (.): ####### #.....# ###...# ..#...# ..#...# ###.### #...#.. ##..### .#....# .###### At this point, the trench could contain 38 cubic meters of lava. However, this is just the edge of the lagoon; the next step is to dig out the interior so that it is one meter deep as well: ####### ####### ####### ..##### ..##### ####### #####.. ####### .###### .###### Now, the lagoon can contain a much more respectable 62 cubic meters of lava. While the interior is dug out, the edges are also painted according to the color codes in the dig plan. The Elves are concerned the lagoon won't be large enough; if they follow their dig plan, how many cubic meters of lava could it hold? --- Part Two --- The Elves were right to be concerned; the planned lagoon would be much too small. After a few minutes, someone realizes what happened; someone swapped the color and instruction parameters when producing the dig plan. They don't have time to fix the bug; one of them asks if you can extract the correct instructions from the hexadecimal codes. Each hexadecimal code is six hexadecimal digits long. The first five hexadecimal digits encode the distance in meters as a five-digit hexadecimal number. The last hexadecimal digit encodes the direction to dig: 0 means R, 1 means D, 2 means L, and 3 means U. So, in the above example, the hexadecimal codes can be converted into the true instructions: #70c710 = R 461937 #0dc571 = D 56407 #5713f0 = R 356671 #d2c081 = D 863240 #59c680 = R 367720 #411b91 = D 266681 #8ceee2 = L 577262 #caa173 = U 829975 #1b58a2 = L 112010 #caa171 = D 829975 #7807d2 = L 491645 #a77fa3 = U 686074 #015232 = L 5411 #7a21e3 = U 500254 Digging out this loop and its interior produces a lagoon that can hold an impressive 952408144115 cubic meters of lava. Convert the hexadecimal color codes into the correct instructions; if the Elves follow this new dig plan, how many cubic meters of lava could the lagoon hold? ================================================ FILE: exm/aoc/2023/aoc_2023_19.adb ================================================ -- Solution to Advent of Code 2023, Day 19 ------------------------------------------- -- Aplenty -- -- https://adventofcode.com/2023/day/19 -- Copy of questions in: aoc_2023_19_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_19 is use AoC_Toolbox, HAT, Interfaces; x, m, a, s : Integer; ok : Boolean; procedure AA is begin ok := True; end AA; procedure RR is begin ok := False; end RR; -- pragma Style_Checks (Off); -- In this day's puzzle, the data is actually a program of -- a Binary Space Partition. -- We have turned XMAS programs into Ada programs using -- Regexp replacements. -- Note the possible simplifications (could be done several times): -- if [cond] then AA; else AA; -> AA -- if [cond] then RR; else RR; -> RR -- -- The "Mini" program (the example shown with the questions): -- procedure m_qkq; procedure m_rfg; procedure m_gd; procedure m_crn; procedure m_qqz; procedure m_hdj; procedure m_px is begin if a < 2006 then m_qkq; elsif m > 2090 then AA; else m_rfg; end if; end; procedure m_pv is begin if a > 1716 then RR; else AA; end if; end; procedure m_lnx is begin if m > 1548 then AA; else AA; end if; end; -- m_lnx = AA procedure m_rfg is begin if s < 537 then m_gd; elsif x > 2440 then RR; else AA; end if; end; procedure m_qs is begin if s > 3448 then AA; else m_lnx; end if; end; -- m_qs = AA procedure m_qkq is begin if x < 1416 then AA; else m_crn; end if; end; procedure m_crn is begin if x > 2662 then AA; else RR; end if; end; procedure m_in is begin if s < 1351 then m_px; else m_qqz; end if; end; procedure m_qqz is begin if s > 2770 then m_qs; elsif m < 1801 then m_hdj; else RR; end if; end; procedure m_gd is begin if a > 3333 then RR; else RR; end if; end; -- m_gd = RR procedure m_hdj is begin if m > 838 then AA; else m_pv; end if; end; -- -- The "Input" program: -- procedure px; procedure sv; procedure lhx; procedure jg; procedure jhd; procedure mhd; procedure bn; procedure bz; procedure dmc; procedure tgt; procedure vb; procedure vtt; procedure fs; procedure rct; procedure sgr; procedure tc; procedure dh; procedure ncl; procedure pbx; procedure xzk; procedure mls; procedure mcm; procedure gqc; procedure tfs; procedure zg; procedure vqn; procedure pkf; procedure hx; procedure mk; procedure xvn; procedure nsd; procedure ft; procedure cng; procedure tkj; procedure mlj; procedure rmb; procedure qkz; procedure mt; procedure gkl; procedure khv; procedure gx; procedure kkc; procedure qcb; procedure zmn; procedure cbv; procedure qnj; procedure lsz; procedure hcp; procedure ntl; procedure crk; procedure rlz; procedure lj; procedure bnz; procedure tv; procedure qrp; procedure blf; procedure xrc; procedure nr; procedure jld; procedure nk; procedure rgl; procedure rl; procedure bjq; procedure bxb; procedure ksl; procedure qzz; procedure xmx; procedure bqt; procedure nx; procedure kfr; procedure rzc; procedure zbv; procedure qds; procedure zz; procedure ctn; procedure mv; procedure pm; procedure vcd; procedure dn; procedure cjf; procedure fcr; procedure kf; procedure zf; procedure npl; procedure hxj; procedure bk; procedure cgf; procedure fj; procedure tvz; procedure ptj; procedure jcf; procedure jf; procedure frc; procedure gkt; procedure lk; procedure cpv; procedure hr; procedure fm; procedure rh; procedure bj; procedure qqj; procedure vs; procedure clk; procedure qrq; procedure blm; procedure bh; procedure qq; procedure pqb; procedure ktn; procedure bxg; procedure ksd; procedure pt; procedure rtk; procedure tck; procedure jzc; procedure csz; procedure qps; procedure lp; procedure blx; procedure ctt; procedure xrp; procedure sm; procedure plc; procedure bnx; procedure dz; procedure fpz; procedure vgq; procedure hrl; procedure kbm; procedure jx; procedure xbr; procedure cz; procedure zh; procedure mx; procedure pz; procedure rt; procedure lbk; procedure cpm; procedure km; procedure qzx; procedure hp; procedure sj; procedure rs; procedure xp; procedure cbr; procedure gcm; procedure kj; procedure lxb; procedure rsn; procedure jbk; procedure zv; procedure jps; procedure mth; procedure mgd; procedure rnh; procedure psj; procedure shf; procedure bgd; procedure mlt; procedure vnq; procedure spg; procedure kqk; procedure zrf; procedure ltl; procedure pk; procedure jct; procedure pbh; procedure bkc; procedure lmm; procedure jjm; procedure td; procedure mdn; procedure st; procedure sts; procedure pr; procedure ds; procedure dmp; procedure nst; procedure szs; procedure zs; procedure vp; procedure dl; procedure lb; procedure kl; procedure hlx; procedure hz; procedure lv; procedure qs; procedure mpf; procedure dm; procedure vq; procedure rrx; procedure hxg; procedure pj; procedure gjs; procedure rk; procedure gr; procedure zlr; procedure qzq; procedure qb; procedure jkl; procedure kd; procedure ztq; procedure vtl; procedure tj; procedure dhp; procedure jv; procedure pjd; procedure fh; procedure gf; procedure cnb; procedure rjs; procedure sl; procedure dd; procedure hl; procedure zc; procedure jhv; procedure rjx; procedure bp; procedure rj; procedure mmc; procedure jzr; procedure hj; procedure lpx; procedure hxs; procedure xv; procedure pfl; procedure vjn; procedure gdk; procedure ljv; procedure rf; procedure zpb; procedure xgr; procedure ln; procedure fg; procedure kq; procedure mln; procedure sjq; procedure rpm; procedure jc; procedure lvq; procedure cc; procedure kxk; procedure lzl; procedure sh; procedure pzx; procedure mrc; procedure sx; procedure jmf; procedure hs; procedure ljn; procedure mq; procedure gc; procedure zjx; procedure kqb; procedure xr; procedure kct; procedure vn; procedure bvg; procedure tzr; procedure ghp; procedure ljh; procedure ttc; procedure hmd; procedure tb; procedure skm; procedure bmk; procedure frf; procedure qzr; procedure xxd; procedure nvs; procedure sbd; procedure sbh; procedure kmc; procedure ks; procedure dxl; procedure lbl; procedure mbj; procedure jsn; procedure qjg; procedure tq; procedure qnp; procedure gnb; procedure xq; procedure ddr; procedure nl; procedure bgz; procedure gj; procedure nzb; procedure gg; procedure lcg; procedure gq; procedure zx; procedure jcs; procedure sdm; procedure btg; procedure rq; procedure fpj; procedure vd; procedure nxf; procedure rhb; procedure qv; procedure hv; procedure ttv; procedure nv; procedure cgx; procedure mz; procedure jnn; procedure vf; procedure gfk; procedure dcg; procedure mp; procedure mg; procedure hzc; procedure nc; procedure vlr; procedure xkx; procedure bb; procedure nh; procedure gmg; procedure cl; procedure xkb; procedure cbb; procedure fr; procedure mh; procedure cv; procedure dcz; procedure vcn; procedure kqs; procedure mcq; procedure hxt; procedure ld; procedure xs; procedure mfn; procedure qfs; procedure nd; procedure jjc; procedure gtq; procedure xf; procedure zgv; procedure dgf; procedure xg; procedure tzv; procedure nt; procedure gbv; procedure qmm; procedure cr; procedure gxs; procedure ctq; procedure mfh; procedure ff; procedure ggb; procedure jkf; procedure bls; procedure czg; procedure sxz; procedure vdv; procedure nsx; procedure gd; procedure vnp; procedure dtc; procedure glj; procedure qt; procedure qvc; procedure ctb; procedure xz; procedure lg; procedure lpq; procedure jhh; procedure mqj; procedure fnv; procedure zfm; procedure vsx; procedure csr; procedure mhf; procedure vc; procedure qnv; procedure cm; procedure jhl; procedure sq; procedure hvz; procedure tr; procedure cgv; procedure ps; procedure rm; procedure qp; procedure qj; procedure qr; procedure cql; procedure fvp; procedure tn; procedure fl; procedure vv; procedure lr; procedure xhx; procedure jzm; procedure tlj; procedure xk; procedure zk; procedure zn; procedure ggh; procedure ht; procedure jbl; procedure vfk; procedure qdz; procedure ll; procedure vbp; procedure rhg; procedure inn; procedure bv; procedure zgx; procedure cfj; procedure mr; procedure bf; procedure rtg; procedure qcr; procedure xnv; procedure nlp; procedure tg; procedure tnp; procedure slq; procedure fz; procedure rgz; procedure rg; procedure nm; procedure mdc; procedure pbt; procedure dbl; procedure cn; procedure hb; procedure nls; procedure tl; procedure mml; procedure dtm; procedure pf; procedure jh; procedure sg; procedure sp; procedure cj; procedure dfh; procedure lm; procedure pp; procedure ddf; procedure mn; procedure hc; procedure lgt; procedure pmb; procedure bq; procedure dj; procedure lz; procedure hml; procedure ckz; procedure vh; procedure rc; procedure zm; procedure jhs; procedure hhd; procedure zds; procedure zd; procedure fzf is begin if m<1642 then AA; else px; end if; end; procedure qqp is begin if s>3732 then RR; elsif m>946 then RR; elsif a<1401 then AA; else AA; end if; end; procedure mqh is begin if x>1081 then AA; elsif m<3344 then RR; elsif m>3632 then RR; else AA; end if; end; procedure bnk is begin if a>2841 then RR; elsif s<3562 then RR; elsif x>3483 then AA; else AA; end if; end; procedure jt is begin if a>3076 then AA; elsif s<2748 then AA; elsif s>2805 then RR; else AA; end if; end; procedure vl is begin if x>2613 then sv; elsif a>2454 then lhx; else jg; end if; end; procedure bhj is begin if x>2768 then jhd; else mhd; end if; end; procedure ggs is begin if x>3053 then RR; elsif x>2848 then RR; else RR; end if; end; procedure lx is begin if a>3685 then AA; else bn; end if; end; procedure hcz is begin if x>763 then RR; elsif s<2753 then AA; else RR; end if; end; procedure mnr is begin if x>1157 then RR; else RR; end if; end; procedure cpd is begin if a<320 then AA; elsif m>1387 then bz; else AA; end if; end; procedure lbm is begin if s<3387 then RR; elsif s>3672 then RR; elsif a<3818 then RR; else AA; end if; end; procedure npb is begin if a<1149 then dmc; else tgt; end if; end; procedure bsh is begin if x<1228 then RR; else RR; end if; end; procedure px is begin if x>1003 then AA; elsif a>3750 then AA; else AA; end if; end; procedure jl is begin if a<1881 then RR; elsif m>1146 then RR; elsif s<400 then AA; else RR; end if; end; procedure cs is begin if s<3185 then AA; else AA; end if; end; procedure krx is begin if x<3153 then AA; elsif a<2570 then RR; else AA; end if; end; procedure dp is begin if a>3221 then AA; else AA; end if; end; procedure zxh is begin if s<2883 then RR; else vb; end if; end; procedure dtj is begin if x<1574 then AA; elsif m<961 then AA; elsif m>1183 then RR; else RR; end if; end; procedure mhd is begin if a<2806 then vtt; else RR; end if; end; procedure mll is begin if s<2589 then fs; else rct; end if; end; procedure nbf is begin if x<2665 then sgr; else AA; end if; end; procedure jr is begin if a>3301 then tc; elsif x>996 then dh; elsif a>2980 then ncl; else AA; end if; end; procedure lxc is begin if x<1450 then RR; elsif m>899 then AA; elsif x>1653 then AA; else RR; end if; end; procedure xfp is begin if a>586 then pbx; else xzk; end if; end; procedure crf is begin if s>3081 then RR; elsif a>1253 then AA; elsif s<2740 then RR; else AA; end if; end; procedure mc is begin if a<330 then AA; elsif a>440 then AA; elsif x>2613 then RR; else AA; end if; end; procedure lcl is begin if m>1452 then mls; else RR; end if; end; procedure scv is begin if a>653 then RR; elsif a<385 then AA; elsif s>2291 then mcm; else AA; end if; end; procedure jg is begin if m>2877 then gqc; elsif a>2247 then RR; else AA; end if; end; procedure kbt is begin if a<75 then AA; elsif x>3256 then RR; elsif a>137 then AA; else RR; end if; end; procedure cmf is begin if m<795 then RR; else AA; end if; end; procedure zxc is begin if a<1971 then AA; elsif a>2270 then RR; else AA; end if; end; procedure lms is begin if s>323 then tfs; else AA; end if; end; procedure mgs is begin if x<2480 then AA; elsif a<1050 then AA; else RR; end if; end; procedure kz is begin if s<3266 then zg; elsif a<2977 then AA; else vqn; end if; end; procedure lh is begin if x>1958 then pkf; elsif m>3511 then hx; else mk; end if; end; procedure db is begin if m<1657 then xvn; else nsd; end if; end; procedure gbg is begin if m<1371 then AA; elsif x>3428 then AA; elsif s<3077 then AA; else RR; end if; end; procedure gz is begin if s<3104 then AA; elsif m<2828 then AA; elsif m>3281 then RR; else RR; end if; end; procedure hpl is begin if a>3117 then AA; else ft; end if; end; procedure zg is begin if x<1698 then RR; else RR; end if; end; procedure vqv is begin if a>1031 then AA; elsif x>2460 then AA; elsif x<1912 then AA; else RR; end if; end; procedure vb is begin if m<1499 then AA; elsif x>1894 then RR; else RR; end if; end; procedure xkq is begin if s<1553 then cng; elsif s<3162 then tkj; else mlj; end if; end; procedure ngz is begin if a<3373 then AA; elsif s>402 then AA; elsif s>204 then AA; else AA; end if; end; procedure dq is begin if m<801 then rmb; elsif a<2127 then AA; else RR; end if; end; procedure kh is begin if x>1408 then AA; else AA; end if; end; procedure jfk is begin if a>1219 then qkz; elsif s<1492 then mt; elsif m<2952 then gkl; else khv; end if; end; procedure pl is begin if s>3123 then RR; else AA; end if; end; procedure tdg is begin if a>1983 then AA; elsif a<1853 then gx; elsif x>1678 then kkc; else qcb; end if; end; procedure nlk is begin if a<2055 then RR; else zmn; end if; end; procedure sxc is begin if s<1553 then RR; else RR; end if; end; procedure nzx is begin if a<2569 then AA; elsif x<1812 then cbv; else AA; end if; end; procedure cph is begin if m<2856 then AA; else AA; end if; end; procedure pxx is begin if x<3670 then qnj; elsif m<3015 then RR; elsif a<3243 then RR; else AA; end if; end; procedure bnz is begin if a<949 then lsz; elsif s>1899 then hcp; elsif s>1631 then AA; else ntl; end if; end; procedure tv is begin if m<1352 then RR; elsif m<1812 then AA; else RR; end if; end; procedure qkz is begin if a<2141 then crk; elsif x<1866 then rlz; else vl; end if; end; procedure qrp is begin if a>3607 then RR; elsif m<2423 then lj; else qqj; end if; end; procedure blf is begin if s<1970 then RR; else RR; end if; end; procedure xrc is begin if x<2476 then rjx; elsif a>1724 then tj; else pbt; end if; end; procedure nr is begin if m>2092 then hzc; else AA; end if; end; procedure jld is begin if s<1570 then AA; else ps; end if; end; procedure nk is begin if a<3132 then RR; else RR; end if; end; procedure rgl is begin if a<2558 then AA; else RR; end if; end; procedure rl is begin if a<1021 then AA; else RR; end if; end; procedure bjq is begin if s<2821 then RR; elsif s<2872 then AA; else RR; end if; end; procedure qnj is begin if s>1202 then RR; elsif s>488 then RR; else RR; end if; end; procedure bxb is begin if m<911 then AA; elsif x>468 then bnx; elsif s>3663 then RR; else RR; end if; end; procedure ksl is begin if x<688 then AA; elsif x>1068 then AA; else RR; end if; end; procedure qzz is begin if a>1963 then sdm; elsif s<1753 then RR; else cgx; end if; end; procedure xmx is begin if m<1231 then qnv; elsif m>1789 then nsx; elsif s>1698 then xrp; else AA; end if; end; procedure bqt is begin if x>392 then RR; else AA; end if; end; procedure nx is begin if m<3603 then RR; elsif s<2999 then mg; elsif m>3830 then RR; else AA; end if; end; procedure kfr is begin if a<2455 then jf; elsif m>1009 then nzx; elsif x<2605 then cgv; else sm; end if; end; procedure rzc is begin if m<3116 then RR; elsif x>1302 then RR; elsif s<2205 then RR; else shf; end if; end; procedure zbv is begin if m<3299 then RR; elsif x<740 then AA; else RR; end if; end; procedure qds is begin if a<3031 then tg; elsif a<3095 then pp; elsif x>2192 then bf; else cgf; end if; end; procedure zz is begin if m<602 then RR; elsif m>616 then AA; else AA; end if; end; procedure ctn is begin if s<1118 then qvc; else jzc; end if; end; procedure mv is begin if m>3603 then RR; elsif s<1044 then RR; else AA; end if; end; procedure pm is begin if m>2113 then kd; elsif a>278 then AA; else RR; end if; end; procedure vcd is begin if m<1762 then AA; else RR; end if; end; procedure dn is begin if m>2924 then RR; else AA; end if; end; procedure cjf is begin if a<886 then jsn; elsif s>538 then hp; else RR; end if; end; procedure fcr is begin if s>738 then vnp; elsif s>647 then cz; else AA; end if; end; procedure kf is begin if a<2869 then RR; elsif m<1983 then RR; else AA; end if; end; procedure zf is begin if m>1116 then vh; elsif m<741 then ljn; else xz; end if; end; procedure npl is begin if m<604 then RR; elsif x<2557 then AA; elsif s>3273 then AA; else lzl; end if; end; procedure hxj is begin if x>1696 then lgt; else hxt; end if; end; procedure bk is begin if m>2024 then kqk; elsif m>1977 then AA; else AA; end if; end; procedure cgf is begin if m>1839 then mdc; else nk; end if; end; procedure fj is begin if s<3773 then RR; else AA; end if; end; procedure tvz is begin if m<725 then AA; else RR; end if; end; procedure nsd is begin if a>549 then AA; else rm; end if; end; procedure ptj is begin if a>2544 then RR; elsif s<474 then RR; else RR; end if; end; procedure jcf is begin if a>3207 then RR; else RR; end if; end; procedure jf is begin if x>1679 then RR; else hmd; end if; end; procedure frc is begin if a>3423 then RR; elsif s<3574 then RR; else RR; end if; end; procedure fs is begin if s<2535 then RR; elsif s>2554 then RR; elsif s>2547 then RR; else RR; end if; end; procedure gkt is begin if x<3699 then AA; elsif s<1808 then RR; else RR; end if; end; procedure lk is begin if x>1920 then vgq; elsif x<915 then vc; elsif s>911 then dcg; else pjd; end if; end; procedure cpv is begin if s<84 then RR; else AA; end if; end; procedure hr is begin if m>3382 then mdn; elsif x<1457 then cph; else vp; end if; end; procedure fm is begin if x<1347 then kxk; else dl; end if; end; procedure rh is begin if m>1468 then AA; elsif a<3525 then ngz; else RR; end if; end; procedure bj is begin if x>574 then RR; elsif a<2312 then AA; else RR; end if; end; procedure qqj is begin if x>1087 then RR; else AA; end if; end; procedure vs is begin if x>1075 then vcd; elsif m<1978 then jv; else jr; end if; end; procedure clk is begin if x<444 then RR; elsif m<2947 then AA; elsif s<3126 then AA; else AA; end if; end; procedure qrq is begin if s>2012 then RR; elsif a<1950 then AA; else AA; end if; end; procedure blm is begin if m<1460 then rj; elsif m>2331 then pxx; elsif s<1091 then bmk; else kq; end if; end; procedure bh is begin if x>1415 then hj; elsif a>1216 then tr; else cj; end if; end; procedure qq is begin if a<3194 then qdz; else rg; end if; end; procedure pqb is begin if s<3296 then AA; else RR; end if; end; procedure lj is begin if s<3684 then RR; elsif s<3855 then RR; elsif a<3556 then RR; else AA; end if; end; procedure ktn is begin if a>3308 then RR; elsif x>2669 then AA; else AA; end if; end; procedure bxg is begin if a>1442 then AA; elsif a>1347 then AA; else AA; end if; end; procedure ksd is begin if s<3546 then mr; else rhb; end if; end; procedure pt is begin if x<1007 then AA; elsif s<3086 then RR; elsif a<2912 then RR; else RR; end if; end; procedure rtk is begin if a<2468 then AA; elsif s>1601 then AA; else RR; end if; end; procedure tck is begin if a>1635 then tlj; elsif m<329 then xhx; else hc; end if; end; procedure jzc is begin if a<1524 then zrf; elsif m>1067 then pr; elsif x>1870 then bls; else rrx; end if; end; procedure csz is begin if a>762 then bnz; elsif x<3126 then qv; elsif s>1898 then csr; else skm; end if; end; procedure qps is begin if a>615 then cjf; elsif s>671 then pm; elsif s>240 then dbl; else nl; end if; end; procedure lp is begin if x<3084 then AA; elsif s<3733 then AA; else RR; end if; end; procedure blx is begin if m>131 then RR; else RR; end if; end; procedure ctt is begin if a<3522 then nxf; elsif x>1395 then cnb; else jzr; end if; end; procedure xrp is begin if x<574 then RR; elsif m<1446 then RR; else AA; end if; end; procedure sm is begin if m<795 then ptj; elsif m>883 then RR; elsif x<3307 then AA; else sbd; end if; end; procedure plc is begin if x>559 then RR; elsif a>3782 then RR; elsif s>3878 then RR; else AA; end if; end; procedure bnx is begin if m<1013 then AA; else AA; end if; end; procedure dz is begin if s<3377 then RR; elsif m>2092 then RR; else AA; end if; end; procedure fpz is begin if m>695 then tvz; elsif s<3213 then qnp; elsif a<1023 then RR; else RR; end if; end; procedure mcm is begin if a<540 then AA; else RR; end if; end; procedure vgq is begin if x<3260 then xp; else blm; end if; end; procedure hrl is begin if s>571 then fcr; elsif a>3310 then lms; elsif a>3059 then dn; else cc; end if; end; procedure sgr is begin if a<2253 then RR; elsif a>2477 then RR; elsif x>1631 then AA; else RR; end if; end; procedure kbm is begin if a<773 then RR; elsif x<500 then xs; else AA; end if; end; procedure dmc is begin if x>811 then ddf; elsif m>1293 then ckz; else RR; end if; end; procedure jx is begin if x<147 then AA; elsif s<3246 then RR; else AA; end if; end; procedure xbr is begin if s<3780 then AA; else AA; end if; end; procedure cz is begin if m>3005 then AA; elsif x<1279 then AA; else RR; end if; end; procedure zh is begin if m>2724 then RR; else AA; end if; end; procedure mx is begin if a>2368 then RR; elsif s<2360 then RR; elsif x<3285 then AA; else RR; end if; end; procedure pz is begin if x>1619 then AA; elsif a>965 then RR; elsif x<1449 then AA; else RR; end if; end; procedure rt is begin if a>1181 then RR; elsif x>2446 then RR; else AA; end if; end; procedure lbk is begin if a>2730 then fz; else hs; end if; end; procedure cpm is begin if a<3279 then rsn; elsif m<1164 then dcz; elsif x>1415 then mcq; else rh; end if; end; procedure km is begin if m>3737 then AA; elsif a>3725 then RR; else RR; end if; end; procedure qzx is begin if s>1504 then RR; elsif s>1454 then RR; elsif x<415 then AA; else AA; end if; end; procedure hp is begin if x<2493 then RR; elsif s<1127 then AA; else RR; end if; end; procedure sj is begin if m>683 then RR; elsif x<1742 then AA; elsif s<2208 then RR; else AA; end if; end; procedure rs is begin if m<1908 then tnp; elsif x<1393 then RR; else AA; end if; end; procedure xp is begin if m>1774 then ktn; elsif a<3517 then bq; else gj; end if; end; procedure cbr is begin if a>2266 then RR; elsif m<819 then AA; else AA; end if; end; procedure gcm is begin if a<3170 then AA; elsif a<3297 then RR; else RR; end if; end; procedure kj is begin if s>3251 then bnk; elsif x<3524 then AA; else AA; end if; end; procedure lxb is begin if a<536 then AA; elsif a>630 then RR; elsif s<1570 then AA; else RR; end if; end; procedure rsn is begin if m<1293 then RR; else RR; end if; end; procedure jbk is begin if x>3170 then AA; elsif a>1074 then RR; else AA; end if; end; procedure zv is begin if x>2404 then AA; elsif s>457 then jmf; else AA; end if; end; procedure jps is begin if a<593 then RR; else ggb; end if; end; procedure mth is begin if x>3569 then gbv; else ds; end if; end; procedure mgd is begin if s>2772 then RR; elsif x<173 then AA; else AA; end if; end; procedure rnh is begin if x>460 then vn; elsif x>266 then pl; elsif a<2800 then hvz; else RR; end if; end; procedure psj is begin if s<3000 then RR; elsif s<3141 then AA; else RR; end if; end; procedure qcb is begin if x<798 then AA; elsif x>1338 then AA; else AA; end if; end; procedure shf is begin if s<2342 then RR; else AA; end if; end; procedure bgd is begin if m>2415 then nzb; elsif s>3123 then ld; else lcl; end if; end; procedure mlt is begin if s<3301 then AA; elsif m>2092 then RR; else AA; end if; end; procedure vtt is begin if a<2787 then RR; elsif m<1501 then AA; else RR; end if; end; procedure gk is begin if a<815 then AA; elsif s>2886 then RR; else RR; end if; end; procedure vnq is begin if x<655 then AA; elsif s<3763 then RR; else AA; end if; end; procedure spg is begin if a<1477 then RR; else RR; end if; end; procedure kqk is begin if a>986 then RR; else AA; end if; end; procedure zrf is begin if a>904 then gg; elsif m<1153 then ljh; elsif s<1804 then jld; else cpd; end if; end; procedure ltl is begin if x>1025 then mh; elsif a<2706 then mlt; else mq; end if; end; procedure kkc is begin if a<1939 then RR; elsif a>1966 then RR; else AA; end if; end; procedure pk is begin if s<3412 then fzf; elsif a>3726 then hxs; else qrp; end if; end; procedure jct is begin if x>2955 then AA; else czg; end if; end; procedure pbh is begin if a>1099 then AA; else RR; end if; end; procedure bkc is begin if x<994 then RR; else RR; end if; end; procedure lmm is begin if m>3383 then RR; elsif a>2887 then AA; else AA; end if; end; procedure jjm is begin if a>2703 then lbk; else fpj; end if; end; procedure td is begin if x<247 then mpf; elsif s>3739 then tzv; else gf; end if; end; procedure mdn is begin if a<3498 then RR; else RR; end if; end; procedure st is begin if s<3009 then AA; elsif a>1143 then rt; elsif a<1107 then rgz; else qzr; end if; end; procedure sts is begin if a<1200 then RR; elsif m<87 then AA; elsif m>132 then AA; else AA; end if; end; procedure pr is begin if x>2249 then dtm; else qzz; end if; end; procedure ds is begin if s<3752 then AA; else RR; end if; end; procedure dmp is begin if m<3305 then RR; elsif a<463 then AA; elsif m<3681 then cm; else RR; end if; end; procedure sdr is begin if a>3376 then vdv; else zbv; end if; end; procedure nst is begin if s>2046 then cbr; else mfn; end if; end; procedure mk is begin if a<388 then RR; else pmb; end if; end; procedure pkf is begin if s>499 then mv; else AA; end if; end; procedure szs is begin if m<3349 then sq; elsif a>718 then AA; else gc; end if; end; procedure zs is begin if m<2661 then RR; else AA; end if; end; procedure vp is begin if x>1477 then RR; elsif s>2269 then RR; else AA; end if; end; procedure dl is begin if s<1214 then RR; else qp; end if; end; procedure lb is begin if x<3138 then AA; elsif a>2670 then RR; else RR; end if; end; procedure kl is begin if m>3862 then AA; elsif x>1259 then mqj; elsif x<1033 then zn; else blf; end if; end; procedure hlx is begin if a<2205 then RR; elsif x>3579 then AA; elsif s<1636 then AA; else RR; end if; end; procedure hz is begin if x>1358 then AA; elsif x<1311 then RR; else AA; end if; end; procedure lv is begin if s>424 then RR; elsif a>3455 then RR; elsif m>513 then AA; else AA; end if; end; procedure qs is begin if a<3308 then AA; elsif x>723 then RR; else RR; end if; end; procedure gqc is begin if x<2158 then RR; elsif s<1851 then RR; else RR; end if; end; procedure mpf is begin if a>3792 then AA; elsif a>3662 then mml; elsif a>3577 then RR; else xk; end if; end; procedure dm is begin if m>3103 then AA; elsif x<1276 then RR; else AA; end if; end; procedure vq is begin if s>2244 then hz; elsif x>1360 then AA; else AA; end if; end; procedure rrx is begin if s>1629 then nst; elsif s>1413 then xnv; else dq; end if; end; procedure hxg is begin if x<324 then mgd; elsif x<469 then dj; else gr; end if; end; procedure pj is begin if a<3150 then AA; elsif a<3454 then AA; elsif x>1606 then AA; else RR; end if; end; procedure gjs is begin if a<2848 then AA; elsif x<651 then AA; else RR; end if; end; procedure nbz is begin if x<2579 then rtg; else bvg; end if; end; procedure tkj is begin if x<2510 then zx; elsif x>3340 then blx; elsif a>1123 then ggs; else ctb; end if; end; procedure rk is begin if m<105 then AA; elsif s<2581 then RR; elsif s>3343 then AA; else RR; end if; end; procedure gr is begin if s>2781 then RR; elsif m>938 then AA; elsif a<3798 then AA; else AA; end if; end; procedure zlr is begin if s>2444 then AA; else RR; end if; end; procedure qzq is begin if x>260 then RR; elsif s>2233 then RR; else AA; end if; end; procedure qb is begin if a<3400 then tv; elsif x<1211 then lbl; elsif s<3532 then AA; else AA; end if; end; procedure jkl is begin if a>569 then RR; elsif a>219 then AA; else AA; end if; end; procedure kd is begin if a<332 then AA; elsif s>1163 then AA; elsif a<441 then AA; else RR; end if; end; procedure ztq is begin if s<1701 then xg; elsif s>1889 then dmp; elsif x>944 then szs; else kbm; end if; end; procedure vtl is begin if s<1362 then RR; elsif m>1164 then RR; elsif s>1500 then AA; else AA; end if; end; procedure tj is begin if x>3274 then AA; elsif s<708 then AA; elsif a<1760 then RR; else AA; end if; end; procedure dhp is begin if a>3146 then qzq; else RR; end if; end; procedure bn is begin if x<466 then RR; else AA; end if; end; procedure jv is begin if a<3111 then RR; else bkc; end if; end; procedure pjd is begin if m<2011 then cpm; else hrl; end if; end; procedure fh is begin if a<3064 then RR; elsif s<2885 then jt; elsif x>920 then RR; else clk; end if; end; procedure gf is begin if s>3568 then AA; else jcs; end if; end; procedure cnb is begin if x>2602 then bgd; else lpq; end if; end; procedure rjs is begin if x<3342 then AA; elsif x>3570 then RR; elsif a<1033 then AA; else RR; end if; end; procedure sl is begin if m>1009 then fvp; else spg; end if; end; procedure dd is begin if a<3115 then AA; else RR; end if; end; procedure hl is begin if a<3182 then RR; elsif x<2541 then AA; elsif s>1661 then RR; else AA; end if; end; procedure zc is begin if m>3224 then RR; elsif x<1402 then AA; else RR; end if; end; procedure jhv is begin if a>2713 then AA; else nh; end if; end; procedure rjx is begin if s>715 then RR; elsif s<450 then RR; else RR; end if; end; procedure bp is begin if a>3418 then RR; elsif a>2981 then AA; else RR; end if; end; procedure rj is begin if m>817 then bp; else AA; end if; end; procedure mmc is begin if a>2356 then bsh; else AA; end if; end; procedure jzr is begin if x>627 then pk; elsif s<3294 then jjc; else td; end if; end; procedure hj is begin if a<1124 then RR; else AA; end if; end; procedure lpx is begin if x>1886 then RR; elsif s<521 then RR; elsif a<379 then AA; else RR; end if; end; procedure vxl is begin if x>1956 then AA; else RR; end if; end; procedure ncl is begin if m>2887 then AA; else AA; end if; end; procedure hxs is begin if a>3893 then zgx; elsif a>3783 then AA; else RR; end if; end; procedure xv is begin if a>245 then AA; else lg; end if; end; procedure pfl is begin if a<440 then RR; else AA; end if; end; procedure jhd is begin if a<2796 then AA; elsif a<2813 then RR; else AA; end if; end; procedure vjn is begin if x<2270 then RR; elsif s<1166 then AA; else AA; end if; end; procedure gdk is begin if a>2886 then qds; elsif x>1553 then jkf; else gmg; end if; end; procedure ljv is begin if m>954 then AA; else bqt; end if; end; procedure rf is begin if m<2314 then AA; else RR; end if; end; procedure zpb is begin if s>1717 then AA; elsif a>434 then RR; else AA; end if; end; procedure xgr is begin if s<2801 then gd; elsif x>2319 then tb; else nv; end if; end; procedure ln is begin if a<3324 then AA; elsif a<3448 then AA; elsif x>1756 then RR; else AA; end if; end; procedure ntl is begin if s<1540 then RR; elsif x<2910 then AA; elsif x>3423 then AA; else RR; end if; end; procedure fg is begin if m<3195 then RR; else AA; end if; end; procedure kq is begin if m<1917 then RR; else AA; end if; end; procedure mln is begin if m>674 then dtc; elsif x<3229 then tl; elsif s<3218 then AA; else AA; end if; end; procedure sjq is begin if x<2421 then RR; elsif s<3380 then zz; else lp; end if; end; procedure rpm is begin if s>67 then RR; elsif x<2573 then AA; else AA; end if; end; procedure jc is begin if s<799 then AA; elsif m>3802 then AA; else RR; end if; end; procedure lvq is begin if x>3719 then AA; elsif s<3613 then ghp; elsif a<1156 then RR; else AA; end if; end; procedure cc is begin if m>3325 then AA; elsif m<2610 then RR; elsif m>3049 then zc; else xxd; end if; end; procedure kxk is begin if m<1500 then AA; elsif a>3205 then RR; elsif m<2576 then RR; else lmm; end if; end; procedure qqs is begin if s>3227 then AA; elsif s>2736 then RR; elsif x<2614 then kqb; else kbt; end if; end; procedure lzl is begin if a>399 then RR; else AA; end if; end; procedure sh is begin if x<2261 then RR; else RR; end if; end; procedure pzx is begin if a<1051 then RR; else RR; end if; end; procedure mrc is begin if x<2382 then RR; elsif a<693 then AA; else RR; end if; end; procedure sx is begin if x>3458 then AA; else AA; end if; end; procedure sv is begin if a>2471 then krx; elsif a<2306 then AA; elsif a<2413 then mx; else AA; end if; end; procedure jmf is begin if a<292 then RR; elsif m>1008 then AA; else AA; end if; end; procedure hs is begin if m<2526 then RR; elsif x>2622 then RR; else RR; end if; end; procedure ljn is begin if m>627 then pf; elsif m>586 then cfj; else bh; end if; end; procedure mq is begin if x>903 then AA; elsif s>3293 then AA; else RR; end if; end; procedure gc is begin if a<365 then AA; elsif a<570 then RR; else RR; end if; end; procedure zjx is begin if m>2207 then RR; else RR; end if; end; procedure kqb is begin if m<602 then RR; else AA; end if; end; procedure xr is begin if s<3802 then RR; else RR; end if; end; procedure lhx is begin if m>3170 then AA; else rgl; end if; end; procedure kct is begin if a<1891 then ttc; else zm; end if; end; procedure vn is begin if a>2795 then AA; elsif s<3343 then AA; else AA; end if; end; procedure bvg is begin if a>1980 then AA; else RR; end if; end; procedure tzr is begin if a>2885 then AA; elsif s<3105 then RR; else AA; end if; end; procedure ghp is begin if s>3260 then AA; else AA; end if; end; procedure ljh is begin if m>884 then zpb; else AA; end if; end; procedure crk is begin if s<1819 then zgv; elsif m<3162 then lz; elsif a<1774 then kh; else nx; end if; end; procedure ttc is begin if x<2046 then RR; else AA; end if; end; procedure hmd is begin if a<2368 then RR; elsif m>1132 then RR; elsif x<1075 then AA; else AA; end if; end; procedure tb is begin if s>3294 then RR; elsif s>2982 then AA; elsif x<3285 then AA; else RR; end if; end; procedure skm is begin if s>1721 then gkt; elsif a>382 then lxb; elsif s>1637 then AA; else AA; end if; end; procedure bmk is begin if x<3657 then fl; elsif a<3341 then RR; else RR; end if; end; procedure frf is begin if m<2252 then xmx; elsif s<1800 then bb; elsif x>515 then sdr; else dhp; end if; end; procedure grp is begin if a>1183 then RR; elsif x>2651 then RR; else RR; end if; end; procedure qzr is begin if a>1128 then RR; elsif a>1121 then AA; else AA; end if; end; procedure xxd is begin if x>1538 then AA; elsif a>2807 then RR; elsif s<361 then RR; else AA; end if; end; procedure nvs is begin if s<2686 then RR; elsif a>148 then RR; else AA; end if; end; procedure sbd is begin if a>2540 then RR; elsif a>2502 then AA; elsif x<3553 then RR; else RR; end if; end; procedure rmb is begin if x<949 then AA; elsif x<1340 then RR; else RR; end if; end; procedure sbh is begin if x>3465 then zxc; elsif m>810 then AA; else qrq; end if; end; procedure kmc is begin if m>2641 then mqh; else RR; end if; end; procedure ks is begin if m<1434 then vq; elsif m<2308 then rs; elsif x>1362 then hr; else rzc; end if; end; procedure dxl is begin if x>2295 then RR; elsif a>2873 then AA; elsif s<3812 then AA; else RR; end if; end; procedure czp is begin if m<90 then AA; elsif x>3608 then AA; elsif s<1450 then AA; else RR; end if; end; procedure lbl is begin if x>571 then AA; else RR; end if; end; procedure mbj is begin if x>2946 then AA; elsif s<1470 then cmf; elsif x<2327 then RR; else AA; end if; end; procedure jsn is begin if s>871 then AA; elsif x>2587 then AA; else AA; end if; end; procedure qjg is begin if s>3258 then RR; elsif m>2447 then AA; elsif x>549 then AA; else AA; end if; end; procedure tq is begin if s<2590 then lk; elsif a<3153 then gdk; else ctt; end if; end; procedure qnp is begin if s>2942 then RR; elsif s<2748 then RR; else RR; end if; end; procedure gnb is begin if s>1449 then RR; elsif a<3469 then AA; else RR; end if; end; procedure xq is begin if x<740 then RR; elsif x>822 then AA; elsif s>1796 then AA; else RR; end if; end; procedure ddr is begin if x>825 then kmc; elsif a<2829 then rnh; else hb; end if; end; procedure nl is begin if s<112 then rpm; else RR; end if; end; procedure bgz is begin if s<3472 then AA; elsif s<3715 then frc; elsif s>3840 then RR; else fj; end if; end; procedure xd is begin if s<3101 then bv; elsif a<3302 then jcf; elsif s<3572 then jh; else xr; end if; end; procedure rxc is begin if m>891 then AA; else AA; end if; end; procedure gj is begin if m<673 then RR; else zds; end if; end; procedure nzb is begin if m<3405 then RR; else lbm; end if; end; procedure gg is begin if a<1286 then mgs; elsif m>935 then bxg; elsif x<2090 then AA; else RR; end if; end; procedure lcg is begin if m<1248 then AA; elsif s>3297 then AA; elsif s>2766 then AA; else RR; end if; end; procedure gq is begin if x<3301 then mz; else lvq; end if; end; procedure cng is begin if x>2558 then rjs; elsif x>992 then sts; else vfk; end if; end; procedure gkl is begin if m>2141 then dfh; elsif m<1900 then db; elsif x>1897 then vd; else sp; end if; end; procedure zx is begin if m>98 then RR; else RR; end if; end; procedure jcs is begin if m<1494 then AA; elsif x<389 then AA; elsif a>3699 then AA; else RR; end if; end; procedure sdm is begin if a>2317 then AA; else RR; end if; end; procedure btg is begin if s>1891 then AA; elsif x<2144 then AA; elsif s>906 then AA; else RR; end if; end; procedure rq is begin if x<2267 then RR; elsif a<513 then RR; elsif x<3300 then AA; else AA; end if; end; procedure fpj is begin if s>3216 then lb; elsif a>2662 then RR; elsif s<2815 then AA; else psj; end if; end; procedure vd is begin if a<417 then xv; elsif a>769 then bk; else jps; end if; end; procedure qvd is begin if a>1423 then kct; elsif a<832 then cql; else xkq; end if; end; procedure nxf is begin if m>2417 then xd; else rc; end if; end; procedure rhb is begin if a<3055 then RR; else AA; end if; end; procedure hq is begin if s>949 then zd; else vcn; end if; end; procedure qv is begin if a<270 then nls; elsif x<2596 then AA; else RR; end if; end; procedure hv is begin if a>116 then AA; elsif a<67 then RR; elsif s<2371 then RR; else AA; end if; end; procedure ttv is begin if a<3583 then RR; elsif a<3757 then RR; elsif s>500 then RR; else AA; end if; end; procedure nv is begin if a>1042 then AA; elsif x<1348 then AA; else RR; end if; end; procedure cgx is begin if a>1726 then AA; else AA; end if; end; procedure mz is begin if s>3365 then qqp; else RR; end if; end; procedure jnn is begin if x>2684 then AA; elsif m<1408 then RR; else AA; end if; end; procedure vf is begin if x<715 then AA; else AA; end if; end; procedure gfk is begin if a<633 then zv; elsif a>1261 then vxl; else cr; end if; end; procedure dcg is begin if x<1256 then vs; elsif x>1509 then hxj; elsif s>1703 then ks; else fm; end if; end; procedure mp is begin if m>1507 then jfk; elsif m<526 then cv; elsif s>2468 then zf; else ctn; end if; end; procedure mg is begin if x<1958 then AA; elsif a>1912 then AA; else AA; end if; end; procedure hzc is begin if s>3226 then AA; elsif x>2499 then AA; elsif a<2843 then AA; else RR; end if; end; procedure nc is begin if m<494 then RR; else RR; end if; end; procedure vlr is begin if a<1639 then RR; elsif m>965 then AA; else RR; end if; end; procedure xkx is begin if s<2878 then RR; elsif s<3070 then RR; else AA; end if; end; procedure bb is begin if a>3530 then RR; elsif s<1510 then AA; else RR; end if; end; procedure nh is begin if x>1430 then RR; elsif a>2684 then AA; elsif m<2349 then AA; else RR; end if; end; procedure dh is begin if x<1024 then RR; else AA; end if; end; procedure gmg is begin if a>2772 then ddr; else cl; end if; end; procedure cl is begin if x<745 then qmm; elsif x<1185 then ltl; else jhv; end if; end; procedure xkb is begin if s<1903 then RR; elsif x>2528 then RR; else RR; end if; end; procedure cbb is begin if m<1781 then AA; else qr; end if; end; procedure fr is begin if s<3106 then slq; else RR; end if; end; procedure mh is begin if m>2269 then AA; elsif x<1093 then AA; elsif a<2684 then AA; else RR; end if; end; procedure cv is begin if m<197 then qvd; else tck; end if; end; procedure mlj is begin if s<3617 then pzx; else sh; end if; end; procedure dcz is begin if a<3605 then lv; elsif a<3752 then AA; elsif s<468 then RR; else RR; end if; end; procedure vcn is begin if s<524 then RR; elsif x<1378 then RR; else vqv; end if; end; procedure kqs is begin if x<1335 then RR; else lr; end if; end; procedure mcq is begin if x>1676 then ttv; else AA; end if; end; procedure hxt is begin if s<2024 then gnb; elsif m>1410 then pj; elsif m<736 then RR; else dtj; end if; end; procedure ld is begin if s<3688 then ggh; elsif s<3793 then AA; elsif m>1290 then AA; else AA; end if; end; procedure xs is begin if x>258 then AA; elsif s<1774 then RR; else RR; end if; end; procedure mfn is begin if s<1906 then RR; else AA; end if; end; procedure qfs is begin if m>1437 then RR; else RR; end if; end; procedure tx is begin if a<3403 then jzm; else tn; end if; end; procedure rct is begin if m<1016 then AA; elsif s<2621 then RR; else RR; end if; end; procedure nd is begin if s>3135 then AA; else RR; end if; end; procedure jjc is begin if s>2911 then mhf; elsif m<1665 then hxg; elsif x<348 then qcr; else lx; end if; end; procedure gtq is begin if m>961 then xbr; elsif m<830 then AA; elsif x<507 then AA; else vnq; end if; end; procedure cx is begin if m>268 then AA; else AA; end if; end; procedure xf is begin if x<345 then AA; elsif s>3174 then RR; elsif m<1739 then AA; else AA; end if; end; procedure cbv is begin if m>1242 then AA; elsif m>1121 then RR; elsif x>897 then RR; else AA; end if; end; procedure zgv is begin if x>2074 then AA; elsif s>733 then AA; elsif s<478 then RR; else RR; end if; end; procedure dgf is begin if x<494 then rtk; elsif x<648 then bj; else xq; end if; end; procedure xg is begin if x<795 then AA; elsif s>1607 then AA; elsif m>3324 then RR; else dm; end if; end; procedure tzv is begin if m<1869 then jhs; elsif m>3270 then km; elsif x>493 then plc; else zs; end if; end; procedure nt is begin if a>3068 then AA; elsif a<3045 then AA; else RR; end if; end; procedure gbv is begin if s<3584 then RR; elsif s<3728 then RR; else RR; end if; end; procedure qmm is begin if m>2061 then zh; else RR; end if; end; procedure cr is begin if x>1870 then RR; elsif x>982 then AA; elsif s<463 then RR; else rl; end if; end; procedure gxs is begin if s>3087 then AA; elsif m>385 then AA; elsif a<280 then RR; else rq; end if; end; procedure ctq is begin if a>987 then RR; else RR; end if; end; procedure mfh is begin if a>1105 then ll; else lm; end if; end; procedure ff is begin if x<1886 then pt; elsif m<1867 then AA; else RR; end if; end; procedure ggb is begin if a<657 then RR; elsif a>714 then RR; else RR; end if; end; procedure jkf is begin if a<2776 then jjm; elsif a<2825 then bhj; elsif a<2860 then hhd; else jhl; end if; end; procedure fdx is begin if s>3342 then RR; else RR; end if; end; procedure bls is begin if s<1648 then mbj; elsif x>3066 then sbh; else nlk; end if; end; procedure czg is begin if s<3077 then RR; elsif x<2514 then AA; else RR; end if; end; procedure sxz is begin if m<937 then grp; elsif s<2655 then mll; elsif m>1045 then vsx; else sl; end if; end; procedure vqn is begin if m<1679 then RR; elsif a>2998 then AA; else RR; end if; end; procedure vdv is begin if s>2257 then RR; elsif a<3750 then AA; elsif s<2080 then AA; else RR; end if; end; procedure nsx is begin if s>1907 then AA; elsif a>3246 then AA; else AA; end if; end; procedure gd is begin if x<2557 then AA; elsif a>1050 then RR; elsif s>2360 then RR; else RR; end if; end; procedure vnp is begin if x<1424 then AA; elsif x>1732 then AA; else AA; end if; end; procedure dtc is begin if m>702 then RR; else AA; end if; end; procedure glj is begin if s>2917 then AA; else AA; end if; end; procedure qt is begin if s>3494 then dxl; elsif x<2302 then kf; else RR; end if; end; procedure xzk is begin if a>296 then RR; elsif x>2358 then RR; else hv; end if; end; procedure mls is begin if s<2885 then AA; elsif m>1811 then AA; else AA; end if; end; procedure qvc is begin if a<1613 then gfk; elsif a>2225 then kfr; elsif a<1820 then xrc; else nbz; end if; end; procedure ctb is begin if s>2109 then RR; else AA; end if; end; procedure xz is begin if s<3018 then sxz; elsif x>2273 then gq; else fnv; end if; end; procedure lg is begin if m<2007 then AA; elsif m<2082 then RR; else AA; end if; end; procedure lpq is begin if s>3341 then zjx; else zxh; end if; end; procedure jhh is begin if m<3882 then AA; elsif s<3163 then mrc; elsif s<3625 then nm; else RR; end if; end; procedure tc is begin if a<3635 then AA; else AA; end if; end; procedure gx is begin if a<1752 then AA; elsif x<2622 then AA; else AA; end if; end; procedure mqj is begin if a>2450 then RR; else RR; end if; end; procedure bz is begin if a>676 then AA; elsif s>2182 then AA; else RR; end if; end; procedure fnv is begin if x>879 then mfh; elsif s<3449 then ljv; elsif a>1353 then gtq; else bxb; end if; end; procedure zfm is begin if x>3316 then czp; else RR; end if; end; procedure vsx is begin if x>1654 then jbk; elsif s>2805 then RR; elsif a>1136 then ksl; else hcz; end if; end; procedure csr is begin if m<3505 then RR; else AA; end if; end; procedure mhf is begin if s<3158 then RR; elsif s<3205 then xf; elsif x<414 then jx; else qjg; end if; end; procedure vc is begin if s<1158 then qq; else frf; end if; end; procedure qnv is begin if m<696 then RR; else RR; end if; end; procedure cm is begin if m>3441 then RR; elsif x<1223 then RR; elsif x>1733 then AA; else AA; end if; end; procedure jhl is begin if x<3102 then qt; elsif a<2877 then cs; elsif a>2880 then cn; else cbb; end if; end; procedure sq is begin if a>671 then AA; elsif s<1821 then AA; elsif x>1635 then RR; else RR; end if; end; procedure hvz is begin if m>2461 then RR; else AA; end if; end; procedure tr is begin if m>563 then RR; else RR; end if; end; procedure cgv is begin if a<2538 then RR; else AA; end if; end; procedure ps is begin if x<1895 then RR; elsif x>3216 then RR; else AA; end if; end; procedure rm is begin if s<3054 then RR; elsif s>3470 then AA; elsif m>1762 then RR; else AA; end if; end; procedure qp is begin if m<2013 then AA; elsif s<1385 then RR; elsif s>1514 then RR; else AA; end if; end; procedure qj is begin if m<3381 then fg; elsif m<3694 then pqb; else jhh; end if; end; procedure qr is begin if x<3568 then AA; elsif m<2760 then AA; else RR; end if; end; procedure tfs is begin if s>433 then AA; elsif x<1324 then RR; else AA; end if; end; procedure cql is begin if x<2048 then rk; else zfm; end if; end; procedure fvp is begin if m>1027 then AA; elsif x<2630 then RR; elsif x<3279 then RR; else AA; end if; end; procedure tgt is begin if a>1670 then RR; else mnr; end if; end; procedure tn is begin if m>824 then RR; else AA; end if; end; procedure fl is begin if x<3396 then AA; else AA; end if; end; procedure vv is begin if s>3244 then RR; elsif a<3126 then dd; elsif s<2826 then rf; else RR; end if; end; procedure lr is begin if s<2004 then AA; else RR; end if; end; procedure xhx is begin if x<1756 then scv; else cx; end if; end; procedure jzm is begin if x>1343 then AA; elsif x>703 then RR; elsif a>3373 then AA; else AA; end if; end; procedure tlj is begin if s>1605 then nbf; else tdg; end if; end; procedure xk is begin if x>152 then RR; else AA; end if; end; procedure mt is begin if m<2968 then qps; elsif a>701 then hq; else lh; end if; end; procedure zk is begin if m>416 then RR; elsif x>3052 then AA; elsif x<2638 then AA; else AA; end if; end; procedure zn is begin if a<2399 then AA; else AA; end if; end; procedure ggh is begin if m<894 then AA; elsif a>3830 then AA; elsif a>3691 then RR; else AA; end if; end; procedure ht is begin if x<1797 then AA; elsif s>2872 then AA; else AA; end if; end; procedure jbl is begin if m>1401 then RR; else dp; end if; end; procedure vfk is begin if x<479 then RR; elsif m>117 then AA; else AA; end if; end; procedure qdz is begin if s>554 then RR; elsif s<239 then cpv; else RR; end if; end; procedure ll is begin if s>3366 then AA; elsif s<3226 then AA; else RR; end if; end; procedure vbp is begin if a<527 then RR; elsif m>2007 then gk; else pz; end if; end; procedure rhg is begin if m<1474 then AA; elsif a>1417 then AA; elsif a<862 then AA; else AA; end if; end; procedure inn is begin if a>2639 then tq; else mp; end if; end; procedure bv is begin if m<3468 then ln; else ht; end if; end; procedure zgx is begin if a>3932 then RR; elsif a>3907 then RR; elsif x>1109 then RR; else RR; end if; end; procedure hx is begin if a<449 then jc; else RR; end if; end; procedure cfj is begin if a>1414 then fr; elsif a>556 then sjq; elsif a>190 then npl; else qqs; end if; end; procedure mr is begin if m<2693 then AA; else AA; end if; end; procedure hcp is begin if a>1108 then RR; else RR; end if; end; procedure bf is begin if x>3211 then vv; else hpl; end if; end; procedure rtg is begin if a>1997 then rxc; else jl; end if; end; procedure qcr is begin if x>162 then AA; elsif x>74 then AA; elsif s>2711 then bjq; else AA; end if; end; procedure xnv is begin if m<724 then sxc; elsif x<921 then qzx; elsif a<2263 then mn; else lxc; end if; end; procedure pbx is begin if a>826 then ctq; elsif m<3306 then AA; else zlr; end if; end; procedure nlp is begin if s>1893 then AA; else RR; end if; end; procedure mfr is begin if x<2238 then RR; else RR; end if; end; procedure tg is begin if a<2948 then ff; else kz; end if; end; procedure tnp is begin if a<3177 then RR; elsif s>2055 then AA; else AA; end if; end; procedure slq is begin if m>611 then RR; else AA; end if; end; procedure fz is begin if m>2476 then RR; elsif s>3368 then RR; elsif s<2963 then RR; else AA; end if; end; procedure rgz is begin if a<1096 then AA; elsif x<2237 then RR; else RR; end if; end; procedure rg is begin if x<396 then RR; elsif a<3472 then qs; else RR; end if; end; procedure nm is begin if x>2253 then AA; else RR; end if; end; procedure mdc is begin if x>1209 then gz; elsif s<3278 then vf; else AA; end if; end; procedure pbt is begin if a>1678 then AA; elsif x>3246 then vlr; elsif m<1092 then RR; else RR; end if; end; procedure dbl is begin if m<2274 then RR; elsif m<2607 then mc; else lpx; end if; end; procedure cn is begin if a<2884 then dz; elsif x>3410 then sg; elsif s>3454 then RR; else tzr; end if; end; procedure hb is begin if s>3486 then RR; elsif a>2860 then glj; elsif x<378 then AA; else gjs; end if; end; procedure nls is begin if a<134 then AA; elsif s>1825 then RR; elsif m<3471 then AA; else AA; end if; end; procedure tl is begin if s>3434 then AA; else AA; end if; end; procedure bl is begin if a<555 then RR; elsif a>1174 then AA; else RR; end if; end; procedure mml is begin if a<3707 then AA; else RR; end if; end; procedure dtm is begin if x>2903 then hlx; elsif a>1934 then xkb; else nlp; end if; end; procedure rb is begin if a>379 then AA; elsif x<2450 then nvs; elsif a>224 then AA; else sx; end if; end; procedure pf is begin if x<1899 then fpz; else mln; end if; end; procedure zmn is begin if m>882 then AA; elsif a>2320 then RR; elsif a>2208 then RR; else AA; end if; end; procedure jh is begin if x<2603 then fdx; else RR; end if; end; procedure crh is begin if a>1398 then xkx; elsif s>2903 then gbg; else RR; end if; end; procedure fmp is begin if a>709 then RR; elsif x<507 then AA; elsif s>2752 then RR; else AA; end if; end; procedure sg is begin if m>1527 then RR; else RR; end if; end; procedure sp is begin if x>1242 then vbp; else fmp; end if; end; procedure cj is begin if m<564 then AA; elsif x<900 then AA; else RR; end if; end; procedure khv is begin if s>2714 then qj; elsif s>2119 then xfp; elsif x>2174 then csz; else ztq; end if; end; procedure lsz is begin if m<3503 then AA; else AA; end if; end; procedure dfh is begin if a<612 then rb; elsif a<1008 then mfr; elsif a>1087 then st; else xgr; end if; end; procedure lm is begin if x>1566 then RR; elsif s>3634 then AA; elsif m<917 then AA; else AA; end if; end; procedure hn is begin if x>1169 then RR; else nt; end if; end; procedure pp is begin if x>2075 then jct; elsif m<1540 then hn; elsif s>3287 then ksd; else fh; end if; end; procedure ddf is begin if s>3058 then AA; else AA; end if; end; procedure mn is begin if x>1509 then RR; else RR; end if; end; procedure hc is begin if m>452 then nc; elsif s<2479 then hml; elsif a>714 then crf; else gxs; end if; end; procedure lgt is begin if x>1822 then AA; elsif m>1939 then RR; elsif s>1685 then sj; else vtl; end if; end; procedure pmb is begin if x<1257 then RR; else RR; end if; end; procedure bq is begin if m>749 then hl; elsif a<2978 then RR; elsif m>283 then AA; else gcm; end if; end; procedure dj is begin if x>419 then RR; elsif m>890 then AA; elsif m<591 then RR; else RR; end if; end; procedure lz is begin if m>2383 then RR; elsif a<1605 then AA; else nd; end if; end; procedure rlz is begin if x<908 then dgf; elsif m<2926 then mmc; elsif m>3586 then kl; else kqs; end if; end; procedure lbs is begin if m<1371 then lcg; elsif m>1435 then rhg; else jnn; end if; end; procedure hml is begin if m<403 then jkl; elsif x<2272 then RR; elsif m<428 then zk; else bl; end if; end; procedure ckz is begin if s<3014 then RR; elsif m>1426 then AA; elsif a>431 then AA; else AA; end if; end; procedure ft is begin if x<2599 then RR; else AA; end if; end; procedure mxb is begin if x<3119 then lbs; elsif s>3317 then mth; else crh; end if; end; procedure vh is begin if x>2169 then mxb; else npb; end if; end; procedure rc is begin if a<3327 then jbl; elsif x>2380 then bgz; elsif s<3109 then tx; else qb; end if; end; procedure zm is begin if m<76 then btg; else RR; end if; end; procedure jhs is begin if a<3796 then AA; elsif a<3916 then RR; elsif a>3966 then RR; else AA; end if; end; procedure hhd is begin if x>2759 then kj; elsif x<2163 then qfs; else nr; end if; end; procedure zds is begin if m<1380 then RR; else RR; end if; end; procedure zd is begin if a>899 then pbh; else vjn; end if; end; procedure xvn is begin if s>2657 then pfl; else RR; end if; end; -- pragma Style_Checks (On); r : array (Part_Type) of Integer_64; choice : Data_Type; procedure Do_Part_1 is sum : Integer_64 := 0; procedure Mini_Test (x0, m0, a0, s0 : Natural) is begin x := x0; m := m0; a := a0; s := s0; m_in; if ok then sum := sum + Integer_64 (x + m + a + s); end if; end Mini_Test; procedure Input_Test (x0, m0, a0, s0 : Natural) is begin x := x0; m := m0; a := a0; s := s0; inn; if ok then sum := sum + Integer_64 (x + m + a + s); end if; end Input_Test; begin ok := False; case choice is when mini => Mini_Test (787, 2655, 1222, 2876); Mini_Test (1679, 44, 2067, 496); Mini_Test (2036, 264, 79, 2244); Mini_Test (2461, 1339, 466, 291); Mini_Test (2127, 1623, 2188, 1013); when input => Input_Test (6, 309, 1182, 757); Input_Test (531, 106, 1009, 142); Input_Test (3264, 506, 301, 807); Input_Test (1197, 394, 351, 1266); Input_Test (3009, 1048, 143, 1549); Input_Test (617, 1696, 778, 28); Input_Test (172, 2243, 1135, 2330); Input_Test (309, 457, 1943, 8); Input_Test (424, 100, 288, 1745); Input_Test (282, 138, 2134, 272); Input_Test (2982, 2488, 1452, 3065); Input_Test (1760, 2317, 3608, 119); Input_Test (682, 303, 1113, 34); Input_Test (806, 3417, 720, 1219); Input_Test (908, 2564, 1065, 766); Input_Test (1044, 70, 511, 1410); Input_Test (848, 262, 1100, 778); Input_Test (1042, 1887, 2083, 847); Input_Test (1051, 1636, 187, 892); Input_Test (782, 489, 1940, 18); Input_Test (33, 1970, 838, 1123); Input_Test (20, 2180, 2036, 1720); Input_Test (468, 788, 170, 983); Input_Test (1893, 1399, 1661, 1493); Input_Test (42, 604, 2889, 219); Input_Test (109, 56, 1004, 2498); Input_Test (1249, 213, 329, 117); Input_Test (544, 380, 124, 1479); Input_Test (1222, 996, 498, 2270); Input_Test (38, 228, 59, 1060); Input_Test (17, 613, 2060, 1358); Input_Test (188, 976, 100, 1415); Input_Test (965, 641, 1563, 2718); Input_Test (867, 386, 1798, 682); Input_Test (1596, 350, 143, 167); Input_Test (390, 2438, 225, 171); Input_Test (1014, 1030, 718, 2678); Input_Test (473, 2034, 1270, 449); Input_Test (2092, 268, 653, 691); Input_Test (951, 16, 1869, 2764); Input_Test (494, 154, 178, 1323); Input_Test (2653, 1230, 238, 787); Input_Test (922, 1420, 1390, 2030); Input_Test (2958, 2763, 1486, 2822); Input_Test (615, 373, 31, 1548); Input_Test (1275, 1486, 2205, 171); Input_Test (1, 2571, 234, 1346); Input_Test (945, 107, 99, 754); Input_Test (1398, 1428, 556, 1724); Input_Test (693, 3354, 3, 218); Input_Test (1706, 39, 1620, 1403); Input_Test (465, 408, 2153, 651); Input_Test (1026, 794, 340, 920); Input_Test (1275, 1806, 120, 599); Input_Test (78, 1030, 1601, 1019); Input_Test (2442, 1645, 331, 69); Input_Test (1797, 480, 479, 1634); Input_Test (135, 1838, 216, 1293); Input_Test (1914, 1031, 53, 23); Input_Test (2862, 303, 883, 537); Input_Test (60, 192, 109, 1577); Input_Test (527, 629, 103, 136); Input_Test (66, 1861, 135, 1026); Input_Test (105, 678, 2551, 495); Input_Test (2558, 33, 322, 1359); Input_Test (2032, 376, 39, 857); Input_Test (929, 1035, 174, 2372); Input_Test (731, 156, 26, 2512); Input_Test (1120, 880, 500, 1070); Input_Test (845, 108, 1492, 1340); Input_Test (2460, 2527, 1057, 1382); Input_Test (390, 942, 953, 402); Input_Test (557, 440, 335, 426); Input_Test (1850, 3068, 1956, 258); Input_Test (351, 296, 222, 181); Input_Test (27, 389, 650, 999); Input_Test (1941, 3377, 1600, 1377); Input_Test (62, 2099, 9, 25); Input_Test (34, 658, 215, 32); Input_Test (1408, 989, 54, 560); Input_Test (969, 431, 634, 856); Input_Test (75, 678, 1523, 157); Input_Test (1087, 837, 763, 118); Input_Test (112, 904, 3317, 313); Input_Test (2163, 1100, 271, 882); Input_Test (474, 289, 305, 197); Input_Test (1307, 2741, 279, 1550); Input_Test (1109, 629, 1600, 298); Input_Test (868, 815, 2970, 21); Input_Test (1850, 285, 1158, 373); Input_Test (1430, 1078, 226, 2374); Input_Test (296, 413, 1609, 1099); Input_Test (11, 3105, 505, 2170); Input_Test (2126, 1961, 389, 1087); Input_Test (592, 1842, 1991, 1083); Input_Test (93, 1662, 1840, 2377); Input_Test (433, 30, 1269, 857); Input_Test (1898, 662, 861, 1131); Input_Test (2484, 278, 1782, 134); Input_Test (102, 1146, 3527, 2090); Input_Test (2530, 727, 1577, 211); Input_Test (316, 2957, 18, 730); Input_Test (492, 183, 624, 1454); Input_Test (3325, 30, 1660, 938); Input_Test (407, 1854, 99, 326); Input_Test (1336, 1276, 473, 24); Input_Test (1718, 438, 956, 384); Input_Test (353, 1534, 2180, 2974); Input_Test (2705, 211, 94, 837); Input_Test (104, 123, 413, 1789); Input_Test (176, 395, 2652, 50); Input_Test (738, 1018, 103, 200); Input_Test (750, 31, 916, 121); Input_Test (2967, 1253, 1593, 1357); Input_Test (262, 112, 131, 63); Input_Test (145, 807, 291, 959); Input_Test (1476, 239, 1054, 3491); Input_Test (428, 351, 2465, 65); Input_Test (35, 236, 863, 1089); Input_Test (1233, 2010, 177, 764); Input_Test (1083, 1863, 25, 1974); Input_Test (957, 1180, 837, 679); Input_Test (66, 1204, 285, 2075); Input_Test (444, 560, 172, 1447); Input_Test (812, 350, 876, 661); Input_Test (200, 366, 752, 851); Input_Test (749, 377, 815, 648); Input_Test (60, 285, 517, 39); Input_Test (2921, 381, 119, 249); Input_Test (466, 1290, 801, 2159); Input_Test (62, 201, 881, 95); Input_Test (3598, 126, 1688, 979); Input_Test (2963, 1112, 2733, 520); Input_Test (62, 1067, 920, 451); Input_Test (2501, 475, 1074, 1150); Input_Test (50, 1111, 12, 44); Input_Test (617, 1106, 1489, 1333); Input_Test (90, 208, 219, 2352); Input_Test (1179, 2166, 1693, 2055); Input_Test (61, 595, 1382, 1140); Input_Test (62, 354, 123, 793); Input_Test (436, 865, 2408, 2578); Input_Test (515, 398, 303, 312); Input_Test (637, 2236, 474, 148); Input_Test (2488, 35, 75, 924); Input_Test (461, 1196, 7, 1092); Input_Test (923, 3184, 1161, 308); Input_Test (191, 1399, 1324, 2784); Input_Test (170, 421, 51, 625); Input_Test (170, 362, 471, 2100); Input_Test (289, 66, 143, 284); Input_Test (542, 339, 455, 54); Input_Test (155, 124, 732, 2057); Input_Test (8, 420, 784, 1455); Input_Test (479, 251, 1883, 136); Input_Test (104, 146, 97, 249); Input_Test (2766, 833, 386, 585); Input_Test (373, 514, 466, 2192); Input_Test (296, 1190, 249, 963); Input_Test (518, 1840, 860, 306); Input_Test (1003, 1955, 756, 1098); Input_Test (1545, 242, 1479, 576); Input_Test (77, 1717, 475, 1692); Input_Test (417, 1517, 2199, 374); Input_Test (3247, 348, 1065, 1154); Input_Test (456, 868, 182, 1077); Input_Test (464, 425, 15, 781); Input_Test (640, 294, 303, 261); Input_Test (1018, 327, 18, 1830); Input_Test (262, 988, 1974, 1665); Input_Test (123, 525, 3062, 460); Input_Test (228, 2020, 29, 701); Input_Test (129, 1163, 1561, 958); Input_Test (29, 1576, 74, 348); Input_Test (64, 2153, 63, 1771); Input_Test (71, 66, 1642, 1749); Input_Test (1373, 3063, 1958, 561); Input_Test (2277, 3766, 384, 363); Input_Test (2956, 127, 865, 1862); Input_Test (599, 115, 2360, 526); Input_Test (651, 644, 580, 514); Input_Test (880, 173, 613, 3270); Input_Test (1228, 951, 1515, 333); Input_Test (1621, 2392, 2665, 1515); Input_Test (933, 1805, 228, 1720); Input_Test (25, 1553, 54, 3177); Input_Test (85, 550, 273, 142); Input_Test (489, 624, 126, 557); Input_Test (256, 2513, 509, 186); Input_Test (2616, 377, 2497, 707); Input_Test (688, 509, 410, 557); Input_Test (1306, 105, 1605, 3217); Input_Test (1405, 31, 824, 543); Input_Test (600, 559, 1299, 110); Input_Test (2683, 1112, 458, 27); Input_Test (1240, 882, 417, 1066); Input_Test (651, 667, 178, 3045); Input_Test (2089, 19, 879, 90); Input_Test (263, 423, 41, 734); Input_Test (630, 44, 135, 98); end case; r (part_1) := sum; end Do_Part_1; procedure Do_Part_2 is subtype XMAS_Rating_Range is Integer_64 range 1 .. 4000; sum : Integer_64 := 0; width_x, width_m, width_a, width_s : XMAS_Rating_Range; procedure Part_2_Mini is d_x : array (1 .. 5) of Positive; d_m : array (1 .. 6) of Positive; d_a : array (1 .. 5) of Positive; d_s : array (1 .. 6) of Positive; begin d_x (1) := 1; d_x (2) := 1416; d_x (3) := 2441; d_x (4) := 2663; d_x (5) := 4001; -- d_m (1) := 1; d_m (2) := 839; d_m (3) := 1549; d_m (4) := 1801; d_m (5) := 2091; d_m (6) := 4001; -- d_a (1) := 1; d_a (2) := 1717; d_a (3) := 2006; d_a (4) := 3334; d_a (5) := 4001; -- d_s (1) := 1; d_s (2) := 537; d_s (3) := 1351; d_s (4) := 2771; d_s (5) := 3449; d_s (6) := 4001; -- for i_x in 1 .. d_x'Last - 1 loop width_x := XMAS_Rating_Range (d_x (i_x + 1) - d_x (i_x)); x := d_x (i_x); for i_m in 1 .. d_m'Last - 1 loop width_m := XMAS_Rating_Range (d_m (i_m + 1) - d_m (i_m)); m := d_m (i_m); for i_a in 1 .. d_a'Last - 1 loop width_a := XMAS_Rating_Range (d_a (i_a + 1) - d_a (i_a)); a := d_a (i_a); for i_s in 1 .. d_s'Last - 1 loop width_s := XMAS_Rating_Range (d_s (i_s + 1) - d_s (i_s)); s := d_s (i_s); -- Test a point in the 4D rectangle m_in; if ok then sum := sum + width_x * width_m * width_a * width_s; end if; end loop; end loop; end loop; end loop; end Part_2_Mini; procedure Part_2_Input is d_x : array (1 .. 257) of Positive; d_m : array (1 .. 211) of Positive; d_a : array (1 .. 288) of Positive; d_s : array (1 .. 249) of Positive; begin -- The partitioning data was retrieved from the -- puzzle's program using Regexp, and Excel. -- In Excel, "> n" was replaced implicitly by ">= n + 1", -- which is the converse of "< n + 1". -- The boundaries (the n's) were then sorted and duplicates removed -- The presence of duplicates were spotted thanks to the -- XMAS_Rating_Range subtype used for the width_* variables. -- d_x (1) := 1; d_x (2) := 75; d_x (3) := 147; d_x (4) := 153; d_x (5) := 163; d_x (6) := 173; d_x (7) := 247; d_x (8) := 259; d_x (9) := 261; d_x (10) := 267; d_x (11) := 324; d_x (12) := 345; d_x (13) := 348; d_x (14) := 378; d_x (15) := 389; d_x (16) := 393; d_x (17) := 396; d_x (18) := 414; d_x (19) := 415; d_x (20) := 420; d_x (21) := 444; d_x (22) := 461; d_x (23) := 466; d_x (24) := 469; d_x (25) := 479; d_x (26) := 494; d_x (27) := 500; d_x (28) := 507; d_x (29) := 516; d_x (30) := 550; d_x (31) := 560; d_x (32) := 572; d_x (33) := 574; d_x (34) := 575; d_x (35) := 628; d_x (36) := 648; d_x (37) := 651; d_x (38) := 655; d_x (39) := 688; d_x (40) := 704; d_x (41) := 715; d_x (42) := 724; d_x (43) := 740; d_x (44) := 745; d_x (45) := 764; d_x (46) := 795; d_x (47) := 798; d_x (48) := 812; d_x (49) := 823; d_x (50) := 826; d_x (51) := 880; d_x (52) := 898; d_x (53) := 900; d_x (54) := 904; d_x (55) := 908; d_x (56) := 915; d_x (57) := 921; d_x (58) := 945; d_x (59) := 949; d_x (60) := 983; d_x (61) := 993; d_x (62) := 994; d_x (63) := 997; d_x (64) := 1004; d_x (65) := 1007; d_x (66) := 1024; d_x (67) := 1026; d_x (68) := 1033; d_x (69) := 1069; d_x (70) := 1075; d_x (71) := 1076; d_x (72) := 1082; d_x (73) := 1088; d_x (74) := 1093; d_x (75) := 1110; d_x (76) := 1158; d_x (77) := 1170; d_x (78) := 1185; d_x (79) := 1210; d_x (80) := 1211; d_x (81) := 1223; d_x (82) := 1228; d_x (83) := 1243; d_x (84) := 1256; d_x (85) := 1257; d_x (86) := 1260; d_x (87) := 1276; d_x (88) := 1279; d_x (89) := 1303; d_x (90) := 1311; d_x (91) := 1324; d_x (92) := 1335; d_x (93) := 1339; d_x (94) := 1340; d_x (95) := 1344; d_x (96) := 1347; d_x (97) := 1348; d_x (98) := 1359; d_x (99) := 1361; d_x (100) := 1363; d_x (101) := 1378; d_x (102) := 1393; d_x (103) := 1396; d_x (104) := 1402; d_x (105) := 1409; d_x (106) := 1416; d_x (107) := 1424; d_x (108) := 1431; d_x (109) := 1449; d_x (110) := 1450; d_x (111) := 1457; d_x (112) := 1478; d_x (113) := 1510; d_x (114) := 1539; d_x (115) := 1554; d_x (116) := 1567; d_x (117) := 1574; d_x (118) := 1607; d_x (119) := 1620; d_x (120) := 1632; d_x (121) := 1636; d_x (122) := 1654; d_x (123) := 1655; d_x (124) := 1677; d_x (125) := 1679; d_x (126) := 1680; d_x (127) := 1697; d_x (128) := 1698; d_x (129) := 1733; d_x (130) := 1734; d_x (131) := 1742; d_x (132) := 1756; d_x (133) := 1757; d_x (134) := 1797; d_x (135) := 1812; d_x (136) := 1823; d_x (137) := 1866; d_x (138) := 1871; d_x (139) := 1886; d_x (140) := 1887; d_x (141) := 1895; d_x (142) := 1898; d_x (143) := 1899; d_x (144) := 1912; d_x (145) := 1921; d_x (146) := 1957; d_x (147) := 1958; d_x (148) := 1959; d_x (149) := 2046; d_x (150) := 2048; d_x (151) := 2075; d_x (152) := 2076; d_x (153) := 2090; d_x (154) := 2144; d_x (155) := 2158; d_x (156) := 2163; d_x (157) := 2170; d_x (158) := 2175; d_x (159) := 2193; d_x (160) := 2237; d_x (161) := 2238; d_x (162) := 2250; d_x (163) := 2254; d_x (164) := 2261; d_x (165) := 2267; d_x (166) := 2270; d_x (167) := 2272; d_x (168) := 2274; d_x (169) := 2296; d_x (170) := 2302; d_x (171) := 2320; d_x (172) := 2327; d_x (173) := 2359; d_x (174) := 2381; d_x (175) := 2382; d_x (176) := 2405; d_x (177) := 2421; d_x (178) := 2447; d_x (179) := 2450; d_x (180) := 2461; d_x (181) := 2476; d_x (182) := 2480; d_x (183) := 2493; d_x (184) := 2500; d_x (185) := 2510; d_x (186) := 2514; d_x (187) := 2529; d_x (188) := 2541; d_x (189) := 2557; d_x (190) := 2559; d_x (191) := 2573; d_x (192) := 2579; d_x (193) := 2588; d_x (194) := 2596; d_x (195) := 2599; d_x (196) := 2603; d_x (197) := 2605; d_x (198) := 2614; d_x (199) := 2622; d_x (200) := 2623; d_x (201) := 2630; d_x (202) := 2638; d_x (203) := 2652; d_x (204) := 2665; d_x (205) := 2670; d_x (206) := 2685; d_x (207) := 2760; d_x (208) := 2769; d_x (209) := 2849; d_x (210) := 2904; d_x (211) := 2910; d_x (212) := 2947; d_x (213) := 2956; d_x (214) := 3053; d_x (215) := 3054; d_x (216) := 3067; d_x (217) := 3084; d_x (218) := 3102; d_x (219) := 3119; d_x (220) := 3126; d_x (221) := 3138; d_x (222) := 3153; d_x (223) := 3171; d_x (224) := 3212; d_x (225) := 3217; d_x (226) := 3229; d_x (227) := 3247; d_x (228) := 3257; d_x (229) := 3260; d_x (230) := 3275; d_x (231) := 3279; d_x (232) := 3285; d_x (233) := 3300; d_x (234) := 3301; d_x (235) := 3307; d_x (236) := 3317; d_x (237) := 3341; d_x (238) := 3342; d_x (239) := 3396; d_x (240) := 3411; d_x (241) := 3424; d_x (242) := 3429; d_x (243) := 3459; d_x (244) := 3466; d_x (245) := 3484; d_x (246) := 3524; d_x (247) := 3553; d_x (248) := 3568; d_x (249) := 3570; d_x (250) := 3571; d_x (251) := 3580; d_x (252) := 3609; d_x (253) := 3657; d_x (254) := 3670; d_x (255) := 3699; d_x (256) := 3720; d_x (257) := 4001; -- d_m (1) := 1; d_m (2) := 76; d_m (3) := 87; d_m (4) := 90; d_m (5) := 99; d_m (6) := 105; d_m (7) := 118; d_m (8) := 132; d_m (9) := 133; d_m (10) := 197; d_m (11) := 269; d_m (12) := 284; d_m (13) := 329; d_m (14) := 386; d_m (15) := 403; d_m (16) := 417; d_m (17) := 428; d_m (18) := 453; d_m (19) := 494; d_m (20) := 514; d_m (21) := 526; d_m (22) := 564; d_m (23) := 587; d_m (24) := 591; d_m (25) := 602; d_m (26) := 604; d_m (27) := 612; d_m (28) := 617; d_m (29) := 628; d_m (30) := 673; d_m (31) := 675; d_m (32) := 684; d_m (33) := 696; d_m (34) := 703; d_m (35) := 724; d_m (36) := 725; d_m (37) := 736; d_m (38) := 741; d_m (39) := 750; d_m (40) := 795; d_m (41) := 801; d_m (42) := 811; d_m (43) := 818; d_m (44) := 819; d_m (45) := 825; d_m (46) := 830; d_m (47) := 883; d_m (48) := 884; d_m (49) := 885; d_m (50) := 891; d_m (51) := 892; d_m (52) := 894; d_m (53) := 900; d_m (54) := 911; d_m (55) := 917; d_m (56) := 936; d_m (57) := 937; d_m (58) := 939; d_m (59) := 947; d_m (60) := 955; d_m (61) := 961; d_m (62) := 962; d_m (63) := 966; d_m (64) := 1009; d_m (65) := 1010; d_m (66) := 1013; d_m (67) := 1016; d_m (68) := 1028; d_m (69) := 1046; d_m (70) := 1068; d_m (71) := 1092; d_m (72) := 1117; d_m (73) := 1122; d_m (74) := 1133; d_m (75) := 1147; d_m (76) := 1153; d_m (77) := 1164; d_m (78) := 1165; d_m (79) := 1184; d_m (80) := 1231; d_m (81) := 1243; d_m (82) := 1248; d_m (83) := 1291; d_m (84) := 1293; d_m (85) := 1294; d_m (86) := 1352; d_m (87) := 1371; d_m (88) := 1380; d_m (89) := 1388; d_m (90) := 1402; d_m (91) := 1408; d_m (92) := 1411; d_m (93) := 1427; d_m (94) := 1434; d_m (95) := 1436; d_m (96) := 1438; d_m (97) := 1446; d_m (98) := 1453; d_m (99) := 1460; d_m (100) := 1469; d_m (101) := 1474; d_m (102) := 1494; d_m (103) := 1499; d_m (104) := 1500; d_m (105) := 1501; d_m (106) := 1508; d_m (107) := 1528; d_m (108) := 1540; d_m (109) := 1642; d_m (110) := 1657; d_m (111) := 1665; d_m (112) := 1679; d_m (113) := 1739; d_m (114) := 1762; d_m (115) := 1763; d_m (116) := 1775; d_m (117) := 1781; d_m (118) := 1790; d_m (119) := 1812; d_m (120) := 1840; d_m (121) := 1867; d_m (122) := 1869; d_m (123) := 1900; d_m (124) := 1908; d_m (125) := 1917; d_m (126) := 1940; d_m (127) := 1978; d_m (128) := 1983; d_m (129) := 2007; d_m (130) := 2008; d_m (131) := 2011; d_m (132) := 2013; d_m (133) := 2025; d_m (134) := 2062; d_m (135) := 2082; d_m (136) := 2093; d_m (137) := 2114; d_m (138) := 2142; d_m (139) := 2208; d_m (140) := 2252; d_m (141) := 2270; d_m (142) := 2274; d_m (143) := 2308; d_m (144) := 2314; d_m (145) := 2332; d_m (146) := 2349; d_m (147) := 2384; d_m (148) := 2416; d_m (149) := 2418; d_m (150) := 2423; d_m (151) := 2448; d_m (152) := 2462; d_m (153) := 2477; d_m (154) := 2526; d_m (155) := 2576; d_m (156) := 2607; d_m (157) := 2610; d_m (158) := 2642; d_m (159) := 2661; d_m (160) := 2693; d_m (161) := 2725; d_m (162) := 2760; d_m (163) := 2828; d_m (164) := 2856; d_m (165) := 2878; d_m (166) := 2888; d_m (167) := 2925; d_m (168) := 2926; d_m (169) := 2947; d_m (170) := 2952; d_m (171) := 2968; d_m (172) := 3006; d_m (173) := 3015; d_m (174) := 3050; d_m (175) := 3104; d_m (176) := 3116; d_m (177) := 3162; d_m (178) := 3171; d_m (179) := 3195; d_m (180) := 3225; d_m (181) := 3271; d_m (182) := 3282; d_m (183) := 3299; d_m (184) := 3305; d_m (185) := 3306; d_m (186) := 3325; d_m (187) := 3326; d_m (188) := 3344; d_m (189) := 3349; d_m (190) := 3381; d_m (191) := 3383; d_m (192) := 3384; d_m (193) := 3405; d_m (194) := 3442; d_m (195) := 3468; d_m (196) := 3471; d_m (197) := 3503; d_m (198) := 3505; d_m (199) := 3512; d_m (200) := 3587; d_m (201) := 3603; d_m (202) := 3604; d_m (203) := 3633; d_m (204) := 3681; d_m (205) := 3694; d_m (206) := 3738; d_m (207) := 3803; d_m (208) := 3831; d_m (209) := 3863; d_m (210) := 3882; d_m (211) := 4001; -- d_a (1) := 1; d_a (2) := 67; d_a (3) := 75; d_a (4) := 117; d_a (5) := 134; d_a (6) := 138; d_a (7) := 149; d_a (8) := 191; d_a (9) := 220; d_a (10) := 225; d_a (11) := 246; d_a (12) := 270; d_a (13) := 279; d_a (14) := 280; d_a (15) := 292; d_a (16) := 297; d_a (17) := 320; d_a (18) := 330; d_a (19) := 332; d_a (20) := 365; d_a (21) := 379; d_a (22) := 380; d_a (23) := 383; d_a (24) := 385; d_a (25) := 388; d_a (26) := 400; d_a (27) := 417; d_a (28) := 432; d_a (29) := 435; d_a (30) := 440; d_a (31) := 441; d_a (32) := 449; d_a (33) := 463; d_a (34) := 513; d_a (35) := 527; d_a (36) := 536; d_a (37) := 540; d_a (38) := 550; d_a (39) := 555; d_a (40) := 557; d_a (41) := 570; d_a (42) := 587; d_a (43) := 593; d_a (44) := 612; d_a (45) := 616; d_a (46) := 631; d_a (47) := 633; d_a (48) := 654; d_a (49) := 657; d_a (50) := 672; d_a (51) := 677; d_a (52) := 693; d_a (53) := 702; d_a (54) := 710; d_a (55) := 715; d_a (56) := 719; d_a (57) := 763; d_a (58) := 770; d_a (59) := 773; d_a (60) := 815; d_a (61) := 827; d_a (62) := 832; d_a (63) := 862; d_a (64) := 886; d_a (65) := 900; d_a (66) := 905; d_a (67) := 949; d_a (68) := 966; d_a (69) := 987; d_a (70) := 988; d_a (71) := 1008; d_a (72) := 1021; d_a (73) := 1023; d_a (74) := 1032; d_a (75) := 1033; d_a (76) := 1043; d_a (77) := 1050; d_a (78) := 1051; d_a (79) := 1075; d_a (80) := 1088; d_a (81) := 1096; d_a (82) := 1100; d_a (83) := 1106; d_a (84) := 1107; d_a (85) := 1109; d_a (86) := 1122; d_a (87) := 1124; d_a (88) := 1129; d_a (89) := 1137; d_a (90) := 1144; d_a (91) := 1149; d_a (92) := 1156; d_a (93) := 1175; d_a (94) := 1182; d_a (95) := 1184; d_a (96) := 1200; d_a (97) := 1217; d_a (98) := 1220; d_a (99) := 1254; d_a (100) := 1262; d_a (101) := 1286; d_a (102) := 1348; d_a (103) := 1354; d_a (104) := 1399; d_a (105) := 1401; d_a (106) := 1415; d_a (107) := 1418; d_a (108) := 1424; d_a (109) := 1443; d_a (110) := 1477; d_a (111) := 1524; d_a (112) := 1605; d_a (113) := 1613; d_a (114) := 1636; d_a (115) := 1639; d_a (116) := 1671; d_a (117) := 1679; d_a (118) := 1725; d_a (119) := 1727; d_a (120) := 1752; d_a (121) := 1760; d_a (122) := 1774; d_a (123) := 1820; d_a (124) := 1853; d_a (125) := 1881; d_a (126) := 1891; d_a (127) := 1913; d_a (128) := 1935; d_a (129) := 1939; d_a (130) := 1950; d_a (131) := 1964; d_a (132) := 1967; d_a (133) := 1971; d_a (134) := 1981; d_a (135) := 1984; d_a (136) := 1998; d_a (137) := 2055; d_a (138) := 2127; d_a (139) := 2141; d_a (140) := 2205; d_a (141) := 2209; d_a (142) := 2226; d_a (143) := 2248; d_a (144) := 2253; d_a (145) := 2263; d_a (146) := 2267; d_a (147) := 2271; d_a (148) := 2306; d_a (149) := 2312; d_a (150) := 2318; d_a (151) := 2321; d_a (152) := 2357; d_a (153) := 2368; d_a (154) := 2369; d_a (155) := 2399; d_a (156) := 2413; d_a (157) := 2451; d_a (158) := 2455; d_a (159) := 2468; d_a (160) := 2472; d_a (161) := 2478; d_a (162) := 2503; d_a (163) := 2538; d_a (164) := 2541; d_a (165) := 2545; d_a (166) := 2558; d_a (167) := 2569; d_a (168) := 2570; d_a (169) := 2640; d_a (170) := 2663; d_a (171) := 2671; d_a (172) := 2684; d_a (173) := 2685; d_a (174) := 2704; d_a (175) := 2706; d_a (176) := 2714; d_a (177) := 2731; d_a (178) := 2773; d_a (179) := 2776; d_a (180) := 2787; d_a (181) := 2796; d_a (182) := 2800; d_a (183) := 2806; d_a (184) := 2808; d_a (185) := 2813; d_a (186) := 2825; d_a (187) := 2829; d_a (188) := 2842; d_a (189) := 2843; d_a (190) := 2848; d_a (191) := 2860; d_a (192) := 2861; d_a (193) := 2869; d_a (194) := 2874; d_a (195) := 2877; d_a (196) := 2881; d_a (197) := 2884; d_a (198) := 2886; d_a (199) := 2887; d_a (200) := 2888; d_a (201) := 2912; d_a (202) := 2948; d_a (203) := 2977; d_a (204) := 2978; d_a (205) := 2981; d_a (206) := 2982; d_a (207) := 2999; d_a (208) := 3031; d_a (209) := 3045; d_a (210) := 3055; d_a (211) := 3060; d_a (212) := 3064; d_a (213) := 3069; d_a (214) := 3077; d_a (215) := 3095; d_a (216) := 3111; d_a (217) := 3115; d_a (218) := 3118; d_a (219) := 3126; d_a (220) := 3132; d_a (221) := 3147; d_a (222) := 3150; d_a (223) := 3153; d_a (224) := 3170; d_a (225) := 3177; d_a (226) := 3182; d_a (227) := 3194; d_a (228) := 3206; d_a (229) := 3208; d_a (230) := 3222; d_a (231) := 3243; d_a (232) := 3247; d_a (233) := 3279; d_a (234) := 3297; d_a (235) := 3302; d_a (236) := 3308; d_a (237) := 3309; d_a (238) := 3311; d_a (239) := 3324; d_a (240) := 3327; d_a (241) := 3341; d_a (242) := 3373; d_a (243) := 3374; d_a (244) := 3377; d_a (245) := 3400; d_a (246) := 3403; d_a (247) := 3419; d_a (248) := 3424; d_a (249) := 3448; d_a (250) := 3454; d_a (251) := 3456; d_a (252) := 3469; d_a (253) := 3472; d_a (254) := 3498; d_a (255) := 3517; d_a (256) := 3522; d_a (257) := 3525; d_a (258) := 3531; d_a (259) := 3556; d_a (260) := 3578; d_a (261) := 3583; d_a (262) := 3605; d_a (263) := 3608; d_a (264) := 3635; d_a (265) := 3663; d_a (266) := 3686; d_a (267) := 3692; d_a (268) := 3700; d_a (269) := 3707; d_a (270) := 3726; d_a (271) := 3727; d_a (272) := 3750; d_a (273) := 3751; d_a (274) := 3752; d_a (275) := 3757; d_a (276) := 3783; d_a (277) := 3784; d_a (278) := 3793; d_a (279) := 3796; d_a (280) := 3798; d_a (281) := 3818; d_a (282) := 3831; d_a (283) := 3894; d_a (284) := 3908; d_a (285) := 3916; d_a (286) := 3933; d_a (287) := 3967; d_a (288) := 4001; -- d_s (1) := 1; d_s (2) := 68; d_s (3) := 84; d_s (4) := 112; d_s (5) := 205; d_s (6) := 239; d_s (7) := 241; d_s (8) := 324; d_s (9) := 361; d_s (10) := 400; d_s (11) := 403; d_s (12) := 425; d_s (13) := 434; d_s (14) := 450; d_s (15) := 458; d_s (16) := 463; d_s (17) := 468; d_s (18) := 474; d_s (19) := 478; d_s (20) := 489; d_s (21) := 500; d_s (22) := 501; d_s (23) := 521; d_s (24) := 524; d_s (25) := 539; d_s (26) := 555; d_s (27) := 572; d_s (28) := 648; d_s (29) := 672; d_s (30) := 708; d_s (31) := 716; d_s (32) := 734; d_s (33) := 739; d_s (34) := 799; d_s (35) := 872; d_s (36) := 907; d_s (37) := 912; d_s (38) := 950; d_s (39) := 1044; d_s (40) := 1091; d_s (41) := 1118; d_s (42) := 1127; d_s (43) := 1158; d_s (44) := 1164; d_s (45) := 1166; d_s (46) := 1203; d_s (47) := 1214; d_s (48) := 1362; d_s (49) := 1385; d_s (50) := 1414; d_s (51) := 1450; d_s (52) := 1455; d_s (53) := 1470; d_s (54) := 1492; d_s (55) := 1501; d_s (56) := 1505; d_s (57) := 1510; d_s (58) := 1515; d_s (59) := 1540; d_s (60) := 1553; d_s (61) := 1570; d_s (62) := 1602; d_s (63) := 1606; d_s (64) := 1608; d_s (65) := 1630; d_s (66) := 1632; d_s (67) := 1636; d_s (68) := 1638; d_s (69) := 1648; d_s (70) := 1662; d_s (71) := 1686; d_s (72) := 1699; d_s (73) := 1701; d_s (74) := 1704; d_s (75) := 1718; d_s (76) := 1722; d_s (77) := 1753; d_s (78) := 1774; d_s (79) := 1797; d_s (80) := 1800; d_s (81) := 1804; d_s (82) := 1808; d_s (83) := 1819; d_s (84) := 1821; d_s (85) := 1826; d_s (86) := 1851; d_s (87) := 1890; d_s (88) := 1892; d_s (89) := 1894; d_s (90) := 1899; d_s (91) := 1900; d_s (92) := 1903; d_s (93) := 1906; d_s (94) := 1908; d_s (95) := 1970; d_s (96) := 2004; d_s (97) := 2013; d_s (98) := 2024; d_s (99) := 2047; d_s (100) := 2056; d_s (101) := 2080; d_s (102) := 2110; d_s (103) := 2120; d_s (104) := 2183; d_s (105) := 2205; d_s (106) := 2208; d_s (107) := 2234; d_s (108) := 2245; d_s (109) := 2258; d_s (110) := 2270; d_s (111) := 2292; d_s (112) := 2342; d_s (113) := 2360; d_s (114) := 2361; d_s (115) := 2371; d_s (116) := 2445; d_s (117) := 2469; d_s (118) := 2479; d_s (119) := 2535; d_s (120) := 2548; d_s (121) := 2555; d_s (122) := 2581; d_s (123) := 2589; d_s (124) := 2590; d_s (125) := 2621; d_s (126) := 2655; d_s (127) := 2658; d_s (128) := 2686; d_s (129) := 2712; d_s (130) := 2715; d_s (131) := 2737; d_s (132) := 2740; d_s (133) := 2748; d_s (134) := 2753; d_s (135) := 2767; d_s (136) := 2773; d_s (137) := 2782; d_s (138) := 2801; d_s (139) := 2806; d_s (140) := 2815; d_s (141) := 2821; d_s (142) := 2826; d_s (143) := 2872; d_s (144) := 2873; d_s (145) := 2878; d_s (146) := 2883; d_s (147) := 2885; d_s (148) := 2887; d_s (149) := 2904; d_s (150) := 2912; d_s (151) := 2918; d_s (152) := 2943; d_s (153) := 2963; d_s (154) := 2983; d_s (155) := 2999; d_s (156) := 3000; d_s (157) := 3009; d_s (158) := 3014; d_s (159) := 3018; d_s (160) := 3054; d_s (161) := 3059; d_s (162) := 3070; d_s (163) := 3077; d_s (164) := 3082; d_s (165) := 3086; d_s (166) := 3088; d_s (167) := 3101; d_s (168) := 3104; d_s (169) := 3105; d_s (170) := 3106; d_s (171) := 3109; d_s (172) := 3124; d_s (173) := 3126; d_s (174) := 3136; d_s (175) := 3141; d_s (176) := 3158; d_s (177) := 3162; d_s (178) := 3163; d_s (179) := 3175; d_s (180) := 3185; d_s (181) := 3205; d_s (182) := 3213; d_s (183) := 3217; d_s (184) := 3218; d_s (185) := 3226; d_s (186) := 3227; d_s (187) := 3228; d_s (188) := 3245; d_s (189) := 3246; d_s (190) := 3252; d_s (191) := 3259; d_s (192) := 3261; d_s (193) := 3266; d_s (194) := 3274; d_s (195) := 3278; d_s (196) := 3288; d_s (197) := 3294; d_s (198) := 3295; d_s (199) := 3296; d_s (200) := 3298; d_s (201) := 3301; d_s (202) := 3318; d_s (203) := 3342; d_s (204) := 3343; d_s (205) := 3344; d_s (206) := 3366; d_s (207) := 3367; d_s (208) := 3369; d_s (209) := 3377; d_s (210) := 3380; d_s (211) := 3387; d_s (212) := 3412; d_s (213) := 3435; d_s (214) := 3449; d_s (215) := 3455; d_s (216) := 3471; d_s (217) := 3472; d_s (218) := 3487; d_s (219) := 3495; d_s (220) := 3532; d_s (221) := 3546; d_s (222) := 3562; d_s (223) := 3569; d_s (224) := 3572; d_s (225) := 3574; d_s (226) := 3584; d_s (227) := 3613; d_s (228) := 3617; d_s (229) := 3625; d_s (230) := 3635; d_s (231) := 3664; d_s (232) := 3673; d_s (233) := 3684; d_s (234) := 3688; d_s (235) := 3715; d_s (236) := 3728; d_s (237) := 3733; d_s (238) := 3740; d_s (239) := 3752; d_s (240) := 3763; d_s (241) := 3773; d_s (242) := 3780; d_s (243) := 3793; d_s (244) := 3802; d_s (245) := 3812; d_s (246) := 3841; d_s (247) := 3855; d_s (248) := 3879; d_s (249) := 4001; -- for i_x in 1 .. d_x'Last - 1 loop width_x := XMAS_Rating_Range (d_x (i_x + 1) - d_x (i_x)); x := d_x (i_x); for i_m in 1 .. d_m'Last - 1 loop width_m := XMAS_Rating_Range (d_m (i_m + 1) - d_m (i_m)); m := d_m (i_m); for i_a in 1 .. d_a'Last - 1 loop width_a := XMAS_Rating_Range (d_a (i_a + 1) - d_a (i_a)); a := d_a (i_a); for i_s in 1 .. d_s'Last - 1 loop width_s := XMAS_Rating_Range (d_s (i_s + 1) - d_s (i_s)); s := d_s (i_s); -- Test a point in the 4D rectangle inn; if ok then sum := sum + width_x * width_m * width_a * width_s; end if; end loop; end loop; end loop; end loop; end Part_2_Input; begin case choice is when mini => Part_2_Mini; when input => Part_2_Input; end case; r (part_2) := sum; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin if compiler_test_mode then choice := mini; else choice := input; end if; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 330820 (example: 19114) -- Part 2: validated by AoC: 123972546935551 (example: 167409079868000) end if; end AoC_2023_19; ================================================ FILE: exm/aoc/2023/aoc_2023_19.txt ================================================ fzf{m<1642:A,px} qqp{s>3732:R,m>946:R,a<1401:A,A} mqh{x>1081:A,m<3344:R,m>3632:R,A} bnk{a>2841:R,s<3562:R,x>3483:A,A} jt{a>3076:A,s<2748:A,s>2805:R,A} vl{x>2613:sv,a>2454:lhx,jg} bhj{x>2768:jhd,mhd} ggs{x>3053:R,x>2848:R,R} lx{a>3685:A,bn} hcz{x>763:R,s<2753:A,R} mnr{x>1157:R,R} cpd{a<320:A,m>1387:bz,A} lbm{s<3387:R,s>3672:R,a<3818:R,A} npb{a<1149:dmc,tgt} bsh{x<1228:R,R} px{x>1003:A,a>3750:A,A} jl{a<1881:R,m>1146:R,s<400:A,R} cs{s<3185:A,A} krx{x<3153:A,a<2570:R,A} dp{a>3221:A,A} zxh{s<2883:R,vb} dtj{x<1574:A,m<961:A,m>1183:R,R} mhd{a<2806:vtt,R} mll{s<2589:fs,rct} nbf{x<2665:sgr,A} jr{a>3301:tc,x>996:dh,a>2980:ncl,A} lxc{x<1450:R,m>899:A,x>1653:A,R} xfp{a>586:pbx,xzk} crf{s>3081:R,a>1253:A,s<2740:R,A} mc{a<330:A,a>440:A,x>2613:R,A} lcl{m>1452:mls,R} scv{a>653:R,a<385:A,s>2291:mcm,A} jg{m>2877:gqc,a>2247:R,A} kbt{a<75:A,x>3256:R,a>137:A,R} cmf{m<795:R,A} zxc{a<1971:A,a>2270:R,A} lms{s>323:tfs,A} mgs{x<2480:A,a<1050:A,R} kz{s<3266:zg,a<2977:A,vqn} lh{x>1958:pkf,m>3511:hx,mk} db{m<1657:xvn,nsd} gbg{m<1371:A,x>3428:A,s<3077:A,R} gz{s<3104:A,m<2828:A,m>3281:R,R} hpl{a>3117:A,ft} zg{x<1698:R,R} vqv{a>1031:A,x>2460:A,x<1912:A,R} vb{m<1499:A,x>1894:R,R} xkq{s<1553:cng,s<3162:tkj,mlj} ngz{a<3373:A,s>402:A,s>204:A,A} dq{m<801:rmb,a<2127:A,R} kh{x>1408:A,A} jfk{a>1219:qkz,s<1492:mt,m<2952:gkl,khv} pl{s>3123:R,A} tdg{a>1983:A,a<1853:gx,x>1678:kkc,qcb} nlk{a<2055:R,zmn} sxc{s<1553:R,R} nzx{a<2569:A,x<1812:cbv,A} cph{m<2856:A,A} pxx{x<3670:qnj,m<3015:R,a<3243:R,A} bnz{a<949:lsz,s>1899:hcp,s>1631:A,ntl} tv{m<1352:R,m<1812:A,R} qkz{a<2141:crk,x<1866:rlz,vl} qrp{a>3607:R,m<2423:lj,qqj} blf{s<1970:R,R} xrc{x<2476:rjx,a>1724:tj,pbt} nr{m>2092:hzc,A} jld{s<1570:A,ps} nk{a<3132:R,R} rgl{a<2558:A,R} rl{a<1021:A,R} bjq{s<2821:R,s<2872:A,R} qnj{s>1202:R,s>488:R,R} bxb{m<911:A,x>468:bnx,s>3663:R,R} ksl{x<688:A,x>1068:A,R} qzz{a>1963:sdm,s<1753:R,cgx} xmx{m<1231:qnv,m>1789:nsx,s>1698:xrp,A} bqt{x>392:R,A} nx{m<3603:R,s<2999:mg,m>3830:R,A} kfr{a<2455:jf,m>1009:nzx,x<2605:cgv,sm} rzc{m<3116:R,x>1302:R,s<2205:R,shf} zbv{m<3299:R,x<740:A,R} qds{a<3031:tg,a<3095:pp,x>2192:bf,cgf} zz{m<602:R,m>616:A,A} ctn{s<1118:qvc,jzc} mv{m>3603:R,s<1044:R,A} pm{m>2113:kd,a>278:A,R} vcd{m<1762:A,R} dn{m>2924:R,A} cjf{a<886:jsn,s>538:hp,R} fcr{s>738:vnp,s>647:cz,A} kf{a<2869:R,m<1983:R,A} zf{m>1116:vh,m<741:ljn,xz} npl{m<604:R,x<2557:A,s>3273:A,lzl} hxj{x>1696:lgt,hxt} bk{m>2024:kqk,m>1977:A,A} cgf{m>1839:mdc,nk} fj{s<3773:R,A} tvz{m<725:A,R} nsd{a>549:A,rm} ptj{a>2544:R,s<474:R,R} jcf{a>3207:R,R} jf{x>1679:R,hmd} frc{a>3423:R,s<3574:R,R} fs{s<2535:R,s>2554:R,s>2547:R,R} gkt{x<3699:A,s<1808:R,R} lk{x>1920:vgq,x<915:vc,s>911:dcg,pjd} cpv{s<84:R,A} hr{m>3382:mdn,x<1457:cph,vp} fm{x<1347:kxk,dl} rh{m>1468:A,a<3525:ngz,R} bj{x>574:R,a<2312:A,R} qqj{x>1087:R,A} vs{x>1075:vcd,m<1978:jv,jr} clk{x<444:R,m<2947:A,s<3126:A,A} qrq{s>2012:R,a<1950:A,A} blm{m<1460:rj,m>2331:pxx,s<1091:bmk,kq} bh{x>1415:hj,a>1216:tr,cj} qq{a<3194:qdz,rg} pqb{s<3296:A,R} lj{s<3684:R,s<3855:R,a<3556:R,A} ktn{a>3308:R,x>2669:A,A} bxg{a>1442:A,a>1347:A,A} ksd{s<3546:mr,rhb} pt{x<1007:A,s<3086:R,a<2912:R,R} rtk{a<2468:A,s>1601:A,R} tck{a>1635:tlj,m<329:xhx,hc} jzc{a<1524:zrf,m>1067:pr,x>1870:bls,rrx} csz{a>762:bnz,x<3126:qv,s>1898:csr,skm} qps{a>615:cjf,s>671:pm,s>240:dbl,nl} lp{x<3084:A,s<3733:A,R} blx{m>131:R,R} ctt{a<3522:nxf,x>1395:cnb,jzr} xrp{x<574:R,m<1446:R,A} sm{m<795:ptj,m>883:R,x<3307:A,sbd} plc{x>559:R,a>3782:R,s>3878:R,A} bnx{m<1013:A,A} dz{s<3377:R,m>2092:R,A} fpz{m>695:tvz,s<3213:qnp,a<1023:R,R} mcm{a<540:A,R} vgq{x<3260:xp,blm} hrl{s>571:fcr,a>3310:lms,a>3059:dn,cc} sgr{a<2253:R,a>2477:R,x>1631:A,R} kbm{a<773:R,x<500:xs,A} dmc{x>811:ddf,m>1293:ckz,R} jx{x<147:A,s<3246:R,A} xbr{s<3780:A,A} cz{m>3005:A,x<1279:A,R} zh{m>2724:R,A} mx{a>2368:R,s<2360:R,x<3285:A,R} pz{x>1619:A,a>965:R,x<1449:A,R} rt{a>1181:R,x>2446:R,A} lbk{a>2730:fz,hs} cpm{a<3279:rsn,m<1164:dcz,x>1415:mcq,rh} km{m>3737:A,a>3725:R,R} qzx{s>1504:R,s>1454:R,x<415:A,A} hp{x<2493:R,s<1127:A,R} sj{m>683:R,x<1742:A,s<2208:R,A} rs{m<1908:tnp,x<1393:R,A} xp{m>1774:ktn,a<3517:bq,gj} cbr{a>2266:R,m<819:A,A} gcm{a<3170:A,a<3297:R,R} kj{s>3251:bnk,x<3524:A,A} lxb{a<536:A,a>630:R,s<1570:A,R} rsn{m<1293:R,R} jbk{x>3170:A,a>1074:R,A} zv{x>2404:A,s>457:jmf,A} jps{a<593:R,ggb} mth{x>3569:gbv,ds} mgd{s>2772:R,x<173:A,A} rnh{x>460:vn,x>266:pl,a<2800:hvz,R} psj{s<3000:R,s<3141:A,R} qcb{x<798:A,x>1338:A,A} shf{s<2342:R,A} bgd{m>2415:nzb,s>3123:ld,lcl} mlt{s<3301:A,m>2092:R,A} vtt{a<2787:R,m<1501:A,R} gk{a<815:A,s>2886:R,R} vnq{x<655:A,s<3763:R,A} spg{a<1477:R,R} kqk{a>986:R,A} zrf{a>904:gg,m<1153:ljh,s<1804:jld,cpd} ltl{x>1025:mh,a<2706:mlt,mq} kkc{a<1939:R,a>1966:R,A} pk{s<3412:fzf,a>3726:hxs,qrp} jct{x>2955:A,czg} pbh{a>1099:A,R} bkc{x<994:R,R} lmm{m>3383:R,a>2887:A,A} jjm{a>2703:lbk,fpj} td{x<247:mpf,s>3739:tzv,gf} mdn{a<3498:R,R} st{s<3009:A,a>1143:rt,a<1107:rgz,qzr} sts{a<1200:R,m<87:A,m>132:A,A} pr{x>2249:dtm,qzz} ds{s<3752:A,R} dmp{m<3305:R,a<463:A,m<3681:cm,R} sdr{a>3376:vdv,zbv} nst{s>2046:cbr,mfn} mk{a<388:R,pmb} pkf{s>499:mv,A} szs{m<3349:sq,a>718:A,gc} zs{m<2661:R,A} vp{x>1477:R,s>2269:R,A} dl{s<1214:R,qp} lb{x<3138:A,a>2670:R,R} kl{m>3862:A,x>1259:mqj,x<1033:zn,blf} hlx{a<2205:R,x>3579:A,s<1636:A,R} hz{x>1358:A,x<1311:R,A} lv{s>424:R,a>3455:R,m>513:A,A} qs{a<3308:A,x>723:R,R} gqc{x<2158:R,s<1851:R,R} mpf{a>3792:A,a>3662:mml,a>3577:R,xk} dm{m>3103:A,x<1276:R,A} vq{s>2244:hz,x>1360:A,A} rrx{s>1629:nst,s>1413:xnv,dq} hxg{x<324:mgd,x<469:dj,gr} pj{a<3150:A,a<3454:A,x>1606:A,R} gjs{a<2848:A,x<651:A,R} nbz{x<2579:rtg,bvg} tkj{x<2510:zx,x>3340:blx,a>1123:ggs,ctb} rk{m<105:A,s<2581:R,s>3343:A,R} gr{s>2781:R,m>938:A,a<3798:A,A} zlr{s>2444:A,R} qzq{x>260:R,s>2233:R,A} qb{a<3400:tv,x<1211:lbl,s<3532:A,A} jkl{a>569:R,a>219:A,A} kd{a<332:A,s>1163:A,a<441:A,R} ztq{s<1701:xg,s>1889:dmp,x>944:szs,kbm} vtl{s<1362:R,m>1164:R,s>1500:A,A} tj{x>3274:A,s<708:A,a<1760:R,A} dhp{a>3146:qzq,R} bn{x<466:R,A} jv{a<3111:R,bkc} pjd{m<2011:cpm,hrl} fh{a<3064:R,s<2885:jt,x>920:R,clk} gf{s>3568:A,jcs} cnb{x>2602:bgd,lpq} rjs{x<3342:A,x>3570:R,a<1033:A,R} sl{m>1009:fvp,spg} dd{a<3115:A,R} hl{a<3182:R,x<2541:A,s>1661:R,A} zc{m>3224:R,x<1402:A,R} jhv{a>2713:A,nh} rjx{s>715:R,s<450:R,R} bp{a>3418:R,a>2981:A,R} rj{m>817:bp,A} mmc{a>2356:bsh,A} jzr{x>627:pk,s<3294:jjc,td} hj{a<1124:R,A} lpx{x>1886:R,s<521:R,a<379:A,R} vxl{x>1956:A,R} ncl{m>2887:A,A} hxs{a>3893:zgx,a>3783:A,R} xv{a>245:A,lg} pfl{a<440:R,A} jhd{a<2796:A,a<2813:R,A} vjn{x<2270:R,s<1166:A,A} gdk{a>2886:qds,x>1553:jkf,gmg} ljv{m>954:A,bqt} rf{m<2314:A,R} zpb{s>1717:A,a>434:R,A} xgr{s<2801:gd,x>2319:tb,nv} ln{a<3324:A,a<3448:A,x>1756:R,A} ntl{s<1540:R,x<2910:A,x>3423:A,R} fg{m<3195:R,A} kq{m<1917:R,A} mln{m>674:dtc,x<3229:tl,s<3218:A,A} sjq{x<2421:R,s<3380:zz,lp} rpm{s>67:R,x<2573:A,A} jc{s<799:A,m>3802:A,R} lvq{x>3719:A,s<3613:ghp,a<1156:R,A} cc{m>3325:A,m<2610:R,m>3049:zc,xxd} kxk{m<1500:A,a>3205:R,m<2576:R,lmm} qqs{s>3227:A,s>2736:R,x<2614:kqb,kbt} lzl{a>399:R,A} sh{x<2261:R,R} pzx{a<1051:R,R} mrc{x<2382:R,a<693:A,R} sx{x>3458:A,A} sv{a>2471:krx,a<2306:A,a<2413:mx,A} jmf{a<292:R,m>1008:A,A} hs{m<2526:R,x>2622:R,R} ljn{m>627:pf,m>586:cfj,bh} mq{x>903:A,s>3293:A,R} gc{a<365:A,a<570:R,R} zjx{m>2207:R,R} kqb{m<602:R,A} xr{s<3802:R,R} lhx{m>3170:A,rgl} kct{a<1891:ttc,zm} vn{a>2795:A,s<3343:A,A} bvg{a>1980:A,R} tzr{a>2885:A,s<3105:R,A} ghp{s>3260:A,A} ljh{m>884:zpb,A} crk{s<1819:zgv,m<3162:lz,a<1774:kh,nx} ttc{x<2046:R,A} hmd{a<2368:R,m>1132:R,x<1075:A,A} tb{s>3294:R,s>2982:A,x<3285:A,R} skm{s>1721:gkt,a>382:lxb,s>1637:A,A} bmk{x<3657:fl,a<3341:R,R} frf{m<2252:xmx,s<1800:bb,x>515:sdr,dhp} grp{a>1183:R,x>2651:R,R} qzr{a>1128:R,a>1121:A,A} xxd{x>1538:A,a>2807:R,s<361:R,A} nvs{s<2686:R,a>148:R,A} sbd{a>2540:R,a>2502:A,x<3553:R,R} rmb{x<949:A,x<1340:R,R} sbh{x>3465:zxc,m>810:A,qrq} kmc{m>2641:mqh,R} ks{m<1434:vq,m<2308:rs,x>1362:hr,rzc} dxl{x>2295:R,a>2873:A,s<3812:A,R} czp{m<90:A,x>3608:A,s<1450:A,R} lbl{x>571:A,R} mbj{x>2946:A,s<1470:cmf,x<2327:R,A} jsn{s>871:A,x>2587:A,A} qjg{s>3258:R,m>2447:A,x>549:A,A} tq{s<2590:lk,a<3153:gdk,ctt} qnp{s>2942:R,s<2748:R,R} gnb{s>1449:R,a<3469:A,R} xq{x<740:R,x>822:A,s>1796:A,R} ddr{x>825:kmc,a<2829:rnh,hb} nl{s<112:rpm,R} bgz{s<3472:A,s<3715:frc,s>3840:R,fj} xd{s<3101:bv,a<3302:jcf,s<3572:jh,xr} rxc{m>891:A,A} gj{m<673:R,zds} nzb{m<3405:R,lbm} gg{a<1286:mgs,m>935:bxg,x<2090:A,R} lcg{m<1248:A,s>3297:A,s>2766:A,R} gq{x<3301:mz,lvq} cng{x>2558:rjs,x>992:sts,vfk} gkl{m>2141:dfh,m<1900:db,x>1897:vd,sp} zx{m>98:R,R} jcs{m<1494:A,x<389:A,a>3699:A,R} sdm{a>2317:A,R} btg{s>1891:A,x<2144:A,s>906:A,R} rq{x<2267:R,a<513:R,x<3300:A,A} fpj{s>3216:lb,a>2662:R,s<2815:A,psj} vd{a<417:xv,a>769:bk,jps} qvd{a>1423:kct,a<832:cql,xkq} nxf{m>2417:xd,rc} rhb{a<3055:R,A} hq{s>949:zd,vcn} qv{a<270:nls,x<2596:A,R} hv{a>116:A,a<67:R,s<2371:R,A} ttv{a<3583:R,a<3757:R,s>500:R,A} nv{a>1042:A,x<1348:A,R} cgx{a>1726:A,A} mz{s>3365:qqp,R} jnn{x>2684:A,m<1408:R,A} vf{x<715:A,A} gfk{a<633:zv,a>1261:vxl,cr} dcg{x<1256:vs,x>1509:hxj,s>1703:ks,fm} mp{m>1507:jfk,m<526:cv,s>2468:zf,ctn} mg{x<1958:A,a>1912:A,A} hzc{s>3226:A,x>2499:A,a<2843:A,R} nc{m<494:R,R} vlr{a<1639:R,m>965:A,R} xkx{s<2878:R,s<3070:R,A} bb{a>3530:R,s<1510:A,R} nh{x>1430:R,a>2684:A,m<2349:A,R} dh{x<1024:R,A} gmg{a>2772:ddr,cl} cl{x<745:qmm,x<1185:ltl,jhv} xkb{s<1903:R,x>2528:R,R} cbb{m<1781:A,qr} fr{s<3106:slq,R} mh{m>2269:A,x<1093:A,a<2684:A,R} cv{m<197:qvd,tck} mlj{s<3617:pzx,sh} dcz{a<3605:lv,a<3752:A,s<468:R,R} vcn{s<524:R,x<1378:R,vqv} kqs{x<1335:R,lr} mcq{x>1676:ttv,A} hxt{s<2024:gnb,m>1410:pj,m<736:R,dtj} ld{s<3688:ggh,s<3793:A,m>1290:A,A} xs{x>258:A,s<1774:R,R} mfn{s<1906:R,A} qfs{m>1437:R,R} tx{a<3403:jzm,tn} rct{m<1016:A,s<2621:R,R} nd{s>3135:A,R} jjc{s>2911:mhf,m<1665:hxg,x<348:qcr,lx} gtq{m>961:xbr,m<830:A,x<507:A,vnq} cx{m>268:A,A} xf{x<345:A,s>3174:R,m<1739:A,A} cbv{m>1242:A,m>1121:R,x>897:R,A} zgv{x>2074:A,s>733:A,s<478:R,R} dgf{x<494:rtk,x<648:bj,xq} xg{x<795:A,s>1607:A,m>3324:R,dm} tzv{m<1869:jhs,m>3270:km,x>493:plc,zs} nt{a>3068:A,a<3045:A,R} gbv{s<3584:R,s<3728:R,R} qmm{m>2061:zh,R} cr{x>1870:R,x>982:A,s<463:R,rl} gxs{s>3087:A,m>385:A,a<280:R,rq} ctq{a>987:R,R} mfh{a>1105:ll,lm} ff{x<1886:pt,m<1867:A,R} ggb{a<657:R,a>714:R,R} jkf{a<2776:jjm,a<2825:bhj,a<2860:hhd,jhl} fdx{s>3342:R,R} bls{s<1648:mbj,x>3066:sbh,nlk} czg{s<3077:R,x<2514:A,R} sxz{m<937:grp,s<2655:mll,m>1045:vsx,sl} vqn{m<1679:R,a>2998:A,R} vdv{s>2257:R,a<3750:A,s<2080:A,R} nsx{s>1907:A,a>3246:A,A} gd{x<2557:A,a>1050:R,s>2360:R,R} vnp{x<1424:A,x>1732:A,A} dtc{m>702:R,A} glj{s>2917:A,A} qt{s>3494:dxl,x<2302:kf,R} xzk{a>296:R,x>2358:R,hv} mls{s<2885:A,m>1811:A,A} qvc{a<1613:gfk,a>2225:kfr,a<1820:xrc,nbz} ctb{s>2109:R,A} xz{s<3018:sxz,x>2273:gq,fnv} lg{m<2007:A,m<2082:R,A} lpq{s>3341:zjx,zxh} jhh{m<3882:A,s<3163:mrc,s<3625:nm,R} tc{a<3635:A,A} gx{a<1752:A,x<2622:A,A} mqj{a>2450:R,R} bz{a>676:A,s>2182:A,R} fnv{x>879:mfh,s<3449:ljv,a>1353:gtq,bxb} zfm{x>3316:czp,R} vsx{x>1654:jbk,s>2805:R,a>1136:ksl,hcz} csr{m<3505:R,A} mhf{s<3158:R,s<3205:xf,x<414:jx,qjg} vc{s<1158:qq,frf} qnv{m<696:R,R} cm{m>3441:R,x<1223:R,x>1733:A,A} jhl{x<3102:qt,a<2877:cs,a>2880:cn,cbb} sq{a>671:A,s<1821:A,x>1635:R,R} hvz{m>2461:R,A} tr{m>563:R,R} cgv{a<2538:R,A} ps{x<1895:R,x>3216:R,A} rm{s<3054:R,s>3470:A,m>1762:R,A} qp{m<2013:A,s<1385:R,s>1514:R,A} qj{m<3381:fg,m<3694:pqb,jhh} qr{x<3568:A,m<2760:A,R} tfs{s>433:A,x<1324:R,A} cql{x<2048:rk,zfm} fvp{m>1027:A,x<2630:R,x<3279:R,A} tgt{a>1670:R,mnr} tn{m>824:R,A} fl{x<3396:A,A} vv{s>3244:R,a<3126:dd,s<2826:rf,R} lr{s<2004:A,R} xhx{x<1756:scv,cx} jzm{x>1343:A,x>703:R,a>3373:A,A} tlj{s>1605:nbf,tdg} xk{x>152:R,A} mt{m<2968:qps,a>701:hq,lh} zk{m>416:R,x>3052:A,x<2638:A,A} zn{a<2399:A,A} ggh{m<894:A,a>3830:A,a>3691:R,A} ht{x<1797:A,s>2872:A,A} jbl{m>1401:R,dp} vfk{x<479:R,m>117:A,A} qdz{s>554:R,s<239:cpv,R} ll{s>3366:A,s<3226:A,R} vbp{a<527:R,m>2007:gk,pz} rhg{m<1474:A,a>1417:A,a<862:A,A} in{a>2639:tq,mp} bv{m<3468:ln,ht} zgx{a>3932:R,a>3907:R,x>1109:R,R} hx{a<449:jc,R} cfj{a>1414:fr,a>556:sjq,a>190:npl,qqs} mr{m<2693:A,A} hcp{a>1108:R,R} bf{x>3211:vv,hpl} rtg{a>1997:rxc,jl} qcr{x>162:A,x>74:A,s>2711:bjq,A} xnv{m<724:sxc,x<921:qzx,a<2263:mn,lxc} pbx{a>826:ctq,m<3306:A,zlr} nlp{s>1893:A,R} mfr{x<2238:R,R} tg{a<2948:ff,kz} tnp{a<3177:R,s>2055:A,A} slq{m>611:R,A} fz{m>2476:R,s>3368:R,s<2963:R,A} rgz{a<1096:A,x<2237:R,R} rg{x<396:R,a<3472:qs,R} nm{x>2253:A,R} mdc{x>1209:gz,s<3278:vf,A} pbt{a>1678:A,x>3246:vlr,m<1092:R,R} dbl{m<2274:R,m<2607:mc,lpx} cn{a<2884:dz,x>3410:sg,s>3454:R,tzr} hb{s>3486:R,a>2860:glj,x<378:A,gjs} nls{a<134:A,s>1825:R,m<3471:A,A} tl{s>3434:A,A} bl{a<555:R,a>1174:A,R} mml{a<3707:A,R} dtm{x>2903:hlx,a>1934:xkb,nlp} rb{a>379:A,x<2450:nvs,a>224:A,sx} pf{x<1899:fpz,mln} zmn{m>882:A,a>2320:R,a>2208:R,A} jh{x<2603:fdx,R} crh{a>1398:xkx,s>2903:gbg,R} fmp{a>709:R,x<507:A,s>2752:R,A} sg{m>1527:R,R} sp{x>1242:vbp,fmp} cj{m<564:A,x<900:A,R} khv{s>2714:qj,s>2119:xfp,x>2174:csz,ztq} lsz{m<3503:A,A} dfh{a<612:rb,a<1008:mfr,a>1087:st,xgr} lm{x>1566:R,s>3634:A,m<917:A,A} hn{x>1169:R,nt} pp{x>2075:jct,m<1540:hn,s>3287:ksd,fh} ddf{s>3058:A,A} mn{x>1509:R,R} hc{m>452:nc,s<2479:hml,a>714:crf,gxs} lgt{x>1822:A,m>1939:R,s>1685:sj,vtl} pmb{x<1257:R,R} bq{m>749:hl,a<2978:R,m>283:A,gcm} dj{x>419:R,m>890:A,m<591:R,R} lz{m>2383:R,a<1605:A,nd} rlz{x<908:dgf,m<2926:mmc,m>3586:kl,kqs} lbs{m<1371:lcg,m>1435:rhg,jnn} hml{m<403:jkl,x<2272:R,m<428:zk,bl} ckz{s<3014:R,m>1426:A,a>431:A,A} ft{x<2599:R,A} mxb{x<3119:lbs,s>3317:mth,crh} vh{x>2169:mxb,npb} rc{a<3327:jbl,x>2380:bgz,s<3109:tx,qb} zm{m<76:btg,R} jhs{a<3796:A,a<3916:R,a>3966:R,A} hhd{x>2759:kj,x<2163:qfs,nr} zds{m<1380:R,R} zd{a>899:pbh,vjn} xvn{s>2657:pfl,R} {x=6,m=309,a=1182,s=757} {x=531,m=106,a=1009,s=142} {x=3264,m=506,a=301,s=807} {x=1197,m=394,a=351,s=1266} {x=3009,m=1048,a=143,s=1549} {x=617,m=1696,a=778,s=28} {x=172,m=2243,a=1135,s=2330} {x=309,m=457,a=1943,s=8} {x=424,m=100,a=288,s=1745} {x=282,m=138,a=2134,s=272} {x=2982,m=2488,a=1452,s=3065} {x=1760,m=2317,a=3608,s=119} {x=682,m=303,a=1113,s=34} {x=806,m=3417,a=720,s=1219} {x=908,m=2564,a=1065,s=766} {x=1044,m=70,a=511,s=1410} {x=848,m=262,a=1100,s=778} {x=1042,m=1887,a=2083,s=847} {x=1051,m=1636,a=187,s=892} {x=782,m=489,a=1940,s=18} {x=33,m=1970,a=838,s=1123} {x=20,m=2180,a=2036,s=1720} {x=468,m=788,a=170,s=983} {x=1893,m=1399,a=1661,s=1493} {x=42,m=604,a=2889,s=219} {x=109,m=56,a=1004,s=2498} {x=1249,m=213,a=329,s=117} {x=544,m=380,a=124,s=1479} {x=1222,m=996,a=498,s=2270} {x=38,m=228,a=59,s=1060} {x=17,m=613,a=2060,s=1358} {x=188,m=976,a=100,s=1415} {x=965,m=641,a=1563,s=2718} {x=867,m=386,a=1798,s=682} {x=1596,m=350,a=143,s=167} {x=390,m=2438,a=225,s=171} {x=1014,m=1030,a=718,s=2678} {x=473,m=2034,a=1270,s=449} {x=2092,m=268,a=653,s=691} {x=951,m=16,a=1869,s=2764} {x=494,m=154,a=178,s=1323} {x=2653,m=1230,a=238,s=787} {x=922,m=1420,a=1390,s=2030} {x=2958,m=2763,a=1486,s=2822} {x=615,m=373,a=31,s=1548} {x=1275,m=1486,a=2205,s=171} {x=1,m=2571,a=234,s=1346} {x=945,m=107,a=99,s=754} {x=1398,m=1428,a=556,s=1724} {x=693,m=3354,a=3,s=218} {x=1706,m=39,a=1620,s=1403} {x=465,m=408,a=2153,s=651} {x=1026,m=794,a=340,s=920} {x=1275,m=1806,a=120,s=599} {x=78,m=1030,a=1601,s=1019} {x=2442,m=1645,a=331,s=69} {x=1797,m=480,a=479,s=1634} {x=135,m=1838,a=216,s=1293} {x=1914,m=1031,a=53,s=23} {x=2862,m=303,a=883,s=537} {x=60,m=192,a=109,s=1577} {x=527,m=629,a=103,s=136} {x=66,m=1861,a=135,s=1026} {x=105,m=678,a=2551,s=495} {x=2558,m=33,a=322,s=1359} {x=2032,m=376,a=39,s=857} {x=929,m=1035,a=174,s=2372} {x=731,m=156,a=26,s=2512} {x=1120,m=880,a=500,s=1070} {x=845,m=108,a=1492,s=1340} {x=2460,m=2527,a=1057,s=1382} {x=390,m=942,a=953,s=402} {x=557,m=440,a=335,s=426} {x=1850,m=3068,a=1956,s=258} {x=351,m=296,a=222,s=181} {x=27,m=389,a=650,s=999} {x=1941,m=3377,a=1600,s=1377} {x=62,m=2099,a=9,s=25} {x=34,m=658,a=215,s=32} {x=1408,m=989,a=54,s=560} {x=969,m=431,a=634,s=856} {x=75,m=678,a=1523,s=157} {x=1087,m=837,a=763,s=118} {x=112,m=904,a=3317,s=313} {x=2163,m=1100,a=271,s=882} {x=474,m=289,a=305,s=197} {x=1307,m=2741,a=279,s=1550} {x=1109,m=629,a=1600,s=298} {x=868,m=815,a=2970,s=21} {x=1850,m=285,a=1158,s=373} {x=1430,m=1078,a=226,s=2374} {x=296,m=413,a=1609,s=1099} {x=11,m=3105,a=505,s=2170} {x=2126,m=1961,a=389,s=1087} {x=592,m=1842,a=1991,s=1083} {x=93,m=1662,a=1840,s=2377} {x=433,m=30,a=1269,s=857} {x=1898,m=662,a=861,s=1131} {x=2484,m=278,a=1782,s=134} {x=102,m=1146,a=3527,s=2090} {x=2530,m=727,a=1577,s=211} {x=316,m=2957,a=18,s=730} {x=492,m=183,a=624,s=1454} {x=3325,m=30,a=1660,s=938} {x=407,m=1854,a=99,s=326} {x=1336,m=1276,a=473,s=24} {x=1718,m=438,a=956,s=384} {x=353,m=1534,a=2180,s=2974} {x=2705,m=211,a=94,s=837} {x=104,m=123,a=413,s=1789} {x=176,m=395,a=2652,s=50} {x=738,m=1018,a=103,s=200} {x=750,m=31,a=916,s=121} {x=2967,m=1253,a=1593,s=1357} {x=262,m=112,a=131,s=63} {x=145,m=807,a=291,s=959} {x=1476,m=239,a=1054,s=3491} {x=428,m=351,a=2465,s=65} {x=35,m=236,a=863,s=1089} {x=1233,m=2010,a=177,s=764} {x=1083,m=1863,a=25,s=1974} {x=957,m=1180,a=837,s=679} {x=66,m=1204,a=285,s=2075} {x=444,m=560,a=172,s=1447} {x=812,m=350,a=876,s=661} {x=200,m=366,a=752,s=851} {x=749,m=377,a=815,s=648} {x=60,m=285,a=517,s=39} {x=2921,m=381,a=119,s=249} {x=466,m=1290,a=801,s=2159} {x=62,m=201,a=881,s=95} {x=3598,m=126,a=1688,s=979} {x=2963,m=1112,a=2733,s=520} {x=62,m=1067,a=920,s=451} {x=2501,m=475,a=1074,s=1150} {x=50,m=1111,a=12,s=44} {x=617,m=1106,a=1489,s=1333} {x=90,m=208,a=219,s=2352} {x=1179,m=2166,a=1693,s=2055} {x=61,m=595,a=1382,s=1140} {x=62,m=354,a=123,s=793} {x=436,m=865,a=2408,s=2578} {x=515,m=398,a=303,s=312} {x=637,m=2236,a=474,s=148} {x=2488,m=35,a=75,s=924} {x=461,m=1196,a=7,s=1092} {x=923,m=3184,a=1161,s=308} {x=191,m=1399,a=1324,s=2784} {x=170,m=421,a=51,s=625} {x=170,m=362,a=471,s=2100} {x=289,m=66,a=143,s=284} {x=542,m=339,a=455,s=54} {x=155,m=124,a=732,s=2057} {x=8,m=420,a=784,s=1455} {x=479,m=251,a=1883,s=136} {x=104,m=146,a=97,s=249} {x=2766,m=833,a=386,s=585} {x=373,m=514,a=466,s=2192} {x=296,m=1190,a=249,s=963} {x=518,m=1840,a=860,s=306} {x=1003,m=1955,a=756,s=1098} {x=1545,m=242,a=1479,s=576} {x=77,m=1717,a=475,s=1692} {x=417,m=1517,a=2199,s=374} {x=3247,m=348,a=1065,s=1154} {x=456,m=868,a=182,s=1077} {x=464,m=425,a=15,s=781} {x=640,m=294,a=303,s=261} {x=1018,m=327,a=18,s=1830} {x=262,m=988,a=1974,s=1665} {x=123,m=525,a=3062,s=460} {x=228,m=2020,a=29,s=701} {x=129,m=1163,a=1561,s=958} {x=29,m=1576,a=74,s=348} {x=64,m=2153,a=63,s=1771} {x=71,m=66,a=1642,s=1749} {x=1373,m=3063,a=1958,s=561} {x=2277,m=3766,a=384,s=363} {x=2956,m=127,a=865,s=1862} {x=599,m=115,a=2360,s=526} {x=651,m=644,a=580,s=514} {x=880,m=173,a=613,s=3270} {x=1228,m=951,a=1515,s=333} {x=1621,m=2392,a=2665,s=1515} {x=933,m=1805,a=228,s=1720} {x=25,m=1553,a=54,s=3177} {x=85,m=550,a=273,s=142} {x=489,m=624,a=126,s=557} {x=256,m=2513,a=509,s=186} {x=2616,m=377,a=2497,s=707} {x=688,m=509,a=410,s=557} {x=1306,m=105,a=1605,s=3217} {x=1405,m=31,a=824,s=543} {x=600,m=559,a=1299,s=110} {x=2683,m=1112,a=458,s=27} {x=1240,m=882,a=417,s=1066} {x=651,m=667,a=178,s=3045} {x=2089,m=19,a=879,s=90} {x=263,m=423,a=41,s=734} {x=630,m=44,a=135,s=98} ================================================ FILE: exm/aoc/2023/aoc_2023_19_questions.txt ================================================ --- Day 19: Aplenty --- The Elves of Gear Island are thankful for your help and send you on your way. They even have a hang glider that someone stole from Desert Island; since you're already going that direction, it would help them a lot if you would use it to get down there and return it to them. As you reach the bottom of the relentless avalanche of machine parts, you discover that they're already forming a formidable heap. Don't worry, though - a group of Elves is already here organizing the parts, and they have a system. To start, each part is rated in each of four categories: x: Extremely cool looking m: Musical (it makes a noise when you hit it) a: Aerodynamic s: Shiny Then, each part is sent through a series of workflows that will ultimately accept or reject the part. Each workflow has a name and contains a list of rules; each rule specifies a condition and where to send the part if the condition is true. The first rule that matches the part being considered is applied immediately, and the part moves on to the destination described by the rule. (The last rule in each workflow has no condition and always applies if reached.) Consider the workflow ex{x>10:one,m<20:two,a>30:R,A}. This workflow is named ex and contains four rules. If workflow ex were considering a specific part, it would perform the following steps in order: Rule "x>10:one": If the part's x is more than 10, send the part to the workflow named one. Rule "m<20:two": Otherwise, if the part's m is less than 20, send the part to the workflow named two. Rule "a>30:R": Otherwise, if the part's a is more than 30, the part is immediately rejected (R). Rule "A": Otherwise, because no other rules matched the part, the part is immediately accepted (A). If a part is sent to another workflow, it immediately switches to the start of that workflow instead and never returns. If a part is accepted (sent to A) or rejected (sent to R), the part immediately stops any further processing. The system works, but it's not keeping up with the torrent of weird metal shapes. The Elves ask if you can help sort a few parts and give you the list of workflows and some part ratings (your puzzle input). For example: px{a<2006:qkq,m>2090:A,rfg} pv{a>1716:R,A} lnx{m>1548:A,A} rfg{s<537:gd,x>2440:R,A} qs{s>3448:A,lnx} qkq{x<1416:A,crn} crn{x>2662:A,R} in{s<1351:px,qqz} qqz{s>2770:qs,m<1801:hdj,R} gd{a>3333:R,R} hdj{m>838:A,pv} {x=787,m=2655,a=1222,s=2876} {x=1679,m=44,a=2067,s=496} {x=2036,m=264,a=79,s=2244} {x=2461,m=1339,a=466,s=291} {x=2127,m=1623,a=2188,s=1013} The workflows are listed first, followed by a blank line, then the ratings of the parts the Elves would like you to sort. All parts begin in the workflow named in. In this example, the five listed parts go through the following workflows: {x=787,m=2655,a=1222,s=2876}: in -> qqz -> qs -> lnx -> A {x=1679,m=44,a=2067,s=496}: in -> px -> rfg -> gd -> R {x=2036,m=264,a=79,s=2244}: in -> qqz -> hdj -> pv -> A {x=2461,m=1339,a=466,s=291}: in -> px -> qkq -> crn -> R {x=2127,m=1623,a=2188,s=1013}: in -> px -> rfg -> A Ultimately, three parts are accepted. Adding up the x, m, a, and s rating for each of the accepted parts gives 7540 for the part with x=787, 4623 for the part with x=2036, and 6951 for the part with x=2127. Adding all of the ratings for all of the accepted parts gives the sum total of 19114. Sort through all of the parts you've been given; what do you get if you add together all of the rating numbers for all of the parts that ultimately get accepted? --- Part Two --- Even with your help, the sorting process still isn't fast enough. One of the Elves comes up with a new plan: rather than sort parts individually through all of these workflows, maybe you can figure out in advance which combinations of ratings will be accepted or rejected. Each of the four ratings (x, m, a, s) can have an integer value ranging from a minimum of 1 to a maximum of 4000. Of all possible distinct combinations of ratings, your job is to figure out which ones will be accepted. In the above example, there are 167409079868000 distinct combinations of ratings that will be accepted. Consider only your list of workflows; the list of part ratings that the Elves wanted you to sort is no longer relevant. How many distinct combinations of ratings will be accepted by the Elves' workflows? ================================================ FILE: exm/aoc/2023/aoc_2023_20.adb ================================================ -- Solution to Advent of Code 2023, Day 20 ------------------------------------------- -- Pulse Propagation -- -- https://adventofcode.com/2023/day/20 -- Copy of questions in: aoc_2023_20_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_20 is use AoC_Toolbox, HAT, Interfaces; subtype Link_Range is Integer range 1 .. 10; type Destination_Array is array (Link_Range) of Integer; type Pulse is (low, high); type Input_Info is record source : Natural; mem : Pulse; cycle : Natural; -- Concerns only the pre_final node's inputs. end record; type Input_Array is array (Link_Range) of Input_Info; type Module_Kind is (broadcaster, flip_flop, conjunction, final); type Flip_Flop_State is (off, on); type Module_Type is record kind : Module_Kind; dest : Destination_Array; -- 0-terminated (a bad idea...) name : VString; -- Only for display. state : Flip_Flop_State; -- Concerns only flip-flop input : Input_Array; -- Concerns only conjunction; 0-terminated. end record; map : array (1 .. 60) of Module_Type; top : Natural := 0; function Name (i : Integer) return VString is begin if i = 0 then return +"Button"; elsif i < 0 then return +"Unknown " & i'Image; -- Notably, the mysterious "rx" node... else return map (i).name; end if; end Name; procedure Clear_Machine is begin for i in map'Range loop -- Set the 0-terminators. map (i).dest (1) := 0; map (i).input (1).source := 0; end loop; end Clear_Machine; procedure Reset_Inputs is dest : Integer; begin for src in 1 .. top loop map (src).state := off; for d_lnk in Link_Range loop dest := map (src).dest (d_lnk); exit when dest = 0; if dest > 0 and then map (dest).kind = conjunction then -- For conjunctions, we need to know the pulse state -- of each source, because some sources may have not been -- yet activated and have an assumed "low" state. for s_lnk in Link_Range loop if map (dest).input (s_lnk).source = 0 then map (dest).input (s_lnk).source := src; map (dest).input (s_lnk).mem := low; map (dest).input (s_lnk).cycle := 0; -- Only useful for pre_final. -- 0-terminate: map (dest).input (s_lnk + 1).source := 0; exit; end if; end loop; -- end if; end loop; end loop; end Reset_Inputs; broadcaster_idx : Positive; -- input_name : constant VString := +"mini_1"; input_name : constant VString := +"aoc_2023_20"; -- procedure Read_Data is use Hash_Maps; hm : Hash_Map_Type; prefix, c : Character; key : VString; arrow : String (1 .. 3); row, i, dest : Integer; f : File_Type; procedure Get_Key is begin key := Null_VString; while not End_Of_Line (f) loop Get (f, c); exit when c not in Alpha; key := key & c; end loop; end Get_Key; dummy, i64 : Integer_64; ignore : constant := -1; begin Clear_Machine; Clear (hm); top := top + 1; key := +"rx"; map (top).name := key; map (top).kind := final; Insert (hm, key, Integer_64 (top), False, dummy); Passes : for pass in 1 .. 2 loop Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get (f, prefix); Get_Key; case pass is when 1 => -- In pass #1 we just fill the vector `map` with names -- and feed the hash map. All but one nodes are listed -- on the lines' headers. top := top + 1; map (top).name := key; Insert (hm, key, Integer_64 (top), False, dummy); Skip_Line (f); when 2 => Find (hm, key, ignore, i64); row := Integer (i64); case prefix is when 'b' => map (row).kind := broadcaster; broadcaster_idx := row; map (row).name := 'b' & map (row).name; when '%' => map (row).kind := flip_flop; when '&' => map (row).kind := conjunction; when others => Put_Line ("Bad data!"); end case; Get (f, arrow); i := 0; loop Get_Key; Find (hm, key, ignore, i64); dest := Integer (i64); i := i + 1; map (row).dest (i) := dest; exit when End_Of_Line (f); Get (f, c); -- Space after ',' end loop; -- 0-terminate: map (row).dest (i + 1) := 0; end case; end loop; Close (f); end loop Passes; end Read_Data; verbosity : constant := 0; -- We make a FIFO buffer type To_Do_Type is record sent : Pulse; from, to : Integer; end record; buffer : array (0 .. 49) of To_Do_Type; read_idx : Natural; write_idx : Natural; procedure FIFO_Reset is begin read_idx := 0; write_idx := 0; end FIFO_Reset; function FIFO_Is_Full return Boolean is begin return (write_idx + 1) mod buffer'Length = read_idx; end FIFO_Is_Full; function FIFO_Is_Empty return Boolean is begin return write_idx = read_idx; end FIFO_Is_Empty; procedure Put_To_Do (e : in To_Do_Type) is begin if FIFO_Is_Full then Put_Line (+"FIFO is full! w:" & write_idx & " r:" & read_idx); Skip_Line; else if verbosity >= 2 then Put_Line (Name (e.from) & " -" & e.sent'Image & " -> " & Name (e.to)); end if; buffer (write_idx) := e; write_idx := (write_idx + 1) mod buffer'Length; end if; end Put_To_Do; procedure Get_To_Do (e : out To_Do_Type) is begin if FIFO_Is_Empty then Put_Line ("FIFO is empty!"); else e := buffer (read_idx); read_idx := (read_idx + 1) mod buffer'Length; end if; end Get_To_Do; r : array (Part_Type) of Integer_64; procedure Simulate is e_cur, e : To_Do_Type; row : Integer; dest : Integer; all_cycles : Boolean; out_pulse : Pulse; ignore : Boolean; high_pulses_for_all_inputs : Boolean; counter : array (Pulse) of Natural; pre_final_idx : Natural := 0; procedure Put_Job is begin counter (e.sent) := counter (e.sent) + 1; Put_To_Do (e); end Put_Job; button_press_count : Natural := 0; begin Reset_Inputs; counter (low) := 0; counter (high) := 0; Button_Presses : loop button_press_count := button_press_count + 1; if verbosity >= 2 then Put_Line (+"=================== Round number " & button_press_count); end if; FIFO_Reset; e.sent := low; e.from := 0; e.to := broadcaster_idx; Put_Job; while not FIFO_Is_Empty loop Get_To_Do (e_cur); row := e_cur.to; if row > 0 then out_pulse := e_cur.sent; ignore := False; case map (row).kind is when broadcaster => null; when flip_flop => case e_cur.sent is when high => ignore := True; when low => if map (row).state = off then map (row).state := on; out_pulse := high; else map (row).state := off; out_pulse := low; end if; end case; when conjunction => if verbosity >= 3 then Put_Line (" For " & Name (row) & ", checking inputs"); end if; high_pulses_for_all_inputs := True; for s_lnk in Link_Range loop exit when map (row).input (s_lnk).source = 0; if verbosity >= 3 then Put_Line (" " & Name (map (row).input (s_lnk).source) & ": " & map (row).input (s_lnk).mem'Image); end if; high_pulses_for_all_inputs := high_pulses_for_all_inputs and map (row).input (s_lnk).mem = high; end loop; if high_pulses_for_all_inputs then out_pulse := low; else out_pulse := high; end if; when final => null; end case; if not ignore then -- Broadcasting if verbosity >= 2 then Put_Line (" Broadcasting from " & Name (row)); end if; for id in map (row).dest'Range loop dest := map (row).dest (id); exit when dest = 0; e.sent := out_pulse; e.from := row; e.to := dest; Put_Job; if dest > 0 then case map (dest).kind is when conjunction => if verbosity >= 2 then Put_Line (" Destination is a conjunction: " & Name (dest)); end if; for s_lnk in Link_Range loop exit when map (dest).input (s_lnk).source = 0; if map (dest).input (s_lnk).source = row then map (dest).input (s_lnk).mem := out_pulse; if verbosity >= 2 then Put_Line (" Updated pulse from input " & Name (row)); end if; if dest = pre_final_idx and then out_pulse = high and then map (dest).input (s_lnk).cycle = 0 then if verbosity >= 1 then Put_Line ("New cycle on the " & Name (row) & " -> " & Name (dest) & " broadcast; button press so far: " & button_press_count); end if; map (dest).input (s_lnk).cycle := button_press_count; end if; exit; end if; end loop; if dest = pre_final_idx then all_cycles := True; for s_lnk in Link_Range loop exit when map (dest).input (s_lnk).source = 0; all_cycles := all_cycles and map (dest).input (s_lnk).cycle > 0; end loop; exit Button_Presses when all_cycles; end if; when final => -- Put_Line -- (+"FINAL " & count & ", pulse: " & -- out_pulse'Image & ", from " & Name (row)); pre_final_idx := row; -- In our data (and seemingly other data as well) -- The final node (rx) has a single predecessor -- (in our case, called "xn"), which is a conjunction -- node. Let's call that node "pre_final". -- The pre_final node will emit a low pulse only -- after all its inputs are high. when others => null; end case; end if; end loop; end if; end if; end loop; if button_press_count = 1000 then r (part_1) := Integer_64 (counter (low) * counter (high)); end if; end loop Button_Presses; r (part_2) := 1; for s_lnk in Link_Range loop exit when map (pre_final_idx).input (s_lnk).source = 0; r (part_2) := LCM_64 (r (part_2), Integer_64 (map (pre_final_idx).input (s_lnk).cycle)); end loop; end Simulate; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data; Simulate; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)'Image); Put_Line (+"Part 2: " & r (part_2)'Image); -- Part 1: validated by AoC: 806332748 -- Part 2: validated by AoC: 228060006554227 end if; end AoC_2023_20; ================================================ FILE: exm/aoc/2023/aoc_2023_20.txt ================================================ %jv -> rn, jn &fb -> hb, vk, fz, kl, cg %rr -> vm, gp &gp -> vm, cb, bd, qm, xf, pk %hm -> ql %cf -> dx, fb %cg -> kl %hv -> kg, fb %hs -> jv %bd -> dt %xv -> mv, gp %js -> zb, jl %rn -> bk, jn %lp -> hm %dx -> fb, jm %ss -> lp &hn -> xn %bh -> jl, ms %km -> jl, lm %mv -> gp, qm &jl -> km, lm, ms, mp, lr, zb, bg %pt -> jt, jl %cb -> bd %xt -> jn, jf %kg -> fb %dg -> jn %rt -> fb, hb broadcaster -> km, xt, pk, vk %lr -> pt %vm -> bf %hx -> qd, jl &mp -> xn %hb -> pd %vk -> cg, fb %kl -> rs %pk -> gp, cb %jt -> hx, jl &jn -> hs, lp, hm, hn, ql, xt, ss %bg -> js %kz -> ss, jn %bf -> fx, gp %bk -> dg, jn %qm -> rr %fx -> gp, dp %dp -> gp %jf -> jn, kz %jm -> hv, fb %ql -> hs %ms -> bg %zb -> lr %rs -> fb, rt %dt -> xv, gp %lm -> bh &xf -> xn %pd -> cf, fb %qd -> jl &xn -> rx &fz -> xn ================================================ FILE: exm/aoc/2023/aoc_2023_20_questions.txt ================================================ --- Day 20: Pulse Propagation --- With your help, the Elves manage to find the right parts and fix all of the machines. Now, they just need to send the command to boot up the machines and get the sand flowing again. The machines are far apart and wired together with long cables. The cables don't connect to the machines directly, but rather to communication modules attached to the machines that perform various initialization tasks and also act as communication relays. Modules communicate using pulses. Each pulse is either a high pulse or a low pulse. When a module sends a pulse, it sends that type of pulse to each module in its list of destination modules. There are several different types of modules: Flip-flop modules (prefix %) are either on or off; they are initially off. If a flip-flop module receives a high pulse, it is ignored and nothing happens. However, if a flip-flop module receives a low pulse, it flips between on and off. If it was off, it turns on and sends a high pulse. If it was on, it turns off and sends a low pulse. Conjunction modules (prefix &) remember the type of the most recent pulse received from each of their connected input modules; they initially default to remembering a low pulse for each input. When a pulse is received, the conjunction module first updates its memory for that input. Then, if it remembers high pulses for all inputs, it sends a low pulse; otherwise, it sends a high pulse. There is a single broadcast module (named broadcaster). When it receives a pulse, it sends the same pulse to all of its destination modules. Here at Desert Machine Headquarters, there is a module with a single button on it called, aptly, the button module. When you push the button, a single low pulse is sent directly to the broadcaster module. After pushing the button, you must wait until all pulses have been delivered and fully handled before pushing it again. Never push the button if modules are still processing pulses. Pulses are always processed in the order they are sent. So, if a pulse is sent to modules a, b, and c, and then module a processes its pulse and sends more pulses, the pulses sent to modules b and c would have to be handled first. The module configuration (your puzzle input) lists each module. The name of the module is preceded by a symbol identifying its type, if any. The name is then followed by an arrow and a list of its destination modules. For example: broadcaster -> a, b, c %a -> b %b -> c %c -> inv &inv -> a In this module configuration, the broadcaster has three destination modules named a, b, and c. Each of these modules is a flip-flop module (as indicated by the % prefix). a outputs to b which outputs to c which outputs to another module named inv. inv is a conjunction module (as indicated by the & prefix) which, because it has only one input, acts like an inverter (it sends the opposite of the pulse type it receives); it outputs to a. By pushing the button once, the following pulses are sent: button -low-> broadcaster broadcaster -low-> a broadcaster -low-> b broadcaster -low-> c a -high-> b b -high-> c c -high-> inv inv -low-> a a -low-> b b -low-> c c -low-> inv inv -high-> a After this sequence, the flip-flop modules all end up off, so pushing the button again repeats the same sequence. Here's a more interesting example: broadcaster -> a %a -> inv, con &inv -> b %b -> con &con -> output This module configuration includes the broadcaster, two flip-flops (named a and b), a single-input conjunction module (inv), a multi-input conjunction module (con), and an untyped module named output (for testing purposes). The multi-input conjunction module con watches the two flip-flop modules and, if they're both on, sends a low pulse to the output module. Here's what happens if you push the button once: button -low-> broadcaster broadcaster -low-> a a -high-> inv a -high-> con inv -low-> b con -high-> output b -high-> con con -low-> output Both flip-flops turn on and a low pulse is sent to output! However, now that both flip-flops are on and con remembers a high pulse from each of its two inputs, pushing the button a second time does something different: button -low-> broadcaster broadcaster -low-> a a -low-> inv a -low-> con inv -high-> b con -high-> output Flip-flop a turns off! Now, con remembers a low pulse from module a, and so it sends only a high pulse to output. Push the button a third time: button -low-> broadcaster broadcaster -low-> a a -high-> inv a -high-> con inv -low-> b con -low-> output b -low-> con con -high-> output This time, flip-flop a turns on, then flip-flop b turns off. However, before b can turn off, the pulse sent to con is handled first, so it briefly remembers all high pulses for its inputs and sends a low pulse to output. After that, flip-flop b turns off, which causes con to update its state and send a high pulse to output. Finally, with a on and b off, push the button a fourth time: button -low-> broadcaster broadcaster -low-> a a -low-> inv a -low-> con inv -high-> b con -high-> output This completes the cycle: a turns off, causing con to remember only low pulses and restoring all modules to their original states. To get the cables warmed up, the Elves have pushed the button 1000 times. How many pulses got sent as a result (including the pulses sent by the button itself)? In the first example, the same thing happens every time the button is pushed: 8 low pulses and 4 high pulses are sent. So, after pushing the button 1000 times, 8000 low pulses and 4000 high pulses are sent. Multiplying these together gives 32000000. In the second example, after pushing the button 1000 times, 4250 low pulses and 2750 high pulses are sent. Multiplying these together gives 11687500. Consult your module configuration; determine the number of low pulses and high pulses that would be sent after pushing the button 1000 times, waiting for all pulses to be fully handled after each push of the button. What do you get if you multiply the total number of low pulses sent by the total number of high pulses sent? --- Part Two --- The final machine responsible for moving the sand down to Island Island has a module attached named rx. The machine turns on when a single low pulse is sent to rx. Reset all modules to their default states. Waiting for all pulses to be fully handled after each button press, what is the fewest number of button presses required to deliver a single low pulse to the module named rx? ================================================ FILE: exm/aoc/2023/aoc_2023_21.adb ================================================ -- Solution to Advent of Code 2023, Day 21 ------------------------------------------- -- Step Counter -- -- https://adventofcode.com/2023/day/21 -- Copy of questions in: aoc_2023_21_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_21 is use AoC_Toolbox, HAT, Interfaces; -- input_name : constant VString := +"mini"; n : constant := 11; n7 : constant := 77; steps_part_1 : constant := 6; input_name : constant VString := +"aoc_2023_21"; n : constant := 131; n7 : constant := 917; steps_part_1 : constant := 64; steps_part_2 : constant := 26501365; type Map_Type is array (1 .. n7, 1 .. n7) of Character; map : array (Binary) of Map_Type; procedure Read_Data is c : Character; f : File_Type; S : Point; begin Open (f, input_name & ".txt"); for y in 1 .. n loop for x in 1 .. n loop Get (f, c); if c = 'S' then c := '.'; S.x := x; S.y := y; end if; -- Copy the data on a n*7 x n*7 map. -- The 7-fold map is used for extrapolating -- further to the infinity... for kx in 0 .. 6 loop for ky in 0 .. 6 loop map (0)(x + n * kx, y + n * ky) := c; end loop; end loop; end loop; end loop; Close (f); map (1) := map (0); map (0) (S.x + 3 * n, S.y + 3 * n) := 'O'; end Read_Data; verbosity : constant := 0; compiler_test_mode : constant Boolean := Argument_Count >= 1; r : array (Part_Type) of Integer_64; procedure Solve is cur : Binary := 0; -- Oscillate between two maps (game-of-life-style). procedure Step_Aside (x, y : Integer) is begin if map (1 - cur) (x, y) = '.' then map (1 - cur) (x, y) := 'O'; end if; end Step_Aside; b_min, b_max : Positive; function Count_Garden_Plots return Natural is total : Natural := 0; begin for y in b_min .. b_max loop for x in b_min .. b_max loop if map (cur) (x, y) = 'O' then total := total + 1; end if; end loop; end loop; return total; end Count_Garden_Plots; degree : constant := 2; t : Integer_64; -- Observations of Count_Garden_Plots every n steps: obs : array (0 .. degree) of Integer_64; begin Macro : for macro_step in 0 .. degree loop b_min := 1 + n * (2 - macro_step); b_max := n * (5 + macro_step); Micro : for micro_step in 1 .. n loop if verbosity >= 2 then Put_Line ("------------"); for y in 1 .. n7 loop for x in 1 .. n7 loop Put (map (cur) (x, y)); end loop; New_Line; end loop; end if; for y in b_min .. b_max loop for x in b_min .. b_max loop if map (cur) (x, y) = 'O' then Step_Aside (x, y - 1); Step_Aside (x, y + 1); Step_Aside (x + 1, y); Step_Aside (x - 1, y); map (1 - cur) (x, y) := '.'; end if; end loop; end loop; cur := 1 - cur; if macro_step = 0 and then micro_step = steps_part_1 then r (part_1) := Integer_64 (Count_Garden_Plots); if compiler_test_mode then return; end if; end if; if (micro_step mod n) = (steps_part_2 mod n) then -- We measure the result every n steps for a while. obs (macro_step) := Integer_64 (Count_Garden_Plots); exit Macro when macro_step = degree; end if; end loop Micro; end loop Macro; -- -- Someone somewhere seems to claim that due to favourable -- settings (n being odd, S being at the centre, borders and -- the crosss through S being free, moves being only horizontal -- or vertical,...), the result is exactly predicted by a -- polynomial of degree 2. -- -- We determine p such as: p (t) = obs (t) for t = 0, 1, 2 -- if verbosity >= 1 then for d in 0 .. degree loop Put_Line (+"d = " & d & ", observation " & obs (d)'Image); end loop; end if; t := steps_part_2 / n; r (part_2) := obs (0) + (obs (1) - obs (0)) * t + (obs (2) - 2 * obs (1) + obs (0)) * t * (t - 1) / 2; end Solve; T0 : constant Time := Clock; begin Read_Data; Solve; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)'Image); Put_Line (+"Part 2: " & r (part_2)'Image); -- Part 1: validated by AoC: 3677. -- Part 2: validated by AoC: 609585229256084. end if; end AoC_2023_21; ================================================ FILE: exm/aoc/2023/aoc_2023_21.txt ================================================ ................................................................................................................................... .#....................#..#......##.#..#.#..#.#..#.#.........#....................##......##...#....#.....#..#.....#........#....... .........#......#.#.........#...#.#...##..#.......#..#...................#........#..........#.#..##...#...#....................... ..#...#...#..#..#.#..#......#.....#...#....##..............................#......#.....#........#.......#.#.......#..#......#..... ............#................#...#.............#.........................#..................#....#..............#......##..#....... .##....#...#....#............#.#..................#.#...#.................#......#.....#..........#.....#.#.#...........#.......... ..###....#.#.#....#....##............##.#...#...............................#.#..#.#.........#....................#.#....###.#..... ..#....##.......#...##..#......#.....................#..........#...#............#.........#.........##......#......#..#......#.... ....................#......##.............#.#.................................#.....#..#.#..#....#...##........#....#.............. ................#...........#.#.....#.#....#.................#.....#...................#..............#....#..#......#......#...... .....#.....#...........#.............#.##......#.#..............#................#........#..#..#....#....#....#.#..........#.#.... ..#......#..........#.............#..........#...#.................#.##..................#.##.....#......##.......#...#.........##. .......#..#..#.......#.......#...##.#....#.....#...........#...#....#..#..............#.............#......#..#.................... ..#..#.........#.......#...#..............#.............#......#....#...................#..........##.....##.##.....#.....#.#...... .....#....###....#......#..#..#..#........#..#............#.....#.....#.#.#..................#.......#...........##................ .........#....#.....#...........#..##..##.......................#..#.......#.............#....##...##...#...#...##........#...#.... .#...#..#.....#.......#.#......#.......#.#.............#..#.#.....#.#.#......#.........#.........#...........#..#.....##....#...... .....#.#.#...............#...........###.#..............#.#..#......#...................#...#....##.........#..#..#.#...#.#........ ......#..........#....##.....#.......#.....#..........#......###....#.......#...........#......#..............#.........#..#.#..... ...#......#............#............#.#..#........#.....#.......#..............#.............#.........#...........#............... ..............##........#.##..#....................#.......#...............#...#.............#...#..##.........#.......#.........#. ..........##....#..#.........#...#..............#.....##..#.....................#...........##.......................#...........#. ......#..........##..............#...................#...#..#.....#.....#.......#...............#.........#..#......#........#..... ....#.#.............#.....#...#.....#.#........#.#...#...###..#........#..#...#.............#.........#.....................##..... ....#...#.........#..............#..............#.......####.........#..............##...........###.......#.....#........##..#..#. ..#...#...........#.#...#...#...............................#............#....................#...#....#..#...#.#...........#..#... ..#.....##..#.#.........................................#.........#....#......#....#..#....................#.#........#..........#. ..#...#..#...#......#.#.......#...............#.#......##..#..#.........#.............#......................#....##...##.#........ ...#.#.#..............#...##..............#...#............#...............#...........#.#.........#..#.......#.#.#...........#.... ............#.....#....#.....##...............#......#..........#.....#........#........#..............#...#.#.....#.#............. ............#........##.................#......#...............................#.#.#................#...#.................#..#..... ......#...#....#............#.........#.......#....#...................#........#..........#...............#...........#........... ........#............#......##.......#...........#.......#.............#.....................................#...........#......... ..........#.....#.........#.#.......................#..........##.........#....#........#.....#..........##..................##.... ..........#........................#.............#.......##..#......#..........#...........#.............#....#..#..#....#......#.. ......#........#........#.........#.......#....#..................#.........##.....#......#....................#...#.........#..... ...#..#....#....#.................#...#.....#.....##....................#.......##.....#...#...##.......................##.....#... ...##........#.....................#.........#..##....#.................###........#.......#..............#...#...#.......#....##.. .......#...........##.............#......##.............##.##........##...#..#..#.#.......#..#.#...........#...#................... .........#.......##.............#............##.....#........#...............#.#.....#.....#.#..............#.......##...#......... .......##...#....#...........#...........#..............#..#..#.........####..........#....##.................#..............#..... ....#..........................#..........#.............#..........#...#...........#.......#............................##......... ...#...#.....###.................................##...............................#....#...#..##.................................#. ..#....#.#......#............#...#......##.....#.....#..##...#.........#.....#.............#......#...#............#............... ......#.....#.##................#.......##.##........#.........................#..............................................#.... .#....#..................#.#...............#..#......##.......##...............#....####..........#...#........................#... ...#........#..........#.................#....#.........#....#.....#.........#.....#.#.......##.......#................#..##....... .#.......#.#..#............##...........#......#.#.......................#.........#.....#.....#.....###...............#.#..##..... .......................#...#...........#.........#....###.......................#.........###.#.#....#......#........##............ ..#....................#.................#.#.##.#........#..#......#....#......##......#............#..#..............#....#....#.. .......................##.##.#..#.....###....#..#.#...#............#........#.....#....#.#.....#..#....#......................##... ....#.....#.........##..#....#..#.........#...#...#..##........#......###.....#..................#......................#.......... .#.#................#..#.#...#........................#....##..#.............#...#.#.......#........#.#.....##................#.... .##..#..........#..#.#........##............#.......#..........#....#.#...#....##.#...#..##...........#.......................#.... .#.#.##..................#............#.#......#.........#............#.#....#..#.........##..#..................##...........##.#. ..............#..........#...#...##..........#.....................#..#..............#.....#.#...........#.....#....#.......#...... ..###.........#........###...#...........#..##.##..###....#...#................#.....#......#...##...................#...........#. ..#...........#.................##........#.........#...#.....##......##...#.........#......#.............#...#..#................. ..#.............#..........#.#.............#.....#............#....#.#......#....................#.#.......#.#.....#............##. ..........#...........#...#...#...#................#......#................#..........................##.##.....#..#..#.#.......... ..............#....#......#............#.....#.......#..#..........................#..#...............................#............ ............#.............#...........##...#.##..#.........#....#.....#..#.....#...............##....#.................#........... ...........#.....#.##..............#....#..........#......#.......#..##....##.......#.........#.......#....#...#..........#........ ......#...#...#..............#.#...##.#..#........#.....#.......#...#.........#.....#.....##.........#.#........................... ..............#..#........#......##.......#......#...#.#........#.............#...##.............#.#.#...............##....#....... .................................................................S................................................................. .........#.....#.#.#..........#.#.............#..#.....................##......##.#.............#.#.......#.........#...#.......... .........#......#......#......#..........#...........................#...#......#..........#..#.#..........#......#..#..#...#...... ........#.#...............##...............................#.#..............#.#....##..#...#...#....#..#.................#......... .............#..#....#............#........#.#......#........#.......#....#......#...#.#..........#....##......#.#................. ............#..........#.............#.#..............#.....#.....#...#...#........#.#........#.#........#.#....................... .................#........#......#....#.#................#..............#.....#.#.....#.............#.#........#.#...#............. ...........#....#.##...........#..#...................................#.#...#........#.......#.........#...#..##..##............... .....................#.#..#...#.#..........#....##...#.................#...............#.......................#................... ..............#..#.............#.#...........#....#.......#.........#.......#.........#...#.#.........##............#.............. ....#.............##....#......#..........................##.........#.#.........#.....#...#..............#........................ ....#............#...........#.####....#...#.......#..#.........#...#.............#...........#...#...........#.##...........#.#... ..##..............#...............#...#.#..#....##.....................#..#.....#.............#....#.......#..###.............##.#. .....#.##........#....#...##.#..###...#......#..##.#.....#..#.#.#........##......#............#.......#.....#....#...........##.... .#......................#.#.......#........#.#.#.........##.....#.....#..#........#..#..#...#..##.......#...............#.......... .....#...#.............................#.....#.....#......##......#...##........#.#.........................###.........#.......... ...#........#...................#....#...........#..#....#...#.........#...........##.#..#..#..#...........##............#......... ......##..#..........##..#..#...........#......#...#........#.....#........#...........#........#............#........#.......#.... .......#.......................#....#......###..#..#..#.........#.##..#................#.....#...............................#..... ...#.........#............................................#...#....#...........#.#..................#.....##.......#...#........#.. ..##..###.......#........#................#.....#..................##.........#..#..#...........#..##...###.........###...#...#.... ..........#.....#.............#.#..#.#...........##.........#..............................#..#.......#.#................#.#.#..... .......#..................#............##.............#..............#.#........#.#..............#...#..........................#.. ...#.......#.....#..........................#...#...#...........#..#.............#.........#..........#.............#........#..... ..............#................##......#.#......#........................####...#.....#....#....#..................#.#.#........#.. ........#.....#.#....#....................##......................................#...#..#.......#..........................##..... ...#.#.........#.#..#.............#...#....##.......#......................##...#.#.........#.....#..........#..................... ..#.#......#...#......##............#......#....#.#..#.#..........#....#......##..#................................#............... ........###..##....##...........................#.#.#.##..###........#....#............#........##.........#...#................... ....#............................#.#.........#.........#...#.......#.................#..#......#.........#..#.....#...#.#....#...#. ..#.#..........#..........#.........#..#...#..........#.....#....................#.#..#.......#...........#............#........... .......#.....#...........##.........#.....#..........#....#..#......#...........#...##....#......................#....#.......#.... ..##......#...##.............................##..........#....#..............#..........#..............##..#....##.#........##..... ....#......#....#.#..................#..........#....#.#..##.#.##........#.............................#...............#.......#.#. .............#..#......#.................#.#..#....####........#......#......#....#.#.....................#.#.#.#..#............... .##......#........##........#.............#.#.###.....#.............#.......#..##....#...#....................##..###.......#...... ....#.#......##.#.......#......#......................#.......#.........#..#...........#................#.........#..#...#....#.... ..........#....#..#...........#.................#...#..#.....................#.#........##.......#.#....#..#................##...#. ......#....#.......#.......#..#...........#......#............#......#................#..........#...#.......##...#....#.#......... ...#..##...##....#..#.......#....#.................#.#.....#....#........#..#.....####.#...........#..#............#...#..##.....#. ..#......#...................#...............................#............#.....##.............#..#...#..##.#......#............... ....#.........#.........#..............................#...#....#..#.#..............#...............#..##.........#.......#....#... .....#.........#....#.............#............................#.................##............#...#......#..........#.....#.....#. ...#.#....#.......##...#....#............................##.#...#.......#...##...................#..........#.#.................... ...........#..#.###.....##...#.........#...........#..#.#.........#.#.#.......#.................#....#............###.........#..#. .##..........#..#......#.....##.##.#...##.........#.................#....#.#.....#.................#.....#...#....#.....###..#.#... ......#.#..##.#.......#...#..#........................#..#..........#.#....#..##........#...#.#.............#.#.................... .......#.#.............#..#.........................#.##..........##......................#...##.........#....#..........#..###.... ...............#..#...#.........#.........#.................#.#......#....................#.........#.......................#.#.... .....#.................#.#...............##............................####...................##....#......#.#....##..#..#.......#. ....#..#.......#.#...#.......................##.........#..#.......#.#.#............#...........#.###............#......#...##..... ..#.#..........#..#.......#...#.........#....#.........#....#...#.......#.#..........##..##........................#..........##... ....#...##......##......#.......#....###..............................#.##........................#......##.......#............#... ...........#......#.#......#.............................#..........#...............#......##...............#.#........###.......#. ..............#......#.....#.........#.....##....#..................#..##.......#.........##.#..##..................#....#......... ....#...#...##.......###.......#....#...........#.#.............#...#.............#.#...#.#..................#..#.........#........ ................#.........#....#....#.##.....#...###..........#.......#...........#..#....#.............#....................##.... .......................##..............#...#.#....##.#............#.#........#......##....#.......#........#.#.......#....#..#..#.. ..#....#..#............#.#...................#.....................................#.......##.#............##..#........#.......... .....#............#.......##.........##...#........#........................................#................#.......#..........#.. ......#.#.....#.......#............##......#.#..#....#.........................#...............#..#.......##....###......###....... ..#...................#.#...#.....#.......#..................................#..#....#......#.#...#..#..#......#.#.#....#....#..... ...#....#....#.....#.....#.............................#.##..............#.....#..#.........#...#.....#........#.......#......##... .....#.......#.....#...#..#....#................#.......................#..#...#........#..........#....#..#....................#.. ......#.............#.#...#.##.......#...#.....#.....#.#.#...............#.....##.#....#...............................#.#.....#... ................................................................................................................................... ================================================ FILE: exm/aoc/2023/aoc_2023_21_questions.txt ================================================ --- Day 21: Step Counter --- You manage to catch the airship right as it's dropping someone else off on their all-expenses-paid trip to Desert Island! It even helpfully drops you off near the gardener and his massive farm. "You got the sand flowing again! Great work! Now we just need to wait until we have enough sand to filter the water for Snow Island and we'll have snow again in no time." While you wait, one of the Elves that works with the gardener heard how good you are at solving problems and would like your help. He needs to get his steps in for the day, and so he'd like to know which garden plots he can reach with exactly his remaining 64 steps. He gives you an up-to-date map (your puzzle input) of his starting position (S), garden plots (.), and rocks (#). For example: ........... .....###.#. .###.##..#. ..#.#...#.. ....#.#.... .##..S####. .##..#...#. .......##.. .##.#.####. .##..##.##. ........... The Elf starts at the starting position (S) which also counts as a garden plot. Then, he can take one step north, south, east, or west, but only onto tiles that are garden plots. This would allow him to reach any of the tiles marked O: ........... .....###.#. .###.##..#. ..#.#...#.. ....#O#.... .##.OS####. .##..#...#. .......##.. .##.#.####. .##..##.##. ........... Then, he takes a second step. Since at this point he could be at either tile marked O, his second step would allow him to reach any garden plot that is one step north, south, east, or west of any tile that he could have reached after the first step: ........... .....###.#. .###.##..#. ..#.#O..#.. ....#.#.... .##O.O####. .##.O#...#. .......##.. .##.#.####. .##..##.##. ........... After two steps, he could be at any of the tiles marked O above, including the starting position (either by going north-then-south or by going west-then-east). A single third step leads to even more possibilities: ........... .....###.#. .###.##..#. ..#.#.O.#.. ...O#O#.... .##.OS####. .##O.#...#. ....O..##.. .##.#.####. .##..##.##. ........... He will continue like this until his steps for the day have been exhausted. After a total of 6 steps, he could reach any of the garden plots marked O: ........... .....###.#. .###.##.O#. .O#O#O.O#.. O.O.#.#.O.. .##O.O####. .##.O#O..#. .O.O.O.##.. .##.#.####. .##O.##.##. ........... In this example, if the Elf's goal was to get exactly 6 more steps today, he could use them to reach any of 16 garden plots. However, the Elf actually needs to get 64 steps today, and the map he's handed you is much larger than the example map. Starting from the garden plot marked S on your map, how many garden plots could the Elf reach in exactly 64 steps? --- Part Two --- The Elf seems confused by your answer until he realizes his mistake: he was reading from a list of his favorite numbers that are both perfect squares and perfect cubes, not his step counter. The actual number of steps he needs to get today is exactly 26501365. He also points out that the garden plots and rocks are set up so that the map repeats infinitely in every direction. So, if you were to look one additional map-width or map-height out from the edge of the example map above, you would find that it keeps repeating: ................................. .....###.#......###.#......###.#. .###.##..#..###.##..#..###.##..#. ..#.#...#....#.#...#....#.#...#.. ....#.#........#.#........#.#.... .##...####..##...####..##...####. .##..#...#..##..#...#..##..#...#. .......##.........##.........##.. .##.#.####..##.#.####..##.#.####. .##..##.##..##..##.##..##..##.##. ................................. ................................. .....###.#......###.#......###.#. .###.##..#..###.##..#..###.##..#. ..#.#...#....#.#...#....#.#...#.. ....#.#........#.#........#.#.... .##...####..##..S####..##...####. .##..#...#..##..#...#..##..#...#. .......##.........##.........##.. .##.#.####..##.#.####..##.#.####. .##..##.##..##..##.##..##..##.##. ................................. ................................. .....###.#......###.#......###.#. .###.##..#..###.##..#..###.##..#. ..#.#...#....#.#...#....#.#...#.. ....#.#........#.#........#.#.... .##...####..##...####..##...####. .##..#...#..##..#...#..##..#...#. .......##.........##.........##.. .##.#.####..##.#.####..##.#.####. .##..##.##..##..##.##..##..##.##. ................................. This is just a tiny three-map-by-three-map slice of the inexplicably-infinite farm layout; garden plots and rocks repeat as far as you can see. The Elf still starts on the one middle tile marked S, though - every other repeated S is replaced with a normal garden plot (.). Here are the number of reachable garden plots in this new infinite version of the example map for different numbers of steps: In exactly 6 steps, he can still reach 16 garden plots. In exactly 10 steps, he can reach any of 50 garden plots. In exactly 50 steps, he can reach 1594 garden plots. In exactly 100 steps, he can reach 6536 garden plots. In exactly 500 steps, he can reach 167004 garden plots. In exactly 1000 steps, he can reach 668697 garden plots. In exactly 5000 steps, he can reach 16733044 garden plots. However, the step count the Elf needs is much larger! Starting from the garden plot marked S on your infinite map, how many garden plots could the Elf reach in exactly 26501365 steps? ================================================ FILE: exm/aoc/2023/aoc_2023_22.adb ================================================ -- Solution to Advent of Code 2023, Day 22 ------------------------------------------ -- Sand Slabs -- -- https://adventofcode.com/2023/day/22 -- Copy of questions in: aoc_2023_22_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_22 is use AoC_Toolbox, HAT; capacity : constant := 1500; -- Poor man's ordered map (inspired from Day 18). -- On a "full Ada" system like GNAT we would use -- efficient Ada.Container.* goodies... type Vector_Values is array (1 .. capacity) of Integer; type Ordered_Map is record last : Natural; key : Vector_Values; -- Ordered values elt : Vector_Values; -- Elements end record; procedure Insert (v : in out Ordered_Map; key, element : Integer) is ins : Positive; found : Boolean := False; begin for i in 1 .. v.last loop if v.key (i) = key then ins := i; found := True; exit; end if; end loop; if not found then ins := v.last + 1; end if; for i in 1 .. v.last loop if v.key (i) > key then ins := i; exit; end if; end loop; -- Make room for the new element for i in reverse ins .. v.last loop v.key (i + 1) := v.key (i); v.elt (i + 1) := v.elt (i); end loop; v.key (ins) := key; v.elt (ins) := element; v.last := v.last + 1; end Insert; procedure Find (v : in out Ordered_Map; -- ^ "out" is not needed, we just force -- a by-reference parameter passing on HAC. key : in Integer; index : out Integer; found : out Boolean) is begin for i in 1 .. v.last loop if v.key (i) = key then index := i; found := True; return; end if; end loop; found := False; end Find; procedure Delete_Index (v : in out Ordered_Map; index : in Integer) is begin for i in index + 1 .. v.last loop v.key (i - 1) := v.key (i); v.elt (i - 1) := v.elt (i); end loop; v.last := v.last - 1; end Delete_Index; -- There may be multiple elements for the same key. procedure Delete_Element (map : in out Ordered_Map; key, element : Integer) is idx_ord_delete : Integer; key_found : Boolean; elt_found : Boolean; begin Find (map, key, idx_ord_delete, key_found); if key_found then elt_found := False; for j in idx_ord_delete .. map.last loop if map.elt (j) = element then -- Found our element in the map. Delete_Index (map, j); elt_found := True; exit; end if; end loop; if not elt_found then Put ("Element not found"); end if; else Put ("Key not found"); end if; end Delete_Element; type Brick is record edge_min, edge_max : Point_3D; end record; type Brick_Array is array (1 .. capacity) of Brick; type List_Type is record brick : Brick_Array; last : Natural; z_top, z_bottom : Ordered_Map; -- Ordered tops and bottoms of bricks end record; -- GNAT runs this program on the actual problem data in 2.24 seconds, -- while HAC takes forever. compiler_test_mode : constant Boolean := Argument_Count >= 2; function Input_Name return VString is begin if compiler_test_mode then -- We grab the small data directly from the text! return +"aoc_2023_22_questions"; else return +"aoc_2023_22"; end if; end Input_Name; example_length : constant := 7; procedure Read_Data (list : out List_Type) is dummy : Character; f : File_Type; e_min, e_max : Point_3D; begin list.last := 0; list.z_top.last := 0; list.z_bottom.last := 0; Open (f, Input_Name & ".txt"); if compiler_test_mode then -- Skip x lines of bla-bla. Skip_Line (f, 13); end if; while not End_Of_File (f) loop Get (f, e_min.x); Get (f, dummy); Get (f, e_min.y); Get (f, dummy); Get (f, e_min.z); Get (f, dummy); Get (f, e_max.x); Get (f, dummy); Get (f, e_max.y); Get (f, dummy); Get (f, e_max.z); -- list.last := list.last + 1; list.brick (list.last).edge_min := e_min; list.brick (list.last).edge_max := e_max; Insert (list.z_bottom, e_min.z, list.last); Insert (list.z_top, e_max.z, list.last); -- exit when compiler_test_mode and then list.last = example_length; end loop; Close (f); end Read_Data; r : array (Part_Type) of Integer; procedure Fall (list : in out List_Type; ignore : in Natural; simulate : in Boolean; moves : out Natural) is own_z_bottom, own_z_top : Integer; idx_own, idx_ord_other, idx_other : Integer; found : Boolean; x1, x2, y1, y2 : Integer; xt1, xt2, yt1, yt2 : Integer; brick_can_move : Boolean; begin moves := 0; Check_Bottoms : for i in 1 .. list.z_bottom.last loop own_z_bottom := list.z_bottom.key (i); idx_own := list.z_bottom.elt (i); own_z_top := list.brick (idx_own).edge_max.z; brick_can_move := False; Iterate_Bottom : while own_z_bottom > 1 loop own_z_bottom := own_z_bottom - 1; own_z_top := own_z_top - 1; -- We let the bottom fall until it hits the top -- of another brick. Find (list.z_top, own_z_bottom, idx_ord_other, found); if found then x1 := list.brick (idx_own).edge_min.x; x2 := list.brick (idx_own).edge_max.x; y1 := list.brick (idx_own).edge_min.y; y2 := list.brick (idx_own).edge_max.y; while idx_ord_other <= list.z_top.last and then list.z_top.key (idx_ord_other) = own_z_bottom loop -- We have a series of "other" bricks whose top face -- might collide with "our" falling brick's bottom face. -- "Our" brick's bottom is at height `own_z_bottom` -- The "other" brick's top face is at the same height. -- If the rectangles intersect, the fall has clearly -- gone too far... idx_other := list.z_top.elt (idx_ord_other); if idx_other /= idx_own and then idx_other /= ignore then xt1 := list.brick (idx_other).edge_min.x; xt2 := list.brick (idx_other).edge_max.x; yt1 := list.brick (idx_other).edge_min.y; yt2 := list.brick (idx_other).edge_max.y; exit Iterate_Bottom when not (xt2 < x1 or else -- the "other" brick is left to our brick xt1 > x2 or else -- the "other" brick is right to our brick yt2 < y1 or else -- same for y axis yt1 > y2); -- same for y axis end if; idx_ord_other := idx_ord_other + 1; end loop; end if; brick_can_move := True; if simulate then moves := 1; -- Just some non-zero value. exit Check_Bottoms; -- "Don't actually disintegrate any bricks - just determine -- what would happen if, for each brick, only that -- brick were disintegrated." end if; -- All right, we can safely move the brick down by -1. list.brick (idx_own).edge_min.z := own_z_bottom; list.brick (idx_own).edge_max.z := own_z_top; -- Keep top / bottom lists up-to-date. Delete_Element (list.z_top, own_z_top + 1, idx_own); Delete_Element (list.z_bottom, own_z_bottom + 1, idx_own); Insert (list.z_top, own_z_top, idx_own); Insert (list.z_bottom, own_z_bottom, idx_own); end loop Iterate_Bottom; if brick_can_move then moves := moves + 1; end if; end loop Check_Bottoms; end Fall; data : List_Type; procedure Do_Part_1 is list : List_Type := data; moves : Natural; begin -- "You'll need to start by figuring out where [the falling bricks] -- will end up." Fall (list, 0, False, moves); r (part_1) := 0; for brick_index in 1 .. list.last loop Fall (list, brick_index, True, moves); if moves = 0 then -- Brick #brick_index is safe to disintegrate. r (part_1) := r (part_1) + 1; end if; end loop; end Do_Part_1; procedure Do_Part_2 is list, work : List_Type := data; moves : Natural; begin Fall (list, 0, False, moves); r (part_2) := 0; for brick_index in 1 .. list.last loop work := list; Fall (work, brick_index, False, moves); -- Put_Line -- (+"Disintegrating brick #" & brick_index & -- " would cause " & moves & " to fall"); r (part_2) := r (part_2) + moves; end loop; end Do_Part_2; T0 : constant Time := Clock; begin Read_Data (data); Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 451 (example: 5) -- Part 2: validated by AoC: 66530 (example: 7) end if; end AoC_2023_22; ================================================ FILE: exm/aoc/2023/aoc_2023_22.txt ================================================ 9,7,295~9,8,295 7,1,214~7,1,217 4,3,272~6,3,272 6,2,55~6,4,55 1,2,254~1,4,254 4,5,291~7,5,291 4,2,73~4,2,74 8,3,224~9,3,224 2,5,94~2,7,94 9,9,15~9,9,17 9,5,88~9,7,88 6,9,253~7,9,253 9,7,215~9,9,215 1,2,295~1,5,295 2,6,54~4,6,54 8,0,7~8,0,9 5,4,301~5,5,301 2,1,172~4,1,172 9,4,99~9,7,99 2,6,59~2,8,59 1,5,17~1,9,17 5,9,100~7,9,100 8,6,227~8,6,227 0,2,177~0,5,177 4,2,184~4,2,187 3,4,147~3,6,147 4,5,313~4,6,313 4,6,99~5,6,99 0,6,3~3,6,3 1,4,265~2,4,265 9,8,14~9,9,14 5,4,317~5,5,317 1,3,253~1,5,253 5,1,85~5,1,86 5,7,24~8,7,24 1,1,84~3,1,84 1,0,101~4,0,101 5,1,58~8,1,58 9,3,234~9,5,234 9,4,203~9,5,203 6,4,227~9,4,227 9,0,261~9,2,261 9,7,106~9,8,106 9,1,262~9,2,262 3,7,67~3,9,67 4,7,301~4,9,301 4,2,339~4,3,339 8,0,262~8,0,264 6,1,91~7,1,91 0,2,102~0,6,102 0,1,169~0,4,169 4,4,332~7,4,332 1,2,39~1,4,39 0,8,45~2,8,45 9,6,211~9,8,211 3,8,137~3,8,139 7,7,242~7,9,242 2,4,128~2,6,128 8,6,299~8,8,299 3,3,42~5,3,42 7,3,9~9,3,9 1,8,92~2,8,92 4,9,289~7,9,289 3,2,280~5,2,280 1,4,1~1,4,1 0,1,39~0,1,42 4,2,231~4,3,231 7,2,86~7,2,88 4,9,104~7,9,104 8,2,234~8,4,234 0,0,163~0,0,164 8,2,22~8,4,22 8,0,131~8,0,133 5,1,196~7,1,196 7,2,311~9,2,311 1,9,188~4,9,188 2,4,29~4,4,29 6,6,342~6,8,342 4,1,116~6,1,116 9,6,213~9,8,213 8,3,270~8,4,270 5,4,312~5,5,312 6,3,257~8,3,257 8,6,81~8,8,81 6,7,191~6,7,193 5,2,6~7,2,6 0,1,117~2,1,117 1,3,338~1,3,339 5,2,58~7,2,58 3,4,140~5,4,140 8,5,315~9,5,315 0,2,259~0,2,261 2,9,300~2,9,302 4,0,263~7,0,263 3,5,28~5,5,28 9,6,234~9,6,235 4,7,126~4,8,126 4,2,286~4,2,286 9,0,124~9,1,124 1,7,137~1,9,137 3,3,136~3,5,136 9,0,104~9,1,104 1,4,229~1,4,232 9,1,200~9,2,200 2,7,209~2,9,209 3,1,33~3,4,33 0,1,124~1,1,124 1,2,242~3,2,242 8,9,176~9,9,176 2,1,46~4,1,46 1,1,43~1,2,43 5,6,243~5,7,243 8,5,42~8,7,42 7,1,84~7,3,84 5,4,127~5,6,127 0,2,117~1,2,117 9,1,296~9,1,299 2,6,44~2,9,44 3,6,49~7,6,49 0,8,188~0,9,188 8,3,195~8,5,195 4,3,140~8,3,140 8,4,200~8,5,200 4,2,31~4,4,31 0,5,327~2,5,327 0,0,109~0,3,109 7,8,301~9,8,301 5,4,112~6,4,112 4,3,255~6,3,255 5,0,177~5,0,177 4,5,320~6,5,320 0,5,58~2,5,58 4,4,300~6,4,300 1,6,39~3,6,39 0,6,94~0,6,97 0,8,182~1,8,182 3,5,30~3,6,30 6,2,71~6,5,71 2,5,125~2,7,125 8,5,168~8,7,168 5,3,275~5,5,275 6,2,153~6,2,154 6,3,63~6,6,63 1,5,42~2,5,42 3,5,306~3,8,306 2,1,296~5,1,296 5,5,85~5,8,85 3,0,260~3,2,260 7,2,213~7,4,213 0,0,16~0,3,16 4,9,34~7,9,34 2,8,163~2,8,163 4,6,209~4,9,209 5,4,297~5,6,297 1,6,222~1,7,222 0,4,227~3,4,227 4,2,50~7,2,50 9,5,61~9,7,61 5,5,115~8,5,115 6,3,85~9,3,85 0,0,106~0,2,106 8,2,219~9,2,219 9,1,14~9,2,14 9,2,306~9,5,306 5,4,302~5,7,302 2,6,97~5,6,97 5,0,146~5,2,146 4,9,125~4,9,127 0,4,293~3,4,293 6,7,295~6,9,295 0,1,44~2,1,44 4,8,158~7,8,158 0,2,118~0,4,118 7,2,191~7,3,191 1,6,18~1,7,18 5,7,33~5,9,33 1,6,140~1,6,142 1,8,321~3,8,321 2,7,30~5,7,30 8,2,174~8,4,174 2,2,275~2,5,275 6,8,247~9,8,247 6,7,217~6,9,217 3,3,65~3,5,65 1,0,312~3,0,312 0,5,141~2,5,141 6,1,208~8,1,208 3,6,99~3,7,99 4,5,57~6,5,57 7,6,121~9,6,121 1,5,317~4,5,317 6,2,56~8,2,56 5,0,13~7,0,13 6,5,157~8,5,157 6,2,52~6,3,52 7,3,239~7,3,242 0,6,220~2,6,220 4,2,91~6,2,91 4,5,332~5,5,332 8,0,65~9,0,65 2,7,282~4,7,282 2,4,100~2,6,100 6,1,98~9,1,98 5,4,119~7,4,119 6,4,153~6,6,153 5,1,62~8,1,62 5,3,142~5,4,142 3,2,326~3,5,326 9,5,90~9,8,90 5,4,145~5,6,145 9,0,234~9,2,234 1,7,21~1,9,21 4,1,261~6,1,261 2,7,336~4,7,336 7,3,87~7,3,90 2,7,154~4,7,154 0,4,171~0,4,173 3,6,309~3,6,311 6,6,114~8,6,114 8,5,60~8,7,60 7,0,205~7,2,205 5,3,339~7,3,339 5,5,276~5,7,276 3,2,241~3,4,241 6,5,301~7,5,301 7,5,40~7,6,40 6,1,331~8,1,331 2,0,96~5,0,96 6,3,87~6,5,87 4,9,228~6,9,228 0,1,49~0,2,49 1,1,248~1,3,248 8,3,87~8,5,87 1,4,149~2,4,149 0,3,31~0,3,33 6,7,122~6,7,124 2,6,149~5,6,149 3,9,7~6,9,7 1,4,329~4,4,329 4,2,259~4,2,262 0,1,1~0,3,1 6,3,12~6,4,12 7,1,199~9,1,199 5,3,166~5,6,166 4,9,97~6,9,97 4,5,292~4,7,292 0,5,79~0,6,79 0,3,258~2,3,258 4,1,258~8,1,258 0,4,72~3,4,72 1,7,261~3,7,261 8,5,313~8,7,313 3,0,44~3,3,44 4,6,307~7,6,307 2,8,258~5,8,258 2,6,45~3,6,45 8,3,90~8,5,90 4,7,213~4,8,213 0,0,19~3,0,19 3,1,306~3,3,306 8,5,207~8,8,207 0,7,210~1,7,210 3,7,102~6,7,102 2,8,249~4,8,249 5,4,133~7,4,133 9,3,237~9,3,240 7,8,125~7,9,125 0,0,272~0,0,274 6,4,16~7,4,16 1,2,47~1,2,49 6,0,265~6,3,265 7,3,148~9,3,148 0,2,264~0,3,264 4,6,124~5,6,124 5,7,75~7,7,75 5,0,75~5,2,75 4,3,28~4,4,28 3,1,92~3,2,92 1,4,92~1,4,93 4,5,49~5,5,49 3,4,76~3,4,78 0,4,252~2,4,252 1,5,205~2,5,205 1,2,263~1,6,263 5,0,17~7,0,17 7,1,59~7,1,60 5,6,173~5,6,175 7,4,81~9,4,81 3,4,330~3,5,330 5,3,216~5,5,216 0,3,338~0,6,338 6,8,292~8,8,292 6,2,3~8,2,3 7,3,259~8,3,259 0,0,223~2,0,223 1,2,118~3,2,118 1,9,71~3,9,71 6,0,121~9,0,121 7,6,197~7,8,197 2,0,81~5,0,81 9,1,100~9,2,100 6,3,3~6,6,3 3,0,262~3,1,262 6,1,144~6,4,144 2,5,95~5,5,95 7,3,198~7,5,198 4,9,86~6,9,86 7,7,84~8,7,84 7,2,327~7,2,331 4,6,69~4,8,69 2,3,255~2,5,255 0,8,319~2,8,319 1,7,198~1,9,198 3,0,263~3,0,264 4,3,327~4,6,327 9,1,126~9,1,128 2,4,22~4,4,22 4,2,207~6,2,207 5,3,45~6,3,45 1,0,232~1,2,232 3,0,330~4,0,330 4,5,101~6,5,101 1,3,42~1,3,43 5,5,239~5,7,239 1,8,332~3,8,332 2,8,6~2,9,6 6,5,113~6,6,113 3,6,249~3,7,249 0,8,164~3,8,164 1,2,179~1,2,181 5,8,91~8,8,91 4,0,54~7,0,54 2,9,286~5,9,286 8,5,260~8,7,260 0,0,302~2,0,302 7,3,195~7,6,195 8,6,86~9,6,86 5,3,171~7,3,171 9,2,15~9,3,15 6,8,225~7,8,225 1,5,203~3,5,203 3,2,301~3,3,301 7,2,265~7,2,268 1,4,81~3,4,81 6,6,65~6,7,65 6,0,22~7,0,22 2,7,124~4,7,124 0,5,145~0,5,146 2,3,179~2,6,179 8,5,308~8,7,308 8,4,173~8,6,173 5,4,284~7,4,284 1,2,147~1,2,148 8,0,64~8,3,64 4,0,283~4,2,283 2,3,253~2,4,253 6,6,171~9,6,171 2,6,290~2,8,290 4,8,37~4,9,37 5,8,252~6,8,252 7,0,267~9,0,267 7,6,317~7,7,317 4,3,250~4,5,250 6,8,21~6,8,23 4,0,156~6,0,156 9,5,96~9,5,98 3,6,51~6,6,51 4,0,167~5,0,167 4,1,251~5,1,251 1,1,13~1,4,13 6,1,87~7,1,87 4,4,135~6,4,135 4,4,88~4,4,90 6,1,287~6,4,287 1,7,163~1,9,163 1,2,90~5,2,90 3,9,131~3,9,134 7,3,11~9,3,11 4,9,225~5,9,225 5,6,37~8,6,37 0,9,289~2,9,289 0,5,88~2,5,88 7,0,78~9,0,78 9,3,5~9,6,5 3,9,105~6,9,105 1,5,147~1,7,147 6,6,339~6,8,339 1,5,57~2,5,57 6,9,119~8,9,119 4,1,11~4,3,11 3,5,133~5,5,133 7,4,217~7,6,217 6,0,220~8,0,220 5,7,70~5,7,73 3,0,3~7,0,3 6,1,24~6,3,24 6,7,319~6,9,319 3,1,256~5,1,256 6,4,36~6,6,36 2,5,151~2,8,151 3,2,281~5,2,281 3,5,144~3,7,144 2,7,46~3,7,46 6,7,336~8,7,336 7,5,162~8,5,162 4,1,241~8,1,241 3,1,47~3,4,47 6,0,266~6,0,269 1,9,8~3,9,8 6,7,220~6,8,220 9,6,174~9,9,174 9,5,92~9,6,92 5,1,111~5,3,111 8,6,83~8,9,83 4,3,23~6,3,23 2,5,324~2,8,324 2,4,256~4,4,256 5,9,292~6,9,292 3,3,243~3,5,243 3,3,163~6,3,163 8,3,96~8,4,96 3,6,142~5,6,142 9,5,58~9,7,58 4,4,172~7,4,172 0,1,115~1,1,115 2,6,8~3,6,8 9,1,316~9,4,316 1,5,256~1,8,256 6,3,137~6,5,137 2,9,316~5,9,316 0,1,38~2,1,38 4,6,328~7,6,328 6,7,287~6,7,290 4,9,84~6,9,84 2,2,315~2,4,315 3,3,197~5,3,197 4,0,217~8,0,217 0,9,297~3,9,297 1,2,277~1,5,277 3,4,202~4,4,202 4,3,150~5,3,150 1,5,207~1,7,207 0,3,17~0,4,17 3,6,256~3,8,256 7,1,129~7,2,129 1,1,272~1,5,272 1,2,278~1,2,280 1,0,267~3,0,267 6,6,19~9,6,19 3,0,140~3,2,140 0,0,95~2,0,95 0,1,159~0,3,159 4,9,322~6,9,322 2,7,173~2,9,173 8,4,92~9,4,92 7,0,19~7,1,19 5,8,320~6,8,320 1,1,251~3,1,251 2,4,24~2,7,24 5,4,303~5,6,303 0,0,270~2,0,270 2,2,70~2,2,73 2,7,174~2,7,177 6,2,11~6,4,11 3,0,169~4,0,169 9,3,93~9,5,93 5,7,316~7,7,316 5,1,3~8,1,3 2,4,70~3,4,70 2,2,61~2,5,61 4,5,205~6,5,205 1,1,2~1,1,5 2,0,143~5,0,143 0,0,166~0,1,166 0,0,113~2,0,113 5,4,23~5,5,23 8,5,78~8,8,78 0,0,224~0,2,224 4,1,90~4,1,91 6,9,91~6,9,93 0,4,207~2,4,207 5,2,39~5,5,39 0,0,22~2,0,22 1,7,95~1,7,95 1,1,274~1,1,277 0,0,25~0,0,27 7,7,295~7,9,295 7,1,52~7,2,52 0,8,219~0,8,221 0,6,136~2,6,136 0,4,255~0,6,255 6,6,294~6,8,294 8,5,57~9,5,57 0,8,175~4,8,175 6,8,47~6,8,49 4,1,342~4,2,342 3,3,200~3,5,200 0,1,337~0,4,337 3,3,43~4,3,43 1,8,179~3,8,179 4,0,205~4,2,205 1,1,130~1,1,131 2,6,4~4,6,4 2,0,211~5,0,211 8,4,295~8,6,295 4,9,211~4,9,214 0,1,47~2,1,47 5,5,160~7,5,160 1,6,85~2,6,85 2,1,170~5,1,170 2,7,191~2,9,191 3,8,68~5,8,68 6,4,204~6,5,204 6,8,194~9,8,194 5,6,111~7,6,111 0,2,256~2,2,256 0,3,73~3,3,73 1,5,177~2,5,177 3,4,84~5,4,84 1,2,229~1,2,231 1,4,290~1,7,290 3,0,108~5,0,108 5,0,127~7,0,127 6,7,196~6,9,196 4,2,188~7,2,188 9,5,316~9,7,316 3,2,136~3,2,139 5,3,2~5,6,2 1,0,8~3,0,8 4,2,252~6,2,252 4,6,167~6,6,167 5,6,188~5,7,188 8,6,261~8,9,261 2,2,332~2,4,332 3,1,4~4,1,4 6,0,292~6,1,292 2,0,99~3,0,99 0,4,147~1,4,147 3,4,242~3,5,242 5,5,245~8,5,245 4,7,217~4,9,217 6,7,85~6,9,85 8,5,66~8,5,67 6,0,190~6,2,190 2,7,137~2,9,137 0,4,87~0,6,87 1,6,217~3,6,217 1,4,14~1,4,14 6,2,176~9,2,176 5,8,139~8,8,139 6,7,300~6,9,300 3,0,180~3,2,180 8,0,129~8,1,129 7,8,175~9,8,175 7,7,244~7,9,244 6,4,38~8,4,38 8,0,171~9,0,171 4,0,285~4,2,285 0,4,12~0,4,13 0,1,75~0,3,75 9,4,177~9,6,177 4,1,324~4,3,324 5,4,75~8,4,75 4,6,118~6,6,118 5,4,158~5,4,160 7,2,152~7,4,152 3,0,87~5,0,87 3,1,78~3,1,78 5,4,87~5,6,87 4,7,67~4,9,67 6,7,157~8,7,157 7,4,184~7,5,184 0,1,307~3,1,307 4,6,299~5,6,299 4,3,325~6,3,325 5,2,196~5,4,196 1,5,52~4,5,52 7,8,99~8,8,99 0,9,179~2,9,179 5,5,58~5,7,58 5,2,327~5,2,327 3,8,17~5,8,17 6,4,333~6,5,333 1,1,245~1,4,245 7,6,292~8,6,292 3,9,223~5,9,223 7,8,128~9,8,128 2,0,338~2,3,338 5,2,152~5,3,152 2,1,304~4,1,304 2,3,69~4,3,69 4,1,71~4,3,71 5,0,300~7,0,300 4,0,328~4,2,328 3,8,6~3,8,8 5,8,219~6,8,219 3,1,14~4,1,14 5,5,54~7,5,54 3,5,71~5,5,71 3,7,159~3,8,159 5,2,260~7,2,260 1,3,204~4,3,204 6,2,179~6,4,179 5,5,81~5,7,81 4,4,299~7,4,299 7,8,47~8,8,47 4,3,6~6,3,6 2,5,3~4,5,3 8,2,203~8,5,203 8,8,86~9,8,86 5,0,16~7,0,16 3,6,218~3,8,218 7,2,158~8,2,158 6,3,162~6,6,162 3,6,173~3,6,174 8,6,224~9,6,224 3,7,221~3,9,221 4,1,247~4,4,247 1,7,85~1,9,85 0,4,93~0,7,93 4,8,7~5,8,7 7,5,305~8,5,305 6,3,74~7,3,74 5,8,245~7,8,245 3,5,305~3,8,305 8,9,127~9,9,127 3,9,181~5,9,181 8,8,197~8,8,198 2,3,142~2,5,142 0,1,157~0,3,157 5,9,302~7,9,302 2,9,128~5,9,128 6,5,9~7,5,9 2,1,320~2,4,320 5,4,72~7,4,72 3,5,201~3,8,201 1,3,271~1,6,271 9,2,19~9,3,19 3,7,68~5,7,68 2,1,302~3,1,302 1,7,318~1,8,318 2,0,164~2,1,164 3,6,330~3,8,330 6,5,250~6,8,250 0,2,42~1,2,42 4,5,168~4,7,168 4,4,241~5,4,241 3,7,281~5,7,281 0,5,61~0,6,61 6,4,13~6,4,15 7,6,251~7,6,252 5,2,173~5,3,173 4,3,206~4,6,206 6,2,54~6,3,54 3,6,247~3,9,247 1,1,77~4,1,77 2,0,226~2,0,228 0,4,335~3,4,335 4,3,288~7,3,288 0,3,72~2,3,72 7,1,2~7,4,2 7,0,4~9,0,4 0,5,257~0,6,257 4,2,12~7,2,12 0,3,30~3,3,30 7,4,309~7,7,309 4,9,101~6,9,101 0,8,75~1,8,75 4,0,76~8,0,76 7,9,11~9,9,11 5,1,182~6,1,182 5,5,170~5,7,170 1,6,143~1,8,143 2,7,61~2,7,62 5,6,43~5,8,43 5,6,65~5,7,65 6,0,152~6,0,154 6,7,175~8,7,175 0,6,258~0,7,258 2,3,65~2,5,65 4,0,89~4,2,89 2,6,130~2,8,130 7,0,333~7,3,333 6,3,269~6,5,269 8,4,267~9,4,267 2,1,184~3,1,184 5,9,295~5,9,296 5,7,215~6,7,215 6,4,188~7,4,188 2,2,43~2,5,43 6,2,311~6,4,311 2,5,105~2,6,105 9,6,222~9,9,222 6,3,334~6,5,334 3,3,338~4,3,338 6,4,155~6,7,155 0,9,86~0,9,88 5,8,159~5,9,159 6,4,148~6,4,151 9,2,291~9,5,291 4,1,211~7,1,211 1,7,78~1,9,78 1,7,44~1,9,44 0,5,8~0,8,8 5,1,127~8,1,127 7,4,78~7,5,78 2,3,1~2,3,2 7,8,43~9,8,43 2,0,6~2,2,6 1,7,134~3,7,134 1,5,72~1,8,72 7,3,337~7,6,337 3,1,336~3,3,336 1,6,1~1,6,2 5,0,246~5,3,246 5,1,328~7,1,328 2,7,100~2,8,100 9,5,205~9,7,205 7,6,165~8,6,165 1,6,139~2,6,139 7,3,135~7,5,135 9,2,207~9,2,210 1,3,311~1,6,311 2,4,152~2,5,152 5,6,88~7,6,88 3,6,33~3,6,37 3,2,177~6,2,177 7,6,38~7,8,38 6,2,150~9,2,150 7,5,250~7,6,250 7,4,334~7,7,334 5,1,180~5,4,180 5,3,155~5,4,155 3,7,310~3,9,310 2,0,15~2,3,15 0,1,227~0,1,229 6,4,68~6,6,68 7,8,215~7,8,217 1,9,45~2,9,45 7,6,21~7,6,23 1,1,294~1,4,294 3,6,283~3,8,283 0,3,63~3,3,63 5,5,315~5,7,315 4,7,5~4,9,5 9,3,6~9,5,6 4,8,322~6,8,322 9,0,308~9,2,308 0,2,144~0,5,144 2,7,28~5,7,28 4,3,308~6,3,308 4,4,330~4,5,330 7,8,1~9,8,1 4,1,1~4,2,1 9,5,289~9,7,289 2,9,192~4,9,192 6,4,185~6,6,185 0,8,90~2,8,90 1,5,316~1,7,316 6,6,189~6,8,189 5,7,252~6,7,252 4,0,141~4,3,141 0,6,7~0,8,7 7,0,65~7,1,65 1,0,233~1,1,233 1,8,154~4,8,154 3,8,157~5,8,157 9,6,216~9,8,216 2,6,172~2,7,172 0,3,130~0,3,132 6,0,207~9,0,207 6,6,298~6,9,298 0,4,210~0,5,210 1,9,185~4,9,185 6,1,93~6,1,95 0,5,328~2,5,328 1,6,289~3,6,289 5,3,46~5,5,46 7,1,144~7,3,144 7,4,247~7,6,247 1,4,36~1,4,38 0,9,139~2,9,139 1,4,89~1,6,89 8,5,196~8,5,198 0,6,5~0,9,5 5,4,266~8,4,266 3,3,234~5,3,234 4,2,301~4,4,301 6,7,68~7,7,68 8,4,311~8,6,311 0,9,84~2,9,84 5,6,82~7,6,82 0,0,162~2,0,162 4,8,200~4,8,202 2,6,284~2,9,284 3,2,131~3,5,131 5,2,236~7,2,236 0,3,312~2,3,312 3,2,203~7,2,203 5,3,108~5,6,108 0,1,301~3,1,301 1,6,82~1,8,82 5,7,60~5,8,60 0,8,218~2,8,218 9,7,2~9,7,5 2,7,178~2,7,181 8,1,103~9,1,103 8,7,235~9,7,235 4,1,72~4,1,74 5,5,284~5,6,284 2,5,175~2,6,175 6,5,12~6,7,12 3,3,238~3,5,238 2,5,222~2,7,222 6,0,149~6,1,149 8,2,225~8,5,225 7,8,210~9,8,210 5,6,278~6,6,278 6,7,18~9,7,18 4,6,295~4,9,295 1,8,14~3,8,14 2,3,83~2,3,84 9,2,206~9,5,206 4,9,184~5,9,184 5,3,247~5,5,247 0,2,155~0,3,155 6,1,151~6,2,151 3,2,134~4,2,134 5,0,303~5,1,303 2,2,326~2,2,328 6,0,124~6,3,124 6,9,315~6,9,318 6,7,36~6,7,38 7,0,311~9,0,311 8,5,118~8,5,119 0,0,168~2,0,168 2,2,10~2,2,12 6,1,42~6,1,45 8,2,70~8,3,70 8,7,88~8,8,88 3,2,199~6,2,199 8,0,107~9,0,107 9,2,231~9,5,231 1,6,322~1,9,322 6,7,77~8,7,77 7,5,161~9,5,161 1,0,12~4,0,12 3,5,35~4,5,35 4,6,164~8,6,164 4,1,270~4,2,270 9,7,101~9,9,101 4,1,113~6,1,113 1,1,127~3,1,127 7,4,53~8,4,53 8,4,17~8,7,17 1,2,319~1,2,319 3,4,19~3,5,19 3,5,246~3,6,246 6,8,191~6,8,193 3,5,164~5,5,164 0,6,89~0,8,89 8,6,4~8,9,4 7,6,289~7,8,289 1,2,144~4,2,144 5,4,294~5,5,294 8,3,95~8,6,95 6,5,117~6,7,117 7,1,53~9,1,53 7,7,107~7,7,109 1,1,336~1,3,336 9,2,12~9,4,12 0,4,10~2,4,10 3,0,305~3,2,305 8,2,1~8,4,1 8,3,67~8,3,67 4,4,137~4,7,137 1,8,3~4,8,3 7,1,220~9,1,220 8,1,178~8,3,178 0,3,314~1,3,314 4,6,187~6,6,187 9,4,229~9,6,229 2,5,257~2,5,259 6,6,41~9,6,41 5,6,62~5,7,62 1,3,105~1,5,105 0,3,175~0,5,175 2,4,268~2,4,268 2,3,35~2,5,35 0,7,195~2,7,195 4,0,257~7,0,257 2,6,87~2,6,90 5,2,77~5,2,78 5,0,63~5,2,63 4,7,170~4,7,171 5,5,214~9,5,214 5,7,240~7,7,240 1,2,317~4,2,317 6,6,16~6,8,16 2,3,167~2,5,167 6,6,198~6,7,198 2,1,167~3,1,167 8,9,124~9,9,124 4,0,168~6,0,168 1,6,213~1,8,213 4,8,286~7,8,286 3,8,10~6,8,10 7,8,41~9,8,41 0,0,219~3,0,219 2,0,4~4,0,4 2,5,138~3,5,138 6,4,182~7,4,182 3,6,341~6,6,341 6,0,159~6,0,161 6,0,162~8,0,162 7,5,69~7,7,69 8,2,314~8,2,316 4,4,113~4,6,113 4,5,208~4,5,211 4,9,305~6,9,305 1,4,268~1,4,270 1,9,1~3,9,1 7,2,8~9,2,8 2,1,130~2,1,132 2,8,11~3,8,11 0,0,112~0,2,112 7,9,2~7,9,3 1,2,177~1,3,177 6,7,14~8,7,14 5,7,279~7,7,279 1,8,160~4,8,160 7,7,171~8,7,171 7,2,263~7,4,263 1,0,45~1,2,45 2,2,67~2,5,67 4,6,77~4,8,77 3,5,162~5,5,162 0,5,211~1,5,211 4,7,285~6,7,285 1,2,276~2,2,276 0,2,335~3,2,335 8,1,271~8,4,271 6,9,304~8,9,304 4,4,111~6,4,111 0,6,217~0,8,217 1,6,74~2,6,74 1,5,69~3,5,69 0,4,336~0,6,336 4,0,104~4,0,107 6,5,2~9,5,2 7,0,208~9,0,208 1,7,156~2,7,156 5,1,39~5,1,42 5,1,289~7,1,289 6,5,298~8,5,298 7,1,145~7,1,147 9,7,20~9,7,22 1,5,6~1,6,6 2,7,212~5,7,212 0,2,34~3,2,34 6,5,14~6,5,15 6,1,7~6,3,7 7,0,63~7,2,63 3,2,164~3,4,164 7,7,250~7,9,250 0,7,292~2,7,292 5,2,191~5,4,191 7,2,145~7,5,145 6,8,231~6,9,231 4,0,158~7,0,158 5,5,206~7,5,206 3,5,18~7,5,18 0,7,320~0,9,320 3,6,178~3,9,178 5,2,210~7,2,210 6,8,93~8,8,93 1,1,133~1,1,136 2,0,210~2,1,210 5,7,287~5,8,287 5,9,94~7,9,94 7,0,67~7,2,67 0,6,313~2,6,313 7,9,129~7,9,130 4,5,181~6,5,181 5,9,96~7,9,96 3,3,290~3,6,290 7,6,258~9,6,258 1,8,200~2,8,200 3,7,333~3,7,335 1,0,81~1,3,81 2,3,108~2,6,108 3,7,145~3,7,148 0,3,160~1,3,160 3,4,91~6,4,91 3,2,321~5,2,321 5,1,215~5,4,215 1,7,81~1,9,81 8,2,175~8,3,175 3,5,206~3,7,206 0,1,125~0,1,127 4,1,238~4,4,238 1,2,33~1,5,33 3,2,322~3,4,322 3,5,36~5,5,36 2,9,85~2,9,86 0,5,1~0,5,3 0,2,105~0,3,105 6,8,222~6,9,222 2,7,138~2,7,138 7,0,90~7,1,90 0,8,190~0,9,190 6,3,142~7,3,142 4,3,328~5,3,328 5,9,313~7,9,313 0,4,74~0,6,74 1,7,295~1,9,295 6,6,179~6,9,179 1,2,84~1,4,84 1,7,259~2,7,259 1,4,61~1,6,61 2,0,146~2,3,146 5,4,86~7,4,86 2,7,164~4,7,164 1,3,29~4,3,29 7,8,74~7,8,74 2,8,79~4,8,79 4,5,67~5,5,67 5,7,26~9,7,26 5,0,55~8,0,55 6,0,214~6,1,214 5,9,88~6,9,88 0,1,122~0,3,122 1,4,308~4,4,308 8,0,223~8,3,223 4,1,265~4,3,265 5,9,308~5,9,311 5,3,237~5,5,237 6,5,33~6,8,33 2,3,260~3,3,260 6,0,78~6,0,80 8,2,160~8,3,160 1,6,41~1,7,41 8,4,244~8,4,247 2,3,203~3,3,203 7,6,202~7,8,202 4,6,301~4,6,303 9,4,180~9,6,180 0,0,115~1,0,115 7,2,324~7,5,324 8,0,80~8,1,80 2,1,255~5,1,255 2,6,56~2,6,58 3,0,1~6,0,1 9,2,179~9,2,182 6,3,193~9,3,193 1,8,220~1,8,221 1,0,57~4,0,57 0,5,109~2,5,109 9,2,212~9,4,212 1,5,258~1,5,260 3,6,40~5,6,40 4,2,83~6,2,83 9,2,202~9,3,202 0,4,314~0,6,314 1,0,159~4,0,159 2,5,262~2,5,264 4,4,25~4,6,25 9,6,60~9,8,60 3,1,36~6,1,36 3,2,237~3,5,237 3,6,253~3,9,253 7,5,213~7,8,213 4,7,123~4,9,123 4,3,305~4,6,305 0,2,323~3,2,323 4,6,26~6,6,26 0,2,325~4,2,325 8,4,61~8,6,61 4,8,88~5,8,88 0,7,293~0,7,295 6,8,343~6,9,343 6,3,88~6,3,90 8,2,245~8,2,246 9,6,29~9,7,29 5,0,175~7,0,175 4,3,343~5,3,343 1,6,250~3,6,250 9,7,250~9,9,250 0,6,263~0,7,263 9,0,223~9,1,223 2,3,166~4,3,166 2,7,97~2,7,97 1,0,9~3,0,9 2,3,273~4,3,273 4,1,147~4,3,147 2,6,194~2,7,194 3,4,30~5,4,30 5,8,71~8,8,71 4,8,199~7,8,199 7,6,72~8,6,72 7,0,135~8,0,135 1,2,124~2,2,124 6,2,47~6,3,47 5,5,88~5,5,88 6,6,121~6,9,121 2,3,341~4,3,341 4,5,16~7,5,16 8,4,210~8,5,210 5,6,283~5,8,283 7,2,89~9,2,89 3,7,135~3,8,135 6,7,203~6,8,203 4,1,9~7,1,9 6,7,118~6,9,118 1,5,312~2,5,312 3,3,286~3,6,286 4,3,85~4,5,85 6,3,60~6,5,60 9,4,233~9,7,233 8,4,19~8,4,20 7,0,168~8,0,168 8,4,250~8,5,250 8,3,149~8,3,150 6,9,308~9,9,308 6,9,123~9,9,123 6,9,12~8,9,12 4,9,82~6,9,82 5,3,243~5,5,243 5,5,311~7,5,311 3,9,313~3,9,314 2,2,279~2,2,282 2,3,80~2,6,80 2,8,303~4,8,303 2,6,285~2,7,285 2,5,208~2,7,208 5,5,183~5,5,186 7,4,118~7,6,118 8,3,142~8,6,142 0,6,138~0,6,139 7,3,267~7,4,267 2,6,170~4,6,170 2,7,213~2,9,213 9,0,294~9,2,294 6,1,175~6,4,175 3,0,299~3,3,299 5,2,74~7,2,74 6,5,209~8,5,209 5,8,3~5,8,5 7,6,311~7,7,311 3,4,101~3,6,101 9,2,17~9,3,17 0,0,1~2,0,1 4,3,321~7,3,321 0,6,86~1,6,86 1,0,87~2,0,87 9,2,314~9,4,314 5,3,169~5,4,169 5,0,174~5,2,174 7,4,232~9,4,232 7,6,46~7,9,46 2,2,9~2,5,9 7,2,238~7,3,238 5,6,15~7,6,15 6,3,178~6,6,178 5,5,97~5,5,99 8,5,201~9,5,201 9,9,216~9,9,220 1,7,225~1,8,225 9,0,153~9,2,153 1,1,79~1,3,79 4,3,116~4,3,116 6,7,177~6,8,177 3,3,9~4,3,9 4,8,297~4,9,297 6,7,20~6,7,21 2,0,89~2,0,92 7,2,51~7,5,51 0,3,149~2,3,149 3,7,64~5,7,64 7,9,128~9,9,128 5,0,266~5,2,266 9,7,103~9,8,103 6,5,20~9,5,20 4,1,212~6,1,212 3,7,224~3,9,224 1,1,182~4,1,182 8,4,54~8,6,54 1,3,151~2,3,151 8,0,243~8,4,243 6,1,70~8,1,70 3,5,32~6,5,32 7,1,82~8,1,82 1,0,309~1,1,309 2,2,228~5,2,228 0,1,304~0,2,304 6,1,254~6,4,254 1,0,11~1,1,11 5,5,66~6,5,66 0,3,108~0,4,108 6,0,216~6,3,216 6,6,24~9,6,24 9,8,61~9,9,61 3,4,309~3,4,310 2,5,293~3,5,293 1,2,226~4,2,226 2,0,84~4,0,84 6,8,72~7,8,72 9,0,3~9,1,3 2,4,34~3,4,34 7,9,307~8,9,307 6,8,5~8,8,5 2,1,35~4,1,35 6,7,194~8,7,194 8,2,63~8,4,63 4,8,44~6,8,44 1,1,121~3,1,121 5,9,160~5,9,162 8,7,21~8,7,22 0,2,127~0,3,127 4,0,254~4,2,254 0,6,99~1,6,99 0,8,298~1,8,298 4,2,266~4,2,267 2,2,103~2,4,103 2,5,294~4,5,294 4,0,51~4,3,51 4,7,299~4,9,299 4,1,305~6,1,305 2,1,225~2,4,225 0,6,212~0,9,212 5,0,326~5,3,326 8,7,296~8,8,296 3,0,49~3,1,49 7,0,119~7,3,119 3,5,165~3,6,165 1,7,144~1,9,144 6,1,1~6,3,1 5,2,310~5,3,310 8,1,216~8,3,216 6,0,297~6,2,297 2,4,41~2,6,41 6,1,39~6,1,41 5,5,104~5,5,106 5,4,59~5,7,59 2,9,256~4,9,256 3,3,172~3,5,172 4,5,310~4,7,310 5,3,21~5,6,21 3,0,202~3,2,202 1,6,165~1,6,167 8,4,306~8,7,306 5,5,6~7,5,6 5,8,20~5,8,22 6,9,223~6,9,226 5,7,104~8,7,104 0,8,185~2,8,185 4,4,74~4,7,74 6,5,288~9,5,288 1,3,249~1,4,249 6,6,181~8,6,181 7,0,260~9,0,260 6,5,286~6,7,286 1,3,174~3,3,174 4,7,163~4,8,163 1,9,80~4,9,80 3,5,257~3,8,257 0,4,89~0,4,91 8,0,108~8,2,108 0,5,77~2,5,77 4,1,249~4,3,249 5,0,83~5,1,83 5,0,279~5,2,279 5,4,279~5,4,282 6,6,200~6,8,200 1,7,92~1,7,93 1,4,315~1,6,315 1,2,17~3,2,17 0,4,294~0,5,294 4,3,114~5,3,114 6,8,19~8,8,19 2,8,46~4,8,46 2,2,166~4,2,166 9,2,103~9,3,103 3,7,312~4,7,312 1,8,94~1,8,95 5,3,256~5,3,256 2,0,301~4,0,301 0,5,317~0,7,317 4,5,140~4,6,140 1,2,120~1,2,121 5,4,78~5,6,78 7,5,255~9,5,255 0,3,124~2,3,124 0,5,62~0,7,62 9,4,292~9,6,292 7,3,12~7,3,15 7,2,116~7,5,116 0,3,78~0,3,80 8,7,173~8,7,173 3,2,181~5,2,181 2,5,27~2,7,27 8,6,170~8,8,170 5,5,255~5,7,255 1,4,74~3,4,74 4,6,121~4,7,121 3,9,68~3,9,69 0,1,116~0,3,116 2,4,337~2,6,337 5,4,136~5,6,136 0,1,15~0,4,15 3,3,244~3,3,245 3,4,130~5,4,130 4,2,233~6,2,233 4,4,244~4,6,244 1,7,158~4,7,158 8,5,253~8,7,253 5,5,138~5,8,138 1,1,236~4,1,236 5,0,23~7,0,23 0,1,77~0,3,77 1,4,55~1,6,55 0,5,103~2,5,103 5,1,213~8,1,213 1,6,191~1,9,191 0,6,261~0,8,261 2,3,148~2,4,148 2,1,208~5,1,208 0,7,91~2,7,91 1,4,204~1,6,204 8,0,313~8,3,313 6,6,310~6,8,310 6,9,9~8,9,9 3,0,10~6,0,10 0,6,216~3,6,216 5,0,165~7,0,165 0,1,119~2,1,119 4,1,293~7,1,293 5,1,194~5,3,194 1,7,327~4,7,327 6,3,5~6,4,5 5,0,80~5,2,80 7,5,303~9,5,303 4,2,84~6,2,84 3,6,41~5,6,41 7,6,216~8,6,216 0,3,152~1,3,152 1,3,145~3,3,145 0,6,105~0,6,108 7,4,302~9,4,302 8,8,294~9,8,294 8,5,63~8,7,63 3,7,309~5,7,309 3,2,169~3,4,169 5,1,276~5,4,276 2,5,133~2,7,133 5,1,56~7,1,56 8,1,109~8,4,109 3,2,257~5,2,257 2,0,213~2,0,217 6,1,147~6,4,147 7,1,177~7,3,177 8,5,205~8,7,205 8,1,317~9,1,317 0,9,7~0,9,7 7,5,119~7,5,121 0,5,196~0,7,196 1,9,176~2,9,176 8,6,255~8,8,255 5,1,2~6,1,2 3,4,7~3,6,7 8,2,39~8,4,39 9,7,319~9,7,321 8,7,96~8,8,96 5,0,295~7,0,295 1,5,266~1,7,266 3,8,19~4,8,19 1,5,164~1,7,164 3,3,104~3,5,104 3,0,89~3,0,90 5,2,65~5,4,65 6,4,8~8,4,8 2,0,222~2,2,222 4,2,318~4,3,318 7,1,155~7,3,155 3,5,202~6,5,202 ================================================ FILE: exm/aoc/2023/aoc_2023_22_questions.txt ================================================ --- Day 22: Sand Slabs --- Enough sand has fallen; it can finally filter water for Snow Island. Well, almost. The sand has been falling as large compacted bricks of sand, piling up to form an impressive stack here near the edge of Island Island. In order to make use of the sand to filter water, some of the bricks will need to be broken apart - nay, disintegrated - back into freely flowing sand. The stack is tall enough that you'll have to be careful about choosing which bricks to disintegrate; if you disintegrate the wrong brick, large portions of the stack could topple, which sounds pretty dangerous. The Elves responsible for water filtering operations took a snapshot of the bricks while they were still falling (your puzzle input) which should let you work out which bricks are safe to disintegrate. For example: 1,0,1~1,2,1 0,0,2~2,0,2 0,2,3~2,2,3 0,0,4~0,2,4 2,0,5~2,2,5 0,1,6~2,1,6 1,1,8~1,1,9 Each line of text in the snapshot represents the position of a single brick at the time the snapshot was taken. The position is given as two x,y,z coordinates - one for each end of the brick - separated by a tilde (~). Each brick is made up of a single straight line of cubes, and the Elves were even careful to choose a time for the snapshot that had all of the free-falling bricks at integer positions above the ground, so the whole snapshot is aligned to a three-dimensional cube grid. A line like 2,2,2~2,2,2 means that both ends of the brick are at the same coordinate - in other words, that the brick is a single cube. Lines like 0,0,10~1,0,10 or 0,0,10~0,1,10 both represent bricks that are two cubes in volume, both oriented horizontally. The first brick extends in the x direction, while the second brick extends in the y direction. A line like 0,0,1~0,0,10 represents a ten-cube brick which is oriented vertically. One end of the brick is the cube located at 0,0,1, while the other end of the brick is located directly above it at 0,0,10. The ground is at z=0 and is perfectly flat; the lowest z value a brick can have is therefore 1. So, 5,5,1~5,6,1 and 0,2,1~0,2,5 are both resting on the ground, but 3,3,2~3,3,3 was above the ground at the time of the snapshot. Because the snapshot was taken while the bricks were still falling, some bricks will still be in the air; you'll need to start by figuring out where they will end up. Bricks are magically stabilized, so they never rotate, even in weird situations like where a long horizontal brick is only supported on one end. Two bricks cannot occupy the same position, so a falling brick will come to rest upon the first other brick it encounters. Here is the same example again, this time with each brick given a letter so it can be marked in diagrams: 1,0,1~1,2,1 <- A 0,0,2~2,0,2 <- B 0,2,3~2,2,3 <- C 0,0,4~0,2,4 <- D 2,0,5~2,2,5 <- E 0,1,6~2,1,6 <- F 1,1,8~1,1,9 <- G At the time of the snapshot, from the side so the x axis goes left to right, these bricks are arranged like this: x 012 .G. 9 .G. 8 ... 7 FFF 6 ..E 5 z D.. 4 CCC 3 BBB 2 .A. 1 --- 0 Rotating the perspective 90 degrees so the y axis now goes left to right, the same bricks are arranged like this: y 012 .G. 9 .G. 8 ... 7 .F. 6 EEE 5 z DDD 4 ..C 3 B.. 2 AAA 1 --- 0 Once all of the bricks fall downward as far as they can go, the stack looks like this, where ? means bricks are hidden behind other bricks at that location: x 012 .G. 6 .G. 5 FFF 4 D.E 3 z ??? 2 .A. 1 --- 0 Again from the side: y 012 .G. 6 .G. 5 .F. 4 ??? 3 z B.C 2 AAA 1 --- 0 Now that all of the bricks have settled, it becomes easier to tell which bricks are supporting which other bricks: Brick A is the only brick supporting bricks B and C. Brick B is one of two bricks supporting brick D and brick E. Brick C is the other brick supporting brick D and brick E. Brick D supports brick F. Brick E also supports brick F. Brick F supports brick G. Brick G isn't supporting any bricks. Your first task is to figure out which bricks are safe to disintegrate. A brick can be safely disintegrated if, after removing it, no other bricks would fall further directly downward. Don't actually disintegrate any bricks - just determine what would happen if, for each brick, only that brick were disintegrated. Bricks can be disintegrated even if they're completely surrounded by other bricks; you can squeeze between bricks if you need to. In this example, the bricks can be disintegrated as follows: Brick A cannot be disintegrated safely; if it were disintegrated, bricks B and C would both fall. Brick B can be disintegrated; the bricks above it (D and E) would still be supported by brick C. Brick C can be disintegrated; the bricks above it (D and E) would still be supported by brick B. Brick D can be disintegrated; the brick above it (F) would still be supported by brick E. Brick E can be disintegrated; the brick above it (F) would still be supported by brick D. Brick F cannot be disintegrated; the brick above it (G) would fall. Brick G can be disintegrated; it does not support any other bricks. So, in this example, 5 bricks can be safely disintegrated. Figure how the blocks will settle based on the snapshot. Once they've settled, consider disintegrating a single brick; how many bricks could be safely chosen as the one to get disintegrated? --- Part Two --- Disintegrating bricks one at a time isn't going to be fast enough. While it might sound dangerous, what you really need is a chain reaction. You'll need to figure out the best brick to disintegrate. For each brick, determine how many other bricks would fall if that brick were disintegrated. Using the same example as above: Disintegrating brick A would cause all 6 other bricks to fall. Disintegrating brick F would cause only 1 other brick, G, to fall. Disintegrating any other brick would cause no other bricks to fall. So, in this example, the sum of the number of other bricks that would fall as a result of disintegrating each brick is 7. For each brick, determine how many other bricks would fall if that brick were disintegrated. What is the sum of the number of other bricks that would fall? ================================================ FILE: exm/aoc/2023/aoc_2023_23.adb ================================================ -- Solution to Advent of Code 2023, Day 23 ------------------------------------------ -- A Long Walk -- -- https://adventofcode.com/2023/day/23 -- Copy of questions in: aoc_2023_23_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; procedure AoC_2023_23 is use AoC_Toolbox, HAT; input_name : VString; skip_header : Natural; n : Positive; max_n : constant := 141; type Map_Type is array (1 .. max_n, 1 .. max_n) of Character; data : Map_Type; procedure Read_Data is f : File_Type; begin Open (f, input_name & ".txt"); for skip_it in 1 .. skip_header loop Skip_Line (f); end loop; for y in 1 .. n loop for x in 1 .. n loop Get (f, data (x, y)); end loop; end loop; Close (f); end Read_Data; procedure Show (map : Map_Type) is begin Put_Line ("Map: -------------------"); for y in 1 .. n loop for x in 1 .. n loop Put (map (x, y)); end loop; New_Line; end loop; end Show; r : array (Part_Type) of Integer; verbosity : constant := 0; procedure Do_Part (part : Part_Type) is procedure Walk_from (map : in out Map_Type; x, y : Integer; done_so_far : Natural) is more : Natural := 0; procedure Flood_Fill (x, y : Integer; ice : Character) is procedure Go is begin more := more + 1; if x = n - 1 and then y = n then if verbosity >= 1 then Put_Line (+"Yuhu, found the End! Length from Start to End: " & (done_so_far + more)); if verbosity >= 2 then map (x, y) := 'E'; Show (map); end if; end if; -- The answer of the puzzle is the longest path. r (part) := Max (r (part), done_so_far + more); else map (x, y) := 'O'; -- Mark this tile as visited. Flood_Fill (x - 1, y, '<'); Flood_Fill (x + 1, y, '>'); Flood_Fill (x, y - 1, '^'); Flood_Fill (x, y + 1, 'v'); end if; end Go; procedure Copy_Map_and_Go is copy : Map_Type := map; begin copy (x, y) := '.'; -- Open the icy gate... Walk_from (copy, x, y, done_so_far + more); end Copy_Map_and_Go; c : constant Character := map (x, y); begin if c = '.' then Go; elsif c = ice or else (part = part_2 and then (c = '<' or else c = '>' or else c = '^' or else c = 'v')) then Copy_Map_and_Go; -- Silent alternative: treat this tile as a forest, -- continue on the same map and perhaps find another path. end if; end Flood_Fill; begin Flood_Fill (x, y, '$'); end Walk_from; map : Map_Type := data; begin if verbosity >= 2 then Show (map); end if; r (part) := 0; map (2, 1) := 'S'; -- Nice, and prevents going outside... Walk_from (map, 2, 2, 0); end Do_Part; T0 : constant Time := Clock; compiler_test_mode : constant Boolean := Argument_Count >= 2; begin if compiler_test_mode then -- GNAT runs this program on the actual problem -- data in 5 minutes, while HAC takes forever. input_name := +"aoc_2023_23_questions"; skip_header := 16; n := 23; else input_name := +"aoc_2023_23"; skip_header := 0; n := 141; end if; Read_Data; for part in Part_Type loop Do_Part (part); if verbosity >= 1 then Put_Line ("Done for part " & part'Image); end if; end loop; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 2114 (example: 94) -- Part 2: validated by AoC: 6322 (example: 154) end if; end AoC_2023_23; ================================================ FILE: exm/aoc/2023/aoc_2023_23.txt ================================================ #.########################################################################################################################################### #.....#.....#.....###...#.........#.....#...#.......#...###...###...###...#.................#...#...........#.......#...........#...........# #####.#.###.#.###.###.#.#.#######.#.###.#.#.#.#####.#.#.###.#.###.#.###.#.#.###############.#.#.#.#########.#.#####.#.#########.#.#########.# #.....#.#...#...#...#.#.#.....#...#.#...#.#...#.....#.#.#...#...#.#.#...#.#.............#...#.#.#.#.........#.....#.#.#...#...#.#...#.......# #.#####.#.#####.###.#.#.#####.#.###.#.###.#####.#####.#.#.#####.#.#.#.###.#############.#.###.#.#.#.#############.#.#.#.#.#.#.#.###.#.####### #.#...#.#...###.#...#.#.#...#.#.###.#.###.....#.#...#.#.#...#...#.#.#...#.#.......#...#.#.###.#.#.#.#...#####.....#.#.#.#...#...#...#.#...### #.#.#.#.###.###.#.###.#.#.#.#.#.###.#.#######.#.#.#.#.#.###.#.###.#.###.#.#.#####.#.#.#.#.###.#.#.#.#.#.#####.#####.#.#.#########.###.#.#.### #.#.#...#...#...#...#.#.#.#...#.#...#...>.>.#.#.#.#...#.#...#.#...#...#.#.#.....#.#.#...#.#...#.#.#...#.>.>.#.....#...#.....#...#...#...#...# #.#.#####.###.#####.#.#.#.#####.#.#######v#.#.#.#.#####.#.###.#.#####.#.#.#####.#.#.#####.#.###.#.#######v#.#####.#########.#.#.###.#######.# #.#.#.....###.....#...#.#.....#...#####...#.#.#.#.#.....#...#...#.....#.#.#...#.#.#...#...#...#.#...#.....#...#...#...#.....#.#.#...#.......# #.#.#.###########.#####.#####.#########.###.#.#.#.#.#######.#####.#####.#.#.#.#.#.###.#.#####.#.###.#.#######.#.###.#.#.#####.#.#.###.####### #...#.#...###...#.#...#.......#...###...#...#.#.#.#...#.>.>.#.....#.....#.#.#...#.#...#...#...#.....#.....#...#.#...#...#...#.#.#.#...#...### #####.#.#.###.#.#.#.#.#########.#.###.###.###.#.#.###.#.#v###.#####.#####.#.#####.#.#####.#.#############.#.###.#.#######.#.#.#.#.#.###.#.### #.....#.#...#.#...#.#...#.......#...#...#...#.#.#...#.#.#.#...#...#...#...#.....#.#...#...#...#...#...#...#.....#...#...#.#.#.#...#.###.#.### #.#####.###v#.#####.###.#.#########.###.###.#.#.###.#.#.#.#.###.#.###.#.#######.#.###.#.#####.#.#.#.#.#.###########.#.#.#.#.#.#####.###.#.### #.#...#...#.>.#...#.#...#.........#...#.#...#.#.#...#...#.#.#...#...#.#.#.>.>...#...#.#.#...#.#.#...#.#...#.........#.#.#.#...#.....#...#.### #.#.#.###.#v###.#.#.#.###########.###.#.#.###.#.#.#######.#.#.#####.#.#.#.#v#######.#.#.#.#.#.#.#####.###.#.#########.#.#.#####.#####.###.### #.#.#...#.#.....#...#...#.........#...#.#.....#...###.....#...#.....#.#.#.#.......#.#.#.#.#...#.#...#...#.#.###...###.#.#...#...#...#...#...# #.#.###.#.#############.#.#########.###.#############.#########.#####.#.#.#######.#.#.#.#.#####.#.#.###.#.#.###.#.###.#.###.#.###.#.###.###.# #...###...#.......#.....#.........#...#.........#...#.........#.....#.#...#.......#...#...#...#...#...#...#...#.#...#.#.#...#...#.#.#...#...# ###########.#####.#.#############.###.#########.#.#.#########.#####.#.#####.###############.#.#######.#######.#.###.#.#.#.#####.#.#.#.###.### ###...#...#.....#.#...#...........###...#.......#.#.###.......#.....#.....#.................#...#.....#...###...###...#.#.....#.#.#...#...### ###.#.#.#.#####.#.###.#.###############.#.#######.#.###.#######.#########.#####################.#.#####.#.#############.#####.#.#.#####.##### #...#...#.......#.....#...#...#...#####.#.#.......#...#.......#.......#...#.........#...........#.......#.........#...#.....#.#.#.#.....#...# #.#######################.#.#.#.#.#####.#.#.#########.#######.#######.#.###.#######.#.###########################.#.#.#####.#.#.#.#.#####.#.# #.#.....#...#...........#...#.#.#...###...#.........#.........#.......#...#.......#...###.....#...................#.#.....#...#...#.......#.# #.#.###.#.#.#.#########.#####.#.###.###############.###########.#########.#######.#######.###.#.###################.#####.#################.# #...###...#.#.#.........#.....#.#...#.......#.......#.....#####.....#...#.#.......#.....#.#...#...................#.#.....#...#.....#.......# ###########.#.#.#########.#####.#.###.#####.#.#######.###.#########.#.#.#.#.#######.###.#.#.#####################.#.#.#####.#.#.###.#.####### #...........#.#.........#.#.....#.....#.....#.........###.....#...#...#...#.........#...#.#...#...###.........#...#.#.....#.#.#...#.#.......# #.###########.#########.#.#.###########.#####################.#.#.###################.###.###.#.#.###.#######.#.###.#####.#.#.###.#.#######.# #.#...#...#...#.........#...#...........#...#...#.............#.#...###.......#.......###...#.#.#...#.......#...###.#.....#.#.#...#.........# #.#.#.#.#.#.###.#############.###########.#.#.#.#.#############.###.###.#####.#.###########.#.#.###.#######.#######.#.#####.#.#.############# #.#.#...#...###.#.........#...###.....#...#.#.#.#.............#...#...#.....#.#.#...###...#.#.#.#...#...###.......#.#.....#.#.#.............# #.#.###########.#.#######.#.#####.###.#.###.#.#.#############.###.###.#####.#.#.#.#.###.#.#.#.#.#.###.#.#########v#.#####.#.#.#############.# #.#.#...........#.#.......#...#...#...#...#...#.#.............#...#...#...#.#.#.#.#...#.#.#.#.#.#.#...#.#.......>.>.#.....#.#.........#...#.# #.#.#.###########.#v#########v#.###.#####.#####.#.#############.###.###.#.#.#.#.#.###.#.#.#.#.#.#.#.###.#.#######v###.#####.#########.#.#.#.# #.#.#.............#.>.#.....>.>.#...#...#.#.....#.........#...#...#...#.#.#.#.#.#...#.#.#.#.#...#.#.#...#.#.....#.###.#...#.....#.....#.#.#.# #.#.###############v#.#.#####v###.###.#.#.#.#############.#.#.###.###.#.#.#.#.#v###.#.#.#.#.#####.#.#.###.#.###.#.###.#.#.#####.#.#####v#.#.# #...###.......#...#.#.#...#...#...#...#.#.#...#...#.....#.#.#.###...#.#.#.#.#.>.>...#...#.#.#.....#.#...#.#...#...#...#.#.#.....#...#.>.#...# #######.#####.#.#.#.#.###.#.###.###.###.#.###.#.#.#.###.#.#.#.#####.#.#.#.#.###v#########.#.#.#####.###.#.###.#####.###.#.#.#######.#.#v##### #.......#...#...#...#.....#...#...#...#.#.#...#.#.#...#.#.#.#.#...#.#...#...###...#...###.#.#.....#...#...#...###...#...#.#.....###...#.....# #.#######.#.#################.###.###.#.#.#.###.#.###.#.#v#.#.#.#.#.#############.#.#.###.#.#####.###.#####.#####.###.###.#####.###########.# #.........#.............###...###.....#...#...#.#...#.#.>.>.#...#.#...#...#...#...#.#...#.#...#...#...#...#.....#...#...#.....#...#.......#.# #######################.###.#################.#.###.#.###v#######.###.#.#.#.#.#.###.###.#.###.#.###.###.#.#####.###.###.#####.###.#.#####.#.# ###...#...#...........#...#.........#...#.....#...#.#...#.......#...#.#.#...#...#...#...#.#...#.....#...#.#.....#...#...###...#...#.#...#...# ###.#.#.#.#.#########.###.#########.#.#.#.#######.#.###.#######.###.#.#.#########.###.###.#.#########.###.#.#####.###.#####.###.###.#.#.##### #...#...#...#.......#.#...#.......#...#.#.....#...#.....#.....#...#...#.......#...#...###...#.......#...#.#.....#.....#.....#...#...#.#.....# #.###########.#####.#.#.###.#####.#####.#####.#.#########.###.###.###########.#.###.#########.#####.###.#.#####.#######.#####.###.###.#####.# #...........#.#.....#...#...#...#.......#.....#.#.....###...#.....#.....#...#...###...#.....#.....#.###.#.#.....#.....#.......###.....#.....# ###########.#.#.#########.###.#.#########.#####.#.###.#####.#######.###.#.#.#########.#.###.#####.#.###.#.#.#####.###.#################.##### #.........#...#.......###...#.#.....#####.......#.#...#...#...#...#...#.#.#.#.........#.#...#...#.#.###.#.#...###.#...#...###...###.....#...# #.#######.###########.#####.#.#####.#############.#.###.#.###.#.#.###.#.#.#.#.#########.#.###.#.#.#.###.#.###v###.#.###.#.###.#.###.#####.#.# #.......#...#...#.....#...#.#.#...#...#...#...#...#...#.#.#...#.#.###.#.#.#.#...........#.#...#.#.#...#.#.#.>.>.#.#...#.#...#.#.....#...#.#.# #######.###.#.#.#.#####.#.#.#.#.#.###.#.#.#.#.#.#####.#.#.#.###.#.###.#.#.#.#############v#.###.#.###.#.#.#.#v#.#.###.#.###.#.#######.#.#.#.# ###...#...#...#...###...#.#...#.#.....#.#.#.#.#.#.....#.#.#.###.#.#...#.#.#...#...#...#.>.>.###.#...#...#...#.#...###...#...#.......#.#...#.# ###.#.###.###########.###.#####.#######.#.#.#.#.#.#####.#.#v###.#.#.###.#.###.#.#.#.#.#.#v#####.###.#########.###########.#########.#.#####.# #...#.....#.........#...#.#...#.....###.#.#.#.#.#.#...#.#.>.>...#.#...#...###...#...#...#.....#.#...###...###.....#.......#...#...#...#.....# #.#########.#######.###.#.#.#.#####v###.#.#.#.#.#.#.#.#.###v#####.###.#######################.#.#.#####.#.#######.#.#######.#.#.#.#####.##### #...........#.......#...#.#.#.#...>.>.#.#...#.#.#.#.#.#.###.....#...#.....###...#.....#.......#.#.#.....#.#...#...#.#...###.#.#.#.#...#.....# #############.#######.###.#.#.#.###v#.#.#####.#.#.#.#.#.#######.###.#####.###.#.#.###.#.#######.#.#.#####.#.#.#.###.#.#.###.#.#.#.#.#.#####.# #...###.......#...###...#.#.#...#...#.#.....#.#.#.#.#.#.#.......#...#...#...#.#.#...#...#.....#...#.....#.#.#...###...#...#.#.#.#.#.#...#...# #.#.###.#######.#.#####.#.#.#####.###.#####.#.#.#.#.#.#.#.#######.###.#.###.#.#.###.#####.###.#########.#.#.#############.#.#.#.#.#.###.#.### #.#...#.........#.#...#.#...###...#...#...#.#...#...#...#...#...#.#...#...#.#.#...#.......#...#.........#.#.......###...#.#.#.#.#.#.#...#.### #.###.###########v#.#.#.#######.###.###.#.#.###############.#.#.#.#.#####.#.#.###.#########.###.#########.#######.###.#.#.#.#.#.#.#.#.###v### #...#.....###...#.>.#.#...#.....###...#.#...###...#...#####...#.#...#...#...#...#...........###.........#.#...#...#...#...#.#.#.#.#.#.#.>.### ###.#####.###.#.#v###.###.#.#########.#.#######.#.#.#.#########.#####.#.#######.#######################.#.#.#.#.###.#######.#.#.#.#.#.#.#v### ###.....#.....#...#...#...#.........#...#...#...#.#.#...###...#.#...#.#.#...#...#...........#...........#...#...###...#...#.#.#.#.#.#...#...# #######.###########.###.###########.#####.#.#.###.#.###.###.#.#.#.#.#.#.#.#.#.###.#########.#.#######################.#.#.#.#.#.#.#.#######.# ###.....#...#.....#...#.#...........###...#...#...#...#.....#...#.#.#.#.#.#.#.....#.........#...#...#...#.......#...#.#.#...#...#...#.......# ###.#####.#.#.###.###.#.#.#############.#######.#####.###########.#.#.#.#.#.#######.###########.#.#.#.#.#.#####.#.#.#.#.#############.####### #...#.....#...###...#.#.#.....#####...#.....#...#####.........###.#.#.#.#.#...#...#...#...#...#...#...#...#.....#.#.#.#.###.......#...#...### #.###.#############.#.#.#####.#####.#.#####.#.###############.###.#.#.#.#.###.#.#.###.#.#.#.#.#############.#####.#.#.#.###.#####.#.###.#.### #.....#...#.........#...#...#.....#.#.#.....#.#...#...#.......#...#.#.#.#.#...#.#.###.#.#...#...#...#.....#.#.....#.#...#...#.....#.....#...# #######.#.#.#############.#.#####.#.#.#.#####.#.#.#.#.#.#######.###.#.#.#.#.###.#.###v#.#######.#.#.#.###.#.#.#####.#####.###.#############.# #...###.#.#.......#.....#.#.......#.#.#.....#...#.#.#.#.......#...#...#.#.#...#.#.#.>.>.#.......#.#.#...#...#.#.....#...#...#.###...#...#...# #.#.###.#.#######.#.###.#.#########.#.#####.#####.#.#.#######.###.#####.#.###.#.#.#.#v###.#######.#.###.#####.#.#####.#.###.#.###.#.#.#.#.### #.#.#...#...#...#...#...#.#.....#...#.....#...#...#.#.#...#...#...#.....#.###...#...#...#.....#...#...#.....#.#...#...#...#.#...#.#.#.#.#...# #.#.#.#####.#.#.#####.###.#.###.#.#######.###.#.###.#.#.#.#v###.###.#####.#############.#####.#.#####.#####.#.###.#.#####.#.###.#.#.#.#.###.# #.#.#.....#.#.#.......###...#...#.......#...#.#...#.#.#.#.>.>.#...#.....#...#...........#.....#.#.....#.....#.#...#...#...#...#.#.#.#.#.#...# #.#.#####.#.#.###############.#########.###.#.###.#.#.#.###v#.###.#####.###.#.###########.#####.#.#####.#####.#.#####.#.#####.#.#.#.#.#.#v### #.#.....#.#...#...#...###.....###...#...#...#.###.#.#...###.#.#...###...#...#.....#.....#.#...#.#.#...#.#...#.#.#...#.#.#...#.#.#.#...#.>.### #.#####.#.#####.#v#.#.###.#######.#.#.###.###.###.#.#######.#.#.#####.###.#######.#.###.#.#.#.#.#.#.#.#v#.#.#.#.#.#.#.#.#.#.#.#.#.#######v### #.....#.#.#.....#.>.#...#.#.....#.#...###...#.#...#...#.....#...#...#...#.###...#...#...#...#.#.#.#.#.>.>.#.#.#.#.#.#.#.#.#.#.#.#.#.......### #####.#.#.#.#####v#####.#.#.###.#.#########.#.#.#####.#.#########.#.###.#.###.#.#####.#######.#.#.#.###v###.#.#.#.#.#.#.#.#.#.#.#.#.######### #.....#.#.#.#.....#.....#...#...#.......#...#.#...#...#...........#.#...#.#...#.......#.....#...#...#...###.#.#.#.#...#.#.#...#.#.#.........# #.#####.#.#.#.#####.#########.#########.#.###.###.#.###############.#.###.#.###########.###.#########.#####.#.#.#.#####.#.#####.#.#########.# #.....#.#...#...#...#...#...#.#...#...#.#...#...#.#.#.............#.#.#...#...#.........#...#.........#...#...#.#.#.....#...#...#.#####...#.# #####.#.#######.#.###.#.#.#.#v#.#.#.#.#.###.###.#.#.#.###########.#.#.#.#####.#.#########.###.#########.#.#####.#.#.#######.#.###.#####.#.#.# #.....#...#####.#...#.#.#.#.>.>.#.#.#.#...#.#...#...#...........#...#.#.#.....#...#.......###...........#.....#.#.#...#...#.#.#...#.....#...# #.#######.#####.###.#.#.#.###v###.#.#.###.#.#.#################.#####.#.#.#######.#.#########################.#.#.###.#.#.#.#.#.###.######### #.......#...#...###.#.#.#.###...#...#...#.#.#...#.....#.........#...#...#.........#.......###.....#...........#...#...#.#...#...###.....#...# #######.###.#.#####.#.#.#.#####.#######.#.#.###.#.###.#.#########.#.#####################.###.###.#.###############.###.###############.#.#.# ###...#...#.#.#.....#.#...#.....#.....#...#...#.#...#.#.....#...#.#.#...#...#...#...#...#...#...#.#...............#...#.#.......#...###...#.# ###.#.###.#.#.#.#####.#####.#####.###.#######.#.###.#.#####.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.###.#.###############.###.#.#.#####.#.#.#######.# #...#.....#...#...#...#...#.......#...#.....#...###.#.......#.#.#.#.#.#...#.#.#.#.#...#.....#...#...........#.....###...#.....#...#.........# #.###############.#.###.#.#########.###.###.#######.#########.#.#.#.#.#####.#.#.#.###########.#############.#.###############.############### #...............#...#...#...........###.#...###...#...#...#...#...#.#.#.....#.#.#.........###.............#...#...#...###...#.....#.........# ###############.#####.#################.#.#####.#.###.#.#.#.#######.#.#.#####.#.#########.###############.#####.#.#.#.###.#.#####.#.#######.# #...............#...#.............#...#.#.#...#.#.###...#.#.#.......#.#.#...#.#...........#...............###...#...#...#.#.......#.###...#.# #.###############.#.#############.#.#.#.#.#.#.#.#.#######.#.#.#######.#.#.#.#.#############.#################.#########.#.#########.###.#.#.# #.#.....#.........#.....#.....#...#.#.#.#...#.#.#.#.....#...#.#...###.#.#.#.#.............#.........#...#...#...#.......#...........#...#...# #.#.###v#.#############.#.###.#.###.#.#.#####.#.#.#.###.#####.#.#.###.#.#.#.#############.#########.#.#.#.#.###.#.###################.####### #...###.>.#...#...#...#.#...#.#.....#.#.....#.#.#.#...#.#.....#.#.###.#.#.#.#...#...#.....#...#...#.#.#.#.#.#...#.#...###...#...#...#.......# #######v###.#.#.#.#.#.#.###.#.#######.#####.#.#.#.###.#.#.#####.#.###.#.#.#.#.#.#.#.#v#####.#.#.#.#.#.#.#.#.#.###.#.#.###.#.#.#.#.#.#######.# ###...#.#...#.#.#.#.#...#...#...#.....#...#.#.#.#.###.#.#.#...#.#.#...#.#.#.#.#.#.#.>.>.###.#.#.#.#.#.#.#.#.#...#.#.#.###.#.#.#.#.#.#.....#.# ###.#.#.#.###.#.#.#.#####.#####.#.#####.#.#.#.#.#.###.#.#v#.#.#.#.#.###.#.#.#.#.#.###v#.###.#.#.#.#v#.#.#.#.###.#.#.#.###.#.#.#.#.#.#.###.#.# #...#...#.###...#...#...#.....#...#...#.#.#.#.#.#.#...#.>.>.#.#.#.#...#.#.#.#.#...#...#...#.#.#.#.>.>.#.#.#...#.#.#.#...#.#...#.#.#.#...#.#.# #.#######.###########.#.#####.#####.#.#.#.#.#.#.#.#.#####v###.#.#.###.#.#.#.#.#####.#####.#.#.#.###v###.#.###.#.#.#.###.#.#####.#.#.###.#.#.# #.......#...###...#...#.#...#.....#.#...#.#.#.#.#.#...#...###...#.....#...#.#.#.....#...#.#.#.#.#...###.#.#...#.#.#...#.#.#.....#.#.###.#.#.# #######.###.###.#.#.###.#.#.#####.#.#####.#.#.#.#.###.#.###################.#.#.#####.#.#.#.#.#.#.#####.#.#.###.#.###.#.#.#.#####.#.###v#.#.# ###.....###...#.#.#...#.#.#.#...#.#...###...#...#.#...#.#.....#...#...#...#...#.......#.#.#.#.#.#.#...#...#.....#.#...#.#.#.#.....#.#.>.#...# ###.#########.#.#.###.#.#.#.#.#.#v###.###########.#.###.#.###.#.#.#.#.#.#.#############.#.#.#.#.#.#.#.###########.#.###.#.#.#.#####.#.#v##### #...#...#...#...#.#...#.#.#...#.>.>.#.......###...#...#...#...#.#...#.#.#.#...........#.#...#...#...#.........#...#...#.#.#.#.....#.#.#.#...# #.###.#.#.#.#####.#.###.#.#######v#.#######.###.#####.#####.###.#####.#.#.#.#########.#.#####################.#.#####.#.#.#.#####.#.#.#.#.#.# #.#...#...#.....#.#...#.#.###...#.#.#.....#...#...#...#.....#...#.....#.#.#.........#.#.........#.....#.....#.#.#.....#.#.#.#.....#...#...#.# #.#.###########.#.###.#.#.###.#.#.#.#.###.###.###.#.###.#####.###.#####.#.#########.#.#########.#.###.#.###.#.#.#.#####.#.#.#.#############.# #...#...#.......#.#...#...#...#...#...###...#...#.#.###...#...###.......#.#.........#.#.....#...#...#.#...#.#.#.#.....#...#...###...#...#...# #####.#.#.#######.#.#######.###############.###.#.#.#####.#.#############.#.#########.#.###.#.#####.#.###.#.#.#.#####.###########.#.#.#.#.### #.....#...#.....#.#.#...###...............#.#...#.#.....#...#.......#.....#.........#...###...#.....#...#.#.#.#...#...#...#.......#.#.#...### #.#########.###.#.#.#.#.#################.#.#.###.#####.#####.#####.#.#############.###########.#######.#.#.#.###.#.###.#.#.#######.#.####### #...........#...#...#.#.#.......#.......#.#.#...#.#...#.#.....#...#...###...........#...###...#...#...#...#...###...###.#.#.......#.#.......# #############.#######.#.#.#####.#.#####.#.#.###.#.#.#.#.#.#####.#.#######.###########.#.###.#.###.#.#.#################.#.#######.#.#######.# ###...#...#...###.....#.#.....#.#.....#.#.#.....#...#...#.......#.......#.............#...#.#...#...#.#.........#.....#.#.#...#...#.#.......# ###.#.#.#.#.#####.#####.#####.#.#####.#.#.#############################.#################.#.###.#####.#.#######.#.###.#.#.#.#.#.###.#.####### #...#...#.#.....#...#...#.....#...#...#.#.#.......#.......#.............#.....#...........#.#...#...#...#.......#...#...#...#...#...#.###...# #.#######.#####.###.#.###.#######.#.###.#.#.#####.#.#####.#.#############.###.#.###########.#.###.#.#####.#########.#############.###.###.#.# #.......#.......#...#...#.#.....#...###...#...#...#.....#.#...........###.#...#...###.....#.#...#.#...#...#.......#.....#.......#...#.....#.# #######.#########.#####.#.#.###.#############.#.#######.#.###########.###.#.#####v###.###.#.###.#.###.#.###.#####.#####.#.#####.###.#######.# #.......#...#...#...#...#...#...#...###.......#.###...#.#...#.........#...#...#.>.>.#...#.#.#...#...#.#...#.#.....#...#...#.....###.....#...# #.#######.#.#.#.###.#.#######v###.#.###.#######.###.#.#.###.#.#########.#####.#.###.###.#.#.#.#####.#.###v#.#.#####.#.#####.###########.#.### #...#...#.#.#.#...#.#...#...>.>.#.#...#.......#...#.#.#.#...#.........#.#####.#.#...#...#.#.#...#...#.#.>.>.#.#...#.#.#...#...#.......#...### ###.#.#.#.#.#.###.#.###.#.#####.#.###.#######.###.#.#.#.#.###########.#.#####.#.#.###.###.#.###.#.###.#.#####.#.#.#.#.#.#.###v#.#####.####### ###...#...#.#.#...#...#.#.#...#.#...#...#...#...#.#.#.#.#...#...#...#.#.....#.#.#.#...###.#.#...#.###.#.....#.#.#.#.#.#.#.#.>.#...#...###...# ###########.#.#.#####.#.#.#.#.#.###.###.#.#.###.#.#.#.#.###.#.#.#.#.#.#####.#.#.#.#.#####.#.#.###.###.#####.#.#.#.#.#.#.#.#.#v###.#.#####.#.# #.......###.#.#.#...#.#.#.#.#...#...#...#.#...#.#.#.#.#...#.#.#.#.#...#.....#...#.#.###...#.#...#...#...#...#.#.#.#.#.#.#.#.#...#.#.#...#.#.# #.#####.###.#.#.#.#.#.#.#.#.#####.###.###.###.#.#.#.#.###.#.#.#.#v#####.#########.#.###.###.###.###.###.#.###.#.#.#.#.#.#.#.###.#.#.#.#.#.#.# #.....#.....#.#.#.#.#.#.#.#.#...#...#.#...#...#.#.#.#.#...#.#.#.>.>...#.........#.#...#.#...###...#...#.#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.#.# #####.#######.#.#.#.#.#.#.#.#.#.###.#.#.###.###.#.#.#.#.###.#.#######.#########.#.###.#.#.#######.###.#.#.#.###.#.#.#.#.#.#.#.###.#.#.#.#.#.# #####.........#...#...#...#...#.....#...###.....#...#...###...#######...........#.....#...#######.....#...#.....#...#...#...#.....#...#...#.# ###########################################################################################################################################.# ================================================ FILE: exm/aoc/2023/aoc_2023_23_questions.txt ================================================ --- Day 23: A Long Walk --- The Elves resume water filtering operations! Clean water starts flowing over the edge of Island Island. They offer to help you go over the edge of Island Island, too! Just hold on tight to one end of this impossibly long rope and they'll lower you down a safe distance from the massive waterfall you just created. As you finally reach Snow Island, you see that the water isn't really reaching the ground: it's being absorbed by the air itself. It looks like you'll finally have a little downtime while the moisture builds up to snow-producing levels. Snow Island is pretty scenic, even without any snow; why not take a walk? There's a map of nearby hiking trails (your puzzle input) that indicates paths (.), forest (#), and steep slopes (^, >, v, and <). For example: #.##################### #.......#########...### #######.#########.#.### ###.....#.>.>.###.#.### ###v#####.#v#.###.#.### ###.>...#.#.#.....#...# ###v###.#.#.#########.# ###...#.#.#.......#...# #####.#.#.#######.#.### #.....#.#.#.......#...# #.#####.#.#.#########v# #.#...#...#...###...>.# #.#.#v#######v###.###v# #...#.>.#...>.>.#.###.# #####v#.#.###v#.#.###.# #.....#...#...#.#.#...# #.#########.###.#.#.### #...###...#...#...#.### ###.###.#.###v#####v### #...#...#.#.>.>.#.>.### #.###.###.#.###.#.#v### #.....###...###...#...# #####################.# You're currently on the single path tile in the top row; your goal is to reach the single path tile in the bottom row. Because of all the mist from the waterfall, the slopes are probably quite icy; if you step onto a slope tile, your next step must be downhill (in the direction the arrow is pointing). To make sure you have the most scenic hike possible, never step onto the same tile twice. What is the longest hike you can take? In the example above, the longest hike you can take is marked with O, and your starting position is marked S: #S##################### #OOOOOOO#########...### #######O#########.#.### ###OOOOO#OOO>.###.#.### ###O#####O#O#.###.#.### ###OOOOO#O#O#.....#...# ###v###O#O#O#########.# ###...#O#O#OOOOOOO#...# #####.#O#O#######O#.### #.....#O#O#OOOOOOO#...# #.#####O#O#O#########v# #.#...#OOO#OOO###OOOOO# #.#.#v#######O###O###O# #...#.>.#...>OOO#O###O# #####v#.#.###v#O#O###O# #.....#...#...#O#O#OOO# #.#########.###O#O#O### #...###...#...#OOO#O### ###.###.#.###v#####O### #...#...#.#.>.>.#.>O### #.###.###.#.###.#.#O### #.....###...###...#OOO# #####################O# This hike contains 94 steps. (The other possible hikes you could have taken were 90, 86, 82, 82, and 74 steps long.) Find the longest hike you can take through the hiking trails listed on your map. How many steps long is the longest hike? --- Part Two --- As you reach the trailhead, you realize that the ground isn't as slippery as you expected; you'll have no problem climbing up the steep slopes. Now, treat all slopes as if they were normal paths (.). You still want to make sure you have the most scenic hike possible, so continue to ensure that you never step onto the same tile twice. What is the longest hike you can take? In the example above, this increases the longest hike to 154 steps: #S##################### #OOOOOOO#########OOO### #######O#########O#O### ###OOOOO#.>OOO###O#O### ###O#####.#O#O###O#O### ###O>...#.#O#OOOOO#OOO# ###O###.#.#O#########O# ###OOO#.#.#OOOOOOO#OOO# #####O#.#.#######O#O### #OOOOO#.#.#OOOOOOO#OOO# #O#####.#.#O#########O# #O#OOO#...#OOO###...>O# #O#O#O#######O###.###O# #OOO#O>.#...>O>.#.###O# #####O#.#.###O#.#.###O# #OOOOO#...#OOO#.#.#OOO# #O#########O###.#.#O### #OOO###OOO#OOO#...#O### ###O###O#O###O#####O### #OOO#OOO#O#OOO>.#.>O### #O###O###O#O###.#.#O### #OOOOO###OOO###...#OOO# #####################O# Find the longest hike you can take through the surprisingly dry hiking trails listed on your map. How many steps long is the longest hike? ================================================ FILE: exm/aoc/2023/aoc_2023_24.adb ================================================ -- Solution to Advent of Code 2023, Day 24 ------------------------------------------- -- Never Tell Me The Odds -- -- https://adventofcode.com/2023/day/24 -- Copy of questions in: aoc_2023_24_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_24 is use AoC_Toolbox, HAT, Interfaces; capacity : constant := 1500; type Hail_Stone is record pos, vel : Point_3D_R; end record; type Hail_Stone_Array is array (1 .. capacity) of Hail_Stone; type List_Type is record stone : Hail_Stone_Array; last : Natural; end record; -- input_name : VString := +"mini_24"; skip_header : Natural := 0; -- min_box : Real := 7.0; max_box : Real := 27.0; -- input_name : constant VString := +"aoc_2023_24"; min_box : constant Real := 200000000000000.0; max_box : constant Real := 400000000000000.0; procedure Read_Data (list : out List_Type) is dummy : Character; f : File_Type; pos, vel : Point_3D_R; begin list.last := 0; Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get (f, pos.x); Get (f, dummy); Get (f, pos.y); Get (f, dummy); Get (f, pos.z); Get (f, dummy); Get (f, dummy); Get (f, vel.x); Get (f, dummy); Get (f, vel.y); Get (f, dummy); Get (f, vel.z); -- list.last := list.last + 1; list.stone (list.last).pos := pos; list.stone (list.last).vel := vel; end loop; Close (f); end Read_Data; data : List_Type; verbose : constant Boolean := False; research_mode : constant Boolean := False; procedure Intersect_Positive_Time (ia, ib : Integer; inter_x, inter_y : out Real; hit : out Boolean) is ax, ay, bx, by, ux, uy, vx, vy, alpha, beta, den : Real; show_intersection_times : constant Boolean := False; eps : constant := 0.0000001; begin -- We look for times alpha, beta such that -- -- a + alpha * u = b + beta * v -- -- The times alpha and beta don't need to be equal: -- "The hailstones themselves don't have to collide, -- just test for intersections between the paths they will trace." -- hit := False; ax := data.stone (ia).pos.x; ay := data.stone (ia).pos.y; bx := data.stone (ib).pos.x; by := data.stone (ib).pos.y; ux := data.stone (ia).vel.x; uy := data.stone (ia).vel.y; vx := data.stone (ib).vel.x; vy := data.stone (ib).vel.y; -- if abs ux < eps then if abs vx < eps then hit := abs (ax - bx) < eps and then abs (ay - by) < eps; beta := 0.0; else hit := True; beta := (ax - bx) / vx; end if; elsif abs uy < eps then if abs vy < eps then hit := abs (ax - bx) < eps and then abs (ay - by) < eps; beta := 0.0; else hit := True; beta := (ay - by) / vy; end if; else -- Both ux and uy are not 0 den := (vx * uy - vy * ux); if abs den > eps then hit := True; beta := (ax * uy - ay * ux - bx * uy + by * ux) / den; end if; end if; if hit then hit := beta > 0.0; end if; if hit then -- Only positive time is considered: alpha and beta must be > 0. if abs ux > eps then alpha := (bx + vx * beta - ax) / ux; hit := alpha > 0.0; end if; end if; if hit then inter_x := bx + beta * vx; inter_y := by + beta * vy; hit := inter_x >= min_box and then inter_x <= max_box and then inter_y >= min_box and then inter_y <= max_box; end if; if hit then if verbose then Put_Line (+"Intersection within test area: " & ia & " with " & ib & " at point " & inter_x & ", " & inter_y & " beta = " & beta); end if; if research_mode and show_intersection_times then Put_Line (+"" & ia & ';' & ib & ';' & alpha & ';' & beta); end if; end if; end Intersect_Positive_Time; r : array (Part_Type) of Integer_64; procedure Do_Part_1 is inter_x, inter_y : Real; hit : Boolean; show_intersection_times : constant Boolean := False; begin if research_mode and show_intersection_times then Put_Line (+"index a;index b;time alpha;time beta"); end if; r (part_1) := 0; for ib in 1 .. data.last loop -- Hail stone at b, velocity u. for ia in 1 .. ib - 1 loop -- Hail stone at a, velocity v. Intersect_Positive_Time (ia, ib, inter_x, inter_y, hit); if hit then r (part_1) := r (part_1) + 1; end if; end loop; end loop; if research_mode and show_intersection_times then New_Line; end if; end Do_Part_1; procedure Research_Part_2 is dist_triplet : Real; x_common, y_common, z_common : Natural; low_velocities : constant Boolean := False; sel_1 : constant := 284; sel_2 : constant := 42; sel_3 : constant := 24; begin if low_velocities then Put_Line (+"index i;index j;index k;sum of L1 of velocities"); -- We list point triplets with mutual velocities that are -- close to each other. for i in 1 .. data.last loop for j in 1 .. i - 1 loop for k in 1 .. j - 1 loop dist_triplet := Dist_L1_3D_R (data.stone (i).vel, data.stone (j).vel) + Dist_L1_3D_R (data.stone (j).vel, data.stone (k).vel) + Dist_L1_3D_R (data.stone (k).vel, data.stone (i).vel); if dist_triplet < 75.0 then Put_Line (+"" & i & ';' & j & ';' & k & ';' & dist_triplet); end if; end loop; end loop; end loop; -- New_Line; Put_Line (+"" & sel_1 & ';' & data.stone (sel_1).vel.x & ';' & data.stone (sel_1).vel.y & ';' & data.stone (sel_1).vel.z); Put_Line (+"" & sel_2 & ';' & data.stone (sel_2).vel.x & ';' & data.stone (sel_2).vel.y & ';' & data.stone (sel_2).vel.z); Put_Line (+"" & sel_3 & ';' & data.stone (sel_3).vel.x & ';' & data.stone (sel_3).vel.y & ';' & data.stone (sel_3).vel.z); end if; New_Line; Put_Line ("Same velocity component as some other"); for ia in 1 .. data.last loop x_common := 0; y_common := 0; z_common := 0; for ib in 1 .. data.last loop if ia /= ib then if data.stone (ia).vel.x = data.stone (ib).vel.x then x_common := x_common + 1; end if; if data.stone (ia).vel.y = data.stone (ib).vel.y then y_common := y_common + 1; end if; if data.stone (ia).vel.z = data.stone (ib).vel.z then z_common := z_common + 1; end if; end if; end loop; if x_common > 0 or y_common > 0 or z_common > 0 then Put_Line (+"" & ia & ';' & x_common & ';' & y_common & ';' & z_common & ';'); end if; end loop; end Research_Part_2; -- procedure Do_Part_2 is -- xb, yb, zb, v, w : Integer; -- ur, vr, wr, xb_r, inverse_tb : Real; -- eps : constant := 0.005; -- begin -- for ia in 1 .. data.last loop -- for ib in ia + 1 .. data.last loop -- if data.stone (ia).vel.x = data.stone (ib).vel.x then -- if verbose then -- Put_Line (+"" & ia & ", " & ib); -- end if; -- xb := data.stone (ib).pos.x - data.stone (ia).pos.x; -- if xb = 0 then -- Put ("!!"); -- else -- yb := data.stone (ib).pos.y - data.stone (ia).pos.y; -- zb := data.stone (ib).pos.z - data.stone (ia).pos.z; -- for u in -1000 .. 1000 loop -- if u /= 0 then -- ur := Real (u); -- Test relative velocity u on x axis -- xb_r := Real (xb); -- inverse_tb := ur / xb_r; -- vr := Real (yb) * inverse_tb; -- wr := Real (zb) * inverse_tb; -- if abs (vr - Real (Trunc (vr))) < eps -- and then abs (wr - Real (Trunc (wr))) < eps then -- -- vr and wr are actually integers. -- Put_Line -- (+"Ah ha! " & ia & ", " & ib & -- ", u = " & ur & -- ", v = " & vr & -- ", w = " & wr); -- v := Integer (vr); -- w := Integer (wr); -- -- Absolute values -- end if; -- end if; -- end loop; -- end if; -- end if; -- end loop; -- end loop; -- end Do_Part_2; -- The following is an adaptation to the HAC Ada subset of the 2nd solution -- to 2nd part by John Perry: -- -- https://github.com/johnperry-math/AoC2023/tree/master/day24 procedure Do_Part_2_By_GB is First, Second, Third : Hail_Stone; -- three non-parallel stones Found : Boolean := False; -- whether we've found the stones yet type Reduction_Matrix is array (1 .. 6, 1 .. 7) of Real; Matrix : Reduction_Matrix; Pivoter : Real; X, Y, Z : Real; -- the solution inter_x, inter_y : Real; valid : Boolean; eps : constant := 0.0000001; begin -- find 3 intersecting stones Outer_Loop : for Ith in data.stone'First .. data.last - 2 loop for Jth in Ith + 1 .. data.last - 1 loop Intersect_Positive_Time (Ith, Jth, inter_x, inter_y, valid); if valid then First := data.stone (Ith); Second := data.stone (Jth); for Kth in Jth + 1 .. data.last loop Intersect_Positive_Time (Ith, Jth, inter_x, inter_y, valid); if valid then Third := data.stone (Kth); Found := True; exit Outer_Loop; end if; end loop; end if; end loop; end loop Outer_Loop; if not Found then Put_Line ("Mayday! Did not find three stones" & " with mutual intersection in the future!"); end if; -- matrix columns set up as -- | dx | dy | dz | x | y | z | -- we want only x, y, z, so this makes for a little less work -- -- matrix coefficients determined by some Groebner basis-like methods: -- -- * we want to know x, y, z, dx, dy, dz -- * we know First, Second, Third -- * the problem implies the following equations: -- x + dx * t1 = First.pos.x + First.vel.x * t1 -- ...and so forth for y, z, dy, dz, t2, t3, Second, Third -- * rewrite the equations to eliminate the quadratic terms -- and you get equations with the coefficients below Matrix (1, 1) := First.pos.y - Second.pos.y; Matrix (1, 2) := Second.pos.x - First.pos.x; Matrix (1, 3) := 0.0; Matrix (1, 4) := Second.vel.y - First.vel.y; Matrix (1, 5) := First.vel.x - Second.vel.x; Matrix (1, 6) := 0.0; Matrix (1, 7) := -(First.pos.x * First.vel.y - First.pos.y * First.vel.x - Second.pos.x * Second.vel.y + Second.pos.y * Second.vel.x); Matrix (2, 1) := First.pos.z - Second.pos.z; Matrix (2, 2) := 0.0; Matrix (2, 3) := Matrix (1, 2); Matrix (2, 4) := Second.vel.z - First.vel.z; Matrix (2, 5) := 0.0; Matrix (2, 6) := Matrix (1, 5); Matrix (2, 7) := -(First.pos.x * First.vel.z - First.pos.z * First.vel.x - Second.pos.x * Second.vel.z + Second.pos.z * Second.vel.x); Matrix (3, 1) := 0.0; Matrix (3, 2) := Matrix (2, 1); Matrix (3, 3) := Second.pos.y - First.pos.y; Matrix (3, 4) := 0.0; Matrix (3, 5) := Matrix (2, 4); Matrix (3, 6) := First.vel.y - Second.vel.y; Matrix (3, 7) := -(First.pos.y * First.vel.z - First.pos.z * First.vel.y - Second.pos.y * Second.vel.z + Second.pos.z * Second.vel.y); Matrix (4, 1) := First.pos.y - Third.pos.y; Matrix (4, 2) := Third.pos.x - First.pos.x; Matrix (4, 3) := 0.0; Matrix (4, 4) := Third.vel.y - First.vel.y; Matrix (4, 5) := First.vel.x - Third.vel.x; Matrix (4, 6) := 0.0; Matrix (4, 7) := -(First.pos.x * First.vel.y - First.pos.y * First.vel.x - Third.pos.x * Third.vel.y + Third.pos.y * Third.vel.x); Matrix (5, 1) := First.pos.z - Third.pos.z; Matrix (5, 2) := 0.0; Matrix (5, 3) := Matrix (4, 2); Matrix (5, 4) := Third.vel.z - First.vel.z; Matrix (5, 5) := 0.0; Matrix (5, 6) := Matrix (4, 5); Matrix (5, 7) := -(First.pos.x * First.vel.z - First.pos.z * First.vel.x - Third.pos.x * Third.vel.z + Third.pos.z * Third.vel.x); Matrix (6, 1) := 0.0; Matrix (6, 2) := Matrix (5, 1); Matrix (6, 3) := Third.pos.y - First.pos.y; Matrix (6, 4) := 0.0; Matrix (6, 5) := Matrix (5, 4); Matrix (6, 6) := First.vel.y - Third.vel.y; Matrix (6, 7) := -(First.pos.y * First.vel.z - First.pos.z * First.vel.y - Third.pos.y * Third.vel.z + Third.pos.z * Third.vel.y); -- make upper-triangular -- the following approach is quite naive and not very good in general for Pivot in 1 .. 5 loop if abs Matrix (Pivot, Pivot) < eps then for Col in Pivot .. 7 loop Pivoter := Matrix (Pivot, Col); Matrix (Pivot, Col) := Matrix (Pivot + 1, Col); Matrix (Pivot + 1, Col) := Pivoter; end loop; end if; for Row in Pivot + 1 .. 6 loop Pivoter := Matrix (Row, Pivot); for Col in Pivot .. 7 loop Matrix (Row, Col) := Matrix (Row, Col) - Pivoter / Matrix (Pivot, Pivot) * Matrix (Pivot, Col); end loop; end loop; end loop; -- now clear last two non-pivot columns in last 3 rows for Row in 4 .. 5 loop Pivoter := Matrix (Row, 6); for Col in 6 .. 7 loop Matrix (Row, Col) := Matrix (Row, Col) - Pivoter / Matrix (6, 6) * Matrix (6, Col); end loop; end loop; Pivoter := Matrix (4, 5); for Col in 5 .. 7 loop Matrix (4, Col) := Matrix (4, Col) - Pivoter / Matrix (5, 5) * Matrix (5, Col); end loop; -- we now have a matrix whose last 3 rows have the form -- 0 0 0 a 0 0 b -- 0 0 0 0 c 0 d -- 0 0 0 0 0 e f -- this is easy to solve X := Matrix (4, 7) / Matrix (4, 4); Y := Matrix (5, 7) / Matrix (5, 5); Z := Matrix (6, 7) / Matrix (6, 6); if verbose then Put_Line (+"X = " & X & ", Y = " & Y & " Z = " & Z); end if; r (part_2) := Integer_64 (X + Y + Z); end Do_Part_2_By_GB; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin Read_Data (data); Do_Part_1; if research_mode then Research_Part_2; end if; Do_Part_2_By_GB; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)'Image); Put_Line (+"Part 2: " & r (part_2)'Image); -- Part 1: validated by AoC: 24192 -- Part 2: validated by AoC: 664822352550558 end if; end AoC_2023_24; ================================================ FILE: exm/aoc/2023/aoc_2023_24.txt ================================================ 212542581053874, 357959731032403, 176793474286781 @ -88, -256, -240 154677220587564, 207254130208265, 139183938188421 @ 184, 74, 235 216869547613134, 38208083662943, 397740686492049 @ 109, 262, -66 221241619250961, 303902532813154, 249144641113790 @ 48, 24, -112 432610900189894, 347346225570463, 389169322099761 @ -166, -99, -81 247078054674939, 279574769079583, 357168683293046 @ 68, -13, -42 282963504691878, 53019767043895, 238787901458543 @ -17, 399, 62 337163551253985, 323723171285276, 476752372944125 @ -8, -74, -103 253985064168104, 111063839515573, 450754418443501 @ -10, 456, -513 258074760233454, 457117599855759, 244857473415713 @ 49, -247, 92 314400910480251, 261232162431814, 339725786848352 @ -14, 8, -14 246590774392044, 268326724153423, 252283137292781 @ -76, 195, -225 283441229604303, 368965998122557, 461958957382550 @ -8, -135, -282 175273393192850, 325589084134993, 358406853832354 @ 167, -63, -156 208105215242940, 346463859222197, 284004541154973 @ 25, -119, -783 336054085870446, 539099420004527, 243053582150753 @ -125, -451, 41 192157026866775, 221346796869463, 239193597650948 @ 138, 27, 138 276769382377332, 404564336355307, 139075528478897 @ -118, -279, 221 244171538000181, 413561793671125, 231547901494709 @ 6, -271, -7 247208942851962, 296793553833683, 207661499518285 @ -14, 32, 36 234192138385646, 334863379919503, 180826848665889 @ -28, -63, 52 130437043915331, 177551493108966, 166468122354373 @ 338, 448, 129 253559901772970, 311389465584945, 216687040440642 @ -9, -19, 42 254322299286702, 321942519715615, 221793429844513 @ -17, -42, 21 317611519474313, 509405643844478, 492629597734339 @ -24, -308, -221 312434433255435, 526132170689517, 256217852328836 @ -50, -379, 50 192520813054515, 351604734054654, 148333436370478 @ 130, -152, 132 225639342892974, 304654108851055, 198053006284713 @ 19, 39, 12 264606145094124, 239752767682501, 207210412874243 @ 29, 61, 131 73119136879824, 45456753334198, 74136546109856 @ 253, 194, 300 231632956914705, 457605979777570, 302698719514094 @ 26, -414, -234 229858006692918, 295381637696215, 265115021539193 @ -34, 118, -354 461793485716737, 253291754164921, 311510874631043 @ -158, 5, 47 325336710582066, 310550712766927, 330361932845723 @ 5, -61, 46 272391892781881, 310661548818291, 260226744483606 @ -34, -25, -30 191540619797068, 314621834402429, 114137462106199 @ 138, -22, 288 191146615936494, 272599606676084, 172343941415066 @ 139, 136, 110 267901500435402, 344752144584613, 304856136274139 @ -39, -98, -158 190703217190290, 247560977233459, 149406776287313 @ 142, 550, 121 201153500629286, 339132186878755, 150323637135481 @ 35, -57, 45 179357508767544, 21932393507743, 145226556713621 @ 154, 315, 227 307987323598344, 301312391795996, 300888123246103 @ -11, -40, 27 181344541654818, 250938115658739, 239246377640253 @ 196, 440, -384 324550882422222, 211574061061843, 237485412093545 @ -29, 72, 111 98537457698304, 238200330125587, 135289135303526 @ 249, 31, 240 313205485078410, 121081864504891, 172268217697865 @ -104, 348, 163 284584577159870, 144278803049487, 200681374736457 @ -57, 323, 99 226456734486356, 282983479210501, 218425710839487 @ -108, 324, -366 548706725108910, 277311257109343, 307850918038817 @ -217, -28, 69 275949926976102, 282022314903463, 311454924607825 @ -113, 87, -291 213263551904504, 318546624732143, 175742955114241 @ 36, 19, 37 216681369963291, 296454359998620, 462583452318421 @ 82, 10, -495 219979404537774, 211918469842543, 232459433192801 @ 77, 188, 27 325980549629430, 547508205102316, 314702156232182 @ -13, -324, 38 284385758172543, 352024785807952, 218382195747631 @ -128, -120, -5 190048554539654, 289779355315179, 173904022587641 @ 149, 388, -145 246873768466142, 272467557005199, 232828642561081 @ -39, 131, -80 163218080831461, 148606013314170, 142402007207516 @ 176, 164, 230 343986154477558, 348372021296886, 250152291857989 @ -205, -106, -23 197767130311944, 180525916592167, 161798814812969 @ 114, 519, 129 198370970228262, 298346938466104, 174124739099332 @ 115, 54, 102 380807631586707, 369450765586399, 481309114237823 @ -200, -141, -381 187175525195694, 309586416720283, 109735015379081 @ 171, 173, 417 281478516067897, 366561714660494, 230365710762598 @ -204, -184, -132 208535431591002, 325419351576169, 191516365446671 @ 57, -12, -40 226624736718348, 308650992940298, 199188859982218 @ -23, 62, -66 236728026197754, 172425510194479, 206288955041960 @ 79, 131, 146 405157823215560, 285719256118206, 491621031364803 @ -83, -34, -129 204644528670384, 339896525956405, 151222667113763 @ -56, -54, -46 185135616546414, 293907013443535, 166394249527601 @ 179, 231, 10 238567782335982, 328412098910479, 192473102467361 @ -85, -26, -45 337502877434493, 307749379575088, 369033005648444 @ -8, -58, 6 241635494672614, 304729449451093, 326150295954981 @ 51, -27, -95 243264345725652, 264419513819446, 345867847848017 @ 73, 6, -27 262661477328582, 274242124962679, 187580319707945 @ -42, 80, 102 208059705739518, 217157359130755, 219168637501631 @ 115, 85, 120 242872575971229, 425458083316108, 227500835165921 @ 36, -258, 53 448263894001344, 301783842143683, 426560436553661 @ -176, -43, -117 322545182274254, 452642407811057, 305182728508413 @ -21, -227, 33 75201284514819, 160785119325533, 104951102720081 @ 352, 241, 293 185323568951310, 233171350573267, 165775283064269 @ 163, 358, 102 242854931589532, 319092328660893, 243043088450517 @ 18, -38, -17 216818686888044, 223426989024383, 346281309297331 @ 58, 283, -434 248624452315030, 297434951348619, 284011728475200 @ 83, -49, 96 308774084417184, 254923461188383, 324690057597731 @ -22, 27, -20 477086131906062, 293633862617983, 289717304778929 @ -153, -43, 83 310556413418768, 388389186178424, 201218392651440 @ -67, -172, 124 294335453543209, 239407270896468, 327371176340196 @ 6, 40, -8 198704436992819, 423313637384734, 211494844150179 @ 114, -360, -21 329848820747522, 171413007628813, 298751280762187 @ -19, 102, 54 232791155115204, 389793252905721, 200914316887487 @ -56, -314, -82 371238777825072, 364331369420770, 349467249711398 @ -35, -114, 34 290194660125822, 286241186809255, 265989895196345 @ -93, 39, -71 138500514403427, 150096241065480, 90891764345181 @ 270, 386, 345 342432728761822, 169489883251125, 160900448427412 @ -69, 145, 204 387284555873510, 268651056280939, 472485507519965 @ -235, 48, -406 348183642749259, 358775680962680, 425167151051150 @ -26, -110, -64 214564960481976, 332636582662001, 166341733116147 @ -35, -19, -17 288352094438008, 172713636729509, 508999993126113 @ 32, 94, -171 429522310493674, 350751066474876, 353772711184036 @ -241, -106, -110 235317931818252, 321016228988431, 221782559196323 @ 8, -29, -24 237395224369976, 271952629687205, 200198427527953 @ 48, 46, 109 267689676493904, 197692176620362, 371002531720142 @ -151, 456, -664 245022629101794, 336310573633898, 178670106406896 @ 79, -86, 192 308555808260267, 235053234862080, 386617281992034 @ 20, 16, -14 254939001555789, 196490967246088, 344406853138846 @ 46, 120, -66 198067603029891, 228271655034477, 230280443116238 @ 112, 353, -142 286182290367015, 324356938662982, 337470234197366 @ 40, -74, 30 182772323746872, 243078357133489, 180935879286305 @ 182, 418, -11 334555295661618, 283598866844113, 307163703216413 @ -19, -28, 51 268032515539496, 179884088413109, 201707373095034 @ 53, 89, 166 314152706857177, 231973181098005, 294537386515547 @ -10, 41, 47 211145445957746, 256130578705417, 227544572919273 @ 105, 54, 81 240281216930434, 308871905093706, 201208104074959 @ -81, 58, -69 194990331403464, 353680311245143, 148152875882771 @ 96, -217, 54 376506453102756, 282681817701967, 308014018133222 @ -59, -29, 56 270559608594507, 293243401201593, 219465840278274 @ -38, 17, 48 271434227107862, 301909819058233, 255037189953162 @ -157, 57, -212 228819748864119, 35415178477933, 360982336746131 @ 100, 225, 7 282571416535269, 237239909717928, 361818410574456 @ 34, 28, -20 237878607070278, 316580360861695, 326197735422041 @ 42, -39, -160 182576050978588, 187101572838317, 131079628110881 @ 153, 161, 245 235076492312502, 318319071558547, 260428708551349 @ -203, 96, -762 187583408959494, 313306547152243, 102716500573961 @ 189, 318, 643 239870832918417, 26077551674877, 194534422319897 @ 10, 745, 77 268344200395759, 336594882856173, 201457637971271 @ -144, -71, -13 351502642713711, 343426968745552, 327993505552334 @ -54, -94, 8 203247301060818, 304211148313729, 144668102389835 @ 17, 294, 108 205287991254828, 326526363823258, 176717703001868 @ 73, -18, 32 228237293076774, 492607291603871, 215976066898633 @ 49, -457, 39 210744469193866, 242345551455857, 338364614486931 @ 87, 173, -305 283795432748766, 324397233772201, 303141716476529 @ 27, -71, 37 318328668468378, 290176478743420, 393177776909696 @ -9, -32, -60 296886504660264, 330367685997713, 290768439652901 @ -8, -76, 23 354925965270690, 204310714489876, 324988197369764 @ -73, 86, -6 277940901110162, 351813200734015, 35068250706381 @ 26, -105, 370 302119534267998, 319648005021051, 257122942759009 @ -185, -26, -123 220643077695684, 355855985807773, 179518771733771 @ 30, -142, 66 281128245154754, 261417029969318, 390265842706956 @ 47, -10, -20 401214520647879, 209382315271573, 394433050114910 @ -66, 37, -12 202419387388134, 370308338321798, 371095720268716 @ 115, -152, -266 243933688132567, 284238541251243, 160523673406178 @ -60, 127, 134 207949728449758, 342146025132292, 160034991638202 @ 27, -90, 52 328107083354006, 506783656792851, 68374835799249 @ -27, -292, 321 334371695727666, 295677547881937, 372669058678174 @ -209, 21, -342 425555650358416, 141386636896383, 400700320063993 @ -94, 107, -23 354111348691934, 360815768065903, 286452836048521 @ -183, -129, -62 186640407106107, 302586436160656, 178053441373097 @ 172, 200, -99 184504662208422, 279753007845271, 194263341780489 @ 217, 645, -497 207498586652070, 122966697911623, 453309639270761 @ 88, 592, -760 175420575327994, 240376844547933, 227794777853156 @ 159, 37, 122 164379037426222, 314155556336019, 361113505933531 @ 171, -59, -30 276158080997198, 255307550628353, 190284041278157 @ 27, 22, 167 188538116291142, 332645165411655, 164893512402481 @ 166, 10, -105 206485169181270, 324400373771635, 174538862304413 @ 37, 28, -44 231705775027484, 354858179856273, 282940665637611 @ 53, -119, -77 192935594972436, 232318329359044, 140280091724297 @ 125, 770, 173 195865425610134, 156203126394403, 201075304936541 @ 121, 618, -22 220291544685654, 60861797261303, 192839119984101 @ 97, 313, 156 216421547979532, 166625355222409, 138232910764571 @ 33, 645, 215 454745381031134, 359071031321598, 433358646779191 @ -229, -116, -177 241211456940334, 274238344824863, 449761596808401 @ 87, -22, -86 300489403237401, 150600505604740, 311021695401350 @ 12, 130, 36 351714451571994, 313870670017933, 87623195530631 @ -79, -54, 304 206304315814166, 322825195619263, 165678725657741 @ 47, 27, 35 235260754952454, 192089045978143, 324835846533921 @ 88, 81, 21 234012378392974, 220537666254223, 244419610199201 @ 21, 243, -67 271646520250074, 328249590902743, 281718062915501 @ 38, -75, 56 221872342890713, 311155829759331, 169665424751063 @ 96, -49, 191 234965964033108, 289605268944487, 264575781614519 @ 53, 11, -17 302656676541801, 314956862712124, 279759708917957 @ 22, -64, 89 194778772231287, 358987377936095, 94944329588325 @ 100, -269, 633 213962227655009, 360175350319088, 187183591353131 @ 78, -140, 95 335872446070469, 310194803249308, 258956779512841 @ -196, -18, -51 237632929340327, 282862400087895, 329308829827744 @ -54, 155, -578 195165381881310, 334127994548035, 177008381765921 @ 83, 25, -395 322431513433582, 335929297302159, 292621591828001 @ -117, -80, -70 315117522492294, 188045711663619, 217859262699941 @ -11, 94, 140 373704262775700, 207296292228736, 462531809606177 @ -143, 116, -267 251431566932470, 262653021312867, 228387402272864 @ -45, 151, -52 200968557727895, 335950123937744, 148782648944484 @ -28, 20, -56 236191762393467, 21120063276068, 319730241477691 @ 22, 742, -245 208913018909190, 375167847286459, 97238860543841 @ -29, -401, 565 290435031159135, 56359235789263, 318028085602160 @ 28, 227, 36 205348838719584, 129089359330730, 397134601580767 @ 109, 358, -317 194757851501280, 310732265284483, 257897724121307 @ 122, 57, -352 322105170096600, 281140697612407, 384217392018125 @ -40, -9, -101 227263802927379, 293407939553692, 217416903679568 @ 34, 50, -6 253024402494847, 472881498291876, 346563578286452 @ -60, -512, -448 314479634908016, 119470812770471, 423291884678263 @ -102, 343, -326 285064202741996, 260225765977046, 328922413430668 @ 17, 14, -12 164764803937924, 131918495543174, 24421731030948 @ 209, 466, 528 302401846001018, 47953136574059, 415330628001011 @ -43, 389, -220 136889723461149, 102922183481659, 257049978466682 @ 254, 415, -22 266977346640134, 399124471391351, 389593482782381 @ 29, -175, -130 372790937915094, 329723676236983, 408552056960081 @ -242, -66, -337 295046549007926, 307216389914204, 245279985581636 @ -93, -14, -10 222962551504923, 300940192862044, 205863476663477 @ 42, 34, 17 217936499850689, 313784346557728, 244304797861441 @ 86, -36, 21 167754243520824, 183008145578501, 255319117162995 @ 184, 214, 6 210177003182478, 429234450438847, 105538845228113 @ 101, -266, 296 199347157290654, 270021317518867, 163266752925959 @ 99, 261, 88 236595610312209, 357567541944595, 163695965251100 @ -116, -177, 62 312426175948804, 126535043607303, 334910821408881 @ 20, 119, 45 250185142335527, 339957515144567, 186490088641817 @ -40, -85, 77 187486534782198, 153491915531223, 178050669591013 @ 145, 217, 168 264452793637374, 364051575147343, 278407165734113 @ -66, -153, -167 321652447174633, 234494711812364, 293511778578951 @ -94, 100, -45 101178528277354, 45310253629503, 279722555547721 @ 231, 211, 93 311483135370989, 117588178673003, 195876215498686 @ -30, 223, 154 349074097657518, 71980788262470, 67744127629012 @ -53, 236, 322 205665951950534, 317578175678991, 174079200152461 @ 9, 131, -140 172224556223070, 207776433045037, 341587542422723 @ 163, 78, -22 199777030731058, 159408594476631, 309534334024285 @ 108, 565, -396 464121799742544, 439378219125328, 480156984371951 @ -191, -210, -177 512533623338691, 269596699742212, 497024716185359 @ -200, -16, -141 449327916519144, 205855641898298, 303200495165981 @ -131, 50, 65 283724606928492, 240851979789205, 384065029237529 @ 38, 18, -31 288013100270877, 208780552824757, 275880042837536 @ 42, 41, 100 225018718395018, 305644724002975, 271186961007503 @ 73, -21, -28 252580597893096, 289594241717095, 283259230473967 @ -14, 39, -134 217696966439229, 236860502115098, 202812154030551 @ 82, 134, 91 290383585895985, 172960262418583, 413523311841740 @ 22, 107, -88 246394854383374, 404386901502983, 316452007110281 @ 63, -178, -10 277440283560394, 298664786803743, 343675845620671 @ 29, -37, -26 549218613325353, 365039367598781, 370814441177496 @ -212, -115, 10 314422297180566, 290227116094987, 220524013374437 @ -127, 20, 52 208288985823519, 332582248866208, 173680963176656 @ 38, -34, -6 344954667419544, 271844404820980, 373070962444213 @ -11, -24, 9 253707352980234, 336179622652543, 293095895839541 @ 22, -81, -58 348619876072741, 233964822099034, 330658038016178 @ -48, 36, 8 294065185957476, 303581225750131, 130406957718587 @ -14, -35, 246 299497691666274, 143845614560983, 193269298796021 @ -30, 217, 148 243761048715324, 305091461548017, 163187922986167 @ -56, 46, 126 228852534457750, 321833988811099, 195275147618589 @ -19, -6, -24 210326083482005, 405825122389483, 255008495328029 @ 48, -393, -343 234154015900814, 320051906908983, 254552486072961 @ 15, -28, -111 221069337881082, 268544927933243, 253793013055353 @ 40, 152, -161 350843574391570, 546291208573433, 245148884150221 @ -57, -343, 105 321884637993916, 151517460880797, 338566691457073 @ -108, 268, -147 332310394683086, 296925474202815, 290407863681483 @ -133, -5, -62 238868612579282, 442767280701488, 312738360614324 @ -73, -538, -562 238005301025171, 315819717023939, 310603161892176 @ 62, -49, -50 184500511341324, 354706787987715, 106858269141817 @ 184, -175, 409 218719926572754, 248846852339899, 417842058727985 @ 109, 9, -67 61527743340558, 41910468004471, 21054306023633 @ 311, 306, 391 206891968805558, 359036109292941, 96347232076181 @ 71, -164, 395 358569854122062, 275252683087759, 280731684589601 @ -219, 51, -75 281134641567294, 255607683726743, 288258712879345 @ -11, 52, -17 325364111053745, 294010589908703, 211245733791773 @ -82, -13, 113 268578371026014, 236127445255093, 380797038274583 @ 59, 17, -13 489485534335218, 226913670756739, 271116263277629 @ -155, 21, 107 200091726654254, 345151854422543, 355346332534721 @ 125, -97, -106 288773407987668, 371116294945099, 330355289788371 @ -128, -171, -300 398345872685398, 211733420030191, 256489704564165 @ -127, 75, 84 410444070061341, 232446702321753, 270268423194688 @ -80, 17, 106 223446110503560, 342994867695369, 176936935212271 @ -23, -95, 15 221456980555537, 346760891427937, 198873039052710 @ 8, -111, -48 241138246161499, 378379591190555, 197910544306414 @ 44, -161, 118 239309488603942, 346974551472951, 243277229211186 @ 51, -101, 40 266720686719534, 249073195909171, 326627536261997 @ 59, 6, 38 175265275057344, 233389584704983, 166232708483831 @ 228, 519, 48 199647143220834, 333605166183208, 126338949433076 @ 87, -38, 274 355059474706240, 112909300036023, 456817283755217 @ -18, 127, -67 291234253229982, 225827198327447, 300458706607553 @ -17, 89, -19 289865647604208, 451420237900663, 518182602681917 @ 12, -233, -253 351557916167787, 226921027459900, 441676807044779 @ -112, 88, -241 171724416708978, 120198249743035, 113845845697733 @ 210, 720, 308 324992776605402, 546442272740313, 176464245808959 @ -35, -358, 186 266166769986634, 268730110669199, 328440341073557 @ 9, 35, -97 225525857274734, 233012276737543, 309959118198911 @ 75, 111, -88 183405703797942, 309355721084695, 182533926443609 @ 173, 53, 19 210515462842953, 291925001904295, 215164290510485 @ -72, 459, -671 235537482505454, 310690173156743, 156326933471977 @ -21, 22, 154 273084618253552, 382626888261135, 273689280998585 @ 8, -157, 17 253722385917350, 315123819243295, 240205666004325 @ 57, -57, 102 196398380835834, 355900579581511, 153312099518087 @ 109, -169, 118 283444009699329, 366561045831077, 202002888581270 @ -146, -167, 26 296532850164962, 253904723261403, 296984689916093 @ 38, -8, 86 356774602967614, 373148843974943, 387561802202761 @ -67, -131, -74 252770877244094, 318171858594683, 216752381636081 @ -25, -28, 17 338919821368038, 232645806842808, 377368303830121 @ -29, 32, -35 209566211606045, 338493165391956, 150634080385665 @ -72, -46, 21 328388255345246, 295645021337031, 342359520358565 @ -13, -41, 11 357923314873354, 213990132914548, 252051459029871 @ -145, 126, 39 300794330404169, 291383403542233, 331991009111531 @ -28, -15, -61 171452764273723, 106269888549931, 325980849738994 @ 168, 255, -42 400651551538638, 227035846405175, 440348818761665 @ -113, 46, -127 183528864416638, 337358904333282, 149647897440530 @ 155, -82, 206 407834029671234, 363038317346083, 326507144649005 @ -126, -118, 6 261232554625244, 272762277507558, 260158766990881 @ -139, 184, -267 276291421501401, 231191690007043, 332403327250334 @ 32, 47, -8 213146770430035, 320595954009642, 182342124018161 @ 36, 10, 5 431072263340031, 549716908674601, 541461834661703 @ -234, -415, -393 271067118142410, 252860807780751, 293724860670289 @ 25, 35, 13 230424456187626, 346336855193767, 374228162998841 @ 76, -99, -145 233683858918340, 451654359126852, 407119183631371 @ 45, -334, -365 309530132675051, 360560922327322, 427729374335125 @ -118, -132, -399 171253360815090, 226755112694191, 106314555408725 @ 286, 763, 428 195185795409569, 365215513552403, 270027401984661 @ 134, -121, 73 ================================================ FILE: exm/aoc/2023/aoc_2023_24_questions.txt ================================================ --- Day 24: Never Tell Me The Odds --- It seems like something is going wrong with the snow-making process. Instead of forming snow, the water that's been absorbed into the air seems to be forming hail! Maybe there's something you can do to break up the hailstones? Due to strong, probably-magical winds, the hailstones are all flying through the air in perfectly linear trajectories. You make a note of each hailstone's position and velocity (your puzzle input). For example: 19, 13, 30 @ -2, 1, -2 18, 19, 22 @ -1, -1, -2 20, 25, 34 @ -2, -2, -4 12, 31, 28 @ -1, -2, -1 20, 19, 15 @ 1, -5, -3 Each line of text corresponds to the position and velocity of a single hailstone. The positions indicate where the hailstones are right now (at time 0). The velocities are constant and indicate exactly how far each hailstone will move in one nanosecond. Each line of text uses the format px py pz @ vx vy vz. For instance, the hailstone specified by 20, 19, 15 @ 1, -5, -3 has initial X position 20, Y position 19, Z position 15, X velocity 1, Y velocity -5, and Z velocity -3. After one nanosecond, the hailstone would be at 21, 14, 12. Perhaps you won't have to do anything. How likely are the hailstones to collide with each other and smash into tiny ice crystals? To estimate this, consider only the X and Y axes; ignore the Z axis. Looking forward in time, how many of the hailstones' paths will intersect within a test area? (The hailstones themselves don't have to collide, just test for intersections between the paths they will trace.) In this example, look for intersections that happen with an X and Y position each at least 7 and at most 27; in your actual data, you'll need to check a much larger test area. Comparing all pairs of hailstones' future paths produces the following results: Hailstone A: 19, 13, 30 @ -2, 1, -2 Hailstone B: 18, 19, 22 @ -1, -1, -2 Hailstones' paths will cross inside the test area (at x=14.333, y=15.333). Hailstone A: 19, 13, 30 @ -2, 1, -2 Hailstone B: 20, 25, 34 @ -2, -2, -4 Hailstones' paths will cross inside the test area (at x=11.667, y=16.667). Hailstone A: 19, 13, 30 @ -2, 1, -2 Hailstone B: 12, 31, 28 @ -1, -2, -1 Hailstones' paths will cross outside the test area (at x=6.2, y=19.4). Hailstone A: 19, 13, 30 @ -2, 1, -2 Hailstone B: 20, 19, 15 @ 1, -5, -3 Hailstones' paths crossed in the past for hailstone A. Hailstone A: 18, 19, 22 @ -1, -1, -2 Hailstone B: 20, 25, 34 @ -2, -2, -4 Hailstones' paths are parallel; they never intersect. Hailstone A: 18, 19, 22 @ -1, -1, -2 Hailstone B: 12, 31, 28 @ -1, -2, -1 Hailstones' paths will cross outside the test area (at x=-6, y=-5). Hailstone A: 18, 19, 22 @ -1, -1, -2 Hailstone B: 20, 19, 15 @ 1, -5, -3 Hailstones' paths crossed in the past for both hailstones. Hailstone A: 20, 25, 34 @ -2, -2, -4 Hailstone B: 12, 31, 28 @ -1, -2, -1 Hailstones' paths will cross outside the test area (at x=-2, y=3). Hailstone A: 20, 25, 34 @ -2, -2, -4 Hailstone B: 20, 19, 15 @ 1, -5, -3 Hailstones' paths crossed in the past for hailstone B. Hailstone A: 12, 31, 28 @ -1, -2, -1 Hailstone B: 20, 19, 15 @ 1, -5, -3 Hailstones' paths crossed in the past for both hailstones. So, in this example, 2 hailstones' future paths cross inside the boundaries of the test area. However, you'll need to search a much larger test area if you want to see if any hailstones might collide. Look for intersections that happen with an X and Y position each at least 200000000000000 and at most 400000000000000. Disregard the Z axis entirely. Considering only the X and Y axes, check all pairs of hailstones' future paths for intersections. How many of these intersections occur within the test area? --- Part Two --- Upon further analysis, it doesn't seem like any hailstones will naturally collide. It's up to you to fix that! You find a rock on the ground nearby. While it seems extremely unlikely, if you throw it just right, you should be able to hit every hailstone in a single throw! You can use the probably-magical winds to reach any integer position you like and to propel the rock at any integer velocity. Now including the Z axis in your calculations, if you throw the rock at time 0, where do you need to be so that the rock perfectly collides with every hailstone? Due to probably-magical inertia, the rock won't slow down or change direction when it collides with a hailstone. In the example above, you can achieve this by moving to position 24, 13, 10 and throwing the rock at velocity -3, 1, 2. If you do this, you will hit every hailstone as follows: Hailstone: 19, 13, 30 @ -2, 1, -2 Collision time: 5 Collision position: 9, 18, 20 Hailstone: 18, 19, 22 @ -1, -1, -2 Collision time: 3 Collision position: 15, 16, 16 Hailstone: 20, 25, 34 @ -2, -2, -4 Collision time: 4 Collision position: 12, 17, 18 Hailstone: 12, 31, 28 @ -1, -2, -1 Collision time: 6 Collision position: 6, 19, 22 Hailstone: 20, 19, 15 @ 1, -5, -3 Collision time: 1 Collision position: 21, 14, 12 Above, each hailstone is identified by its initial position and its velocity. Then, the time and position of that hailstone's collision with your rock are given. After 1 nanosecond, the rock has exactly the same position as one of the hailstones, obliterating it into ice dust! Another hailstone is smashed to bits two nanoseconds after that. After a total of 6 nanoseconds, all of the hailstones have been destroyed. So, at time 0, the rock needs to be at X position 24, Y position 13, and Z position 10. Adding these three coordinates together produces 47. (Don't add any coordinates from the rock's velocity.) Determine the exact position and velocity the rock needs to have at time 0 so that it perfectly collides with every hailstone. What do you get if you add up the X, Y, and Z coordinates of that initial position? ================================================ FILE: exm/aoc/2023/aoc_2023_25.adb ================================================ -- Solution to Advent of Code 2023, Day 25 ------------------------------------------- -- Snowverload -- -- https://adventofcode.com/2023/day/25 -- Copy of questions in: aoc_2023_25_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory (..) --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2023.gpr . with HAT; with Interfaces; procedure AoC_2023_25 is use AoC_Toolbox, HAT, Interfaces; capacity : constant := 1570; link : array (1 .. capacity, 1 .. capacity) of Natural; -- ^ To save memory, we use the same array for storing -- the data's information (0 = no link between i and j) -- and for counting visits through edges. last : Natural := 0; name : array (1 .. capacity) of VString; -- For display purposes. verbosity : constant := 0; function Label (i : Positive) return VString is begin return name (i) & '-' & Image (i); end Label; input_name : VString; skip_header : Natural; mc_iter : Positive; vertex_limit : Positive; procedure Read_Data is use Hash_Maps; hm : Hash_Map_Type; c : Character; key : VString; src, dst : Integer_64; f : File_Type; procedure Get_Key is begin key := Null_VString; loop Get (f, c); exit when c not in Alpha; key := key & c; exit when End_Of_Line (f); end loop; end Get_Key; begin for i in 1 .. vertex_limit loop for j in 1 .. vertex_limit loop link (i, j) := 0; end loop; end loop; Clear (hm); Open (f, input_name & ".txt"); for skip_it in 1 .. skip_header loop Skip_Line (f); end loop; while not End_Of_File (f) loop Get_Key; Insert (hm, key, Integer_64 (last + 1), False, src); if Integer (src) > last then -- We found a new name last := Integer (src); name (last) := key; end if; if verbosity >= 2 then Put (Label (Integer (src)) & ": "); end if; Get (f, c); loop Get_Key; Insert (hm, key, Integer_64 (last + 1), False, dst); if Integer (dst) > last then -- We found a new name last := Integer (dst); name (last) := key; end if; if verbosity >= 2 then Put (Label (Integer (dst)) & ' '); end if; link (Integer (src), Integer (dst)) := 1; link (Integer (dst), Integer (src)) := 1; exit when End_Of_Line (f); end loop; if verbosity >= 2 then New_Line; end if; exit when End_Of_File (f); Skip_Line (f); exit when End_Of_Line (f); -- Blank line after the data. end loop; Close (f); end Read_Data; -- Dijkstra stuff. list_length_max : constant := 500_000; subtype List_Range is Integer range 1 .. list_length_max; subtype State_Type is Positive; type Node is record len : Natural; state : State_Type; pred : Natural; -- `pred` is for backtracking the shortest path, to -- increment the edges counters. end record; list : array (List_Range) of Node; current, explored : Natural; -- 0 <= current <= explored inf : constant Natural := Integer'Last / 4; function Dijkstra_Algorithm (start, finish : Positive) return Natural is best : array (1 .. capacity) of Natural; cur_len : Natural; cur_s : State_Type; procedure Visit (new_vertex : Positive) is len_to, ins : Integer; new_node : Node; begin len_to := cur_len + 1; -- All edge have a length 1. if len_to < best (new_vertex) then -- Found a better path to target state. best (new_vertex) := len_to; -- -- Insert in a sorted way. -- ins := explored + 1; for i in current + 1 .. explored loop if len_to < list (i).len then ins := i; -- Insert here. -- Optional: remove another node -- with the same state and a larger length. exit; end if; end loop; for i in reverse ins .. explored loop list (i + 1) := list (i); end loop; new_node.len := len_to; new_node.state := new_vertex; new_node.pred := current; list (ins) := new_node; explored := explored + 1; end if; end Visit; begin current := 0; explored := 0; for x in 1 .. last loop best (x) := inf; end loop; cur_s := start; cur_len := 0; loop for j in 1 .. last loop if link (cur_s, j) > 0 then Visit (j); end if; end loop; -- -- Switch to the next best explored point. -- current := current + 1; if current > explored then Put_Line ("No way found."); return inf; end if; cur_s := list (current).state; exit when cur_s = finish; cur_len := best (cur_s); end loop; return best (cur_s); end Dijkstra_Algorithm; busiest : Positive := 1; -- We walk from each vertex to another, randomly chosen, vertex. -- On the way, we increment the visited vertices' counts by 1. -- procedure Walk_Through_Randomly is procedure Mark_Edge (vertex_1, vertex_2 : Positive) is busy : Natural; begin if verbosity >= 3 then Put_Line (+" edge " & Label (vertex_1) & " to " & Label (vertex_2)); end if; busy := link (vertex_1, vertex_2) + 1; link (vertex_1, vertex_2) := busy; link (vertex_2, vertex_1) := busy; busiest := Max (busiest, busy); end Mark_Edge; len : Natural; j, k : Positive; begin for i in 1 .. last loop loop j := 1 + Rand (last - 1); exit when j /= i; end loop; len := Dijkstra_Algorithm (i, j); if verbosity >= 2 then Put_Line (Label (i) & " -> " & Label (j) & ": " & len); if verbosity >= 3 then for lp in 1 .. current loop Put_Line (+" list item " & lp & ": vertex: " & Label (list (lp).state) & ", predecessor item " & list (lp).pred); end loop; end if; end if; -- Back-track from j to i loop current := list (current).pred; if current = 0 then Mark_Edge (i, j); exit; end if; k := list (current).state; Mark_Edge (j, k); j := k; end loop; end loop; end Walk_Through_Randomly; procedure Show_Busiest is count : Natural := 0; top_x : constant := 5; begin Outer : for busy in reverse 1 .. busiest loop for i in 1 .. last loop for j in 1 .. i - 1 loop if link (i, j) = busy then Put_Line (+" " & Label (i) & " -> " & Label (j) & ": " & busy); count := count + 1; exit Outer when count = top_x; end if; end loop; end loop; end loop Outer; end Show_Busiest; procedure Show_Graph_Stats is count : Natural := 0; begin Put_Line (+"Vertices : " & last); for busy in reverse 1 .. busiest loop for i in 1 .. last loop for j in 1 .. i - 1 loop if link (i, j) > 0 then count := count + 1; end if; end loop; end loop; end loop; Put_Line (+"Edges : " & count); end Show_Graph_Stats; procedure Remove_Busiest_Edge is count : Natural := 0; busiest_i, busiest_j : Positive; begin Outer : for i in 1 .. last loop for j in 1 .. i - 1 loop if link (i, j) = busiest then busiest_i := i; busiest_j := j; count := count + 1; exit Outer when count = 2; end if; end loop; end loop Outer; if count = 2 then Put_Line ("!! At least two ex-eaquo busiest"); end if; link (busiest_i, busiest_j) := 0; link (busiest_j, busiest_i) := 0; end Remove_Busiest_Edge; procedure Reset_Counts is begin for i in 1 .. last loop for j in 1 .. last loop if link (i, j) > 0 then link (i, j) := 1; end if; end loop; end loop; busiest := 1; end Reset_Counts; function Count_any_Group_Size return Integer is visited : array (1 .. capacity) of Boolean; counter : Natural := 0; procedure Visit_from (i : Positive) is begin if not visited (i) then visited (i) := True; counter := counter + 1; for j in 1 .. last loop if link (i, j) > 0 then Visit_from (j); end if; end loop; end if; end Visit_from; begin for i in 1 .. last loop visited (i) := False; end loop; Visit_from (1); return counter; end Count_any_Group_Size; answer : Integer; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Random_Seed (1); -- ^ We want a reproduceable result, even though -- mc_iter is sufficient *most of the time* when -- the seed is randomized... if compiler_test_mode then -- GNAT runs this program on the actual problem -- data in 3 seconds, while HAC takes forever. input_name := +"aoc_2023_25_questions"; skip_header := 43; mc_iter := 10; vertex_limit := 40; else input_name := +"aoc_2023_25"; skip_header := 0; mc_iter := 1; vertex_limit := capacity; end if; Read_Data; if verbosity >= 1 then Show_Graph_Stats; end if; for edge_removal_count in 1 .. 3 loop -- Empirical observation: apart from the busiest edge, -- the next top edges in the list of busiest edges are -- not reliable candidates for cutting all three wires -- at the same time. -- Check with `verbosity` >= 1 and by disabling the -- fixed random seed (comment out `Random_Seed (1)`). for iter in 1 .. mc_iter loop if verbosity >= 2 then Put_Line (+"Macro iteration " & iter & ", shortest paths"); end if; Walk_Through_Randomly; end loop; if verbosity >= 1 then Put_Line (+"Round " & edge_removal_count & "; busiest edges:"); Show_Busiest; end if; Remove_Busiest_Edge; -- Snip! Reset_Counts; end loop; -- Now, we have done three times this : remove the busiest edge. -- AoC promises us that the heap of components can be -- split into two separate, disconnected groups by cutting -- only three wires. answer := Count_any_Group_Size; answer := answer * (last - answer); if compiler_test_mode then if answer /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & answer'Image); -- Part 1: validated by AoC: 614655 end if; end AoC_2023_25; ================================================ FILE: exm/aoc/2023/aoc_2023_25.txt ================================================ msv: nlh lsd: mfs fpv nlc jjg bbb gmv lbf: dxk jlf: rdb rvx rcl bqc fjk: hfb tll: rqx pms bbk: bst zfs dpb dlq klb: ktc nzs xsk hbp rvm: jfd skf gkv hrq: rmk pmb pts pdf vtx: fvh pnn ttt: gdf scv xrz fzd: vdk qsz dnf bqm: cxr nvk jfd cgl qgn: dbz lrp jrk: htq nsq klc pkn: njn fcs xrz xsk: gfc tpm ttg: bdd mkx dxc kdz nxg: gbq fqt mhg: cfg hdr znv rfn fzg: jkg qhx rfl vhp lnj: vnc mdj pms: mdj nfj dmb: mqv bkr: lzd hdz fdv mzq brq: bmc pls nsv bqf: zkf xzd: jgs bdd vll qrb jqj: rhx dxh lvk tvv ghd: std vzs lzh: pgt gzd: xzb fdr zbp zjp gqp: hch bfb fjv hjx bxd vkc: kdt hfq: gkj qmt dms: dsx pgm xpq qgn vfn zxd: kjf thq rcj zmt jht dnk: tqx hsl grd: rrv mdv fcp rzd: rcj kjr kpq hjk qrn: dbl jpm msn sph: xxk rkh jkg sff qfb kfm: tgt qzq: jbg jlz: zxj xvq znq pnd: pzh xgr rcl ttq: tql fcp vcp qhm vnk: vfd qcp nrq: xcq tql tvc htq: rbm qhx tkt hlj: ndl lkx nbp bxz sxc: ffz bfm vgh bsg kls jcf pjv: vll sjp hzm jlj: bcm ndh: dpz plz jvl srv hnb: zkx jsm rvs: jhm fkg: rzx hsx: rcx hqt: lkq fgc qbb: tsh dnj bjm hdr: tgt cfl gtr: fpt mch: rgx xck mqh: fzc jrt kmr: pzd xqq: hzz knm fdd zmj lxp: nrg nnf dnv fms ckp: svb cjn vqj ltb: bsp hcz: pzd ljc rvm bvj zkx: xtj qvb lzg: xzq fnx njz: ztf xvx: fpt xqn xhn qfc nxf: rfn nqn fkg ddk gpz: bcr czd zpm zjd fdc: xlk ghq tvg plz: rhc dds dtx xjc: vtj bsq rkh zrf: hzz ncn: gtr pts: ftn zlx: mxx rcb qxx: vrc zst npk rhc: dqc kds: vcg bjm cxr rkg sds: vpz dcv zbq ckq bqd vjm: gbq kqk dfp: vjm tpm kdv khl gkr nbz: zft dxk psg: vdr rpv kjf: xnq hzk: qfc vbt mnr: nhf skk zxt rmg drk: qlp xbv sdv: pnl zlh dhd xxk: fzb tql jpj std: hvb bsg ndv: sld gdl pgk: csd nxt cjd xlk vsf: jgd kfm trf qtk: rhl fvg: tgl vcb mjb hpz htz: shx hvc spq fvj jcf nnk hmb tvc: lzd thq lht jzd nct bdg: lfx jkg: mtj gsl ktf kpc: rcc crj mgs: svb tpt dgb: qvg nbc: bnx jpt pgt ngj: gnl zkx lvz rgg czp: lbs sqk: hbc dmb tnx mfs sdt: jrt xvr kdv: fsj qbh msj hpv: xxb jsm trf: jbn fpn: bfm nnv: ghl dbl jds bhq zlh: vxp xjt: bgj mhs pzd lxb hqk pbg: qzq pls zmb rxx rfs ckf dsx: nlb bbr xzq rhn: cxr vjl qlh: cpb jgl tvd bdq fhp: jpv dbk hrf: tdv rvp vfd trk xzb: ksj gdt: qnh rvp klf chb: hfc fdr tkt jsq: qrr czg kft fjr: xnd kjp: gqd vdb: mgx vrn: cvk rkh: mhs rhc gnb fvc: pbj fht fdd lbs gxg cnr: rhl xjf vhp: kgf jht glq kqr: fpt scv rpr lzg pzj: frr dps lxj: qsq hcm ngn xng shr jgh: xvq jcc rnt khl rvc: tzm vcp lgl cct: vnc pfc sjn fkb kpc hfb nvv: gfv ntb dqb: czh nvk: cts ccz zmt: rbm bcx znm xtx xbr: pmk xqt nrk zcn dlk xll mcx: bdm jsm cst mgt: lrd knm dzf zgc: lbs qlp ksj zpm: mgx qmv qhf: zcp nhf vgh fsb cfl: pvk mrg pkd cnr spq: mmt mhb dqb btt: kpf kzd: lrk dqh scd vdb lkq: gbr nkl: hmm trf kvx kpc lqg: mxq zgc bmr fsn klp qgp tvj: gdl tgs dlb rnq: pkd sjm jfv ndl rcm: vcb gqn cns nsp: crj cjd dbq tmh: fjk ndt pct njj xxm: mlp lbf gmm: gfm rqz dpk pjx kqt txb: sxn hvc rvj: sxf dqh xxm gxp gnl: ssg zrf rsf: htj vkc tfb: lkv vbb: fdr skx qxq: dbp dzr rcb zpx: pcl kzx grm tmj jcf: ghm ndm czd: bsp ccr htp: xtm vrn jhm dpd: zcn ckh ghg zbp xjq brf: lkq bqf zpj rzk tsh: cqv ndt: rcb jlk: jrm lzd: xbl gmj: snf csz vgr llc: cvh xcq lft hlr: xxb ddn mff cjn: gvx tgt lfz ljc pnm: lpf ndr bnt zsk pvk dds fmg: bmm klc hdz vpz msj: vnc sqb tpx: vdb vtj nmn nhf qhm: sld kft rrk: jfc hcj hsx hbg fpn dnr: ngm mps vtk: pbj xqz: lbx ssf nxz: llp vnr tfz cpb: fdm tcj xhg vnv: sst bcj lzh czp spj hrd: sth mff dbz cgp: mhm zmj rbq hkz: sjx dbq zft kqk lxc: gkj bmj: rgp dmc: gdt rvp xph txb ckg tmb: pkd lhs krm: hmm szh jmp sst: khg sgv kpf snz: njs bnx rcj kjr hbc zcb vbl pfv: bbv qtk znv: mjb tqt xgf: bnc zng vqf dft kdz: sld ldb: plg rss: rcb vlq rcx dpz hrs: mnf xbl crp lsl: tgs vtv fjr bgt nqd: hrn mgs trm gkv jhs: pgm xgh pjz xgb hbn: kdt ljc bqf scl: xgb hdz xnd: lqr vjn: hzk dxc dsm hjx fjs: jfg jfv nmx btf qnh qrb: mlk pmk knz: rkg ncm: sgv sxb hqc: nzv vzs tqz tfp: klf scv: xgb lfl jft: kmt lrd nxs: pnc qfv hdn pnd qvb sjv: pct cck: mbz klp rlr rvc csr sjp: ckf tsg rbc: mch vsq nbp bkq qtj: lnp dkn lrb: hbp zgx bxp: sdh kmf rxz chz: vxk hrf mrb cxr qnh mhf: fpn qxx vdb zrv: bdm fnn dlk: jjg dzx kjt fvm: knm gpc kjm: ppd cbk rqx: czh pdq: mhp dft dbk fqg: sdt bsv kqk: rgx mgk lnp: nlc tzm: jgg nts bmm jlj qks: grj cst skg qmt: vgh shr: mfs tqz: bqf srb pgm: bgt jlf njn: xvx zfj bpd hpc: dxd qpr qbb ndr fvk: tdn rgx: vxk gvj: ssl slr vpr pxf czg: frd qdt qvs: xvr mxg cxz: mdc fgz sck: kjk pdg qgp zjj zjp mff: tkz kft tpm: bsv fnf: bcm xqz mbz shr mgt fzj xrm ftf: dmd thk znk vcp: ckq ssk: jpm sjp rrv hlx tbb hfc: mqv xdv: jvl rvr vnc bdq: ngr llc fzb tqd: xcf trm rmr vth: dcs tkl rmr zzk knm: scv xhg: ssg ksn fxx: zvz vfz cft chr vbv zrd bfm: zgd ckh: xbv dnq jjb cnz xcr: xqt lvz: mlk xjq lfx vql rtn: njj vqg zsk nmn ldb qzc: vfz lrb nzv pbk rsz: mdv rqd: xmp cst mzz gxg jfr gqn: rqk tpm ghl: pgt hch: dxc sbx rbj: djb tpm flb dbz: pgt nfx: clv ptp ktz fbn nnf: cns ndl mxx: dzc xrz: qdt dfn: pjx xgr jrm pqq: rvx gdd: hmg nvs tbb: xnd mnp jrk csz: rhl slb: txb dnj gnb mgh: znq klf mqb jpv qgs hph stq: fzd zzt ghr dsg vjg: kvx thq: gdf str: qgs dps grj: rpr fnx mkk: dnq scv psg nnx: ksx ttt xfp xlh qbl qxz: xdc ggf qrr: vpd czp xnt: xll scl lvl: dnj vqf qxq vmp qtb hqx zkj: mxx tjp fkg rcx rbh: nml zkf rkg kqj gxl: rcc mng: zmp tdg cgm: hqc dxd nqn pdq bcm: tkb kls: vgh kql fzc cpp: dkg nzt mkk ssg rvx: jxn hdm: kzj kdl: shl cjg szd: hbf bvv gzf mxx cdv: qbf xdz snf mnl zzl xgn: dbc gcn zmp vxz ljk: vpr prj cqb: nbz vhz gcn mnl crj: hfb bzj: srg ghd thh mmt glq: vtv hlx cbs vbl: jdb zgn qcr: qlz zpl: xtm rbm mbz fsn gsl lbt: vvv pzk pqq hqx: fzc skq: hcn vfj bfb crm: xgv fjv hks qkc rts mkb fkk: bsq rzk nlh kmr dcg: pnv rcm ndl: kxr pcl: lxb vzs jvx ldq: lrp trh dgb ntb hzj: scv ptn pmf qsr lpp hjk: xqt xcq: psp vll jzd ddk: txv mdg jbx: frk qpd jht kmp cgk rrn ngr grj rqk: tmj cbr: knz trm tfz czd ckk: tpm rmq bvv gcq: mzh lzb bgl qsl ctc: hrn hdr mhb lqv: rcc srg: vlb cfg jtm: psp zhn rdb kzv gmr: jft lzh phj pnt: jgl jds hvm rdp: pnn vqg gzv rzx mjd: trf rfn fbv mgp: crp skx lbx rgp lpf: lcn chl zmg: xvj ffr gcl: zfl prj jgg: bfb htv: xqz ngr rvd vsg: gdf btv fcs snf: sjm ztg: mdr vgv rxd ddq lsg: bcx lzd fpt fzj: sjk vtk crp: kdz ddq: vrn zvl lqr gjg: kzx trk qvs jzq jqd: tfb ghq crj jbs lnv: qtp bzr rrn: hgm bhq mll: bqc xtz rpv zbq vrg: xtx bkq: nqn btc nmx: djb mzx: ffr pls slm mqz dzn: plz zrd ldb hdm qjx zxt: pdf tch: lnj jpv gft hbt: sqq nzs dtx xqs mch jqq: bfq hrs jlj khs mqz: kjr xgv ghg vqj: ldz nvf vlx: hgm bvj: xph sxf zst: lkv dnb qgc sqc ggx: srb jfd jmg lhj dcg nmb: rcj kqt: lcm fdd kjk: rdt rgm: xhn phx jjb rvx mnp: bvg fdm ljc: qjr vzj: bdm bds gjm mkb dhz jsc: lfl phz rdn tdn szh: nvs qsq: mps jrm cbk smv: cfg ktc vnr: sqq bms: zlp nzt: ssg gfz jbg cfm: gnl jdb rlv qdv bvg: tgs nbb nbj: dbc cjn pdl xcf dbh: pzk nts zfl scj: vxg xnx: ffr ngm qmh hqk: qkt ssm: vpd nbb xlk: dzc ccv: vhp xhg jrm xnq: kxv rvd vbm: pzk drk nmb ncn dqh: gbq tvv: dnv kfm xcx ztn: cvk mzz jff krn: jvx ndt cfz nbp qgp: cql bzr qcr jfg: tdg dtv vlb: vnr rdz: jkt jgg sfj hpx: lkb lcn hvb jbl cqv rcx: gqd qmv: jbn kvx gzv tsv: ggf tbg zfz: scd rfn jhr pjg: vbq thh bnc tjm pdf: vjl pgg tlg: hrn fgc: dgc btc fcp: nlj mdj: vmb pct bbd: jhr gsg jqs hbn xvq: sbg xpz: bgj jmp: smk tdv: cnj tfp klc: phx ddn vrz: fsb vfz chz qcp szt mbg: rzh mmt: lql fsj: vjl vxz: fjk mxq: mbg zjg: jlh ghq fsj npk mnh: szv ltv gbq stk: gct vfd crz nrg skd: znq dxr dqc dtq kbc: pqv mmt pgg zlh vgv: hzm fzb qgs: lql pmf: nnp ljd: lhs ghr mkv sdq tmb ghg: ktz ndg vzq: bpd jth cgk: xcq kpq vbb gkj: ftn gbb: bqm fkg jrt htm qbl: rqd nsm btx vkd zrv nnl: tcj kpc qrr hch cjq: gmx zgn tdc: rvs dhz jlk gmq gfs: xpf gjg zmp fsj tqz vxj: msn hnb vvv zrv qmh mlg: qrr hcm sfl: hdn hjk vmk jdb bzf: ksj nsq zrf drk tsg: xmp nct kjr crk: trk gbr pms mkn: mlk zzg slx: rfl vbl lnv zjp: rhz xqf: ccv qkc dbs bbl: pmb jlz bkq skd dzr: vxp dzk: gtd lnp mps mzx qgl: vxk sjh: cgl scd tqd vbv: tfp vnk ssc: qgn qmh frm jsq jrj: zml lbf zpt mgk dbg: mkv gfp cvv lfz tbg: drg zzl: msj dcq: qmt rbj mhs nhx: hrs knm ntq mdc ptv: rst dcq mtc nxz kbj: crk hbg thp: xjf rsh jvc nnf ssl: hmj hgh hvm: zhn jkl nlj hcv: phz vdr mhm xhq: scg vmb mgx: jvx flb: xgx bxd: rlr cvh cdn tlc: hrd lzh cjq kdj lnp xtj rmb vbq: xhq hvb hpz zbp: skq qtm dsm: qlz lcm: qdv vbt frr: cln bsg sld: lbx frj: ldz dqb jpv fhp msg: mhv ghl dlk clv sjn: gxl hzh rst: jgd gqd crj vnl: dsm hcn ksx qcr grv: xcf fsj vzc lfd: ctc mch jgq: fgz hgh ftl ccg: zsd krj zxj gbm znn: ptn vgk dkn qvg fdv: tsd prj szv: tll vcb: rzx jvz mhb gzb: mxr lxc jdb: zzg jrm zjd: pqv lqv hkm crz: fqt sdq: nbz lfd rnl rgl: dbq ktd pfv zkv khj: qmh zjj: lht qcr ntb: nct xxb bsn: xck bpd: jth qsj: dkn xdc tvg: kfm rqk nsq: xvj mzh qvg: kjm lzb fgn: scl thq rvd jgl jhx: krm rsf mxg vjm sgc: xqt jjb zfl kvm: pmf jsl bkr fjv rdn: vnl ngn: vtv gpj: bgl rdb tdn cft: zcl xtz: pjx sth xxb cjg: vfd dnf pjq: hpz vrc pts mhp fdn: htj zpp bgs: rrt zmh: rgx krj xjf jth: dxb fjl: jgd ltb vqg lrk dtq zts: jrj sjh gct jmg grv hsl: bqc tvd: nts xng rhs rhz: hdz bcx kdj: jgl nmb rxd: xlh vbm dsz hzm: rfx frd: jlk kxv xdz: sdt ltb pns: tll vgh vpz: ptp ksx dmb sdh: ssf ksm xlh: lxj fpj kqj: lbf gzb btx: dbj bmm khg chq: ktd qjt hhr pdl dnq: fsx nmf: sbr jgq ghg kzv: qpd smx mlp: qng llp txv dpk: zfs dxb gvg sjx: gft skk zzl vxk: xgx tgh: djb shk: hqk mgh szv tlf: txt qks bmj dkn rrt ltv: kxr lxc qbh: jmg pqv: spm dtx bdx: jgs tsv xrm dmb dbj dpg: kgg rsf nxt jcc: vds lch gfp thk bjq: nmx cnj jqs rsh cgv: dlq lqp tnx srv: rmq cfl sff: zcb clv xzp: dbb nbc qrn ztn dkm dzx: bzr rgp rpr gmq lcn: pbk hmb: spm ltb pls: gdf hsc: tzz brq vrg tdn jpv: fdn hgh: xpq kmp cfm nvv vrg tmn: txt jbg mzh pxf qnf: ffz slb mpb pqv khb: kmp pjz lkr fht: lpr fcz fdd bcr: lrb jmp xcs vlq: sqb fqt drq: ccz fdn xvr rvr jgs: bbr txf: gdd mrb ghr cbs: tzz sjm: nfj xdc: xhn fjr fsx grx: tql drg: qlz vcg: cts jrt mrb cxc: lrb hzh mst vlb zcr: ppc gjm qsr ccb mzz: fdm cpg: mrb kxp zpp pqv xpf: tqt bjx: kxr pts qdh: szh zgd vqj zkf: mgk fcc: pdg bcj zlt: rhz grd kdj sns: scv kgf kmp: jkl zmg szt: tfb xqs mrb hxr: grx nvv zvl xtj ghr: hdr bbv: rpc zzk cqg khs: bqc xnd hsl zlp: hfb gnn: khl bfm rtn fjq sdv kmf: jkl fsx cbs pdh: xll vgk cdn vtk ffz: ldz vlb lcp: zxj lnd zbr qsp: vdr gfz gtr mlg tpt: dqh gql skk spm nqn jzd: xqt hph: zft gnb sdk: vsg ptp kjf ftl dvc: zlp htm djb dbk fdd: rzh gpf: qzq bhq rmb dbh rrv tht: pzh qdt tkt ckf hsb: ssm gvn pnv: tsh rhb: sld khj ggf jbc: chr mdg bxz xdv vkc bqz: qkt qmv xgx pjc: pnl zkv tqt sxg: xnx tqx fcc gjm mrv: vtt rzx znk dbc gmj lcc: pjv vrn xnq zlt prq: svb rzt jvz rjd: thk pbk kmr xcx xfp: phj sns hzz pjx rgg: vql bdg bnx sld zml: fvj tfp khl jgd: jgz sbg zmp lct: rxl bsc txf hfl: gdl xbv tsk: xgx dmd rhx: bvv hxl bnp: psg fbl qdv fsx hzt: kvb zmg zkb xpb rqz: mnp dzf zfj jgs qpd: lbs rcl: ksm qff: hqt dhd vmp mdr: gxg kjk ctj qlj: xcr fdr gnl ptk kgk: hgm jdb ctj kvc: jht qlp vrn lhx: mng zbr vjg vtx cdn: cbf xdb: kmf thq zmb fzs: tsk zcl nfz ndr dxc: ckq vql: nts cbf fdm: xbl ktf: kjf frm xgh jpt: lhb rpr mhc: zfj pmk sdk zgj sbx xjq: dbs kmf ppm: ssf bxd zhn cgp xxg: zbr rhc vdb pbf: fpj drg shf bds: cps dgb dxb shp: bjx kxp bvj nnk xqs: nlh bvk: fqg gft vbv sdt bzr: tsd xcs: bsg txv txb dqx: dtq pjc hpg kzk dxr: fvh vzs rzb pjz: zmj qfb xmp dzb: lrq dkx ftl fzj dbl: hfl cbf gdf crp bfp: fpn rnl skk plg qsl: xvx rjj: mhm tmn mkx qvb cts: nfj bbb: scj sld sqs: zng vnk fqt zkr flb qjm: lcn zcl zcp tgl pbj: ptk ccb: dfn frm scv fgq: vlb dps kbj ndt sjg: scv lcm dlb btv cqg: qtk dhl: gdm fsj phf: pnt dkm xqq zgn zxq: kql frr dzc zsd nzs: nfj xpf bnc: mhs dpg kmt: tsd rmb: xgr mfs gxp: tlg dhd sgb: skx hlx pgs: gvx vlb qnl: nvf tvg mgs fhp xcx mbz: lqr mtj: ptk cbk klp: vlx cfz: xxg llp zkv vhz: bms gkv vgr fms: gkr khl: kxp lml: cqg jdh fjk nxt dzf: sdh xrt: xqf rsz mhm lrd tql: dbj qpr: pbk zjr: qsz srv hdm mhp dcg nfz: bsv gzv ftn spj: sns dbj zpt: hph qfr: rrv slm vrg nsv zmb: fvk ctj: xrp cfv: skf kmr rnk kdt jpj: cbs chb ncn gmr rlv gmx xsh: jcc cnj lfd lch lxp hqx njs: jxn lkr fdr cps: cjq fcs vbc djv: xpb bmc ptt: nvf gkj pgg zzg: hcn jzj: zcp ndm xlk bnc fcs: dzf jlg: xkr qnk cqv vfx rnt: jzq lrb cnj nvf sxr: zqn hsb rdn xkk: rcl lzg vpr fcz: ksm vlx kdz ghv vgr: zpm jfd mzq: vrn xcr mzh: qfb cxs: znk zcp nvk xjf xxv: glg gvx mjb gbr kjt: rzh zfj pgt fjq: hqt bsc hqq qcp gnz: kjm fcz vzq pzk sxb: sgv pmk svl: hsl xgb lgx: xlk zsk qkt zst lst: ftl djv xrm xrp dnr ztx: jbl zpt tgt hmm: rzb kkf: jlh zzk nkv kfm fnj: jbn dnv qjr shx: bms rxl fjk gfc: qjg zkf pzh: nct qfx: vgk cgv fqx mhv fqf: vtv tsv rrn qlp cjd: lxc frk: spj dkg bmc rrt: bcm xbl: rlr jdh: bfm scg gxl ktd: mst cqv bxm nqj: czh gdd lhs rmr nxj: bxm hmg kqb xjc rcp: tvg zlh ltv xnz: fzb hjx: hfc nlj vmp: krj qbh zvs: cps qhm lft sgb skr: vjl xpz hmm krm fdc hfq jvn: vxp nxg jns msv prq ndm: rzk gdm mpb: smk srb kmr xsv: cbk jgg lnv rfx nmh: qbh rhn ztf pzk: fvk lqp rsz rlv: vmk ssg: dnk shv: khb kjk shj gmm bst: zzg dkn lft cnz hxt: scv dgb rxz bxp jvt: vgv rdt svl jpm bdg zgn qfv: gpj xcr xbv pqq zng: bms tmj ksn: dkc hgm cql vvx: plg tjp tfz zpj: mnl nzv qbb dxk rbq: svl xrm: nlc tqx vcp lft: cdn lhb: rpr ksj mhv gqs: rpv rrt dkc vng: znk dzr pzr nml dsg: nmx jmp spf hdl: tvv kdl hmb mnh hmg: tmj bmc: rbq mlk zsk: jbn fgz: zhn zgj phx: mdc rhs: psp lzg lsl mss: gvn bmj tmq: rcp lcp vcb fnj rnt vfj: fpt svx: sdh nlb zgn: tsd dlq: rfs jrt: qjg dkm: jjg kvs nzv: qcp zlp btc: fzc lpn: ghd vvx mgs mhp tch hpg zkr dft nkv: tjp qgl nvj: rcc tnc: lrq hln qqq vgk dlb kdm: dkg sth fvm fdv xkr: dbp njz lvk bhh: dsz dlb tkb qmc: pmf bdm jht mss hcj: kdt njj bxz: jrh vmb qtp: skx mbg ghm: vjl jvx: pzr gjm: gtr fjv mps: mcx rhd: xgg lhj jdh qnh htj: sjv qrl: fdm xqn vpd mmx sbx: sbr gmq hbf: rnk str gkj lnd: mrg gdd nvj mpp: scv jpt tnx sth jvl: pnn sxf scd: znq kxp rxl: bqm sjm mkv lhj chd: qff zpt bzs npk njd: nvj jfc gvx fpq sjn mqj: qpr sjm tfb pzd cln jvc: htj gbm: bqz xpf hqq sth: hks xgg: rvr gkj hdm mqr: ccr mdg lpf gzv gkv: mnf fvh jkd: jds phx nts btf: rhx xqr rzk vfh: gsg jbs xvq cfl bdm: lrp sjk rbm: jhm lfx: gvn zcb: msn pmg: vvv jff ksm xzb bnt: dcq qjx bxz hmj: vbt dgb xnf mhm: sbr xmn mqv tdn pnp: hrq dmc lhs fzd znr: szt jvl jgz shf: gvg rgp cnx: xpz gql jgz pfc rcc: ddx jzs: vmb plg dgc dzc vnp: rbq zgj tzz pkz: qhx jrk ptn zgn vfq lst xzg: lzg ncm gsl rlv dxh: pzd lkx: fms bjm gct mth: kmp kcg grd hcm: dxc tqm: vpr shf dlk dcv chr: fkb blr ztf: dqc bpf: skq shr btt hmj btv: tkz mbg qlz qgc: vzs vfx ccr pgg: jhr qbf: nsp hhp vqf rzb bfp grm msv clg: lqr czp rgp bsc: dbk rmk: hmg mxg flb vtj psz: jnh vbc jkd smx: cnz fdv nqn: mnl npm: jgg xnq mqv: lrq ffr: jxn kzx: rqx kql vqg kgf: lqr ntq: tbg lfx mzz skg qnt: rlr fjr mbh: cst kqt tcj dbz jvz: ccz mkb: ggf xdc sxn: rzt grm zfs: bgl ljk lqd: nkl xxm sqc jbl vdr: xgr hln: ssl vrg hzk vxg: cvh dpc lfl pqq nxt: lqv blr: mgx jvc shj: pdg mhv zmj bsf: cjd tsh szh hqx krt: gsl psp lzb jfv: plg hbp rfs: mdc cdr: zxt str snf pqb fpq: gxl tfz ffj lct qjr: vlq pnn tnt: xgv kxv prj xrz xnt lnr: dcs fms bxm gzb dnb: nmn xck fqg lcn cfj: bms pgs qdh rzt jjb: sld hrp: nkc bnx zrf xll slr: jlj hbc kdz nnp: xnd sjk sth hbg: vjg nxg nsm: ppd rfs tjm: cvv fcq rzv: kmt lrq gcl npm jdc: fkk zfz fvj mgh kzk: pns qjg fsj qfc: zfl gvn: bvg dlq xdd: fqg npk cjg rdh: rnk tdv nfz tzc: vjg ftf nkv jlh lxb: sqb qjg nkp: vsq scg hqq xjc dbp: qkt dpz dgc vqf: xsk xgd: ztx kbj vxz gfm: dsz khj lbx kvg: rlr jth xqt gzd btt tjz: sgb xnz vfj qhx qvb: tkb kjr kcg: jpt ggf fzj gdr: zxt rmq ccj jxv: rjd grm dnj csz hbt fpv: jlk zmb lqp xmn: pdh dmb sqq: nlh fms dbb: smx dnr tbg xzb gcn: gfc jhr mkx: cvk qsl cfp: rdz qsj slm ngn rts: mzq dbs sgk pnc: lsg hpv ncn csd: gnb ttr rdp bxm: rcm qnh fvx: zgx dtq rdh tgl fjv: vpd qlp: dnk csr: grx jfr kpf ndv lbt zbr: spm scd nxl: xhg lft sjk lhj: tlg tdg: qnh cts jvx txt: khj hdq: fnx xqn lnp xrz sqk bdg dbq: rsh bsv nrk: gpc lbx zgc rvs jsm kmk: kvx htm shl lpf htm: sqb glg: pns ckk svb hsx vsq: xvq mtc: sjv jvz djb hxl dxk vtj: cln qkn: mrg gkv mkv bmx dmd: hbf kmr ghm thh: srb kxr dbs: tkt ssf vxs: hpv rvd snd: qjr glg dxh dps jrh: cgl ktz: pzk lrd zpp: tmb zkv rxz: bmm xvm: mxq ndg xzg xgr xhh: pnl fsb hqx qqr: vsq hzh kjp ccr dhd: zmp vfq: svx nbb bdx mst: pnv hcj hlg: nmf jft xpq dnq nlb: djv ngn rmr: jfg jff: ghl psz cvv: jzq gpc: nsm jxn: dhz jsl: zqn bgs jnh sfj llp: mgk pbk xqr: trk nmx jgr btc mvd: gdr xdd qtb shk zvl: nlc qnt klp gdj: frd ptk lkr jhm rzh hhm: jvx hbp mgh bjx zgd lql: xpz xfn: bgj pgs sxn xhh tgh znr nkn: ngn bqd scv zjj nnk: nhf rqx qvs kqb: tgh qjx: dbk tjm fnn: jpj bhq dbv: hdn mxq sgc glq hrr: zzt pnl nvs skf sfj: rpr tkl: ghm dqc smk mrg bqz cgl: nlh hrr ckg: hbf zcl: bgj rkz: bfp htj lqv mhf dxd qxd: kmk knz klf tjp jkt: vmk hzm dqp: spj scj vkd zjp xcf: chl ldb bmx: mhb zgx qmt lgl: bfb nsv: jds pdg trm: vrc srb: bsp vmb gql: cqv zrd: lql pnv zkr: pfv qtb nmh qkt gnb: tmj fbl: sbr btt zcb rdb kvb: skg ndg qkc sgv: fbn dtx: bsp ndr: qgl zcn: qfc rnl: mqh ddx ldm: zhn qhj jff xzg lzb: dpc rhr: qsq pgt xhn lzg lrk: fzc rsh vzs qsz: zcp xhn: ptn ngm: rfl tkb jbg ckf zrx: jqs svb tkz: tzz rkg: skf sbg: kfm dnf czq: ldz sqs rqs frr msn: cnz ckq lqp: frm kql: lcn jnh: qdv ptk bbr: dkc nts ksc: ssm sxr dpk ppd rxx: dpc tkz nmb mtj vbc: mkn jns: jrh nkl qhf slm: kpf dss: dxh pzr dnv xck xsp: gxp lvk czh qbh vfz: mgk zmh shl: nfj ddx gcn thk: qgl dbc: mnf bcj: hgm tkb zkb: qfr xnd fpt kgf rns: lss cjm rsz vhp pxf: vmk zfc: dnf chl ktc cft ndm jtx: ksm dcv zcn tnx lch: mnf fbv gfv: lgl qfb hsb vfn lkv: pkd lfz hkm: mhp hrn xdq: rdt sgk txt znm bhh qtb: blr ldz: rvr fcq: vxp zrx dpz tgl: fqt bsn mnz: ttq jlf ndg qtj rqs: ltv szv lnj pzj vfx: pct rvp tnl: hbn hpg bsn qxd tsk xng: vtk qnt dcl: hks fvk tdc btx dkc: khg cbf kxv: ppd xvj vdk: plz sjv njz dmk: xrp ncm qrb zcr ghg fvh: vzs ppc: sfj cvh kvs: xzq dkg vbc bmj hdn: rxz qng: pgg hvb gdm: vkg gbq nbp: fvj bsc vkg dgc qng phj: ljk nlj gmv: xdc dkc fvm hlx bdd: czg sgk: dxc qtp mxr: spf gql kjp rmq: vds kgg zkv jpm: fcp fsn: bdd pfc: hfq ddk cfq: xhg tvj fsn pbf rgz: gfp hkm rcm hhp ptt hpg: ckp vkg qjt: mqh smv dhl xcx xgh: rvx mdv ffj: jqs vjg zlx tlp: lht bfq sgc hbc mcf: drq tqt pzr qsz dcs: jrh xph vnk mng lnd lhr: vxs qvg krt hnb fpj: xzq jjg qkc bjm: dtv cns: rnk gbr ccj: cxc fqg tlg lpp: jgl kjk lft mhs: lfz sjv vfd lvk: mhp fzn: xnz bbk dcv lfl gxg: xkk nkf: vfn rsz mkn bbb jmg: ccz lkb: cqg drq gct xvr gjf: hfl lzh nrq gvt hhr: dft qpr fzd dzr vrc kqc: pmf kzv cvk pqb: vds ltv fcx: tgh bsf hsx chd fbv jfr: mbz jht gqb: khg hcv nxl jtm jfc: rhn kgg crl: zbr xhq vsf czh zvz: kjp cvv rhx ksx: hzz dpb: lqr xtj jds gdl xgv: ncn pnk: cxz tzz bgs pxf qsr: fnx tgs bgs dxt: fbv stk znk pvk qdt: jkl spf: nvj ptd: fdd grx rdt sff cql: bcj fbn pmb: zrx fgc zzt bkq lhf: bxz znv vfz kbj hlx: fpt hvc: njz gkv phz: bgt vfn lss: kft pbj dxb gjd: crp dbz qfr bgl trh: sxb lgl tsd zzk: gfp nvs vtx rfl: xtm bzs: qgs gsg mjd vnr dgp: vxs xtx jlj rfx gmx bpd lpr: cpb dsz hcm mkv: ftn jgr: jqs lkq pqv bsq: nlh lql nsx: dsm gvg slx zqn sqc: vjg fsb shq: gft cnr dqb gvx fkb: khl rmg: kqj pqb trm tpd: ttr vzs srg zlx gfz: kvc jkt qxz qtm mqg: vbc xnf kgk hjk pdl: xph str xvp: jxn kmt bpd fht vds: rhl nrg: dxr qtk vxz znm: mhv mmx xpq: jkt dxd: kqb hbp: shq rpc: zxj vjm btc rzb crz dhz: zbq tcj: xnz rpv bgt: tqx gsg: chl jbl cjm: zbq xtx rhb qnk: xqs vxp jcc qbq: cfg rqk gbr xdz hqq: hqk kqb nks: qjx scg jbl fkb msv clv: gmq jzn: khs gfz qsr kjk qtm: ndg dkn: drg xnf qhj: zgj bqd xqn dsm rfn: rgx nbq: zrd jvc trf hdr zfl: mdc tgt: ddx dtv: jgz mjd smv mlk: jgl vkg: jlh lnt: hlr frk ddn hks gtd: ptp dlk dpc ghv: chb qtm gmx qgj: mdv qlp bcx qsl bcx: hcn bzx: gqs mss fbn dxb clg mqb: hph tfp lbf fqx: lht vbt bqd trt: knz mdg crz bvv hhp: xjf pjc kpq: vzq xnt xvj qtj jpl: qxz ngr qnt cbf jkd xdb zfj: fcc vkd: skq xmn pnx: ztf sxf kzj pvk kzj: zzt vgh xrp: jkl nkc: xpq ppc vvv rdn vzc: njj zgd cqv skg: dmb jzd dkx: ctj pzh ttr: srb kzj xvt: rcm dbq kdl ckg gzf: dmd hzh ckg pct: dds gkr ktc: csz vkc ghq dcv: gvg hfl xmp: lkr zfh: sdt gqn hdr gkr zzl pxb: nbb fcc gcl dkx lrz: kgg xgd hmb mxg spf zsd: fms cln zgx: zft dnj ddn: lrp mkq: nzt fnn nbc htv qqq: scj sgv lgl nml: cft smk rzt xpb: xtm bcj mjb: hpz bdp: fcs mth mlg cfp kcc: czp vnp dcv gpc hxl: qjg rcc vtt: dhl gfc pzj bfq: vll cxz rvs vcq: xnf kqc frd dpb gnp: qsj mmx qpd vfj zqn gvt: pkn rfx ndv bmr: nsm lnv npm jbs: nqn dds gqd: std nmn: txv kkm: htp vbb svx mmx vtq: jzq bsn crk pqv krj: mdj ntl: lzg hfc qzq vlx psz rnk: hxl ================================================ FILE: exm/aoc/2023/aoc_2023_25_questions.txt ================================================ --- Day 25: Snowverload --- Still somehow without snow, you go to the last place you haven't checked: the center of Snow Island, directly below the waterfall. Here, someone has clearly been trying to fix the problem. Scattered everywhere are hundreds of weather machines, almanacs, communication modules, hoof prints, machine parts, mirrors, lenses, and so on. Somehow, everything has been wired together into a massive snow-producing apparatus, but nothing seems to be running. You check a tiny screen on one of the communication modules: Error 2023. It doesn't say what Error 2023 means, but it does have the phone number for a support line printed on it. "Hi, you've reached Weather Machines And So On, Inc. How can I help you?" You explain the situation. "Error 2023, you say? Why, that's a power overload error, of course! It means you have too many components plugged in. Try unplugging some components and--" You explain that there are hundreds of components here and you're in a bit of a hurry. "Well, let's see how bad it is; do you see a big red reset button somewhere? It should be on its own module. If you push it, it probably won't fix anything, but it'll report how overloaded things are." After a minute or two, you find the reset button; it's so big that it takes two hands just to get enough leverage to push it. Its screen then displays: SYSTEM OVERLOAD! Connected components would require power equal to at least 100 stars! "Wait, how many components did you say are plugged in? With that much equipment, you could produce snow for an entire--" You disconnect the call. You have nowhere near that many stars - you need to find a way to disconnect at least half of the equipment here, but it's already Christmas! You only have time to disconnect three wires. Fortunately, someone left a wiring diagram (your puzzle input) that shows how the components are connected. For example: jqt: rhn xhk nvd rsh: frs pzl lsr xhk: hfx cmg: qnr nvd lhk bvb rhn: xhk bvb hfx bvb: xhk hfx pzl: lsr hfx nvd qnr: nvd ntq: jqt hfx bvb xhk nvd: lhk lsr: lhk rzs: qnr cmg lsr rsh frs: qnr lhk lsr Each line shows the name of a component, a colon, and then a list of other components to which that component is connected. Connections aren't directional; abc: xyz and xyz: abc both represent the same configuration. Each connection between two components is represented only once, so some components might only ever appear on the left or right side of a colon. In this example, if you disconnect the wire between hfx/pzl, the wire between bvb/cmg, and the wire between nvd/jqt, you will divide the components into two separate, disconnected groups: 9 components: cmg, frs, lhk, lsr, nvd, pzl, qnr, rsh, and rzs. 6 components: bvb, hfx, jqt, ntq, rhn, and xhk. Multiplying the sizes of these groups together produces 54. Find the three wires you need to disconnect in order to divide the components into two separate groups. What do you get if you multiply the sizes of these two groups together? --- Part Two --- You climb over weather machines, under giant springs, and narrowly avoid a pile of pipes as you find and disconnect the three wires. A moment after you disconnect the last wire, the big red reset button module makes a small ding noise: System overload resolved! Power required is now 50 stars. Out of the corner of your eye, you notice goggles and a loose-fitting hard hat peeking at you from behind an ultra crucible. You think you see a faint glow, but before you can investigate, you hear another small ding: Power required is now 49 stars. Please supply the necessary stars and push the button to restart the system. ================================================ FILE: exm/aoc/2024/aoc_2024.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the Advent of Code 2024 examples. -- -- Some programs work with both HAC and "full Ada" compilers like, -- GNAT some (titled *_full_ada.adb) work only with "full Ada". -- project AoC_2024 is for Source_Dirs use (".", "..", -- For the AoC_Toolbox package "../../../src"); -- GNAT's access to the explicit version of the HAT package. for Exec_Dir use "."; for Create_Missing_Dirs use "True"; type AoC_Build_Mode_Type is ("Debug", "Fast", "Fast_Unchecked"); AoC_Build_Mode : AoC_Build_Mode_Type := external ("AoC_Build_Mode", "Debug"); type AoC_Styles_Checks_Type is ("Level_0", "Level_1", "Level_2"); AoC_Styles_Checks : AoC_Styles_Checks_Type := external ("AoC_Styles_Checks", "Level_1"); for Main use ("aoc_2024_25.adb", "aoc_2024_24.adb", "aoc_2024_23.adb", "aoc_2024_22_full_ada.adb", "aoc_2024_22.adb", "aoc_2024_21.adb", "aoc_2024_20.adb", "aoc_2024_19.adb", "aoc_2024_18.adb", "aoc_2024_17.adb", "aoc_2024_16.adb", "aoc_2024_15.adb", "aoc_2024_14.adb", "aoc_2024_13.adb", "aoc_2024_12.adb", "aoc_2024_11.adb", "aoc_2024_10.adb", "aoc_2024_09.adb", "aoc_2024_08.adb", "aoc_2024_07.adb", "aoc_2024_06.adb", "aoc_2024_05.adb", "aoc_2024_04.adb", "aoc_2024_03.adb", "aoc_2024_02.adb", "aoc_2024_01.adb"); case AoC_Build_Mode is when "Debug" => for Object_Dir use "obj_debug"; when "Fast" => for Object_Dir use "obj_fast"; when "Fast_Unchecked" => for Object_Dir use "obj_fast_unchecked"; end case; Common_Compiler_Options := ("-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatwCijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ"); -- Don't quit, write ali/tree file even if compile errors Style_Checks_1 := ("-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens "-gnatye", -- Style: check e:end/exit labels present "-gnatytc"); -- Style: check t:token separation rules, c:comment format (two spaces) Style_Checks_2 := ("-gnatye", -- Style: check e:end/exit labels present "-gnaty2"); -- Style: check indentation case AoC_Styles_Checks is when "Level_0" => null; when "Level_1" => Common_Compiler_Options := Common_Compiler_Options & Style_Checks_1; when "Level_2" => Common_Compiler_Options := Common_Compiler_Options & Style_Checks_1 & Style_Checks_2; end case; Fast_Options := ("-Ofast", "-gnatn", "-ffunction-sections"); Fast_Unchecked_Options := ("-Ofast", "-gnatpn", "-ffunction-sections"); Debug_Options := ( -- "-gnateV", -- Validity check for parameters, GNAT > 4.6, redundant with -gnatVim ? "-gnatVa", -- Turn on all validity checking options "-gnato", -- Enable overflow checking in STRICT (-gnato1) mode "-g", "-fno-inline", "-fstack-check" ); package Compiler is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Compiler_Options & Debug_Options ; when "Fast" => for Default_Switches ("ada") use Common_Compiler_Options & Fast_Options; when "Fast_Unchecked" => for Default_Switches ("ada") use Common_Compiler_Options & Fast_Unchecked_Options; end case; end Compiler; Common_Linker_Options := ("-g", "-Xlinker", "--stack=0x20000000,0x200000"); -- ^ Absent that, GNAT-compiled programs using lots of recursion -- die with error code 16#C0000005# (Windows, Access Violation) -- - no Ada exception, no trace-back... package Linker is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Linker_Options; when "Fast" | "Fast_Unchecked" => for Default_Switches ("ada") use Common_Linker_Options & ("-s", "-Wl,--gc-sections"); end case; end Linker; package Binder is -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks for Default_Switches ("ada") use ("-Es"); end Binder; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-j0"); end Builder; end AoC_2024; ================================================ FILE: exm/aoc/2024/aoc_2024_01.adb ================================================ -- Solution to Advent of Code 2024, Day 1 ------------------------------------------ -- Historian Hysteria -- -- https://adventofcode.com/2024/day/1 -- Copy of questions in: aoc_2024_01_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_01 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 6; input_name : constant VString := +"aoc_2024_01"; n : constant := 1000; type List is array (1 .. n) of Natural; pair : array (1 .. 2) of List; procedure Read_Data is f : File_Type; begin Open (f, input_name & ".txt"); for i in List'Range loop Get (f, pair (1)(i)); Get (f, pair (2)(i)); end loop; Close (f); end Read_Data; procedure Shell_Sort (b : in out List) is i, j, step : Integer; step_size : array (1 .. 4) of Integer; stop : Boolean; temp : Integer; begin step_size (4) := 1; for pass in reverse 1 .. 3 loop step_size (pass) := 2 * step_size (pass + 1); end loop; for pass in 1 .. 4 loop step := step_size (pass); -- Do a straight insertion sort with 'step' as -- an increment instead of 1. i := step + 1; while i <= List'Last loop temp := b (i); j := i; stop := False; while j > step and not stop loop j := j - step; if b (j) > temp then b (j + step) := b (j); else b (j + step) := temp; stop := True; end if; end loop; if not stop then b (1) := temp; end if; i := i + step; end loop; end loop; end Shell_Sort; r : array (Part_Type) of Integer; procedure Do_Part_1 is score : Natural := 0; begin for i in List'Range loop -- Put (pair(1)(i)); Put_Line (pair(2)(i)); score := score + abs (pair (1)(i) - pair (2)(i)); end loop; r (part_1) := score; end Do_Part_1; procedure Do_Part_2 is score, count, n : Natural := 0; cache : array (1 .. 99_999) of Integer; not_counted : constant := -1; begin for i in List'Range loop cache (pair (1)(i)) := not_counted; end loop; for i in List'Range loop n := pair (1)(i); if cache (n) = not_counted then count := 0; for j in List'Range loop if pair (2)(j) = n then count := count + 1; end if; end loop; cache (n) := count; else count := cache (n); end if; score := score + n * count; end loop; r (part_2) := score; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; Shell_Sort (pair (1)); Shell_Sort (pair (2)); Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 2086478. -- Part 2: validated by AoC: 24941624. end if; end AoC_2024_01; ================================================ FILE: exm/aoc/2024/aoc_2024_01.txt ================================================ 57643 17620 19062 47340 11105 16109 72032 30050 16289 65967 42361 35795 45873 16124 16167 65832 57216 47340 15920 71163 22534 30837 38721 64603 27502 32313 17094 50986 84849 67526 20884 64392 21987 59516 39419 98547 10839 29910 77870 15917 94474 57604 29876 18768 72281 16109 52066 21561 11847 24044 83711 11404 47340 29941 54869 62664 63495 62664 87421 46184 12673 51492 21401 77546 13800 70131 35534 46986 51304 41199 51515 39683 25160 55295 39133 88509 68329 62664 56917 84849 68841 33033 27693 78397 82953 22601 47353 27226 70002 59980 74154 16109 86034 84849 95639 62349 45722 59516 69049 22317 51692 17620 39166 65967 30495 55388 81255 17869 60454 41199 26224 81511 74983 16124 55752 90759 22465 24501 57854 22943 94700 59516 83099 31049 26617 32773 23277 52176 34125 18754 61685 11874 49752 44170 82839 26115 28748 62664 19753 73220 76703 16124 41076 60454 94607 98100 88668 47340 56446 90759 93070 65832 25427 65524 51967 16964 23531 92947 44724 76864 32642 60237 54203 22536 62977 69799 31242 64392 94016 75284 55953 84849 35527 83890 54207 16964 44027 46184 82186 60112 72150 28927 68617 89252 57085 65832 18164 39683 28818 61894 94464 96385 73344 17681 76429 27054 25559 84215 24143 65907 12888 93195 33654 52859 13309 67042 90824 55187 42199 61494 99525 33401 60919 59516 14832 74668 83140 90759 68116 75402 35265 16124 30971 57216 84947 98547 35362 15902 98472 65832 32851 30050 47123 23601 37165 73599 64938 97672 39094 16964 32542 84849 70739 89107 59747 65832 51960 87068 75826 16109 96621 92566 80372 60656 15595 92864 17009 59796 87108 16124 70344 85636 12951 89107 25963 41199 60994 12246 26308 96930 58823 37556 18153 72254 20975 11570 42013 30141 53539 39683 40729 63401 10964 17620 76208 18768 55734 12636 29742 14160 40999 33033 61760 47123 57734 85993 32323 17620 53967 71169 41453 60454 53895 39683 99823 30156 12983 20098 71421 47829 76964 33049 82841 87433 55517 47340 75661 17620 22232 16081 36803 33033 83930 32773 54392 29132 67783 27226 78834 34040 46044 60454 97734 41199 16374 82621 23972 39787 80360 33654 48876 34378 11260 16124 53596 71313 60950 65832 37956 90734 87063 64392 66760 90734 24341 90734 13907 56662 39084 64270 30798 22591 30370 22943 57538 93797 41199 60454 79187 25199 43099 18768 13070 20881 39307 45484 89252 40350 94161 81798 91119 39683 97429 39599 64997 20578 32145 98547 13342 90759 82088 58672 61898 62664 72616 78897 17954 71652 58825 68383 44525 30658 28074 33033 17636 16124 94958 61724 48971 47340 85361 48120 82391 68794 69603 23741 64066 13582 65092 45163 49086 32773 42231 98547 56734 81797 76829 30156 99378 42745 59516 22285 18672 47123 68792 97672 46265 17620 28964 77566 14875 61068 95708 23528 38828 65832 56799 51315 40443 92737 64615 32773 27557 27226 89585 76621 67867 61305 28621 65979 88258 32773 73478 16124 98662 32773 38098 90759 76219 18768 23664 32773 70807 82839 64392 16109 39683 87325 47297 91952 25007 37572 90841 32773 82423 60454 56193 59516 83332 82839 17826 59516 95927 82839 62664 88503 33750 27771 51457 90759 47908 27341 67000 30050 66855 14734 20055 52372 60010 16109 30431 95964 12321 30156 53585 88159 55043 18768 20000 73383 28871 41199 82812 89107 13060 71616 70027 36310 80606 30050 55151 27226 63800 64392 35192 66432 78917 29589 92483 32773 10457 20728 70963 57216 67927 91119 36688 67070 93141 64392 93362 16124 81614 94940 81186 66565 56418 60166 64292 70331 43290 65832 10656 27226 38812 40982 33000 16124 18100 17109 37989 85483 14064 82711 14399 16964 22066 72604 49658 47123 29682 59516 59980 19363 91466 89107 70211 30342 35905 27226 67755 17620 75456 10664 54074 65832 23976 91119 22224 80267 78250 16081 53819 26866 99580 53011 49653 89107 13703 18768 39210 33033 13265 19583 70869 74044 42643 64392 97800 80872 33668 90759 62475 21888 64693 83264 31715 99185 83449 13990 33033 91104 39765 60517 93890 60670 23400 17620 92189 93768 63780 16109 73093 50153 13323 89107 69167 61436 48878 55630 13718 57216 27903 94896 69456 16109 46468 60454 52145 30596 20909 89107 22536 67083 80514 43159 98390 36556 78956 60454 23497 55983 15348 47123 61890 90734 89951 31879 20728 79394 49303 30713 30422 57216 73676 33033 49698 81919 76046 17620 45242 84849 25389 40202 32448 47299 59354 82839 70423 89252 89306 65967 59766 27268 37037 98547 65021 18895 54230 18768 43969 63446 50630 65832 54139 88509 85677 88746 47692 37399 21467 22536 83644 67594 21789 97672 13648 90759 28017 57216 74883 49798 16109 72646 46184 30050 36000 44597 33728 22536 44888 59516 11222 30050 36641 78012 42426 18768 93707 90734 82249 39683 86185 79158 63476 45090 52464 24645 33497 47340 51699 31223 67877 36634 16955 69854 49928 61017 16708 62664 91134 29644 24080 98547 16031 91119 49022 74628 88710 44253 22505 27651 22483 33033 10981 76873 74260 90620 53783 62664 67774 16124 56303 66706 87017 74124 25003 57216 54386 20728 55011 32773 35564 45090 43205 90759 90317 96125 65967 57216 27412 88804 26888 67612 50833 83419 90825 16964 68203 18108 51609 69179 69744 65832 56356 89107 89107 54941 88509 65832 92237 90734 44066 36406 80980 58864 98957 60659 22264 41199 60969 33654 17620 40115 90800 93572 62862 64392 27780 18768 66419 60454 70524 86222 26486 27226 72422 98298 90508 30050 28259 41199 14239 39683 21310 86711 35507 62664 77638 83310 10307 33033 71173 98232 39165 57216 92119 86108 52470 17765 18950 42325 55271 29040 25924 56949 55619 20728 48809 18768 32300 53100 60316 16153 44763 74270 25666 16964 81291 67521 60771 93797 81653 16964 67405 89107 79747 52151 47382 33033 29989 34981 50331 44690 17848 60454 89637 18768 98116 64392 80694 45090 95798 10999 78442 99645 45090 94611 23385 62664 86919 59516 71255 33033 82002 97672 89066 16109 98896 86008 27000 64545 99089 90734 13394 18768 20748 89107 88835 47340 87101 16109 61684 82505 87896 16081 97799 20728 63040 62664 85411 89107 34131 74658 65406 83937 91155 99556 65832 33674 81208 55861 85395 46184 16926 99827 35793 30050 12707 57216 67126 52814 92795 88509 91840 84607 54768 65833 52180 17819 53100 30156 73239 69810 49380 49485 80253 76262 53209 49131 11121 33033 44463 39683 53271 84849 69448 76937 36173 63218 60547 75774 54971 27226 44418 65832 66775 19905 71561 21069 32773 91318 76204 81715 98547 16081 24876 22287 33855 90759 28306 16554 30050 12914 21242 90734 19505 14213 54591 48135 72512 73973 10186 72386 98061 42401 83084 32773 38957 53473 56756 98547 36706 32773 82325 47179 24632 90734 55788 34600 21147 25888 97814 89467 76627 57216 83496 45700 35495 16109 57929 30156 44008 37332 68284 20370 58203 59516 33603 91682 91850 39247 55632 16124 48086 33894 96381 10569 77170 84849 39336 85833 74736 15527 92977 93797 74412 47340 99801 58501 51368 17620 68476 27226 21734 45090 85160 91119 67622 80512 33195 32773 99282 17620 40016 59575 70136 10061 60848 67727 79546 47112 71409 16964 48029 34780 75919 45090 26206 47123 26139 17620 98726 47340 75480 16333 60703 16081 56290 16109 20547 97672 85264 17620 72745 41885 11648 15733 89927 64392 41626 22536 40096 98547 11676 97594 38937 27226 95166 92683 45499 90759 44553 19438 58227 32773 78021 33033 31576 78113 25095 59274 62956 43830 87587 48890 37318 26768 31960 84849 44972 30050 47152 55462 48034 69405 99245 57216 51671 20728 31412 92094 19038 53100 30040 16109 81022 24270 28727 89381 63343 62053 44062 90734 52098 20786 32337 69696 10627 47340 86438 91119 11359 97672 79827 78893 50991 73474 41506 64392 64427 58282 30314 38013 55147 51690 24076 97672 55139 30156 84755 65832 77418 39683 65841 83092 89026 17102 43842 17620 69091 92274 45281 97447 76721 57216 85918 30383 75795 30156 25664 55704 97570 15961 52566 56257 56772 46184 66023 70725 70877 60352 58489 17620 97243 16081 90065 96590 15509 87622 16396 64392 52851 96477 27226 46960 90734 16124 69265 45713 52153 56385 62294 56305 60456 47123 22359 59516 72820 22831 16060 88509 48347 11949 93708 16109 40506 97672 34923 16152 82726 16124 75211 45090 42580 26606 55998 60454 36766 57216 49855 37173 95715 64233 88333 46280 43573 94103 58068 43319 65789 67256 26337 16081 41559 39630 94353 22943 60210 48776 31864 81825 43486 89107 89008 29137 40463 22547 69990 30050 43940 56443 77221 18768 75112 98547 10957 78948 74710 12120 59368 89107 32133 33654 75434 72998 14918 89107 78742 51635 47615 59414 92968 71551 34542 22943 38734 20291 10118 56801 43713 55518 82778 90734 90759 30050 65951 35684 60584 97672 74575 65365 79698 39683 25005 97672 87205 41199 61821 69895 91262 36850 59774 16124 25663 56501 59643 18768 91239 18768 67918 27226 90338 27226 46014 25578 83831 87690 61964 47340 93797 89252 31368 90759 25677 59638 98724 62664 45567 23553 58366 44041 97070 22943 42402 45061 30156 39747 21792 97672 88704 43711 86958 65967 87735 69189 46436 97038 67398 89243 25402 95547 75281 39683 10908 56544 13665 32898 14289 22943 78567 19318 58378 27226 70508 16670 27417 79914 39259 31265 75173 18768 67055 58536 94446 58240 13538 93924 47472 98146 73403 95703 80112 90734 53479 39683 68774 79739 15947 88002 98908 95443 34832 33654 49962 97672 37504 59516 75818 52244 61492 45090 46636 36056 60015 16109 91286 46184 37897 91119 92495 32773 86458 93797 39276 61612 22884 56365 71464 45090 32095 87760 54595 27226 24423 94229 22187 91119 82210 48731 19488 88509 65566 68008 77921 62589 17295 92247 91582 45090 24317 89107 68159 94508 81663 79967 78357 23724 36492 65832 53202 85336 64614 36692 13683 30156 46365 82672 61031 18768 52374 45090 24823 97672 90438 32489 14871 87616 65089 20993 37779 16124 39308 12698 32476 80660 61005 17620 22943 46184 87147 89107 25126 13389 16978 93342 60815 72087 84082 93797 73857 67867 18643 64984 90549 61047 30337 32773 62788 84849 36450 91530 18667 27226 31868 17135 34793 50284 87706 89107 24983 76729 49759 58359 88262 76480 75939 64392 19997 88556 62343 56462 45616 97672 45860 93888 68344 11535 55812 68813 58211 30050 57040 57926 60518 32773 71099 57155 24428 57216 54582 90308 55276 55066 58848 20728 75393 97672 11569 68342 88739 60454 92898 83347 91074 19081 68506 78420 28953 64392 40480 68489 78476 33654 52052 90759 38383 69088 94501 58424 11804 92541 88802 72137 14159 20700 31951 25669 71802 90759 51736 93797 40245 33196 76174 79841 65410 39683 77053 79537 47630 62664 22202 73334 67248 27226 18768 84849 75554 41199 91793 16109 15692 97672 78398 96505 64570 60454 85672 37902 32952 93797 72503 46027 62594 47340 14375 98105 98715 68010 68922 64392 14526 19785 47522 65951 58875 93129 90570 60939 36853 47817 72716 53863 64202 27240 18894 93797 16184 62664 18595 45090 68531 45090 29435 94452 48615 33033 90773 97672 65539 16964 37091 16124 85835 90759 93470 32585 71460 16320 67920 93186 71775 80052 31403 74944 68444 89107 57842 65832 12734 35998 14195 41229 63687 73891 19494 65967 28761 70887 64063 50742 90511 17620 47699 90759 99339 74495 64610 87080 30124 39683 44098 39683 92946 60454 63078 71049 69198 19253 81067 66283 27276 62664 60707 16124 92750 10833 15611 93797 80632 22536 81434 30050 31643 89107 12277 46282 94027 98547 65878 46619 88364 49881 66635 33033 70736 46184 94291 73977 96756 21223 74141 98354 99623 64392 47960 28999 67373 91119 44303 97672 24370 41607 41710 47340 27632 22536 14584 38508 12530 20728 99369 33033 47344 18768 69327 16541 51570 11107 29199 46184 16964 61946 95237 29761 22379 90759 85798 41199 25053 27180 61660 62664 41800 95048 16124 35616 63219 28270 81668 39683 75520 79737 99726 16081 38012 93797 38268 13109 92610 26416 27885 91119 21596 24011 67364 97672 75268 98704 91852 21659 62389 84076 10196 53612 92074 47123 29408 31697 21662 32940 13219 89107 13114 21512 48531 31805 71249 20665 67554 79621 86260 59516 87497 70849 16230 46623 38758 90759 84298 30050 84242 16124 95389 86465 77666 73820 79652 44579 83324 62664 53778 57216 43407 83484 99150 59782 16081 29507 73980 17620 63828 58641 47913 59516 67136 97390 97672 90734 98377 75087 36910 16109 61140 93797 69501 96356 91030 45251 37044 16124 71591 39683 87886 64392 51030 65967 12076 32551 82030 60454 28642 95851 45176 73711 44774 92783 35230 73053 85460 78500 95631 66420 77427 84991 26839 90759 98740 64392 55636 51814 14543 16109 71485 61007 78254 68306 28704 60454 ================================================ FILE: exm/aoc/2024/aoc_2024_01_questions.txt ================================================ --- Day 1: Historian Hysteria --- The Chief Historian is always present for the big Christmas sleigh launch, but nobody has seen him in months! Last anyone heard, he was visiting locations that are historically significant to the North Pole; a group of Senior Historians has asked you to accompany them as they check the places they think he was most likely to visit. As each location is checked, they will mark it on their list with a star. They figure the Chief Historian must be in one of the first fifty places they'll look, so in order to save Christmas, you need to help them get fifty stars on their list before Santa takes off on December 25th. Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck! You haven't even left yet and the group of Elvish Senior Historians has already hit a problem: their list of locations to check is currently empty. Eventually, someone decides that the best place to check first would be the Chief Historian's office. Upon pouring into the office, everyone confirms that the Chief Historian is indeed nowhere to be found. Instead, the Elves discover an assortment of notes and lists of historically significant locations! This seems to be the planning the Chief Historian was doing before he left. Perhaps these notes can be used to determine which locations to search? Throughout the Chief's office, the historically significant locations are listed not by name but by a unique number called the location ID. To make sure they don't miss anything, The Historians split into two groups, each searching the office and trying to create their own complete list of location IDs. There's just one problem: by holding the two lists up side by side (your puzzle input), it quickly becomes clear that the lists aren't very similar. Maybe you can help The Historians reconcile their lists? For example: 3 4 4 3 2 5 1 3 3 9 3 3 Maybe the lists are only off by a small amount! To find out, pair up the numbers and measure how far apart they are. Pair up the smallest number in the left list with the smallest number in the right list, then the second-smallest left number with the second-smallest right number, and so on. Within each pair, figure out how far apart the two numbers are; you'll need to add up all of those distances. For example, if you pair up a 3 from the left list with a 7 from the right list, the distance apart is 4; if you pair up a 9 with a 3, the distance apart is 6. In the example list above, the pairs and distances would be as follows: The smallest number in the left list is 1, and the smallest number in the right list is 3. The distance between them is 2. The second-smallest number in the left list is 2, and the second-smallest number in the right list is another 3. The distance between them is 1. The third-smallest number in both lists is 3, so the distance between them is 0. The next numbers to pair up are 3 and 4, a distance of 1. The fifth-smallest numbers in each list are 3 and 5, a distance of 2. Finally, the largest number in the left list is 4, while the largest number in the right list is 9; these are a distance 5 apart. To find the total distance between the left list and the right list, add up the distances between all of the pairs you found. In the example above, this is 2 + 1 + 0 + 1 + 2 + 5, a total distance of 11! Your actual left and right lists contain many location IDs. What is the total distance between your lists? --- Part Two --- Your analysis only confirmed what everyone feared: the two lists of location IDs are indeed very different. Or are they? The Historians can't agree on which group made the mistakes or how to read most of the Chief's handwriting, but in the commotion you notice an interesting detail: a lot of location IDs appear in both lists! Maybe the other numbers aren't location IDs at all but rather misinterpreted handwriting. This time, you'll need to figure out exactly how often each number from the left list appears in the right list. Calculate a total similarity score by adding up each number in the left list after multiplying it by the number of times that number appears in the right list. Here are the same example lists again: 3 4 4 3 2 5 1 3 3 9 3 3 For these example lists, here is the process of finding the similarity score: The first number in the left list is 3. It appears in the right list three times, so the similarity score increases by 3 * 3 = 9. The second number in the left list is 4. It appears in the right list once, so the similarity score increases by 4 * 1 = 4. The third number in the left list is 2. It does not appear in the right list, so the similarity score does not increase (2 * 0 = 0). The fourth number, 1, also does not appear in the right list. The fifth number, 3, appears in the right list three times; the similarity score increases by 9. The last number, 3, appears in the right list three times; the similarity score again increases by 9. So, for these example lists, the similarity score at the end of this process is 31 (9 + 4 + 0 + 0 + 9 + 9). Once again consider your left and right lists. What is their similarity score? ================================================ FILE: exm/aoc/2024/aoc_2024_02.adb ================================================ -- Solution to Advent of Code 2024, Day 2 ------------------------------------------ -- Red-Nosed Reports -- -- https://adventofcode.com/2024/day/2 -- Copy of questions in: aoc_2024_02_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_02 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2024_02"; r : array (Part_Type) of Integer; data : array (1 .. 100) of Integer; last : Natural := 0; function Check_with_Hole (hole : Natural) return Boolean is cols : Natural := 0; i, i1, d1, d2 : Integer := 0; begin for col in 1 .. last loop if col /= hole then cols := cols + 1; i1 := i; i := data (col); d2 := d1; d1 := i - i1; if cols >= 2 and then abs d1 not in 1 .. 3 then return False; end if; if cols >= 3 and then d1 * d2 < 0 then return False; end if; end if; end loop; return True; end Check_with_Hole; procedure Read_Data is f : File_Type; is_safe_part_2 : Boolean; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop last := last + 1; Get (f, data (last)); if End_Of_Line (f) or End_Of_File (f) then if Check_with_Hole (0) then -- Report is safe without removing any level. r (part_1) := r (part_1) + 1; r (part_2) := r (part_2) + 1; else is_safe_part_2 := False; for c in 1 .. last loop if Check_with_Hole (c) then is_safe_part_2 := True; exit; end if; end loop; if is_safe_part_2 then r (part_2) := r (part_2) + 1; end if; end if; last := 0; -- Clear data (report). end if; end loop; Close (f); end Read_Data; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 332 -- Part 2: validated by AoC: 398 end if; end AoC_2024_02; ================================================ FILE: exm/aoc/2024/aoc_2024_02.txt ================================================ 48 51 52 53 52 86 87 88 91 91 22 25 28 31 32 36 65 66 68 69 71 72 75 82 39 42 41 44 47 20 21 22 19 20 22 23 22 25 26 27 29 31 34 33 33 54 57 59 61 58 59 60 64 17 19 20 22 25 26 24 31 86 88 90 91 92 92 93 95 23 25 25 28 26 56 57 59 60 61 61 62 62 73 75 76 76 79 83 10 13 16 16 18 21 23 30 43 45 49 52 55 58 59 61 69 72 76 77 75 6 9 11 14 18 18 72 74 77 81 84 86 87 91 18 19 22 26 29 32 39 2 5 8 13 16 17 67 70 72 79 78 17 18 23 26 26 68 70 73 79 82 86 71 72 73 79 81 86 14 13 14 17 20 22 25 27 70 67 70 71 74 71 84 83 84 87 88 88 29 27 30 31 32 36 80 78 79 80 82 87 45 42 44 46 49 46 47 49 41 38 39 41 38 41 42 41 69 66 64 65 65 87 86 89 91 89 92 96 30 29 30 32 29 32 37 83 80 80 83 86 87 89 90 56 55 55 57 56 50 47 49 51 51 54 54 8 7 7 10 11 15 15 14 14 15 16 18 21 26 24 21 25 28 31 33 35 36 34 36 37 41 38 43 40 44 46 46 87 84 86 90 94 34 31 34 36 40 41 48 57 55 57 60 66 68 71 73 42 41 46 48 50 49 48 46 53 56 56 86 83 85 87 92 96 67 64 70 72 78 56 56 57 58 61 63 54 54 55 57 59 57 73 73 75 77 79 81 81 30 30 31 33 36 40 64 64 65 66 68 70 73 80 55 55 53 55 58 60 63 80 80 77 80 83 86 85 55 55 56 59 58 59 61 61 31 31 32 30 34 38 38 37 40 46 75 75 76 79 81 81 83 86 70 70 71 71 72 69 13 13 15 18 18 21 21 22 22 25 28 28 32 72 72 75 76 76 83 65 65 69 72 75 76 77 80 43 43 46 48 52 51 21 21 22 24 28 30 30 55 55 59 61 63 66 69 73 13 13 16 17 21 27 61 61 64 66 68 74 76 73 73 74 79 80 79 22 22 25 27 30 37 37 69 69 70 75 79 80 80 86 89 95 29 33 35 36 39 42 45 62 66 69 71 72 75 78 77 31 35 36 37 38 38 53 57 60 62 65 68 69 73 45 49 50 51 53 54 55 61 37 41 43 41 42 44 47 49 87 91 93 90 91 93 92 21 25 26 23 26 28 28 10 14 13 15 18 21 25 13 17 20 22 23 20 23 30 72 76 76 77 78 19 23 26 26 24 80 84 84 85 85 39 43 46 46 50 9 13 15 16 16 18 24 81 85 88 90 93 97 98 37 41 43 47 45 24 28 32 35 36 39 39 40 44 45 49 51 52 56 42 46 50 53 56 63 4 8 14 16 17 20 22 23 30 34 40 42 40 42 46 47 48 50 57 57 69 73 78 81 85 41 45 47 53 59 57 63 64 65 68 78 83 86 88 90 92 90 38 43 46 49 50 50 15 20 21 23 26 29 33 22 27 29 30 36 69 74 76 79 82 84 83 86 7 14 11 14 13 19 26 25 28 28 67 74 75 77 76 80 60 67 68 66 69 71 76 76 83 85 86 88 88 89 78 84 84 85 87 90 91 89 15 21 21 23 25 27 28 28 63 69 69 71 73 74 78 57 64 64 65 72 39 46 47 50 51 55 56 59 80 86 89 91 95 97 94 4 11 15 16 16 5 11 13 17 21 56 61 64 66 67 71 73 78 9 14 17 20 27 30 32 80 86 87 92 91 64 70 72 75 82 82 23 30 33 35 42 46 54 61 64 67 72 79 90 88 85 84 87 96 94 92 90 87 84 84 57 56 54 52 50 49 48 44 51 49 46 43 42 37 25 22 19 21 20 17 14 13 55 53 52 49 51 50 53 6 4 7 4 4 20 19 16 17 16 14 10 79 76 73 70 73 71 65 94 91 91 88 87 84 67 65 63 62 59 59 62 18 16 14 14 11 11 55 53 51 50 47 46 46 42 39 37 34 33 33 27 54 51 47 46 43 31 30 26 25 26 43 40 39 35 34 34 98 97 94 90 89 86 82 79 78 76 72 70 68 61 42 41 40 37 34 27 24 30 28 25 22 15 17 80 78 76 69 68 67 67 57 54 49 48 46 42 82 81 80 74 73 70 68 61 12 13 11 9 7 44 46 45 43 45 75 78 77 75 75 66 67 64 63 59 84 85 82 81 78 76 75 70 57 58 60 58 55 54 53 52 52 53 54 52 55 82 85 83 80 81 79 77 77 25 27 26 23 24 23 20 16 53 56 53 50 51 46 87 90 90 87 84 82 14 17 14 13 13 15 84 87 86 86 86 24 26 25 25 23 20 17 13 26 29 28 27 26 23 23 16 74 75 71 68 66 64 96 97 94 91 87 85 87 56 59 58 54 54 65 67 66 62 58 67 70 66 65 63 62 57 84 86 83 76 73 71 58 59 56 53 50 45 48 86 87 82 79 79 28 31 29 24 20 84 86 81 80 74 90 90 89 86 83 80 79 8 8 7 5 4 3 5 29 29 28 26 24 23 20 20 41 41 38 35 34 31 30 26 54 54 53 50 45 82 82 79 78 77 79 76 96 96 93 90 88 89 90 65 65 64 62 65 64 64 11 11 13 10 9 8 6 2 34 34 37 35 30 8 8 8 7 6 5 38 38 38 36 37 16 16 16 14 13 10 10 16 16 14 14 12 8 70 70 67 65 65 59 51 51 50 46 43 41 45 45 43 39 41 75 75 73 70 68 67 63 63 83 83 81 77 75 71 68 68 64 62 59 52 99 99 97 92 91 90 47 47 41 38 41 66 66 64 62 61 56 56 94 94 87 84 80 73 73 71 64 62 60 53 18 14 13 12 10 9 84 80 78 76 74 71 69 71 87 83 82 80 77 74 74 54 50 47 45 42 40 38 34 24 20 18 15 9 60 56 53 55 52 51 47 46 47 50 46 42 39 37 38 38 54 50 48 47 50 46 77 73 76 74 73 71 69 63 53 49 47 46 45 45 44 19 15 13 13 11 8 6 7 46 42 40 40 39 36 36 96 92 92 91 87 27 23 23 22 19 14 93 89 87 84 83 79 76 75 62 58 57 54 50 53 98 94 91 87 86 86 74 70 67 63 60 56 82 78 75 71 69 68 65 59 51 47 45 44 37 36 72 68 66 60 59 60 62 58 57 52 50 50 35 31 24 21 17 72 68 65 62 57 52 94 87 86 84 83 82 99 94 91 90 88 86 87 40 35 32 31 30 30 95 90 88 87 83 90 84 81 78 76 74 71 66 62 57 56 58 57 56 53 29 23 24 22 25 87 81 78 79 79 16 9 8 9 8 4 23 16 19 16 14 13 7 80 73 70 67 67 65 88 81 79 77 75 75 78 25 19 19 18 16 16 76 69 68 67 66 66 64 60 26 19 18 17 17 10 26 21 19 15 13 47 40 36 35 37 92 87 83 81 79 77 76 76 42 35 34 30 28 27 23 31 24 21 17 16 13 11 6 73 67 66 63 61 59 53 52 58 52 50 45 44 46 31 24 17 14 11 11 32 26 21 20 17 14 10 45 40 34 33 31 28 21 61 62 64 67 70 72 70 29 30 32 34 34 89 90 92 93 97 26 28 31 32 35 42 88 90 87 88 91 93 96 99 68 71 74 76 77 74 71 83 85 84 85 85 57 58 59 57 61 27 30 32 35 33 34 37 44 59 60 63 63 66 67 76 78 79 82 84 84 85 82 44 47 50 50 53 54 55 55 23 25 25 28 32 11 14 17 17 20 27 49 51 54 55 56 60 63 52 55 57 61 60 35 36 38 42 44 44 9 11 15 18 19 21 25 78 81 82 86 89 95 54 56 61 63 66 69 86 89 96 99 96 31 34 35 37 38 44 45 45 70 71 76 78 81 82 83 87 29 31 33 38 39 40 41 48 68 66 68 69 70 84 81 82 84 87 89 87 72 70 72 75 75 18 15 17 18 22 8 7 10 12 13 16 19 24 7 6 9 6 7 61 58 60 63 61 63 62 52 49 52 55 56 54 56 56 77 76 77 79 76 78 82 72 69 66 67 74 35 34 35 37 37 38 59 58 58 59 56 51 49 49 52 52 49 48 48 51 54 56 60 41 40 42 43 43 46 49 56 81 79 83 85 86 89 90 93 92 96 97 99 97 35 32 33 34 38 38 4 2 3 7 8 11 14 18 45 42 46 47 50 57 56 53 54 57 64 65 67 66 68 69 72 79 82 80 45 44 47 50 52 59 61 61 14 13 20 23 27 51 49 50 53 54 60 62 69 80 80 82 84 87 71 71 73 75 76 79 81 78 39 39 42 45 45 68 68 70 73 74 78 68 68 70 72 79 89 89 88 91 92 93 89 89 90 87 89 91 94 92 21 21 22 24 22 23 24 24 46 46 47 44 45 48 50 54 17 17 15 16 17 23 79 79 79 82 83 85 44 44 46 46 47 48 45 96 96 96 98 98 3 3 3 6 8 12 5 5 8 8 11 14 21 78 78 81 85 88 90 3 3 7 10 12 15 13 15 15 19 20 22 23 26 26 9 9 10 14 17 21 13 13 17 18 19 25 14 14 19 20 21 86 86 91 94 95 93 57 57 58 63 63 1 1 4 7 12 15 16 20 60 60 63 66 71 76 9 13 16 19 21 24 52 56 58 61 63 64 62 77 81 84 86 89 89 9 13 14 17 20 21 25 60 64 65 67 68 69 70 76 30 34 33 36 39 42 45 46 88 92 93 96 95 94 1 5 4 5 6 6 57 61 63 66 69 71 68 72 51 55 53 54 61 20 24 25 25 28 31 34 37 66 70 70 72 70 91 95 96 96 96 53 57 59 62 64 64 68 4 8 10 10 12 19 43 47 51 53 55 58 49 53 55 56 60 61 64 62 28 32 36 39 39 79 83 84 88 90 94 48 52 54 56 60 66 71 75 76 81 82 39 43 50 52 50 39 43 44 50 53 56 59 59 40 44 46 47 50 56 60 42 46 49 55 60 21 27 29 31 32 33 34 27 32 33 36 37 34 68 75 76 78 78 3 10 11 14 17 18 19 23 5 10 11 13 16 22 17 24 26 28 30 32 30 31 30 36 37 35 34 34 40 38 40 40 84 90 91 93 94 92 96 1 6 3 4 7 8 10 16 58 63 66 68 70 73 73 74 61 68 68 70 71 70 3 10 12 12 13 13 8 14 16 16 17 20 21 25 76 82 85 85 86 92 3 8 10 13 14 15 19 21 47 52 53 56 60 58 85 91 92 93 94 98 99 99 74 80 81 82 83 87 90 94 77 83 87 89 90 95 54 59 61 63 66 73 74 77 41 48 49 56 54 68 74 77 80 87 87 13 18 24 26 30 15 20 23 26 33 36 43 40 38 35 32 30 28 30 56 53 52 50 47 45 42 42 93 92 91 90 89 85 22 19 16 14 12 9 4 40 37 34 33 31 32 30 28 37 34 35 33 31 32 61 58 61 60 57 57 19 17 14 11 13 11 8 4 85 84 81 80 83 81 79 74 17 15 15 13 12 11 10 9 76 74 73 73 71 68 69 22 20 18 17 17 14 11 11 75 73 71 71 67 94 91 90 90 87 86 84 77 29 26 22 20 19 62 61 59 58 56 52 55 75 73 70 68 64 64 23 20 17 13 12 8 79 76 75 72 70 66 59 39 36 34 31 24 21 36 35 34 28 25 22 25 80 78 77 76 73 68 68 22 19 17 15 10 8 4 80 78 76 71 68 67 61 81 83 82 79 77 75 74 71 27 30 28 25 22 19 18 19 16 18 16 15 14 12 12 51 53 50 48 44 51 54 52 49 43 15 16 14 17 15 13 11 8 68 69 72 71 68 67 70 19 22 23 21 20 20 16 18 16 19 16 12 38 40 38 35 36 33 30 23 76 78 75 74 74 71 68 19 21 21 19 16 14 17 59 60 60 59 58 58 33 35 33 31 31 28 26 22 32 35 35 33 27 57 58 54 52 49 46 43 40 34 35 34 30 29 26 28 52 55 52 48 48 49 50 48 45 44 40 38 34 40 42 39 37 35 31 30 23 74 75 73 70 67 64 58 55 15 18 16 11 9 10 36 37 36 34 32 31 25 25 81 82 80 73 69 89 91 88 86 79 76 69 20 20 17 16 15 85 85 84 82 81 78 79 63 63 62 60 59 59 87 87 84 81 77 36 36 35 33 32 31 25 62 62 64 61 60 57 55 58 58 55 58 61 36 36 35 32 35 35 36 36 34 32 33 29 93 93 92 93 87 33 33 30 30 27 88 88 87 86 86 87 95 95 92 92 92 35 35 35 32 28 59 59 56 56 49 69 69 67 63 62 61 14 14 10 9 7 6 3 5 72 72 70 69 65 64 64 73 73 72 69 65 62 61 57 47 47 46 42 36 65 65 64 61 58 52 50 37 37 30 28 26 28 89 89 87 82 82 19 19 17 14 7 6 2 24 24 22 21 15 8 44 40 39 38 35 72 68 65 64 67 46 42 39 38 36 33 32 32 88 84 81 80 78 77 73 90 86 83 80 79 76 70 49 45 42 39 41 40 95 91 90 91 92 34 30 31 30 27 27 46 42 41 44 41 40 36 84 80 77 78 73 29 25 25 22 21 20 19 16 79 75 75 73 71 74 64 60 58 55 55 54 51 51 83 79 77 74 74 72 71 67 86 82 79 79 77 75 69 44 40 36 33 30 28 27 52 48 47 43 40 43 38 34 30 27 25 25 40 36 33 29 26 22 67 63 61 59 55 49 94 90 87 82 79 78 75 48 44 42 37 35 34 37 61 57 54 47 45 45 94 90 87 82 78 60 56 53 50 43 38 88 81 78 75 74 71 98 91 90 89 88 91 92 85 83 81 79 77 74 74 30 23 20 19 17 13 37 32 30 27 25 24 19 66 59 57 56 57 55 54 90 84 83 86 85 83 84 16 10 9 12 11 10 10 68 63 60 57 58 55 51 91 86 83 84 79 36 29 29 27 26 49 44 44 42 44 87 82 79 76 76 73 73 48 41 38 38 36 33 32 28 23 17 14 13 10 10 4 80 74 70 68 65 64 58 57 53 52 51 52 25 20 17 14 13 9 8 8 47 40 37 33 32 28 76 69 65 64 63 60 57 52 40 35 34 27 26 23 22 24 19 18 15 12 6 8 73 66 64 61 58 51 51 98 91 86 84 82 81 77 68 62 61 54 51 48 41 24 28 32 33 35 38 40 40 10 10 12 10 13 16 95 92 90 86 84 82 80 81 33 37 40 44 42 83 80 78 77 73 70 65 71 72 75 76 79 80 85 11 6 4 3 2 1 62 66 69 70 73 75 57 60 62 69 70 73 74 80 58 61 58 54 54 92 93 92 89 87 86 86 28 32 36 37 40 44 38 40 40 42 40 83 77 76 73 68 66 63 60 40 41 44 46 48 48 91 87 84 87 85 85 1 1 8 10 8 9 9 10 14 16 21 91 92 93 96 97 94 95 95 45 42 45 47 50 54 45 50 51 52 53 55 58 56 26 23 27 28 31 33 35 35 86 89 88 87 86 84 77 22 22 24 25 26 29 30 36 33 34 38 39 40 41 42 41 45 44 45 47 47 49 50 50 42 39 38 34 33 31 25 11 10 9 7 2 1 1 18 17 16 10 9 7 51 46 42 39 38 37 34 42 43 43 41 34 44 42 46 49 47 28 24 21 19 20 17 11 11 15 17 20 20 25 78 72 69 63 62 61 60 60 40 44 47 49 50 50 53 17 22 25 28 32 29 38 34 33 33 34 80 78 76 76 76 69 65 64 59 56 55 55 3 8 10 12 15 19 21 21 4 1 1 3 5 7 8 11 97 97 96 93 91 88 85 82 26 27 34 35 33 57 57 58 61 63 70 72 76 20 22 20 21 20 17 16 16 59 63 61 62 64 67 68 72 37 39 37 39 42 44 46 47 39 33 32 29 28 24 24 52 46 43 42 39 36 38 38 76 73 72 71 73 44 41 44 47 51 52 57 46 43 40 37 31 52 52 52 54 60 24 31 32 32 34 35 20 20 23 26 27 27 29 31 41 43 44 46 49 53 13 19 19 22 25 31 62 58 57 55 53 56 57 53 51 54 54 58 79 75 71 69 69 33 33 31 29 28 25 22 22 84 80 73 70 68 67 65 61 42 40 41 43 49 50 52 53 23 23 25 27 29 31 33 21 22 18 16 14 8 97 93 92 93 91 90 78 82 88 90 90 58 52 49 51 48 47 40 75 75 78 76 71 29 28 26 24 18 16 14 7 51 55 52 54 59 23 26 21 19 22 36 36 36 37 39 37 76 70 69 69 66 65 63 65 69 71 72 73 72 72 41 41 40 34 32 30 24 48 44 41 39 37 85 83 86 89 90 90 73 79 82 83 86 88 91 95 2 7 8 12 14 17 19 21 5 5 6 8 9 12 12 63 63 64 71 74 77 77 18 16 18 19 25 27 29 34 77 77 74 73 70 68 70 7 11 16 19 16 27 26 33 36 37 37 44 42 41 39 41 38 94 95 94 93 86 85 83 77 77 78 75 78 78 83 79 78 78 75 30 32 31 25 22 21 20 14 13 16 15 13 10 6 17 21 23 26 32 33 48 52 49 50 53 92 89 87 84 82 81 81 68 64 62 56 54 51 54 41 43 40 37 35 34 30 29 27 30 26 31 28 29 28 30 35 22 24 25 26 28 29 32 31 62 65 61 58 55 53 49 67 74 78 80 82 85 88 93 23 21 22 24 24 23 93 90 88 85 85 83 78 56 62 61 64 65 70 54 61 62 63 65 68 66 66 84 81 80 76 75 72 69 65 71 71 70 67 68 68 33 33 35 38 41 45 48 49 32 29 35 36 37 40 37 52 58 61 62 62 60 21 18 18 21 26 81 81 83 87 87 79 79 78 79 82 83 86 84 94 94 91 88 87 85 82 75 92 88 87 85 83 81 78 78 30 30 28 27 26 26 23 26 40 36 32 30 29 59 59 62 65 65 66 66 39 46 49 50 50 50 13 13 13 11 8 1 3 6 7 10 7 10 14 76 77 74 71 71 68 70 30 27 29 26 28 95 95 94 90 86 35 36 34 32 29 24 22 18 24 27 28 31 34 36 35 34 46 46 48 47 54 81 74 74 73 72 68 54 52 53 57 59 60 63 66 41 39 42 41 37 31 29 32 30 32 32 77 73 70 63 58 19 16 18 23 26 30 15 18 19 17 20 26 26 30 32 36 37 44 43 46 48 47 51 78 80 83 84 85 92 4 9 11 12 13 15 17 60 61 63 67 70 72 72 41 37 36 36 32 43 41 39 37 35 30 32 21 25 26 31 35 21 22 23 24 31 31 81 86 93 96 95 89 89 92 95 99 98 63 62 65 63 65 67 66 68 62 59 60 59 56 53 49 26 27 25 22 19 13 12 12 86 89 88 84 82 80 19 19 20 27 30 32 37 56 59 61 63 63 65 68 72 64 71 74 73 74 76 79 83 17 11 9 7 6 1 4 25 19 18 16 14 12 8 2 85 81 78 77 73 25 25 23 21 17 20 52 51 49 47 44 42 38 60 56 53 53 52 52 21 23 25 23 20 23 21 21 18 14 12 10 7 24 26 24 21 18 18 15 14 73 68 66 64 62 58 46 49 56 58 60 62 66 47 54 56 58 58 33 33 32 35 31 91 86 84 83 81 84 6 8 9 10 12 18 21 22 57 53 52 49 44 82 78 77 77 70 42 43 42 42 38 67 65 64 62 60 91 93 94 95 97 99 85 86 87 88 91 94 36 34 32 31 28 25 23 22 20 18 16 13 10 7 88 91 94 96 97 92 93 95 96 97 23 24 26 29 32 35 94 91 89 88 86 45 44 41 40 37 36 34 32 98 95 92 89 86 84 74 71 69 68 65 64 63 60 24 26 27 29 30 31 23 20 18 17 16 15 13 11 92 91 89 88 85 83 81 80 86 89 91 94 96 37 36 34 33 32 31 10 12 15 17 19 22 23 55 53 50 47 46 43 42 22 19 16 13 12 10 8 7 36 38 41 44 45 48 39 37 36 34 32 78 80 81 82 85 87 89 57 58 59 60 63 72 69 67 66 64 71 74 76 77 80 81 83 86 39 40 43 44 47 48 51 38 37 34 31 29 26 25 23 4 7 9 10 12 30 28 26 25 24 22 21 24 25 28 30 31 32 49 47 46 44 43 41 40 45 48 49 50 51 52 54 43 45 48 49 50 53 55 64 61 59 57 55 54 52 51 40 41 42 45 47 50 51 52 43 41 39 37 36 34 69 68 65 64 61 60 4 7 9 12 13 35 34 33 32 30 28 25 55 54 53 51 48 59 61 62 65 66 67 70 71 81 80 77 76 75 72 86 85 83 80 78 76 75 73 94 92 91 89 88 95 93 92 90 88 85 82 80 73 75 77 78 79 43 41 38 37 35 34 32 15 16 17 20 21 24 28 27 24 23 20 17 14 60 57 54 53 50 47 44 74 72 70 68 66 63 60 60 61 63 64 67 70 72 73 77 78 79 82 85 87 24 21 20 18 17 16 14 35 34 33 31 28 27 29 28 26 25 23 29 31 32 33 36 37 40 42 59 62 65 67 69 70 68 65 63 61 58 66 69 72 75 77 78 79 81 97 95 93 92 91 46 45 44 42 39 37 36 35 46 44 43 41 38 35 17 14 13 12 9 6 5 6 9 10 12 13 27 24 23 22 19 17 16 15 78 76 75 72 69 66 65 11 10 8 7 5 66 68 69 70 71 73 74 82 80 79 78 75 72 71 68 99 96 94 91 89 57 55 53 51 48 46 43 42 10 11 13 16 19 37 40 41 43 46 48 51 5 6 7 8 9 12 83 84 87 88 91 94 96 98 76 75 74 72 71 69 68 11 14 16 17 20 48 47 45 42 41 39 37 34 11 14 15 17 18 19 64 61 59 56 53 51 50 68 66 63 62 61 24 26 27 30 31 34 37 38 71 73 75 78 80 82 85 37 39 40 41 42 44 45 48 22 23 25 26 28 31 32 37 34 32 31 28 26 27 30 32 33 43 44 47 49 52 54 55 49 46 45 44 43 42 94 92 91 89 86 83 82 31 32 34 35 36 37 40 43 95 94 91 90 88 86 85 31 33 36 37 40 43 44 45 75 72 71 70 69 78 75 72 71 69 66 65 64 53 51 48 46 44 43 64 63 62 60 59 39 42 45 48 49 52 55 56 91 88 86 84 82 80 12 15 18 20 21 22 25 26 41 39 38 37 35 33 31 30 44 41 40 39 36 14 16 19 22 25 56 57 59 62 64 99 97 95 94 92 91 89 87 83 81 79 77 76 73 52 54 56 58 59 61 63 47 49 51 52 54 55 58 18 21 22 23 26 27 28 29 39 41 43 45 46 48 50 44 43 42 41 38 36 76 73 70 68 66 63 62 37 34 32 31 28 25 40 38 37 34 32 29 58 55 53 50 48 46 39 36 33 32 30 27 43 44 45 47 48 23 26 27 29 32 33 34 90 87 85 83 81 80 78 19 20 21 23 24 27 76 75 73 72 71 83 82 79 77 75 73 72 19 17 15 13 11 72 70 69 68 65 63 60 56 54 51 48 46 44 52 51 48 46 43 40 33 32 31 28 27 24 21 11 10 8 6 5 92 89 87 86 84 81 79 86 87 89 91 93 95 59 61 64 67 68 69 72 75 28 31 32 35 36 39 41 86 89 90 93 94 96 76 79 82 83 86 87 88 29 27 26 23 21 20 51 53 54 56 58 61 62 65 77 78 81 83 84 87 88 38 40 41 42 44 47 47 45 44 43 41 56 59 62 64 67 70 71 9 11 14 16 19 20 29 28 27 24 21 20 30 27 25 23 20 19 16 13 84 83 82 79 77 46 49 50 53 54 55 56 21 24 25 27 29 32 33 14 15 16 18 20 85 82 79 78 77 76 75 73 63 60 59 57 55 32 34 37 40 41 44 45 48 53 56 58 59 61 12 11 9 8 5 4 3 84 81 78 77 76 75 73 72 44 43 42 39 37 76 73 70 68 67 86 89 91 93 94 97 99 77 80 81 82 85 19 16 13 11 9 8 5 19 22 24 27 30 18 20 23 24 26 64 66 68 69 72 74 77 78 78 75 73 72 70 67 65 64 37 38 41 43 46 48 36 35 34 31 28 26 24 21 27 30 31 34 35 37 39 41 80 83 84 86 89 61 64 66 69 70 50 53 54 57 60 61 62 63 57 60 63 66 69 70 73 60 57 54 52 49 48 45 43 48 46 43 41 39 37 35 33 21 22 23 24 26 64 65 68 69 71 74 46 49 50 51 52 54 56 20 18 16 15 14 13 11 9 34 32 29 27 24 21 18 15 16 14 12 11 10 18 19 22 24 25 53 51 48 46 44 42 39 77 74 72 69 68 66 65 25 22 21 20 17 14 13 33 30 28 27 25 22 19 17 29 28 26 23 21 40 39 38 36 33 32 63 60 57 54 52 49 47 45 84 85 86 89 91 93 96 99 20 23 24 25 28 6 8 9 12 14 16 52 53 56 59 62 65 66 51 54 57 58 61 63 65 36 34 33 31 29 28 27 61 62 65 66 69 70 71 74 25 26 29 31 34 37 40 42 48 47 46 44 41 40 31 34 37 39 42 43 46 48 95 93 91 88 85 83 80 77 75 72 70 68 67 66 15 18 21 22 23 26 29 30 94 93 90 89 88 87 84 82 36 34 33 31 29 26 65 64 63 60 59 12 14 17 19 22 25 28 30 20 18 15 13 11 8 7 4 11 13 15 16 19 71 69 66 65 64 61 61 62 65 67 70 73 74 76 51 49 46 45 43 61 59 58 56 53 50 48 29 31 33 36 39 42 45 47 74 76 79 82 84 86 93 90 87 84 83 82 81 70 72 74 77 79 80 81 83 89 90 93 95 98 41 42 44 46 48 50 53 54 31 29 26 24 23 20 19 33 30 29 27 25 22 82 83 86 87 88 89 90 38 40 41 43 44 71 68 65 62 61 58 88 86 83 82 80 77 80 82 84 87 89 90 15 12 9 8 6 3 67 64 62 59 56 52 54 55 57 59 9 8 5 4 3 1 23 26 28 31 32 35 36 44 47 48 49 52 55 57 14 16 17 18 21 24 38 41 43 45 47 48 89 88 87 86 85 82 97 96 93 91 90 88 87 18 15 12 9 7 5 45 46 48 51 54 56 59 61 95 92 90 88 85 82 96 95 93 92 91 89 86 33 34 36 37 38 16 19 21 24 27 29 74 72 69 66 65 64 62 27 25 23 21 20 17 64 66 68 69 70 72 73 75 6 9 12 15 16 19 22 14 11 8 5 4 3 2 47 50 53 56 57 60 63 81 84 86 89 90 36 37 38 41 43 44 45 42 40 39 36 35 33 31 49 46 45 42 41 38 59 57 54 52 49 46 44 25 23 22 19 16 43 44 45 48 51 6 9 11 13 16 75 74 71 69 68 67 64 59 56 55 52 51 70 72 75 78 79 33 31 28 26 23 22 21 38 41 44 47 49 26 23 21 20 19 8 9 12 14 16 19 22 54 55 57 59 61 16 18 19 21 23 25 82 79 78 76 75 73 71 68 38 39 40 41 44 96 95 93 92 91 88 87 24 27 30 33 35 37 38 47 50 53 55 57 59 61 22 19 16 13 12 9 35 37 38 41 42 43 3 6 9 10 12 15 18 37 40 41 44 45 48 51 54 56 59 60 61 62 42 41 38 37 36 34 31 28 97 96 93 90 88 87 47 45 43 42 39 38 18 15 13 12 9 8 6 81 83 86 88 89 90 92 94 32 29 26 24 21 19 16 13 68 67 66 65 62 61 58 56 44 43 40 37 35 34 33 57 56 55 53 50 47 45 18 15 13 10 8 6 87 85 82 80 77 75 58 56 54 53 52 49 48 51 52 55 57 58 60 17 16 15 13 11 8 27 29 32 35 38 39 40 43 38 40 42 45 48 50 52 53 62 63 66 68 70 92 91 90 88 85 82 81 80 3 6 9 12 14 75 78 81 84 87 90 48 45 42 41 40 39 72 73 74 75 76 78 79 50 52 55 56 59 62 83 81 80 78 75 73 71 68 30 33 34 37 40 42 43 46 48 50 51 52 30 28 27 24 22 19 56 54 51 50 48 46 43 40 29 30 32 35 37 38 39 40 74 73 72 70 68 67 80 78 77 75 73 21 18 15 12 9 7 6 42 43 44 46 48 50 51 35 32 31 28 25 22 69 71 72 75 77 79 76 75 73 72 70 68 53 54 56 59 61 64 65 42 39 37 36 35 22 25 28 31 33 20 18 15 13 12 11 9 34 36 39 40 42 43 46 49 17 19 20 23 25 27 30 30 33 35 36 39 42 44 26 24 21 20 17 15 44 42 40 39 37 70 71 72 74 77 79 82 45 42 40 39 38 35 32 30 17 18 19 20 23 25 28 30 89 92 95 97 99 94 93 90 88 85 83 62 65 67 70 71 73 79 76 75 73 71 70 17 15 13 12 9 6 4 74 71 68 66 64 63 60 41 40 37 35 32 30 27 25 19 22 25 26 27 38 41 42 45 48 51 94 92 89 86 83 80 46 49 50 52 55 56 57 78 75 74 73 71 70 68 ================================================ FILE: exm/aoc/2024/aoc_2024_02_questions.txt ================================================ --- Day 2: Red-Nosed Reports --- Fortunately, the first location The Historians want to search isn't a long walk from the Chief Historian's office. While the Red-Nosed Reindeer nuclear fusion/fission plant appears to contain no sign of the Chief Historian, the engineers there run up to you as soon as they see you. Apparently, they still talk about the time Rudolph was saved through molecular synthesis from a single electron. They're quick to add that - since you're already here - they'd really appreciate your help analyzing some unusual data from the Red-Nosed reactor. You turn to check if The Historians are waiting for you, but they seem to have already divided into groups that are currently searching every corner of the facility. You offer to help with the unusual data. The unusual data (your puzzle input) consists of many reports, one report per line. Each report is a list of numbers called levels that are separated by spaces. For example: 7 6 4 2 1 1 2 7 8 9 9 7 6 2 1 1 3 2 4 5 8 6 4 4 1 1 3 6 7 9 This example data contains six reports each containing five levels. The engineers are trying to figure out which reports are safe. The Red-Nosed reactor safety systems can only tolerate levels that are either gradually increasing or gradually decreasing. So, a report only counts as safe if both of the following are true: The levels are either all increasing or all decreasing. Any two adjacent levels differ by at least one and at most three. In the example above, the reports can be found safe or unsafe by checking those rules: 7 6 4 2 1: Safe because the levels are all decreasing by 1 or 2. 1 2 7 8 9: Unsafe because 2 7 is an increase of 5. 9 7 6 2 1: Unsafe because 6 2 is a decrease of 4. 1 3 2 4 5: Unsafe because 1 3 is increasing but 3 2 is decreasing. 8 6 4 4 1: Unsafe because 4 4 is neither an increase or a decrease. 1 3 6 7 9: Safe because the levels are all increasing by 1, 2, or 3. So, in this example, 2 reports are safe. Analyze the unusual data from the engineers. How many reports are safe? --- Part Two --- The engineers are surprised by the low number of safe reports until they realize they forgot to tell you about the Problem Dampener. The Problem Dampener is a reactor-mounted module that lets the reactor safety systems tolerate a single bad level in what would otherwise be a safe report. It's like the bad level never happened! Now, the same rules apply as before, except if removing a single level from an unsafe report would make it safe, the report instead counts as safe. More of the above example's reports are now safe: 7 6 4 2 1: Safe without removing any level. 1 2 7 8 9: Unsafe regardless of which level is removed. 9 7 6 2 1: Unsafe regardless of which level is removed. 1 3 2 4 5: Safe by removing the second level, 3. 8 6 4 4 1: Safe by removing the third level, 4. 1 3 6 7 9: Safe without removing any level. Thanks to the Problem Dampener, 4 reports are actually safe! Update your analysis by handling situations where the Problem Dampener can remove a single level from unsafe reports. How many reports are now safe? ================================================ FILE: exm/aoc/2024/aoc_2024_03.adb ================================================ -- Solution to Advent of Code 2024, Day 3 ------------------------------------------ -- Mull It Over -- -- https://adventofcode.com/2024/day/3 -- Copy of questions in: aoc_2024_03_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_03 is use AoC_Toolbox, HAT; input_name : constant VString := +"aoc_2024_03"; r : array (Part_Type) of Integer; procedure Read_Data (part : Part_Type) is i, j, a, b : Integer; f : File_Type; s : VString; enabled : Boolean := True; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get_Line (f, s); Scan_Line : loop Scan_Expression : for fake in 1 .. 1 loop -- Just for the comfort of the EXIT statement. i := Index (s, "mul("); exit Scan_Line when i = 0; if part = part_2 then j := Index (s, "do()"); if j in 1 .. i - 4 then enabled := True; Delete (s, 1, j + 3); exit Scan_Expression; end if; j := Index (s, "don't()"); if j in 1 .. i - 7 then enabled := False; Delete (s, 1, j + 6); exit Scan_Expression; end if; end if; Delete (s, 1, i + 3); exit Scan_Expression when Length (s) = 0 or else Element (s, 1) not in '0' .. '9'; a := 0; while Length (s) > 0 and then Element (s, 1) in '0' .. '9' loop a := a * 10 + Character'Pos (Element (s, 1)) - Character'Pos ('0'); Delete (s, 1, 1); end loop; exit Scan_Expression when Length (s) = 0 or else Element (s, 1) /= ','; Delete (s, 1, 1); exit Scan_Expression when Length (s) = 0 or else Element (s, 1) not in '0' .. '9'; b := 0; while Length (s) > 0 and then Element (s, 1) in '0' .. '9' loop b := b * 10 + Character'Pos (Element (s, 1)) - Character'Pos ('0'); Delete (s, 1, 1); end loop; exit Scan_Expression when Length (s) = 0 or else Element (s, 1) /= ')'; if enabled then r (part) := r (part) + a * b; end if; end loop Scan_Expression; end loop Scan_Line; end loop; Close (f); end Read_Data; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data (part_1); Read_Data (part_2); if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 173529487 -- Part 2: validated by AoC: 99532691 end if; end AoC_2024_03; ================================================ FILE: exm/aoc/2024/aoc_2024_03.txt ================================================ ~-mul(858,892)?@#mul(380,985)what()[^what()%mul(340,11)~*}don't())/~-mul(849,387)%-why()when():how()>-,what()mul(605,504)what()~:]what();how()who()];mul(771,783)?^ who()}~?>mul(111,830))@ ~mul(329,797)%'why()why()mul(125,409)-*/where()()@&!why()mul(390,37)when(974,538)#/when()){/don't()/mul(20,990)}?%{(who()mul(627,567)(how()'<(#%how()mul(387,315){;%who()%#from()mul(868,680)}^$mul(862,19)mul(847,689)>((#@when()}mul(339,156)+/{}@{^%[why(231,704)mul(236,754)]'^where(978,690)mul(460,872)#'*mul(518,944)>mul(301,886))mul(477,933)^mul(685,909)who())]what(288,791)mul(170,434){ &where()~(@where()mul(191,104)mul(637,600)&select()why())~select()mul(534,617)?mul(763,508){from()when(22,266)+who() when()mul(204,352)when()mul(426,122)-<*where()'$ why()mul(192,980)[(#[!$-}mul(798,208)''[!where()what()select()mul(295,727))#)}($,$%where(539,126)what()when()select()'@mul(311,541),?don't()#select()!}!(}&?mul(100,142)),-}%mul(222,856)~$;>!from()where()mul(758,901)mul(757,796)mul(976,686);@'~+-{#who()mul(26,971);mul(404,362)^~who(417,106)what()#mul(186,691)from() %#+{/mul(67,433)-who()!-+!mul(184,469)*when()[&when(458,221)<$mul(163,556)^)]?,'}&+who()mul(514,239)~)(mul(143,441)'how(741,776)~who(766,575)when();>*^mul(281,143)+!>;+:mul(767,44)# when()why()don't()how()from()[from()from(){mul(436,519)what() *who();@{,>do()%'mul(19,540)when()mul(643,539)~when(812,543)mul(527,639)-!mul(409,379)where()/(mul(168,491)#$>]mul(432,333)@%>>&who()(mul(113,494)%where()why()when()mul(659,592)#(/'mul(72,670)when()^^mul(369,596)mul(631,168)-why()()[*}mul(330,968) $why()where()mul(230,139)don't()@)@where())%}where()&,}mul(875,661)~don't()':why(){mul(793*:mul(399,702)!://select()@when()why()do()@mul(488,581{?{&how()&select()!<'mul(912,311)why()! })@+}mul(128*mul(626,752)%mul(49,60)[,who()what()select())@@]*]why(937,788)from():mul(945,658)<]don't()where()how(515,644)@+'select()how()mul(369,665)/],mul(263,185)where()^why()why()@what()mul(82,407)mul(464,537)[mul(871,333)^mul(560,227)-why()mul(966,203)$what()+where()#mul(101,21)}%how(),)^who()>,select()mul(667,565)('what(),%select()(@mul(500,204:''<~'why(477,559))[where()mul(698,648);how(){&?what()^@[%mul(280,395)>~, mul-#/%:where()>where():mul(170,746)don't()}($:@mul(998,876)*~<[mul(121,366)-?#;how()>from() ::mul(804,883)^-[ (:mul(100,354who(544,766)+,]>!['/;mul(949,115) [^!})from()&mul(617,518)*how()(:@who()what()/mul(591,163):what()?{'do()!/when()!$mul(394,797)]how(620,741)!:!mul&%mul(523,862) ~}where()why()}from()! @do()mul(270,205)from()[&^mul(577,474)?{*/why()*what()mul(656,30)where()+#,@mul(295,616)why()/mul(8,267))-^when()who(610,661)'mul(182,139)select()}select()!when();;mul(492,992)?how()~($who(716,562)%/mul(702,654))*>mul(126,386)[mul(351,400)select()%$[!}{+mul(98,266)mul(924,5)*'(^:[}!?mul(112,163)+!?where()mul(987,791)mul(943,488)how()mul(698,312)&:@from(442,439)~%~:mul(235,520)%mul(248,221&>/;select()what()) ~@from()mul(546,261)'mul(956,953why(458,937)when()~!where();mul(442,916)%;)&(mul(410,237)where()~why()[+?[mul(169,337)what()who()&what()mul(901/mul* don't()mul(999,662)*]&/'#<+,^}'mul(365,260){{?,,}from(520,861)where()what()mul(325,208): when()+>{!;mul(335,726)#',:>@?mul(48,443![mul(130,626)!{^don't()*?-*[%>mul(934,995),how()@from()'#mul(433,843)why()<}$}how()-mul(754,464)when()why()mul(992,113);]/{%mul(87,293^]how()why()~&when()*#mul(589,979)@-&select()/%mul(218,248);mul(536,581)when()mul(215,212)/%when(66,857)@what()+mul(958,271) '%#who()&{mul(239,197)}what()$>{*'select()mul(365,443)>why()how()what()%mul(885,496how()when()}{@/ mul(589,42)^:;who()where()why() !how()(mul(574,947)*;where():&where()%]<{mul(572,4)$mul(232,716)when()when()mul(928,697)^(where()mul(301,501)-mul(100,436)#~?mul(708,770): @:@)!*mul(89,177)><@+ {when()+mul(926,998);>,)?,$)mul(813,382)}from(728,403)^mul(497,820)where()(?why(454,153)!select()}*!don't()what()from()}&}?how()mul(432,895)$!+mul(743,149)$!why(704,998)when()mul(229,683)((when()from()#&{mul(217,869)^)?)?what() select()}mul(765,209)who():}%{mul(448,553)[:-,don't()what()<,}from()where())mul(543,719)from(415,153)why()!'?^~mul(666,540)mul(922,877)mul(416,636)+#;$select()'mul(971,485)from(964,539)where()^ *who()/mul(35,594)<:mul(207,585)~*}'[]#mul(815,776){?%&*@?mul(385,133)['!:who() )mul(439,846)&)mul(529;?>;#mul(677,906)^& ()mul(75])how())mul(481,206)who()why()$^ from();what()'why()do()(%^&)mul(277,454)>where()where()$-#select()+/don't()what()select()]mul(295,126)why();from()mul(203,301){#mul(572,420){%(-*mul(929,786)do()mul(107,813)mul(921,668)'^+++!:[;mul(587,921)mul(242,920)mul(933,463)why()mul(340,196)'--']-mul(623,675)select()what()mul(656,927)<$)from()where(473,933)]~mul(408,566)!>$mul(373,541)}%*^)mul(346,14)>&how()@^-(&;mul(993,735)select()*{mul(990,221)*from():[ mul(940,96)/how()^>#;select()/#?mul(624,249)>mul(160,974)]^mul(589,900)&$[?[<-!select()mul(512,717)^/&mul(226,478)* ';'+from()?@~mul(224,929)!when()^what()where()'@'>~mul(451,87) when()%how()where()how()what() mul(59,36)how()where() )>mul(270,950)--mul(864,193)$!!from()[+when()do()?&]from(){?who()mul(576,443)}>*what()mul(60,617)]where(){*}what(16,936)*:mul(613,575) @$%%'mul(930,241)!~when()<+what()&{mul(189,41)don't()how()%who()how()mul(79,681){']{({ mul(615,354)~#&{mul(863,397)@?(mul(469,991)!mul(97,649)'%{where()/{+*}when()mul(429,913)[ >where()>](when(654,639)),mul(763,148):!~do()%+*',mul(646,831)~*$!?>mul(632 @?from()[mul(165,564)#mul(464,289)from(),mul(197,442)~[&mul(739,935)how()where()!],mul(583,831){mul(4,501)mul(912,584):select()(when()>&& &what()mul(836,498)where(987,400)*${mul(983,648)+~]don't()&,how()'^[*({mul(180,898)mul(982,907): select()($what()mul(294,259)do()where();>mul(130,154)mul(566,682)how()-:from()/ )^mul(50,250)~@select()(->mul(65,434)mul(865,288)+$don't()#+-mul(875,123)@@>?mul(606,377);do();!where(){mul(267,543):]','# #*why()mul(31,575)#;who() *<$mul(797,419)'what()}when():what()/mul(627,73)'how(218,429)who()]*$,$from()mul(221,471)$ ;what()mul(38,106)?-&!~&from()mul(117,669):how()mul(422,348)(:/]mul(568,980)when(){~where(490,375)<(& mul'*)'where();##:}mul(34,144)mul(352,352) select()-when()/where(365,161)mul(571,634)mul(373,66)}how()don't()where()@>$$(!&mul(532,260))!mul(304,873)select(676,286)?#<,why(),^~do()%@~where()mul(56&+select()>select()what()mul(670,288)< $:+[$~what(){@!%mul(422,126)(who()?from()}*}mul(459,923)mul(38,243)^)!who()::#from()/mul(845,589)^/when()'#when()~,'select()mul(454,166)who()~>when()^when()?'@where()mul(237,855)~from()from()why()mul(233,606)]@mul(947,750)!@*}who()(@%mul(252,951)[from(995,363))}),when()who()+where()mul(368,442)>from()where()select()from()what()^?mul(190,689)mul(337#who()*when()/*mul(652,631);,*why()+select()>}where()%mul(839,296)>&%,@}$mul(723,530)who(685,511) %~where(782,449)mul(36,917);]]{mul@where()!&*%why()mul(191,759):why()what()$mul(900,773):$who() *{mul(426,740) why(396,306)/from()why()*%}'+do()@!'how()%^/mul(970,462)when()who()!-mul(535,35)}from(377,342)when()/(how()who()-}:mul-what()/how()?*^how()mul(217,447)/]?%!mul(495,690)}#<{?,do()+-why()mul(3,559)who()+what()mul(942,139)})when()who()<-]'what()what()mul(218,316)how()mul(669,389),<+mul(861,165)why(){^}[mul(594,386what()who(){mul(801,662)mul(852,2)-mul(458,479)//mul{don't()mul(826,480)>mul(954,968)$;mul(871,184)from()select()**<]!mul(503,290)#select()where()?do()mul(154%[&how()?mul(279,673)-[don't()$]why()-what(754,13)mul(841,495)where()}{mul<-'##!/usr/bin/perl@~mul?what()<^-@/>from()!mul(573,383)where()-{#mul(420,579)when(977,697)when() &@##from()+}mul(314,487) who()+from()where()mul(878,982)]~mul(812,80)?select()don't()how()];mul(986,548)/how(311,658)/select()(don't()(select()select(533,328)<^+from()what()why()@mul(786,152)*<[ }},)mul(30,285)mul(721,12)#(-{what()mul(70,496)^when()-/how(420,87)select()what()]$mul(645,406);-~where()>do()~&^(,}$#$mul(993,357)?/select()}do()+from()~@mul(661,590))what()*!?]*!'mul(19,345)-why())select(){%(% don't():*#when()~select()mul(910,416)}mul(550,400)when()]~mul(515,93)&where()mul(412,99);(;+mul(611,500%what()%,from()when()mul(822,769),-*(([$(mul(153,856)why(){mul(476,25)do()-mul?from()<<[why()&mul(859,60)what()]+ :how()what(434,726):^from()do()}*?}?mul(432,641)>%?!mul(93,484)++}?mulwho()#>who()select(): why()mul(889,212)>]?where()&mul(808,71)<*/'-+select()mul(523,619)+#where()mul(324,306)why()';why()}mul(337,315)~:what():^?-$from()mul(924,137)mul(444,59)why()[from()how()who()mul/how()>mul(304,707)'select() select()mul(224,915)mul(991,306)[>$! &how()>/mul(719,679)how()select()mul(65,620)from()#'~:]+-from()]mul(971,857)how()#[~~]?%mul(230,961)from()from())# } where()mul(330,14)>mul(411,981)}}<)mul(304,453)how()from()$who()mul(573,848)% ;:from()(~select()!mul(542,790)}'#mul(530,502)%$(-#$mul(358,540)mul(10,361)when()where()<}&where()mul(429+!*$~)mul(446,812)%when()don't()>~>^what()select()why()from()where()mul(330,214) -[mul(731,164)/mul(776,235)mul(240,20)who()^what()']@!-who()%don't()(( )'!how()why();>mul(941,911)'?where()from()how()/mul(489,746(select(725,995)-from()?;when()%]%mul(555,315),how()#%!>?mul(664,596how()+'-who()from(51,408)mul(605,672)?!%from()) #}don't():}mul(579where()mul(243,699)mul(321,902)*!/mul(465,704)*when()[*how()mul-!mul(15,80)}#}mul(413,156)(;mul(71,288)/$;'don't(),how()+[;$who()%$when()mul(516,863)mul(268,600)(mul(602,939)who())>)<&'!mul(323,967)?mul(673,398)):&#}>>{!mul(501,484)<;who(969,453)-who(624,921)-)<-mul(72{-//!mul(576,751)mul(318,331)mul(707,186)+how()mul(660#how()!+#?where()mul(547,453) [what()?->+[mul(266,969)what()from()%^!how()?mul(236,335) )'<>,&!-where()mul(563-select()(mul(405,969)when()[%;why():$]mul(266,763)what()~#-{+don't()~+-mul(68,150)#{{?%:mul(422,966)select()mul(143,33);mul(917,142))]'>mul(23,457);'what()why()-where()}/>mul(66,911)&&':(>why()>mul(413,27)mul(772,64)mul(266,512)%$*[why():where(),@%^',mul(750,295)*]:mul(17,60)!!}*from(975,930)mul(763,134)mul(463,381)when()(select()where()+{?what()mul(755,843)!why()+>mul(24,584){mul(105,734)$why()@where()!+what()%what()mul(5,111)#^;?{^/?^~mul(24@>when()what()where()#from(284,9)when(437,59)mul(978,337))+:(select()mul(996,373)(what(188,513)@ ]from()}mul(370,765)~$mul(490,904))]/%who()why()/mul(123,978how()why()[who()~%how(180,982)@:mul(343,157)![/*^mul(157,976)who()from() select()]+?+do();)&)mul(734,420)$%(select()>'mul(143]mul(4,351)mul(279,828)'}^mul(108,132) #how()why()}mul(573,602)}@mul(747,126)where()'@mul(247>why())when()+::^&from()mul(843,212)^mul(612,743)[mul(204,899)$mul(174,265)%]mul(864,804)-from()how()%%mul(674,431)^^#[(@:&*mul(619,935)select()//~^mul(70,941)why()select(405,825)why()who()@mul(112,658)'+(@!$who(){select()do()from()from()@how(846,925)mul(417,888)~{: who()&-;mul(285,186)-+what(){/+-mul(24,944''mul(935,370)why()?~ +mul(468,38)'why()(/mul(704,512)%mul(946,591,<);from()select(290,495)*{:['%mul(554,965)(~mul(308,534)mul(6,373)^how()@%&how()~mul(669,386)when() 'mul(33,652)mul(950,268)::mul(98,181)]^how()'!mul(982,613)how()&where()]what()how()do()[from()#[? mul(929,452)<$$ mul(506,408)-mul(670,674)how()mul(645,104)do()(>[%from()@'who()&%mul(45,884)mul(895,714)mul(871,6)},?&;!select()#where(779,295)^mul(113,370)why())%[select()[,^' mul(976,960)][%mul(828,993){}}mul(135,443)>what()mul(344,20)>where()/) :@mul(564,715){([,]'mul(675,478)#*@who()>]$*+mul(94,992}from()mul(288,445)mul(72,57)*/})how()[how()!mul(543**%who():what()mul(345,778){mul(462,244)from()[@*who(),+mul(591,870)#select()%mul(779,654)$+%%@ mul(920,934)?-select()-}mul(247,709)@$why()mul(179,824)(when(989,252)?mul(422,816)$[from()#who()@,when(),mul(922,47)@mulwhy()-mul(890,397)-^/+'select()[&!who()mul(547,6)-]>:^;mul(870,938),~?[%mul(8,689!>*@!]mul(311,244)->how()$when()'}mul(213,766)$:!+ mul(620,644)%where()mul(430,127)%{[mul(682,585)mul(245,26)don't()mul(510,688)where()]-mul(844,443)/@+who()?who()when()mul(453,182)mul(928,131)?&'{[+@?,mul(55,18)mul(795,739):}what())@$]'mul(377,34)&,~*why()/@who()mul(467,127))&how(28,925)mul(955,519)}where(830,382)$when()[-why()/+mul(310,139)mul(217,931)!mul(574,122)!mul(227,82)where()mul(940,851) {mul(545,758):from()%~/mul(937,897)mul(665,919)^&/ &what()mul(23,37),select()%*mul(98,952);mul(171,967)who()$+]when()%$mul(426,870)<<;;why()[do()@mul(28,286)-what()([+select()why()do()<^+what()^?~-mul(246,992)/mul(938,936)'$>when()mul(18,736)%?how()-what()from() when()select()mul(37,387)}<[}?+how()#&?mul(779,369)select()mul(750,510)%[,'from()>who()mul(13,97)what(547,477)why(859,962)?,where()mul(806,879)mul(577,179)#from()+>where(705,292)what(712,121))when(227,970)*mul(942,336)& who())!*mul(992,750):from()<:+-mul(938,672)mul(55,872)mul(354,183)>+(+mul(520,932)#from():}{who()$mul(675,973)@^@%mul(58,468)/select()what()->]mul(343,375)^ ,%mul(480,300)where()(/*$mul(695,676)how()where(),-!:from()mul(363,212)~(!where()-[what()don't()mul(614,594))mul(569,802)'mul(995,471)~&$:^:how()how()-^mul(853,428)-;-%what()(from()+do()'where()() !{^?#mul(376,780)select())where()select()&{-,{,mul(894,646)select()*< @}*[}}mul(332,665)[ ================================================ FILE: exm/aoc/2024/aoc_2024_03_questions.txt ================================================ --- Day 3: Mull It Over --- "Our computers are having issues, so I have no idea if we have any Chief Historians in stock! You're welcome to check the warehouse, though," says the mildly flustered shopkeeper at the North Pole Toboggan Rental Shop. The Historians head out to take a look. The shopkeeper turns to you. "Any chance you can see why our computers are having issues again?" The computer appears to be trying to run a program, but its memory (your puzzle input) is corrupted. All of the instructions have been jumbled up! It seems like the goal of the program is just to multiply some numbers. It does that with instructions like mul(X,Y), where X and Y are each 1-3 digit numbers. For instance, mul(44,46) multiplies 44 by 46 to get a result of 2024. Similarly, mul(123,4) would multiply 123 by 4. However, because the program's memory has been corrupted, there are also many invalid characters that should be ignored, even if they look like part of a mul instruction. Sequences like mul(4*, mul(6,9!, ?(12,34), or mul ( 2 , 4 ) do nothing. For example, consider the following section of corrupted memory: xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5)) Only the four highlighted sections are real mul instructions. Adding up the result of each instruction produces 161 (2*4 + 5*5 + 11*8 + 8*5). Scan the corrupted memory for uncorrupted mul instructions. What do you get if you add up all of the results of the multiplications? --- Part Two --- As you scan through the corrupted memory, you notice that some of the conditional statements are also still intact. If you handle some of the uncorrupted conditional statements in the program, you might be able to get an even more accurate result. There are two new instructions you'll need to handle: The do() instruction enables future mul instructions. The don't() instruction disables future mul instructions. Only the most recent do() or don't() instruction applies. At the beginning of the program, mul instructions are enabled. For example: xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5)) This corrupted memory is similar to the example from before, but this time the mul(5,5) and mul(11,8) instructions are disabled because there is a don't() instruction before them. The other mul instructions function normally, including the one at the end that gets re-enabled by a do() instruction. This time, the sum of the results is 48 (2*4 + 8*5). Handle the new instructions; what do you get if you add up all of the results of just the enabled multiplications? ================================================ FILE: exm/aoc/2024/aoc_2024_04.adb ================================================ -- Solution to Advent of Code 2024, Day 4 ------------------------------------------ -- Ceres Search -- -- https://adventofcode.com/2024/day/4 -- Copy of questions in: aoc_2024_04_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_04 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 10; n_p_3 : constant := 13; input_name : constant VString := +"aoc_2024_04"; n : constant := 140; n_p_3 : constant := 143; a : array (-2 .. n_p_3, -2 .. n_p_3) of Character; r : array (Part_Type) of Integer; procedure Read_Data is f : File_Type; begin Open (f, input_name & ".txt"); for i in a'Range (1) loop for j in a'Range (2) loop if i in 1 .. n and then j in 1 .. n then Get (f, a (i, j)); else a (i, j) := ' '; end if; end loop; end loop; Close (f); end Read_Data; procedure Do_Part_1 is begin for i in 1 .. n loop for j in 1 .. n loop case a (i, j) is when 'X' => -- Search_Ver: for fake in 1 .. 1 loop exit when a (i + 1, j) /= 'M'; exit when a (i + 2, j) /= 'A'; exit when a (i + 3, j) /= 'S'; r (part_1) := r (part_1) + 1; end loop; -- Search_Diag: for fake in 1 .. 1 loop exit when a (i + 1, j + 1) /= 'M'; exit when a (i + 2, j + 2) /= 'A'; exit when a (i + 3, j + 3) /= 'S'; r (part_1) := r (part_1) + 1; end loop; -- Search_Hor: for fake in 1 .. 1 loop exit when a (i, j + 1) /= 'M'; exit when a (i, j + 2) /= 'A'; exit when a (i, j + 3) /= 'S'; r (part_1) := r (part_1) + 1; end loop; -- Search_Counter_Diag: for fake in 1 .. 1 loop exit when a (i - 1, j + 1) /= 'M'; exit when a (i - 2, j + 2) /= 'A'; exit when a (i - 3, j + 3) /= 'S'; r (part_1) := r (part_1) + 1; end loop; when 'S' => -- Search_Ver_Inv: for fake in 1 .. 1 loop exit when a (i + 1, j) /= 'A'; exit when a (i + 2, j) /= 'M'; exit when a (i + 3, j) /= 'X'; r (part_1) := r (part_1) + 1; end loop; -- Search_Diag_Inv: for fake in 1 .. 1 loop exit when a (i + 1, j + 1) /= 'A'; exit when a (i + 2, j + 2) /= 'M'; exit when a (i + 3, j + 3) /= 'X'; r (part_1) := r (part_1) + 1; end loop; -- Search_Hor_Inv: for fake in 1 .. 1 loop exit when a (i, j + 1) /= 'A'; exit when a (i, j + 2) /= 'M'; exit when a (i, j + 3) /= 'X'; r (part_1) := r (part_1) + 1; end loop; -- Search_Counter_Diag_Inv: for fake in 1 .. 1 loop exit when a (i - 1, j + 1) /= 'A'; exit when a (i - 2, j + 2) /= 'M'; exit when a (i - 3, j + 3) /= 'X'; r (part_1) := r (part_1) + 1; end loop; when others => null; end case; end loop; end loop; end Do_Part_1; procedure Do_Part_2 is begin for i in 1 .. n - 2 loop for j in 1 .. n - 2 loop case a (i, j) is when 'M' => -- X1: for fake in 1 .. 1 loop exit when a (i + 1, j + 1) /= 'A'; exit when a (i + 2, j + 2) /= 'S'; exit when a (i, j + 2) /= 'M'; exit when a (i + 2, j) /= 'S'; r (part_2) := r (part_2) + 1; end loop; -- X2: for fake in 1 .. 1 loop exit when a (i + 1, j + 1) /= 'A'; exit when a (i + 2, j + 2) /= 'S'; exit when a (i, j + 2) /= 'S'; exit when a (i + 2, j) /= 'M'; r (part_2) := r (part_2) + 1; end loop; when 'S' => -- X3: for fake in 1 .. 1 loop exit when a (i + 1, j + 1) /= 'A'; exit when a (i + 2, j + 2) /= 'M'; exit when a (i, j + 2) /= 'S'; exit when a (i + 2, j) /= 'M'; r (part_2) := r (part_2) + 1; end loop; -- X4: for fake in 1 .. 1 loop exit when a (i + 1, j + 1) /= 'A'; exit when a (i + 2, j + 2) /= 'M'; exit when a (i, j + 2) /= 'M'; exit when a (i + 2, j) /= 'S'; r (part_2) := r (part_2) + 1; end loop; when others => null; end case; end loop; end loop; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 2483 -- Part 2: validated by AoC: 1925 end if; end AoC_2024_04; ================================================ FILE: exm/aoc/2024/aoc_2024_04.txt ================================================ SXMXXMXMASXXXMASXXAMXMMXSAMAMMMXSXMSASMMMXXSMSAMMMMXMAMXASAMAMXSAMXAMXXMXMXMMMSXMXSAMXSSXASXMASMSXMASMSSSMMSSMMXMASMSMMMMXMMSAXXMXXSXSXXXXXX MXMMMSAXSAMMMXMASMXSAXSAMXMASAMASAMXMAASMMSXXSAMXSAMMSSSMSAMASASMSSSMXSSSMXSAAMMXMMASAMXSAXSMSMXMAXAMAAAAMSAMASMSAMMASAAAMAAXXSMMMXMAMAMSMSA SAAAXSASMMAMAXXAAXXSASMASXSASASASXMAMXMMAXSMXSAMXMAXSAAAASXMAMASAAAAAAAXAAASMSMMSASXMASAXXAMXMSMSMMSMMMSMMMAMMMAMAXSASXMSAMXSMXAXMASAMAMAAXX SSSSXXXMASMSAMSSXMAMMMXXMAMAMAMAMASMSMASMMXMASMSMSMMMXSMMMSMXSAMMMMMMASXMMMSXAAASXMXSAMASMMXAMAMAXXMAAXAXSXXXSMXSAMMMSXSMMSXMAMSASXXXSXSMSMX XAMXMMXSAMXMAXAAASMSMSMMMXMXMSMMMXMAXMAMXMAMMSAAXMASXMAAAAAXAMXSXXASXMAMXSMMAMMMSAMXMAMAMMMMSSMSMSMSXMSMSMXMXXAAMAMXXSXMAMSXMSMMASAMXSAMXAAX MAMAXMAXAXSMSMMSMMAXAXXASASAAXAAMAMXMMXSASAMXMXMXSAMXXXSMSSMXSAXMMMXAMSAAXAXAXAAXAMXSAMXMXXAMMXSAAAAXMXMAXAMXMMMMMMXMMAMSMMXSXMXSMAMAMMMSMSA MAMMMMXSSMAAAXAMXMMMSMSAMASXXSAMSMSAXSASXSMSSMMXXAMMMMXMMMAMMMXXSASMSMMMMSMSMSMXMAMAMXAAAMMMSMAMXMMMXSASXSASASMSAAMSSMAMXAMXAXMSASAMXSMXAMXM XSXSAXAXXAMSMSMMAMXMAAMXMXMMMMXXMASMSMMXASAAAAMXMMXAAXAAAMMMSMMMSAMAMXAAAAAAAXAMSAMSMMSSSXXSAMASAMASASAMXSMXXXAMXMSAMXSXSAMMMXSAASXMMSAMMSAS XMASASXMXSXXAMASAMAMMSAXMAMXSSSMMMMMXASXXMMSSMMMAXSXMSSSMSMAAXAXMSMAMSSSSMSMXMAMXAMXAXAMAMXSASASASMAAMMXMMMXSMAMAXMAMAAAMMASXMAMMMMSAXMAXMAS SMAMAAMXMXAMMMASASASXMXXMASAMAMSAXAXXAMXAXAXXXAXSAMMMMXAAAMSSSXXAMMMMMMMMXAXAMXSSMMSSMMMSAMSMMMSMMXMXMAAXAAASMMMSSSMMMMSMSASASMXXAAXSXMSAMMM SMXMMMXSXMXMXMASASASASAXSAMMSMXSMSSSSSMSSMAMMXMSMASXAASMMMMAMXMMAMMASMMASMXSXSAAXAAAAAAAMAXXXAXMAXAXMXSMSSMMSAXAAXAXXXAAAMASAMXMASMMMMXXXMAS XXXXASAMXXAAMMMSAMAMXMAMMXMMAXMMMAXXAAAAXXMMAASMXAMXSMXXMXMXMAMXAMSASASAXAMXAMMXMMMXSMMSSSXMSMSMSXMAXMAAAXMASMMMXSMSMSAMXMAMMMAAMMXAAAAMASMS MSMMXMASASMSMAAMXMXXAMSMXXXSAMAXMXSMMMMMXXMMXMSAMMSXMMMMMSMSMSSSMXMMSMMMSMSMXMASAXSXMAXMAXAAAAAAXMSXMAXMXXXAMXAMXMAMXMAMXMAMAXMSMSXSSSMMAMXX MAAXXSAMMXAAMMMSMMSAMXMSMSMMAXSAMMAAASAXMAMASAMXMASAAMAAMAAAAAMASXSMMAAXAAAAMXAASAAASMMMAMMSMSMSMMAMMMSSSMSAMAMXAMAMASAMASXSMSAAAAMAMXMMSSMX SSSMMMSSXMMMSXXAAXAAXXMXXAAAAXXAMAMXMMAXAMXXXAMXAXSSMSSSSMSMSMXAMXMAXSMSMSMMAMAXMXMXMSAMXMXAXAAXXXAMAXXAAAAAXSSSMSASXSAMXMAAAMXMMMASAAMAMAMM MAAAXAXMAXSAXMSSSMSSSSSSSSSMSSSSMSSSMSSSSSMMXAMXAMMAMAAAXAXMXXMSSSMSMXASXXMMXAMXSMMMAXXSSSSSXMSMMSMSSSMSMMMSMAAAXSAMAMMMAMMMXMAXMXMXMSMAXAMM MSMMMSMXAMMMMAXAMMXAAAAXMAMAAAXMAAXAAAMXAAXMASMSMXSAMMSMMMMXMASAAAAAXMAMMSAAXSSMSASMSMAXAAAMSMAAXXAAAMAMAMSMMMMMMMMMSMSMSASMXSMMMAXASMXSMMSS XMAMAAMMSXMASXMMMMMMMMMMMAMMMMMMMMSMMSSMSMMAXXAMXASASXMXSXAASXMMSMMMXMSMAMMMSXAASMXAAMMMMMMMAMSSXMMMSMMSAMMAMXAXMXAXMASAMXSXAXXASMXMMAXMASAM ASAMMMSAMASAMMAAXXAXAAXAMASAAAAAAXXXAMAMXXMSMSSMMXXAMAMAMXXMSMMAMXAMSMAMMSAXXXMASMMSMSMASXMMAXAMAXXXAAXSAXSAMSMSSSMXMAMAMASMMMSASAASMSMSXMAS XSASXAMAMMMMXSSMSSSSSSXSSXMMSSSSMSSMXSMMSXXMAMAASXMSXMMAMMSAMXMXSMSMAMAMASMSMXXAXXAXMAMASMSMXMASXMSSMSMSSMMXMAXSAMSAMASXMASAMAXAMAMSAXAXMXAA AMAMXXXSMSASAAAAXAAMAXAMXMMAMXMAMSXMASXASMMMSMSMMAAAASMXSAAMSMMMSAAXMSXSAMXAAASMMMMXSAMXSAMXSMMMAXAAXXMXMXAXSMSXMASXXASXMASAMSSMMMMMMMXMXMXM SMAMMSXMXSASMSMMMMMSAMXMAMMAMXXXMXAMASMMMAXAAXAAMSMSSMAMXMAXAASAMSMSXAASMMSSXXSAAXXAMASXMASASAAMSMSSMMMAMXXMAMXAXAXMSMSAMASAMXAAAXAAXAXSXMAS MXMXXMASAMXMAAXAAAXMASXMASXMSSXMMSXMASAMSSMSSSSSMAAMXMXMMMMMSXMAXASAMXXXAAMMSXSXMXMMSXMASAMXSMMMMAMXAASASAMSSMSAMXXXAASXMASMMSXMMSXSSSXMASAS SASXXSAMASAMXMSSSSMSAMXMASAAAXAAAAAMXSAMXMAXXXAMAMXMAXAMAAAAMASMMMAMXSXMMMSAAMMAXMAXMXXXMXSXSXMXXAXSSMSAMXXAMXSAMASAMXMAXAMXXMAXXXXXAXSSMMMS SAMAAMXMXMASXMAXMAAMXXAMSMMMMSMMSSSXASXMAMMMSMSMXMAMMXSSSXSASMMMXMSXAXMASAMMMASAMMSXSMSAMXSAMASMSMMXMAMXMSMMXAMAMMSXXSSSMMSMMASMAMSMAMXMAAAM MAMMSMSSMMAXMASMMMSMMSXXASAMXSAAXMXMASMMASAMXAAAASMMSAAAMAMXAAAMMMMMXSMSMASAXMMSSXMAMMAMXMXASXMAAXAAMAMSSXAAMMSSSXMXMMAMXXAASAMMAAAAXMXSSMMS SXMAAXXAAMAXXXXMAAAAMASMSXXMASMMXMAAAXAXASAAMSMSMSAAMMMMSXMMSSMSAAAMXSXAXSSXXSAAXXMASAMAASXMMMMSMMSXSAXSAMMMMMAMAXXMAMAMMMSXMAXMXXMSAMXMXMAX MAMSSSSSMMMMSMASMSSSMASMASAMXSXXASXSSMSMMMMMXXAAMMMMXXXMAMXAAAMSMSASAXSMMXXAMMMMSXSASAXXXSAMXMAAXXMXSXSXSAXAXMMMMXMAMSAMXAXAMXMMSMXXAMASAMXM SAMMAAXXXMAAAAMMAMMAMXMXMASXAMAXXXMAXAMAAXXSMSSMSMASMAXXMSMMXSMSAXXMMMMSASMMMAAMXAXASAMSMSAMAMSSSXMAMMSAMXMMSSXAXMXSXSASMSSSMXSAAXAXSMASMSSS SXSMAMXMAXMMSSMMXMSMMAAXSAMMAXSXSAMXMMMMXSXAAAAMMMAMAMMXMMMSXMAMAMSMMMAAXMASASXSSMMMMAMAAMASXMAMMAMAMXMAMXSMAMSMSMAMAMAMAAAAAAMSSMMAXMXSAAAS SXSAMMMXMMMAMAMXAXAXSSSXMASMSAMMSAMASMSMAMMMMMSMMMAXSSSXASAXAMMMSXXXAMXMSSMMAMAAXMASMXMMSSXMXMAXXAXASXMXSXXMAMAMAMMSMSAMMMSMMMXMXXMASAMMMMXM XAXMMMXASAMMSAMXMMXXXAXAMXMAXMSASAXAXAAMASASAXMAMXMXAAMXAMMSAMAAXAMMMSXXMASMSMMXMSAMXMSXAMASXSAMMSSMAASAMXXSMSMMAXAAMMAXSAMMMSMAMXMMSXMASMMS MMMAAXMASXSXSAMXSMMSMAMAMMMXMXMASAXSMSMSXSASXXSAMASMMMMMSAXMASMSSSMASAMXSAMMXMAXXMXSAAXMXXAMXMASAMAASXMAXAMXAAMMMSMSSSMMMMSAAASAMASXSAMXSXAX AASXMSMAXAXASMMMSAAXXXAAMMSMMXMMMAMXAAAAAMAMAXSXMAXAMAXXXASXAXAAXMSXSAMAMAMMAMXSMAMSMMMSMMXSXSAMXSSMMMSAMSSMMXSAMSAAAAAXAXMMSXSXXAMAXAMAMMSS SMXAAXMMMMMMMXXAMXXMMMMMSAAAXAMSMAMMAMSMMMAMMMMMMMMMMXXXMASMSMMMSMSXSAMMSMMSMMAXMAMXMXAAAAMMAMMMAXXAMMSAMXAXMAXASMMMSMMMMSSMXXMMMSMMXAMAXAAA XMMMXMAMAXAAXXMSSSMMXAAMMXXSSMSXAMXXAMMMSXXXAAAXMXAMXMMSMXMAXAAXAAMASMMAAXMAMSAMXXSAAMSSMSSMAMASMXMXMASMMXXMSSXMMMSAXAAAXAAASAXMAMASMSXSMMSS MAAXXMMSSSSMSAMXAAXASMMSASMMAMMMMMXMASXASASASMSSMSXSASAAAAMXMMSMMSMMMMSXMASAXMASAMMMSMMAMAAXAMXAXAAAMMSASXSAAMAXAXMASMSSMSSMSAMMSMAMAXAXMAMM AMSSXSAMMAAAAMXMXMMXXAAMAMASAMXSASXSXMMMMAXMMSAAXAASAMSXSASASMXAAXAXXXAAXAMXXSAMAXXAAASAMSMMSSSSSMSXSASAMAMSMSMMXXMXMAAXMAXAMXMAMMXMAMSMSSSS MAMAMMASMAMASMAAASXSMMMSASMMMSXSASAMXSXMXMXXMMMXXSMMXMAXMXXASAXSSSMMSMSAMXXAMMSSMMMMMMSXMXAAMXAAMXMAMXMAMXMAXAXSSXMMMMMMMMMXMAMASAMMXSAAAAAX SXMAMSAMXXXAXMXSAMAMAXAAAMXAXAAMMMAMAMXSAMMSXMXXMMAMXMSSMAMSMMMXAAXXMAXXMAXSXAAMXAMXSMMMMAMXSMMMXAMXMMSASMXSSMMAMAMXMMMAASXSXSMAMAMAXSMMMMMM AASMMMAMASMMSXMMXMAMAMSSMMSMSMAXXXAXASMSASAMAXAAXSAMAXAAMAMAAXSMSMMSMMMMMMXXAMMSXXXASAAXMAMXMAASXSXMAXMXMAMMAMXMSAMAMSASAXAMAXMMSSMMMSXMAMXM SXMAXSAMXAAAAMMAMSXMAMXAAXAAMXAMXSMSXMASAMXSAMXSMAMSXMMXMMSSSMMMAMMMAAMSSXXMAMMMMMMXMMMMMASXXSMSAXSAAMMAMXMSAMMXMXMMXAMMXMAMMMSMAMAMASMSASAM MMSSMSXSSSXMSMMAMSASMSXSMSMSMMSSMAXSAMMMMMMMASXAXMMSMXSAMXMMAAASASAMSMSAMXXMXMXAAAAAMXXSXAXMAXXMAMASAMSMSMMSAMMSSSSSSMMASXMMMAXMAXXMAXXMMMAS AAMXASAMXAMMAXMAXMMSAAAXASAXXXAAXXMMAMAMSAMXAMAMSXSXAAXXMASMMMMSASAXAXMAMMSSMMMSXSSXSAASMMMXAMASASMMSXAAXXASMSAMXAAAXXMASMAAMMSMMSMMSSMXSMMM MSSMXMAMMMXSASMSSMAMMMSMAMXMMMSSMSASMMMMSASMAMMAAXMMMMSMMMMMSAASAXMMSXSAMMAAAMAXMMAAMMSMAAAMASASASXAXSSSSMXSAMASMMMMMXMASXSMSSMMAAAMAAMMSAXX XMAMMMMASMMMASXAAMXMAAAMAMSSMAAXMMMAMXXMSAMXAMMXMASASXXXAMAAXMMMAMSAMASXSMSSMMASAMMMMXAMMMMAXXMMMMMMXAMAXXSMXMSMXSAMMASXMAXSMAAMSXSMXXMASAMX AMMMMAAMAAAMXMMSMMMSMSSSXMAAMSSSXSXSAXXAMXMSSSXAXXXAXAXSXMMSXMXMMMMASXMAMMAAXMXSXMASXSMSSMMSMMMAAMAMMMMAMMMSMXMAMSASAASXMAXASMMMMMXXSMMMSSMX SSMMSASMSSMSMAMAXAAAXXXMAMSSMMXMASAMSAMXMAMXAMXSXMMMMSMMAMXXAMXXMSMXAASXXSMSMSMSASXAXSXAAAAAAAMMMXMXASMSSXAASAMAMMAMMMMAMSMMMXSASXAAXAXXXMSX XAAAAMXMAXAAXAMXMMMMXMASXMAXXXXMAMAMXXMAXSSMMMAXAMAAAAASXMASMMXMMXSMSXMAMSAXAAASMMMMMSMSMMMSSSSXSAMXASAAMMSMSXXAXMXMXASAMMASAMMASMSSMMMSAMXM SSMMSMSMSMSMSMSXMSMSASAMAMMSMSMMAXSMMMSMSMSAXMAXAMSMSSMMMSMSXSXAXAMMMAMXAMXMSMMMSAAAASAMMXAMXXAASAMMSMXMAAAAXMXSSSSMSMSASXXMAXSAMAAMAMAXMSMA MAAMXAXAXMXMXAMMAAASAMXSXSXAAAAMMSMAAMAMAASXMMSSSMXXAXXAMAMXMMMSMASASXSXAXMAMXXASMXXXMAMXMMSSMMMMAMXAAXXMSSXXSAXMMAAAASXMAMSAMMASXMMMMSMXAXX SSMMMMMMMMAMMSMMMSMMXMMXMAMMXSSMMAXMMSASMMMAXMAAAMMMSMMMSASXXMAMSAMASASXMSXSSSMMMMMXAMXMASXAAAASXMMMMSMXMAMAAMMSASMMMXMMMSAMXSSMMMXSSMAMSMSA MAMXXAAAASASAAXAAXAAMSXAXXASAXAXSAMXXSAMXMAMAMMSMMXAXAAAMAMAAASMMXMXMAMMMMAAAAMXAAAAMSAMXAMSSSMSAAAXSAMXMASXSMXSAMMAMSMAMXSMAMMMASASXMAXAAMM SMMMSXSSXXAMMMSMSSXMAXSXSSMMXSAMMAMSMSMMMMMXXXMMMXMSSSMSSXMMSMXAMAMAMXMSAAAMMMMSMMMXXAASXMAMAXASXMAMXAMXMAMAXAXMMMMAMASASMMMMXAMXMMMASMSMSMM AXAXMAXXMMMMSXMAAMAMMXAMMAXSAMMMMXMAAXXMSASAMXAMSSMAXAAAAXSXXASMMASXMMSSXSXSXSAMMAXSSMMAMXXMAMXMXXMMSSMMMSMXMMSMSASAXMSXMAASMSSSMSXSAMMAMXMM SSSSSXMASXMXMAMSMMXAMXMAMAMMMSASMMXMSMXAXASASMXMAMMASMMMSMSAMXMAMAXAAXAXMMMSXMASXAMXAXAXMASMMMSXXSAAAMAAAAXASMAAXAXMSMMMSSMMXAAAXAXMAMSXXAMM AAMAMXMXMASMMSMMAMSXXAXSXMSAXSMSAAXSAMXSMAMAMMAMMSMXSXXXAAMSMMSSMAMSMMMMAXAXAMAMMSMSAMSXSAAXMASAASAMXSSMMXMASMMSMSMMAAAMAMXSMMMMMMMXMXMASMSM MXMAMMMMXMXXAAMSSMMMMSXXAAMXMXXSMMXMASAMMAMMMSMMXAXAMXMSMSMAMMAAMAXMAMXXSMMSSMASAMMMSMAAMXSAMMMMMSSMXMASMAMSXMAMAMXXSSMSASASXSAXASAMSAMXAMAX SMXAXAMXASMMSXMAAAAAAXASMMMSXSMSXSMSXMASXXSAAAASXSMMSMXAMAXMSMSSMXSXAMSMXAAAAXSMASXAAMMSXSMMSSXSXXAMMMAAMXMXAASMMMSXMAMXAMASASMSAMAMSASASXSM AAMXXMMXAXAMXXMXSSMSMMMMXAXXAMAMASAXXMAMAAMMMSSMMMAMAASMSXSMAXMAMXAMAMXASMMMSMXMAMMAXXXXXMAASXAMASMMAMSSMMSMSMXAXAMXMMSMMMAMAMXSAMXMSAMXXAMX ASASXSMSSSSMMMSMMMAAXAXMXXMMAMAMMMSMXMASMMMSAMXMXSAMSXMMAMMXSSSXMMSSXSMXMAAAAMAMMSSMMSAMXSAMMMXMASXSMMAAMASAMXSSMMSAMSXMSSSMMMASASAMXSAMMAMM AMXMMAAAXXAAAAAAAMSMXMAMSMSSMXXSAXMMSSMSXXAMASASMSXMMASXAXMAXAMXMAMMASXMMSMSXXAMXAAAAMASAXASMSAMAXAMXMSSMXMAMAMXAAMAXSAMXAAAXMXSMMXSAASAMXMA XXMXSMMMSSSMMSSMMMAXSSMXAXMAASMMMXSXAAXMXMXSMMASXMMMSAMSMSMMSAMAMXSMAMASXMAMMSMSMSXMXSASMMSMAAMMMMSASAXXMASAMXXXMMMSMSAMMMMMMMXXXXAMAXMSMXXS MXAXXAAXXMASXXAASXMMXAXSXSMMMMAASMSMSSMMMSAMXMASAXMAMAMAXAMXXXXSAMXMASAMAMXAMAAAAAASXMASMXMMMMXMSAXAMXMXMXAMXMSSXSAAASAMSAAAXXMMMMSMSMXAXMAM SMSXSSMSXSMMSMSMMAXAMXMAAXAXSXSMMASAXXAAAAASXMASXXMAXMXMXSASXSXMAMXSXMASXMAXSMSMSSMMAMSMMAAMXSAAMMSXXMASMSMSMAXAAMXXXSAXSXSSSXAAAXMAMXSMSAAM AMMAMXAMXSXMAMAMXXMSAAAMMMMSAAMXMAMXMXXMXMMMMMMXXAMAMSXSMXMSAMMSAMXXMMXMAXSMXMAMXMXSMMMASMSMAMMSMAMXSMSAMXAAMXMMMMSMAXMMMXMMMMSSSXMAMASAXXSA MAMASMMMASAMMMSMMXSMXMSAXAXMMMMAMXSAMSSSMXMAMASMSMSMSMASAMXMXMAMAXMASMASXMMAMMSXSMASMAMMMMAMXMMXMXSASXMASMSMSXXXAAAMXMSASASAAXMAMXMASXMAMAMX XMSAMMAMMSAMXAAASXMSSXMXMASMMMSAMAMXAAAAXASASASAMAAXAMXMMASAAMSSSMSAMSMMSXMAMAAMXMAMMAMXAXAMMMSSMMMXXASMMMMAMXSSMSSMSASASASMSSMAMXXMMXMMXXXX XXMMSAMXMMAMMMMSMAAASAMXSAXAAXMAMSSMMMSMMMSAMAMAMSMSSSMMMASXMSMXMAMXXXXAMMSXMXSSXMASXMSSMSMXAAMAAXMXMAMMAXMAMAXAAXAAMAMAMAMAMAMSSMSSMSXMASAA MMXMXMMSXSSMMSMXXSMMSMSMMMSMMXXAMXAXMXMMSXMAMSMSXAAXAMMSMASAMXMAMAMMSMMXMAXAXAXAXMASAAAMMAMMMSMMMMMAXAMMSXSAMMSMMMMMMMMMMXMXSAMXAMAAAAAMAMMX AAAMMSXSAXAAAMAAMXAAXMAAAAAAAAXSSSSMSMAMMXMXMXAXSMSMMMSAMASAMXSASASAMXSSMSSMMMSMMMMMMMMMMASAMAASMSSMSASMMMSXSXAAAAAXAAAMMXMASMSSMMSSMSXMSSXS MSMSASAMXMSMMSMMMXMMMAXXMMMSMSAMXAAAMSMMMSAMXMXMASAAXXSASMSAMXSXMAMAXAXAAAMMAMAXAAAAAMMMSASASMXMAAAASAMXMASXMXSSSSSSSSMMAAMXSAMXAAAAMXXAXAAX MAMMXMMMMXMMAXAMXXSXSSSSSSMMAAXAMXMMMAMXXSAMSAMXMAMAMMMMMASAMXMXMXSSMSSSMMMSASMSSSSSXSAAMMSMMXAMMMMMMAMSMAMSMAXMMAAXMMMSSXSAMAMSMMSMMAMMAMXM SASMMXMAMASMSSSMSMAAAAMAAMMMSMSXAMSMSASAASAMSMSAMAMMMAAMMMMMSASXSAAXMAXAAXXXAMMAAMXAMXMMXAMMMXMXSAMSSXMXMASAMXXXMMSMMSAAMSMXSMMMMAXXMXMXXSSX SASAAASASAXMXAAAAMMSMMMMMMAAAXXAXSAMSASMMMMMXASMXMXASXXSAMXMSASAAMMMMMSSMMMMSMMSSMMMMMSSMMSAMXSAMAAAMAXMAMMASMMSAAXAAMMXSAXAAMASMASASMSSXAAS MMMMXXMAMXSMMSMSMMXXAXMMMSMSSSXXMMXXMMMMMAASMMMAASXMXAMXXXAMMAMMMSXSAXMASAXSXAAAAMXXSAAMSXSASAMAMMMAXXMASXSMMAASMMSMMAXMAMAMASASMMSAMAAMMSMX SSMMXSMXMMAXXXMMMXXSXMASXAAAAMAMMXMAMMAMSSXMAMMSMSASMSMSSSMSMSMMMSASXMSASXSASMMSMMMAMXSMSMSSMASAXSXSSSSXMMAXMMMSAMXMSSSMASMMAMMSAMMAMMMMAAXS AMASAAMMSSSXSMASAAMAMXAXSMMMSMSAASMMSMMMAXMMSMMMAMAMXXAAMAAAXAASXMAMAXMAMXMMXSMMMSMMMAXAXXMAMMMMXMAXAMXAMSSMMSXSXSAAXXAMXSAMXSASAMSXMAMMXSAA MSAMMSXAMAMAXSAMMXMAMMMXMMAMAXXSMSAAAASMMSMAMAMMSMMMSMMMSMMMSSSMXMAMMMMXMMXAMXXAAXAXMAXMMMSXMXAMXMMMAMMMMAMAXAAMAMXMASMMXSMMAMMSXMMMSASXMXAM XMASXMMSSMMAMMMSAASAMASAAXMSMSMMXSMMSXMAAAMASAMAXMAAXAXXMAAXMMMAXSXSAMAAMAMMXMSMSMXMMMSSXXAAMSAMXSXSAMAXMASMMMXMAMAXMAXXMMXMASASMSMASASXMXMX SMMMAXMAMMMXSSMMMMMASXMSXMAAXAASAMXAXXSMMASXXAMXSSMSSMMSXSSMSAMMMSASMXMXMMAXSAMXAASMSMAAXASXMAXXAXXMAXSSSMSAAAAXAMMXXSXSASAMXMXSAAMMMXMASAMX SASMSMSASMSSMXMASXSXMMMAMSSMXMXMMMMMSASAMXSASMMMMAMAAXAAMAMASAXSAMXSXMXMMSSMAXSMMSAAAMMMMMMMSXSMSMMMSMXAAMSXMMMSASXMXAAMAMASMMMMXMXMSASASASM SAMAXASASAXAXMMMSAXXAMMMMMASXMASASAMXAMAMMMMMAAMMAMSSXXMSAMAMSXMXSXSAMSAAAAXAMMASXMAMMAXAXAAMMXAXXSAMMMSMMSXSAMAAMAASMMMSMMMAAXMASXASASXSAMX MAMXMAMXMMSMMAXSMMMMSMAXXSAMXSMSASXSMMXAMAAASXMMSMMXMXMXXMXSXMMSMMASAMMMMSXMSAMXMAXSMSMSSSMSSMMSMAMASMXXAMSAMXSMMMXMMAXXAASMSMSMAXMMMXMXMAMM XXMXMXMAAXSXASXMAAXAASMMXMMXAMXXASXXAMSSSSXMMXAXAMSMMMAMSMAMAMAAAMAMAMXSMMXAXMSASMMXAAXAAAMAAAMMMXAXAAASAMMXMASAMXAXXXMMSSMAMAXMAMSASAAXMSMS MMXXMAXXSMSMMMSMAMSSMSMMSAAMSMMMMMXMSMAAMAXSMSAMMMAAAXXSAMMSAMSSSMXSXMXMAMMXMXSASMAMXMMMSMMSSXMXMXMMMMXSMMMMMXSXMXASMXSXMAMMMMXAXXMAMMMSMAAX ASMMXSSMXXSAXAAXAXAMXXMASMMXXAMAMAXXAMMXMXMXAXXAASXSMSMSASASAMXMMMMMMMSSMXMASAMAMMXMASAXAAXXMASAMAAAXSMMMAAASXMAXSAMXAAASAMXASMSXSMSMSASMMSM SMMAAXAMSASMMSSMSMMXSXMASASASXMSMSSMSSSXAASXMSSSMSMMAAASAMAMMXSAAAAAXAAAMXSASAMSMXXSMSAXMSMSSMMASMSSSXMASMSXSASAMMMMMXMAMMXSMXAAXSAMAMAMAXMM MAMMMSAMMAMXAXMXXMSMSXMASAMASAAXAXAXAAMMSMMAXAAAAMAXSMXMXMMMSMMSMSSMSMSSMXMXSMMXAMXXXMMSMMAASXXXAMXXAXSXMXMASMMMSASMMXMSMXAXAMSMMMAMXMASMMMM SXMXXSAMMMMMXSMAXAAMSASAMAMAMMMMSMMMMSMAMASMMMSMMMMMXMAMXSAAXAAMXMXMAAXAMXAAMASXMMSMSAAMXMMMXXMXSMSMMMXASXSAXAMXMASAAASXSMSSSMAAAXXMXMAMAAAA MAMSAMXMAAAAAXMMSSMXSAMASMMXMXAAXAXMXMASMAMXAXMXXAAAMSMSAXMXMMMSAMXAMXSAMMMXSAMAAXMASMMSAMSMSAMAMAAAMAMMAMMMSMMMMAMMMMSAMXMAMSXSMSASXMMXSMMS MAMXASMSXSMMMSAXXAXAMXMXMASXSSSSMMMSAMXXMASASXMASXXXAAAMMSMSMSAXMASMXASAMSSMMXMXMMMXMAMSMSAXSAMSSSSSMXAXMAXAAAAMMASXSSMMMSXSMXMXAMMMAXSAMAXA MSSMASAMXXMASXXMXMMAXMASMXMAMAAAASAXXMASXMSXXAMASAAASMXMXAAAAMSXSAMXSASAMXAMASXASASMMSMMXMAXMAMXAAMXMMXSXMMSSSMSSMSAMXAAMXAMXXAMMMSSMMMASAMM SAAMAMAMMMSMMMXAAXMXXASMMSMAMMMMMMASMSAMXMXMSMMASMXMXAMSXMSMSSMMMASXMASMMMXMASAXSASMAMASXMMSSSMMMMMAMSASAMXMXXXXAMXAMMSMSMSMSMSMSMMASXMXMAMX XMMMASAMAXAAAAMSMSMMMXAXAAXMMXXSXSXMAXXMAMAAAXMXSXMMMMMAAXAAXAAASXMMMXMASXMMXMXAMXMMSMAMAAAAXXXXAAMASMASAMSMSSXMMXXAMXXXXXMXSAXAAASMMMMASAMX MXXSXSXSXSXSMXMAAAAAMMMMSSSSMSMSAMAMSMMSASASMSMAMASAAMXSMMMSMXXMMAMXSASMMAAMAXXMXXXAAMAXSMMSSMSXSSSXSMXMAAAAMMAMSSSMSAMASXMXMAMSSXMXSASMSSSS SSMSASASASAMXMSMSSSMSAXMAXAAAASMAMMMMAXSXMAMMSMMSAMSMSAMMAMXMSSMSAMAXXSXSMMMSMMAXMMXXMMXMXXAAAAAMXMAMXXXASMSMSSMAAAAAASMSAMMMXMXXXMASASAXMXM MAAMMMAMAMMMSXSMXMAMSXXXXMSMSMSSMMMAMSMSMMXMMMAMMMXAXMAXSMSSXAAXMAMXMXMXMASAMXSAMXMMSASAMXSSMMMMSAMXMASMMMXMXAAMMSMMMXAXSAMAAMASAAMAMAMAMMAS SMMMXMAMMMXXSAMMASAMMMSSMAXAAAMXSAMXXXAMXXAMAXXMMMSMSSSMAAAMMMMMSSMSAMXASXMASAMASAAASAMAXAXXXMAAXAMMMAMAAAMSMSSMXMAXSMMASAMXSASXSXMXMMMAAMAS AAXMASXSSMMXMAMSMSAMXMAAMAMSMSMXSXSXMMMMSSXSMSMAMXXXXAMXMMMSXSSMXMASMXSXSAMXMXSASMSMMXSAMSSMMMMSSXMAMXSSMMMAAXMASMMMSAXAXAMXAMAAMSXAMASXSMXS XMAMXXSAMXMMSAMAMXXMAMSMMXXXXXMASMMAXSMAASMXMAAAMMMMMAMASAMMAXMAAMMMAXMMXXMXXAMASXXXMAMAMXAMXXAXMAMSXXXMAXSSSSXAXAXXMXMMMSAMXMMAMSSMSASAXMMS MMMSMMXMSAMXSASMSSMSXMXXMXMSMMMMSASMMMMMXSMAMMSMSAAMSMXAXAXMMMMSMMASMAMMSMMXMMSMMMMMMMMMMSMMMMSSXSMMMAMXSXXAAMMMMAMSSSMSAMXXAMXAXMAMMASXXMAM AAAAAXAASXXASXMXMXAAMXMXSAAAAAAAMXAMAAMMMSASXAAAMXXXAMMSSMMXSAMXMXMAXAMAAAMMSMAMAXSAXMXSAAAAXAAXXMASAXSAMMSMSMASAAXSAAXMMMASXMSSSSMMMMMAMMAS MMSSXSAXXSMASMMXMMSMSASASMSMSSMSSSMSSMXAXMAMMMMSMAXMASAMAMAMSSXMMSXMSSSSMSMAAXAMSMSMSAAMXSXMMSXSAMAMXAMASASXAMAMMMMMMMMAXMXMSAAXXXXXXAAAXMAS SAMXXSXMAXMAMAMAXXXXXAMMXAMMAAMAMXXAAMSSSMAMAAAMMSMSMMXMAMAMMASAMXAXAXMAMXMSSMXXMASXAMMSXMASAMMAAMXMMSSMMASMMMSMSXAXAAMAXMMAMMMMSSMSSMSASAAS MAXMAXAMSMSSSSSSSMSSMXMMMSMMSSMSSSMMSMAAAMASMMMSAMAXMSSSSSSSXSAMXSMMMMMMMMAMAMSAMAMSAMXXASMMMSMSSMXXXAAMMXMAXSMASASMSSSMSAMAMMAAXAAMAMXASMSM SASMMSMMXAAAXAAAAMAMMSMMAXXXMAXAAXMAXMMSMMXMASMMMMXMMXAMMAMMMASMXMASXXMAXMAMAMMAMSMXMXSMMMAAMMAAXXMASMMMSAMSXXMAMAMAXAMAMXSASMMSSXMMAMMXMMAM MASAXMAAMMMXMMMSMMXSAMAMASAXSXMMSMSMSSMAMSSMAAMAMSMMSMXMMXMASMXMAXXSAMSAXSAMAMMSMMMASAMAASXMSMMMSXSAMAAASASAAMMMMMMXMMMXMASASMXMAMMMXMASMSMS MXMMMXMMSXSMMXAXAMXMASMMMXMMMXMAXAXAAASXMSAMAMMAXAASXAXAMXXASXSMMXAMAMMMMSASMSAXAMXXMASMMSAXXXMAAXMASXMMSXMAMAAAASMMSMSAMAMXMXASXXMAXAMXXAXA MMMXAAXXMAMXMAMSAMAMAMXAMXSAXAAXMAMMSMMXXSAMAMSXSSSMMMAMMSMASAMASMMMSMXXASXMAAMMMMASMAMAAXMSMSMMMSMAMMAMXMMSASMMMMAAMAAAMXSAMSMSXAXSXMMASMSM SAMMSMSAMAMAMAAXMMXMASMXMASXSXSAMMAMXAXXXSAMXMAMXMAAASMAAXMAMAMAMAMAMMXMXSAMMMMAXMAXMAXMMMMAAMXSXMMAMSAMXMAXMMMSSSMMSMSXMAMAMSXMMSMXASXAXXAX SXSAAMSMMMMXMMSMSMASAMAAMAMMMMMAMMSAMXMAMMMSMXAAAXMMMAXMASMASAMXSXMASMMSMSAMXASXSMSSSMMXAAXMSMAXAASMXSAMXMSSXSAAAAXMXXMAMMSAMMAAAAASAMMMMSAM XAMMXXSAASMSAAAAAAMSAMSXMXMAAASAMXMASAAAMAMAXXXMMSMASXMSAMXASMSMSAMASMAAAMMMSMSAMXXAAMASMSSXXMASXMMSAMXASMMXAMMMSMMXMAMSMASASMMMMSAMXSASMASA MMMSMAMSXXAAMMMMMMAMAMXAMXSSSMSASXMMSMSMMASMSSMMAAXAMSAXMMMMSAMASXMASMSMMMSAXXXXXSMMMMAXXAAMXMXSAAMXSMXXXAAMXMSXXXMASMXMMASAMXXAXXXMAXXSAAMM AAAAMXMXXMAMXASMSMAMSMSASAAAMXSAMAXXXMAXMMSAAAASXMMSSMSMAAAMMMMXMMMXSMMAXXMMSSMSMAASXMXSMXMMXSSXMASAXXMSSSMSAMXXAXXMAMMAMAXAMXMSSSSMASXXMMSX XMSXMXMAASAXXMMAXMAMAAXAMMMMMAMASAMXASMSAAMMMMMMAAAXSAMMSSMSASMXAXXAXAXMXSAAAMAAMMXMXMASMSSMAXMASXMASAAMAMAXMAMXSSMMAXXAMSSMMMAXAAXMXMMAXAXX SMMXMAMXMSASMXMMMSMSXSMXMAXMMXSAMXMXMMAMMXMAXAASMMMSMMMAAAASASMSAMMSSSMAASMMSMSMSXMASMASXAAMMMSAMXMMSMSMAMXMXXSMAAXMMXSASMAMXMMMMMMMSSSMMSSM MAAAXAMXAXASAAXXXAAAAXMXSXSSMASMSASASMAMXMSXSSMXAASXAAMMSSMMAMXSSSXMAMMMMSXMAAAAXAAMAMAMMSXMAAXMMXSAXMAMASMSXMAAXSMAAAXXMMAMXAAAXAMXAAXXAAAX MMMMSSSMSMMMXSSMSXSMXMAXMMSAMXSASASASXXSAMMMAXAXSMMSMMXMAXXMMSAMXMAMXMASXXAXMSMMSMMSAXXXXAMMSMMSMAMASXMXMSMAAXXSAMMMMSSXSMSMMSMSXMSMMXXMMXMM SXSXXMAAXXXMAXXXAMXMAMMASXSAMXMAMMMAMXMMMAAAMSMMMAMXXAXMMMXMASMASMXMXSXSMSSMMAXAMMASMSSXMASXAXAAMXSMMAMASXMMSMAMMSAXAAAASAXAAMAXXMXAXMSXSASA AAMXMSMMMSMSMMXXMAAAAXSXXMSAMMMSMSMMMMXSSSSMXMAASAMMMMSSMMAMXSXXSAMMMMXMAAMMSAMMSMMSAMXASAMMMMSMSAMXSAMXSAMAAMXMXSAMXSMXMASMMMAMAXSAMXAASASX MMMAXAAAAAAXASASMSMXMMAMXMSXMXMAAAMXSAMXAXXMSMMMSAMXAAAAASXXMXMMMMXAAXXMMMSAMXXXAMAMMSSMMAMASXXXMMMMXXSMSAMSXMASXMXXXAXXMMMXXMAXXMXMAMMMMAMA XAMSSSSMXSSXMMASMASAXSASMAMAMASMSMSAAXAMSMSXSASASXMMSSSSMMAMSMMAAXMMMXXMAMMXSMSMSMMSAAAXSSSXSAXXMASXSAMXMAMXASAMMAMMMMSAMASXSSSSXAAMSMMXSAXX SXSAAMXMAMAMXMXMMASXMSASXAXAXMSAMXMMXMMSAAAASAMXMAXAMXMAMXAXAAXMSSSSMSSSMSAMMAAAXAMMMSSMAASAMXMMXMAAMXMXSXMMAMMSMAMXAXMASASAXAAMMMMXMXMAXMMM XMMMSSSMMSAXXXMXMXSAMMXMXXXXXMMMMXAXAXSAMXMAMMMMSAMSSSSSMSASMSMAMAAXAAXAMMAMMSMMMAMXMXAXMMMMXMASAXMSMXSAMMXXAXMAXASMMMSAMXMAMMMMMASMXSMMXMMM XSXMAMAAASMMMASXMASAMAXMXMSMSAAAXXSMXSAAAXXXXMAAMASAAMAMAXAAAMMAMMMMMMSSMSSMAXAXSAMAXXAXXXAMXMXMMSAAAMXAXAMSXMSSSMXAXAMMSMXMAXSMSMSAASXMASMA XSASXSMMXSXSAAXAMAXXMMMXAAAAAMSMXAMXXAXMAXMXSSMMSMMMSMAMMMSMMMSXSXMXSAAXMAAMAMSXSASXSMXMMSMSAMASXMXSMMSSMMXSAMXAAMSSXMSXAMAXMAXMAXMMMMAAXAAX MSAMXXXMASXMMMSSMSSXAMASMSMSMMAMMXMMAMXSXSMAAAAXSAMSAMXSMAAXXXMXMAMMMMSSMSSMXXMASMMMXMASXAXAAMASMSAMAAXAAMAXMMMSMMXXAAAXASMSSSXSSSSMSSSMSMSM AMXMXSXSSSXMAMAXAXXMSAMXAAAAXSASXMSMSXAMAAMMSMMMMAMXASAAMSSXSAAASAMMSXMAXAAMSAMXMXAXSXASXXSSSMASMMASXMMSMMMXSAAMXMASMMMXXXAAAAAMAXXAAAXAAAXA MXMASMAMAXASXSMMXMXAXASAXMXMXMXSMAAAXXSSSMXXAAXASMMSMMASXXMASMSMMSSXMASXMMSXSMSMMXSSMMXMXXMAXMSMMSAMAAXMMMAASMSSXMAXASXMXMSMMMMMAMMMMSMSMSMS XAMXAMAMXMMMAAXSSMSMSASAASXXAMASASMSMMMAMXASXSMXXMAAXMAMXXMMMXXMXXXXSMMMXXAXMXSMAAMAMAAMXSMMMMMAXXMSMMXXAMMXSMAMAMMSMMAASAXASXAXAXAAAXAXAAAA ASXSMSMSMSAMXMMSAAMXMAMMMXAXSMASMXAAMAMAMXXMAMXMSSSMSMASMXSAMSAMXMXAXAAMMSSMAAMMMMSAMSMMAMXXAMXSMAMXAAASMMMMSMASAMAAMSMMAASAMSSSMMSSSMXMSMSM MMAMXAAAASASXMMSMMMXMXMSMSMMAMMSXMSMXSMMSASMMMAXXAAAXXSXXAXAMMMMXMAMXSMSAAAXMAMXAXMXMXAMMSASXSAMMXMSMMXXAAXXXSAXAMMMXXSSXAMAMXXAMAXAAMSAAAXA XMAMMMXMMSXMAAXXXSXMMAXAAAMAXSAMXXASMXMXMMMASMMMMXMMMMMXMXSXMSASMSSXAXMMMSSMXSXMMSMSMMXMXMAMXMMSMMAXXMSSSMMMXMSMSMSMSAMXMXSXMXSAMXMMAMSSMSMM MSASASMSASASXMMSSMASMMSMSMMMXXMASXAMMASAMXSAMAMXXMSMSASXMASMMSASAAMMSMAAAMAMAMAMAAAAMMSSSMSMXSAAAXXXXAMAMAAMSAMXXAAAMMMAXMAMXAMAMXMMXAXAMXAX AMASAMAMAXAMAMAXAMXMAMAXMASMMMXXXMMMSMMASAMXMAMMSSMAMAMXMXSAXMMMMMSAMSSMMSAMXSAMSMMMMXAAXAAASMSXSMMMSMMAMXMSMAMAMAMMMASAMXMXMXSAMXMAMSSMMSSM MMMMMMAMMSMSAMMSSMMSMMXMXAMXMXXXXASAMXSMMMSMSAMAMAMMMAMAXXXMXMXSXMMMXAXAXMXMASAMXMASXMMXMMMXMAXMAAAAXXMAMXSXXAMXXAMXMXMAMXXXXMXAXAXXSAAAAAAX XSXAASXMAAMXASAAAAASXSASASMASMMMMXMASAXSAXAMSXMSSSMXSMSMSMSMSMASAMAMMMMMXMMMXSSMSAMAAASASXSXMAMSSSMSSMSMSMSASXSXSMSXMSMSXMASXMSSSMSMMMSMMSXM AAMSMSXMMSXSAMMSMMMSASASAASASMAAAASXMASXMMAXSAXMAXMAXAAMAAAAAMASAMXSAXAAMMASXMASXAMSMMMASAMXMAMAAMAMXAAAMAMXMXMASAAAAAAXAAAMMAAMAAMAXMMXMAXS AXXXAXXXMAXMXMAMAMXMMMMMXAMXSXSXSASXMXMXMASASAMMAMSAMSMSMAMSMSMSXMXSMSASXSXSAMXSSXMAXAMXMXMAMMMMSMMMMSMSMXMASXMAMXSSMMAMAMASMXMSMMMSXMASXMAS ================================================ FILE: exm/aoc/2024/aoc_2024_04_questions.txt ================================================ ================================================ FILE: exm/aoc/2024/aoc_2024_05.adb ================================================ -- Solution to Advent of Code 2024, Day 5 ------------------------------------------ -- Print Queue -- -- https://adventofcode.com/2024/day/5 -- Copy of questions in: aoc_2024_05_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_05 is use AoC_Toolbox, HAT; type Rule_Line is record a, b : Integer; end record; rule : array (1 .. 2000) of Rule_Line; last : Natural := 0; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2024_05"; r : array (Part_Type) of Integer; procedure Read_Data (part : Part_Type) is dummy_separator : Character; f : File_Type; update : array (1 .. 100) of Natural; lu : Natural; already_correct, correct : Boolean; tmp : Integer; begin Open (f, input_name & ".txt"); last := 0; while not End_Of_File (f) loop last := last + 1; Get (f, rule (last).a); Get (f, dummy_separator); Get (f, rule (last).b); if End_Of_Line (f) then Skip_Line (f); exit when End_Of_Line (f); -- Empty line end if; end loop; lu := 0; while not End_Of_File (f) loop lu := lu + 1; Get (f, update (lu)); if End_Of_Line (f) or End_Of_File (f) then already_correct := True; loop correct := True; Scan : for i in 1 .. lu - 1 loop for j in i + 1 .. lu loop -- put(update (i)); -- put(update (j)); -- new_Line; for r in 1 .. last loop if rule (r).b = update (i) and then rule (r).a = update (j) then correct := False; already_correct := False; exit Scan when part = part_1; -- Swap the pages tmp := update (i); update (i) := update (j); update (j) := tmp; exit Scan; end if; end loop; end loop; end loop Scan; exit when correct or already_correct or part = part_1; end loop; -- Put_Line(ok); if already_correct then if part = part_1 then r (part_1) := r (part_1) + update ((lu + 1) / 2); end if; elsif correct and then part = part_2 then r (part_2) := r (part_2) + update ((lu + 1) / 2); end if; lu := 0; -- Clear data (update). else Get (f, dummy_separator); end if; end loop; Close (f); end Read_Data; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data (part_1); if not compiler_test_mode then Read_Data (part_2); end if; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 5166 -- Part 2: validated by AoC: 4679 end if; end AoC_2024_05; ================================================ FILE: exm/aoc/2024/aoc_2024_05.txt ================================================ 96|89 15|17 15|93 55|49 55|82 55|72 37|87 37|26 37|33 37|12 52|57 52|89 52|67 52|19 52|38 58|97 58|22 58|91 58|93 58|32 58|12 61|49 61|87 61|58 61|39 61|63 61|52 61|84 33|51 33|49 33|21 33|71 33|44 33|97 33|57 33|67 54|41 54|56 54|26 54|96 54|39 54|44 54|95 54|52 54|45 88|57 88|84 88|55 88|89 88|91 88|32 88|25 88|63 88|33 88|69 24|26 24|37 24|45 24|33 24|25 24|69 24|15 24|56 24|87 24|84 24|63 32|24 32|21 32|93 32|62 32|51 32|72 32|41 32|71 32|19 32|95 32|17 32|53 13|55 13|65 13|87 13|96 13|69 13|25 13|24 13|26 13|84 13|33 13|52 13|39 13|79 31|25 31|96 31|55 31|45 31|61 31|49 31|39 31|87 31|58 31|12 31|37 31|84 31|89 31|24 93|38 93|51 93|62 93|17 93|44 93|41 93|79 93|53 93|65 93|88 93|56 93|19 93|71 93|97 93|24 87|21 87|19 87|17 87|89 87|97 87|93 87|62 87|55 87|57 87|15 87|82 87|22 87|12 87|63 87|33 87|49 53|56 53|37 53|71 53|54 53|97 53|17 53|31 53|88 53|51 53|79 53|13 53|61 53|38 53|95 53|19 53|47 53|72 71|51 71|61 71|37 71|69 71|96 71|24 71|87 71|39 71|65 71|95 71|47 71|31 71|79 71|44 71|88 71|54 71|84 71|26 84|58 84|25 84|77 84|89 84|82 84|63 84|57 84|52 84|33 84|55 84|17 84|12 84|26 84|49 84|67 84|93 84|53 84|32 84|91 21|65 21|39 21|41 21|56 21|52 21|37 21|88 21|62 21|31 21|47 21|79 21|61 21|51 21|69 21|13 21|72 21|24 21|54 21|84 21|95 69|45 69|57 69|89 69|33 69|84 69|58 69|91 69|63 69|82 69|96 69|25 69|15 69|67 69|49 69|39 69|93 69|32 69|87 69|52 69|12 69|55 49|17 49|79 49|67 49|51 49|54 49|22 49|57 49|93 49|72 49|77 49|38 49|13 49|82 49|62 49|44 49|21 49|95 49|71 49|32 49|15 49|53 49|19 47|58 47|57 47|39 47|63 47|89 47|96 47|33 47|93 47|91 47|26 47|45 47|55 47|25 47|15 47|82 47|69 47|67 47|77 47|32 47|87 47|49 47|52 47|12 25|57 25|32 25|62 25|63 25|33 25|77 25|71 25|19 25|91 25|21 25|38 25|72 25|97 25|93 25|95 25|12 25|15 25|82 25|54 25|53 25|22 25|67 25|49 25|17 65|26 65|52 65|63 65|47 65|77 65|91 65|12 65|39 65|82 65|96 65|61 65|56 65|15 65|49 65|55 65|88 65|58 65|25 65|84 65|87 65|45 65|89 65|69 65|33 62|71 62|45 62|52 62|95 62|44 62|56 62|61 62|39 62|72 62|65 62|41 62|31 62|37 62|97 62|96 62|47 62|24 62|69 62|79 62|84 62|13 62|54 62|51 62|88 63|57 63|97 63|19 63|15 63|21 63|77 63|72 63|54 63|13 63|67 63|51 63|71 63|53 63|38 63|49 63|17 63|93 63|95 63|41 63|32 63|22 63|82 63|44 63|62 57|67 57|93 57|44 57|54 57|19 57|79 57|56 57|38 57|62 57|21 57|53 57|13 57|37 57|22 57|24 57|31 57|72 57|17 57|95 57|65 57|71 57|51 57|97 57|41 77|19 77|79 77|31 77|22 77|21 77|67 77|97 77|62 77|54 77|82 77|32 77|51 77|71 77|53 77|44 77|95 77|38 77|57 77|41 77|24 77|13 77|93 77|72 77|17 19|62 19|97 19|39 19|21 19|13 19|54 19|69 19|88 19|79 19|45 19|47 19|56 19|51 19|84 19|95 19|72 19|31 19|61 19|24 19|44 19|37 19|41 19|65 19|71 39|84 39|67 39|91 39|12 39|32 39|53 39|87 39|25 39|63 39|89 39|96 39|58 39|15 39|49 39|38 39|52 39|33 39|22 39|55 39|57 39|77 39|93 39|26 39|82 79|87 79|88 79|26 79|61 79|24 79|52 79|47 79|37 79|33 79|91 79|84 79|65 79|45 79|63 79|25 79|39 79|31 79|56 79|12 79|58 79|96 79|69 79|89 79|55 41|87 41|79 41|65 41|39 41|44 41|55 41|61 41|37 41|84 41|58 41|52 41|45 41|69 41|56 41|96 41|47 41|13 41|51 41|24 41|31 41|88 41|25 41|26 41|89 12|41 12|77 12|71 12|67 12|97 12|93 12|91 12|82 12|63 12|62 12|19 12|32 12|57 12|21 12|54 12|38 12|95 12|53 12|15 12|49 12|72 12|17 12|33 12|22 91|71 91|63 91|77 91|49 91|57 91|51 91|53 91|33 91|38 91|82 91|93 91|62 91|32 91|41 91|15 91|22 91|97 91|21 91|54 91|17 91|72 91|95 91|67 91|19 51|61 51|26 51|87 51|65 51|44 51|84 51|24 51|39 51|45 51|52 51|56 51|96 51|79 51|47 51|13 51|89 51|12 51|69 51|55 51|31 51|25 51|58 51|37 51|88 95|56 95|58 95|41 95|39 95|96 95|79 95|26 95|47 95|55 95|45 95|31 95|61 95|88 95|84 95|89 95|65 95|69 95|44 95|52 95|87 95|37 95|24 95|13 95|51 22|47 22|21 22|31 22|62 22|88 22|45 22|79 22|97 22|41 22|37 22|19 22|61 22|13 22|24 22|54 22|69 22|65 22|44 22|51 22|95 22|17 22|71 22|56 22|72 97|51 97|31 97|41 97|54 97|61 97|71 97|84 97|45 97|47 97|95 97|24 97|26 97|79 97|96 97|37 97|72 97|52 97|69 97|13 97|44 97|56 97|65 97|88 97|39 38|61 38|31 38|47 38|65 38|44 38|88 38|41 38|37 38|95 38|62 38|56 38|79 38|22 38|17 38|19 38|97 38|21 38|71 38|24 38|51 38|54 38|72 38|69 38|13 82|32 82|53 82|79 82|17 82|37 82|44 82|57 82|31 82|38 82|54 82|95 82|13 82|41 82|19 82|72 82|24 82|62 82|71 82|21 82|93 82|51 82|67 82|22 82|97 44|45 44|87 44|37 44|47 44|25 44|56 44|84 44|58 44|24 44|89 44|69 44|13 44|79 44|26 44|88 44|52 44|31 44|91 44|39 44|12 44|55 44|61 44|65 44|96 72|52 72|65 72|54 72|84 72|88 72|44 72|26 72|96 72|47 72|37 72|79 72|39 72|69 72|71 72|87 72|95 72|56 72|31 72|24 72|41 72|45 72|51 72|61 72|13 26|17 26|57 26|91 26|67 26|12 26|89 26|15 26|32 26|22 26|82 26|77 26|38 26|33 26|55 26|63 26|49 26|21 26|58 26|93 26|19 26|25 26|53 26|87 26|62 17|88 17|45 17|71 17|44 17|41 17|79 17|19 17|97 17|62 17|39 17|69 17|54 17|72 17|37 17|13 17|47 17|61 17|21 17|51 17|31 17|56 17|24 17|95 17|65 45|89 45|53 45|39 45|52 45|87 45|63 45|12 45|91 45|67 45|32 45|33 45|93 45|82 45|57 45|15 45|77 45|25 45|96 45|38 45|84 45|55 45|58 45|49 45|26 67|71 67|61 67|19 67|95 67|97 67|21 67|56 67|41 67|79 67|24 67|65 67|37 67|38 67|22 67|54 67|72 67|17 67|51 67|31 67|13 67|62 67|88 67|44 67|53 89|53 89|25 89|97 89|93 89|91 89|62 89|22 89|54 89|32 89|15 89|82 89|38 89|12 89|17 89|33 89|49 89|57 89|19 89|63 89|21 89|72 89|77 89|67 89|71 56|52 56|87 56|96 56|25 56|45 56|63 56|89 56|88 56|82 56|61 56|26 56|33 56|58 56|84 56|12 56|39 56|55 56|15 56|91 56|47 56|77 56|32 56|49 56|69 96|58 96|22 96|49 96|77 96|82 96|32 96|57 96|19 96|21 96|87 96|55 96|33 96|38 96|15 96|63 96|17 96|53 96|12 96|67 96|26 96|25 96|91 96|93 15|19 15|54 15|13 15|77 15|38 15|31 15|72 15|32 15|41 15|51 15|71 15|44 15|53 15|97 15|95 15|82 15|67 15|57 15|21 15|79 15|62 15|22 55|33 55|15 55|93 55|12 55|38 55|22 55|89 55|58 55|21 55|62 55|67 55|19 55|97 55|91 55|17 55|32 55|25 55|57 55|63 55|77 55|53 37|77 37|25 37|91 37|49 37|52 37|58 37|15 37|63 37|89 37|56 37|39 37|47 37|96 37|88 37|84 37|69 37|65 37|61 37|55 37|45 52|12 52|82 52|96 52|53 52|77 52|58 52|25 52|49 52|93 52|55 52|22 52|33 52|26 52|32 52|87 52|15 52|63 52|91 52|17 58|19 58|25 58|21 58|71 58|62 58|67 58|82 58|15 58|33 58|89 58|49 58|77 58|63 58|38 58|17 58|57 58|53 58|72 61|32 61|26 61|57 61|77 61|47 61|33 61|96 61|45 61|55 61|25 61|12 61|82 61|15 61|93 61|91 61|89 61|69 33|53 33|63 33|77 33|62 33|19 33|54 33|38 33|32 33|93 33|72 33|82 33|22 33|95 33|17 33|15 33|41 54|55 54|51 54|13 54|87 54|58 54|65 54|88 54|47 54|79 54|84 54|31 54|24 54|69 54|37 54|61 88|61 88|87 88|82 88|12 88|39 88|15 88|49 88|52 88|77 88|47 88|26 88|58 88|45 88|96 24|39 24|12 24|91 24|61 24|52 24|88 24|96 24|49 24|47 24|65 24|58 24|55 24|89 32|57 32|65 32|37 32|67 32|38 32|44 32|97 32|13 32|31 32|79 32|54 32|22 13|37 13|88 13|91 13|31 13|56 13|58 13|61 13|47 13|45 13|12 13|89 31|63 31|91 31|65 31|26 31|88 31|33 31|56 31|47 31|52 31|69 93|72 93|54 93|37 93|22 93|31 93|21 93|67 93|13 93|95 87|25 87|38 87|53 87|32 87|58 87|67 87|77 87|91 53|44 53|62 53|65 53|21 53|41 53|24 53|22 71|55 71|13 71|45 71|52 71|56 71|41 84|96 84|38 84|87 84|22 84|15 21|44 21|45 21|71 21|97 69|26 69|53 69|77 49|41 49|97 47|84 79,65,51,72,41,95,37,24,97,61,13,44,21,38,71,56,17,31,47,62,22,88,19 62,97,72,71,54,95,41,51,44,13,79,31,24,37,65,56,88,61,45,39,52 13,79,21,69,97,54,22,17,56,51,44,65,72,19,71,61,88,62,24,41,95 54,95,13,79,31,24,56,88,61,47,39,84,52,96,55 56,69,39,52,26,55,89,25,91,15,82 37,21,24,51,19,72,54,44,56,95,41,71,22,38,17,62,67,88,65,31,97 79,51,97,84,61,41,21,95,71,72,62 65,56,88,47,69,45,39,84,52,96,26,87,55,58,89,12,33,63,49,15,77 72,41,54,19,95,13,65,24,44,38,62,22,71,97,93,31,57,37,53,67,21 21,32,79,51,67,53,44,19,15 57,13,19,93,82,67,79,53,22,62,41,71,54,21,32,17,72,44,51,15,38 97,72,71,95,41,51,44,13,31,24,37,65,88,61,47,69,84,52,96 17,21,72,95,41,51,44,79,65,56,88,47,45 79,24,37,65,56,88,47,69,45,39,52,87,55,58,89,25,12,91,33 62,97,95,41,51,44,13,56,52 56,69,89,25,33,49,15,77,82 62,71,54,95,45,39,52 95,49,77,17,44,54,38,57,97,67,62,22,13,82,32,41,19 41,51,44,13,79,31,24,37,65,56,88,61,47,69,45,84,52,96,26,87,55,58,89 39,84,52,96,26,87,55,89,12,91,33,63,49,15,77,82,32,93,67,53,38 12,15,77,32,93,53,22,19,62 31,24,37,61,84,89,63 47,39,84,96,26,55,58,91,33,15,77,32,93 61,47,69,39,58,25,91,33,49,15,77,32,57 12,91,25,96,45,13,58 33,77,57,38,19,62,72 51,67,71,19,53,54,32,93,17 37,65,56,88,47,69,39,84,52,96,26,87,58,89,25,12,91,33,63,49,15 15,77,57,93,17,21,62,97,54,95,13 87,88,65,26,13,58,39,37,47,55,25,89,51 63,19,72,89,49,25,15,67,62 41,51,79,37,45,52,89 31,65,56,88,61,47,69,45,39,52,26,87,55,58,89,25,12,91,63 91,32,55,77,25 96,91,52,37,84,31,12,55,39,87,89,69,24,25,65,88,47,45,33,58,26,79,56 63,25,15,56,61,45,96,52,87,88,39,49,58,26,89,91,84,69,47,77,65 26,87,55,89,33,49,15,82,32,57,93,53,38,22,17,19,21 12,32,82,53,57,96,15,52,91,63,33 62,45,61,44,54,88,52,97,69 67,22,19,21,62,97,54,95,51,44,79,24,37,56,88 41,51,44,13,79,31,65,56,88,61,69,45,39,84,52,96,26,87,55,58,89 56,63,52,33,47,82,58 38,93,15,84,57,22,89,91,26,53,67,96,82,77,25,32,63,58,33 53,82,67,32,58,87,22,38,93,26,25,57,91,96,33,63,49,89,12,19,17,55,15 96,26,55,58,89,25,91,33,63,15,77,57,93,67,53,38,17 33,49,15,77,93,53,38,22,97,71,54,41,51 26,87,58,89,12,91,33,77,32,57,93,67,53,38,21 61,47,69,39,87,55,58,89,33,63,15,82,57 44,38,15,51,53,72,62,22,95,93,41,17,71,82,97,19,13,32,21,79,57,54,67 41,95,54,52,39,56,26,72,71,37,65,24,51,13,88 24,65,88,45,39,84,52,26,55,58,89,25,12,91,33,63,49 24,52,55,87,56,89,65,33,84,12,58,39,45,88,31,91,37,25,79,47,96,61,26 88,39,24,63,25,61,33,37,56,96,31 21,62,97,72,54,41,51,44,31,24,37,65,56,61,47,69,45,39,84 88,61,69,45,39,84,52,96,26,87,55,58,89,25,12,91,33,63,49,77,32 67,96,15,93,87,52,39,26,69,77,58,32,91,82,63,84,12,55,57 38,93,51,71,31,97,57,21,72,13,41,44,65 84,96,87,89,12,33,63,49,15,77,32,57,53 61,47,39,55,25,12,33,82,57 89,25,12,49,32,67,38,19,62 82,93,97,71,54,79,24 89,91,55,25,12,32,97,63,93 62,97,72,54,95,41,51,44,13,79,31,24,65,88,61,45,39,84,52 97,93,71,21,67,95,54,33,91,22,72,32,82,63,53,12,57,77,49 13,24,47,69,84,96,87,58,25,12,91 65,25,89,37,24,58,55,49,69,63,61,87,56,33,39 13,49,54,32,22,62,19,44,97,57,38,71,15,51,82,93,21,53,67 87,55,89,25,12,91,33,63,49,15,77,82,32,57,93,67,53,38,19,21,62 91,63,49,38,17,97,41 93,67,53,38,22,17,19,21,62,97,72,71,54,41,44,13,31,24,37,65,56 84,52,26,87,58,89,25,12,91,33,63,15,82,32,93,67,53,38,22 22,17,21,62,97,71,95,41,51,44,79,24,65,56,61,47,69 51,89,45,69,26,56,24,88,61,47,39,31,44,65,96,25,55,37,58 88,31,56,69,26,13,39,37,96,55,45,61,58,24,65 21,24,41,72,93,53,17,65,13,54,62,95,38,57,37,31,97,19,71,22,67,51,79 15,77,22,91,67,17,49,82,72,12,32 32,93,67,53,22,17,19,21,62,71,54,41,51,13,24 31,24,56,88,61,45,39,96,26,87,55,89,25,12,91,33,63 72,95,41,51,44,13,31,24,37,65,56,88,47,69,39 88,58,52,24,26,13,89,25,39,84,45 21,62,51,13,37,65,84 33,77,82,32,67,38,17,97,71,95,51 12,33,91,53,21,82,32,15,57,93,17,38,77,67,89,87,62,25,58 79,26,55,24,39,88,89,51,31,47,52,58,37,25,56,61,84,44,13 56,31,45,39,91,52,79,12,96,69,13,37,25,88,87,89,24,65,58,84,61 53,38,17,97,71,54,41,13,24 89,93,53,33,87,25,77,57,63,19,91,15,22,38,21,12,58,32,67,82,17 71,97,79,17,13,54,44,41,22,21,93,57,32,38,31 97,72,71,54,95,51,44,79,65,56,88,69,45,52,96 77,87,49,25,67,89,15,33,55,93,17,91,38,12,82,53,63,26,52,96,22 49,77,82,32,53,62,41,51,13 39,57,55,89,82,25,93,49,96,45,58,33,53,67,12,77,91 17,31,21,95,69,41,61,79,13,72,47,88,97,44,62,65,51,45,24 25,12,91,33,63,77,82,32,57,93,67,53,38,22,19,21,62,97,72,71,54 62,71,54,41,51,24,37,65,88 41,44,13,79,65,56,61,69,45,52,96,26,87,58,89 62,72,51,44,88,61,84 37,65,56,61,47,69,45,52,96,26,87,55,33,49,15 47,69,45,96,26,55,58,25,12,63,49,15,77,82,93 37,26,52,65,55,15,63 19,57,17,77,67,58,22,72,12,62,53 56,41,72,96,47,97,88,24,52,84,45,37,51 32,53,21,62,95,41,44,79,37 38,22,62,72,79,41,37,53,56,24,44,19,51,31,97,54,71 96,39,58,25,61,55,13,47,65,84,52,12,89,87,56,91,45,69,37 45,67,32,93,63,53,96 79,95,69,96,54,87,71,26,52,65,41,44,31,24,51,84,61,37,56 32,93,17,19,97,71,54,95,44,79,24 45,63,25,69,58,93,87,33,12,49,84,55,47,89,26 61,56,58,37,44,95,26,31,96,87,39,65,52,51,88,84,13,45,24,41,47,79,69 31,61,58,33,47,24,79,52,87,89,91 63,84,52,32,77,93,91,87,96,53,55,57,82,12,26,22,67,89,25 71,54,95,51,24,88,47,69,84,52,26 69,45,39,84,52,96,26,87,55,58,89,12,63,49,15,77,82,32,57,93,67 25,12,82,57,93,53,54 62,97,54,95,44,13,24,65,56,69,45,84,52 26,87,89,25,12,49,53,38,22,19,21 79,56,88,47,69,96,89,12,33 57,93,53,38,19,62,71,54,41,44,79,31,65 15,77,32,22,19,62,97,72,71,54,95,41,51,13,79 49,77,32,93,67,53,17,62,97,72,71,51,13 26,25,89,49,58,24,37 25,12,33,63,49,15,82,32,93,67,38,22,21,62,97,71,54 13,31,24,37,65,56,88,61,47,45,39,84,26,87,58,89,25,12,91 51,44,24,65,56,88,47,96,87 71,54,51,44,13,79,31,65,88,61,47,69,39,52,26 55,89,25,12,91,33,63,49,77,82,32,57,93,53,38,22,17,19,21,62,97 19,62,71,95,51,13,79,31,37,56,61,45,39 33,63,15,77,67,17,97,71,51 93,17,62,54,51,44,31,24,56 51,93,19,53,13,21,95,44,67,41,17,24,31,22,38,62,79,72,56,65,37 49,12,63,97,72,91,21,15,57,93,19,32,71,82,77,22,62,53,67,38,25,17,54 93,62,41,54,53,67,72,17,71,91,97 63,15,97,54,95,41,44 26,61,84,54,45,41,51,52,87,37,13,47,88,39,56,65,55 89,25,12,91,33,63,49,77,82,32,57,93,67,53,38,22,17,19,21,62,97,72,71 25,49,72,53,71,57,91,15,17,82,22,67,54,38,62,63,77 88,47,96,26,58,91,33,77,82 71,53,67,54,72,95,21,17,41 97,72,71,54,95,41,51,44,13,79,24,37,65,56,88,61,47,69,45,39,84,52,96 71,54,51,13,79,37,56,47,69,26,87 89,96,24,56,47,33,49,65,87 69,45,39,84,52,26,87,55,91,33,57,93,67 24,38,57,13,22,19,53,37,44,72,31,65,97,21,67,79,51,62,41,17,71,93,54 13,12,25,84,79,96,55,65,89,44,24,31,61,88,39 91,87,57,49,19,15,62,53,89 26,87,58,89,25,12,91,33,77,82,57,93,67,53,38,22,17,19,21 84,51,26,69,44,72,61,31,95,88,47,41,39 15,67,33,38,52,53,32,12,17 12,53,82,19,95,49,54,72,33,21,63,32,67 32,93,53,22,21,72,54,95,51,44,79,31,37 49,77,57,38,97,72,54,51,13 31,37,56,88,61,47,69,84,52,96,87,55,58,91,63 13,71,24,88,44,79,19,72,95,65,56,41,67,21,31,62,54 63,49,15,77,82,32,57,93,67,53,38,22,17,19,21,62,97,72,71,95,41,51,44 65,13,26,69,56,96,87,37,31,84,24,71,95 61,96,89,91,33 26,89,93,57,52,12,91,63,53,33,15,49,82,67,39,84,55,87,96,25,45,58,77 52,91,82,25,88,77,45,55,32 71,19,62,95,77,57,79,13,97,72,41 53,38,22,17,19,62,97,72,71,54,95,41,51,44,13,79,31,24,37,65,56,88,61 53,19,21,62,97,72,71,54,95,41,51,44,13,79,31,37,65,88,61 44,71,67,54,51,77,82,72,31,38,32 93,82,63,67,25,72,49,62,12,33,53,58,57,21,38,22,19 19,21,62,71,41,24,37,65,56,88,61,47,69,45,39 95,17,54,57,21,72,63,82,32,51,44,38,77,62,67,71,41 15,63,88,12,39,37,91 52,96,87,55,49,15,32,93,53,38,17 63,55,91,89,45,31,56,65,26,96,37 32,57,93,67,38,22,17,19,21,62,97,72,71,54,41,44,13,24,37 69,12,32,87,88,77,47,58,96,89,49,84,39 12,91,63,49,32,17,62,97,71,54,95 31,19,44,47,71,51,62,17,97,88,37,79,61,24,22,13,21,65,56 45,12,25,26,84,13,24,65,37,58,79,87,44,55,39 ================================================ FILE: exm/aoc/2024/aoc_2024_05_questions.txt ================================================ --- Day 5: Print Queue --- Satisfied with their search on Ceres, the squadron of scholars suggests subsequently scanning the stationery stacks of sub-basement 17. The North Pole printing department is busier than ever this close to Christmas, and while The Historians continue their search of this historically significant facility, an Elf operating a very familiar printer beckons you over. The Elf must recognize you, because they waste no time explaining that the new sleigh launch safety manual updates won't print correctly. Failure to update the safety manuals would be dire indeed, so you offer your services. Safety protocols clearly indicate that new pages for the safety manuals must be printed in a very specific order. The notation X|Y means that if both page number X and page number Y are to be produced as part of an update, page number X must be printed at some point before page number Y. The Elf has for you both the page ordering rules and the pages to produce in each update (your puzzle input), but can't figure out whether each update has the pages in the right order. For example: 47|53 97|13 97|61 97|47 75|29 61|13 75|53 29|13 97|29 53|29 61|53 97|53 61|29 47|13 75|47 97|75 47|61 75|61 47|29 75|13 53|13 75,47,61,53,29 97,61,53,29,13 75,29,13 75,97,47,61,53 61,13,29 97,13,75,29,47 The first section specifies the page ordering rules, one per line. The first rule, 47|53, means that if an update includes both page number 47 and page number 53, then page number 47 must be printed at some point before page number 53. (47 doesn't necessarily need to be immediately before 53; other pages are allowed to be between them.) The second section specifies the page numbers of each update. Because most safety manuals are different, the pages needed in the updates are different too. The first update, 75,47,61,53,29, means that the update consists of page numbers 75, 47, 61, 53, and 29. To get the printers going as soon as possible, start by identifying which updates are already in the right order. In the above example, the first update (75,47,61,53,29) is in the right order: 75 is correctly first because there are rules that put each other page after it: 75|47, 75|61, 75|53, and 75|29. 47 is correctly second because 75 must be before it (75|47) and every other page must be after it according to 47|61, 47|53, and 47|29. 61 is correctly in the middle because 75 and 47 are before it (75|61 and 47|61) and 53 and 29 are after it (61|53 and 61|29). 53 is correctly fourth because it is before page number 29 (53|29). 29 is the only page left and so is correctly last. Because the first update does not include some page numbers, the ordering rules involving those missing page numbers are ignored. The second and third updates are also in the correct order according to the rules. Like the first update, they also do not include every page number, and so only some of the ordering rules apply - within each update, the ordering rules that involve missing page numbers are not used. The fourth update, 75,97,47,61,53, is not in the correct order: it would print 75 before 97, which violates the rule 97|75. The fifth update, 61,13,29, is also not in the correct order, since it breaks the rule 29|13. The last update, 97,13,75,29,47, is not in the correct order due to breaking several rules. For some reason, the Elves also need to know the middle page number of each update being printed. Because you are currently only printing the correctly-ordered updates, you will need to find the middle page number of each correctly-ordered update. In the above example, the correctly-ordered updates are: 75,47,61,53,29 97,61,53,29,13 75,29,13 These have middle page numbers of 61, 53, and 29 respectively. Adding these page numbers together gives 143. Of course, you'll need to be careful: the actual list of page ordering rules is bigger and more complicated than the above example. Determine which updates are already in the correct order. What do you get if you add up the middle page number from those correctly-ordered updates? --- Part Two --- While the Elves get to work printing the correctly-ordered updates, you have a little time to fix the rest of them. For each of the incorrectly-ordered updates, use the page ordering rules to put the page numbers in the right order. For the above example, here are the three incorrectly-ordered updates and their correct orderings: 75,97,47,61,53 becomes 97,75,47,61,53. 61,13,29 becomes 61,29,13. 97,13,75,29,47 becomes 97,75,47,29,13. After taking only the incorrectly-ordered updates and ordering them correctly, their middle page numbers are 47, 29, and 47. Adding these together produces 123. Find the updates which are not in the correct order. What do you get if you add up the middle page numbers after correctly ordering just those updates? ================================================ FILE: exm/aoc/2024/aoc_2024_06.adb ================================================ -- Solution to Advent of Code 2024, Day 6 ------------------------------------------- -- Guard Gallivant -- -- https://adventofcode.com/2024/day/6 -- Copy of questions in: aoc_2024_06_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_06 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 10; input_name : constant VString := +"aoc_2024_06"; n : constant := 130; map : array (1 .. n, 1 .. n) of Character; d0 : Direction; x0, y0 : Positive; r : array (Part_Type) of Integer; procedure Read_Data is f : File_Type; c : Character; begin Open (f, input_name & ".txt"); for y in reverse 1 .. n loop for x in 1 .. n loop Get (f, c); map (x, y) := c; if c = '^' then x0 := x; y0 := y; d0 := north; end if; end loop; end loop; Close (f); end Read_Data; verbose : constant Boolean := False; visited : array (1 .. n, 1 .. n) of Natural; procedure Show_Map (ox, oy : Integer) is begin for y in reverse 1 .. n loop for x in 1 .. n loop if visited (x, y) > 0 then Put ('X'); elsif ox = x and then oy = y then Put ('O'); else Put (map (x, y)); end if; end loop; New_Line; end loop; Put (r (part_2)); New_Line; end Show_Map; procedure Do_Part_1 is x, y, nx, ny : Integer; d : Direction; begin for yy in 1 .. n loop for xx in 1 .. n loop visited (xx, yy) := 0; end loop; end loop; x := x0; y := y0; d := d0; loop visited (x, y) := visited (x, y) + 1; case d is when north => nx := x; ny := y + 1; when east => nx := x + 1; ny := y; when south => nx := x; ny := y - 1; when west => nx := x - 1; ny := y; end case; exit when nx not in 1 .. n or else ny not in 1 .. n; if map (nx, ny) = '#' then d := Turn_Right (d); else x := nx; y := ny; end if; end loop; for yy in 1 .. n loop for xx in 1 .. n loop if visited (xx, yy) > 0 then r (part_1) := r (part_1) + 1; end if; end loop; end loop; if verbose then Show_Map (0, 0); end if; end Do_Part_1; procedure Do_Part_2 is x, y, nx, ny : Integer; d : Direction; begin for obs_x in 1 .. n loop for obs_y in 1 .. n loop if map (obs_x, obs_y) = '.' then -- Free cell: set obstacle here. for yy in 1 .. n loop for xx in 1 .. n loop visited (xx, yy) := 0; end loop; end loop; x := x0; y := y0; d := d0; loop visited (x, y) := visited (x, y) + 1; if visited (x, y) > 4 then -- We arrived on this cell at least twice from the same direction. r (part_2) := r (part_2) + 1; exit; end if; case d is when north => nx := x; ny := y + 1; when east => nx := x + 1; ny := y; when south => nx := x; ny := y - 1; when west => nx := x - 1; ny := y; end case; exit when nx not in 1 .. n or else ny not in 1 .. n; if map (nx, ny) = '#' or else (nx = obs_x and then ny = obs_y) then d := Turn_Right (d); else x := nx; y := ny; end if; end loop; if verbose then Show_Map (obs_x, obs_y); end if; end if; end loop; end loop; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; Do_Part_1; if not compiler_test_mode then Do_Part_2; end if; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 5461 -- Part 2: validated by AoC: 1836 end if; end AoC_2024_06; ================================================ FILE: exm/aoc/2024/aoc_2024_06.txt ================================================ ....#.................#......................#..........................#..................#....##..#...........#................. ...................................#...............................#......#..#...............................#.................... ..........................#................#......##.....#.....................................#...............#..#............... .......................................................................................................#.......................... ...................#....#.........................#..............#.....#......................................................#... .....#.........................................................................................................#.................. .........................................................#....................#..#............#................#.................. ..............#...............#..................................................................#......#......................... .........#.....#.......#......#.......................#.............#..#........#.......#............#.......#....#..#.......#.... ........................#....#...............................................#...#.#.........................................#.... .........................#........................................................................#.....................#......... .#..........#...#...............#..................#...#......#.................................#....................#.......#.... ............................................................#......#.........................................................#.... .......................#...#..................#.#.............#......................#.............#.............................. ............................................................................................................#.........#........... ....#..................###........#.............................#.#....................#..........#.....................#......... ................................................................................................#.......................#.#....... ..........................................................................#........#...#.................#.......#................ ..........................#.#..#.#...............................................#..........#..............................#...... ..............#........#.#...............#............................#..........#....................................#........#.# #..................................................................................................#...........#................#. ...............................................#........................................#.................................#....... .....#..#......#.......#..............#........#........#...........................................................#............. .......#..........#.......#.#...........#................#.................................................#...................... ....#.....#...............#....#.......#...#.............................................................#...................#.... ............................................#....#.......#................................#......#......................#.....#... .....................#...................................#....#...........................................................#....... ..#..............................#...........#...........................#.................................#...................... ........#.............................##...................#.....................#................................................ ................#.#.#......#...............................................#...###.........#....#................................. .......#.............#.............#...........#..#...............................#..................................#.....#.....# .....#...#.......#.........................................#..............................#........................#.............# ...............................................#.....#..............................................................#............. .........#.......................................#.......................#...........#............................................ .......................#.....#.....................................................#....................................#......... .............................#......................#.....................#..............#..#.......................#............. ......#......................................#.......#.....................#.....#...........#..........#.....................#... ..................................................#....................#.......#....#.......#...#................................. ......................................#......#........#.....#........................................#.............#.............. #......................#.#..............#.....#.........#...............................#...............................#......... #......#...............#.........................................................................................#..#............. .#..............................................#.................#.......#....................................................... ...#.......#.....#.............#...................................................................................#.............. ..........................#........#........#.....................................#........................#..............#..#.... .......#..........#.......#...................................................#.##.....#.#.........#....#.................#....... ..##...................#.......................................#..............#.#........#........................................ #.......#..............#...........#.....#....#....#............#........#..................................#.#.........#......... ..................#.......................................................................................................#....... ............................#.........#....................#...............................#..........#........................... .............#.....................................................................#.....#.................#...................... ...#...#............#..........................#..........................................#....................................... ..#.............#.#........................#...#.......................#.........#....................##....#..................... ...........................................................................................................#.........#...#........ .............................#.#..........................................................................................#....... ....................#........................#.#......#...............#......#.............................#...................... ....#...#.......#..................#..........................................................#........................#.......... .#...........#..............................................#...........................................#......................... ..............................#...........#...........................................#.........#...........................#....# ............#.......#......#....#.......................................................................#......................... .........................................#...#..................#..................#.....................................#........ ................#..................#........#.........................#...................#......................................# ............................................................#.....#........#...................................................... ..............................#............#.........................................#.............#.......#..#................... ...#............#........................................................................#..................................#....# ..............................#.......#.............#.................................................#........................... .....#.................................................#..........#...............................#..##..........................# .............#.........................................................#.............................#..#..............#........#. ....................#...............#................................................................................#....#......# ........#....#..#...........................................................................#................#..............#..... ....#......................#...............#..........#......#.........#..^....#..........#..................#.......#............ ...........................#.#...................................................#...............................#................ #..#.........................................................#.....#........................#..................................... .#.#....#.......................................#......#..........#................#..#........................................... ...#.....#..........#...................#.......#............................#.................................................... .............#......................................................#............#.....................#.....................#.... ...................#.............................................................................................#................ ...................#.....#...................................................................................................#.... ................#............#......................#.......#..................#..#.....................#..............#........#. #....#...................................................................#.......##....#..........#............................... .........................................#............#......#.......................#........#..............#.#.................. .##........#.....#...........................................................................................#..............#..... #...........................................................#.......#....#......#..#...................................#..#.#..... .............#........................................#...............................#........................................... ......................#..................................................................#..................................#..... ...#.#........................................#.................................................................................#. .............#.......................#............................#.#................................#.......#..#...........#..... ...#..#...............................................................................#................#.......................... .......#.............................#............#..#........#.....#.........................#..................#................ ......#...............................................................................##.................................#....#... ........#..................#.......................................................................#......#..........#............ ...........#.......#........#..........................................#........#..............#.................#.........#...... ...................#..............................#...............................#.....................#.....#................... .............#..#..................#.#..#.....#..#..........................................................................#..... ..............................#...................................................#.......................#..............#........ .......#......................#.............................#...........................#.....#...#.................#........#.... .........#.......#....##.......................................................................................................... ........................................................................#......................#.................................. .......................#..........##.#................................................#..#.....#......#......#.................#.. ......................................#......................................................................#.................... .....................................#....#...............................................#...#.....#.......#...#...........#..... ...................#..#................................................................................#.......................... ..............#.................#..............................#..............#...........#.#..................#...#.............# ................#..#......#.........................#.....#.....#..............#..#.........................................#..... .....#.........................#........................................#.....#.......#...........#...................#........... ......#....................##......................................................................................#.............. ............................................................................###...............................#................... #..................................#......#..............................................................................#.......# .....#...................#.....#............................................................#.....................#...#........... .......#......#........................#.....................#.#..##............#......#.................#.....................#.. .....#..............#.................#........#..................#..#..........................##.....#..#...................#... ........#................#................#...........#.........................................#....................#............ .........#.........#....#................#........#........#...............#....#................................................. ...........#...#............#..................#.............................#.#..#....................#.#........................ .#............#..#..#................#.#................................................................##.............#.......... ...........#.......................#.........................................................#.................................... ..#..........................#...........#......#................................#.#.............................................. ............................................................#..................#...........#.....##.................#............. ....#.........#............................##..........................................#.....#....#..........#.................... ..................#..............#........#........#....................#..............#....................#..................... ....#...................................#.....................................................#.............#...................#. .........#...........#...#.............................#.............##..#................................................#.#..... ............................##..............#................#..#........................................#....................#... .............................#.#......................................................##.....#..................................#. .............................................................................#..................#...#.................#........... ........................#...........#..................#......#................................................................... .....#.......................#......#................#............#..................#.................................#.......... #..........#...................................................................#...................#...#...............#.......... ....................#............................................#...............#........................##....#..#.............. .#.....#............................#...............#.#.#..........................#.........#..............#..................... .............................#....................................#..#......#........................#............................ ================================================ FILE: exm/aoc/2024/aoc_2024_06_questions.txt ================================================ --- Day 6: Guard Gallivant --- The Historians use their fancy device again, this time to whisk you all away to the North Pole prototype suit manufacturing lab... in the year 1518! It turns out that having direct access to history is very convenient for a group of historians. You still have to be careful of time paradoxes, and so it will be important to avoid anyone from 1518 while The Historians search for the Chief. Unfortunately, a single guard is patrolling this part of the lab. Maybe you can work out where the guard will go ahead of time so that The Historians can search safely? You start by making a map (your puzzle input) of the situation. For example: ....#..... .........# .......... ..#....... .......#.. .......... .#..^..... ........#. #......... ......#... The map shows the current position of the guard with ^ (to indicate the guard is currently facing up from the perspective of the map). Any obstructions - crates, desks, alchemical reactors, etc. - are shown as #. Lab guards in 1518 follow a very strict patrol protocol which involves repeatedly following these steps: If there is something directly in front of you, turn right 90 degrees. Otherwise, take a step forward. Following the above protocol, the guard moves up several times until she reaches an obstacle (in this case, a pile of failed suit prototypes): ....#..... ....^....# .......... ..#....... .......#.. .......... .#........ ........#. #......... ......#... Because there is now an obstacle in front of the guard, she turns right before continuing straight in her new facing direction: ....#..... ........># .......... ..#....... .......#.. .......... .#........ ........#. #......... ......#... Reaching another obstacle (a spool of several very long polymers), she turns right again and continues downward: ....#..... .........# .......... ..#....... .......#.. .......... .#......v. ........#. #......... ......#... This process continues for a while, but the guard eventually leaves the mapped area (after walking past a tank of universal solvent): ....#..... .........# .......... ..#....... .......#.. .......... .#........ ........#. #......... ......#v.. By predicting the guard's route, you can determine which specific positions in the lab will be in the patrol path. Including the guard's starting position, the positions visited by the guard before leaving the area are marked with an X: ....#..... ....XXXXX# ....X...X. ..#.X...X. ..XXXXX#X. ..X.X.X.X. .#XXXXXXX. .XXXXXXX#. #XXXXXXX.. ......#X.. In this example, the guard will visit 41 distinct positions on your map. Predict the path of the guard. How many distinct positions will the guard visit before leaving the mapped area? --- Part Two --- While The Historians begin working around the guard's patrol route, you borrow their fancy device and step outside the lab. From the safety of a supply closet, you time travel through the last few months and record the nightly status of the lab's guard post on the walls of the closet. Returning after what seems like only a few seconds to The Historians, they explain that the guard's patrol area is simply too large for them to safely search the lab without getting caught. Fortunately, they are pretty sure that adding a single new obstruction won't cause a time paradox. They'd like to place the new obstruction in such a way that the guard will get stuck in a loop, making the rest of the lab safe to search. To have the lowest chance of creating a time paradox, The Historians would like to know all of the possible positions for such an obstruction. The new obstruction can't be placed at the guard's starting position - the guard is there right now and would notice. In the above example, there are only 6 different positions where a new obstruction would cause the guard to get stuck in a loop. The diagrams of these six situations use O to mark the new obstruction, | to show a position where the guard moves up/down, - to show a position where the guard moves left/right, and + to show a position where the guard moves both up/down and left/right. Option one, put a printing press next to the guard's starting position: ....#..... ....+---+# ....|...|. ..#.|...|. ....|..#|. ....|...|. .#.O^---+. ........#. #......... ......#... Option two, put a stack of failed suit prototypes in the bottom right quadrant of the mapped area: ....#..... ....+---+# ....|...|. ..#.|...|. ..+-+-+#|. ..|.|.|.|. .#+-^-+-+. ......O.#. #......... ......#... Option three, put a crate of chimney-squeeze prototype fabric next to the standing desk in the bottom right quadrant: ....#..... ....+---+# ....|...|. ..#.|...|. ..+-+-+#|. ..|.|.|.|. .#+-^-+-+. .+----+O#. #+----+... ......#... Option four, put an alchemical retroencabulator near the bottom left corner: ....#..... ....+---+# ....|...|. ..#.|...|. ..+-+-+#|. ..|.|.|.|. .#+-^-+-+. ..|...|.#. #O+---+... ......#... Option five, put the alchemical retroencabulator a bit to the right instead: ....#..... ....+---+# ....|...|. ..#.|...|. ..+-+-+#|. ..|.|.|.|. .#+-^-+-+. ....|.|.#. #..O+-+... ......#... Option six, put a tank of sovereign glue right next to the tank of universal solvent: ....#..... ....+---+# ....|...|. ..#.|...|. ..+-+-+#|. ..|.|.|.|. .#+-^-+-+. .+----++#. #+----++.. ......#O.. It doesn't really matter what you choose to use as an obstacle so long as you and The Historians can put it into position without the guard noticing. The important thing is having enough options that you can find one that minimizes time paradoxes, and in this example, there are 6 different positions you could choose. You need to get the guard stuck in a loop by adding a single new obstruction. How many different positions could you choose for this obstruction? ================================================ FILE: exm/aoc/2024/aoc_2024_07.adb ================================================ -- Solution to Advent of Code 2024, Day 7 ------------------------------------------- -- Bridge Repair -- -- https://adventofcode.com/2024/day/7 -- Copy of questions in: aoc_2024_07_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_07 is use AoC_Toolbox, HAT, Interfaces; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2024_07"; n : constant := 100; r : array (Part_Type) of Integer_64; type Row_Type is array (1 .. n) of Integer_64; compiler_test_mode : constant Boolean := Argument_Count >= 1; procedure Read_Data is left : Integer_64; len_left : Integer; data : Row_Type; last : Natural := 0; function Check_1 return Boolean is b : Integer; x : Integer_64; begin if last = 1 and then left = data (1) then return True; end if; for i in 0 .. 2 ** (last - 1) - 1 loop b := i; x := data (1); for pos in 2 .. last loop if b mod 2 = 0 then x := x + data (pos); else x := x * data (pos); end if; exit when x > left; -- Too big, give up. b := b / 2; end loop; if x = left then return True; end if; end loop; return False; end Check_1; function Check_2 return Boolean is b : Integer; x : Integer_64; concat : VString; begin if last = 1 and then left = data (1) then return True; end if; for i in 0 .. 3 ** (last - 1) - 1 loop b := i; x := data (1); for pos in 2 .. last loop case b mod 3 is when 0 => x := x + data (pos); when 1 => x := x * data (pos); when others => -- 0 concat := Image (x) & Image (data (pos)); if Length (concat) > len_left then -- Too big, give up. x := 0; exit; end if; x := Integer_64'Value (To_String (concat)); end case; exit when x > left; -- Too big, give up. b := b / 3; end loop; if x = left then return True; end if; end loop; return False; end Check_2; dummy_separator : Character; f : File_Type; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop if last = 0 then Get (f, left); Get (f, dummy_separator); len_left := Length (Image (left)); end if; last := last + 1; Get (f, data (last)); if End_Of_Line (f) or End_Of_File (f) then if Check_1 then r (part_1) := r (part_1) + left; end if; if (not compiler_test_mode) and then Check_2 then r (part_2) := r (part_2) + left; end if; last := 0; -- Clear data (calculator terms & factors). end if; end loop; Close (f); end Read_Data; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put (+"Part 1:"); Put (r (part_1)'Image); New_Line; Put (+"Part 2:"); Put (r (part_2)'Image); New_Line; -- Part 1: validated by AoC: 850435817339 -- Part 2: validated by AoC: 104824810233437 end if; end AoC_2024_07; ================================================ FILE: exm/aoc/2024/aoc_2024_07.txt ================================================ 12427056279= 3 5 3 8 3 22 1 651 5 3 1 6 554266023266= 835 7 40 9 7 66 323 3 6 156802= 957 23 8 2 5 451396= 2 21 3 3 4 969 8 8 3 11 4 541800= 6 8 8 350 8 7 2 7 4 5 5 502= 43 53 5 397 4 564543133= 3 4 47 54 3 133 185183376789= 47 3 775 7 4 939 202 7 10300720= 359 30 5 16 331 10114285876= 8 80 7 2 19 3 2 861 3 4 6 6658354= 4 62 5 8 354 1679555006712= 7 4 7 9 4 17 8 883 3 2 2 6 3281626= 4 1 8 1 5 6 242 5 7 6 45 646984854= 1 6 767 4 924 50 2 6 9 15435205= 8 6 2 6 97 117 1 5 9 8 1 5 323223= 2 7 6 197 3 381 27 3 14719245= 801 75 4 31 6 163 7 2 384800550= 513 83 590 129 5 843710637122= 71 2 965 5 12 998 4 1 3 2785998= 15 9 1 2 25 70 1 20879049= 2 52 28 6 1 533 9 6 9 9 28589067= 227 894 5 70 51 7231832= 677 763 7 59 2 1131570= 8 64 691 26 8 33 99 9 448728996= 6 82 57 76 80 16 1 35 38586511= 86 437 653 351 511 1017223= 77 4 25 33 20416= 48 78 451 74 46 7 29 56987487= 63 1 2 42 67 8 1 962 9 6098476= 69 63 660 14 5 76 1395810072= 442 510 4 1 5 43 4 6 6 49896817= 557 56 3 81 72 7 88 3849663743508= 3 1 81 2 8 6 373 1 3 51 1 1963977= 9 68 48 74 4 209 8 11735601= 446 49 537 5853= 50 58 3 1 18 2945091= 999 5 7 1 88 4 7 7 3 408 385659= 3 9 1 6 8 5 7 9 2 597 34 13416= 41 9 4 8 6 6845472302= 97 93 215 684 302 1112504= 74 2 87 7 472 54440= 4 2 9 35 8 9 445835058612= 7 43 6 341 9 586 11 6027221856= 41 4 7 882 9 5 9 8 9 888 26490050= 37 8 1 2 8 11 5 1 1 2 4 5200= 2 29 89 1 38 9746919= 6 4 7 78 3 284 945 7 27 1356978= 50 5 89 241 3 4 28681= 75 370 27 8 896 113054413= 226 5 5 43 90 21 1692= 4 49 98 7 635 1789551225= 97 13 5 5 499 7 9 99 152347805= 6 397 4 895 3 353 1 39 655047= 39 145 479 988 3 4835382339= 73 80 468 4 3 2 14 8 29 13503378578= 424 13 309 78 578 932087= 97 834 1 8 2 87 2828= 4 9 4 4 7 2663212860= 329 52 296 1 5 89 90 8879504= 88 1 78 1 501 4992196576175= 21 4 2 9 5 8 5 70 62 81 8 25625354= 1 75 81 1 2 53 54 546379203959= 6 3 3 712 3 8 36 36 3 5 6 41783203= 47 889 167 9 30 7328754= 2 673 9 594 854 3 3 6 391236= 65 5 250 611 1 97 2 225642= 4 40 178 143 469 53 448848= 87 2 8 1 51 69 48 4650= 4 371 169 1 98 8 326690= 8 10 67 2 6 1 3 49 996 27492032= 619 1 33 421 6 51 6 75 191745655= 655 123 4 34 7 25256= 69 8 41 1 8 1440= 74 16 2 395 865 76638936= 5 96 6 7 8 384 2 68 9 6 4 16475979= 63 97 4 7 5 9 79 2948707379= 8 8 102 32 2 23 280 2 5 139295624= 7 6 16 9 2 7 5 9 8 6 32 72 464621= 357 4 26 5 3 237265609378= 61 5 176 442 93 81 67396998= 69 4 941 56 1 6 6 736 4 17731594= 8 7 82 6 6 2 78 4 1 2 3 1 38794833350= 1 5 2 765 74 979 2 7 50 1511975= 70 77 4 1 975 3479377= 369 73 41 94 61 30750833673= 3 349 764 6 1 153 1 3236809= 66 2 40 119 9 218349= 3 42 70 15 7 349 1389960358= 515 5 54 495 87 271 104= 7 93 2 135021376= 2 96 2 973 59 3 28 4 467432= 649 1 276 2 1 25 491 3824775= 4 6 6 33 4 8 7 7 75 573 618569001= 61 856 8 905 96 3510= 177 93 44 5 366 131985= 96 24 57 655 5 16202819= 1 3 926 58 42 861 9 3 1 3411269120= 64 14 932 43 95 36000444= 4 72 6 76 828 47 1633755= 6 62 432 16 127 27 972911772212= 5 4 4 2 5 12 99 9 9 209 4 13240902895= 7 5 2 71 195 16 433 9 122248101= 863 13 392 356 548 56140560365= 783 6 7 32 705 36 6 1 48197812= 7 982 6 4 2 92 406 7 9 23433= 75 3 1 92 5 1732374= 4 1 5 93 590 4 45 3 7 6 36502= 7 8 70 4 129 7 5 1 7 2 22 2510281833807= 715 1 8 13 27 28 5 80 7 5040243= 4 8 7 60 237 3 2332657654= 85 7 6 72 4 6 2 518 1 52 135673= 32 6 4 15 643 1063567= 296 49 681 8 7 5 8 5083677= 105 9 10 2 24 13560481= 64 57 2 3 1 70 291 39721250= 90 947 63 8 76 30247= 13 5 255 29 33 3 1 9 2 2604= 89 4 78 6 1 1483313= 685 482 942 4 6 7 1 3 4072802= 9 93 23 868 74 2 819216581= 1 637 2 6 4 6 8 9 3 5 80 2 367230334= 9 33 62 8 230 332 2398440= 9 1 903 7 33 79 1 1732799= 74 43 68 2 445 4 5 4 2 7084389272= 63 1 1 921 4 7 7 2 3 4 6 1 10959= 6 7 6 576 6 9 13407283= 315 3 51 541 8 83 378826569= 4 8 33 7 52 828 8 14261= 7 7 8 927 9 173854= 6 7 4 8 5 4 6 1 40 1 9 44 57783= 4 1 9 33 256 4 1 1 2 2 6 3 19425406= 2 76 7 326 3 8 6 1 7 805 1619775= 531 8 9 25 3 29867= 9 3 614 88 1 4 8 6 3 7 19 655= 2 51 45 502 6 274409943= 946 241 29 5 3 2518= 247 8 518 17 7 3569675730= 40 46 7 4 47 509 95 62 62041462= 878 7 5 5 557 4 9 1 46 4 51320839626= 252 76 84 35 75 319 4534248981= 83 967 3 85 78 9 6 4 3 3 15568060= 126 22 605 922 5 90 13024055= 5 74 4 88 54 141= 45 92 6 291251791= 6 515 7 6 745 1761366933= 74 23 352 4 294 994404= 4 8 6 48 123 32 8 452 4 76514= 6 7 98 600 14 5058051= 71 482 91 4 185 3 91 2216287993= 9 42 8 936 35 66 61 7 4 12894510= 6 7 1 7 7 307 2 4 4 426 64522175595= 6 452 21 7 497 2 6 602 7303887494= 25 5 609 5 5 84 8 7 49 7 4155= 822 5 46 374608580613= 2 3 616 25 8 58 796 46 23207960= 197 65 4 515 43 443412841610= 479 22 8 40 46 914 9 6789655= 17 254 466 1 92 55 7625964= 76 25 95 5 6 1741= 1 9 1 9 22 180931249= 723 724 5 5 50 3493889717= 41 8 85 6 5 99 1 8 1 883 262770906= 568 976 2 2 79 3 251029= 65 5 26 715 64 3507640= 216 75 6 2 15 642 211904= 13 48 6 344 522= 7 5 3 5 3810= 7 3 379 9 8 8 530 460174478= 6 8 5 2 4 876 6 8 8 9 16 660268231= 77 70 2 5 849 62 870 6128325= 98 5 807 63 75 4669= 3 87 5 6 7 154 37269025921= 374 58 23 83 80 9 44644811817= 7 7 3 6 3 85 786 1 1 8 1 6 16012= 65 4 6 19 8 1 3 7 9 1 8 6 2736304425= 30 841 8 695 3 156 51616= 724 58 2 47 8 2 1 7 7 2 2 270916= 5 8 8 50 172 9 19 3340= 4 679 475 7 142 350635929= 2 5 7 6 73 3 1 796 2 2 5 104348= 1 51 3 8 7 3 8 2 8 6 476 8 49388638= 3 8 6 3 21 4 7 2 8 629 3 5 679606950492= 19 436 446 98 8 83 5 6 90546= 90 53 6 2 5 505494= 1 758 666 1354= 779 443 25 9 98 17895006361= 9 44 65 1 2 6 750 6 361 186277= 2 44 5 7 2 18 23 7 43 1 92249344= 27 192 35 2 47 32 8 6570= 6 155 412 5264531371= 1 657 4 26 5 65 6 2 59 864129820150= 465 94 72 2 45 226 95 73453752= 7 1 4 8 3 76 210 4 831 100776= 1 77 9 7 8 7 775 38 3 341785221= 874 1 13 1 391 6488622= 84 4 356 18 207 146011741= 70 1 2 6 61 486 697 3271= 6 305 16 4 1 582909893= 259 25 8 8 873 892 9 5 780= 9 7 9 9 746 3290654498= 32 90 489 161 4 494 4 12801= 540 35 696 2 89 464472216= 4 1 562 4 4 717 871 9 8 1495= 1 396 440 92 500 66 805473= 80 680 380 706 633 461553= 90 959 6 20 5 43 411 74990463= 4 31 8 1 9 6 931 4 592 5 5768093342= 9 5 7 2 592 688 9 78 5 6 2243= 15 9 87 86 69 11837412709= 785 14 6 9 5 4 698 1291692080932= 92 1 26 372 140 932 1436857560988= 6 4 4 8 357 9 92 1 1 6 43 329661792269= 6 86 7 6 6 4 2 59 5 3 3 90 1839165= 92 5 5 949 19 505911537= 3 69 2 62 8 7 21 470 67 6035327022= 7 5 8 581 8 483 9 5 6 9 2 13893971398= 2 14 6 2 4 3 5 746 900 131628160= 765 22 6 344 5 257664= 18 6 8 2 8 61 5627412= 7 72 2 2 7 95 9 6 3 8 3 12 767366= 95 2 805 760 188 55 577347= 8 9 593 4 863 571= 9 4 66 69 400 13728= 6 5 994 60 215 73 6 519998220= 6 8 8 91 5 9 57 275 8 9 1 343275= 46 4 19 5 995 54549= 20 3 3 250 171 114723458963= 7 3 230 1 6 899 9 89 64 34001983= 5 77 3 69 635 771 2 5310= 29 61 1 3 8917506= 3 5 7 4 315 2 32 9 234 749965= 3 481 6 5 761 6 7 9 3 1 4 6920410040783= 59 87 474 100 40 785 1285810= 43 38 6 30 8 760 75 8 6504567036023= 591 324 276 110 23 39312817= 8 1 4 1 66 2 7 6 1 6 810 7 31945133= 45 557 71 4 75 70 6 14822498693= 162 4 35 80 1 891 20101915756= 235 611 7 7 8 2 9 2 4 2 2 7211517= 13 4 63 9 56 2 5 661 7 486695= 51 2 3 95 7 77338= 5 3 1 3 99 4 8 8 5 285 54 15735= 1 84 1 185 4 6 1308827965= 7 5 1 31 1 90 891 37 56 41036= 496 81 197 6 657 77442240512= 5 1 7 925 886 8 364 8 4 178800585= 2 3 9 4 4 4 10 6 729 2 9 6 191563683819= 87 231 2 6 122 5 3 819 1580= 2 83 88 33 76 7 4 94 6 2524028= 5 38 41 4 9 9 68 1371= 1 6 85 2 1 20180153709061= 6 2 5 89 5 903 9 5 9 3 2 1 5348= 650 46 50 5 6 842 7574880= 152 9 2 9 38 2 3 5 1 86 180263798= 630 8 697 2 41 135637= 451 5 5 895 39 193645= 857 4 5 6 1 9 4 35 2 9 7 4 2209115606= 97 7 360 50 628 9 158736= 6 877 6 399 7 4 9 4 1 8 8191921= 855 5 5 638 3 1 70319106= 80 257 380 433 9 9 300940= 4 686 436 91 8 124= 2 60 4 2054222905284= 7 73 7 532 7 9 1 18 638 3852485577= 804 37 568 4 57 585 7733360= 9 44 7 4 6 3 1 2 6 2 6 292 137876= 40 8 239 5 1 3 1 6 3 3 2 4 8607831= 859 11 162 50 484 495232= 2 1 3 42 786 1 5 6 3 7 4 5 242862437= 62 445 8 8 11 35 6621686= 5 5 5 1 3 922 7 2 8 8 8 6 7604= 6 169 8 7 3 9 6 5 427 89227= 7 932 95 19 2 1 5776= 232 7 3 903 1 45069696= 4 157 9 48 36 18 161643300= 926 4 910 191 1 26868960342= 397 94 800 38 9 333724133= 91 3 79 28 78 3 9 39 4049582505842= 218 86 6 40 28 6 8 60 6 38981085= 1 4 33 1 8 7 29 9 29 7 9 4 88293150= 5 274 2 286 3 66 5 3 5 571913273753= 1 7 563 913 2 7 3 5 2 5 3 255816565= 500 1 15 51 565 22656504= 75 52 155 3 40 5037237= 7 70 3 1 685 30 862 1 9 843118= 4 8 4 3 3 9 8 748 14 6 94 165818013= 7 741 8 74 54 30367= 45 664 3 324 82 78 1248741970= 9 8 46 8 142 680 394 5 121360516= 9 3 8 1 4 6 7 6 8 598 96 1 595928718= 744 8 160 18 931 20 4 229253= 804 4 71 822 4 91 24354727= 722 6 7 4 861 780 6 7 828734019865= 666 36 436 17 39 694 107802= 68 7 9 2 9 8 3 65 1 7 2 9 6909840084= 480 5 5 914 1 9 9 7 21 67574887954= 2 7 9 3 29 485 3 795 1 3 80117581952= 950 38 56 9 843 2 4341626= 9 9 2 268 24 64179026= 49 8 9 7 1 55 3 2 27 7 8 2 39320134= 7 437 4 459 5 833 7 39231675= 4 7 777 855 57 2917615= 7 1 643 7 8 9 8 9 247 76131594= 1 177 627 7 98 69998078= 64 9 6 8 2 367 73 7 8 1 6937280= 4 8 17 15 6 3 2 5 760 8 176737= 8 897 508 23 5 69538171= 13 443 2 8 806 7 1 68 357696643= 46 324 8 3 3 3 4 2 19806500021567= 565 9 625 2 5 7 2 6 9 6 8 1831104= 1 6 809 561 4 90536995= 3 6 8 3 189 14 6 5 2 7 9 5 30610466= 34 9 10 4 67 108330= 4 7 2 2 2 471 5 2078527= 2 7 41 739 6 439 301 2738759568= 7 42 4 2 5 8 3 4 99 7 2 3 2125570= 8 497 4 46 5 2 5 5 54 12120409= 109 18 58 250 24 409 338023= 613 1 67 71 5 2 7 7 3 4 14584= 5 1 8 5 86 116860285= 1 6 3 160 2 50 6 4 72 87 53282559= 5 3 282 5 5 7 46965024966= 757 5 62 2 4 965 308893= 11 2 8 7 69 4 1 82 6 4 7 203220= 27 6 2 94 540 7 4 669 7850309= 9 5 3 36 6 6 21 88 12 5 595056931= 8 36 2 21 616 931 22230= 55 51 884 16 6 68686892= 70 6 722 481 92 123516= 112 9 5 52 2 94 445040= 3 6 5 97 87 7 1 678 5 8 1379473= 7 1 3 9 39 7 7 1 7 8 9 744 577124515= 6 47 892 270 245 1990431900= 998 67 2 793 548 9 3 385832= 82 49 96 91 6 7 42255489= 7 8 939 3 484 4 470= 364 51 6 1 48 97711378199= 977 11 37 1 7 199 1 19493527= 7 2 759 2 39 1 241 51 1 782908337= 8 24 5 5 626 76 19 425193= 1 537 4 77 688 7 2 115915142= 7 5 3 7 208 4 8 1 17 3 6 2 2732= 8 2 29 70 2 48697176= 178 771 6 27 4 7 38 3 8 897561= 5 9 327 8 4 1 57 3 3 567 44027= 95 83 247 3 58 34314052= 75 2 986 4 301 41 8 38591798= 399 10 52 186 518 56857776= 5 4 23 9 61 5 7 76 1495= 6 2 7 8 8 5 5 6 72 54 7 6 1665265= 5 3 89 410 45 331 9 5 145680408675= 4 9 419 4 4 408 674 3 5965317120552= 7 2 1 456 6 56 5 64 554 2419624368= 60 9 7 6 7 8 635 8 7 7 2 3 120212= 26 92 1 5 5 537 1544730757552= 790 143 61 50 391 50250860= 2 7 988 6 84 4 200 2 2 6144650= 67 317 4 4 649 938= 36 24 74 3582735= 562 35 122 6 7130101416= 9 1 8 70 56 2 8 3 5 6 86 114876= 94 3 44 45 2 18 1 627 2 10753200639= 8 5 71 18 52 28 8 2 748= 6 56 90 122935376= 8 96 15 1 9 51 59 4 4 79 30240723944= 12 1 473 6 7 9 9 8 394 2 1132= 32 589 4 500 7 1 523= 49 3 6 10735945123= 2 8 5 8 9 41 2 7 635 12 3 349141893129= 6 550 836 52 5 1 963 3 2970495= 7 847 501 1 57 6 227240795= 553 45 76 5 798 6201= 78 8 540 1 63 9 322171047= 4 9 874 7 27 6 86 342112130= 1 33 211 2 128 527649= 48 4 6 4 13 7 38 8 5 6 3 242559363052= 67 9 4 85 3 9 3 630 5 4 962= 879 35 39 6 1 563393= 8 85 896 6 12 5 212505= 5 16 57 85 8 74 2 20 2 9 1201= 8 3 8 4 789 24 312 259335373= 1 7 4 5 9 3 4 1 3 46 32 8 1497577545545= 3 765 138 725 6 9 7 4446072= 45 50 2 988 72 3916= 46 388 9 8 372 15162562= 4 816 238 3 560 14450297= 4 9 37 78 49 93 2 21 8 2578194502= 54 4 82 36 66 4 875 2 37351= 71 2 7 6 94 5 62832442= 3 6 37 9 7 5 8 7 542 8 38973= 94 6 228 61 75 661997= 66 19 88 6 6 709= 3 27 49 49 73 496 3 9 1 4367700475= 8 4 566 215 3 3 997 2 2 328739= 1 724 24 72 85 2 2 207366= 384 6 3 3 4 104848968= 8 98 4 6 8 66 9 2 6 54 7 127344= 27 44 683 4 168 7932172= 8 38 484 5 2 172 2754000= 234 81 6 4 425 3 51 24 909986= 8 44 4 6 2 5 8 7 6 7 7 7 44597= 445 69 7 12 9 748244= 7 1 99 6 98 8 3 53 4 29674500= 76 885 490 73 6 20135958947= 402 1 7 5 10 85 8 946 139668= 357 1 41 998 68 972= 1 6 59 22 1 809500= 48 5 36 424 466 37 5 15993846= 39 897 8 729 57 45 439929401952= 43 992 93 9 44 75 50 25053= 1 3 2 4 4 3 8 19210481= 74 7 67 236 81 29385628= 5 6 946 307 56 63 65 210880133085= 44 1 8 78 6 4 9 4 2 5 249 91393425= 182 11 62 5 67 2 1 3 9 5 98124= 2 732 67 28 4 4 24650065440= 76 450 2 99 364 4 5 116388725= 1 1 121 2 61 1 3 4 3 8 9 2 7476908378= 747 6 90 78 5 77 1 58420= 7 817 96 19 5 76 10606404= 23 1 6 83 926 178010= 996 1 777 84 623 4954535792640= 435 2 644 5 9 7 92 61 1 1195764= 2 65 9 3 10 412 1 6 397 39193416= 505 9 353 9 216 6654027= 1 70 61 6 39 1130903171= 883 518 1 8 16 1170420= 487 4 30 81 20 253743= 11 17 194 1 9 405720= 7 13 69 311 955 8 1015923= 6 9 47 79 83 68 3 10538269546= 56 8 437 235 4 6 8343= 677 249 9 9 1 2007882= 2 8 74 5 7 8 9 402 2 694 5270243= 20 831 253 16738245= 5 9 184 79 2 5 3 9 5 37 834249= 7 28 360 642 63 108410793= 49 79 753 61 28 32176521= 336 28 4 883 2 570330= 9 4 16 597 339 302 9 2 468520= 67 9 69 2 6 4046008= 66 327 61 55 4 26265204422= 679 742 422 2 73 2 8 6 229= 127 73 22 4 4 288910= 28 8 831 6 73 949182= 58 73 3 224 7 87 55638= 87 634 14 87 3 8 368 3438732966= 9 9 3 9 2 91 6 8 4 312 9 1090577000387= 5 4 52 88 4 3 7 50 9 7 2 2 1367893818= 9 409 59 2 637 9 5 8 3 6 6699= 1 4 4 3 72 9014897= 8 469 76 12 86 62 4 97 46407= 8 3 843 9 8 6 142 85 16 38= 13 6 5 6 8 5472046634994= 21 2 29 367 89 4 99 1 35992250= 4 703 509 1 6 47 6 47 1 437614423219= 972 3 5 8 8 155 93 9 2 1 56110916= 890 5 446 819 6 56479317484= 51 50 247 5 58 4 444 5 384= 6 128 56 2 4 710496= 10 8 740 8 12 532040= 42 548 9 97 943 24095= 41 6 33 9 47 31 2 316 969496385774= 9 9 1 98 92 8 53 4 7 3 72 91959= 3 79 13 90 29 2566398922= 2 7 9 81 6 413 62 853 3425= 70 39 640 53 945989120= 10 161 931 19 99686839= 9 9 6 3 2 3 59 9 27 12 1215180= 40 446 60 6 5 187385= 77 61 61 9 3 825 3 2935383102= 2 257 98 70 130 51339= 4 5 812 7 1 7 4 97 8 7 18 1387980028932= 81 5 918 8 6 994 43 1 14550071987= 92 53 500 71 900 82 6 11932737= 3 7 8 1 819 4 5 614 4 4 8 1888477= 5 9 75 2 559 60 9 7 658 720516= 4 318 6 827 9 619 6346= 27 78 8 3 6 18076176= 1 829 4 3 1 1 4 592 6 6 6 383939244= 5 65 5 73 133 33 9 453 174276= 5 1 967 30 1 157 55 3 54871772= 86 839 1 456 76 62562= 786 95 71 7 4 95673724= 22 2 48 453 4 7 77 1407900= 50 1 19 57 26 188871577= 5 9 8 4 7 129 6 8 257 8 8 29797632= 40 53 136 600 9 6 762624287= 133 9 6 7 9 95 8 9 9 4 1 4 5311278= 46 716 26 2 69 668 9 14390442= 1 1 14 90 7 93 697 90 2 38143333= 17 4 8 8 92 6 8 7 3 8 408 522548= 768 9 87 466 70 8735836482= 429 4 93 7 931 741 9 26425157= 8 373 8 394 229 22 55 61960= 6 4 968 9 13680= 38 99 53 9 8 253971240= 184 695 662 2 518 3 40577051= 84 70 4 8 479 8552= 3 992 5 69 8 6721479438= 3 3 4 94 11 9 5 8 86 5 8 78193003= 9 5 7 9 1 8 183 8 1 763 107829= 4 547 463 301 82 31071077946= 291 841 491 2 722 38 60978= 417 8 3 155 6 85981666= 3 7 170 3 21 2 3 5 2 4 9 5 7362= 7 945 6 38 703 58242= 8 6 828 9 30 3 5 4 66 2 4075= 9 5 352 7 408 2484607586= 637 13 62 7 6 329 3 86 18816= 5 8 2 3 11 43 4 8 2 112 2768866= 8 459 8 67 87 2 73 8 8 4256479= 37 3 98 593 114 4 4 7 13315217= 7 59 9 69 77 5 228 5 2 7 95584639= 9 55 846 32 6 47650502420= 6 1 7 2 2 3 2 2 592 33 7 7 1114026= 17 68 630 98 87 2991360= 591 1 187 64 2 30 75109= 70 5 1 33 64 168 6 7 21908287= 7 33 95 6 661 25 1 4 47090556= 9 869 79 2 9 596 23985780= 46 91 10 573 34076= 8 85 50 69 7 194928707= 18 5 8 1 921 7 6 6 3 9 5 4 1804453= 7 535 3 80 9 5 3 94 781 1161588602= 29 9 733 6 6 53 2 2643840079= 4 6 40 9 1 4 75 34 1 3 78 12231768= 50 96 57 8 3 22053= 315 1 7 3 59127088135= 7 99 74 291 797 132 209537664= 5 5 1 8 4 1 6 92 220 8 8 26634957= 1 85 2 4 2 24 816 3 714 3940518666= 36 3 80 28 442 3 3 1 8 1 12161796610= 49 56 7 998 6 245 43 199948= 61 976 3 192 268 15654= 5 192 3 7 2 6 62 146720= 31 6 58 8 96 1772= 73 6 482 778 74 105802= 4 9 6 226 764 99 73 1410441620754= 671 6 3 8 867 21 51 1278730= 717 4 39 53 216 1 4 2 1755915= 2 178 6 64 3 1 52 6 7 63 111843603828= 2 157 2 341 794 433 3 227276742914= 911 297 551 84 6 5 1 6 188988963= 7 489 8 9 22 8 7 90 6 5 3 2518558236= 94 687 396 39 6 786 179452851= 26 69 50 2 8 11 38 3 4483617753= 771 6 52 55 7 83 2 84 3045905= 5 8 9 319 62 7 3 4 78 1 8 11261535713= 3 250 769 3 5 714 3854= 344 8 2 31 5 1487109= 835 5 356 1 808 2489= 83 176 8 8 6 3 4 388 8 13541635031= 564 234 793 24 29416717243= 462 527 212 14 3 176849= 162 8 2 1 52 73467964416= 868 704 2 258 233 25815023= 1 64 62 5 650 2 8 62 8 98= 4 9 5 42 15 6487913759= 5 6 7 4 9 791 1 2 753 6 1 3527= 45 18 1 7 8 461767= 565 816 99 628 760= 46 9 8 2 3 8 2 3 6 5 318 7 1202974088= 5 39 7 2 2 7 165 632 1 8 24185454= 2 4 442 552 60 94 6 5237162784= 744 1 9 9 6 6 8 8 6 1 7 81 75160511= 1 2 8 75 92 9 9 40 1 5 11 203314725= 681 6 653 85 191 747 165316= 21 4 9 4 74 217= 51 157 9 2985686= 4 5 8 749 59 8 4 864 83 6236226= 8 959 7 9 86 92 8 23190= 6 5 773 3585388362400= 8 936 913 202 5 416 245815119= 76 340 1 7 46 770044= 9 5 550 33 2 6 531732= 63 3 1 928 924 3 53482062= 3 6 716 8 550 9 55 428281604= 7 198 7 85 57 549 102148233= 4 1 6 9 5 907 3 9 4 5 235 156141= 1 11 5 8 2 8 39 8 1 5 1 3406245075= 905 82 68 9 675 8992= 1 40 4 27 48 16 8125201052= 812 5 20 10 52 1186311= 7 2 91 7 8 38 1 7 2 161 3 846893376= 86 8 287 32 981 1260411= 7 9 65 2 21 79 89 194 2137656811665= 44 777 7 41 42 7 3 682 7628618= 9 5 1 2 2 25 8 9 6 728 4 3 4284404= 6 4 352 764 401 1953248008= 9 6 1 619 8 550 62 1 3 6 23217= 59 4 203 61 71 201456= 40 5 872 578 3 1441638= 2 28 4 79 596 6 8 54 33 6923652= 1 47 116 4 847 41 924 80960930= 176 5 92 93 2 1142233984= 8 9 847 406 64 1478491= 29 8 3 9 634 158600757= 996 272 4 4 6 521 23 682984325= 8 2 1 7 860 4 8 8 48 2 426= 7 59 8 5 2 176333692= 732 2 7 2 2 7 5 6 55 64 2 1944= 877 835 2 5 225 14785562880= 76 3 4 22 4 5 89 6 3 23 222447224873= 669 8 2 369 2 9 10 6 1 4 97661641= 6 9 4 1 9 5 2 6 90 40 3 1346404= 732 9 279 132 2 638099= 69 924 8 531 4826320= 2 580 1 1 9 7 1 460 2 5424478= 6 903 6 476 3 174745089= 9 44 932 9 6 4 9 2 5 54 9 49666959984= 8 869 8 798 7 8 10 48 7 13790117510= 3 9 8 93 531 6 7 8 6 7 8 1158= 38 4 1 5 435 289 8 2461918479= 246 1 918 479 1 37175171= 76 5 62 4 97 4 9 792 4 6855= 7 66 15 52 5 42 6 759 10202049= 300 4 907 37 49 6 58 32659503291= 9 7 8 5 3 9 4 2 318 6 3 8 119110203559= 50 9 52 1 62 772 5 6 2 9 286389091119= 1 81 5 7 2 2 9 741 112 2 1729945= 5 616 77 47 4 32 12666905955= 45 1 7 3 29 3 459 985 741595172= 30 78 166 3 22 762 8 1236667= 47 52 506 190= 3 7 9 25153920494= 15 4 3 79 3 24 11 246 2 3990535857= 63 341 839 7 9 4418193= 31 2 177 80 6 267 11286445296= 778 8 23 77 258 56 876672511= 7 2 122 575 3 64 2 55 2 10080485= 29 62 2 4 5 7 16 5 480 5 193818= 193 1 17 701 4322= 33 64 44 7 47 10731634711= 50 3 32 17 685 86 8 3734528= 9 59 32 5 9 8 2 8 7 512 1912249= 237 8 1 9 8 5 3 269 2 7 986442912= 586 25 2 57 75 882 38 2052= 57 5 9 68 84 5 9 360552= 24 6 6 67 35 54 50657277= 388 2 85 768 831901772= 83 2 37 79 9 3 5 62 72 132361= 4 61 2 2 361 27312518714= 9 3 2 11 8 93 51 8 717 86741323257= 18 408 6 124 38 56 56676545931= 3 4 227 5 7 429 3 8 4 9 3595708= 2 9 274 9 9 3 3 275 4 1 5175468= 5 4 3 8 85 5 1 729 8 4 4 6 73015409730= 6 5 838 2 88 223 6 74 6 197559600= 379 594 20 58 7 5 1980192= 6 6 30 18 4 8 246000= 4 4 70 47 25 38 200 429= 5 9 378 6 48175277= 29 769 45 98 8 9 59 6 5 1646= 1 5 538 9 643 4 439 8 168824= 18 91 50 13 8 78074= 747 28 55 1 516 2605050= 1 826 90 7 5 464453= 2 75 1 5 708 8 5 85549= 94 27 9 9 626 3593392= 4 795 9 44 17 8929787= 924 36 93 12 9 49 5 204815029= 204 8 150 28 441987= 1 626 992 7 39 1104672465971= 5 5 2 6 4 672 460 5 9 70 187704= 7 975 91 36 27 4074= 97 6 7 137722= 8 2 86 70 50 1988= 283 7 5 514083842= 918 8 7 380 2 43 1638= 3 6 46 459 32 3 74762172= 70 4 1 762 172 1779191747= 355 5 4 191 749 220802= 2 3 4 80 30 26027520= 229 8 3 457 18 399 80 34859430= 1 3 311 3 2 261 6 7 7 5 5 10896747904= 19 11 71 57 905 6046305385= 920 2 9 657 8 3 65477902626= 7 1 2 3 3 680 5 7 1 1 39 8 18668556= 27 942 734 35140= 389 9 13 2 5 41271300835140= 733 581 2 4 97 33 580 58892856= 396 627 649 177 199 8702400028= 440 4 4 222 875 29 708207= 3 4 63 73 42 68 2267548393= 35 55 7 25 483 48 8 34 158740626= 623 52 7 32 7 37165412= 447 975 1 99 22 3 4 1 4 87584= 8 391 31 135 1 8 7 1438547106= 45 38 317 161 945 504983= 8 4 6 1 604 8 371 14519220930= 93 1 14 159 90 97 949379= 9 58 991 300867840= 81 8 963 6 62 65 3 3 50593616= 4 20 9 71 98 413 9 8 1 6 15598080= 326 497 62 396 96 8680959= 96 4 549 2 9 1354365818046= 7 93 16 9 9 47 1 940 46 2365= 4 7 9 9 431 687 347 6 3 37026= 9 2 2 18 422 4 3 1 5 5 2 3 72608= 8 254 3 2 137 395449= 7 8 4 1 24 1 2 5 21 144 1 23639040= 5 76 33 6 608 324 28177014753= 505 871 557 5 3 66765514217= 3 179 3 1 5 2 1 3 3 7 1 5 275038= 53 4 51 27 9 94 3 6 79 4059426114= 7 4 4 90 9 7 2 258 3 15 1558696408= 7 773 6 77 90 37 72339600= 4 209 1 4 6 1 5 9 3 2 5 40 654= 6 6 7 42 7 5 44 15902= 691 154 38 18 6 991782= 991 22 7 1 552 60835= 60 8 38 924485= 37 3 33 642 5 4249823= 11 2 6 33 828 3 3 23 47841349= 4 4 70 44 7 353 318 74786945= 63 9 24 4 63 7 744 8 65 25553824= 25 5 527 6 8 34 9 92 244489= 116 4 3 7 7 232787240= 3 91 95 931 28 168883= 2 61 1 2 40 8 84 10517265= 156 62 5 766 8 9 8 72 21531469614= 2 976 729 57 302 498= 1 53 2 9 3 35119420617= 2 5 7 949 499 5 5 2 3 4 5 51053418= 4 1 79 8 488 8 69 42 9064910= 866 428 982 7 37 101985094351= 4 400 7 2 7 37 8 7 7 5 3 6 284804116= 678 3 2 5 6 2 67 7 6 2 3 3 3304056= 550 4 4 7 213 105853334787= 43 2 5 2 6 9 7 9 7 90 78 7 8881534= 25 71 5 6 531 1433046= 1 21 270 9 545 27 759 13727957= 8 324 4 1 79 9 1 57 2 9 6 10591349= 37 162 30 22 3 462 49205= 8 4 1 6 422 500 51 245 812346909= 77 797 1 5 125 58 4 6 3 56448843= 56 7 144 84 3 86848= 7 7 7 7 56 8 1 1 4 4 2 32 5763= 10 7 4 7 65 35 6 7147742595255= 12 5 6 3 73 73 91 9 29 5 5946090= 16 6 25 192 86 85 3 1950322773= 16 8 3 15 61 8 5 9 335 7 80001341= 41 7 302 13 4 71 955 189269= 249 758 325 9 193 24353171198= 74 3 8 36 5 13 249 3 3 3 21988928= 7 22 4 8 5 26 19 169 8 8857= 393 3 77 7 68 87464047546= 57 4 9 3 28 5 4 53 22 45 576270130= 38 7 4 98 22 2 6 1 50 12 1038237= 2 5 38 227 10 16437242= 1 8 8 6 1 118 19 118533= 238 6 88 357 8 55755= 4 8 3 2 1 4 94 6 55 5 59 1878= 46 30 20 470 8 188107538= 9 3 7 369 3 4 9 2 4 7 253 6986478= 847 5 41 2 49 22 4 1 56073= 576 1 7 462 9 16147623= 299 6 9 927 696 172299= 6 6 8 39 8 4 420 7 4 8 2 9 19707121= 14 8 80 277 72 542 4807047= 85 84 1 56 8 103399= 4 4 93 614 944 842 415241080= 2 40 2 4 8 48 3 7 877 39496683225= 99 941 494 8 25 65523806= 284 958 81 49 651 5 10531660= 8 8 609 4 3 9 9 40 2 578 251905= 57 8 38 702 3 70 2 745 54818482= 137 81 4 251 82 1318= 993 314 13 797843199= 92 271 6 128 25 253960= 9 1 8 47 300 55 3 8 94 312486050= 4 3 93 8 6 60 3 5 8 7 20412576= 68 790 237 779 76 32860= 4 804 203 4 8 81 8 6 4 6763= 31 3 4 7 2 6 7 7 140 4 8 7 125419236697= 6 7 53 7 9 7 67 2 2 468 2 480424= 71 9 5 2 373 26062600= 548 3 42 4 6 732 474 66809704= 5 78 89 9 9 5 5 1 67 3 6 704520= 5 8 710 6 2 5532597= 6 2 7 5 6 3 7 3 3 5 2 485 90883= 32 28 8 4 80 5795286550= 5 1 795 286 549 351162= 43 8 2 44 474 9 2179214380= 2 4 609 1 57 505 7 916 828= 46 47 558 67 6 99 5 26940060= 614 4 365 86 80 4 5 63 75738= 31 5 2 6 4 89 138382641= 45 3 6 51 198 72 8 10 7881700869= 36 9 349 83 243 48585= 59 423 17 7 361 2649371051236= 306 5 5 9 6 4 4 9 2 809 4 1599= 599 618 1 5 375 2 1 11245= 849 83 80 112 4 20025747125= 9 1 12 9 39 873 125 304159954= 2 6 7 9 7 7 8 15 995 5 174669224220= 6 5 684 442 81 12 159 27806031= 5 3 7 590 702 77 749 1 7817= 7 21 52 168 5 176057= 55 32 57 319278= 48 67 3 3 11 894 4064102= 200 1 4 66 2 36 301 1294= 8 4 2 3 1 663 1 5 515 3 6 40524= 40 69 617 2 6 14779018942= 5 78 29 3 4 9 932 7 61 3 113488760= 4 1 648 4 18 947 815 8 41492589= 514 468 684 43 4 4857= 8 76 4 52 25 256 470973600= 2 7 778 6 1 60 5 9 5 32 500361= 61 82 1 20 44 22257= 7 2 32 32 14 2 753 6 34936254697= 698 7 2 5 5 37 2 7 72 8 6130747= 28 252 7 31 63 621094920= 24 815 93 8 995 25081134120= 91 3 352 31 5 8 5 343 575932900= 57 9 81 5 3 36 77 3 1 7237736= 714 7 57 7 26 66 8 5 63 8371616= 157 845 9 82 9 805 1 6 2270829= 415 7 7 652 21 7 29 291305= 6 85 67 72 10 49 6 6 7 909249513= 35 1 9 73 4 5 7 8 187 6 3 7452225= 6 360 5 5 3 1 5 8 5 5 33 1 92774412762= 4 89 3 10 302 4 1 595 8 186042= 949 4 49 36 2 10280455589= 4 5 9 3 804 1 554 92 96 4222018= 7 4 9 3 4 3 1 467 5 2 337 517625= 95 22 1 46 2 96 753 3 5 5126817530= 2 439 493 8 3 7 47 4 3 2 28996334= 57 909 54 44 3 35154= 4 9 31 1 87 6 26120= 6 71 6 5 3 6 30 2 6 1 5 4 381682302= 50 76 6 84 589 3 4 3 4 3 7152040= 74 17 3 6 4 5 9 8 5 1 89 84383= 6 8 7 43 36 743 83 938542735821= 521 412 3 18 59 58 21 296700= 1 1 3 856 345 1565677140234= 392 4 42 12 95 234 102060855978= 462 319 13 2 2 7 761 3 23908402876= 90 388 5 840 287 6 8716682= 454 534 165 63 120 2 36326= 34 95 402 6 38384656= 1 97 2 94 2 8 833 9 7 1457826837= 10 70 2 589 308 98 5 1344414= 322 5 2 834 6 12427020= 7 789 75 9 5 6 722534456= 2 8 8 9 9 3 9 980 3 3 3 3 885= 2 6 5 68 1 82339793544= 8 2 33 9 7 93 5 44 56161976= 11 66 47 463 75 ================================================ FILE: exm/aoc/2024/aoc_2024_07_questions.txt ================================================ --- Day 7: Bridge Repair --- The Historians take you to a familiar rope bridge over a river in the middle of a jungle. The Chief isn't on this side of the bridge, though; maybe he's on the other side? When you go to cross the bridge, you notice a group of engineers trying to repair it. (Apparently, it breaks pretty frequently.) You won't be able to cross until it's fixed. You ask how long it'll take; the engineers tell you that it only needs final calibrations, but some young elephants were playing nearby and stole all the operators from their calibration equations! They could finish the calibrations if only someone could determine which test values could possibly be produced by placing any combination of operators into their calibration equations (your puzzle input). For example: 190: 10 19 3267: 81 40 27 83: 17 5 156: 15 6 7290: 6 8 6 15 161011: 16 10 13 192: 17 8 14 21037: 9 7 18 13 292: 11 6 16 20 Each line represents a single equation. The test value appears before the colon on each line; it is your job to determine whether the remaining numbers can be combined with operators to produce the test value. Operators are always evaluated left-to-right, not according to precedence rules. Furthermore, numbers in the equations cannot be rearranged. Glancing into the jungle, you can see elephants holding two different types of operators: add (+) and multiply (*). Only three of the above equations can be made true by inserting operators: 190: 10 19 has only one position that accepts an operator: between 10 and 19. Choosing + would give 29, but choosing * would give the test value (10 * 19 = 190). 3267: 81 40 27 has two positions for operators. Of the four possible configurations of the operators, two cause the right side to match the test value: 81 + 40 * 27 and 81 * 40 + 27 both equal 3267 (when evaluated left-to-right)! 292: 11 6 16 20 can be solved in exactly one way: 11 + 6 * 16 + 20. The engineers just need the total calibration result, which is the sum of the test values from just the equations that could possibly be true. In the above example, the sum of the test values for the three equations listed above is 3749. Determine which equations could possibly be true. What is their total calibration result? --- Part Two --- The engineers seem concerned; the total calibration result you gave them is nowhere close to being within safety tolerances. Just then, you spot your mistake: some well-hidden elephants are holding a third type of operator. The concatenation operator (||) combines the digits from its left and right inputs into a single number. For example, 12 || 345 would become 12345. All operators are still evaluated left-to-right. Now, apart from the three equations that could be made true using only addition and multiplication, the above example has three more equations that can be made true by inserting operators: 156: 15 6 can be made true through a single concatenation: 15 || 6 = 156. 7290: 6 8 6 15 can be made true using 6 * 8 || 6 * 15. 192: 17 8 14 can be made true using 17 || 8 + 14. Adding up all six test values (the three that could be made before using only + and * plus the new three that can now be made by also using ||) produces the new total calibration result of 11387. Using your new knowledge of elephant hiding spots, determine which equations could possibly be true. What is their total calibration result? ================================================ FILE: exm/aoc/2024/aoc_2024_08.adb ================================================ -- Solution to Advent of Code 2024, Day 8 ------------------------------------------- -- Resonant Collinearity -- -- https://adventofcode.com/2024/day/8 -- Copy of questions in: aoc_2024_08_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_08 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 12; input_name : constant VString := +"aoc_2024_08"; n : constant := 50; map : array (1 .. n, 1 .. n) of Character; type Antenna_Type is record x, y : Positive; c : Character; end record; a : array (1 .. 2500) of Antenna_Type; l : Natural := 0; r : array (Part_Type) of Integer; procedure Read_Data is c : Character; f : File_Type; begin Open (f, input_name & ".txt"); for y in reverse 1 .. n loop for x in 1 .. n loop Get (f, c); map (x, y) := c; if c in 'a' .. 'z' or c in 'A' .. 'Z' or c in '0' .. '9' then l := l + 1; a (l).x := x; a (l).y := y; a (l).c := c; end if; end loop; end loop; Close (f); end Read_Data; procedure Show_Map is begin for y in reverse 1 .. n loop for x in 1 .. n loop Put (map (x, y)); end loop; New_Line; end loop; New_Line; end Show_Map; verbose : constant Boolean := False; procedure Do_Part (part : Part_Type) is procedure Plant_Antinode (xa, ya : Integer) is begin if xa in 1 .. n and then ya in 1 .. n then map (xa, ya) := '#'; end if; end Plant_Antinode; dx, dy : Integer; begin for i in 1 .. l loop for j in i + 1 .. l loop if a (i).c = a (j).c then -- Create andinodes: dx := a (j).x - a (i).x; dy := a (j).y - a (i).y; case part is when part_1 => Plant_Antinode (a (i).x - dx, a (i).y - dy); Plant_Antinode (a (j).x + dx, a (j).y + dy); when part_2 => for m in -n .. n loop Plant_Antinode (a (j).x + m * dx, a (j).y + m * dy); end loop; end case; end if; end loop; end loop; -- Count the antinode locations: for y in 1 .. n loop for x in 1 .. n loop if map (x, y) = '#' then r (part) := r (part) + 1; end if; end loop; end loop; if verbose then Show_Map; end if; end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; Do_Part (part_1); Do_Part (part_2); if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 409 -- Part 2: validated by AoC: 1308 end if; end AoC_2024_08; ================================================ FILE: exm/aoc/2024/aoc_2024_08.txt ================================================ ........0.......................c................. ........a......................................... .......0........................................r. .....W............................................ ..............Z..F.......................c........ ..F....a.....................c.......Lr....5...... ............................v.......L5............ ..................0.....v............r...E........ ...a..........................p..E..5...7L.m...Z.. ......j..0............z.....p.........E........... ...j...S...W.7................J........4.......... ......W........X...............................4.. W..........................p................M..... i........Z....................L.............U..... .....z....j..X..............................b....M ........................Z......m.................. ....f.........X........J................4......H.. y..................p............X.JvmR.U.......... .................................................. ................................4................. .........N........................U............... ........u...q.......5....J..7.................M... .y..i.F...z..........................9x.....A..... ...i.....2...zw....Y.........................M.... ............Bu.................I...........U...... ..f.....2.......k...........b.........I.......x... .f............................................G... .O...o.......f...............7.t..Q.G............. a.....N....i2.........g..o...RI........G.......... ......oy...q..........N..H........sQ.............. ....y..2............K........b........9...m....... .......w...............b....Y........G.......A.... ......uO.w............q.k..Y.....v.............A.. ...u...K....O..............I...................... o.O.........w.......Y.........R.Q..............T.. ......................t...3........k...x...C9..... .............q........3..6......t............Q.x.. V......................N..............S........... ..............6....K...............1...n..P....... ......8..........................T....H.........1. ..................s....t.....3....H.......n....... ......K.g6...B...........h..T..l.....P.....9...... ..................l....k..T....h............1....e ............6.........l.......h.....Pe..C......... ...........s.V....................e..........C.... .....8...V.......s.g...........n......e........... ..V......B.g...........l.8........................ ......B.................R..3...............1.....S ........................h...................S...CP .................................................. ================================================ FILE: exm/aoc/2024/aoc_2024_08_questions.txt ================================================ --- Day 8: Resonant Collinearity --- You find yourselves on the roof of a top-secret Easter Bunny installation. While The Historians do their thing, you take a look at the familiar huge antenna. Much to your surprise, it seems to have been reconfigured to emit a signal that makes people 0.1% more likely to buy Easter Bunny brand Imitation Mediocre Chocolate as a Christmas gift! Unthinkable! Scanning across the city, you find that there are actually many such antennas. Each antenna is tuned to a specific frequency indicated by a single lowercase letter, uppercase letter, or digit. You create a map (your puzzle input) of these antennas. For example: ............ ........0... .....0...... .......0.... ....0....... ......A..... ............ ............ ........A... .........A.. ............ ............ The signal only applies its nefarious effect at specific antinodes based on the resonant frequencies of the antennas. In particular, an antinode occurs at any point that is perfectly in line with two antennas of the same frequency - but only when one of the antennas is twice as far away as the other. This means that for any pair of antennas with the same frequency, there are two antinodes, one on either side of them. So, for these two antennas with frequency a, they create the two antinodes marked with #: .......... ...#...... .......... ....a..... .......... .....a.... .......... ......#... .......... .......... Adding a third antenna with the same frequency creates several more antinodes. It would ideally add four antinodes, but two are off the right side of the map, so instead it adds only two: .......... ...#...... #......... ....a..... ........a. .....a.... ..#....... ......#... .......... .......... Antennas with different frequencies don't create antinodes; A and a count as different frequencies. However, antinodes can occur at locations that contain antennas. In this diagram, the lone antenna with frequency capital A creates no antinodes but has a lowercase-a-frequency antinode at its location: .......... ...#...... #......... ....a..... ........a. .....a.... ..#....... ......A... .......... .......... The first example has antennas with two different frequencies, so the antinodes they create look like this, plus an antinode overlapping the topmost A-frequency antenna: ......#....# ...#....0... ....#0....#. ..#....0.... ....0....#.. .#....A..... ...#........ #......#.... ........A... .........A.. ..........#. ..........#. Because the topmost A-frequency antenna overlaps with a 0-frequency antinode, there are 14 total unique locations that contain an antinode within the bounds of the map. Calculate the impact of the signal. How many unique locations within the bounds of the map contain an antinode? --- Part Two --- Watching over your shoulder as you work, one of The Historians asks if you took the effects of resonant harmonics into your calculations. Whoops! After updating your model, it turns out that an antinode occurs at any grid position exactly in line with at least two antennas of the same frequency, regardless of distance. This means that some of the new antinodes will occur at the position of each antenna (unless that antenna is the only one of its frequency). So, these three T-frequency antennas now create many antinodes: T....#.... ...T...... .T....#... .........# ..#....... .......... ...#...... .......... ....#..... .......... In fact, the three T-frequency antennas are all exactly in line with two antennas, so they are all also antinodes! This brings the total number of antinodes in the above example to 9. The original example now has 34 antinodes, including the antinodes that appear on every antenna: ##....#....# .#.#....0... ..#.#0....#. ..##...0.... ....0....#.. .#...#A....# ...#..#..... #....#.#.... ..#.....A... ....#....A.. .#........#. ...#......## Calculate the impact of the signal using this updated model. How many unique locations within the bounds of the map contain an antinode? ================================================ FILE: exm/aoc/2024/aoc_2024_09.adb ================================================ -- Solution to Advent of Code 2024, Day 9 ------------------------------------------- -- Disk Fragmenter -- -- https://adventofcode.com/2024/day/9 -- Copy of questions in: aoc_2024_09_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_09 is use AoC_Toolbox, HAT, Interfaces; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2024_09"; r : array (Part_Type) of Integer_64; s : VString; type Disk is array (0 .. 180_000) of Integer; d : Disk; l : Integer := -1; -- Last block free : constant := -1; type Block_Descriptor is record id : Natural; pos : Natural; len : Natural; -- Possibly length of free blocks becomes 0. end record; -- Following arrays are "cheap vectors". -- In "full Ada" we would use Ada.Containers.Vectors -- free_list, file_list : array (1 .. 10_000) of Block_Descriptor; last_free, last_file : Natural := 0; procedure Read_Data is f_in : File_Type; b : Natural; is_file : Boolean := True; invalid_file_id : constant := -1; file_id : Integer := invalid_file_id; begin Open (f_in, input_name & ".txt"); Get_Line (f_in, s); Close (f_in); for i in 1 .. Length (s) loop b := Character'Pos (Element (s, i)) - Character'Pos ('0'); if is_file then -- File block: file_id := file_id + 1; -- Files are always of length > 0 last_file := last_file + 1; file_list (last_file).id := file_id; file_list (last_file).pos := l + 1; file_list (last_file).len := b; for j in 1 .. b loop l := l + 1; d (l) := file_id; end loop; else -- Free block: if b > 0 then last_free := last_free + 1; free_list (last_free).id := 0; -- Don't care free_list (last_free).pos := l + 1; free_list (last_free).len := b; for j in 1 .. b loop l := l + 1; d (l) := free; end loop; end if; end if; is_file := not is_file; end loop; end Read_Data; procedure Do_Part_1 is k : Integer; dc : Disk := d; lc : Integer := l; begin -- Move individual blocks from the right to the left, -- for compacting the disk (and fragment it by the way): k := 0; while k < lc loop if dc (k) = free then while lc > k and then dc (lc) = free loop lc := lc - 1; end loop; exit when k >= lc; -- dc (lc) is a file block to be moved. dc (k) := dc (lc); lc := lc - 1; end if; k := k + 1; end loop; -- Checksum: for i in 0 .. lc loop r (part_1) := r (part_1) + Integer_64 (i * dc (i)); end loop; end Do_Part_1; procedure Do_Part_2 is dc : Disk := d; from, to : Integer; begin -- Move contiguous blocks to compact the disk: for i in reverse 1 .. last_file loop for j in 1 .. last_free loop exit when free_list (j).pos > file_list (i).pos; -- Free space candidate is left to the file first block's position. if free_list (j).len >= file_list (i).len then -- There is enough room on the left to move the entire file -- as contiguous blocks. -- NB: AoC is kind and did not require overlapping moves (would -- have been a slightly more difficult special case)... from := file_list (i).pos; to := free_list (j).pos; for k in reverse 0 .. file_list (i).len - 1 loop dc (to + k) := dc (from + k); dc (from + k) := free; end loop; -- Update file & free lists: file_list (i).pos := free_list (j).pos; free_list (j).pos := free_list (j).pos + file_list (i).len; free_list (j).len := free_list (j).len - file_list (i).len; exit; end if; end loop; end loop; -- Checksum for i in 0 .. l loop if dc (i) /= free then r (part_2) := r (part_2) + Integer_64 (i * dc (i)); end if; end loop; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; Do_Part_1; if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Do_Part_2; Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put (+"Part 1:"); Put (r (part_1)'Image); New_Line; Put (+"Part 2:"); Put (r (part_2)'Image); New_Line; -- Part 1: validated by AoC: 6340197768906 -- Part 2: validated by AoC: 6363913128533 end if; end AoC_2024_09; ================================================ FILE: exm/aoc/2024/aoc_2024_09.txt ================================================ 4321114116413220541570577637245222444021661592171263865885224732273825869312483167708567817674108840154724814020488319597433518153794891419711843176705367457679452376442217873733926272917445955965888693468662976755233261564921212689858670822660921045521689325943861594792490217120327169792723237499587216904596599872121716859263956010994733457813596119487219392335736372245437169845898643189872245098246593768525719380823858692982841997272433155826154557589241449370746452694744461120803257817535871172861258399540791614671067669690485675575933779748639948612937974158443365681381337526776774557741709676398828286316936658527222644790712081652079243716718611714699591264889640908296877633397167645451824070692546271790612617368492387914819957451645126977652136993264543623984384273362998737586428844228427296633769815863805665473967815551981495259377432875783190113477509081634710887810853437713320802968906322258914297070369853573125859475605183363166665329463965516862161297928888617275265155104615907291186595883452383619243819833884714240719940259088646582164654782873155710965164503170548756254577791371262615158875962165429840846220173176672970878450984584757470954558851240499851819135176896339517949559592010834183236225915786392844753971771793218825354086948632255319742470157416924228693257901121299548413048685467541823787196394337517443937526888558491143659311349383956767396432628441416997634281956812854725174313273077916694598269211890567042477033257983257160403158507232419567166311591163292917407821414886113847306035342651999622606188754969403283241121901850207333124593501645469311878494651918804390694545382750561942479545387589151426228333806175831818618494733754688552211119951431572377692121656717159962743198155099237435107282505324506857964249375143308986135817237797135928386281215430721911948241474760431551459886778627335289222234881513785592697542215865548616194646447290367944374636461661493544386976889897712197475479439284583466543522118184824277279544578397564821711844992157299072334544344347393518638415773194913160896241788887377413377910983999937821871575474330796944125124876935907831408948197599769748848468774946693089334245425064251832141337715019849016633180483280473463373469937330402148711175395642486870187930578986661661949150469828729648275129308716375696783413712450946119371155924062393761249225972820323293384444425054794157242189298697518415872861359697737982562718141021917969125832586393135398622427718665355173468650992010379831649180938096823577641054289969506454168791105968599514496071384326353674647229327396894513563423623911413867293312219062414042644222883627246350422260746018339683356399199818442796773048636727648879712035861312999284254812337320868944982526426180896240994851136933868646545715693417557173996121562641842781856213787259527966922844811928228251547046163980684936233822204467873781809924138487141164222260364059366166934060789376123195576129499292509370965413491936736789428734228663605638966713362492208042333420734550628573965989212192423214196569296363527715854172857343352695102138309955132462967357823645689395129654103733491624536981708445212611445279314796423830412478444388406353248455802158481642919297188637397343942282327629574139202993427430448412546532703421297366159234324841957243915910452836224850677662527196569625593775634174766638612913666885258045577938861855311390752252783046428076922838226068623447986491125231645180541554778110436281493541901854839657993766703187708195435110913941368565534722398784628620526343405445368526137747556153507651854394702491513777992653327519186340975477847496488878752093428930771399803170458833725450926978652731839282911250373122871990577319189354515713604175863759179737991051514750527246614825992546437560382241327435449375219756271021485811632048364251373298727230612711876021119171548289774899737731501046109853298634274828683092782124317750895240508756337089107999759468191617527615944451672234885574425316718748434078221077819646502057489592913199296210883535911544982034487321212629114867383868686878985084131330576553356120833533954492809892223317939489667862535718593632663831604567127434314014229368954478686646103728896042953192651519276579803263559577913090598270654298681358951431222459563845954510162235864077732831174541723027325025116013983768653224598842348749981797674191761893263795132525327325192588375818981539382887576766224756281349278566602233546774288911763371413377431912394844955714932557807661545335615687315285992586648443886643165128951292864455345594656679355779244057993229857938482481947798249591724927613062657712604098122250782760151834129858837123411864705792974869574354889538867756922422726798931221558775769727881758826071478185599055376169264799383751155589729514451253358863358215893058403355182966171435544826595034886765837084142520341327194075203730745285209075829874921957462131201390378043993158623797173576734240156155452544599381177278588448847356477959337225543952343954698893738347292822194269995946849594638850225650173992575664115935141112725073803782429176945128394580838114482299997252782724186074418943845233743442398247196559241594506196627165144248133934611766663681613712316415467431955546533285892666424331669792322352673286789814893956552174882147128298833640248151621180367829809933463829712429885344754340374326164350266629732441149538333452867687539344879826214447997574683065894656585496617544624296772388351486914042866418825791272674972519789594162261956127145736671823569353836365674096941379827192439529108480115954339179141142855874417477178312435372387176761798559152951755417227292686132689174530518858328127284839408274825323577746985765795789213810465380694797446886587977573429852612247361299350906842239959882180674969894087597655754114102155749039971871291553356863967671873197765582984918919140282938406213709790619237114679132588209483221452326183733518462987818873437573175192237316863817464681484468901275849737846137277615793565215879612967456532377419849883842487144473315889739285138695723581105761583560448549974360315857923122873531754047846347318420878318112893255868443756939555745886405465834939983220798590651849177077605353864889174968742748442944306875319335117782901685672750385822689782227432291691759237513521754297753835254468722115723127928367431953993686856869349894323668489587143796451493508341886492408361363577505983379786692749683120429736376746466957245272921375692920149078588995673571288259578375948056789251477253158817748168454499871495181671278891968654608712766574653052992533637433534073889245394276631746942681841015643292592182943131942632384437554330306923515181465221505956806372638157855025666490354658753549794057976165112426103638225294735483541928218915443586328290759924556353147812609911965457924899921096899371307391302224886331937785799084918169416117501692883543402022994171224536195467264626998878744958286666442582289288102172359520318919117074228585511048171417636714148667252013863440485321953084226966521353352637806769315018247940273880208965901540187171226792716899578461947134948058957452428519142838519031109118174137639541446329453866774269224556394759603636963794585527971410576779151499902590752475765674506816776549764514922799169675753231508956748715412547611344949042972655169344364167289447858964479935166949527985135361445836673388302779233339437687584668573625291019966630413198934236923532377453507517171567617394808651198084218372246247159114269062174915709064194639282458669270463892394923748920667531455531844293637910719565391811379353168289672797936212994835838881158770603414118415153821829127705948414952103876785693821864517024873114439268399033609954588026101172375931983178258079311434278424326983718065776537483521564083779911382417409856813428435580583455462035491638854284135549941838939999925882858855956643847937482250613099327149234859527318731459513080381831518246379783314915158823921230746526501724905619808116909470109262498841256310336157368064183440203822319726158528203554443569671628645691513617383471509487668794278375677536295475298334144623981796399878979118924040111889958327103765326067841183441034424425899687962114245625932660637243202616379410815470583780776115563751162228628222417532799514515178688739693249586023492911474323644958412130867620254184887935503258979771677620333724833965649756313514273147587539171484709740836633202969793864288213608287704058787046753515204412974853314734609451506375761093197758969925776878488166271121642488974529166441684838433160517024162646926010653669949791916485103446258284963420911022176467238245289775268559948222212130333761575020156314289284659297204647487434297510216159422547824314653545254523803812531915142657583842241193442286141431396838912698668150208469286733137732127382472251809267259741244726715963317535887853294822315836221384121214336192199812604921652971333722189314647238406346716571629931599324772149122996604761973677681280762114212891867213146635765812239828187043208923556476639992523011958539223687268385136594375311422162868239394733366595699545814392877352457599391352787027801530568459535084455343789244947759902924979560413913426760437871405956551431437674694641415516294196497813893967211595696131667842617197642921407365877211856556254135312662757440442187807065295455366384856386758917394484508182319143598092402319809119367546667571624996519067541757805981615682897141757046153884993477338399184313644572934044293387841515687296617046799232226122475270642588596454336736484114964761426629768194755114296567266437996134797076902323601612658797708767691367472051768728636962377494602045146933279853636185988288419338803059606119822121573154308265266058742928928633679957416393953291964437155627877498373655949865879692336168519098625755643124606212773043191057683488153014532644376635169846642687215886909622501091321277744273707555964665653297316958866416686718594525108249308760273863174651846660601017498218905218191327924653122889653987748335881793598873222016351729471564851783193060587471749248735755734858858119644343838996737924778526147013321652812061614587515235723289414296137673809012664277601969105358777669677577327872999217561759421626109654295042875249222745149771163617543543688975359247208116611014768117832711869436205546556168133082197814168175328927484928339626205077659830782257906315414995756828666929779432365314953979283787693288935784483450887370235155583679376823629814855155706270865091449074597341593219569429697271281878617541829736893614135677383848323599686750374973321045879796113980469647154844735028751934769129291063841439824632795126156669776780368076573820566426377490748642101694313924351780656869536466855999817090719960562986867029874152538143298257617022486283931319679945816567798752856926807591637179809990791713557535122758837159874890218888717077374295694942291858973216585858673254665785378588276478215162783916701218849754863525762699212885416528623929242475675695469934273970895988577525403489632820768216623138994417301821729135821098457467373796248579672354192736529248745042894224904098885144109074233198573666204098543729715697777812804331124170435726665770264320539220167776631693379727472524627913466669736835289363636385477356437328648227559321675076399329723212152473686722294391655671507816268154831796379793384316155189903591338484715477841646207942788766753966914484852028348858944368435491839921267988405761204270855868464955891911288337157457181327888386628921447824649448678382342358382967708910207344285614711363883032583151921955798960457354751216597789864597293263726749824318517870432590689094941214161577201415909490256328652669562652619865296282929693653427413873189788311645177196504986854920549587273497525381924414323838645054988895388714824368609517575070979756145681296531214630676266306598414571812943193264453758709324797518567631676645427463212627923639505018243571142376865896313115784920593465218688537650843595763760759794436161335496565974725333349190181588345527121074292541751768894959473515656719943375323558352147103033668467691947177042993850557674293166685212647533105722197476371536171245334462575299556061148013608517743615558516382543173123864121167529258881407757954219704379233527337646533285984918612122205741225897332563354998944967617732229336906879765573849429365575452688924386173741884396973612405780503787307463978280806946437412402596946985941935707128266099928197163125767164545567263146357942171930656299248445375354935716946053581174673148487925888881261432561184599752517166975073678984616450272333132763979919971962984080879093439578125884662155948717808716338257454087327463741569423864247443955566132439989682948716964367849418821429157541634270626465994996511480491285478371469925499010667193942120101370672385249435966940769996572420961552746191278366693080901698779358624998151824306686192084378493551014518066272421529355953859136391422477579863774829184025967557594040575741319674402785296927795462831584623972471832884040339274829627158451712790395732311375868844548018992247931685722255987340686918972223942989855391399232336361187522728766613995309641656445537997334221704678916089283315979318528613262172143539379458734790637992384534549819763113415718987260235494106483783561287642581089459089181386578224405957268813464461814747265088424971475315281987392146256285251832957624209559163754748532155114667461355777561427432128679091734014692225198815814935752821187669627855433788304533603535859540525849282530499699827742419325221127534322709285899640516432825741305175903968574997348630471241398221823365612087563199237210972592712536357153443436428975743771631222934410772849299928735160368375129497124662267230427247416614282897595137787981673393214613933029245415193144559485416721361435332463304247769532746526629924571769797862108254534337755428419124534767643330581026736463958840176642936592228574957337293890305193898270682983257562463011804246111949791316161391541280315557862349256890222236485369278472707110282999444613298125543223296757173543693923689688236648434544729365721447438286728357967981293482981094729329359267461187505929161441446750604518633592812751888589197325935059319267973651812327211274575527488847884251643216553762919213423361994658112578461035845795398886238918737198691539863073213763722154735764662485262818147847995340662076864030744773351333374080536885242013213289628680624140895023652794781777495350414673712743824913122717585183406019627017737334484765879984357513348570213153675917869073101626319629942044543586655715408574591284946882374067416087117018898020353843578772444551403125215675109121419878265376755289923246393376981513403017944568433527501924888366829612382486798355468756116150607893998512762475165110989639665338874061912124124145139078184938679816619817634913429486321248798744826795194468154794994475209969615011984024423318482917573594439664825572437338665636419635935079818414548414592781415025394782523448945943608979271729584555484625221973535534312367734920997313994782209560272827978696977441216839314812542948879582628157119837692387434314699877305973321619154259452436657743604939384814446077134483379426745193973745134696826946935695449958504989269487657443188642972551457210864717438558191447581123597763495581619756687166373890754276523716707924492932372886597130681955488887201032231187341123552213845612959122285852607974187029327929792238208226278649265282341660192887237668671555448027611932135389447532856549182369446037952174171825663681149428378897849564118358612033535917716317499131797757541383105250194978203846838566976940141921554542747985879171781697116251744692321157905169184556349199843357814188673013985537535349326441114077326231258825234022659357133871548575786240437552753048695141253147218156254837669568351873644230227965765873131481622118595179281895622954496652936839479614161836527799434533205124271422116835358971276229653395109352873191494342237342461846167526829977812826604830188392455833928515102269871161193618284055148790214019991759389295404253364181271523795871913949398388434154292584337110442320437060266045589057984934659074784969468697442917875733159363377424489494734053878645998464939861551767197816208170645630786167424254951751311272423559185467583975389634892740681373796582866410288087614168892159723658975316709947442681124331842495602168505595545073714284531348156290633562548351693649258134181957266823947668917069813466652882978119934929269910171716838663964133265654238875654893801163738778769269938760806863517885301464165935795277882876696222452864583388975339574494709053544463299463889722493637509874531259161841519950899343594862258845642724245195539659226471672110927493595244389198306993688779781186116197221356448755642797446782767846373794568559528920899751179047719420367152761788115071115864177121755938642375745358883830333977876818522620137969509244171685428828608180597383325328579742981955509288737536125562397675377466547460585158209130829523376729638379244357769994736280547918894710809188553526228798675121943695954067898355309649523623521875619479419316363939529525796520757986434941205191146228866838108965458135547710831352804822271930481895557050168871361841177078137113422318294861941795519024145863907088921097522263771980972285341455862850433432601973693518839938412481252759368224833891701532523572722135671827298859657194827340209651646475798361745425287131617672387268503258649566574590613825554027155395718458651217795626496771931822466736223334967986855454737871433525121891134674221396658515434790511733296689784961383946152622835659316877601986606920659537435256396691492636379999451196556471566964958186383339468655995554515983856728673321982454368138343054338471738388527245727299878936294687822957826297624892794252983594252129773629365642155026969784122740788219898447387475742356683189961246169693499897444083687665464042189884162690655142969224899952165144599541639893793081258847167030726666398198102652827031195654829283367968109398422944411534273441546653627691273347965997119968196592553348255930497246129567435525582748726828771458206228921947967028187288313865377675342693888942702138617755339335355064771932138945266498123285628751316622845867722386619781929242781814951876581929483985964696863751554779188997157889441679654186465135244950943355351087144885679820541962836957805352236763761320879317431248609575643590688728117634946611691622241834828862521986135958194322996329343823938329589974416224597064556131163512101169435099473543852385772977247491582648406218239651786918169246822634379680416567335899186456606636773297566839364270799947419138657876949733817831747453589595464510125235552030289231445983809357436071721715628927395734154731442379984169925923921993747591987682832565811499577174376932199366894181969653481193304631753493479681825176325062219360584017968524762814862882302186903639389631435119836968707561529552813911395582511113645753964436982974184567996956491557424193671412896959339812569630979181787076177650146233442311174964754188295551784873679151304650225191907546514940683716157389344854311010168676134726856468852036954132272598409183843034219074918324865479141755546332575733492957845360507412509241761313806311944365159338752080718756706476427137167763559324925866326911533249245773106584364653871781114823415949702318474418738265688053978583876326258151586824275191385991347649439025898765596395507266135612264314874021189798567064733389296874133438816029512010711177384987283424948768653051799643299745381332867060459860572342458821628140289297711230852310341158388687585820324322501271814864926571947059767568433988689255364928651289422622392267275154404595472193275012321858675228765385611695647228125522464689905226789517144581467059212194833613889441565251682987108972285566824932765849894449146351245595393529776839424852485537494698127153701072623482794638807974927663982192809086315494991329946557154575512634504776406971742957666498799156187975257783197571956826811830117974624782289085907327396295284564395625275867717552842987395575245482432528429444767941114410138943483186229460348039436 ================================================ FILE: exm/aoc/2024/aoc_2024_09_questions.txt ================================================ --- Day 9: Disk Fragmenter --- Another push of the button leaves you in the familiar hallways of some friendly amphipods! Good thing you each somehow got your own personal mini submarine. The Historians jet away in search of the Chief, mostly by driving directly into walls. While The Historians quickly figure out how to pilot these things, you notice an amphipod in the corner struggling with his computer. He's trying to make more contiguous free space by compacting all of the files, but his program isn't working; you offer to help. He shows you the disk map (your puzzle input) he's already generated. For example: 2333133121414131402 The disk map uses a dense format to represent the layout of files and free space on the disk. The digits alternate between indicating the length of a file and the length of free space. So, a disk map like 12345 would represent a one-block file, two blocks of free space, a three-block file, four blocks of free space, and then a five-block file. A disk map like 90909 would represent three nine-block files in a row (with no free space between them). Each file on disk also has an ID number based on the order of the files as they appear before they are rearranged, starting with ID 0. So, the disk map 12345 has three files: a one-block file with ID 0, a three-block file with ID 1, and a five-block file with ID 2. Using one character for each block where digits are the file ID and . is free space, the disk map 12345 represents these individual blocks: 0..111....22222 The first example above, 2333133121414131402, represents these individual blocks: 00...111...2...333.44.5555.6666.777.888899 The amphipod would like to move file blocks one at a time from the end of the disk to the leftmost free space block (until there are no gaps remaining between file blocks). For the disk map 12345, the process looks like this: 0..111....22222 02.111....2222. 022111....222.. 0221112...22... 02211122..2.... 022111222...... The first example requires a few more steps: 00...111...2...333.44.5555.6666.777.888899 009..111...2...333.44.5555.6666.777.88889. 0099.111...2...333.44.5555.6666.777.8888.. 00998111...2...333.44.5555.6666.777.888... 009981118..2...333.44.5555.6666.777.88.... 0099811188.2...333.44.5555.6666.777.8..... 009981118882...333.44.5555.6666.777....... 0099811188827..333.44.5555.6666.77........ 00998111888277.333.44.5555.6666.7......... 009981118882777333.44.5555.6666........... 009981118882777333644.5555.666............ 00998111888277733364465555.66............. 0099811188827773336446555566.............. The final step of this file-compacting process is to update the filesystem checksum. To calculate the checksum, add up the result of multiplying each of these blocks' position with the file ID number it contains. The leftmost block is in position 0. If a block contains free space, skip it instead. Continuing the first example, the first few blocks' position multiplied by its file ID number are 0 * 0 = 0, 1 * 0 = 0, 2 * 9 = 18, 3 * 9 = 27, 4 * 8 = 32, and so on. In this example, the checksum is the sum of these, 1928. Compact the amphipod's hard drive using the process he requested. What is the resulting filesystem checksum? (Be careful copy/pasting the input for this puzzle; it is a single, very long line.) --- Part Two --- Upon completion, two things immediately become clear. First, the disk definitely has a lot more contiguous free space, just like the amphipod hoped. Second, the computer is running much more slowly! Maybe introducing all of that file system fragmentation was a bad idea? The eager amphipod already has a new plan: rather than move individual blocks, he'd like to try compacting the files on his disk by moving whole files instead. This time, attempt to move whole files to the leftmost span of free space blocks that could fit the file. Attempt to move each file exactly once in order of decreasing file ID number starting with the file with the highest file ID number. If there is no span of free space to the left of a file that is large enough to fit the file, the file does not move. The first example from above now proceeds differently: 00...111...2...333.44.5555.6666.777.888899 0099.111...2...333.44.5555.6666.777.8888.. 0099.1117772...333.44.5555.6666.....8888.. 0099.111777244.333....5555.6666.....8888.. 00992111777.44.333....5555.6666.....8888.. The process of updating the filesystem checksum is the same; now, this example's checksum would be 2858. Start over, now compacting the amphipod's hard drive using this new method instead. What is the resulting filesystem checkum? ================================================ FILE: exm/aoc/2024/aoc_2024_10.adb ================================================ -- Solution to Advent of Code 2024, Day 10 ------------------------------------------- -- Hoof It -- -- https://adventofcode.com/2024/day/10 -- Copy of questions in: aoc_2024_10_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_10 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2024_10"; n_max : constant := 56; nx_max : constant := n_max; ny_max : constant := n_max; subtype Range_X is Integer range 1 .. nx_max; subtype Range_Y is Integer range 1 .. ny_max; type Map_Type is array (Range_X, Range_Y) of Integer; map : Map_Type; n : Point; procedure Data_Acquisition is c : Character; f : File_Type; x, y : Natural := 0; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop y := y + 1; x := 0; Get (f, c); loop x := x + 1; map (x, y) := Character'Pos (c) - Character'Pos ('0'); exit when End_Of_Line (f); Get (f, c); end loop; end loop; n.x := x; n.y := y; Close (f); end Data_Acquisition; r : array (Part_Type) of Integer; -- Walk (part 2: all possible paths) to all possible points with a 9. -- Since we always go up one level above, we don't need to mark visited cells. -- procedure Hike (x, y, level : Integer; part : Part_Type) is begin if x in 1 .. n.x and then y in 1 .. n.y and then level = map (x, y) then if level = 9 then r (part) := r (part) + 1; if part = part_1 then map (x, y) := -1; -- "Erase" the summit (we count only one path to it). end if; else Hike (x - 1, y, level + 1, part); Hike (x + 1, y, level + 1, part); Hike (x, y - 1, level + 1, part); Hike (x, y + 1, level + 1, part); end if; end if; end Hike; procedure Find_Hiking_Heads is map_orig : constant Map_Type := map; begin for y in 1 .. n.y loop for x in 1 .. n.x loop if map (x, y) = 0 then -- Part 1: walk to all possible summits. Hike (x, y, 0, part_1); map := map_orig; -- Part 2: walk all possible paths to all possible summits. Hike (x, y, 0, part_2); end if; end loop; end loop; end Find_Hiking_Heads; T0 : constant Time := Clock; compiler_test_mode : constant Boolean := Argument_Count >= 2; begin r (part_1) := 0; r (part_2) := 0; Data_Acquisition; Find_Hiking_Heads; if compiler_test_mode then if r (part_1) /= Integer'Value (To_String (Argument (1))) or r (part_2) /= Integer'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: score : " & r (part_1)); Put_Line (+"Part 2: rating : " & r (part_2)); -- Part 1: validated by AoC: 737 -- Part 2: validated by AoC: 1619 end if; end AoC_2024_10; ================================================ FILE: exm/aoc/2024/aoc_2024_10.txt ================================================ 43217654309879876104563234589896761012345656543098901001 34108903212368123233472105676787851299856567832187812652 45677814301457014312986345589876940387765678943046543743 56789325100876525800345276430105432456566589858956769821 65438456912963436901236187621234501223455410767349874430 74321067803451107898547093412012982016764323101210143561 89412210987430210789698892102123673107895214589723652678 78601521856521345678721743089034543212345605679854781789 66789430545678934505430654898745672212236765434765690878 55676545038943213216765989601654981300129870121012345969 46543216127657804389834808762347690456789983498141456452 65454307233456934870126712354878765565210012507230987321 54567898332110125961015645403969234674323215616546576010 65658983021001876854324106912452128789321308723455678901 76543212137892965348933217832141089873410419678964987652 89862901236543501267018363101033210565566566569873788543 89871876544345652106529854892123521454479877654012699830 78100703454278743212434763763014672343287778943210581021 65210212565189858906763212654985785650198961212101432010 54321056876012567875898708783476698763267890303215678321 87012567988703489874345679692676543294986725456574329478 96543498589876530365210189501987650187675216987687610569 01234567651010921234501076401236501010564307678596789876 10389830532329854376542345321545692323403018789455430965 21456721013456765289031234980098783410912129670320121054 92505432565421010109120345671107654567823451061210120123 87615443478302341018750134543234541050765962552121234984 34322342189219650129665234789432132021894873443010965673 45451056077828743234574343276543032134703210523457876532 51069987456943104545987650167898749865612309610765454101 32678678345652210698092156756547056764303458779890363232 43010589232781306787183045876532178965210569888211274321 56923432101090458989254234923421369878934678898302989430 87889211078764567876360143010030450767125986567401276589 96676305669653478985478652102141341458076803456564345676 45435434734522780340349760123456232349883712678178737894 80127821821011091211299854354987101016792103549069016323 92346940910329654304587121267807652345013401232108925412 81055432101458765643671010871018947654324589543987432101 76567789023467010782532346965425638945695678654986540012 05498654110567821891047897212334721032786014345678901098 12387013223489932346156598101549889821012823216765212387 03456323016576542345692367210678710701296954907854323456 12345465437895431016781450123467623654387867878985401501 21089870124326528701670101874345634565676541045621032012 32189210065017019632543210965236730120545632456734548743 43498349876298903545450143050159821321234012349895699654 34567658389101232123469052101567634489234510106786789985 99876501276788943016578769872498105672105621215021058876 87035432365897654107689898763343234321678789334134567655 70129641034781089898791099854232145690569245493254321567 63238701123654178718982387763156056781410126787655010498 54345652321073265001073456012047189872328901098546710327 34568543434589874132569895145438976987437812361239891210 21879654898678013203456701236327805456546521450967890123 30968745467654320112345210987610112345545430567856543234 ================================================ FILE: exm/aoc/2024/aoc_2024_10_questions.txt ================================================ --- Day 10: Hoof It --- You all arrive at a Lava Production Facility on a floating island in the sky. As the others begin to search the massive industrial complex, you feel a small nose boop your leg and look down to discover a reindeer wearing a hard hat. The reindeer is holding a book titled "Lava Island Hiking Guide". However, when you open the book, you discover that most of it seems to have been scorched by lava! As you're about to ask how you can help, the reindeer brings you a blank topographic map of the surrounding area (your puzzle input) and looks up at you excitedly. Perhaps you can help fill in the missing hiking trails? The topographic map indicates the height at each position using a scale from 0 (lowest) to 9 (highest). For example: 0123 1234 8765 9876 Based on un-scorched scraps of the book, you determine that a good hiking trail is as long as possible and has an even, gradual, uphill slope. For all practical purposes, this means that a hiking trail is any path that starts at height 0, ends at height 9, and always increases by a height of exactly 1 at each step. Hiking trails never include diagonal steps - only up, down, left, or right (from the perspective of the map). You look up from the map and notice that the reindeer has helpfully begun to construct a small pile of pencils, markers, rulers, compasses, stickers, and other equipment you might need to update the map with hiking trails. A trailhead is any position that starts one or more hiking trails - here, these positions will always have height 0. Assembling more fragments of pages, you establish that a trailhead's score is the number of 9-height positions reachable from that trailhead via a hiking trail. In the above example, the single trailhead in the top left corner has a score of 1 because it can reach a single 9 (the one in the bottom left). This trailhead has a score of 2: ...0... ...1... ...2... 6543456 7.....7 8.....8 9.....9 (The positions marked . are impassable tiles to simplify these examples; they do not appear on your actual topographic map.) This trailhead has a score of 4 because every 9 is reachable via a hiking trail except the one immediately to the left of the trailhead: ..90..9 ...1.98 ...2..7 6543456 765.987 876.... 987.... This topographic map contains two trailheads; the trailhead at the top has a score of 1, while the trailhead at the bottom has a score of 2: 10..9.. 2...8.. 3...7.. 4567654 ...8..3 ...9..2 .....01 Here's a larger example: 89010123 78121874 87430965 96549874 45678903 32019012 01329801 10456732 This larger example has 9 trailheads. Considering the trailheads in reading order, they have scores of 5, 6, 5, 3, 1, 3, 5, 3, and 5. Adding these scores together, the sum of the scores of all trailheads is 36. The reindeer gleefully carries over a protractor and adds it to the pile. What is the sum of the scores of all trailheads on your topographic map? --- Part Two --- The reindeer spends a few minutes reviewing your hiking trail map before realizing something, disappearing for a few minutes, and finally returning with yet another slightly-charred piece of paper. The paper describes a second way to measure a trailhead called its rating. A trailhead's rating is the number of distinct hiking trails which begin at that trailhead. For example: .....0. ..4321. ..5..2. ..6543. ..7..4. ..8765. ..9.... The above map has a single trailhead; its rating is 3 because there are exactly three distinct hiking trails which begin at that position: .....0. .....0. .....0. ..4321. .....1. .....1. ..5.... .....2. .....2. ..6.... ..6543. .....3. ..7.... ..7.... .....4. ..8.... ..8.... ..8765. ..9.... ..9.... ..9.... Here is a map containing a single trailhead with rating 13: ..90..9 ...1.98 ...2..7 6543456 765.987 876.... 987.... This map contains a single trailhead with rating 227 (because there are 121 distinct hiking trails that lead to the 9 on the right edge and 106 that lead to the 9 on the bottom edge): 012345 123456 234567 345678 4.6789 56789. Here's the larger example from before: 89010123 78121874 87430965 96549874 45678903 32019012 01329801 10456732 Considering its trailheads in reading order, they have ratings of 20, 24, 10, 4, 1, 4, 5, 8, and 5. The sum of all trailhead ratings in this larger example topographic map is 81. You're not sure how, but the reindeer seems to have crafted some tiny flags out of toothpicks and bits of paper and is using them to mark trailheads on your topographic map. ================================================ FILE: exm/aoc/2024/aoc_2024_11.adb ================================================ -- Solution to Advent of Code 2024, Day 11 ------------------------------------------- -- Plutonian Pebbles -- -- https://adventofcode.com/2024/day/11 -- Copy of questions in: aoc_2024_11_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_11 is use AoC_Toolbox, HAT, Interfaces; use Hash_Maps; h : Hash_Map_Type; -- Hash table with stone counts. d : constant Data_Type := input; verbosity_level : constant := 0; procedure Set_Data is procedure Set (i : Integer) is dummy : Integer_64; begin Insert (h, Image (i), 1, True, dummy); end Set; begin Clear (h); -- First example: "0 1 10 99 999" -- Second example: "125 17" -- Input: "3028 78 973951 5146801 5 0 23533 857" case d is when mini => Set (125); Set (17); when input => Set (3028); Set (78); Set (973951); Set (5146801); Set (5); Set (0); Set (23533); Set (857); end case; end Set_Data; r : array (Part_Type) of Integer_64; procedure Show is total : Integer_64 := 0; begin for i in h'Range loop for j in 1 .. h (i).slots loop if h (i).slot (j).value > 0 then Put (h (i).slot (j).key); if h (i).slot (j).value = 1 then Put (' '); else Put (+":" & h (i).slot (j).value'Image & "x "); end if; total := total + h (i).slot (j).value; end if; end loop; end loop; New_Line; Put_Line (+"Stones: " & total'Image); end Show; procedure Do_Part (part : Part_Type; rounds : Integer) is h2 : Hash_Map_Type; -- Hash table with stone counts, after transformation. procedure Apply_Rules (s : in out Hash_Slot_Type) is l : Integer; s1, s2 : VString; procedure Transform (from, to : VString; remove : Boolean) is old, dummy : Integer_64; begin Find (h2, from, 0, old); if remove then Insert (h2, from, old - s.value, True, dummy); if verbosity_level > 1 then Put_Line (+"From " & from & " stones: " & old'Image & " -> " & Integer_64'Image (old - s.value)); end if; else if verbosity_level > 1 then Put_Line (+"From " & from & " stones: " & old'Image); end if; end if; Find (h2, to, 0, old); Insert (h2, to, old + s.value, True, dummy); if verbosity_level > 1 then Put_Line (+" To " & to & " stones: " & old'Image & " -> " & Integer_64'Image (old + s.value) & dummy'Image); end if; end Transform; begin if s.value > 0 then l := Length (s.key); if s.key = "0" then Transform (s.key, +"1", True); elsif l mod 2 = 0 then s1 := Slice (s.key, 1, l / 2); s2 := Slice (s.key, l / 2 + 1, l); while Length (s2) > 1 and then Element (s2, 1) = '0' loop Delete (s2, 1, 1); end loop; Transform (s.key, s1, True); Transform (s.key, s2, False); else s1 := +Integer_64'Image (Integer_64'Value (To_String (s.key)) * 2024); Delete (s1, 1, 1); Transform (s.key, s1, True); end if; end if; end Apply_Rules; begin if verbosity_level > 0 then Show; end if; h2 := h; for iter in 1 .. rounds loop -- Traverse the hash table for applying the rules to -- all stones: for i in h'Range loop for j in 1 .. h (i).slots loop Apply_Rules (h (i).slot (j)); end loop; end loop; h := h2; if verbosity_level > 0 then Show; end if; end loop; -- Traverse the hash table for counting the stones: for i in h'Range loop for j in 1 .. h (i).slots loop r (part) := r (part) + h (i).slot (j).value; end loop; end loop; end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Set_Data; Do_Part (part_1, 25); Do_Part (part_2, 50); if compiler_test_mode then if r (part_1) /= Integer_64'Value (To_String (Argument (1))) or r (part_2) /= Integer_64'Value (To_String (Argument (2))) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put (+"Part 1:"); Put (r (part_1)'Image); New_Line; Put (+"Part 2:"); Put (r (part_2)'Image); New_Line; -- Part 1: validated by AoC: 198089 -- Part 2: validated by AoC: 236302670835517 end if; end AoC_2024_11; ================================================ FILE: exm/aoc/2024/aoc_2024_11_questions.txt ================================================ --- Day 11: Plutonian Pebbles --- The ancient civilization on Pluto was known for its ability to manipulate spacetime, and while the Historians explore their infinite corridors, you've noticed a strange set of physics-defying stones. At first glance, they seem like normal stones: they're arranged in a perfectly straight line, and each stone has a number engraved on it. The strange part is that every time you blink, the stones change. Sometimes, the number engraved on a stone changes. Other times, a stone might split in two, causing all the other stones to shift over a bit to make room in their perfectly straight line. As you observe them for a while, you find that the stones have a consistent behavior. Every time you blink, the stones each simultaneously change according to the first applicable rule in this list: If the stone is engraved with the number 0, it is replaced by a stone engraved with the number 1. If the stone is engraved with a number that has an even number of digits, it is replaced by two stones. The left half of the digits are engraved on the new left stone, and the right half of the digits are engraved on the new right stone. (The new numbers don't keep extra leading zeroes: 1000 would become stones 10 and 0.) If none of the other rules apply, the stone is replaced by a new stone; the old stone's number multiplied by 2024 is engraved on the new stone. No matter how the stones change, their order is preserved, and they stay on their perfectly straight line. How will the stones evolve if you keep blinking at them? You take a note of the number engraved on each stone in the line (your puzzle input). If you have an arrangement of five stones engraved with the numbers 0 1 10 99 999 and you blink once, the stones transform as follows: The first stone, 0, becomes a stone marked 1. The second stone, 1, is multiplied by 2024 to become 2024. The third stone, 10, is split into a stone marked 1 followed by a stone marked 0. The fourth stone, 99, is split into two stones marked 9. The fifth stone, 999, is replaced by a stone marked 2021976. So, after blinking once, your five stones would become an arrangement of seven stones engraved with the numbers 1 2024 1 0 9 9 2021976. Here is a longer example: Initial arrangement: 125 17 After 1 blink: 253000 1 7 After 2 blinks: 253 0 2024 14168 After 3 blinks: 512072 1 20 24 28676032 After 4 blinks: 512 72 2024 2 0 2 4 2867 6032 After 5 blinks: 1036288 7 2 20 24 4048 1 4048 8096 28 67 60 32 After 6 blinks: 2097446912 14168 4048 2 0 2 4 40 48 2024 40 48 80 96 2 8 6 7 6 0 3 2 In this example, after blinking six times, you would have 22 stones. After blinking 25 times, you would have 55312 stones! Consider the arrangement of stones in front of you. How many stones will you have after blinking 25 times? --- Part Two --- The Historians sure are taking a long time. To be fair, the infinite corridors are very large. How many stones would you have after blinking a total of 75 times? ================================================ FILE: exm/aoc/2024/aoc_2024_12.adb ================================================ -- Solution to Advent of Code 2024, Day 12 ------------------------------------------- -- Garden Groups -- -- https://adventofcode.com/2024/day/12 -- Copy of questions in: aoc_2024_12_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_12 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini1"; n : constant := 4; -- input_name : constant VString := +"mini2"; n : constant := 5; -- input_name : constant VString := +"mini3"; n : constant := 10; input_name : constant VString := +"aoc_2024_12"; n : constant := 140; map : array (1 .. n, 1 .. n) of Character; type Seen_Type is array (1 .. n, 1 .. n) of Boolean; seen_clear : Seen_Type; -- Substitute for (others => (others => False)) -- Borders of each cell (think of spreadsheet cells' styles): -- type Cell_Border is array (Direction) of Boolean; type Border_Type is array (1 .. n, 1 .. n) of Cell_Border; border_clear : Border_Type; -- Substitute for (others => (others => (others => False))) r : array (Part_Type) of Integer; procedure Read_Data is f : File_Type; cell_border_clear : Cell_Border; begin for d in Direction loop cell_border_clear (d) := False; end loop; Open (f, input_name & ".txt"); for y in reverse 1 .. n loop for x in 1 .. n loop Get (f, map (x, y)); seen_clear (x, y) := False; border_clear (x, y) := cell_border_clear; end loop; end loop; Close (f); end Read_Data; procedure Do_Part (part : Part_Type) is seen : Seen_Type; procedure Do_Region (x_start, y_start : Integer; plant : Character) is fence, area : Natural := 0; border : Border_Type; -- Min/Max framing for part 2's search for aligned fences. -- The framing speeds up massively the search. -- In HAC: part 2's total run time goes from 29 seconds to 1.2 second! min_x, max_x : Integer := x_start; min_y, max_y : Integer := y_start; procedure Flood_Fill (x, y, orig_x, orig_y : Integer; dir : Direction_or_Nil) is -- Developped from aoc_2023_18. begin if x in 1 .. n and then y in 1 .. n and then map (x, y) = plant then -- We are still inside the region. if not seen (x, y) then seen (x, y) := True; area := area + 1; Flood_Fill (x - 1, y, x, y, west); Flood_Fill (x + 1, y, x, y, east); Flood_Fill (x, y - 1, x, y, south); Flood_Fill (x, y + 1, x, y, north); end if; else -- We have crossed a border: either the map's limits, or to -- a region for another plant type. fence := fence + 1; if part = part_2 then border (orig_x, orig_y)(dir) := True; min_x := Min (orig_x, min_x); max_x := Max (orig_x, max_x); min_y := Min (orig_y, min_y); max_y := Max (orig_y, max_y); end if; end if; end Flood_Fill; begin if part = part_2 then border := border_clear; end if; Flood_Fill (x_start, y_start, 0, 0, nil); if part = part_2 then -- Compute rebates for the bulk discount. -- Horizontal fences: for y in min_y .. max_y loop for x in min_x + 1 .. max_x loop if border (x, y)(north) and then border (x - 1, y)(north) then fence := fence - 1; end if; if border (x, y)(south) and then border (x - 1, y)(south) then fence := fence - 1; end if; end loop; end loop; -- Vertical fences: for x in min_x .. max_x loop for y in min_y + 1 .. max_y loop if border (x, y)(west) and then border (x, y - 1)(west) then fence := fence - 1; end if; if border (x, y)(east) and then border (x, y - 1)(east) then fence := fence - 1; end if; end loop; end loop; end if; r (part) := r (part) + area * fence; end Do_Region; begin seen := seen_clear; for x in 1 .. n loop for y in 1 .. n loop if not seen (x, y) then Do_Region (x, y, map (x, y)); end if; end loop; end loop; end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; Do_Part (part_1); if not compiler_test_mode then Do_Part (part_2); end if; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 1319878 -- Part 2: validated by AoC: 784982 end if; end AoC_2024_12; ================================================ FILE: exm/aoc/2024/aoc_2024_12.txt ================================================ WEEEEEFFFFFFFFFFFTTTTTTTTTTOBBBBQGGGQQQQQQQQQQQQQQQEEGGGGGGGGGGGGGOEMMMMMMMMMMMCMMMIIIIINWWWWWWDDDDDDDDDDDOOOOOOOOOOOOOOOOOXXXXWWWWWWWWWWWWW WWEEEEWWFFFFFFFFFFFNNNTTTTOOOBBBQQQGGQQQQQQQQQQQQQEEEEGGGGGGGGGGGGOOOMMMMMMMMMMMMMMIIIINNVNNWWWDDDDDDDDDOOOOOOOOOOOOOOOOOOOXXXXCQWWWWWWWWWWW WWWEEEWFFFFFFFFFFFNNNNNNTTOOOOBOQQQQQQQQQQQQQQQQQQEEEEEEGGGGGGGGGXOOOMMMMMMMMMMMMMMMINNNNNNNWWWDDDDDDDDDVQOOOOOOOOOOOOOOOOOXXXXCCCWWWWWWWWWW WWWWWWWFFFFFFFFFFFNNNNNNNTOOOOOOUUQQQQQQQQQQQQQQQQEEEEGGGGGGGGGGROOBBMMMMMMMMMMMMMMMINNNNNNNWWDDDDDDDDDDVVVOOOOOOOOOOOOOOOGXXXXCCWWWWWWWWWWW WWWWWWWTWFFFFFFFFNNFNNJJNNOOOOOUUUUNNNQQQQQQQQQQEEEEEEEEEGGGGGRGRRRRBMMMMMMMMMMMMMMMNNNNNNNNNNDDDDDDDDVVVVVHOOOOOOOOOOOOOOGGXXXXXWWWWWWWWWWW WWWWWWWWWWFFFFGFFFFFFNOOOOOOOOUUUNNNNNQQQQQQQQQQEEEEEEEEGGYGYRRRRRRRBMMMMMMMMMMMMMMNNNNNNNNFFFDDDDDDDDDVUUUUUUUOOOOOOOOOOGGGGXXXXWWWWWWWWWWW WWWWWWWWWWWWWGGGFFFFFFOOOOOOOOUNNNNNNNNNQQQQQQQEEEEEEEDGGYYYYRRRRRRRBUUMMMMMMMMMMMMCCNNNNNNFFDDDDDDDDDDDUUUUUUUOOOOOOOORGGGGGGGGGGWWWWWWWWWW WWWWWWWWWWWWGGGGGFFFFFOOOOOOONNNNNNNNNNNNNQQQQQEEEEEEEEGGRRRRRRRRRUTUUUUUMMMMMMMMCMCCNNNNNNFFFDDDDDDDDDDUUUUUUUOOOORRORRRRRGGGGGGGGKKKWKWWWW WWWWWWWWWWWGGGGGGFFFHFOOOOOONNNNNNNNNNNNNNNNQQQQEEEEEEEEERRRRRRRRRUUUUUUUMMMMMCCMCCCNNNNNNNNNFDDDDDDDDDGUUUUUUURORRRRRRRRGGGGGGGGGGKKKKKWWWW WWWWWWWVGGGGGGGGGGGFVFOOOOOOOOONNNNNNNNNNNNNNWWQEEEEUEEERRRCCCCCCCUUUUUUTMIIIMCCCCCCNNNNNNNNNDDDUUDDDRDGUUUUUUURORRRRRRRRRGGGGGGGGGGKKKKKWWW WWWWWWWGGGGGGGGGGGHVVBOOOOOOOOOONNNNNNNNNNTTWWHQEEEEUUEERRRCCCCCCCUUUUUUUIIIIMMCCCCNNNNNNNNNHDAANUNNNNNNUUUUUUURRRRRRRRRRRGGGGGGGGGAKKKKKWWW WWWWWWWWWGGGGGYYGGVVVBOOOOVVVOOONNNNNNNNNNTWWWTTTEEUUUUURRRCCCCCCCUUUUUUUIIICCCCCCNNNNWWNNNNNNAANUNNNNNNUUUUUUUUUUUUUUUUHGGGGGGGGGGGKKKKKKWW WWWWWWWWWGGGGYYYYYVVVBVOOVVVVVNNNNFFNNNNNNTTWWTTTTTUUUUUUURRRRRUUUUUUUUUUIICCCCCCCCCCCCCANNNNNAANNNNNNNNUUUUUUUUUUUUUUUUHGGGGGGGGGGGKKKKKKWW WWWWWWWGGGGGGYYYYYVVVVVVQVVVVVNNXXXFFFFNFTTTTTTTTTTUUUUUUURRRRRRUUUUUUUUUIICCCCCCCCCCCCCAAAANNAAANNNNNNGGGGGGRUUUUUUUUUUUUUUUUUGGGGKKKKKKKGG WWNWWWWGGGGGGGYYVYVVVVVVVVVVVVVNFFFFFFSFFTTTTTTTTTTUUUUUUURRRRRRWUUUUUUUUUUUCCCCCCCCCCCCAAAAAAAAANNNNNGGGGGRRRUUUUHUUUUUUUUUUUUGGGGKKKKKKKGG WWGGGGGGGGGGGGYVVYVVVVVVVVVVVVVVFFFFFFSFFFFTTTTTTFTTUUUUUURRRRRWWUUUUUUUUAAUCCCCCCCCHCCAAAAPPPAAANNNNNVVGRRRRRUUUUHUUUUUUUUUUUUGKKKKKKKKKKKG WDDGGGGPGGGGGYYVVVVVVVVVVVVVVVVVVVFFFFFFFTTTTTTTTFFFUUUUUBRRRRRRUUUUUUUUAAAAACCCCTCCMMAAAAPPPPPAANNPPVVVVZRZZZUUUUHUUUUUUUUUUUUKKKKKKKKKKKKG DDDGDGGGGGGGGYYYVVVVVVVVVVVVVVVVVVFFFFFFFFTTTTTTTFFFFUBBBBBRRRRRUUUUUUUUUAAAAACCACCCMAAAAPPPPPPAPVVPVVVVVZZZZZUUUUHHHHHHHQUUUUUKKKKKKKKKKKKK DDDDDDDGDGWWJYJVVVVVVVVVVVVVVVVVHHHHFFFFFFTTTTTFFFFFFUUBBBRRRRRRUUJRUUCUUAAAAAAAAMPCMMAAAAPPPPPAPJVVVVVVVZZZZZZHHHHHHHHHQQUUUUUKKKKKKKKKKKKK DDDDDDDDDDJWJJJVVVVVVVVVVVVVVVVVHHHHFFFTFTTTTTFFFFFFFFBBBBBRRRRRRURRUUUAAAAAAAAMMMMCMMMMAAAPPPPPPJVVVVVVVZZZZRZZRHHHHNHHQQUUUUUZKKKKKKKKKKUK DDDDDDDDDDJJJJJJJJJVVVVVVVVVVVVVHHHHFFFFHTTTTHTHFFFFBBBBBBBBRRRRRRRRRUUUUAAAAAAMMMMMMMMMPPPPPPPPPVVVVVVVVVVRZRZZRHHNNNDDQQUUUUUKKKKKKKKKKKUU DDDDDDDDDDJJJJJJJJJVVQVVOVVVAAHVVHHHFFFFHHHTTHHHHFFRRRRRRRRBBBRRRRRRRRRUAAAANNNMMMMMMMMMYPPPPPPPPVVVVVVVVVVRRRRRRRRNNNDDDDDDDDDDKKKKKUKUUUUU DDDDDDDDDDJJJJJJJJDVVQQVVVVVVVHHHHHHHHHHHHHHHHHHHFFRRRRRRRRBBBBRRRRRRKKNNAAANNNNNMMMMMMMPPPPPPPPVVVVVRRRVVVRRRRNRRRNDDDDDDDDDDDDNFFKKKUUUUUU DDDDDDDDDDDDJJJJJJJQQQVVVVVVVVVHHHHHHHHHHHHHHHHHFFFRRRRRRRRBBBBEERRRKKKKNNNNNNNNMMMMMMMPPPPPPPPPPUUVVRRRRRRRRRRRRRRNDDDDDDDDDDDDNKKKNNUUUUUU DDDDDDDDDDDJJJJJJJQQQQQVVOVPVHHHHHHHHHHHHHHHHHHHHFFRRRRRRRRGGEEEEERNNKKKNNNNNNNNMMMMMMMPPPPPPPPPPUUUUURRRRRRRRRRRRSDDDDDDDDDDDDDNNNNNUUUUUUU DDDDDDDDDDDJJJJJJQQQQQQQOOOPPHHOHHHHHHHIHHHHHHHRRRRRRRRRRRRGGEEENNNNNNNNNNNNNNNMMMMMMMMMPPPPPPPPUUUUUUURRRRRRRRRRRSDDDDDDDDDDDDNNNNSNUUUUUUU DDDDDDDDDDJJJJJJJQQQQQQOOOOOOOOOHHHHHHHIIHHHHIFRRRRRRRRRRRRRRGEEEEENNNNNNNNNNNNMMMMMMMMPPPPPPPPPUUUUUUURRRRRRYRRRSSDDDDDDDDDDDDNNNNSISSSUUUU DDDDDDDDDDJJJJJJJJFFQQQOOJOOOOOOHHHHHHHIIHHIIIFRRRRRRRRRRRRRRGEEEEENNNNNNNNNNNMMMMMMMMMPPPPPPPPUUTTUUUURRLRPRYYYYYDDDDDNNNNNNNDNNNNSSSSSSUUU DDDDDDDDDDJJJJJJJJFFQOOBOOOOOOQQHHHHHIIIIHIIIIFRRRRRRRRRRRRRRGEKKEEENNNNNNNNNNNMMMMMMMMMMPPPPPPTTTUUUUURRYRYYYYYYWDDDDDNNNNNNNNNNNSSSSSSUUUU KKDDDDDDDDDJJJJJFJFQQOOOOOOOOOOOOHHIIIIIIIIIIIFRRRRRRRRRRRRRKKKKEEEENNNNNNNNNNNMMMMMQMMMMZPPPPPTTTUUUUUUUYYYYYYYYNNDDDNNNNNNNNNNNSSSSSSSSUUU KDDDDDDDDDDDDKFFFFFFHHHHHHHHHOOODIHHIIIIIIIIIIFRRRRRRRRRRRRRRRRRRKENNNNNNNNNNNNMMMMMQXMMMZZPZTTTTTTUUUYUUYYYYYYYYYNNNNNNNNNNNNNNSSSSSSSSSSUU KDDKDDKKKDDDKKFFFFFFHHHHHHHHHOOOIIIIIIIIIIIIIIIRRRRRRRRRRRMRRRRRRKKNNNNNNNNNNNNMMMMMQXMMMZZZZZTTTTTTUUYYYYYYYYYYYYNNNNNNNNNNNNNSSSSSSSSSSSUU KDDKKKKKKKKKKFFFFFFFHHHHHHHHHOOOZIIIIIIIIIIIIMMEERRRRRRRRRMRRRRRRKKKKNNNNNNNNNNMGQQQQQQZMZZZZZTTTTLILLLYQYYYYYYYYNNNNNNNNNNNNNNNSSSSSSSSSSUU KKKKKKKKKKCCFFFFFFFFHHHHHHHHHOOOZZIIIIIIIIIIMMMEERRRRRRRRRKKKKKKKKKKNNNNNNNNNCMMGGQQQQQZZZZZZZTTTLLLLLLYYYYYYYYYYYNNNNNNNNNNSNSSSSSSSSSSSUUU NNKKKCCKKKCCFFFFFFOOHHHHHHHHHOOOZZZIZZXIIIIMMMMMMRRRRRRRRRKJKKKKKKKKKNNNCUNNNNNGGQQQQQZZZZZZZZZTTLLLLLLJYYYYYYYYYYNNNNNNNNNSSSSSSSSSHSSSSUUU NNNKKCCCKKCFFFFFFFFFHHHHHHHHHOOOZZZZZZZCIICMMMMMMMMMMMMMJJJJJKKKKKKKKKKKCCCNNNNNQQQQQZZZZZZZZZTTTTLLLLLLLHHHYYYYYYYYYNNNNNNNNSSSSSSSSSUUUUUU NNNCCCCCKCCCFFFFFFFFHHHHHHHHHOZZZZZZZZZCCCCMMMMMMMMMMMJJJJJJJJKKKKKKKKKKKCCCCNNCCCQCZZZZZZZZZZZZTTTLLLUHHHHHYYYYYYYYYNNNNNNNPPPSSSSSSSUUUUUU NNEECCCCCCCCSFFFFFFFHHHHHHHHHOZZZZZZZWZCCCMMMMMMMMMMMJJJJJJJJJJJKKKKKKKKYCCCCCCCCCQCZZZZZZZZZZZZZTTTUUUUHHHHYYYYYYYYYNNUNNNNNGGGSGSSSSUUUUUU NNEECCCCCCCCFFFFFGFFGVVOZZZZZZZZZZZZZZCCCCCMMMMMMMMMMMJJJJJJJJJJKKKKKKKKKATTTTCCCCQCCZZZZZZZZZZZZTKKUHUUHHHHHYYYYYYYYNNDZNNGGGGGQGGGGGGUUUUU NNCCCCCCCCCPCFFFFGGFGVGZZZZZZZZZZZVZZZZZCCCMMMMMMMMMJJJJJJJJJJJJKKKKKKKKKATTTCCCCCCCCZZZZZZZZZZZTTKKUHHHHHHHHHYYYYYYYYYDZZZGGGGGGGGGGGGUUUUU NCCCCCCCCCCCCFFFFGGFGGGZZZZZZZZVVVVVZZVCCCCCMYYYYYYYJJJJJJJJJJJDKKKKKKKKKTTTTTTCTTCCCCCZZZZZZZZZZTKKKKHHHHHHHHHHHYPYYYDDZGGGGGGGGGGGGGGGUUUU NCCCCCCCCCCCGGFFGGGFGGZZZZPPZVVVVVVVVCVCCCCCCYYYYYYYGJJJJJJJJJJDKKKKKKKKKTTTTTRTTTCCCCCZCZZZZZZZZZKKKKKHHHHHHHHPPPPPYDUDDGGGGGGGGGGGGGGGUUUU NNNCCCCCCCCCGGGGGGGGGGGZZZPPPVVVVVVVVVVVCCCHCCCYYYYYJJJJJJJJJJJJKKKKKKKKGTTTTTTTTCCCCCCCCZZZZZZZKKKKKKKHHHHHHHHHPPDDDDDDTGGGGGGGGGGGGRRGUUUU NNNNCCCCCCCGGGGGGGGGGGGZZPPPPSVVVVVVVVVVHHHHCCCYYYYYJJJJJJJJJJJJJKKKDDKKGTTTTTTTTTTTTCCKKUZZZZZZKKKKKKKHHHHHLHHHPPPDDDDTTGGGGGGGGGGGGRRRUUUU NNNNNCCCGGGGGGGGGGGGGGGGGPPPPSVVVVVVVVVXHHHHCCCYYYYYADDDJJJJJJJJJJKKDDDTTTTTTTTTTTTTTTTTKKKKKKKKKKKKKKKDDELLHHHHPPPPPDTTTTGGGGGGGGGGGRRRRUUU NNNNNNCCGGGGGTTTGGGGGGGGPPPPPSVVVVVVVVVYYYYYYYYYCYEEAAADJJJJJJJZJJJKKKDTTTTTTTTTTTTTTTTKKKKKKKKKKKKKEEKDEEELLHPPPPPNPDTTTTGGTGGRRGGGRRRRUURR NNNNNNCCCTTTTTTTTTGGPPPGGPPGGGVVVVVVVVHYYYYYYYYYCCAAAAAAJJJJJJJTTTJKKKTTTTTTTTTTTTTTTTTWKKKKKKKKKKEEEEEEEECELLPPPNNNNNNTTTTTTTGRRRRRRRRRRRRR NNNNNNNNCTTTTTTTTGGPPPGGPPPGGVVVVVVVHHHYYYYYYYYYAAAAAAAQQQJJJJJTTTKKKKTTTTTTTTTTTTTTTTTTKKKKKKKKKKKEMEEEEEEEEPPPNNNNNNTTTTTTTGGRRRROORRRRRRR NNNNNNNNNTTTTTTTTPPPPPPPPPGGGGVVVHHYYYYYYYYYYYYYAAAAAAAQQQJJJRJTTTTTTTTTTTTTTTTTTTTTTTKKKKKKKKKKKKKKKQEEEEEEEEFFNHNNNNNNNTTTTTOROOOOOOORRRRR NNNNNNNNGITTTTTTPPPPPPPPPPGGGGGHHHHYYYYYYYYYYYYYAAAAAEAAQQQQQQTTTTTTTTTTTTTTTTTTTTTFTTKKKFKKFKLKKKKKKQEQQEEKKFFNNNNNNNNNNNNTTOOROOOOOGGORRRR NNNNNNNGGTTTTTIPPPPFFFPPFGGGGGGGYYYYYYYYYYHHHAAAAAAAAAAAQQQQQQQTTTTTTTTTTJJJJJJJJTTFFFFFFFFFFKKKWNNQQQQQQGKKFFFNNNNNNNNNNNNTTOOOOOOOOOGORRRR NNNNNNNGGGGGGGIIFPFFFFFFFGGGGGGGYYYYYYYYYYHHLAAAAAAAAAALQQQQQQQTTTTTTTTTTJJJJJJJJGTFFFFFFFFFFFFKNNNNQQQQQGGKKFNNNNNNNNNNONNTOOOOOOOOOOOOORRR NNNNGNGGGGGGGGIIFFFFFFFFFGGGGGGGYYYYYYYYYYHHAAAAAAALLLLLLYQQQQQTTJJJJJJJJJJJJJJJJGFFFFFFFFFFFFFFNNNNNNQGGGGGGGQGNNNNNNNNNNHHHOOOOOOOOOOOORRR NNGGGGGGGGGGGGGIIFFFFFFFFFGGGGGGYYYYYYYYYYGHANAAAAHLLLLLLYQQQQQJJJJJJJJJJJJJJJJJJFFFFFFFFFFFFFFFRNNNNQQQQQQQQQQGNNNNNNNNNHHHHOOOOOOOOOOORRII NNNGGGGGGGGGGGGGIFFFFFFFFFCGGGGGYYYYYYYYYHHHANANNAALLLLLLYYQQQQJJJJJJJJJJJJJJJJJJFFFFFFFFFFFFFFFNNNNNQQQQQQQQQQGVNNNNNNNNHHHHOOOOOOOOOIIRRII NNGGGGGGGGGGGGQQFFFFFFFFFFGGGGGPPGGHHLTTEHHNNNNNNCALLLLAAYYQAQWJJJJJJJJJJJJJJJJJJWFFFFFFFFFFFFFFFNNNNQQQQQQQQQQGGIINDNNNNNPPPPOOOOOOOOIIIIII NNGGGGGGGGGGGGQQKKFFFFFFFFFUGPPPPGGHITTTTTTNNNNNNNKLLLLLAYYYQQWJJJJJJJJJJJJJJJJJJWFFFFFFFFFFFFFFRFFNNQQQQQQQQQQGGIIINNNNNNPPPPFOOOOOOOIIIIII NNNGGGGGGGGGGQQKIKFFFFFFFFPPPPPPPPPPIJJJJJNNNNNNNWLLLLLAJJJJJJJJJJJJJJJJJJJJJJJJJWWFZFFFFFFFFFFFFFRRRQQQQQQQQQQQIIIINNNNPPPPPFFOOOOOOOIIIIII NNNGGGGGGGGGGGKKKKFFFFFFFFFPPPPPPPPPIJJJTTNNNNNNLLLLLLAAJJJJJJJJJJJJJJJJJJJJJJJJJWWPPPPFFPFFFFFFFRRRRQQQQQQQQQQQIIIINNNPPPPPPPAOOOOODIIIIIII NNGGGGGGGGGGGGKKKKKKFFFFFFFPPPPPPPPPPJJJTTTNNNNAAAAAAAAAJJJJJJJJJJJJJJJJJJJJJJJJJWWPPPPPPPFFFFRFFRRRRQQQQQQQQQQQYIYIINNNPPPPPPAOOOOODIIIIIII GGGGGGGIGXGKKGKKKKKFFFFFFFUUUUPPPPPPJJJJJJJNNNAAAAAAAAAAJJJJJJJJJJJJJJJJJJJWWWQWWWWPPPPPPKKFFNRRRRRRRQQQQQQQQQQQYYYYYYPPPPPPPPAAAAAIIIIIIIII XGGGGGGGGXXKKKKKKKKFFFFFUUUUUPPPPPPPJJJJJJJNNOAAAAAAAAAAJJJJJJJJJJJJJJJJJJJWWWQWWWPPPPPPPKKVVVRRRRRRRRMMMRYYYRYYYYYYYPPPPPPPPAAAAAAIIIIIIIII XGXXXXXXXXKKKKKKKKKBBFBBPPPPPPPPPJJJJJJJJJIOOOAAAAAAAAAAJJJJJJJJGVJJJJJJJWEEEQQWWPPPPPPPPPPVVVVVVRRRRMMMMRRYYYYYYYYYYYYPPPPPPAAAAAAIIIIIIIII XXXXXXXXXXKKKKKKKKBBBBBBBBBBBBCJJJJJJJJJJJOOOOOOOAAAAAAAJJJJJJJJGVJJEEEEEEEEEQQWWWPPPPPPFPVVVVVVVQVVRRMMRRRRYYYYYYYYYYYTPPPPAAAAAAAAAIIIIIII XXXXXXPXKKKKKKKKKKKBBBBBBBBBCBCJJJJJJJJOOOWWOOOOOAAAAAAGJJJJJJJJGJJJEEEEEEEEEEEEEEPPPPPVVVVVVVVVQQVVRRMRRRRRRRYYYYYYYYYYAAAAAAAAAAAAAIIIIIII XXSXPPPPPKKKKKKKKBBBBBBBBBBBCBCJJJJJJJJOOOOWOOOOOOOAAGAGJJJJJJJJGJJLEEEEEEEEEEEEEEPPPPPVVVVVVVVVVVVVRRRRRRRRRRYYYYYYYYWWAAAAAAAAAAAAAAIIIEIE XXSXPPPPPPKKPPPKBBBBBBBBBBCBCCCJJJJJJJOOOOOOOOOOOOLLLGGGGGGGGGGGGGJLLJFFFJQEEEEEEEPPPPPPVVVVVVVVVVVVVVRRRKRRRYYYYYYYYYWWAAAAAAAAAAAAIIIIEEEE XXSSPPPPPPPKPPPPPBBBBBBCCCCCCCCCJJJJJJJOOOOOOOOOOOILLLGWWGGGGGGGGGZMMMMMMZQEEEEEEEPPPPPTTVVVVVVVVVVWKKKKKKKKRRQQQQYYYYYWWWAAAAAAAAAAAAAAAAEE XXSMPPPPPPPPPPPPBBBBBBBCCCCCCCCCCJJJDJDDOOOOOOOOOOLLLLOLLLGGGGGGGGMMMMMCCMFEEEEEEETPPPPTXXXVVVVVVVVVKKKKKKKKRRRQQQQQYYYYWWIAAAAAAAAAAAAAAEEE XXSSSSSPPPPPPPPPPBBBCCCCCCCCCCCCCJDJDOODDOOOOOOOOLLLLLLLLLGGGGGGGGGMMTMMEEEEEEEEEETTPTTTTVVVVVVVVVVVKKKKKKKKRRQQQQQYYWYWWWIIAAAAAAAAAAAAAAAE XXSSSBSPPPPPPPPPPBBBBCCCCCCCCCCCCCDDDDDDDOOOOOOOOLLLLLLLLLQLGGGGGGGRGTMMEEEEEEEEEETTTTTTVVVVVVVVVVVVKKKKKKKKRRQQQQQQQWWWWWIIAIAAAAAAAAAAAAGO XXSSXPPPPPPPPPPPPWWWWCCNCUCCCCCCCZDDDDDDDOOOOOOOOQLLLLLLLLLLGGLGGGGGGTMMEEEEEEEEEETTTTTTVVVVVTTHVVVVKKKKKKKKKRQQQQQQWWWWWIIIIIIAAAAAAAAAOOOO XXXXXXXPPPPPPPPPPWWWWCINCCCCCCCCCDDDDDDDDOOOOOOWOORLLLLLLLLLLLLGMGMMNMMMEEEEEEEEEETTTTTTVVVTTTTTKKKKKKKKKKKKKKQQQQQQWWIIIIIIIIIAAAAAAAAAAOOO XXXXXXXPPPPPTTPPPWWWWWWNNNNBBBBBBDDDDDDDDOOOOOOWOOLKLLLLLLLLLLLQMMMMNMMMEEEEEEEEEETTTTTTTTTTTTTKKKKKKKKKKKKKKQQQQQQQWIIIIIIIIIIIIOOOAAAOOOOO JJJXJJXPPPPNTTTWWWWWWWNNNNNBBBBBBUDDDDDDDOOOWWWWWFLLLLLLLLLLLLLLLMMMMMMMEEEEEEEEEETTTTTTTTTTTTTTKKKKKKKKKKKKKQQQQQQQWWWIIIIIIIIIIIQOAAAOOOOO JJJJJJJJPPPNTTTTTWWWNNNNNNNBBBBBBDDDDDDDDOOOWWWWWLLLLLLLLLLLLMLLMMMMMMMMMEEEEEEEEETTTTTTTTTTTTTTTKKKKKKKKKKKKQQTQTQQQIIIIIIIIIIIIIIOKAOOOOOO JJJJJJJNNNNNNTTTTTWWNNNNNNBBBBBBBDDDDDDDDDOWWWWWWBBLLLLLLLLLMMLLMMMMMMMMMEEEEEEQQQTTTTTTTTTTTTTKKKKKKKKKKKKKFQQTTTKXXIIIIIIIIIIOOHHHHKOOOOOO JJJJJJJNNWNNNTTTTNNWNNNNNNBBBBBBBSVDDDDDXXOOOWWWBBBLLLLLLULLMMMMMMMMMMMMWMEEEEBBQQQQQTTKTOTTTTTTKKKKKKKKKKKKKKQQTKKXXXIIIIIIIIIHHHHHHKOOOOOO JJJJJJWWWWWNNTTTTNNWNNNNNNBBBBBBBVVVVVEDXXXXWWWWWWBSSLTTLMLMMMMMMMMMMMMMMBEEEEBBQBBQQQQQOOTTTTTTTKKKKKKKKKKKKKKQKKKKKXXIIIIIIIIHHHHHHOOOOOOO JJJJJDDWWWWNNNTTTNNNNNNNNNBBBBBBBVVVVVVDXXXXWWWWWBBOOOTTMMMMMMMMMMMMMMMMBBEEEEBBBBQQQQQQOOTTTTTTTTKKKKKKKKKKKKKKKKKKKXXXXXIIIIIHHHOOOOOOOOOO JUJJJWWWWWWNNNTTNNNNNNNNNNNBBBBBBVVVVVVDXXXXXWWWWBBBOOMMMMMMMMMMMBBBMBBMBBEEEEBBBQQQQQQQTTTTTTTTTTKKKKKKKKKKKKKKKKKKKXXXXXIIIIIHHHOOOOOOOOOO JUWWWWWWWWWWWNNNNNNNNNNNNNNBBBBBBJVVVVVDXXXXXXXXWOOOOOMMMMMMMMMMMBBBBBBBBBEEEEBBQQQQQPQPTTTTTTTTTKKKKKKKKKKKKKKKKKKKKXPPPPIIIIPHHHOOOOOOOOOO UUUWWWWWWWWWWWWWWWNNNNGGNNGBBBBBBJVVVJXXXXXXXXOOOOOOOOGGMMMMMMMBBBBBBBBBBBEEEEBMQTTPPPQPPTTTTTTTTTKVVVVVVVVVVVVVKKKKKPPPPPZZIPPHHHOOOOOOOOOO UUUWWWWWWWWWWWWWWWNNNGGGGGGGGBBBBJJJJJJXXXXXXOOOOOOOOOOGMVMMMMMBBBBBBBBBBBEEEEBBBTTTTPPPTTTTTTTTTTKVVVVVVVVVVVVVKKKKKNPPPPPPEEEHHHOOOOOOOOMO UUUWWWWWWWWWWWWWWNNNNGGGGGGGGBBBBJJJJJJJXXXXXOEOOOOOOOOOOMMMMMMMCCCCBBBBBBBBBBBAAATTTTTPTTTTTTTTTKKVVVVVVVVVVVVVKKKPCPPPPPPPPEEHHHOOOOOOOOMM UUUWWWWWWWWWWWXXNNNNGGGGGGGGGBBBBJJJJJJXXXXXXOOOOOOOOOOOMMMMMMCCCICCBBBBBBBBBBBTTTSSSSSSSSSZTTTTTUUVVVVVVVVVVVVVKPPPPPPPPPPPNNEHHHFFOFOOOMMM UUUWWWWWWWWWWWXNNNNGGGGGGGGGGJJJJJJJJJJJXXXXXXXOOOOOOOOOMFMMIIIICIIIIBBBBBBBYBLTTTSSSSSSSSSTTUTXUUUVVVVVVVVVVVVVKPPPPPPPPPPNNNNNPPFFFFFOMMMM UUUUWWWWWWWWWWXNNNNNGGGGGGGGGJJJJJJJJXXXXXXXXXZQOOOOOOVOFFFMIIIIIIIIIIBBBBBBBBTTTTSSSSSSSSSUUUTUUUUVVVVVVVVVVVVVKPPPPPPPPPPPNNNNNNFFFFFQMMMM UUUWWWWWWWWWWXXXXXGGGGGGGGGGGGGJJJJJJJJXXXXXXXZZOOOOOOOIIIMMIIIIIIIIIIBBBBBBWBTTTTSSSSSSSSSUUVVVVVVVVVVVVVVVVVVVKPPPPPPPPPPPNNNNNFFFFFQQQMMM UUUUWWWWWWWZWWXNXXXXGGGGGGGGGGJJJJJJJJXXXXXXZZZZDDDOOOOIIIIIIIIIIIIIIIBGFFBBWTTTTTSSSSSSSSSUUVVVVVVVVVVVVVVVVAAKKPPPPPPPPPPNNNNNNNNQQQQQQMMM UUWWWWWWWUUWWNNNNXXXGGGGGGGGJJJJJJJJJJJXXZZZZZZZZDDZOOHBIIIIIIIIIIIIIGGGGBBBWTTTTTSSSSSSSSSUUVVVVVVVVVVVVVVVVAAKKPPPPPPPPPPNNNNNNNNNQQQQQMQQ UUWWWUUWUUNNWNNNNXXGGGGGGGGGJJJJJJJJJJXXXXZZZZZZZZZZKKHIIIIIIIIIIIIIIGGGGGBBWTTTTTSSSSSSSSSUUVVVVVVVVVVVVVVVVAAAKKKPPPPPPPPPPPNNNNSSSQQQQQQQ UUWWUUUUUNNNNNNNRRXXGFGGGGGJJJJJJJJJJJJXXXZZZZZZZZZKKKHHIIIIIPIIIIIIWGGGGGGBBTTTTLSSSSSSSSSSUVVVVVVVVUUUUVAAAAAAAKKPPPPPPPPPPPNNNSSSSQQQQQQK UUUWUNNNNNNNNNNRRBRRGFGGGGGJFJJJJJJJJJJXXXZHHZZZKZZKKKHHIIIIPPPPIIIIIGGGGGGGGTTTLLSSSSSSSSSSAVVVVVVVVUUUUVAAAAAKKKKPPBBBBPPPPPSNSSSQQQQQQQQK UUUUUNNNNNNNNNNRRRRRFFGGGGGJFFFJJJJJJJJJXOHHZZZKKKKKHHHHHIIIPPPPIGGGGGGGGGGGGGTTTLLAAAAASSSSAAAUUUUUUUUUUUAAAAAAAKKKBBBBBBPPPSSSSSSSSSQKQQQK UUUUUUUNNNNNNNNNRRRRFFGGFFGFFFFFFJJJJJOOOOHOCZKKKKKHHHHHHIIIPPPPPGGGGGGGGGGGGGTTTTAAAAAASSSSAAAUUUUUUUUUAAAAAAAAAKKKBBBBBBBBBSBSSSSSSDDKKQQK UUUUUUUUNNNNNNNRRRRRFFGFFFFFFFFFFFJJJJOOOOHOOKKKKKKKHHHHHHHHCCPPGGGGGGGGGGGBBBBBBBAAAAAASSSSAAAUUUUUUUUAAAAAAAAAAABBBBBBBBBBBBBSBSSSSDDDKKKK UUUUUUUUUUNNNNRRRRRFFFGFFFFFFFFFFFJJJOOOOOOOOKKKKKHHHHHHHHHHCHPPPGGGGGGGGGGBBBBBBBAAAAAAAAAAAAAAUUUUJJUAAAAAAAAAAFFBBBBBBBBBBBBBBBDDDDDKKDDK UUUUUUUUUUNNNRRRRRRRRFFFFFFFFFFKJJJJJJOOOOOOOOKKZZHHHHHHHHHHHHYPZGGGGGGGGGGBBBBBBBAAAAAAAAAAAAAUUUUUUUUAAAAAAAAAAABBBBBBBBBBBBWBBBWDDDDKKDDK UUUUUUUUUUNBNRRRRRRRRRFRFFFFKKKKKKKOOOOOOOOOOKKKZZHHHHHHHHHHHHYZZYGGGYYGGYGGGGGGAAAAAAAAAAAAQQQUUUUUZAAAAAAAAAAABBBBBBBBBBBBYSWWWBWDDDDKDDKK UUUUUUUUUUNBNURRRRRRRRRRKFKKVKKKKKYYOOOOOOOOOOZZZZZZHHHHHHHHHHYYYYYYYYYYYYGGGGGGGAAAAAAAAAQQQQQQQQULZAAAAAAAAAAAABBBBBBBBBBBYSSSWWWWWDDDDDKK DDDDUUUUUUNBBBRRRRRRRRRPKKKKKKKKKKYKOOOOOOOOZZZZZZZZZHHZHHHHHHYYXXXYYYYYYYYGGGGGGAAAAAAAAQQQQQQQQQUUZAAAAAAAAAAAABBBBBBBBBBBYYSSSWWWDDDDDDPP DDDDDDDUUUBBBBRRRRRRRRKKKKKKKKKKKKKKVOOOOOOOOZZZZZZZZHZZHHHHHYGYXYYYYYYYYWWWWCJCAAAQQQAAQQQQQQQQQUUZZZZZAAAAAAAAABBBBBBBBBBYYSSSSSWZDDDPDDPP DDDDDDDDDBBBBBBRRRRRHKKKKKKKKKKKKKKKOOOOOOOOOOZZZZZZZZZZZHHQQYYYYYYYYYYYYYYWCCCCCAAQQWQQQQQQQQQQQZZZZZZZAAAAAAAAHBALLOBBRBBBSSSSZZZZDDDPPPPP DDDDDDDDDDBBBBBLLNRRNNNKKKKKKKKKKKKKOOOOOOOOOOZZZZZZZZZZZZZQQQQQQYYYYYYYYYYYCCCCCMQQQQQQQQQQQQQQQZZZZZZZZZZZAAAAAAAALOORRBRRSSSSZZZZZDDDPPPP DDDDDDDDDDDBUBBLLNRRNNNKKKKKKKKKKKKKOOOOOOOOOOOZZZZZZZZZZZQQQQQQYYYYYYYYYYYYCCCCCCQQQQQQQQQQQQQQQQQZZZZZZZZZZAAAAOOOOOORRRRRSSSZZZZZZZDPPPPP DDDDDDDDDDDFBBQLNNNNNNKKKKKKKKKKKKKFFFOOOOOOOZZZZZZZZZZZZZZQQQQYYYYYYYYYYYYYNYCCCCQJQQQQQQQQQQQQQPZZZZZZZZAZZJAOOOOOOOOZZRRRRSSZZZZZZZZZPPPP DDDDDDDDDDDDNLLLNNNNVVKKKKKKKKKKKFFFFAOOOOOOOOZZZZZZZZZZZQQQQQQYYYYYYYYYYYYYYYCCCCCJQQQQQQQQQQQQQQSZZZZEZEAOOOOOOOOOOOARRRRSSSZZZZZZZZZPPPPP DDDDDDDDDDDNNNLNNNNNNNKKKKKKKKKKFFFFFOOOOOOOOOZZZZZZZZZZZZZQQQQQYYYYYYYYYYYLYCCCCCPJQQQQQQQQQQQQQJZZEEEEEEAAOOOOOOOOOOOREEESSHHZZZZZZZPPPPPP DDDDDDDDDDDNNNNNNNNNNNNKKKKKKKKKKFFFFFFFFOOOOOZZZZZZZZZZUUZQQQQYYJYYJJLYYLLLCCCCCCPPQQQQQQQQQQQQQJJTTREEEEAAAOOOOOOOOOOOEEESSHHZZZZZZZPPPPPP DDDDDDDDDDNNNNNNNNNNNNOKKKKKKKKKFFFFFFFFDOOOOOOOHZZZZZZZUUQQQQUYYJJJJJLLLLLLLLLCPPPPPPPQQQQQQQQQQTTTTTTEEEEAAAOOOOOOOOOOOEEYSHHHZZZZZZPPPPPP DDDDDDDDDDNNNNNNNNNNNNNKWWKKKKFFFFFFFFFFFFFOOOOOZZZZZZZUUUUUUQUUQJJJJLLLLLLLLCCCCPPPPPPPPQQQQQQQUTTTTTEEEEEAAAAAAOOOOOOOOEEYSXPBZZZZPPPPPPPP DDMDDDDDDDNNNNNNNNNNNNNNWKKKKFFFFFFFFFFFFFFFOOOOZZZZZUUUUUUUUUUUQQQJJLLLLLLLLLCCCCPPPPPPPQQPQPGGGTGTTTEEEEEAAAXAAAOOOOOBOEYYPPPPPPPPPPPPPPPP DWDDDDDDDDNNNNNNNNNNNNNFUUUQQFFFFFFFFFFFFFFFOOFZZZKKKKKKKUUUUUUUQQQQQCLLLLLLCCCCCPPPPPPPPPPPMGGGGGGGTTGJJJJAAAAAAAAAAGOOOEYYYXPPPPPPPPPPPPPP WWDDDDDDDNNNNNNINNNNNNNNUULDQFFFFFFFFFFFFFFFONZZZZKKKKKKKUUUUUUUQQQCQCLCCLCCCCCCCCPPPPPPPPJPMGGGGGGGGGGGGJJJJJAAAAAAAAAZYYYYYYPPPPPPPPEPPPPP WWDDDDDDDNNNINIIINNNNNNNUULDDEFFFFFFFFFFFFFFFFOOOONNNKKKKUUUUUUUQQQCCCCCCCCCCCCCCPPPPPPPPPJPMMMGGGGGGGGGGJJJJAAAAAAAAAYZYYYYYPPPPPPPPPEEPPPP WYYDDDDDUIIIIIIIIINNNNNUUUDDDFFFDFFFFFFFFFFCFOOONNNNKKKUUUUUUUUUQQQCCCCCCCCCCCCCCCPPPPPPPPPPMMMMMMGGGGGGGJJJAAAAAAAAAAYYYYYYYYYPPPPPPEEEPPPP YYYUUDDUUIIIIIIIIINNNNUUUDDDDDDDDFFFFFFFFNNNNMMMMMMMMMKUUUUUUUUQQQQQQCCCCCCCCCCCCPPPPPPPPPPPMMMMMMMGGGGXJJJAAAAAAAAAAAYYYYYYYYYYMMPPEEEEEPPP YYUUUUUUUIIIIIIIIIIUNNUUDDDDDDDDFFFFFFFFNNNNNMMMMMMMMMKKKUUUBUQQQQQQQQCCCCCCCCCCCPPPPPPPPPPPMMMMMMMGGGNXMMJJAMAAAAAAAAAYYYYYYYYYYYPPEIEEEPPP YYYUUUUUUUIIIIIIIIIUUUUUDDDDDDDDFFFFFFFFNNNNNMMMMMMMMMMKKWKUBUUQQQQQQQQCCCCCCHHCCPPPPPPPPMMMMMMMMMMMXXXXMMMMMMAAAAAADAAYYYYYYYYYYYPYEEEEEPPP YYUUUUUUIIIIIIIGUUUUUUUUUUDDFFFFFFFFFFFNNNNNNMMMMMMMMMMKKKKXKKKKQQQQQQQCCCCCHHHCCPPPPPPPNNMMMMMMMMXXXXXXMMMMMMAAAAAAAAYYYYYYYYYYYYYYYYEEEEPP YYYYUUUIIIIIIIIIIIUUUUUUUUUUUFFFFFFFFFNNNNNNNMMMMMMMMMMKKKKKKKQQQQQQQQQCCCHHHHHHHPPNNPNNNNMMMMMMMXXXXXXXXMMMMMMMAAGDDAAYYYYYYYYYYYYYYYEEEEPP UYUYYUUIIIIIIIUUIUUUUUUUUUUUUUUUFFFFFFNNNNTTTMMMMMMMMMMKKKKKKKLQQQQQQQQCCHHHHHHHHNNNNNNNNNMMMMMMMXXXXXXXXMMMMMMMMAMDDDDDDYYYYYYYYYYYYEEEEEEE UYUUUUIIIIIIIIIUUUUUUUUUUUUUUUUUFFFFFFNTTTTTTMMMMMMMMMMKKKKKKKQQQQQGGGQQHHHHHHHHHNNNNNNNNNMMMMMMMXXXXXXXXXMMMMMMMMMDDDDDDDYYYYYYYYYYYEEEEBEA UYUUUUUIIIIIIIIUUUUUUUUUUUIUPIUUFFFFNNNTTTTTTMMMMMMMMMMKKKKKWWQQQQQQQGQQTTHHHHHHHNNNNNNNNMMMMMMMXXXXXXXXXXXMMMMMDDDDDDDDJDYYYYYYYYYYYYEEEEEA UUUUUUUIIIIIIIUUUUUUUUUUUUIIIIFFFFFFFNNTTTTTTTNNNMMMMMMKKKKKKWQQQQQQQQTTTTHHHHHHHHNNNNNNNMRRRMMMMXXXXXXXXXXMMMMMMMDDDDDDDDDDDYYYYYYYYGEEAAEA UUUUPUUIIIIIIIIIUUUUIIIUIIIIIIIFFFFFFNBBNNTTTTNNNMMMMMMKKKKWWWWQQQQQQQQTTHHHHHHHHHHNNNNNNRRRRRMMMMMXXXXXXXMMMMMMMMMDDDDDDDDCYYXYYYYNYGEGGAAA UPPUPUPIIDIIIIIIUUUUIIIIIIIITTIFNNFJJJBBBNTTTTNUUMMMMMKKKKKWWWWQQQQQQQQTTTHHHHHHHHHNNNNNNRRRRRRRSSSSSXXXXXMMMMMMMMMDDDDDDDZNNYXNYYNNNGGGGGGG PPPUPPPPPIIIIUUUUUUIIIIIIIIIITTNNNNJJAEBBNTTTTUUKKKKKKKKKKWWWWQQRQTQQQTTTHHHHHHHHHHNNNNNCRRRRRRRRLSSSXXXOXMMMMMMMMMMDDVVDDZNNNNNNYNNNGGGGGGI PPPPPPPPPPIUUUUUUUUIIIIIIIIINTNNNNREEEENNNNWNUUUUUKKKKKKKKWWWQQRRTTTQQTTTTHHHHHHAAHNNNNNRRRRRRRSSSSSSSXXOOMOOMMMMMMMDDRVVZZZZNNNNNNNRGGGGGGG PPPPPPPPPPPPUUUUUUIIIIIIIIIINTTNNNRRREEEEJNNBUUUUUKKKKKKEERRRRRRRTBTTTTTTTTHHAAHAAHNNNNDRRRRRRRSSSSSSSOOOOOOOOMMMMMMMMVVVZZZNNNNNNNNNNGGGGGG EEPPPPPPPUUUUUUUIIIIIIIIIINNNNNNNNRRREEYYEINBBBUBBKKKKKKEERRRRRRTTTTTTTTTTHHHHAAAAHNNNNDBRRRRRSSSSSSSSSSOOOOOMMMMMMMMVVVVZNNNNNNNNNNNGGGGGGG EGGGGGGPPPUUUUUUUIIIIIIIIINNNNNNNNNRRREEEEIIIBBBBBCKKEEEERRRRRRRTTTJTTTTTTHHTHAAAAANNNDDDDJRRSSSSSSSMMMMOOOOOMMMMMMMVVVVVNNNNNNNNNNNNNGGGGGG EGGGGGGGGPPUUUUUUIIIIIIIINNNNNNNNNNEEEEEEEIIBBBBBBBEEEEEEERRRRTTTTTJTTTTTTTTTHAEAANNNNDSSSSRRSSSSSSSSMGMMMGGMMMMMMMMVVVVVNNNNNNNNNNNNGGGGGGG EGGGGGGGDPPUUUUUUIIIIIIINNNNNNNNNNNNEEEEEEBBBBBBBBBEEEEEEEEERTTTTTTTTTTTTTTTTEEEEEEUUUUUSSSRSSSSSSSSSGGGGGGGMMMMMVVVVVVVVNNNNNNNNNNNNGGGGGGG EGGGGGGGGPPUUUUUUIIIIIIINNNNNNNNNNNNNEEEEGGBBBBBBBBBBEEEEEEEETTTTTTTTTTTTTTTTTEEEEEEUUUUSSSSSSSSSSSGGGGGGGGGGMMMMVVMMVVVMMNNNNNNNNNNNNNGGGGG EEGGGGGGGGPUOUUUUFFIIIINNNNNNNNNNNNNEEEEEEBBBBBBBBBBBBBBEEEEETTTTTTTTTTTTTTTTTTEEEEUUUUFFSSSSKKSSSGGGGGGGGGGMMMMMMMMMVVVMMNNNNNNNNNNNNNGGGGG GGGGGGGGGGGGOUUUFFFIIIIINNNNNNNNNNNNEEEEEBBBBBBBBBBBBBBBEEEEEEEETTTTTTTTTTTTTTTTEUUUUUUFFSSKKKKSSSSGGGGGGGGGGMMMMMMMMVVVMMMNNNNNNNNNGGGGGGGG GGGGGGGGGGOGOOUOOFIIIIFFNNNNNNNNNNNEEEEEEEEEBBBBBBBBBBBBEEEEEEEETTTTTTTTTTTTTTTTEUUUUUUFFFKKKKKKSSSSSGGGGGGGGGMMMMMMMMMMMMNNNNNNNNNNSGGGGFGG VGGGGGGGGGOOOOOOOFFFFFFFNNNNNNNNNNNNNEEEEEEEEBBBBBBBBBBBEEEEEEEEEETTTTTTTTTTTTTEEEUUUUUFXXKKKKKKKSSSSGGGNGGGJGMMMMMMMMMMMMNNNNNNNJNNSSGFFFGG ================================================ FILE: exm/aoc/2024/aoc_2024_12_questions.txt ================================================ --- Day 12: Garden Groups --- Why not search for the Chief Historian near the gardener and his massive farm? There's plenty of food, so The Historians grab something to eat while they search. You're about to settle near a complex arrangement of garden plots when some Elves ask if you can lend a hand. They'd like to set up fences around each region of garden plots, but they can't figure out how much fence they need to order or how much it will cost. They hand you a map (your puzzle input) of the garden plots. Each garden plot grows only a single type of plant and is indicated by a single letter on your map. When multiple garden plots are growing the same type of plant and are touching (horizontally or vertically), they form a region. For example: AAAA BBCD BBCC EEEC This 4x4 arrangement includes garden plots growing five different types of plants (labeled A, B, C, D, and E), each grouped into their own region. In order to accurately calculate the cost of the fence around a single region, you need to know that region's area and perimeter. The area of a region is simply the number of garden plots the region contains. The above map's type A, B, and C plants are each in a region of area 4. The type E plants are in a region of area 3; the type D plants are in a region of area 1. Each garden plot is a square and so has four sides. The perimeter of a region is the number of sides of garden plots in the region that do not touch another garden plot in the same region. The type A and C plants are each in a region with perimeter 10. The type B and E plants are each in a region with perimeter 8. The lone D plot forms its own region with perimeter 4. Visually indicating the sides of plots in each region that contribute to the perimeter using - and |, the above map's regions' perimeters are measured as follows: +-+-+-+-+ |A A A A| +-+-+-+-+ +-+ |D| +-+-+ +-+ +-+ |B B| |C| + + + +-+ |B B| |C C| +-+-+ +-+ + |C| +-+-+-+ +-+ |E E E| +-+-+-+ Plants of the same type can appear in multiple separate regions, and regions can even appear within other regions. For example: OOOOO OXOXO OOOOO OXOXO OOOOO The above map contains five regions, one containing all of the O garden plots, and the other four each containing a single X plot. The four X regions each have area 1 and perimeter 4. The region containing 21 type O plants is more complicated; in addition to its outer edge contributing a perimeter of 20, its boundary with each X region contributes an additional 4 to its perimeter, for a total perimeter of 36. Due to "modern" business practices, the price of fence required for a region is found by multiplying that region's area by its perimeter. The total price of fencing all regions on a map is found by adding together the price of fence for every region on the map. In the first example, region A has price 4 * 10 = 40, region B has price 4 * 8 = 32, region C has price 4 * 10 = 40, region D has price 1 * 4 = 4, and region E has price 3 * 8 = 24. So, the total price for the first example is 140. In the second example, the region with all of the O plants has price 21 * 36 = 756, and each of the four smaller X regions has price 1 * 4 = 4, for a total price of 772 (756 + 4 + 4 + 4 + 4). Here's a larger example: RRRRIICCFF RRRRIICCCF VVRRRCCFFF VVRCCCJFFF VVVVCJJCFE VVIVCCJJEE VVIIICJJEE MIIIIIJJEE MIIISIJEEE MMMISSJEEE It contains: A region of R plants with price 12 * 18 = 216. A region of I plants with price 4 * 8 = 32. A region of C plants with price 14 * 28 = 392. A region of F plants with price 10 * 18 = 180. A region of V plants with price 13 * 20 = 260. A region of J plants with price 11 * 20 = 220. A region of C plants with price 1 * 4 = 4. A region of E plants with price 13 * 18 = 234. A region of I plants with price 14 * 22 = 308. A region of M plants with price 5 * 12 = 60. A region of S plants with price 3 * 8 = 24. So, it has a total price of 1930. What is the total price of fencing all regions on your map? --- Part Two --- Fortunately, the Elves are trying to order so much fence that they qualify for a bulk discount! Under the bulk discount, instead of using the perimeter to calculate the price, you need to use the number of sides each region has. Each straight section of fence counts as a side, regardless of how long it is. Consider this example again: AAAA BBCD BBCC EEEC The region containing type A plants has 4 sides, as does each of the regions containing plants of type B, D, and E. However, the more complex region containing the plants of type C has 8 sides! Using the new method of calculating the per-region price by multiplying the region's area by its number of sides, regions A through E have prices 16, 16, 32, 4, and 12, respectively, for a total price of 80. The second example above (full of type X and O plants) would have a total price of 436. Here's a map that includes an E-shaped region full of type E plants: EEEEE EXXXX EEEEE EXXXX EEEEE The E-shaped region has an area of 17 and 12 sides for a price of 204. Including the two regions full of type X plants, this map has a total price of 236. This map has a total price of 368: AAAAAA AAABBA AAABBA ABBAAA ABBAAA AAAAAA It includes two regions full of type B plants (each with 4 sides) and a single region full of type A plants (with 4 sides on the outside and 8 more sides on the inside, a total of 12 sides). Be especially careful when counting the fence around regions like the one full of type A plants; in particular, each section of fence has an in-side and an out-side, so the fence does not connect across the middle of the region (where the two B regions touch diagonally). (The Elves would have used the Möbius Fencing Company instead, but their contract terms were too one-sided.) The larger example from before now has the following updated prices: A region of R plants with price 12 * 10 = 120. A region of I plants with price 4 * 4 = 16. A region of C plants with price 14 * 22 = 308. A region of F plants with price 10 * 12 = 120. A region of V plants with price 13 * 10 = 130. A region of J plants with price 11 * 12 = 132. A region of C plants with price 1 * 4 = 4. A region of E plants with price 13 * 8 = 104. A region of I plants with price 14 * 16 = 224. A region of M plants with price 5 * 6 = 30. A region of S plants with price 3 * 6 = 18. Adding these together produces its new total price of 1206. What is the new total price of fencing all regions on your map? ================================================ FILE: exm/aoc/2024/aoc_2024_13.adb ================================================ -- Solution to Advent of Code 2024, Day 13 ------------------------------------------- -- Claw Contraption -- -- https://adventofcode.com/2024/day/13 -- Copy of questions in: aoc_2024_13_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_13 is use AoC_Toolbox, HAT, Interfaces; subtype I64 is Integer_64; -- The wording is misleading (on purpose of course!), -- with portions such as "...the cheapest way to win the prize..." -- or "...the minimum tokens you would have to spend..." -- Actually there is at most *one* solution in the real plane (\IR^2), -- thus also at most one solution in the square lattice (\ZZ^2). -- So, if there is a solution, we already have the lowest cost. -- function Cost (ax, ay, bx, by, px, py : I64) return I64 is det : constant I64 := ax * by - bx * ay; a_times_det, b_times_det, a, b : I64; begin -- / \ / \ / \ -- | px | | ax bx | | a | -- | | = | | * | | -- | py | | ay by | | b | -- \ / \ / \ / -- / \ / \-1 / \ -- | a | | ax bx | | px | -- | | = | | * | | -- | b | | ay by | | py | -- \ / \ / \ / -- / \-1 / \ -- | ax bx | | +by -bx | -- where: | | = | | / (ax by - bx ay) -- | ay by | | -ay +ax | -- \ / \ / if px = 0 and py = 0 then -- Case not seen on our input data. Put_Line ("px = 0, py = 0 ------> solution: a = 0, b = 0"); return 0; end if; if det = 0 then -- Case not seen on our input data: a row is a multiple of the other. -- -> Zero or an infinity of solutions in \IR^2. -- -> Zero or a smaller infinity of solutions in \ZZ^2. -- We would have to look for the pair -- of natural integers with the smallest cost... Put_Line ("Determinant 0"); return 0; end if; a_times_det := by * px - bx * py; b_times_det := ax * py - ay * px; if a_times_det rem det /= 0 or else b_times_det rem det /= 0 then -- There are remainders -> non integer solution -- (solution is in the plane \IR^2 but not in the square lattice \ZZ^2). return 0; end if; a := a_times_det / det; b := b_times_det / det; if a < 0 or b < 0 then -- Case not seen on our input data. Put_Line ("Negative number of button presses"); return 0; end if; if a = 0 or b = 0 then -- Case not seen on our input data. Put_Line ("Solution with 1 or 2 buttons pressed 0 times"); end if; return a * 3 + b; end Cost; r : array (Part_Type) of I64; procedure Read_Data_and_Solve is butax, butbx : String (1 .. 12) := "Button A: X+"; butay, butby : String (1 .. 4) := ", Y+"; prix : String (1 .. 9) := "Prize: X="; priy : String (1 .. 4) := ", Y="; ax, ay, bx, by, px, py : Integer; f : File_Type; big : constant := 10_000_000_000_000; begin Open (f, "aoc_2024_13.txt"); while not End_Of_File (f) loop Get (f, butax); Get (f, ax); Get (f, butay); Get (f, ay); Get (f, butbx); Get (f, bx); Get (f, butby); Get (f, by); Get (f, prix); Get (f, px); Get (f, priy); Get (f, py); r (part_1) := r (part_1) + Cost (I64 (ax), I64 (ay), I64 (bx), I64 (by), I64 (px), I64 (py)); r (part_2) := r (part_2) + Cost (I64 (ax), I64 (ay), I64 (bx), I64 (by), I64 (px) + big, I64 (py) + big); end loop; Close (f); end Read_Data_and_Solve; compiler_test_mode : constant Boolean := Argument_Count >= 2; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data_and_Solve; if compiler_test_mode then if +r (part_1)'Image /= +' ' & Argument (1) or +r (part_2)'Image /= +' ' & Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 36954 -- Part 2: validated by AoC: 79352015273424 end if; end AoC_2024_13; ================================================ FILE: exm/aoc/2024/aoc_2024_13.txt ================================================ Button A: X+92, Y+24 Button B: X+13, Y+94 Prize: X=8901, Y=8574 Button A: X+52, Y+13 Button B: X+27, Y+72 Prize: X=18587, Y=299 Button A: X+45, Y+21 Button B: X+34, Y+56 Prize: X=12602, Y=14690 Button A: X+78, Y+53 Button B: X+14, Y+35 Prize: X=2228, Y=2432 Button A: X+77, Y+16 Button B: X+13, Y+79 Prize: X=16314, Y=19562 Button A: X+27, Y+72 Button B: X+57, Y+11 Prize: X=16094, Y=14389 Button A: X+43, Y+77 Button B: X+51, Y+13 Prize: X=15606, Y=16498 Button A: X+79, Y+45 Button B: X+41, Y+99 Prize: X=5535, Y=7389 Button A: X+14, Y+69 Button B: X+83, Y+25 Prize: X=15390, Y=13803 Button A: X+18, Y+38 Button B: X+60, Y+30 Prize: X=16586, Y=1146 Button A: X+32, Y+65 Button B: X+40, Y+16 Prize: X=19544, Y=14414 Button A: X+67, Y+15 Button B: X+28, Y+79 Prize: X=9428, Y=13828 Button A: X+51, Y+20 Button B: X+12, Y+35 Prize: X=8252, Y=19415 Button A: X+76, Y+52 Button B: X+12, Y+37 Prize: X=19492, Y=11639 Button A: X+74, Y+11 Button B: X+84, Y+80 Prize: X=6934, Y=2381 Button A: X+20, Y+59 Button B: X+42, Y+36 Prize: X=2816, Y=5846 Button A: X+13, Y+39 Button B: X+67, Y+38 Prize: X=16077, Y=14664 Button A: X+15, Y+61 Button B: X+56, Y+23 Prize: X=9909, Y=18887 Button A: X+71, Y+99 Button B: X+90, Y+15 Prize: X=3897, Y=3003 Button A: X+23, Y+49 Button B: X+35, Y+15 Prize: X=783, Y=12319 Button A: X+40, Y+74 Button B: X+73, Y+43 Prize: X=3809, Y=4009 Button A: X+55, Y+18 Button B: X+11, Y+61 Prize: X=1265, Y=1562 Button A: X+80, Y+86 Button B: X+15, Y+94 Prize: X=8075, Y=11562 Button A: X+80, Y+26 Button B: X+15, Y+69 Prize: X=8175, Y=1263 Button A: X+14, Y+55 Button B: X+56, Y+18 Prize: X=16958, Y=1101 Button A: X+20, Y+75 Button B: X+73, Y+12 Prize: X=1703, Y=8597 Button A: X+32, Y+84 Button B: X+89, Y+42 Prize: X=4212, Y=7224 Button A: X+50, Y+64 Button B: X+69, Y+14 Prize: X=8066, Y=5568 Button A: X+22, Y+80 Button B: X+52, Y+21 Prize: X=4102, Y=6848 Button A: X+96, Y+40 Button B: X+34, Y+88 Prize: X=6838, Y=6024 Button A: X+74, Y+21 Button B: X+59, Y+77 Prize: X=11659, Y=8792 Button A: X+17, Y+61 Button B: X+59, Y+12 Prize: X=2971, Y=2273 Button A: X+71, Y+37 Button B: X+14, Y+46 Prize: X=7100, Y=19268 Button A: X+59, Y+82 Button B: X+73, Y+27 Prize: X=2427, Y=2703 Button A: X+92, Y+65 Button B: X+25, Y+83 Prize: X=8252, Y=7921 Button A: X+97, Y+49 Button B: X+60, Y+99 Prize: X=5570, Y=3638 Button A: X+43, Y+14 Button B: X+25, Y+43 Prize: X=16821, Y=13757 Button A: X+79, Y+13 Button B: X+17, Y+23 Prize: X=4481, Y=2495 Button A: X+23, Y+58 Button B: X+66, Y+22 Prize: X=4056, Y=1562 Button A: X+18, Y+42 Button B: X+67, Y+40 Prize: X=4107, Y=2952 Button A: X+17, Y+53 Button B: X+99, Y+14 Prize: X=4219, Y=3430 Button A: X+36, Y+13 Button B: X+40, Y+82 Prize: X=4508, Y=6019 Button A: X+16, Y+69 Button B: X+88, Y+56 Prize: X=2152, Y=1840 Button A: X+34, Y+13 Button B: X+12, Y+69 Prize: X=2684, Y=1928 Button A: X+79, Y+21 Button B: X+31, Y+85 Prize: X=1675, Y=2441 Button A: X+42, Y+68 Button B: X+87, Y+30 Prize: X=8829, Y=7754 Button A: X+76, Y+42 Button B: X+37, Y+87 Prize: X=8620, Y=7692 Button A: X+26, Y+45 Button B: X+96, Y+33 Prize: X=522, Y=504 Button A: X+22, Y+80 Button B: X+57, Y+52 Prize: X=1460, Y=4688 Button A: X+78, Y+61 Button B: X+24, Y+91 Prize: X=3108, Y=6620 Button A: X+18, Y+40 Button B: X+33, Y+16 Prize: X=10217, Y=10816 Button A: X+99, Y+14 Button B: X+97, Y+90 Prize: X=10479, Y=5830 Button A: X+13, Y+57 Button B: X+91, Y+20 Prize: X=4095, Y=2037 Button A: X+31, Y+15 Button B: X+24, Y+37 Prize: X=3109, Y=1809 Button A: X+12, Y+29 Button B: X+51, Y+18 Prize: X=2549, Y=18593 Button A: X+19, Y+93 Button B: X+90, Y+63 Prize: X=3706, Y=5304 Button A: X+80, Y+88 Button B: X+14, Y+81 Prize: X=4168, Y=5372 Button A: X+39, Y+19 Button B: X+21, Y+58 Prize: X=3183, Y=1694 Button A: X+43, Y+21 Button B: X+31, Y+52 Prize: X=16089, Y=8718 Button A: X+49, Y+18 Button B: X+40, Y+58 Prize: X=965, Y=1134 Button A: X+20, Y+88 Button B: X+69, Y+58 Prize: X=1074, Y=3252 Button A: X+21, Y+70 Button B: X+63, Y+16 Prize: X=15950, Y=16374 Button A: X+74, Y+35 Button B: X+14, Y+39 Prize: X=1672, Y=3064 Button A: X+20, Y+45 Button B: X+48, Y+23 Prize: X=5340, Y=9415 Button A: X+62, Y+58 Button B: X+23, Y+99 Prize: X=2573, Y=4809 Button A: X+31, Y+63 Button B: X+54, Y+15 Prize: X=19014, Y=5888 Button A: X+55, Y+23 Button B: X+15, Y+37 Prize: X=8895, Y=2213 Button A: X+15, Y+67 Button B: X+54, Y+20 Prize: X=9194, Y=17528 Button A: X+18, Y+75 Button B: X+68, Y+15 Prize: X=4586, Y=16760 Button A: X+16, Y+39 Button B: X+42, Y+26 Prize: X=6762, Y=12119 Button A: X+47, Y+71 Button B: X+40, Y+17 Prize: X=1887, Y=13467 Button A: X+31, Y+16 Button B: X+37, Y+88 Prize: X=5502, Y=8352 Button A: X+33, Y+76 Button B: X+43, Y+14 Prize: X=16415, Y=12452 Button A: X+71, Y+45 Button B: X+11, Y+23 Prize: X=16969, Y=10475 Button A: X+85, Y+17 Button B: X+41, Y+46 Prize: X=4525, Y=1472 Button A: X+25, Y+63 Button B: X+49, Y+23 Prize: X=9351, Y=16161 Button A: X+15, Y+45 Button B: X+82, Y+47 Prize: X=7046, Y=15131 Button A: X+16, Y+48 Button B: X+22, Y+11 Prize: X=2828, Y=3534 Button A: X+27, Y+13 Button B: X+27, Y+61 Prize: X=8063, Y=7145 Button A: X+39, Y+71 Button B: X+52, Y+18 Prize: X=13679, Y=8591 Button A: X+23, Y+60 Button B: X+49, Y+13 Prize: X=4680, Y=2419 Button A: X+61, Y+83 Button B: X+62, Y+17 Prize: X=8921, Y=7019 Button A: X+66, Y+32 Button B: X+19, Y+40 Prize: X=10739, Y=2600 Button A: X+25, Y+93 Button B: X+98, Y+66 Prize: X=3314, Y=6954 Button A: X+16, Y+70 Button B: X+70, Y+68 Prize: X=3930, Y=7902 Button A: X+67, Y+27 Button B: X+69, Y+89 Prize: X=6749, Y=6269 Button A: X+15, Y+54 Button B: X+57, Y+20 Prize: X=335, Y=8334 Button A: X+73, Y+16 Button B: X+18, Y+20 Prize: X=5917, Y=2212 Button A: X+42, Y+15 Button B: X+60, Y+86 Prize: X=3900, Y=3330 Button A: X+62, Y+27 Button B: X+13, Y+51 Prize: X=2144, Y=11759 Button A: X+60, Y+21 Button B: X+11, Y+60 Prize: X=4782, Y=8672 Button A: X+77, Y+11 Button B: X+38, Y+78 Prize: X=6040, Y=7104 Button A: X+19, Y+85 Button B: X+23, Y+24 Prize: X=1183, Y=3320 Button A: X+58, Y+74 Button B: X+56, Y+13 Prize: X=2040, Y=1200 Button A: X+19, Y+80 Button B: X+87, Y+33 Prize: X=1790, Y=4537 Button A: X+19, Y+90 Button B: X+63, Y+55 Prize: X=7689, Y=13540 Button A: X+20, Y+73 Button B: X+66, Y+22 Prize: X=8268, Y=3896 Button A: X+45, Y+78 Button B: X+74, Y+12 Prize: X=7371, Y=6498 Button A: X+83, Y+14 Button B: X+55, Y+66 Prize: X=3469, Y=3478 Button A: X+95, Y+32 Button B: X+32, Y+77 Prize: X=6871, Y=8473 Button A: X+17, Y+31 Button B: X+94, Y+50 Prize: X=3538, Y=3902 Button A: X+16, Y+66 Button B: X+28, Y+11 Prize: X=4960, Y=4676 Button A: X+23, Y+73 Button B: X+54, Y+13 Prize: X=6634, Y=7542 Button A: X+63, Y+25 Button B: X+50, Y+77 Prize: X=7290, Y=5465 Button A: X+83, Y+11 Button B: X+11, Y+58 Prize: X=19276, Y=11149 Button A: X+11, Y+88 Button B: X+83, Y+45 Prize: X=6666, Y=5665 Button A: X+43, Y+14 Button B: X+14, Y+67 Prize: X=11261, Y=14558 Button A: X+62, Y+29 Button B: X+19, Y+44 Prize: X=2521, Y=3339 Button A: X+70, Y+15 Button B: X+59, Y+68 Prize: X=10614, Y=5928 Button A: X+94, Y+13 Button B: X+87, Y+96 Prize: X=8387, Y=8801 Button A: X+87, Y+89 Button B: X+71, Y+13 Prize: X=6299, Y=4953 Button A: X+96, Y+24 Button B: X+49, Y+72 Prize: X=11557, Y=7968 Button A: X+95, Y+98 Button B: X+16, Y+85 Prize: X=6874, Y=8050 Button A: X+71, Y+13 Button B: X+13, Y+43 Prize: X=3894, Y=2638 Button A: X+39, Y+87 Button B: X+23, Y+16 Prize: X=2003, Y=2950 Button A: X+18, Y+51 Button B: X+88, Y+42 Prize: X=7254, Y=3759 Button A: X+11, Y+52 Button B: X+66, Y+22 Prize: X=17876, Y=7662 Button A: X+40, Y+21 Button B: X+15, Y+35 Prize: X=2195, Y=14382 Button A: X+12, Y+87 Button B: X+64, Y+21 Prize: X=5356, Y=2505 Button A: X+13, Y+33 Button B: X+70, Y+50 Prize: X=5649, Y=7169 Button A: X+92, Y+16 Button B: X+42, Y+85 Prize: X=5178, Y=4863 Button A: X+59, Y+92 Button B: X+65, Y+25 Prize: X=5947, Y=4921 Button A: X+53, Y+29 Button B: X+24, Y+55 Prize: X=4866, Y=1041 Button A: X+17, Y+66 Button B: X+67, Y+39 Prize: X=5699, Y=7974 Button A: X+14, Y+38 Button B: X+71, Y+33 Prize: X=4260, Y=4216 Button A: X+58, Y+22 Button B: X+12, Y+47 Prize: X=1726, Y=2862 Button A: X+70, Y+33 Button B: X+48, Y+98 Prize: X=8822, Y=8229 Button A: X+13, Y+51 Button B: X+54, Y+16 Prize: X=4006, Y=5336 Button A: X+69, Y+32 Button B: X+19, Y+43 Prize: X=11505, Y=3154 Button A: X+35, Y+14 Button B: X+16, Y+49 Prize: X=16262, Y=6269 Button A: X+94, Y+20 Button B: X+20, Y+57 Prize: X=7242, Y=2543 Button A: X+22, Y+68 Button B: X+63, Y+14 Prize: X=12524, Y=7976 Button A: X+13, Y+59 Button B: X+63, Y+28 Prize: X=3729, Y=15618 Button A: X+22, Y+11 Button B: X+37, Y+67 Prize: X=3661, Y=1532 Button A: X+98, Y+41 Button B: X+15, Y+39 Prize: X=10330, Y=6547 Button A: X+69, Y+16 Button B: X+23, Y+94 Prize: X=5451, Y=5786 Button A: X+13, Y+60 Button B: X+40, Y+15 Prize: X=8281, Y=9155 Button A: X+41, Y+19 Button B: X+31, Y+66 Prize: X=4199, Y=5457 Button A: X+27, Y+70 Button B: X+59, Y+12 Prize: X=7391, Y=17342 Button A: X+66, Y+12 Button B: X+40, Y+77 Prize: X=5714, Y=3061 Button A: X+66, Y+46 Button B: X+11, Y+33 Prize: X=14081, Y=9323 Button A: X+42, Y+20 Button B: X+34, Y+66 Prize: X=3960, Y=2334 Button A: X+94, Y+56 Button B: X+12, Y+41 Prize: X=6256, Y=4404 Button A: X+14, Y+33 Button B: X+58, Y+24 Prize: X=5254, Y=1715 Button A: X+20, Y+63 Button B: X+81, Y+24 Prize: X=6982, Y=7662 Button A: X+66, Y+95 Button B: X+94, Y+41 Prize: X=5004, Y=3242 Button A: X+66, Y+75 Button B: X+12, Y+75 Prize: X=6786, Y=11025 Button A: X+12, Y+33 Button B: X+71, Y+25 Prize: X=17784, Y=10819 Button A: X+17, Y+92 Button B: X+92, Y+49 Prize: X=2731, Y=5353 Button A: X+93, Y+41 Button B: X+11, Y+25 Prize: X=7015, Y=3677 Button A: X+65, Y+13 Button B: X+13, Y+66 Prize: X=17722, Y=10475 Button A: X+11, Y+36 Button B: X+79, Y+41 Prize: X=7505, Y=10050 Button A: X+12, Y+44 Button B: X+62, Y+23 Prize: X=5604, Y=5836 Button A: X+51, Y+27 Button B: X+19, Y+71 Prize: X=2344, Y=5324 Button A: X+96, Y+12 Button B: X+80, Y+85 Prize: X=10560, Y=4920 Button A: X+36, Y+98 Button B: X+99, Y+55 Prize: X=3069, Y=7711 Button A: X+56, Y+25 Button B: X+20, Y+61 Prize: X=6116, Y=16247 Button A: X+36, Y+52 Button B: X+78, Y+30 Prize: X=5898, Y=5626 Button A: X+31, Y+95 Button B: X+68, Y+26 Prize: X=4862, Y=4686 Button A: X+59, Y+13 Button B: X+14, Y+55 Prize: X=3090, Y=15871 Button A: X+45, Y+20 Button B: X+35, Y+55 Prize: X=4270, Y=4580 Button A: X+96, Y+52 Button B: X+14, Y+58 Prize: X=9848, Y=7956 Button A: X+58, Y+25 Button B: X+11, Y+20 Prize: X=6199, Y=18370 Button A: X+77, Y+24 Button B: X+44, Y+81 Prize: X=4631, Y=5817 Button A: X+11, Y+42 Button B: X+89, Y+30 Prize: X=665, Y=990 Button A: X+56, Y+26 Button B: X+20, Y+60 Prize: X=1760, Y=2090 Button A: X+73, Y+16 Button B: X+49, Y+71 Prize: X=732, Y=522 Button A: X+43, Y+20 Button B: X+16, Y+37 Prize: X=16455, Y=11559 Button A: X+62, Y+11 Button B: X+22, Y+58 Prize: X=8054, Y=17144 Button A: X+11, Y+56 Button B: X+91, Y+56 Prize: X=7989, Y=8904 Button A: X+54, Y+16 Button B: X+33, Y+86 Prize: X=4410, Y=8624 Button A: X+23, Y+96 Button B: X+60, Y+42 Prize: X=2925, Y=8040 Button A: X+71, Y+39 Button B: X+19, Y+41 Prize: X=5533, Y=13797 Button A: X+74, Y+33 Button B: X+54, Y+77 Prize: X=7604, Y=5984 Button A: X+28, Y+89 Button B: X+64, Y+19 Prize: X=4460, Y=3664 Button A: X+14, Y+39 Button B: X+68, Y+56 Prize: X=1442, Y=3083 Button A: X+19, Y+87 Button B: X+56, Y+60 Prize: X=3601, Y=7257 Button A: X+59, Y+24 Button B: X+14, Y+33 Prize: X=15888, Y=7589 Button A: X+61, Y+19 Button B: X+59, Y+64 Prize: X=9413, Y=6673 Button A: X+53, Y+80 Button B: X+44, Y+16 Prize: X=14124, Y=16208 Button A: X+31, Y+31 Button B: X+71, Y+11 Prize: X=6501, Y=2841 Button A: X+94, Y+20 Button B: X+49, Y+59 Prize: X=6254, Y=4828 Button A: X+54, Y+31 Button B: X+29, Y+52 Prize: X=2883, Y=9438 Button A: X+58, Y+54 Button B: X+18, Y+59 Prize: X=814, Y=1307 Button A: X+20, Y+71 Button B: X+59, Y+11 Prize: X=3109, Y=17101 Button A: X+12, Y+34 Button B: X+37, Y+11 Prize: X=16103, Y=1699 Button A: X+94, Y+96 Button B: X+11, Y+62 Prize: X=4691, Y=7786 Button A: X+95, Y+25 Button B: X+78, Y+89 Prize: X=12181, Y=8478 Button A: X+25, Y+65 Button B: X+79, Y+18 Prize: X=962, Y=1939 Button A: X+12, Y+63 Button B: X+42, Y+45 Prize: X=1872, Y=6318 Button A: X+44, Y+17 Button B: X+20, Y+58 Prize: X=6780, Y=19261 Button A: X+34, Y+65 Button B: X+54, Y+17 Prize: X=3820, Y=11780 Button A: X+12, Y+75 Button B: X+71, Y+19 Prize: X=11722, Y=15270 Button A: X+22, Y+58 Button B: X+61, Y+46 Prize: X=3750, Y=5064 Button A: X+26, Y+30 Button B: X+46, Y+15 Prize: X=6232, Y=3840 Button A: X+69, Y+79 Button B: X+79, Y+22 Prize: X=9421, Y=7227 Button A: X+50, Y+22 Button B: X+35, Y+60 Prize: X=17190, Y=12800 Button A: X+20, Y+57 Button B: X+55, Y+24 Prize: X=2955, Y=10643 Button A: X+63, Y+17 Button B: X+16, Y+62 Prize: X=12674, Y=17090 Button A: X+30, Y+71 Button B: X+95, Y+50 Prize: X=8800, Y=5791 Button A: X+46, Y+15 Button B: X+40, Y+70 Prize: X=9362, Y=2425 Button A: X+68, Y+72 Button B: X+66, Y+11 Prize: X=6626, Y=5897 Button A: X+15, Y+39 Button B: X+50, Y+35 Prize: X=13560, Y=6621 Button A: X+63, Y+37 Button B: X+25, Y+52 Prize: X=16956, Y=14505 Button A: X+27, Y+84 Button B: X+93, Y+39 Prize: X=8091, Y=7899 Button A: X+14, Y+43 Button B: X+83, Y+49 Prize: X=8887, Y=1332 Button A: X+26, Y+41 Button B: X+86, Y+23 Prize: X=3690, Y=2553 Button A: X+42, Y+15 Button B: X+19, Y+56 Prize: X=4755, Y=18862 Button A: X+50, Y+25 Button B: X+14, Y+66 Prize: X=4302, Y=7638 Button A: X+59, Y+35 Button B: X+12, Y+36 Prize: X=11278, Y=13462 Button A: X+41, Y+77 Button B: X+45, Y+12 Prize: X=5703, Y=7665 Button A: X+49, Y+68 Button B: X+34, Y+12 Prize: X=3834, Y=2940 Button A: X+24, Y+49 Button B: X+42, Y+27 Prize: X=13496, Y=6346 Button A: X+11, Y+52 Button B: X+43, Y+18 Prize: X=5977, Y=8740 Button A: X+49, Y+93 Button B: X+68, Y+37 Prize: X=6795, Y=4427 Button A: X+57, Y+21 Button B: X+27, Y+66 Prize: X=18467, Y=14201 Button A: X+71, Y+13 Button B: X+50, Y+68 Prize: X=6377, Y=5581 Button A: X+86, Y+24 Button B: X+14, Y+95 Prize: X=1510, Y=6889 Button A: X+24, Y+77 Button B: X+83, Y+31 Prize: X=6372, Y=6326 Button A: X+70, Y+35 Button B: X+23, Y+44 Prize: X=3744, Y=3107 Button A: X+41, Y+13 Button B: X+41, Y+65 Prize: X=8553, Y=10117 Button A: X+31, Y+92 Button B: X+65, Y+45 Prize: X=2715, Y=7170 Button A: X+20, Y+93 Button B: X+39, Y+34 Prize: X=5098, Y=11623 Button A: X+47, Y+22 Button B: X+30, Y+50 Prize: X=10226, Y=6806 Button A: X+47, Y+16 Button B: X+32, Y+62 Prize: X=4072, Y=11088 Button A: X+20, Y+95 Button B: X+69, Y+17 Prize: X=2893, Y=2244 Button A: X+12, Y+40 Button B: X+71, Y+25 Prize: X=19241, Y=5175 Button A: X+13, Y+59 Button B: X+98, Y+86 Prize: X=4005, Y=8131 Button A: X+49, Y+15 Button B: X+17, Y+57 Prize: X=3550, Y=12584 Button A: X+29, Y+14 Button B: X+13, Y+49 Prize: X=369, Y=819 Button A: X+19, Y+72 Button B: X+62, Y+13 Prize: X=15652, Y=2141 Button A: X+24, Y+66 Button B: X+58, Y+20 Prize: X=16168, Y=12354 Button A: X+12, Y+47 Button B: X+25, Y+13 Prize: X=7445, Y=3589 Button A: X+19, Y+60 Button B: X+77, Y+63 Prize: X=5950, Y=7980 Button A: X+41, Y+15 Button B: X+31, Y+52 Prize: X=14064, Y=12352 Button A: X+24, Y+93 Button B: X+70, Y+24 Prize: X=2140, Y=5820 Button A: X+15, Y+69 Button B: X+86, Y+13 Prize: X=5919, Y=6567 Button A: X+14, Y+28 Button B: X+53, Y+11 Prize: X=18614, Y=18488 Button A: X+98, Y+15 Button B: X+55, Y+98 Prize: X=7148, Y=5394 Button A: X+31, Y+11 Button B: X+11, Y+68 Prize: X=9045, Y=10249 Button A: X+58, Y+70 Button B: X+76, Y+16 Prize: X=12382, Y=7750 Button A: X+93, Y+56 Button B: X+27, Y+97 Prize: X=2238, Y=2478 Button A: X+62, Y+30 Button B: X+16, Y+53 Prize: X=8124, Y=3852 Button A: X+42, Y+24 Button B: X+28, Y+54 Prize: X=13850, Y=6044 Button A: X+55, Y+97 Button B: X+77, Y+17 Prize: X=5995, Y=8791 Button A: X+24, Y+49 Button B: X+40, Y+26 Prize: X=6432, Y=18253 Button A: X+79, Y+32 Button B: X+49, Y+68 Prize: X=11798, Y=8920 Button A: X+72, Y+15 Button B: X+84, Y+77 Prize: X=11244, Y=5972 Button A: X+70, Y+45 Button B: X+27, Y+91 Prize: X=1990, Y=4225 Button A: X+18, Y+53 Button B: X+61, Y+50 Prize: X=5128, Y=6804 Button A: X+96, Y+46 Button B: X+21, Y+65 Prize: X=5880, Y=4136 Button A: X+67, Y+21 Button B: X+21, Y+52 Prize: X=8162, Y=6010 Button A: X+29, Y+66 Button B: X+54, Y+20 Prize: X=4291, Y=12102 Button A: X+53, Y+24 Button B: X+14, Y+30 Prize: X=1819, Y=680 Button A: X+52, Y+23 Button B: X+20, Y+60 Prize: X=7176, Y=9774 Button A: X+21, Y+54 Button B: X+45, Y+14 Prize: X=15716, Y=17168 Button A: X+24, Y+52 Button B: X+31, Y+11 Prize: X=14283, Y=16015 Button A: X+12, Y+77 Button B: X+88, Y+26 Prize: X=1104, Y=620 Button A: X+13, Y+70 Button B: X+81, Y+73 Prize: X=6158, Y=8464 Button A: X+99, Y+38 Button B: X+20, Y+88 Prize: X=932, Y=920 Button A: X+45, Y+70 Button B: X+41, Y+17 Prize: X=365, Y=16505 Button A: X+16, Y+45 Button B: X+71, Y+29 Prize: X=18570, Y=525 Button A: X+92, Y+22 Button B: X+34, Y+84 Prize: X=9554, Y=9644 Button A: X+23, Y+52 Button B: X+46, Y+27 Prize: X=7897, Y=18630 Button A: X+63, Y+91 Button B: X+32, Y+15 Prize: X=2452, Y=1887 Button A: X+11, Y+74 Button B: X+60, Y+13 Prize: X=10126, Y=1345 Button A: X+16, Y+47 Button B: X+37, Y+11 Prize: X=19201, Y=8796 Button A: X+76, Y+34 Button B: X+42, Y+97 Prize: X=5870, Y=5207 Button A: X+66, Y+13 Button B: X+14, Y+56 Prize: X=2014, Y=7202 Button A: X+23, Y+62 Button B: X+74, Y+32 Prize: X=16271, Y=5174 Button A: X+22, Y+51 Button B: X+50, Y+28 Prize: X=644, Y=2445 Button A: X+14, Y+48 Button B: X+72, Y+27 Prize: X=7124, Y=4751 Button A: X+64, Y+37 Button B: X+27, Y+50 Prize: X=8691, Y=14528 Button A: X+35, Y+94 Button B: X+60, Y+13 Prize: X=7870, Y=7063 Button A: X+95, Y+86 Button B: X+19, Y+98 Prize: X=8816, Y=10324 Button A: X+92, Y+17 Button B: X+12, Y+43 Prize: X=7600, Y=2220 Button A: X+90, Y+36 Button B: X+35, Y+54 Prize: X=5245, Y=5418 Button A: X+91, Y+31 Button B: X+33, Y+54 Prize: X=3713, Y=1949 Button A: X+36, Y+61 Button B: X+77, Y+12 Prize: X=9005, Y=6610 Button A: X+22, Y+48 Button B: X+52, Y+11 Prize: X=1826, Y=5756 Button A: X+63, Y+29 Button B: X+18, Y+58 Prize: X=15623, Y=6557 Button A: X+36, Y+71 Button B: X+53, Y+13 Prize: X=4948, Y=4633 Button A: X+70, Y+29 Button B: X+14, Y+48 Prize: X=17364, Y=2186 Button A: X+31, Y+45 Button B: X+66, Y+29 Prize: X=2118, Y=1872 Button A: X+39, Y+82 Button B: X+81, Y+11 Prize: X=7965, Y=5914 Button A: X+13, Y+73 Button B: X+67, Y+15 Prize: X=2161, Y=19093 Button A: X+45, Y+24 Button B: X+35, Y+80 Prize: X=5740, Y=7048 Button A: X+37, Y+64 Button B: X+54, Y+12 Prize: X=6408, Y=3432 Button A: X+87, Y+11 Button B: X+11, Y+85 Prize: X=14470, Y=7034 Button A: X+24, Y+16 Button B: X+13, Y+39 Prize: X=10040, Y=18520 Button A: X+23, Y+38 Button B: X+78, Y+13 Prize: X=4645, Y=1765 Button A: X+89, Y+63 Button B: X+13, Y+70 Prize: X=4343, Y=4655 Button A: X+73, Y+75 Button B: X+15, Y+89 Prize: X=5844, Y=6740 Button A: X+14, Y+58 Button B: X+43, Y+12 Prize: X=11274, Y=1678 Button A: X+35, Y+66 Button B: X+54, Y+18 Prize: X=6095, Y=10178 Button A: X+28, Y+93 Button B: X+63, Y+28 Prize: X=4599, Y=8569 Button A: X+28, Y+61 Button B: X+54, Y+28 Prize: X=1510, Y=1945 Button A: X+17, Y+55 Button B: X+39, Y+18 Prize: X=9257, Y=12020 Button A: X+32, Y+13 Button B: X+39, Y+61 Prize: X=8346, Y=11909 Button A: X+25, Y+14 Button B: X+27, Y+50 Prize: X=8055, Y=7970 Button A: X+13, Y+39 Button B: X+47, Y+29 Prize: X=1065, Y=2299 Button A: X+91, Y+14 Button B: X+83, Y+90 Prize: X=10148, Y=5500 Button A: X+88, Y+25 Button B: X+11, Y+38 Prize: X=7799, Y=3506 Button A: X+36, Y+95 Button B: X+48, Y+21 Prize: X=1824, Y=1749 Button A: X+73, Y+19 Button B: X+18, Y+78 Prize: X=521, Y=18131 Button A: X+11, Y+89 Button B: X+93, Y+39 Prize: X=3321, Y=9747 Button A: X+46, Y+19 Button B: X+27, Y+60 Prize: X=2172, Y=17400 Button A: X+90, Y+18 Button B: X+23, Y+43 Prize: X=4461, Y=3081 Button A: X+34, Y+72 Button B: X+91, Y+26 Prize: X=2725, Y=3270 Button A: X+25, Y+55 Button B: X+73, Y+16 Prize: X=1417, Y=2539 Button A: X+16, Y+30 Button B: X+30, Y+12 Prize: X=9614, Y=2156 Button A: X+48, Y+18 Button B: X+11, Y+54 Prize: X=15777, Y=14444 Button A: X+20, Y+51 Button B: X+97, Y+29 Prize: X=5497, Y=5065 Button A: X+69, Y+28 Button B: X+13, Y+31 Prize: X=18098, Y=2226 Button A: X+73, Y+15 Button B: X+16, Y+17 Prize: X=3422, Y=1759 Button A: X+32, Y+73 Button B: X+59, Y+16 Prize: X=6024, Y=5866 Button A: X+18, Y+50 Button B: X+62, Y+24 Prize: X=1178, Y=6386 Button A: X+48, Y+44 Button B: X+24, Y+85 Prize: X=2664, Y=4773 Button A: X+27, Y+23 Button B: X+14, Y+88 Prize: X=2685, Y=4113 Button A: X+18, Y+44 Button B: X+67, Y+26 Prize: X=13034, Y=14972 ================================================ FILE: exm/aoc/2024/aoc_2024_13_questions.txt ================================================ --- Day 13: Claw Contraption --- Next up: the lobby of a resort on a tropical island. The Historians take a moment to admire the hexagonal floor tiles before spreading out. Fortunately, it looks like the resort has a new arcade! Maybe you can win some prizes from the claw machines? The claw machines here are a little unusual. Instead of a joystick or directional buttons to control the claw, these machines have two buttons labeled A and B. Worse, you can't just put in a token and play; it costs 3 tokens to push the A button and 1 token to push the B button. With a little experimentation, you figure out that each machine's buttons are configured to move the claw a specific amount to the right (along the X axis) and a specific amount forward (along the Y axis) each time that button is pressed. Each machine contains one prize; to win the prize, the claw must be positioned exactly above the prize on both the X and Y axes. You wonder: what is the smallest number of tokens you would have to spend to win as many prizes as possible? You assemble a list of every machine's button behavior and prize location (your puzzle input). For example: Button A: X+94, Y+34 Button B: X+22, Y+67 Prize: X=8400, Y=5400 Button A: X+26, Y+66 Button B: X+67, Y+21 Prize: X=12748, Y=12176 Button A: X+17, Y+86 Button B: X+84, Y+37 Prize: X=7870, Y=6450 Button A: X+69, Y+23 Button B: X+27, Y+71 Prize: X=18641, Y=10279 This list describes the button configuration and prize location of four different claw machines. For now, consider just the first claw machine in the list: Pushing the machine's A button would move the claw 94 units along the X axis and 34 units along the Y axis. Pushing the B button would move the claw 22 units along the X axis and 67 units along the Y axis. The prize is located at X=8400, Y=5400; this means that from the claw's initial position, it would need to move exactly 8400 units along the X axis and exactly 5400 units along the Y axis to be perfectly aligned with the prize in this machine. The cheapest way to win the prize is by pushing the A button 80 times and the B button 40 times. This would line up the claw along the X axis (because 80*94 + 40*22 = 8400) and along the Y axis (because 80*34 + 40*67 = 5400). Doing this would cost 80*3 tokens for the A presses and 40*1 for the B presses, a total of 280 tokens. For the second and fourth claw machines, there is no combination of A and B presses that will ever win a prize. For the third claw machine, the cheapest way to win the prize is by pushing the A button 38 times and the B button 86 times. Doing this would cost a total of 200 tokens. So, the most prizes you could possibly win is two; the minimum tokens you would have to spend to win all (two) prizes is 480. You estimate that each button would need to be pressed no more than 100 times to win a prize. How else would someone be expected to play? Figure out how to win as many prizes as possible. What is the fewest tokens you would have to spend to win all possible prizes? --- Part Two --- As you go to win the first prize, you discover that the claw is nowhere near where you expected it would be. Due to a unit conversion error in your measurements, the position of every prize is actually 10000000000000 higher on both the X and Y axis! Add 10000000000000 to the X and Y position of every prize. After making this change, the example above would now look like this: Button A: X+94, Y+34 Button B: X+22, Y+67 Prize: X=10000000008400, Y=10000000005400 Button A: X+26, Y+66 Button B: X+67, Y+21 Prize: X=10000000012748, Y=10000000012176 Button A: X+17, Y+86 Button B: X+84, Y+37 Prize: X=10000000007870, Y=10000000006450 Button A: X+69, Y+23 Button B: X+27, Y+71 Prize: X=10000000018641, Y=10000000010279 Now, it is only possible to win a prize on the second and fourth claw machines. Unfortunately, it will take many more than 100 presses to do so. Using the corrected prize coordinates, figure out how to win as many prizes as possible. What is the fewest tokens you would have to spend to win all possible prizes? ================================================ FILE: exm/aoc/2024/aoc_2024_14.adb ================================================ -- Solution to Advent of Code 2024, Day 14 ------------------------------------------- -- Restroom Redoubt -- -- https://adventofcode.com/2024/day/14 -- Copy of questions in: aoc_2024_14_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_14 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; nx : constant := 11; ny : constant := 7; nr : constant := 12; input_name : constant VString := +"aoc_2024_14"; nx : constant := 101; ny : constant := 103; nr : constant := 500; type Robot is record p, v : Point; end record; type Robot_Array is array (1 .. nr) of Robot; r0 : Robot_Array; r : array (Part_Type) of Integer; procedure Read_Data is sep1, sep2 : Character; peq : String (1 .. 2); veq : String (1 .. 3); f : File_Type; begin Open (f, input_name & ".txt"); for i in 1 .. nr loop Get (f, peq); Get (f, r0 (i).p.x); Get (f, sep1); Get (f, r0 (i).p.y); Get (f, veq); Get (f, r0 (i).v.x); Get (f, sep2); Get (f, r0 (i).v.y); end loop; Close (f); end Read_Data; procedure Show (ro : Robot_Array) is has_robot : Boolean; begin for y in 0 .. ny - 1 loop for x in 0 .. nx - 1 loop has_robot := False; for i in 1 .. nr loop if ro (i).p.x = x and then ro (i).p.y = y then has_robot := True; end if; end loop; if has_robot then Put ("*"); else Put (" "); end if; end loop; New_Line; end loop; end Show; procedure Evolve (ro : in out Robot_Array) is begin for i in 1 .. nr loop ro (i).p.x := (ro (i).p.x + ro (i).v.x) mod nx; ro (i).p.y := (ro (i).p.y + ro (i).v.y) mod ny; end loop; end Evolve; function Safety_Factor (ro : in Robot_Array) return Natural is q1, q2, q3, q4 : Natural := 0; begin for i in 1 .. nr loop if ro (i).p.x in 0 .. nx / 2 - 1 and then ro (i).p.y in 0 .. ny / 2 - 1 then q1 := q1 + 1; elsif ro (i).p.x in nx / 2 + 1 .. nx and then ro (i).p.y in 0 .. ny / 2 - 1 then q2 := q2 + 1; elsif ro (i).p.x in 0 .. nx / 2 - 1 and then ro (i).p.y in ny / 2 + 1 .. ny then q3 := q3 + 1; elsif ro (i).p.x in nx / 2 + 1 .. nx and then ro (i).p.y in ny / 2 + 1 .. ny then q4 := q4 + 1; end if; end loop; return q1 * q2 * q3 * q4; end Safety_Factor; procedure Do_Part_1 is ro : Robot_Array := r0; begin for t in 1 .. 100 loop Evolve (ro); end loop; r (part_1) := Safety_Factor (ro); end Do_Part_1; -- The threshold is determined heuristically. -- A perfectly uniform setup has 125 robots in -- each quadrant (safety factor 125**4 = 244,140,625). -- If all robots are in a single quadrant, the factor is 0. -- If 497 robots are in a quadrant and the other quadrants -- contain a robot each, the factor is 497. -- procedure Do_Part_2 is ro : Robot_Array := r0; begin for t in 1 .. nx * ny + 1 loop Evolve (ro); if Safety_Factor (ro) < 40_000_000 then r (part_2) := t; Show (ro); exit; end if; end loop; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; if not compiler_test_mode then Do_Part_2; end if; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 226236192 -- Part 2: validated by AoC: 8168 end if; end AoC_2024_14; ================================================ FILE: exm/aoc/2024/aoc_2024_14.txt ================================================ p=50,78 v=89,45 p=65,96 v=88,-21 p=23,63 v=61,46 p=61,76 v=25,-67 p=23,90 v=6,91 p=1,47 v=-17,-9 p=84,56 v=-73,-24 p=78,66 v=-20,-76 p=49,59 v=-22,17 p=73,95 v=34,-64 p=99,76 v=67,-40 p=59,77 v=-49,-4 p=15,30 v=24,65 p=89,2 v=-19,-38 p=28,70 v=93,66 p=39,33 v=24,-42 p=14,42 v=-33,-49 p=68,85 v=-37,-47 p=91,0 v=-45,12 p=88,92 v=78,-24 p=19,63 v=-70,-10 p=69,4 v=-40,90 p=61,91 v=64,-11 p=47,95 v=-77,46 p=20,10 v=-23,-63 p=98,82 v=90,96 p=90,30 v=4,74 p=0,28 v=-73,8 p=88,102 v=51,-51 p=66,29 v=26,1 p=19,20 v=-61,-15 p=13,18 v=6,71 p=12,39 v=67,24 p=41,67 v=-24,-23 p=78,10 v=-59,-68 p=30,2 v=-35,85 p=86,47 v=-95,53 p=44,36 v=-69,-89 p=19,20 v=-87,-95 p=65,3 v=73,16 p=95,29 v=43,61 p=66,50 v=49,-69 p=28,92 v=-25,19 p=74,60 v=-6,-98 p=15,80 v=92,-27 p=80,12 v=18,-62 p=72,34 v=19,-65 p=46,75 v=33,-74 p=14,100 v=-79,99 p=94,97 v=74,49 p=46,13 v=-45,-61 p=93,39 v=-9,-64 p=100,45 v=45,-76 p=62,19 v=-76,85 p=18,85 v=30,-71 p=24,68 v=84,-73 p=31,20 v=-86,-35 p=76,46 v=-59,77 p=27,52 v=-95,77 p=52,81 v=1,59 p=43,60 v=-71,-38 p=59,38 v=-6,24 p=70,65 v=26,-23 p=11,40 v=60,-33 p=26,77 v=62,43 p=24,93 v=99,-51 p=46,84 v=24,76 p=48,30 v=58,-87 p=46,100 v=21,98 p=24,39 v=-23,84 p=25,6 v=47,-78 p=89,73 v=-73,23 p=4,49 v=-96,14 p=69,61 v=52,-10 p=96,68 v=-96,99 p=17,12 v=-30,75 p=91,47 v=-98,-87 p=50,38 v=71,67 p=68,58 v=-13,17 p=39,30 v=84,93 p=93,19 v=-66,98 p=31,7 v=-8,75 p=7,81 v=-95,-4 p=38,43 v=8,-89 p=24,21 v=-98,3 p=72,43 v=25,-13 p=4,98 v=-71,78 p=79,65 v=-91,-57 p=49,47 v=-97,23 p=37,7 v=-15,45 p=41,74 v=-15,36 p=58,30 v=-92,71 p=72,92 v=68,-7 p=1,79 v=-4,-75 p=82,99 v=42,6 p=62,51 v=57,63 p=10,43 v=48,-74 p=74,70 v=65,-40 p=25,35 v=-1,-39 p=50,71 v=37,68 p=51,84 v=67,55 p=71,25 v=-45,-98 p=47,14 v=-7,28 p=70,99 v=69,46 p=21,44 v=-94,-16 p=52,40 v=-83,-49 p=76,99 v=-71,63 p=21,92 v=-32,-34 p=78,27 v=-85,-55 p=42,92 v=-76,-61 p=50,29 v=95,77 p=72,10 v=65,58 p=92,48 v=20,-1 p=42,80 v=55,-98 p=69,96 v=41,62 p=68,35 v=-91,-45 p=18,56 v=-33,37 p=52,96 v=1,49 p=22,87 v=53,99 p=84,31 v=19,41 p=87,38 v=58,-13 p=9,13 v=-18,98 p=40,0 v=-94,-31 p=71,16 v=-62,76 p=41,88 v=-46,99 p=27,97 v=-15,-4 p=25,54 v=23,-36 p=61,0 v=-60,-21 p=28,75 v=41,-79 p=64,46 v=-8,34 p=97,26 v=37,74 p=32,67 v=-48,-93 p=18,81 v=53,-2 p=12,101 v=30,-1 p=80,40 v=-90,-16 p=48,16 v=-69,61 p=7,89 v=52,49 p=93,0 v=-35,-61 p=24,52 v=31,53 p=37,67 v=-98,36 p=92,77 v=28,46 p=76,59 v=-74,-21 p=96,63 v=58,57 p=62,2 v=-68,-68 p=39,20 v=-39,-25 p=5,12 v=60,88 p=75,35 v=-37,88 p=77,24 v=-52,-13 p=42,0 v=92,-72 p=33,61 v=-91,-6 p=10,74 v=23,-17 p=6,73 v=37,-54 p=76,99 v=2,-71 p=53,20 v=71,91 p=82,31 v=71,-82 p=20,87 v=-40,26 p=52,47 v=-45,-69 p=32,38 v=43,-55 p=8,85 v=-56,-77 p=11,0 v=68,2 p=40,30 v=-46,-72 p=26,53 v=27,-43 p=5,40 v=98,-90 p=46,4 v=39,-85 p=15,36 v=-95,87 p=0,4 v=-49,42 p=69,11 v=-86,-87 p=47,47 v=86,-17 p=95,88 v=-73,26 p=2,5 v=53,52 p=92,84 v=63,79 p=25,0 v=47,-35 p=83,55 v=-43,-46 p=95,43 v=-3,40 p=30,60 v=-79,-27 p=89,79 v=-39,-80 p=10,19 v=6,-95 p=70,64 v=87,10 p=51,93 v=79,-31 p=30,82 v=85,16 p=66,75 v=-51,40 p=79,70 v=-20,-20 p=59,60 v=25,63 p=86,17 v=75,-62 p=3,62 v=-18,-47 p=43,20 v=24,91 p=23,13 v=56,93 p=32,13 v=71,76 p=12,10 v=53,-28 p=20,86 v=-71,-74 p=91,90 v=-97,-75 p=76,66 v=-67,83 p=54,54 v=-84,64 p=66,70 v=-12,36 p=30,73 v=54,43 p=62,22 v=-21,31 p=11,92 v=-94,76 p=47,101 v=93,-25 p=37,21 v=96,19 p=93,51 v=20,97 p=46,31 v=-54,61 p=26,99 v=-64,-11 p=6,91 v=-55,-90 p=95,7 v=95,33 p=1,89 v=5,19 p=69,24 v=-83,81 p=82,37 v=-66,-92 p=20,66 v=-80,-77 p=45,87 v=-47,-11 p=19,77 v=8,1 p=61,12 v=-70,79 p=59,48 v=14,44 p=68,70 v=48,-37 p=77,94 v=42,-84 p=47,31 v=1,-32 p=22,1 v=-40,95 p=41,98 v=-53,16 p=38,49 v=48,77 p=21,98 v=-71,12 p=67,92 v=-13,69 p=99,99 v=-80,-84 p=50,18 v=-77,-45 p=71,35 v=-36,-22 p=61,65 v=-68,10 p=96,25 v=56,-21 p=77,65 v=-20,-40 p=56,81 v=56,29 p=81,19 v=-97,-15 p=31,12 v=-62,-38 p=92,83 v=51,-4 p=70,23 v=-44,45 p=55,61 v=-27,-33 p=9,48 v=99,40 p=20,36 v=-80,-52 p=83,46 v=-35,-59 p=52,43 v=58,-88 p=2,88 v=-49,-34 p=31,99 v=54,59 p=76,21 v=11,31 p=5,51 v=-27,35 p=57,88 v=2,19 p=86,41 v=-51,60 p=82,58 v=-98,-96 p=100,70 v=-38,-85 p=81,47 v=-10,-30 p=96,88 v=82,6 p=24,28 v=62,98 p=44,71 v=-69,-50 p=75,11 v=-99,-52 p=35,80 v=16,-37 p=2,21 v=-27,84 p=80,14 v=-43,98 p=49,76 v=80,21 p=84,96 v=-82,67 p=32,79 v=-95,74 p=35,81 v=-90,-68 p=47,45 v=-22,-6 p=69,45 v=41,-83 p=63,21 v=1,-92 p=57,1 v=-98,4 p=34,4 v=-93,-81 p=46,63 v=-99,47 p=8,99 v=5,29 p=32,27 v=54,-42 p=27,98 v=17,-98 p=63,22 v=81,98 p=75,36 v=-86,66 p=58,5 v=-67,-58 p=82,20 v=81,-57 p=82,67 v=81,83 p=58,58 v=17,-13 p=18,89 v=14,-21 p=76,63 v=24,65 p=38,48 v=-85,-99 p=17,34 v=45,21 p=77,70 v=3,-50 p=56,82 v=17,76 p=64,97 v=94,-71 p=16,40 v=37,84 p=29,96 v=-61,-7 p=12,79 v=-95,-34 p=1,72 v=63,38 p=0,20 v=60,68 p=43,60 v=-6,40 p=20,22 v=-17,58 p=47,49 v=-70,94 p=12,29 v=-25,-32 p=22,69 v=-44,-22 p=44,78 v=31,33 p=86,50 v=76,-19 p=0,92 v=35,16 p=42,8 v=-39,87 p=30,1 v=14,61 p=41,57 v=18,-84 p=83,82 v=-97,36 p=72,7 v=-78,62 p=17,4 v=-95,12 p=15,15 v=60,73 p=80,79 v=-59,56 p=49,76 v=-22,-47 p=58,82 v=26,62 p=59,101 v=-82,96 p=78,56 v=-97,-56 p=19,62 v=85,-44 p=21,4 v=61,-91 p=80,66 v=-12,-27 p=66,17 v=96,28 p=57,6 v=-45,-38 p=24,70 v=61,-90 p=4,12 v=68,-58 p=27,37 v=15,-59 p=10,66 v=-33,-50 p=22,64 v=95,-38 p=47,44 v=24,-39 p=96,28 v=75,71 p=95,20 v=32,30 p=38,52 v=-89,10 p=88,94 v=96,-6 p=93,31 v=-38,18 p=61,79 v=46,-3 p=22,27 v=-33,5 p=77,62 v=81,-60 p=63,13 v=-94,81 p=39,49 v=93,89 p=7,37 v=-2,-89 p=59,2 v=24,-58 p=82,32 v=-4,-45 p=28,55 v=-70,-13 p=36,49 v=-93,90 p=16,74 v=53,-20 p=56,69 v=-84,93 p=40,25 v=-93,-89 p=73,60 v=-75,90 p=28,82 v=-47,-27 p=35,67 v=-8,-73 p=76,17 v=68,63 p=33,43 v=1,37 p=5,7 v=-52,-34 p=79,49 v=89,60 p=78,59 v=20,57 p=96,31 v=-93,-50 p=24,88 v=78,-24 p=12,39 v=37,-16 p=60,15 v=-21,45 p=25,17 v=-40,-45 p=9,63 v=-42,13 p=46,48 v=8,1 p=16,85 v=18,48 p=36,45 v=-41,95 p=62,88 v=54,6 p=46,57 v=-99,23 p=57,67 v=79,-40 p=88,96 v=4,-51 p=82,19 v=66,-2 p=9,73 v=68,-54 p=66,38 v=9,74 p=40,68 v=-15,83 p=97,24 v=-64,-55 p=52,56 v=-61,7 p=55,15 v=-53,91 p=98,66 v=78,-47 p=27,46 v=-47,4 p=100,19 v=36,-78 p=5,9 v=6,82 p=63,35 v=49,21 p=40,101 v=8,-14 p=98,19 v=-74,-28 p=74,15 v=96,-65 p=53,47 v=-84,34 p=48,14 v=94,-98 p=69,2 v=3,-71 p=38,10 v=78,35 p=74,76 v=-90,-60 p=37,68 v=55,-70 p=52,78 v=-31,48 p=6,24 v=-73,24 p=77,51 v=38,94 p=73,45 v=-42,-72 p=52,57 v=67,-51 p=12,14 v=46,39 p=6,11 v=65,21 p=29,37 v=-54,-95 p=41,24 v=-85,68 p=78,102 v=96,-24 p=13,25 v=-16,66 p=8,53 v=6,90 p=77,6 v=26,-71 p=98,45 v=-95,84 p=56,15 v=-27,-83 p=82,98 v=-35,52 p=24,42 v=-8,-29 p=16,46 v=-78,-53 p=25,15 v=-34,-54 p=27,42 v=-11,-13 p=12,69 v=46,3 p=74,20 v=43,-9 p=25,85 v=9,-93 p=65,99 v=26,-1 p=90,78 v=74,36 p=41,6 v=77,-88 p=85,62 v=-43,93 p=34,61 v=33,2 p=0,65 v=75,53 p=40,30 v=48,-36 p=31,1 v=47,48 p=24,100 v=85,99 p=97,24 v=-76,-67 p=69,59 v=21,28 p=82,72 v=7,96 p=9,10 v=68,25 p=26,91 v=85,49 p=35,86 v=39,-24 p=38,35 v=48,-99 p=99,61 v=35,-61 p=79,86 v=-98,99 p=94,40 v=50,-22 p=47,101 v=16,72 p=53,61 v=41,-3 p=27,101 v=-48,89 p=28,82 v=15,29 p=83,58 v=58,-10 p=40,38 v=-14,-82 p=52,78 v=79,16 p=45,15 v=-47,78 p=72,0 v=81,64 p=72,51 v=-95,-32 p=88,67 v=34,70 p=89,72 v=12,-90 p=61,31 v=25,-92 p=68,53 v=48,70 p=47,53 v=94,10 p=15,53 v=-72,27 p=80,8 v=20,-37 p=28,66 v=-16,-17 p=77,17 v=99,-11 p=46,10 v=-9,-66 p=76,71 v=78,-78 p=26,62 v=-85,56 p=87,9 v=-80,-71 p=67,36 v=-67,18 p=99,32 v=-80,61 p=69,87 v=73,89 p=6,100 v=-72,-48 p=40,38 v=-93,-92 p=89,12 v=81,-92 p=85,97 v=-19,-88 p=22,100 v=37,-4 p=11,45 v=-33,34 p=43,32 v=6,79 p=47,102 v=-84,52 p=89,94 v=-84,65 p=75,14 v=-3,-11 p=11,65 v=2,46 p=76,59 v=65,35 p=65,60 v=-75,40 p=92,36 v=-32,-9 p=69,16 v=11,15 p=62,63 v=32,80 p=47,50 v=-30,60 p=13,98 v=-80,-98 p=32,82 v=23,-74 p=28,6 v=-92,35 p=72,89 v=4,3 p=72,57 v=-3,80 p=6,44 v=89,-1 p=33,19 v=31,-78 p=43,101 v=-39,78 p=46,51 v=-30,-63 p=24,37 v=-79,-82 p=51,46 v=64,44 p=0,36 v=13,-99 p=71,6 v=72,9 p=40,98 v=78,-81 p=36,33 v=96,-14 p=63,100 v=95,12 p=12,42 v=-41,87 p=66,48 v=-52,77 p=5,77 v=36,23 p=94,54 v=80,24 p=77,71 v=-50,1 p=81,20 v=89,-85 p=9,13 v=-95,42 p=13,78 v=71,20 p=36,43 v=-21,88 p=56,94 v=87,69 p=91,53 v=21,57 p=80,84 v=-74,-44 p=19,90 v=-87,96 p=13,83 v=-63,-51 p=14,91 v=5,56 p=23,1 v=-72,-15 p=50,44 v=71,-73 p=6,49 v=45,67 p=4,0 v=-9,-91 p=70,8 v=-98,45 p=30,42 v=-78,61 p=87,74 v=-97,26 p=35,89 v=92,-32 p=23,61 v=94,41 p=87,21 v=-82,28 ================================================ FILE: exm/aoc/2024/aoc_2024_14_questions.txt ================================================ --- Day 14: Restroom Redoubt --- One of The Historians needs to use the bathroom; fortunately, you know there's a bathroom near an unvisited location on their list, and so you're all quickly teleported directly to the lobby of Easter Bunny Headquarters. Unfortunately, EBHQ seems to have "improved" bathroom security again after your last visit. The area outside the bathroom is swarming with robots! To get The Historian safely to the bathroom, you'll need a way to predict where the robots will be in the future. Fortunately, they all seem to be moving on the tile floor in predictable straight lines. You make a list (your puzzle input) of all of the robots' current positions (p) and velocities (v), one robot per line. For example: p=0,4 v=3,-3 p=6,3 v=-1,-3 p=10,3 v=-1,2 p=2,0 v=2,-1 p=0,0 v=1,3 p=3,0 v=-2,-2 p=7,6 v=-1,-3 p=3,0 v=-1,-2 p=9,3 v=2,3 p=7,3 v=-1,2 p=2,4 v=2,-3 p=9,5 v=-3,-3 Each robot's position is given as p=x,y where x represents the number of tiles the robot is from the left wall and y represents the number of tiles from the top wall (when viewed from above). So, a position of p=0,0 means the robot is all the way in the top-left corner. Each robot's velocity is given as v=x,y where x and y are given in tiles per second. Positive x means the robot is moving to the right, and positive y means the robot is moving down. So, a velocity of v=1,-2 means that each second, the robot moves 1 tile to the right and 2 tiles up. The robots outside the actual bathroom are in a space which is 101 tiles wide and 103 tiles tall (when viewed from above). However, in this example, the robots are in a space which is only 11 tiles wide and 7 tiles tall. The robots are good at navigating over/under each other (due to a combination of springs, extendable legs, and quadcopters), so they can share the same tile and don't interact with each other. Visually, the number of robots on each tile in this example looks like this: 1.12....... ........... ........... ......11.11 1.1........ .........1. .......1... These robots have a unique feature for maximum bathroom security: they can teleport. When a robot would run into an edge of the space they're in, they instead teleport to the other side, effectively wrapping around the edges. Here is what robot p=2,4 v=2,-3 does for the first few seconds: Initial state: ........... ........... ........... ........... ..1........ ........... ........... After 1 second: ........... ....1...... ........... ........... ........... ........... ........... After 2 seconds: ........... ........... ........... ........... ........... ......1.... ........... After 3 seconds: ........... ........... ........1.. ........... ........... ........... ........... After 4 seconds: ........... ........... ........... ........... ........... ........... ..........1 After 5 seconds: ........... ........... ........... .1......... ........... ........... ........... The Historian can't wait much longer, so you don't have to simulate the robots for very long. Where will the robots be after 100 seconds? In the above example, the number of robots on each tile after 100 seconds has elapsed looks like this: ......2..1. ........... 1.......... .11........ .....1..... ...12...... .1....1.... To determine the safest area, count the number of robots in each quadrant after 100 seconds. Robots that are exactly in the middle (horizontally or vertically) don't count as being in any quadrant, so the only relevant robots are: ..... 2..1. ..... ..... 1.... ..... ..... ..... ...12 ..... .1... 1.... In this example, the quadrants contain 1, 3, 4, and 1 robot. Multiplying these together gives a total safety factor of 12. Predict the motion of the robots in your list within a space which is 101 tiles wide and 103 tiles tall. What will the safety factor be after exactly 100 seconds have elapsed? --- Part Two --- During the bathroom break, someone notices that these robots seem awfully similar to ones built and used at the North Pole. If they're the same type of robots, they should have a hard-coded Easter egg: very rarely, most of the robots should arrange themselves into a picture of a Christmas tree. What is the fewest number of seconds that must elapse for the robots to display the Easter egg? ================================================ FILE: exm/aoc/2024/aoc_2024_15.adb ================================================ -- Solution to Advent of Code 2024, Day 15 ------------------------------------------- -- Warehouse Woes -- -- https://adventofcode.com/2024/day/15 -- Copy of questions in: aoc_2024_15_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_15 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"micro"; n : constant := 6; nx : constant := 12; nm : constant := 1; -- input_name : constant VString := +"mini0"; n : constant := 7; nx : constant := 14; nm : constant := 11; -- input_name : constant VString := +"mini1"; n : constant := 8; nx : constant := 16; nm : constant := 15; -- input_name : constant VString := +"mini2"; n : constant := 10; nx : constant := 20; nm : constant := 700; input_name : constant VString := +"aoc_2024_15"; n : constant := 50; nx : constant := 100; nm : constant := 20_000; map : array (1 .. n, 1 .. n) of Character; mapx : array (1 .. nx, 1 .. n) of Character; move : array (1 .. nm) of Direction; p0, p : Point; r : array (Part_Type) of Integer; procedure Read_Data is new_tile : String (1 .. 2); c : Character; f : File_Type; begin Open (f, input_name & ".txt"); for y in reverse 1 .. n loop for x in 1 .. n loop Get (f, c); if c = '@' then p0.x := x; p0.y := y; c := '.'; end if; map (x, y) := c; case c is when '#' => new_tile := "##"; when 'O' => new_tile := "[]"; when '.' => new_tile := ".."; when others => null; end case; mapx ((x - 1) * 2 + 1, y) := new_tile (1); mapx ((x - 1) * 2 + 2, y) := new_tile (2); end loop; end loop; Skip_Line (f); for i in 1 .. nm loop Get (f, c); case c is when '^' => move (i) := north; when 'v' => move (i) := south; when '>' => move (i) := east; when '<' => move (i) := west; when others => null; end case; end loop; Close (f); end Read_Data; procedure Show_Map is begin for y in reverse 1 .. n loop for x in 1 .. n loop if x = p.x and then y = p.y then Put ('@'); else Put (map (x, y)); end if; end loop; New_Line; end loop; New_Line; end Show_Map; verbose : constant Boolean := False; procedure Do_Part_1 is begin p := p0; for m in 1 .. nm loop case move (m) is when north => case map (p.x, p.y + 1) is when '.' => p.y := p.y + 1; when 'O' => for y in p.y + 2 .. n loop exit when map (p.x, y) = '#'; if map (p.x, y) = '.' then -- Push boxes North: for my in reverse p.y + 2 .. y loop map (p.x, my) := map (p.x, my - 1); end loop; map (p.x, p.y + 1) := '.'; p.y := p.y + 1; exit; end if; end loop; when others => null; end case; when south => case map (p.x, p.y - 1) is when '.' => p.y := p.y - 1; when 'O' => for y in reverse 1 .. p.y - 2 loop exit when map (p.x, y) = '#'; if map (p.x, y) = '.' then -- Push boxes South: for my in y .. p.y - 2 loop map (p.x, my) := map (p.x, my + 1); end loop; map (p.x, p.y - 1) := '.'; p.y := p.y - 1; exit; end if; end loop; when others => null; end case; when east => case map (p.x + 1, p.y) is when '.' => p.x := p.x + 1; when 'O' => for x in p.x + 2 .. n loop exit when map (x, p.y) = '#'; if map (x, p.y) = '.' then -- Push boxes East: for mx in reverse p.x + 2 .. x loop map (mx, p.y) := map (mx - 1, p.y); end loop; map (p.x + 1, p.y) := '.'; p.x := p.x + 1; exit; end if; end loop; when others => null; end case; when west => case map (p.x - 1, p.y) is when '.' => p.x := p.x - 1; when 'O' => for x in reverse 1 .. p.x - 2 loop exit when map (x, p.y) = '#'; if map (x, p.y) = '.' then -- Push boxes West: for mx in x .. p.x - 2 loop map (mx, p.y) := map (mx + 1, p.y); end loop; map (p.x - 1, p.y) := '.'; p.x := p.x - 1; exit; end if; end loop; when others => null; end case; end case; end loop; for y in 1 .. n loop for x in 1 .. n loop if map (x, y) = 'O' then r (part_1) := r (part_1) + 100 * (n - y) + (x - 1); end if; end loop; end loop; if verbose then Show_Map; end if; end Do_Part_1; procedure Show_Map_X is begin for y in reverse 1 .. n loop for x in 1 .. nx loop if x = p.x and then y = p.y then Put ('@'); else Put (mapx (x, y)); end if; end loop; New_Line; end loop; New_Line; end Show_Map_X; procedure Do_Part_2 is function Can_Move_Box (bx, by, dy : Integer) return Boolean is ok : Boolean := True; begin for dx in 0 .. 1 loop case mapx (bx + dx, by + dy) is when '#' => return False; when '[' => ok := ok and then Can_Move_Box (bx + dx, by + dy, dy); exit when dx = 0; when ']' => ok := ok and then Can_Move_Box (bx + dx - 1, by + dy, dy); when others => null; end case; end loop; return ok; end Can_Move_Box; procedure Move_Box (bx, by, dy : Integer) is begin if Can_Move_Box (bx, by, dy) then for dx in 0 .. 1 loop case mapx (bx + dx, by + dy) is when '#' => return; when '[' => Move_Box (bx + dx, by + dy, dy); exit when dx = 0; when ']' => Move_Box (bx + dx - 1, by + dy, dy); when others => null; end case; end loop; if mapx (bx, by + dy) = '.' and then mapx (bx + 1, by + dy) = '.' then mapx (bx, by + dy) := '['; mapx (bx + 1, by + dy) := ']'; mapx (bx, by) := '.'; mapx (bx + 1, by) := '.'; end if; end if; end Move_Box; begin p.x := (p0.x - 1) * 2 + 1; p.y := p0.y; if verbose then Show_Map_X; end if; for m in 1 .. nm loop if verbose then Put_Line (Direction'Image (move (m))); end if; case move (m) is when north => case mapx (p.x, p.y + 1) is when '[' => Move_Box (p.x, p.y + 1, 1); when ']' => Move_Box (p.x - 1, p.y + 1, 1); when others => null; end case; if mapx (p.x, p.y + 1) = '.' then p.y := p.y + 1; end if; when south => case mapx (p.x, p.y - 1) is when '[' => Move_Box (p.x, p.y - 1, -1); when ']' => Move_Box (p.x - 1, p.y - 1, -1); when others => null; end case; if mapx (p.x, p.y - 1) = '.' then p.y := p.y - 1; end if; -- On East-West it is just like Part 1 when east => case mapx (p.x + 1, p.y) is when '.' => p.x := p.x + 1; when '[' => for x in p.x + 2 .. nx loop exit when mapx (x, p.y) = '#'; if mapx (x, p.y) = '.' then for mx in reverse p.x + 2 .. x loop mapx (mx, p.y) := mapx (mx - 1, p.y); end loop; mapx (p.x + 1, p.y) := '.'; p.x := p.x + 1; exit; end if; end loop; when others => null; end case; when west => case mapx (p.x - 1, p.y) is when '.' => p.x := p.x - 1; when ']' => for x in reverse 1 .. p.x - 2 loop exit when mapx (x, p.y) = '#'; if mapx (x, p.y) = '.' then for mx in x .. p.x - 2 loop mapx (mx, p.y) := mapx (mx + 1, p.y); end loop; mapx (p.x - 1, p.y) := '.'; p.x := p.x - 1; exit; end if; end loop; when others => null; end case; end case; if verbose then Show_Map_X; end if; end loop; for y in 1 .. n loop for x in 1 .. nx loop if mapx (x, y) = '[' then r (part_2) := r (part_2) + 100 * (n - y) + (x - 1); end if; end loop; end loop; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin r (part_1) := 0; r (part_2) := 0; Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) or r (part_2) /= Integer_Value (Argument (2)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 1515788 -- Part 2: validated by AoC: 1516544 end if; end AoC_2024_15; ================================================ FILE: exm/aoc/2024/aoc_2024_15.txt ================================================ ################################################## #.O#..O#.....##.O.O.OO#..OO..OO.......O....O.O.O.# #.....O.#.....O.#..OO#....O#O..#OO#.#..#OO......O# #.....OO...#..O.O.........OOO#..O...#O...O.O...OO# #..OO....O.#...O.O...O....OO............O.OO..O..# #OO.OO...O#.OO....#....O.OO........OO.....#..O.#.# #OOO...#....OOO...OOO...O.O.....O..O...O..O.O.#..# #......O.#O.....#OO............OOO...OO....O.O...# ##....O...#.OO.##.O..O..#.#...#.O..#.....O..#....# #.O..#.#...O#..OO.OO.O..O..O.O.O...O#..OOOO......# #.............O.O...O..OO..#...O.O..O..O....O....# #.O#O.OO..O....O......OO.............O....O..O.#.# #....O....O.O..........O.##..O.OOO...##O.O.O.O.OO# ##...O...#......#.#..O..O..OO#O...#...OO..#OO.O.O# #.OO..OO.#.##.OO....O.O.#.OO...O.O.......O.#..OOO# #.O#OO#.O.O..OO.....O....OO.#O..O.#.....O..#.O...# #.OO........O.......O.O...O...O.O#......O.O..O...# #....O...O.OO..#...#.O.#..#..O.OOOOO.....O.#.O.#O# #.O...#O..#.#.#OO.O...O.##O.O......O.###.O.#O#...# #.#O...........O.........O...OO.OO#..O......O.OOO# ##.....#O..#....O.O...#O.#.O..OOO#......O.O......# #O.OO...O..O#....O#O.O....#....O.#.O....O..#.....# #........#.#....O.O.OOO......OO.#....#.....O...OO# #O...#.#O..O.OO..O...O.#..OOO.OO....#...O.....#..# #..O.....OO#O.O....#O..#@...#...#.O....OO....#.#.# #O.O.#......#O....OO.OO.OO.#..OO.#OO.........O...# #OOOO.##...#..#OO..O...O..O#O....#.OOO...##....O.# #.O............O...OO.#........OOO.....O.O..#..OO# #......O..OO.....OO.O.O...O....O.O.O.#........#..# #............O#.O.O....O.O.O.#OO.O.#....OOO.....O# #.O.#..........OOO...O..OOO...#.....O.........O..# ##OOO.O....#OOO.O...O....O..O...O.O#O.OO.O......## #OOO##.......OO...#.........OO..O....O..#......O.# #OOO....O.....O.#.O..O.#.......O....O.O..O.O.....# #.....O....O.OO....OO.OO..O.OOOO..#..O.O..O.O.O.O# #O..OOO#....#.#..OO.O.#..O#OOO.O...O.............# #OO......OOO..OO..O.O...##...#..#O..O....O.......# #...#..O.#O#.O..O....OO.O.....O#.O.....O..O..O..## #O....O..O.OO#.....O#O.#......OOOOOO.O.#OO...#O..# #OOO...#O.....OO#O..OOO#...#.........O....O..O...# #O.#.O.OOOO....O#O...O.....##.OO....O...O..O#.O..# #.OO.OO.......O..O.O.......OO.#OO..#OO..O.O..O.O.# ##O..............O..#O.....OO.......#O.#.#.O#....# ##...OO..#.O.......O..#.O...#..OO.O..O...#...O.O.# #..OO#....O.....O..O..O#...#.....O#...O...O..O.#.# #..O#..OOO.O.O.....OO....O#O...O.O#....OO........# #..#..O.O.....#...O#.O........O..O.OO.#O#..OO.O..# #...........O..O....OO..O.......O..O#....O...OO.O# #.O.O.O...OO......OO....O..OO.....OO#.O.O...OO.OO# ################################################## >>v>>^<><<><^v>v^<<>vv<<^<<>v<^<<>><>^><>v>>^^vvv^^^^>^<^v^<>vv><<>v^<^v<^<>^>>><>^<>>^v>v>>>vv>v^^^>vvv><^^>^vvv^^v<^>^v<^>><^<>v>><<<^>>v>^^>>vv><<^>^v^^^<>vvv^<^^>^^>v^vvvv>^>vv>v>^v>^^<>>v>>>^>^v>^^^v>vv^v^><^^^>>v<^<>v<^^<<>>v>v>^<<>>v^><^vvv<^<^>>>^>>>>^>><^v<>^>^<^<^><<<>v<<>vv^^v>v><>vv<><^^^vvv>^<>vvv>v^^vv^^<^>v>><<<^<^><^><<^>v<^>><>vv<<><>^<^>><^^^<<^^<^>^^><^vv>vvvvv<^v>>^vv>vv>^vvv^^v><<<>^vv><>^^<^v^>>>>v><>vv^<^^v^^vv<<>><>^v^^<^><>^>^^vvvv>>^^>^<v<v<>v<<<^<^<>>vv<<<^v<>vv>v><^><^^^^<<>vv>v^^^>>^>>v>v^v^<>>^<>v<^^v>^^vv^>v^v^<>>>>vv>><<^>^^^^v<^v>v^v><^>vv<>>>><>>vv<^^<<><^v<<^^>^>^>^v<<^v>v<<><><>v<><<><>^v>^v<><<^v>>^^<^^v^^vv>v>^>v>>v<^vv<>>><^><^^>v>><><>^>^<vv<<><>vvvv>^vv>><>^^v<><>>^vv^>v><>>>>><<>>v<<>vvv^^v>v^>v<>>>><^v>v^><><<< >v^^^><^<><>^>><>v<>vvv>v>>>v<>>vv>>^v>>v>^<^^v>>>^v^<><^<^<<>^<>>vv<^v>v<><^v>^vv>vv>^>>>v><<<<>vv<^>v<^^^<>^^vv<><<>^<^v<^<<<^>v^v^<^>>>vv^v>><^v^>v^<>><>vvv^<<<<>>v^v><<>>><>v>vvvvvv>^>vv^vvv<^v><v<<><^v^^<^v^v^><>v>><^^<>v<>v>><<^>><^v^>>^^>vv>v><><^>>^v>^>v<^^<<^>>^^^v<^^<>^^vvvv>^<>v>^>>v>v><><>>^<>^v^<><^v^v<>v<>>^v>><><<>v^><<>^>v<^<><^>^><^>v^>>v>v^<^vv<>><<v^<<^v><><^>v>^vv^>v>^v<>>^^<^<>^v>vvvv<^v^>>>vv>v<^^>v<<><^<<<>>v>>^<<^v>^vv>v<^^^vv>^<<^v<<^v^vv^v^vv><^<^>^^<^><>>v^^v^>>v<^^v>^>^<>^<>^>><>>^^^v<<^^<>vv^^v^<^>vv<><^^<>>>v<<<^<^<^v>v^^v>>^^><>>^v^^><vv^^vv<^<^v^^^^>vvvvv^<<>^^^^^v<^<^^<<>>^^<<<^v^>>><>^<>^<>^<>v<^^vvv><^^>vv<^v^^v>^<<^v^v<<>>^^v>^<>v>v^vv>v^^v^^v>^v<><v>>>>^^<<<><^>v^^>^v^v>v<<>v^>v<>>v^<><>v ^v<<>v^>^<<<^><>>^>v^v<^>><<^<^^^<<^v^vv<^<<><>><^v^>v>^v<<^v<>><>>>vv^>>v^>v>^>v^^<^^^>^><^<<^><^^^^<<^vvv>>^v^v^>>^>vv^^vv^<><^>>^^v>>>v>><<^v<^v^><>>^<>vv>>^^^v>^v^v<<<^^<^>^vv>>^><<^<^>v>^>^v^><>v><>>v<><>>^><^><<><>^^>^<<<>><^v^^^>^>^^>^<^>^><<>^^^>^^^v^><<^^v<>^v>>v>v^>^^>^>>v^><^^^^^<<<^>vvv^>v^^><<<^<^<>>>v^^^^<>^v^^>>v^v<<<<<v^>^^^<>vvvv>vv>>v<><>^v>^^vv><<^vv^<vvv<vv<>>^<>^^<<>>v^^^^<>>^<>>^<><^<<^^<^<>^>v<>v^v^>^<^vv>><>^<<><^<<>>^^^>vv>v^<^>v^v^>^^vv^^^>>^^<^<^v<v^^<>v<>><^^v<>^v^<>^v<^vv<^vv^<>^v<<v>>>^v<<^v^><^>v^v^vv<>v<^>^<^v^<v<^>v<^>vv^>^><<<<^vv^>>vv^><<>vvv>^v^vv>^>v<>^vv<<>v<^v>>v^^><>>^<<^>^<<^>vv<<>vv^<<>>v^^<<>><^<>>^^>^>^>v<^^>^vv^<<^>vvv^>vvv^<<^<^^><^v^^>^vvv^v>^<^<vv><^<>>^>>vvvv^>>>v<>^^^vvv<^v>^vvv<>^<^<>v>>v>>v>^<^^><>vv>v^<>>>^^<<>v^>>^v>^^^vv>^v^>>^v<>>>^<^v>><^>v^>^v<^v>>v^^^^v<>>^vvv<^^v^v<^^<<vv^<><^v<><>v><>^^v^<^<^>vv^><>vv>^>^v^<>>>v^<^v>vv<^>^^>v>>^vv>><^^<<>>^><>v<^^^>v<^>^vv<>>^^^<^v><><<<<>>v^<>>><^<^^v^<v>>vv>^<>^><^v<<^<>vv><>^^>><><<^>><<<<^^^^v>^^^>v^v<<><<>>v<^^>^^^><^^v>>^^>v>v<^^>^^^<^<^<^^vv>^^<<>>^v<<<<<^<><<>>^v^^<^<>>v>^><>v<<<<^<^v<>^<>v^^v><<^<<^>^vv^<<^^^^<<^><>^v>^<v<^v^v^>>^>>vv><><^^v^><>vv<^v<^>^v^>v<^<^^^^>^>><^^><>>v^><<^<><>^v>>^vvv^^v<>^<^<^<<^>^v><<><<<<<>v>v>^><>>><^>vv^v>v<>^v>^>^><< ^^^<^^>v><>^<<^v^^v>v><><<^^^^^<<^>v^>^^>^vv>^^><^>v>v><<^><^^v>^<<>>^^^v^>v^>v<<^>^>v<<>^>>>^>>^<<<>v<<<<<>><^<<^>^^v<^v<><v>^<<^v^^v^<<<^>>>v^v>^v>^<>vvvv><^<>v>^>vv<^v>>vv>^^>vv<^<^>>^^^><<^<^<<>^^^<^vv^^v>^>v<>v^>>v>vv>vvv^>^<^vv>^><<^v^><^vv><<^^v^>^>^v<^v^>>>v^v^^^^v><^<<<^^>><<^>v><>vvv^<^>^><>^vv>v^v^v<<^vvvv>v>v<<^vvv<>v^^<^v^v>^v^v>v<>>vvv<>^<>v>>v<<^^>vv>>^>^v><^<<>v>><<^>v>^^>v<<<>v<><^v>v<^<^v<>>>^vvv>^<>v>v>>^^^v<>^vvv>>vv<<^v>><^^>v<^v<>v><<>v^>^^<<^^>v^v>>v<><^<><^^><^^v^>>v>><>vv<v>>>^>>vv>^^v>><>>v><>^>>>^<v<v><<<>>v<>v^vv><^<>^v<><>v>vvv<><>>>><<<^<^v^v>^^v^>><<<>^v^><>><<<>^vv>^v>v>>>>^v^>>^^>>>^^>vv^v^<^v<>v>vv<>v><<>^^^^^vvv>>>^v^vv<<>>^^vvv^<<^>^^vv^>>v<^>^>>>vvv>v<^^vv<>^^>< <<<<>^^^<>><>^<^<><<^^<^><vv<>^<><^^^v^v^^v^>>>^^><^<<^v^v>^v^^<>^<^^v^>><<>^v<^>vv<><><>><^<>v^><^<<<<^^^v^^^>v^<>vv^^^^^>^>>v>vv<>v<^v>vv^>^vv<^<^^<^v>^>>v<<>v<<>v>^<v>>^^vv^<^vvvv^v^^<>^^>^v^v^^<^>^^><<<<^<><><^^<>^>>>>>><v<^^>>vv^^<^^v<<<<<><^^v^v<<>>v^v^><><>^<^^<^v^v<<>><<^^^>>^<<^v><>^>v>^>v>>^>>^v<<<^^>^>vv^<^<><>><>>>>>>><>^><>v>^><^^>>v^^>v><>>^vv<>v^<>>v^<><<<<^^vv<>^^^v><<^>>>>>><^>>^v^^<^v>v>v^>v<>^>^>^<^<>>^^v>^>^^<v^^>^vv<^>^v<<>>>^^>>>^<^^v^v>^>><>^>vv<^>^vv>^vv<^^>^^>vv^vv^^v^^v^^^v<^><^>>>v^<^><<^v>v><^<<<><^>^vvv<<<^^>>v^^>><>v>v^v>^v<>v^>^^v^<^>><>v><<<<^<>><<>>^<>>vvv>^v><><^>^^v<^vvvv<>>v<>^>v>^<>v<>^><^^vv>>^>^^<<>><^>v^><^^>>>v>>^<^vvv<>^>vv^>vv<^^>>^vv^>v^<^<^v>v<>^^v><<^^v^>><>>^^^v^>><^><><>v^<^>^<>vvvv<<^^>>>vv^>^vvvv<^<^v<><^vvvv>^>v<^^v^v<^<^^>v>v^<^><><^<^>^v<^v>^<^^^<<^><>>^v<^^<>><^>^<>^^>><^^v<^<<>><>^<<^v^v<^vv><^v^>v>><<<^v<^^^v<>><<>>v>>^^^^<^^<^^>v^^v<<<^v><^><>>v<>><^<>v^v^^^^><>^v^vvv<^^<>v<<>^vv>v<^^><<<<>><^><<>^^v^v>^>v<^v>v^v>>v>>^^>v^>><>>^^^^^<^>>^>^<<>^v^^v^v<^^v^v<^>>><>^v<^^>^vv>v<>^^v><<^^v^^^<>v<^>^^><>v<>^^<^<<<>v<>v^^^v<^>^<>^^v<>^v^^>^><^><>^>^^>vv<>v<<^^>>vv>vv^<>>>>><>v^^>>>>><^>>^v>v^>^^^<<^vv^>^vv>^<<<^v<>>^vv<^v>^^^v^^^vvv>^<^>v>v<v>>>><<>^^<>v<^v><^^v^^>^vvv^><^v<^>v><^v^v^v^v>>v<^v^<^<>><>^^^^v>v<^^v<^>v^v^v^^>v>^v>^v^>vvv<>^>>>>^v>^<>v^<^v>>^>^>>^vv^>^^v^><>v^v>>^^>><<>vv>^^^vvv>v>vv<>>^v^<^v<<^>^>vv^^>v<^<^>^^^v^^<^<<^^<>>v^^vv^v^v<<<<>>v^<>><>v<>^>v<>^vv^>v<v^><>^v<<<>v>vv^v>>v^>v^^<^^<vvv<>^v><^<<<>><<<>^vv^<<<>><>^<<><>>^^<>v^>^v^<><^^>v^^<>^<^<^^>vv><^^^v<<<<>^vv^v>vv<<^<^>>^>><><^>><<^<>v<>^v^>>v^>vv^<^v>>><>^<^>^^<<<>^^>^v>^vv^<<>v^>^^v^>^<>v<<<>v^v<<^^v><^>>^>^^<^^v>^v<<^^>v<^>v^^^<^>>^>>^v>vv>^v^^v<<<^>>^>>vv^<^^<>^<>v^vv^v<>^><^v<>v<^<^v<^vv><<<v>>>v><^v^^vv>vv>>v^<>^>^^><>>^<^>>v>v^>>><^^v^^^<<<^^v^>>^vv^^v<<^v^>vv^vv^><^^vv>><^>^^^<><^>v<>^v<>v^<<>^v>>><>v^v^>^><><<<>vv<^>^^>^^^^^^v^<>>>>v><>v<>v<^><<^>^^>^>><>v>v>^^<>^^>v^v>v>^<<>v>><<v>v>v^>^>>><>v^^^vv^vv>v^^vv><>>^v^^<>>vv>>><>>v^<>><>>^^^^><<^>>^v^v<>>^^vv^<><^^>^v<>^><>v^^^^>v<^^vv><<<>vvv^^<^<<>>^v^<^<<>v><<<<>^v>vvv>v>>vv>v><^>>^^^>^><^><><<><>^>v^>>>>>><^^vv<<v<>^>^< ^vv<>v<>^v>^^<^v<<>>^<v^<<^v>>^>^<>v<>^v>v>>>^><<^>>^>^v^><^vv^v<<^<<<>^^><<<>v>^<^<<<>>>>>>vv^<<^><^^>^v<<^vv<^vv^^^vv^<^v^v<>^v><^^^^^>><<^v<>^^v>v^>>^^>v>><^v<^<>>>v<<<^<>vv<^><><<>>><^v^<^>>>^>v^>^><^^^<^vv<>><v^v>vvv<^<>^v<^^^vv^^^<^v<<<>>>>vv^^^vv><^>v^^<^<<<^>v<>^<<<<^>><>^><<>^v^<<^^<^<^^v^>><<^>>>vv^vv>>v>>v<vv^<^>v>v^>^>>^^v>>v<><>>v><>^vv<^^^>><>v>vvv^>^>>><<^^<^^>v<<>>>>^v><><<<><^^v>v^<><<^vv^>v>vvv<^>>>^>>^^>>>>v^>vv^^^^^>^^<<^v>v<<<^<<^<>^><^>><>>><>>>^<^^^vv^>>^<><^vv<<<^v>^^v^>^^>>v>>>^><>v><^<>>><<^vv<^^<^^^vv><>v^^v>^<<>>vvv^>>^v>><<<>^<>^^<<>v<^><^^>^<<<^<<^^vvvv^^>^^^<>^v<><^v<^>vv>>v>v^^<>v^v^>^^><>^vv>^vvv<<>v^^<>vv^v<^v^><^>>>vvv^><^<^^><^v>^<>v>vv^>vvv<^>v^v>>v^v>^^^<>v^vvv^>^> <><>^>^v<^vv^>^<<>^^><>v>^v>^>^^<>v<>^<><><^v>>v>vv><^<>>^^^>>>>v^vv^v^><>v<^vvv><^v><<^vv^^>>>v>vv^>v<^v>vv^^v<^v>v^^vv^v^^^^>v<^>>>><>^^^v^<^v^^^>v>v>>^v^^<^><^^<<^>v<^v><>><><<>>v<^^<<^vv<>>^^^>><>>^<<>v^>>^<>>>v^^^v>><>vv^><^<^vv<>v>^v^v^v<<>v<^v><^^^v>v^<<><^v>^^vvv^>>^>v^^vv>^vv^>>>><^>v<<^v><<>^v>v>v>>vvvvv<^<>>vvv>>>^<^<^^^<^<>^>>>vv^<^>>><><^v<>v>><<<<>^<>v^>>^v^<<<^v^v<^v>>^<>^><<>^v<<<>vvv^v><^vvvv<><>>^^>>>v<^>^^v><v><^^^>v<>^v^><<^^<^^>>>^v<^^^>v>^>v^^v>vv^v><>v^><<<^^v^v>v>>><^<^v<^v<^^^v<>v>^^<<^<<^>>><>>>>>v>v>^^^^>^^>>^><>^<<^<><><<>>^^<<<^^>^v^^v<^v^>>>^><^><>v<>v<<<^><>v^<^^^v^vvv>v^>><>>vvv<<<>vv^>>vv<^><^^v<<>v>>v<>v<><^<><<>^v>>^^v<^><>><>v^<>>v<<^^<<>^><>vv<^<>^v^<v><^<^<>>^<>><<^^v<<< >^<>^^>>>^vv^^^v<>^<^^<^<>v^>>>v>>v^^>^^^<><^v^<>v>>^vv^^>>>^^^<<^<>>><>^>>^^v^v>>v>>><>^v<>^^^>^^><>v^^vvvvv>>^v<^<<^<>^^vvv^^v>v<>^><^^v<<<>^>^^^vv^<^^^vv<>^v<>v>^<><^^^>v>vvv^^^>^^>v<^>^<^>v><>v<^vv>^v^<>>>>v<v>^<<^>^>><<<<<><<v>^>v>>^^<<><^v><^v>v<>v<<^><^>^v^<^^^v><>v<<<>^^^><<><^^>^>>^>vv<^><^>^^<^^v>vvv^v>^^>>^v^v^>^^^>^^>vv^<<<<>>^<^><^>v<^>v><^<>^<>v^v>^<^<>v>>vv><>v<>v^^^vv<<^<<<>>vv>^>>vv^^v>v<^^><^><>^>^<^^>>^>v<v<<><>>^v^vv<^v>v><>vv>^><<>^>>v<>v^><><^^<>>><^<<^>v>^v>v>^^v<>>v>>^><>>v>>^<<<^^^<^^>v^^<^>^><>vv>><>^v<v><>^v><<^^vv<^>^^>^^>^v>>><>^vv><<>>v><>>v><>vv<<<><>^vv^^v<<><^>v^>v<^^>vv<^vv<^<<^<>>v>^<<<^>^v>^vv^vvv^^<<^^v^>^<^^<>^>^^>><^^> v^^>v<vvvv<>^>^<><^^<>v^>^v<^v^>>>>>>^<><><^^^<>vv^vv>^<<>^^>^v^^v^><>v<<^<>>>v<<^>>>>^<>>><>>><v<>>v>^^v><^<><v^>vv>vvv>>^vv><<<<<^>^v>^<^>v^v^>^^>^vv^v>vv^^^<<v<v>^v<>^v^>^<<>>v<>>v>^><vvv^v>><>^^<<>v^^><<^<>^>>^<>>>^<^>>v^>^^^v>v^<>><>>><^vv^v^><^<<^>v^^>^<>>^vv><>^v^^<><>v>v>^v<^<^^v>><>>><<<>v>>^vv^v<>^<<^^v>v>v>v>>>>v><>^v<>>v<<<<><<^<>vv^vv<>>vvv^>^^vv^v>v^<^<>>^<^v><<^<>>v><>^v<^vv<><^^>>v^>v<<>>v>^<^>vv^>>^vv<>v<^v<<^v<<>^^^^vv^^^v><>^v>^><<>>v><><>v><>>v^^>>>>>^v>^>^v<>v><^>vvv>>v^>^^>><^^v>^vv<^><<>^v><>>><><>^><>^vv<>^v^<^^<<><>v><>v^<^^>><<>>vvv>^v^>^<^v<^v<<>>^<>vv^>v^<^>>^>^vv<>>>v<<^^^<>^<><><><>^^v^>>v<^^<<^vv>^^><^^<>^<^^>><<<><^><^<<>^v>^<><<^^^>^^<>v^<^^>^v<^^>v> ><>>v<<<^<^v^vvvvv^<^<>>v^>^>^^v><>v^><^^v^v<>><<>v^>v<^vv^<>>>v<^^v<^v^v<<^v><>^>v>>v<^^>>v<^><><^<^<<^^vv^<^^<>^>>>^^v<<>^>v^vv^>><>^<><<^<^<>v>v^>v^v<^<<<^<<><^v>^<>^>>>v^v>^<<>^>>v>v>^<^v<>vvv^<>>>^^vv>^^>^v><<<<^<>^>^>>>>>^^>^<<^v>^<<<^v>><><^>v>>^<^<^>>>><^vv>>vv^v^^>>^^^><^<^^^>><<<<>><^<^v^v^vv<<>v><>^^>>><^^v^><^v^v^>>^^vv^^vv><>vv>^v><>v^>vv^>vv>^v<>>^><>>^>vvv^<>>^v<^>^vv^^v><<>^>v>^^<><^>>^><v>^^vv^>v<<<<<^^>^><>vv><^>>>^>^v><<<>v^<^^<<>><^^<^<^>^v>^><><^>^^^>v<v<^^v^vv<<<<^v>vv>v^<<^>><>>><^>>><^^<>v^^<>>><>vv^>>vvv><><<><^^>v>^>v>>^><<^v<^<<><^<^<^v^v<^^<<^<>^<<<^vv><>>^^<^^^^^vv>>vv^>v><>^v>vv^^>>>v>v^v^^^><>^>v>vvv^>^vv>^v<^^^^>^v<^v<<^><^^^v^v^v^<^><<^>><>>>>>>v^>^>vv><^^>^vv>v^^v^<<^<^<<^ v^><<>vv^vv^v<<^^v>^>>^>^>vvvv>>v<^<<><<>><<<<^^^v>v>vvv<^<><><^>^v^><^^^^^v>>v^^vv^^><^<^<<<>>><>^>>^<^^^>^^v^^v^>>^>vv<<>^^v>>v^v>>v<>v<^v<<^v<^>v>v>vv^>^^<<>^^^v<<^>>><<^v<<^^<<<^>v>>v>^^v^^v^^v>^^<<^><<v><<>>vv<^^<^^v^^v^^<<<<<>^^<>>v><>^vv<>v^v^<<<^^>v>vv^v^<<^^^^v><^^^<<>^^<><^^v^^v<^v>v<<<><^<^>vv<<<^>vv><^vv<<>^<^<<>^vv>v>>^><^v^vv<^v<<^><<^^<^^<>>>^^^vv^<><^^v<^>v^v^><<>^v>^>v^^v^^>vvvv>v>^v>>^<>^^<>>vv^^<v^<^vv^^<^>>^^>vv>^<>v<>vv>v<^^vv^<v>>v<>^><>^v>v<<<<<<^v^^<^>^^<^<>v<^^v>^vv^>>>>^v>^<<>vvv>v<^^<><<>vv^><^v^v>^^^>v>vv>><><>^v>v<<>^vv<><^^<>v<^>>^v>v^v>^v^^<>v^^v>^^v^vv<>v<<>>^vv^>^^v<^^>v<>^^^v<^^<^><><>^>v>v>^^<^<^vvvv^^v<^^><<<^>^v<<v^>^v>>v^><^<>><^vv<^>>^>^^^^v^^v^vvv>v>>^<<>^<v><>^>^<^<>>v<>v^^><><< ^^>>v^v>^^^>^vv<<^^^><<>v<<^>>>v>vv><>>^v^v>v<<^<^vvv>>v<<^v<>>>vv^v>><>><>^v>v>^>>^^^^><<><^vvv^>>^>><^^<<^<<<>^vvv>><<<>^><^^>^<>>^>>>>^^v<>>^^^v>>vv<>>>>^><^v^<^^^vvvvv^v^^><<^v>vvv^^>>>^<<>^<>^^v^^>>^>>v>^>>^^^v<^<>^^vv>>v^v>^^^>v<<^v>^<>v>^>^vvv>v^<^<^<>><v^><<<^<^^^v^<<^>vv^<<^<^>>>^v>>vv<><^>>>>^v<<>vv><^v<^v<>>v>v><^v<^v<><><^v>^><>^^^<^^vv<<<>^>>>v^<>vvv<>^vv>><^<^>^v<^<>v>><^^>>v><<^^>>>>^>^^^^<^v^^<vvv<>v>>^v>>>^>v^v^^>><<>>^^^vv^^>v>v^v^>>v<<^v>v>v>^<<>^vv>^vv<^vv^^>>><><>>v^^>vv^^<<<><^v>v<^^^^>>v<^>v<>^>^^vv^v^vv>^^>vv>>>^^^^>>v>>v>^>^^<^^^<>v<><^v^^v^vv^>v^v^><>v>v^v<^^v^>v><<^<>v^v>>^^v<>^v>vv^v^>v<><^^>>^<^><^^>^>^>>v^^<<>^><>^<^>><<>^<<>>v^^vv>>^^<<>^>>>>>^<<><^>v<><>v^><<<><>v<>v>><>><^<>^^^><^^v^^>^^v>>^^>>v^><^>>^^vv^^<^><^ >>v>^^<<><^^<>><^<>^v^v<^v>v><>>>^^vv><^vv>v^>^<^^<^<<^vv^v^<<^^<>>^<>^^^>><<^<>vv^>>>>v>v^>>>^v^vv><^^v^v^<^v>>^<><>>^v>v<<^v^vvvvvv<><<<^>^<<>^<<>>v<<><v^>v<<<vv>><^>v<^>vvv<>^^^>>^vv^vv^v<<<>v^^^^^v>v<^^>^<>>^v^v^>v<<<>v^>>v>>^vv^^<>>v<<<^v<>^>^<^>v>>^^^^><<<>v<><<^<>v>vvvvv^>>v>>v>v>vv<^v<<^>vv>vv<<>v>>>><^><>vv>v^<^>vvv><>>v><<>^>^>>>>>^vv^<^<><>>>^v^>>v^<<^^^<>v<^>^>>^^<>^^>vv><^^^^><<>v><>vv<^<^<><^>v^v^>v<>>v>^>v^v^<<^>v<<<>vv^<^<>><^v^^>vv<>>^<>^^^^>>v^<<<><^^v>^^<<>^<>>v>^^<>v<<<^^^>vv>^<^>v<><^>>^<v>v>>>>v>v^>>v<>>><^^>^v<><v><v<>vv^>^>v<<^^^<<>^>^^v>v<>>v^>><>^<>^>^>v>v<>>>^>v><<^^>vvvv>v>^v<>><<><^<<><<>^v>><^v^vvv>^vvv^v^v>^vvv^><^v^v><^>v<^<<^vvv^^>^ ^<^^v<><v^>^^<>^^>^v><<><<><^<><^<^<^><^^v<><>^v^^>v<>vv^v<^>^vv^v><^<>v^<>>>^>><<<><^^<><>^^><<^^v>>vv^>^v><^^<>^v^>>^><^v^<<><<^^v>v<>v<^<>^v^><<<<><^><<<v<>^v<<^>^>v>v^><^>>vv>vv<^^v<>^>><>>>vv^^v^>vv^v>^<<<<^^><><^>^v>^<>^vv>vv^>^^v>^^>^<<^^^^>v^><^^^>>^<>>>><^<^<>>v^vv<^<><^^v^<^v<>v<^^^>v^vv^^v>><^<^>v<^>^^^^>vv^v<^>^vv>^v>>><>><>^v^^vv^>><<>^v^>vv<<>><<>vvv<<<<^><><^v><vv>v<^^>v^>v^v^v^<>^v><<>vv^v><>vv>v>>v^>vvv>vv>^^<^v^^v^^<>>>v<><>v>v>v^v^><<^>^^^^^><><^>^v^^vv^>^^<<^>vv^^<^<<>^v^v<<^<>^v>^<<<>v>>^^<>>>^>^^v^v^^<><>>^<<>v>>^^>v>^>^v<^^<>^^<<<^<<>>^^>><^^v^vv>>^vvv><^v<>>^^v>vvv>v>>>v^>^><vv>vv<<^v<<>v>>>^v^<v>>^vv>^v>^><^vv<^vv^<^>^<>^^^v^vvv>vv^^v>>^>vv>v^^ <><^v^^^><>>vv><><>><<>^^>^<^v^>^>^><^<^vv>>v<^^>v<<<<<^^^<^v>><>^>>>vv^^>v^v^^v>>><<<<>^>>^<<>v<v^v>v^<<<^>><^>^v><^<^^<>^<^>><><<^^<^vv>^^>>>v^<^>>v<^^<>^<>>vvvv><v>^>^<^<^<<><^^v^>>v><^<^>^v><^>>^v>^<^>^>^<<v>^^<<<>><<^^v>><^><<^v<^><<<<>v<>v^^<^^vv^>^v>^v>>>>^<^<>^<>>>v<^<<^^v>><><<^<>^^v>>^>^^>vv<<^>>v<^>><vv>^^>v<^^>>^><^v<^v^v<^^v^v^<><><^<v<><^^<<<>v>^v^<v>^v<<^>^^vv>^>>>v<><<>><>>^>v^><<<v^>^>vv^<<^>>^<>vv^>^>><<>^^^^<>^^<^>>^^^v^vv<>><>>^^>^vv<>>><><>>>^>>vv^v^<^>>>v^^v<^vv^<^<^<>^^v>>>^<><>>>^<>vv^^>^v>>>v>>v>>>v^>>>^<^^<>>>^>^>>>>>^>>^vv^^^<>>v<>vv>v^^>^v>><<>v^^^<><^v^>>v^<><>>>v>>vvvvvvv^v>>>^^^>>^^>>^^>v><<^>v<><<<^^>>v>^vv^^^v<<^^>^>^>^^^^v>><^><<^v<>>>>v<>v<^v<<<>>vv^>><<><^<^^v^^>v>^v><>v>^<<<^> <>^^>>^v>vv^v^<>>^>^v>^>v^<>>^<^v><^<>v^>>>^^^><<>v>^<^^<<<>>^^^^>^>^<<^^<<^>^<<<^v>>>^^v<>vvv>v>^v><>>>vv^v<>^>^vv^>^^vvvv^v^>>v^<<^v^^><^><>>v^v>^^^^^v<>v<<^>vv>^>><<<^^><>>v^vv><><<^>vv^v<<^>^>^<^v><>^^<<^<^^v<>>^^vv>vv<><^>v>v>v^>v>^>^<<><^v^^v<v^v<>v^<<^<^<^^v>>><>^v^>^^<>v<^^v><^vvv>>v>^v>^^v<>v^v><^<>v<>>v>>v^v^v<<><^>>>>^v^^^vv^v>^^<^^>^v>v^>v<<>^vvvv<^<^v^v>^^>^v<<>^>^>^^>^>vvv^v>>vv<^<><>>v^^>^v<<>>v>>>vv>><<>v<<^>>>>v<<vv<^vv>^>v<>>^><>v^<^<^^v^^>v^^>><<<>>>^^v>^^^^^^<>v^<>>^<^v<^>>^v>v^^<><>><><>^<<>^><^^><^^vvv^^^><^<<<^^>v<<^v<^<^vv^v^><>>>>^v^vvvv<>v<>^^^v>^^<><v>>vv<>v<<^^>vvvv^<<>v^^^^^vv^^vv<>><>v<^v^>>^v>^vv<>v><>vv>v<v>><^vv^vv>>>^^^<^v>^vv^vv^>v<<v<^v>^vv<v^v>^v^<><^ ^^>vv<^^vv>^>^^><><>><><<^vv><<><>>^<>>^^vvv^>>>^^vvv^>><<>>^><^<<>^<<^>v^v>v>><^^>vv>v^><^>>vv>^vv<>v^>>^<>>^^>>^><<<^>>v<>^>^>>vv^<<^^v^v^v^<>^^>^><<>>><<^v^v^>><>^v^>v<>>>^v>vv^>><v>v<>^^^v>>^^>^>><<^<^v<^<v><>>vv>^v^^^^>v<>^vv^v>^^v<><<>^<^<<v><^^><>v^^>v<><v>^>v>v>vvv<><<<^>v<<<<<>>vv>vv^v<<<<<>^>^>^><^v>>^^<<<<<^v^vv><^v^vv>^^vv<<^v>v^^>v^v><^<<>^^^^<>v^><^>><^^>>^^^>v<>^v>^v>>^v<^>>>^>><<^<^v>>v^v<>>>^>>^>>^>>>>>^>^>v><<^<<>><<v<>>^^<><v^><^>v<<^<>vv^><<^v<<<>vv><>v>>v<^>^<^^<<^<^vvv^<^<><^>v<^<<>>v<<^>>>>^<>^v^<<^<^v>^><>>>^v>vv^^>><><^><<<^>^<>><>vv^><^<>>v<<^>vv>^v><<^^vv<<>>>v>v<^>v<<^><<^>v><^>v>v>vv<^>v>^>v<>>><^>vv^>^>><>^^v>>^>^>vv^<<>^^vvv><>>^>^<>>><^>^^vv<^v>>><^v<>>^>^^^^>^v<>v>>v>v>>vv<>vvv>>v<>v<<^ ================================================ FILE: exm/aoc/2024/aoc_2024_15_questions.txt ================================================ --- Day 15: Warehouse Woes --- You appear back inside your own mini submarine! Each Historian drives their mini submarine in a different direction; maybe the Chief has his own submarine down here somewhere as well? You look up to see a vast school of lanternfish swimming past you. On closer inspection, they seem quite anxious, so you drive your mini submarine over to see if you can help. Because lanternfish populations grow rapidly, they need a lot of food, and that food needs to be stored somewhere. That's why these lanternfish have built elaborate warehouse complexes operated by robots! These lanternfish seem so anxious because they have lost control of the robot that operates one of their most important warehouses! It is currently running amok, pushing around boxes in the warehouse with no regard for lanternfish logistics or lanternfish inventory management strategies. Right now, none of the lanternfish are brave enough to swim up to an unpredictable robot so they could shut it off. However, if you could anticipate the robot's movements, maybe they could find a safe option. The lanternfish already have a map of the warehouse and a list of movements the robot will attempt to make (your puzzle input). The problem is that the movements will sometimes fail as boxes are shifted around, making the actual movements of the robot difficult to predict. For example: ########## #..O..O.O# #......O.# #.OO..O.O# #..O@..O.# #O#..O...# #O..O..O.# #.OO.O.OO# #....O...# ########## ^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^ vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv< <>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ ^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^>< ^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ <><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> ^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<>< v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^ As the robot (@) attempts to move, if there are any boxes (O) in the way, the robot will also attempt to push those boxes. However, if this action would cause the robot or a box to move into a wall (#), nothing moves instead, including the robot. The initial positions of these are shown on the map at the top of the document the lanternfish gave you. The rest of the document describes the moves (^ for up, v for down, < for left, > for right) that the robot will attempt to make, in order. (The moves form a single giant sequence; they are broken into multiple lines just to make copy-pasting easier. Newlines within the move sequence should be ignored.) Here is a smaller example to get started: ######## #..O.O.# ##@.O..# #...O..# #.#.O..# #...O..# #......# ######## <^^>>>vv>v<< Were the robot to attempt the given sequence of moves, it would push around the boxes as follows: Initial state: ######## #..O.O.# ##@.O..# #...O..# #.#.O..# #...O..# #......# ######## Move <: ######## #..O.O.# ##@.O..# #...O..# #.#.O..# #...O..# #......# ######## Move ^: ######## #.@O.O.# ##..O..# #...O..# #.#.O..# #...O..# #......# ######## Move ^: ######## #.@O.O.# ##..O..# #...O..# #.#.O..# #...O..# #......# ######## Move >: ######## #..@OO.# ##..O..# #...O..# #.#.O..# #...O..# #......# ######## Move >: ######## #...@OO# ##..O..# #...O..# #.#.O..# #...O..# #......# ######## Move >: ######## #...@OO# ##..O..# #...O..# #.#.O..# #...O..# #......# ######## Move v: ######## #....OO# ##..@..# #...O..# #.#.O..# #...O..# #...O..# ######## Move v: ######## #....OO# ##..@..# #...O..# #.#.O..# #...O..# #...O..# ######## Move <: ######## #....OO# ##.@...# #...O..# #.#.O..# #...O..# #...O..# ######## Move v: ######## #....OO# ##.....# #..@O..# #.#.O..# #...O..# #...O..# ######## Move >: ######## #....OO# ##.....# #...@O.# #.#.O..# #...O..# #...O..# ######## Move >: ######## #....OO# ##.....# #....@O# #.#.O..# #...O..# #...O..# ######## Move v: ######## #....OO# ##.....# #.....O# #.#.O@.# #...O..# #...O..# ######## Move <: ######## #....OO# ##.....# #.....O# #.#O@..# #...O..# #...O..# ######## Move <: ######## #....OO# ##.....# #.....O# #.#O@..# #...O..# #...O..# ######## The larger example has many more moves; after the robot has finished those moves, the warehouse would look like this: ########## #.O.O.OOO# #........# #OO......# #OO@.....# #O#.....O# #O.....OO# #O.....OO# #OO....OO# ########## The lanternfish use their own custom Goods Positioning System (GPS for short) to track the locations of the boxes. The GPS coordinate of a box is equal to 100 times its distance from the top edge of the map plus its distance from the left edge of the map. (This process does not stop at wall tiles; measure all the way to the edges of the map.) So, the box shown below has a distance of 1 from the top edge of the map and 4 from the left edge of the map, resulting in a GPS coordinate of 100 * 1 + 4 = 104. ####### #...O.. #...... The lanternfish would like to know the sum of all boxes' GPS coordinates after the robot finishes moving. In the larger example, the sum of all boxes' GPS coordinates is 10092. In the smaller example, the sum is 2028. Predict the motion of the robot and boxes in the warehouse. After the robot is finished moving, what is the sum of all boxes' GPS coordinates? --- Part Two --- The lanternfish use your information to find a safe moment to swim in and turn off the malfunctioning robot! Just as they start preparing a festival in your honor, reports start coming in that a second warehouse's robot is also malfunctioning. This warehouse's layout is surprisingly similar to the one you just helped. There is one key difference: everything except the robot is twice as wide! The robot's list of movements doesn't change. To get the wider warehouse's map, start with your original map and, for each tile, make the following changes: If the tile is #, the new map contains ## instead. If the tile is O, the new map contains [] instead. If the tile is ., the new map contains .. instead. If the tile is @, the new map contains @. instead. This will produce a new warehouse map which is twice as wide and with wide boxes that are represented by []. (The robot does not change size.) The larger example from before would now look like this: #################### ##....[]....[]..[]## ##............[]..## ##..[][]....[]..[]## ##....[]@.....[]..## ##[]##....[]......## ##[]....[]....[]..## ##..[][]..[]..[][]## ##........[]......## #################### Because boxes are now twice as wide but the robot is still the same size and speed, boxes can be aligned such that they directly push two other boxes at once. For example, consider this situation: ####### #...#.# #.....# #..OO@# #..O..# #.....# ####### s.x := x; s.y := y; c := '.'; when 'E' => e.x := x; e.y := y; c := '.'; when others => null; end case; map (x, y) := c; end loop; end loop; Close (f); end Read_Data; -- Dijkstra shortest path algorithm. -- Code adapted from AoC_2023_17. -- -- The following definitions belong to the Dijkstra algorithm, but -- we keep them less local because of the path tracking. list_length_max : constant := 500_000; subtype List_Range is Integer range 1 .. list_length_max; type State_Type is record pt : Point; dir : Direction; end record; type Node is record len : Natural; state : State_Type; pred : Natural; -- This is for backtracking the path. end record; list : array (List_Range) of Node; current, explored : Natural; -- 0 <= current <= explored best : array (1 .. n, 1 .. n, Direction) of Natural; inf : constant Natural := Integer'Last / 4; function Dijkstra_Algorithm (start, finish : Point) return Natural is cur_len : Natural; cur_s : State_Type; s : State_Type; -- Test state derived from current state. procedure Visit (dir : Direction) is len_to, ins : Integer; vec : Point; new_node : Node; begin if dir = Opposite (cur_s.dir) then -- Turns must be 90 degrees. return; end if; vec.x := 0; vec.y := 0; -- Move (otherwise, turn without moving): if cur_s.dir = dir then case dir is when north => vec.y := +1; when east => vec.x := +1; when south => vec.y := -1; when west => vec.x := -1; end case; end if; s.pt.x := cur_s.pt.x + vec.x; if s.pt.x in 1 .. n then s.pt.y := cur_s.pt.y + vec.y; if s.pt.y in 1 .. n then if map (s.pt.x, s.pt.y) /= '.' then return; end if; if cur_s.dir = dir then len_to := cur_len + 1; -- Cost for a move. else len_to := cur_len + 1000; -- Cost for a turn. end if; if len_to < best (s.pt.x, s.pt.y, dir) then s.dir := dir; -- Found a better path to target state s. best (s.pt.x, s.pt.y, dir) := len_to; -- -- Insert in a sorted way. -- ins := explored + 1; for i in current + 1 .. explored loop if len_to < list (i).len then ins := i; -- Insert here. -- Optional: remove another node -- with the same state and a larger length. exit; end if; end loop; for i in reverse ins .. explored loop list (i + 1) := list (i); end loop; new_node.len := len_to; new_node.state := s; new_node.pred := current; list (ins) := new_node; explored := explored + 1; end if; end if; end if; end Visit; begin current := 0; explored := 0; for x in 1 .. n loop for y in 1 .. n loop for d in Direction loop best (x, y, d) := inf; end loop; end loop; end loop; cur_s.pt := start; cur_s.dir := east; cur_len := 0; loop for d in Direction loop Visit (d); end loop; -- -- Switch to the next best explored point. -- current := current + 1; if current > explored then -- Put_Line ("No way found."); return inf; end if; cur_s := list (current).state; exit when cur_s.pt.x = finish.x and then cur_s.pt.y = finish.y; cur_len := best (cur_s.pt.x, cur_s.pt.y, cur_s.dir); end loop; return best (cur_s.pt.x, cur_s.pt.y, cur_s.dir); end Dijkstra_Algorithm; procedure Do_Part_1 is begin r (part_1) := Dijkstra_Algorithm (s, e); end Do_Part_1; procedure Show_Map is begin for y in reverse 1 .. n loop for x in 1 .. n loop if x = s.x and then y = s.y then Put ('S'); elsif x = e.x and then y = e.y then Put ('E'); else Put (map (x, y)); end if; end loop; New_Line; end loop; New_Line; end Show_Map; seat : array (1 .. n, 1 .. n) of Integer; -- PPM picture output, adapted from AoC_2023_10. -- procedure Dump_PPM is d : File_Type; f : constant := 50; c : Integer; begin Create (d, input_name & ".ppm"); Put (d, "P6" & Chr (10)); Put (d, n); Put (d, ' '); Put (d, n); Put (d, Chr (10)); Put (d, "255" & Chr (10)); for y in reverse 1 .. n loop for x in 1 .. n loop if x = s.x and then y = s.y then -- Start. Put (d, Chr (255)); Put (d, Chr (100)); Put (d, Chr (100)); elsif x = e.x and then y = e.y then -- End. Put (d, Chr (100)); Put (d, Chr (255)); Put (d, Chr (100)); elsif seat (x, y) >= 0 then -- One of the optimal paths. -- We try to given distinctive colours... c := f * seat (x, y); Put (d, Chr (255 - c)); Put (d, Chr (255 - c / 2)); Put (d, Chr (c / 2)); elsif map (x, y) = '.' then -- Path, not optimal. Put (d, Chr (44)); Put (d, Chr (44)); Put (d, Chr (44)); else -- Wall. Put (d, Chr (1)); Put (d, Chr (1)); Put (d, Chr (1)); end if; end loop; end loop; Close (d); end Dump_PPM; verbose : constant Boolean := False; -- For part 2 you have to find all optimal paths. -- The method below is certainly far from being the most efficient -- but at least maybe you will understand it ;-) ... -- procedure Do_Part_2 is opt : constant Integer := r (part_1); blocks_added : Natural := 0; procedure Search_Alternatives is path : array (1 .. 20_000) of Point; last : Natural := 0; block : Point; procedure Record_Optimal_Path is -- We record the optimal path found by latest -- run of Dijkstra's algorithm. i : Integer := current; begin last := 0; while i /= 0 loop if i = current or else not (list (i).state.pt.x = path (last).x and then list (i).state.pt.y = path (last).y) then last := last + 1; path (last) := list (i).state.pt; -- Mark the seats: seat (path (last).x, path (last).y) := blocks_added; end if; i := list (i).pred; end loop; end Record_Optimal_Path; alternative_found : Boolean; begin loop Record_Optimal_Path; alternative_found := False; for i in 2 .. last - 1 loop block := path (i); -- Put a road block on the optimal way, step #i, and see what happens. map (block.x, block.y) := 'B'; if Dijkstra_Algorithm (s, e) = opt then -- There is another optimal path despite the road block. alternative_found := True; blocks_added := blocks_added + 1; exit; else -- The road block worsens the optimal path. Remove it. map (block.x, block.y) := '.'; end if; end loop; exit when not alternative_found; end loop; end Search_Alternatives; begin for x in 1 .. n loop for y in 1 .. n loop seat (x, y) := -1; end loop; end loop; Search_Alternatives; r (part_2) := 0; for x in 1 .. n loop for y in 1 .. n loop if seat (x, y) >= 0 then r (part_2) := r (part_2) + 1; end if; end loop; end loop; if verbose then Show_Map; Dump_PPM; Put_Line (+"Total road blocks added: " & blocks_added); end if; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; if not compiler_test_mode then Do_Part_2; end if; if compiler_test_mode then if r (part_1) /= Integer_Value (Argument (1)) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 74392 -- Part 2: validated by AoC: 426 end if; end AoC_2024_16; ================================================ FILE: exm/aoc/2024/aoc_2024_16.txt ================================================ ############################################################################################################################################# #.......#.....#.....#.........#...........#.....#.............#.......#.#.....#.......#...#.....#.....#.......#.....#.......#.........#....E# #.#.###.###.#.#.###.#####.#.###.#.#.#######.###.#.###.#.#######.#.###.#.#.###.#.#.###.#.#.#.#.#.#.###.#.#.#####.###.#.#.###.#.###.#####.#.### #.#...#.....#.....................#.#.....#.#...#.....#.#...........#...#...#...#...#.#.#...#.#.#.....#.#.......#...#.....#.#.#.#.......#...# #####.###########.#####.#####.#.#.###.###.#.#.#.###.#.#.#.#########.#######.#######.#.#######.#.#.#.###.#########.#####.#.#.#.#.#.#####.#.#.# #.....#.....#...#.....#.#...#.#.#.....#.#.....#.#...#...#.....#...#.......#.#.....#.#.........#...#.#...#.#.......#...#...#.#...#.......#...# #.#########.#.#.#.#.###.#.#.#.#.#######.#####.###.###.#######.###.#######.#.#.#.#.#.###########.#.#.#.###.#.###.###.#.#.###.###.#.#.###.#.#.# #...#.....#.#.#...#.#...#.#.#.#.......#...#.#.......#.......................#.#.#.#.#.........#...#.#.#...#...#.#...#...#.#...#.....#.....#.# #.#.###.#.#.#.#####.#.###.#.#.###.###.#.#.#.#.#######.###.#.###.###.###.#.#.#.#.#.#.#.#######.###.#.#.###.###.#.#.#####.#.#.#####.#.#.#.#.#.# #.#...#.#.........#.#.#...#.#.......#...#...#.#.........#...#...#.......#.#.#...#.#.#.#.....#...#.#...#.....#.................#.....#...#...# #.###.#.###.###.#.#.#.###.#.###.#.#.#######.#.#.#####.#.###.#.#########.#.#.#.#####.#.#.#######.#.#.###.###.#.#.#######.#.###.#.#.#.###.#.### #...#.#...#.#.....#...#...#.....#.........#...#...#...#...#...#...#.....#.#...#.....#...#.......#.....................................#.....# ###.#.###.###.#.#######.#######.#.###########.###.#.#.###.#####.#.#######.###.#.#######.#.#####.#.#.#####.#.#.#.#.#####.#.#.#.#.#.#.#.#.#.#.# #...#...#.........#.........................#...#.#...........#.#.......#.....#...#...#.#.....#.#.#.....#.#.#.#.#...#.#...#.#.#.#...#...#.#.# #.#.###.#.#####.#.#######.#.#.###.###.#.#.###.#.#.###.#######.#.#######.#####.###.#.#.#######.#.#.#####.#.#.#.#####.#.#.###.#.#.#.#.###.###.# #.#.....#.#.....#.........#.#.....#.#.#.#.......#.........#...#.#.....#.....#...#.#.#...#.....#.#.....#.#.#.#.....#...#.....#...#...#.#.#...# #.#.#######.###.#########.#.#######.#.#.#####.#######.###.#.###.#.###.#####.#####.#.###.#.###########.#.#.#.#####.###.#.###.#####.#.#.#.#.#.# #.#.#.........#.#.#.......#...#.....#.#.....#.......#...#.#.....#...#.....#.......#.#...#.#.......#...#...#...#.....#.#...#.....#.#...#...#.# #.###.#########.#.#.#########.#.#.#.#.#####.#.#####.###.#.#########.#.#.###.#######.#.###.#.#####.#.#####.#####.#####.#.#.###.###.#.#.#.###.# #.......#.....#.#...#.......#.#.#.#.#...#...#...#.#...#.#.#...#.....#...#...#.......#.#...#.....#.#.#.#...#.....#.....#.#.#.#.#...#.....#.#.# #.#######.###.#.#.###.###.###.###.#####.#.#####.#.###.###.#.###.#.#######.###.#######.###.#####.#.#.#.#.###.#####.#######.#.#.#.#.#.###.#.#.# #.#...#...#.#.#.#.#.#...#.#...#...#.....#...#.#.#.........#.....#...........#.......#.#...#...#.#...#.#.#.#.....#.#.....#.#.#.#.#.....#...#.# ###.#.#.###.#.#.#.#.#.#.#.#.###.#.#.#######.#.#.###.#############################.###.#.###.#.#.#.###.#.#.#####.#.###.#.#.#.#.#.#.#.#.#.#.#.# #...............#.#...#.#.#.....#.#.....#...#.#...#.#...#.......#.....#...........#...#.....#...#.....#.#.....#.......#.#.#.#.#...#.#.#...#.# #.#.#############.###.#.#######.#######.#.###.###.###.#.#.#####.#.###.#.#######.###.###.#########.###.#.###.###########.#.#.#.###.###.#.###.# #...#.......#.......#.#.....#...#.......#.....#.#...#.#.......#.#.#.#...#.....#.....#...#.#.........#...#...#.....#.......#.....#.#...#.#...# #.#.#.#####.#######.#.#.#.#.#.###.#####.#####.#.###.#.#########.#.#.#####.#####.#####.###.#.#########.###.#.#.###.#######.#######.#.#####.### #.#...#...#.......#.#.#...#.#.#.#.....#.....#.#...#...#.........#.....#.....#...#...#.....#.#...#...#.#...#.#.#.......#...#...#.............# #.#.#####.###.###.#.#.###.#.#.#.#####.#####.#.#.#.###.###.#.#########.#####.#.#.#.###.###.#.#.###.#.#.###.###.#######.#.###.#.#.#####.#.#.#.# #...#.......#.#...#.#.#.....#.#...#...#...#.#...#.#.....#.#...#...#.........#.#.....#...#.....#...#.#...#...#...#...........#...#.....#.#...# ###.#.#.###.#.#.###.#.#.###.#.###.#.###.#.###.###.#.###.#.###.#.#.#.#########.#####.###.#######.###.###.#.#.###.###################.###.#.#.# #...#.#.#.#...#.#...#.#.#.#.#.....#.....#.......#...#.#.#...#...#...#...#...#...#.....#...#.....#.#...#.#.#...#.......#...#.#.......#...#.#.# #.#.#.#.#.###.#.#.#####.#.#.#####.#########.###.###.#.#.###.#########.#.#.#.#.#.#.###.###.#.#####.###.#.###.#.#######.#.#.#.#.#.#####.###.### #.#...#.#...#.#.#.......#.#...#...#.......#.#.#.#.......#...#.......#.#...#.#.#.#.#.....#.#.#...#...#.#.....#.#...#...#.#.#.#.#...#...#.....# #.#.###.#.#.#.#.#######.#.###.#.###.#####.#.#.#.#.###.#.#.#.###.#####.#####.#.#.#.#.#.###.#.#.#.#.#.#.#########.#.#.###.#.#.#.###.#.###.#.#.# #...#...#.#.#.#.#.............#.#.......#.#.#...#.....#...#.....#.....#...#.....#...#.....#...#...#...#.........#.#...#...#.....#...#.......# ###.#.#####.#.#.#####.#########.#########.#.#.###.#############.#.#####.#.#######.#########.#########.#.#########.#.#.#.#.#######.###.#.#.#.# #...#.....#...#.....#...#...#.#.......#...#.#.....#.............#...#.#.#.....#.#.#.......#.........#.#.....#...#.#.#...#.......#.....#...#.# #.#.#.#.#.#.#######.#.#.#.#.#.###.###.#.#.#.#######.#########.#.###.#.#.#.###.#.#.#####.#.#######.#.#.#.###.#.###.#.#########.#.#######.#.#.# #.....#.#.#...#...#...#...#.....#.......#.#.......#.....#...#.....#.#.#.#.#.#.#.#.......#...#.......#.#...#.#.#...#.#...#...#.#.#...#.......# ###.#.###.###.#.#.###.#########.#.#########.#.###.#####.#.#.#######.#.#.#.#.#.#.###########.#.#######.#.###.#.#.###.#.###.#.###.#.#.###.#.### #.#...#...#...#.#.......#.......#.#.#...........#.......#.#...#.....#...#.#...#.....#...#...#.#.....#.#.#...#.#.#.#...#...#...#.#.#...#.#...# #.#.#.#.###.###.#######.#.#######.#.#.###.#####.#####.###.###.#.#####.###.#.#####.#.###.#.###.#.#####.#.#.###.#.#.###.#.###.#.#.#.###.#.#.#.# #.#.#...#...#...#...#.....#...#...#.#...#...........#.#...#.#.#.#.......#.#.......#.....#...#.#.#.....#.#.#...#.#.#...#.#.......#.#.#.......# #.#.#.#####.#.###.#.#######.#.#.###.###.###.#######.#.#.###.#.#.#######.#.#####.###.#######.#.#.#.#####.#.#.#.#.#.#.###.#.#######.#.#.#.###.# #...#.....#.#.....#.........#...#.....#.#.......#...#.#.#.......#...#...#.....#.#.....#...#.#.#.......#.#.#.#.#.#...#...#.#.......#.#...#...# #.###.###.#.#####################.###.#.#.#####.#.###.#.#######.#.#.#####.###.###.###.#.#.#.#.#######.###.#.###.#.#.#.#####.#######.###.##### #.#.....#.#.#.........#...#.....#.#...#.#.#.....#...#.....#...#.#.#.#...#...#...#...#...#...#.....#.......#...#.#...#...........#.....#.....# #.###.#.#.#.#######.#.#.#.#.#.#.#.#.###.#.#########.#####.#.#.###.#.#.#.###.###.###.#########.###.###########.#.#######.#######.#####.#.###.# #.....#...#.....#...#...#.#.#.#...#.#.#.#...........#...#...#.....#...#...#...#.#...#.....#...#.#.....#.......#.#.....#.#.....#...........#.# #.###.#########.#.#######.###.#.#.#.#.#.#.###########.#.#################.###.#.#.###.###.#.###.#####.###.#.###.#.###.#.#.###.#######.#.###.# #.......#.........#.....#...#.#...#...#.#...#...#.....#...................#...#.#.#...#...#.#.......#...#.#.......#...#.#.#.........#.#.....# #.#.###.#.#######.#.###.###.#.#########.###.#.###.#.#######################.###.#.#.#######.###.###.###.#.#.#######.#####.#########.#.#.###.# #.#.#.#.#.#.....#.#.#.#...#.............#.#.#.#...#.........#.....#.......#.#.#.#.#.......#...#.#.#.#.#.#.....#...#.......#...#...#.........# ###.#.#.#.#.###.#.#.#.###.###.#.#########.#.#.#.#########.#.#.###.#.###.#.#.#.#.#.#######.###.#.#.#.#.#.#######.#.###.#####.#.#.#.###.#.#.#.# #...#.#.#.#.#...#.#.#...#.....#...#.....#.#.#.....#...#.....#...#...#...#.#.#.#.#...#...#.#...#.#.#.#...........#.#...#.....#...#...#...#.#.# #.###.#.###.#.#####.#.#######.###.#.###.#.#.#.###.#.#.#.#####.#.#####.#.#.#.#.#.###.#.#.#.#.###.#.#.#.#########.#.#####.###########.#.#.#.#.# #.........#.........#.......#...#.....#...#.#...#...#.#...#...#...#.#.#...#...#.....#.#...#...#.#...#...#.#.....#...#...#.........#...#.....# #.#######.#.#########.#####.###.#.#.#.###.#.#.#.#####.###.#.#.###.#.#.#######.#######.#######.#.#.###.#.#.#.###.###.#.###.#######.###.#.##### #.....#...#.#.#.......#...#...#...#.#...#.#...#.......#...#.#.#...#.#.......#.#...#.#.................#...#.#.#.....#.#...#.........#.#.....# #.###.#.###.#.#.#########.#.###########.#.#.#######.###.###.###.###.#######.#.#.#.#.#.#######.#######.#####.#.#####.#.###.#.#######.#.#####.# #.#.#.#.#...#.#.#.........#.............#.#.......#...#.#.......#.........#.#.#.#.#.....#...#.#.....#.#.....#.#.....#...#.#...#.....#...#.#.# #.#.#.#.###.#.#.#.#####.###########.#.###########.#.###.#.###.#.#.#.#####.#.#.#.#.#.#####.#.###.###.###.#####.#.#####.#.#####.#####.#.#.#.#.# #...#.#.#...#...#...#...#.........#.#.#...#...#...#.#...#.#.#...#.#.....#.#...#.#.#.#.....#...#...#.....#.......#...#...#...................# ###.#.#.#.#.#.#####.#.###.#######.#.###.#.#.#.#.#####.###.#.###.#######.#.#####.#.#.#.#######.#.#.#.#########.###.#.#.###.#.###.#.#####.#.#.# #...#.#...#.....#.#.#.....#...#...#.....#...#.#...#...#.#.#.............#.#.....#.#.#.#...#...#.#.....#.....#.....#.#.....#.#...#.......#...# #.###.#####.###.#.#.#######.#.#.#.###########.###.#.###.#.#.#########.###.#####.#.#.#.###.#.#######.#.#.###.#######.#####.###.#.#########.### #...#.......#.#.#.#...#.....#...#.#.#.....#...#...#...#...#.#.....#.....#.......#...#...#...#.........#.#.#.....#.....#...#...#.#.........#.# #####.#####.#.#.#.#.#.#.#########.#.#.###.#.###.#####.#.#.#.#.#####.###.###########.#.#.#.#####.###.###.#.#####.#######.###.###.#.#########.# #...#...#...#...#.....#.........#.#...#...#.....#.....#...#.#.#.....#.#.......#.....#.#.......#.#...#...#...#.#...........#.#.....#...#.....# #.#.#####.#.#.###.#####.#######.#.#####.###########.#####.#.#.#.#####.#####.###.#####.#.#####.#.###.#.###.#.#.#############.#.#.###.#.#####.# #.#.#...#.#.#...#.#...#.....#...#.#...#.............#...#.#.#.#.#.....#...#...#.....#.#.#.....#.......#...#.............#...#.....#.#.......# #.#.#.#.#.#.###.###.#.#.#.#.#.###.#.#.#.#########.###.#.#.#.#.#.#####.###.#.#.#####.###.#.#####.#######.#######.#.#######.#####.#.#.#.###.#.# #.#...#...#...#.....#.#...#...#.#.#.#.#.#.#...#...#.#.#.....#...#.......#.#.#...........#.....#.#.......#.........#.....#...............#...# #.#########.#.#####.#.#.###.#.#.#.#.#.#.#.#.#.#.###.#.#.#####.#.#.###.###.#.#######.#########.#.#####.###.#####.###.###.###.#.#.#####.###.### #.#...#.......#.....#...#.#...#...#.#.#.....#...#...#.#.....#.#.#...#.#...#.#.............#.#.#.#...#.#...#...#.#.#.#.#...#.#.....#...#...#.# #.#.#.#####.###.#.#######.#####.###.#.#####.#####.#.#.###.#.#.#.#.#.#.#.###.#.#.###.#####.#.#.#.#.#.#.#.###.#.#.#.#.#.###.#.###.#.#.#.#.#.#.# #.........#.#...#.............#.#...#.....#...#...#.......#.#.#...#.#.#.#...#.#.........#.#.......#.#.#.#...#.#.#.#.#...#...#...#...#.#...#.# #.#.#####.#.#.#####.#########.#.#.#######.###.#.###.#####.###.#.###.#.#.#.###.#.#########.#.#######.#.#.#.###.#.#.#.#.#######.#.#.###.###.#.# #...#.#...#.....#...#.......#.#.#...#.....#...#...#.#.#...#...#.#...#.#.#.#...#.................#...#.....#...#...#.#.#...#.......#...#.#...# #.###.#.#########.#.###.###.#.#.###.#.#####.#####.#.#.#.###.#####.###.#.###.###.#.#############.###.#.###.#.#######.#.#.#.#.#####.#.#.#.#.#.# #.......#.........#...#...#...#...#.#.......#.....#.#.#...#.....#.#...#.....#.#.#.........#...#...#...#...#.#.......#...#...............#...# #.#####.#.#.#######.#.###########.#.#########.###.#.#.###.#####.#.#.#########.#.#####.###.###.###.###.#.#.#.#.#######.#.#########.#.#.#.#.### #.#.....#.#.......#.#...........#...#...#.......#.#.#...#...#...#.#.#.#.......#...#...#.....#.....#...#.#.#...#.....#...#.........#...#.#.#.# #.#.#####.#######.#.###.###.#.#######.#.#.#####.###.#.#.#.#.#.###.#.#.#.#####.###.#.###.###.###.###.###.#.#####.###.###.#.#############.#.#.# #.#...#...#.....#...........#.......#.#.#.......#...#.#.#.#.#.....#.#.#.#.#.....#...#.#...#...#.#.....#.#.......#.....#.#.....#.......#.#...# #.###.#.#####.#.#####.#######.###.###.#.###.#.#.#.#####.#.###.#.###.#.#.#.#.###.#####.#.#.###.#.#####.#.#########.###.#.#####.#.#####.###.#.# #...#.#.....#.#.....#.......#...#.....#...#.#.#.#.#.....#.....#...#.#...#.#.#...#...#...#...#.#.#...#.#...#...#...#.....#...#.#.#...#.....#.# ###.#.#####.###.#####.#####.###.#########.#.#.###.#.###.#####.###.#.#.#.#.#.#####.#.#.###.#.#.#.#.#.#.###.#.#.#.###.#######.#.#.#.#.#####.#.# #...#...#...#...#.....#...#...#.#...#...#...#...#.#.#...#.........#.#.....#.......#.#.....#...#...#.#...#...#.#.....#.....#.#...#.#.#.....#.# #.#####.#.###.###.#####.#.###.#.#.#.#.#.###.###.#.#.#.#####.#######.###############.###.#.###.#####.#####.###.#.#####.###.#.#####.#.#.#####.# #.....#.#...#.#...#.....#...#.#.#.#.#.#...#...#.....#.......#.....#.................#...#.....#.#...#.........#...#.#...#...#.....#.#.......# #####.#.###.#.#.#.#########.#.#.#.#.#.###.###.#############.#.###.#.###############.#.#####.#.#.#.###.###########.#.#.#.###.#####.###.#.##### #.#...#.#...#.#.......#.....#.....#.#...#.#...#.#...#.......#...#.............#...#.#.......#.#.#.....#.....#...#.#...#.#.............#...#.# #.#.###.#.#.#.#######.#.#####.#######.#.#.###.#.#.#.#####.#.###.#.###########.###.#.#######.#.#.###.#####.###.#.#.#####.#######.###.#.###.#.# #.#.#...#.......#.#...#.#...#...........#...#...#.#.....#.#...#.#...#.......#...#.....#.......#...#.......#...#.#.....#...#.....#...#...#.#.# #.#.#.#.#######.#.#.###.#.#.###############.#.###.#####.###.#.#.#.###.###.#####.#######.###.###.#.#.###.###.###.#####.#.#.#######.#####.#.#.# #...#...#.......#.#.#.#...#...#.....#...........#.....#.....#.#.#.....#...#.....#...............#.#.#...#...#...#...#.#.#.#...#...#...#.#.#.# #######.#.#######.#.#.#.###.#.#.###.#####.#####.#.###.#######.#.#.#.###.###.#####.#############.#.#.#.###.###.#.###.#.#.#.#.#.#.#####.#.#.#.# #.......#.......#.#.#.#.#...#.#.#...#...#.....#.....#...#...#.#.#.#...#...#...#...#.#...........#.#.#.....#.#.#.....#.#.#...#.#...#.........# #.#####.#######.#.#.#.#.#.###.#.#.###.#.###.#.###.#####.###.#.#.#.#.#.###.###.#.###.#.#.#########.#.#######.#.#######.#.#####.###.#.###.#.#.# #.....#...........#.#.#.#.#...#.#.....#.....#.#...#...#...#.#...#...#...#...#...#.....#.......#...#.#.....#.#.........#.....#...#.#.....#...# #.###.#.###########.#.#.#.#.###.#############.#.###.#.###.#.#####.#####.###.#############.###.#####.#.###.#.###############.#.###.#.#.#####.# #...#...#...........#...#.#.#...#...#.....#...#.....#...#.#...#...#...#...#.........#...#.#...#.....#.#...#.#...........#...#.#...#...#.....# ###.###.#.###########.###.#.#.#.#.#.###.#.#.#########.#.#.#.#.###.#.#.###.#.#####.#.#.#.###.#.#.#####.#.###.#.#######.#.#####.#.#.#####.##### #.......#.....#.........#.#.#.#...#...#.#.#.....#...#.#.#...#...#.#.#.....#.#...#.#...#...#.#.#.#.....#.#.........#...#.#.....#.#.#.....#...# #.#####.#####.#########.#.#.#########.#.#.#####.#.###.#.#######.#.#.#######.#.#.#.#######.#.###.#.#####.###########.###.#.###.#.#.#.#####.#.# #.#...#.....#.......#.#.#.#...........#.#.#.....#...#.#.#...#.#...#.......#.#.#.#.....#.......#.#.....#...#.....#...#.#...#...#.#.#.#.....#.# #.#.#.#.#.#########.#.#.#.#############.###.#######.#.#.#.#.#.###########.#.#.#.#####.#.#.###.#.#####.###.#.###.#.###.#.#######.#.#.#.#####.# #...#.#...#.......#.#...#...#.......#...............#.#...#.#.#.....#...#.#.#.#...#...#.#.....#.......#.#.#.#.....#.....#...#...#.#.#.....#.# #.###.#.#.#.#.###.#.#.#####.###.#.###.###########.#.#.#####.#.#.###.#.#.#.###.###.#.###.#####.#######.#.#.#.#######.#####.#.#.###.#.#######.# #...#...#.#...#.#...#.....#...#.#...#.#...#.......#.#.#...#...#.#.#.#.#...#...#.....#.....#...#.#.........#...#...#.#...#.#...#...#.........# ###.###.#.###.#.#####.#######.#####.#.#.#.#.#####.#.#.#.#.#####.#.#.#.#####.###########.#.#.###.#.###########.#.#.###.#.#.#####.###########.# #...#...#...#...#.............#.....#...#.#.#...#.#.#.......#...#.#.#...#...#.........#.#.......#.#.........#...#...#.#...#.....#.....#...#.# #####.#.###.#.#.#.###.#########.#####.###.#.#.###.#.#####.#.#.###.#.###.###.#.#######.#.#########.#.#####.#.#######.#.###.#######.#.###.#.#.# #.....#.......#.#.#...#.....#.....#...#...#.#...#.#.#...#...#.#...#.....#...#...#...#.#.#.....#...#.#.....#.......#.#...#.#.................# #.###.#.###.#.#.#.#.###.###.#.###.#.#.#.###.#.#.#.#.#.#.#.#.#.###.#######.#####.#.#.#.#.#.###.#.#.#.#.###########.#.###.###.#############.#.# #.#...#.....#...#.#.#.....#.#...#...#.....#.#.#.#.#.#.#...#.#...#.....#...#.....#.#.#.#.#...#...#.....#.........#...#.....#...#.....#...#...# #.#########.#.###.#.#.#.#.###.#####.#######.###.#.###.#####.###.###.#.#.###.#####.###.#####.#####.#####.#######.###.#.###.###.#####.#.#.##### #.#.....#...#...#.#...#.#.....#...#...#...#.#...#.....#...#.#.#.....#.#.#...#.....#...#...#.#.....#.#.......#.#...#...#.#.#...#...#...#.....# #.#.###.#.#.#.###.###.#.#######.#.###.#.#.#.#.#########.###.#.#######.#.#.###.###.#.###.#.#.###.###.#.#####.#.###.###.#.#.#.###.#.#######.### #...#.#...#...#...#...#...#.....#...#.#.#.#.#.................#.....#.#.........#.#.....#.#...#.#...#.....#.#.......#.#.#...#...#.......#...# #.###.#####.#.#.###.#####.#.#######.###.#.#.#############.#####.###.#.#####.###.#.#######.###.#.#.#.###.#.#.#########.#.#####.#########.###.# #.........#.#...#.#...#.#.#.#.....#.....#...#.....#.....#.#.....#...#.....#...#.#...#...#.....#.#.#...#.#.#.#.........#.......#.......#.#...# #.#######.#.#####.###.#.#.#.#.#.#####.#####.#.###.#.###.###.#####.#.#####.###.#.###.#.#########.#####.#.#.#.#.#######.#.#.#######.#####.#.### #.....#...#.....#...#.#.#.#.#.#.......#...#.#.#.#...#.#.......#...#.#...#.#.#.#.#.....#.....#...#.....#.#.#...#.....#...#.#.....#...........# #####.#.###.###.###.#.#.#.#.#.###.#####.#.###.#.#####.#########.#.###.#.#.#.#.#.#######.#.#.#.#.#.###.#.#.#######.#.#.#.###.###.#.#########.# #.....#...........#.#.#...#.#.........#.#.....#...........#.....#.#...#...#.#.#.#.......#.#.....#.#...#...........#.#.#...#.#...#...#.......# #.###.#.#.###.###.#.#.#.#.#.#######.###.#######.###.###.###.###.#.#.#######.#.#.#.#######.###.###.#######.#########.#.###.#.#.#####.#.#.###.# #.#...#...#.#.#.....#.#...#.....#.#.#...#.....#...#.#.#.#...#...#.#.#...#.....#...#.....#.#.....#.......#.....#...#.#.#...................#.# #.###.#####.#.#.#####.#.#######.#.#.#.#.#.#.###.###.#.#.#.###.#.#.#.###.#.#####.###.###.#.###.#.#######.#.#.###.#.#.#.#.#.#.###.#.#.###.#.#.# #...#...#.....#.#.....#.......#.#...........#...#...#...#.#...#...#.#...#.#.....#.#.#.#...#...#.........#.#...#.#...#...#...#...#...........# #.#.###.#.#####.#.###.#########.#####.#.#####.###.#######.#.#######.#.###.#.#####.#.#.#####.#######.#####.###.#.#####.#####.#.###.###.###.#.# #.#...#.#.#.....#.#...#.........#.....#.....#.#...#.......#...#...#.#.....#.#.....#.#.........#...#.#...#...#.#.#...#.#...#.#...#.#...#...#.# #.###.#.#.###.###.#.###.#######.#.###.#####.#.#.###.#########.#.###.#.#####.#.###.#.#.#######.###.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.#.###.# #.#...#.#...#.#...#.#.#...#.....#.........#...#.#...#...#.#.....#...#.#...#.#.#...#.#.....#.#...#...#.#...#...#.#...............#.....#.....# #.#.#######.#.#.###.#.###.#####.#########.###.#.#.#.#.#.#.#.#####.###.#.#.#.#.#####.#####.#.###.#.###.###.#.###.#####.#.#.###.#########.##### #.#.....#...............#.#...#.#...#.....#.....#.#.#.#.#.....#...#.#...#.#...#...#...#.#...#...#.#...#...#.....#...#.#.#.....#.....#...#...# #.###.#.#.#####.#.#####.#.#.#.###.#.#.#####.#.#.#.###.#.#######.###.#####.#####.#.###.#.###.#.#####.#.###.#####.#.#.###.#######.#.###.###.#.# #S....#.........#.......#...#.....#.........#...#.....#.........#...............#.....#.....#.....................#.....#.......#.........#.# ############################################################################################################################################# ================================================ FILE: exm/aoc/2024/aoc_2024_16_questions.txt ================================================ --- Day 16: Reindeer Maze --- It's time again for the Reindeer Olympics! This year, the big event is the Reindeer Maze, where the Reindeer compete for the lowest score. You and The Historians arrive to search for the Chief right as the event is about to start. It wouldn't hurt to watch a little, right? The Reindeer start on the Start Tile (marked S) facing East and need to reach the End Tile (marked E). They can move forward one tile at a time (increasing their score by 1 point), but never into a wall (#). They can also rotate clockwise or counterclockwise 90 degrees at a time (increasing their score by 1000 points). To figure out the best place to sit, you start by grabbing a map (your puzzle input) from a nearby kiosk. For example: ############### #.......#....E# #.#.###.#.###.# #.....#.#...#.# #.###.#####.#.# #.#.#.......#.# #.#.#####.###.# #...........#.# ###.#.#####.#.# #...#.....#.#.# #.#.#.###.#.#.# #.....#...#.#.# #.###.#.#.#.#.# #S..#.....#...# ############### There are many paths through this maze, but taking any of the best paths would incur a score of only 7036. This can be achieved by taking a total of 36 steps forward and turning 90 degrees a total of 7 times: ############### #.......#....E# #.#.###.#.###^# #.....#.#...#^# #.###.#####.#^# #.#.#.......#^# #.#.#####.###^# #..>>>>>>>>v#^# ###^#.#####v#^# #>>^#.....#v#^# #^#.#.###.#v#^# #^....#...#v#^# #^###.#.#.#v#^# #S..#.....#>>^# ############### Here's a second example: ################# #...#...#...#..E# #.#.#.#.#.#.#.#.# #.#.#.#...#...#.# #.#.#.#.###.#.#.# #...#.#.#.....#.# #.#.#.#.#.#####.# #.#...#.#.#.....# #.#.#####.#.###.# #.#.#.......#...# #.#.###.#####.### #.#.#...#.....#.# #.#.#.#####.###.# #.#.#.........#.# #.#.#.#########.# #S#.............# ################# In this maze, the best paths cost 11048 points; following one such path would look like this: ################# #...#...#...#..E# #.#.#.#.#.#.#.#^# #.#.#.#...#...#^# #.#.#.#.###.#.#^# #>>v#.#.#.....#^# #^#v#.#.#.#####^# #^#v..#.#.#>>>>^# #^#v#####.#^###.# #^#v#..>>>>^#...# #^#v###^#####.### #^#v#>>^#.....#.# #^#v#^#####.###.# #^#v#^........#.# #^#v#^#########.# #S#>>^..........# ################# Note that the path shown above includes one 90 degree turn as the very first move, rotating the Reindeer from facing East to facing North. Analyze your map carefully. What is the lowest score a Reindeer could possibly get? --- Part Two --- Now that you know what the best paths look like, you can figure out the best spot to sit. Every non-wall tile (S, ., or E) is equipped with places to sit along the edges of the tile. While determining which of these tiles would be the best spot to sit depends on a whole bunch of factors (how comfortable the seats are, how far away the bathrooms are, whether there's a pillar blocking your view, etc.), the most important factor is whether the tile is on one of the best paths through the maze. If you sit somewhere else, you'd miss all the action! So, you'll need to determine which tiles are part of any best path through the maze, including the S and E tiles. In the first example, there are 45 tiles (marked O) that are part of at least one of the various best paths through the maze: ############### #.......#....O# #.#.###.#.###O# #.....#.#...#O# #.###.#####.#O# #.#.#.......#O# #.#.#####.###O# #..OOOOOOOOO#O# ###O#O#####O#O# #OOO#O....#O#O# #O#O#O###.#O#O# #OOOOO#...#O#O# #O###.#.#.#O#O# #O..#.....#OOO# ############### In the second example, there are 64 tiles that are part of at least one of the best paths: ################# #...#...#...#..O# #.#.#.#.#.#.#.#O# #.#.#.#...#...#O# #.#.#.#.###.#.#O# #OOO#.#.#.....#O# #O#O#.#.#.#####O# #O#O..#.#.#OOOOO# #O#O#####.#O###O# #O#O#..OOOOO#OOO# #O#O###O#####O### #O#O#OOO#..OOO#.# #O#O#O#####O###.# #O#O#OOOOOOO..#.# #O#O#O#########.# #O#OOO..........# ################# Analyze your map further. How many tiles are part of at least one of the best paths through the maze? ================================================ FILE: exm/aoc/2024/aoc_2024_17.adb ================================================ -- Solution to Advent of Code 2024, Day 17 ------------------------------------------- -- Chronospatial Computer -- -- https://adventofcode.com/2024/day/17 -- Copy of questions in: aoc_2024_17_questions.txt -- -- HAC 0.40 "nice-to-have"'s detected in this exercise: -- -- * Modular types (esp. Unsigned_X and bitwise operators) -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- HAC 0.40 "nice to have"'s detected in this exercise: -- * Unsigned_X and bitwise operators on it. -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_17 is use AoC_Toolbox, HAT, Interfaces; subtype UInt is Integer_64; -- Hack for HAC. "Full Ada": type UInt is mod 2 ** 64; subtype Word is Integer range 0 .. 7; -- Hack for HAC. "Full Ada": type Word is mod 2 ** 3; r : array (Part_Type) of VString; type Instruction is (adv, bxl, bst, jnz, bxc, ovt, bdv, cdv); type Word_Array is array (0 .. 20) of Word; type Word_Vect is record oct : Word_Array; last : Integer; end record; procedure Convert (prog_s : in VString; prog : out Word_Vect) is begin prog.last := Length (prog_s) - 1; for i in 1 .. prog.last + 1 loop prog.oct (i - 1) := Word (Ord (Element (prog_s, i)) - Ord ('0')); end loop; end Convert; procedure Run (A_start : in UInt; prog : in Word_Vect; code : out Word_Vect) is A : UInt := A_start; B : UInt := 0; C : UInt := 0; p : Natural := 0; inst : Instruction; oper : Word; function Combo return UInt is begin case oper is when 0 .. 3 => return UInt (oper); when 4 => return A; when 5 => return B; when 6 => return C; when 7 => Put ("Error"); return 0; -- "Full Ada": raise Program_Error; end case; end Combo; begin code.last := -1; while p <= prog.last loop inst := Instruction'Val (prog.oct (p)); oper := prog.oct (p + 1); p := p + 2; case inst is when adv => A := A / (2 ** Natural (Combo)); when bdv => B := A / (2 ** Natural (Combo)); when cdv => C := A / (2 ** Natural (Combo)); when bxl => B := Sim_XOR (B, UInt (oper)); -- "Full Ada" has `xor` of course. when bst => B := Combo mod 8; when jnz => if A /= 0 then p := Natural (oper); end if; when bxc => B := Sim_XOR (B, C); -- "Full Ada" has `xor` of course. when ovt => code.last := code.last + 1; code.oct (code.last) := Word (Combo mod 8); end case; end loop; -- mini : result is: 4,6,3,5,6,3,5,2,1,0 -- input : result is: 5,1,4,0,5,1,0,2,6 end Run; procedure Run_Hardcoded (A_start : in UInt; code : out Word_Vect) is A : UInt := A_start; B : UInt := 0; C : UInt := 0; begin code.last := -1; loop B := A mod 8; B := Sim_XOR (B, 1); -- "Full Ada" has `xor` of course. C := A / 2 ** Natural (B); B := Sim_XOR (B, 4); -- "Full Ada" has `xor` of course. A := A / 8; B := Sim_XOR (B, C); -- "Full Ada" has `xor` of course. code.last := code.last + 1; code.oct (code.last) := Word (B mod 8); exit when A = 0; end loop; end Run_Hardcoded; procedure Do_Part_1 (A_start : UInt; prog_s : VString) is prog, res : Word_Vect; begin r (part_1) := +""; Convert (prog_s, prog); Run (A_start, prog, res); for i in 0 .. res.last loop r (part_1) := r (part_1) & Character'Val (res.oct (i) + Character'Pos ('0')); end loop; end Do_Part_1; -- Emulate Full Ada's `p1.oct (from .. to) = p2.oct (from .. to)` -- function Equal_Slice (p1, p2 : Word_Vect; from, to : Natural) return Boolean is begin if p1.last < to or else p2.last < to then return False; end if; for i in from .. to loop if p1.oct (i) /= p2.oct (i) then return False; end if; end loop; return True; end Equal_Slice; procedure Do_Part_2 (prog_s : VString; shortcut : Boolean) is prog : Word_Vect; best : UInt := UInt'Last; procedure Match (base : UInt; d : Natural) is code : Word_Vect; x : UInt; begin for i in reverse 0 .. 1023 loop x := base + UInt (i) * 8 ** d; if shortcut then Run_Hardcoded (x, code); else Run (x, prog, code); end if; if d <= code.last and then Equal_Slice (code, prog, 0, d) then -- if code.last = 15 then -- Put (+"Prog: " & prog_s & "; A=" & x'Image & "; d =" & d'Image & -- "; code.last =" & code.last'Image & " -> "); -- for p in 0 .. code.last loop -- Put (Character'Val (code.oct (p) + Character'Pos ('0'))); -- end loop; -- New_Line; -- end if; if code.last = prog.last and then Equal_Slice (code, prog, d + 1, code.last) then if x < best then -- Put_Line ("*** " & x'Image & "; d =" & d'Image & "; code.last =" & code.last'Image); best := x; end if; elsif code.last < prog.last then Match (x, d + 1); end if; end if; end loop; end Match; begin Convert (prog_s, prog); Match (0, 0); r (part_2) := Trim_Left (+best'Image); end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; kind : constant Data_Type := mini; prog_s : VString; begin case kind is when mini => -- Register A: 729 -- Register B: 0 -- Register C: 0 -- -- Program: 0,1,5,4,3,0 Do_Part_1 (729, +"015430"); if not compiler_test_mode then -- Register A: 2024 -- Register B: 0 -- Register C: 0 -- -- Program: 0,3,5,4,3,0 Do_Part_2 (+"035430", False); end if; when input => -- Register A: 65804993 -- Register B: 0 -- Register C: 0 -- -- Program: 2,4,1,1,7,5,1,4,0,3,4,5,5,5,3,0 prog_s := +"2411751403455530"; Do_Part_1 (65804993, prog_s); Do_Part_2 (prog_s, True); -- 202941412157999 -- 202391656344111 -- 202322936867375 -- 202322936867370 --> OK. end case; if compiler_test_mode then if r (part_1) /= Argument (1) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 5,1,4,0,5,1,0,2,6 (mini: 4,6,3,5,6,3,5,2,1,0) -- Part 2: validated by AoC: 202322936867370 (mini: 117440) end if; end AoC_2024_17; ================================================ FILE: exm/aoc/2024/aoc_2024_17_questions.txt ================================================ --- Day 17: Chronospatial Computer --- The Historians push the button on their strange device, but this time, you all just feel like you're falling. "Situation critical", the device announces in a familiar voice. "Bootstrapping process failed. Initializing debugger...." The small handheld device suddenly unfolds into an entire computer! The Historians look around nervously before one of them tosses it to you. This seems to be a 3-bit computer: its program is a list of 3-bit numbers (0 through 7), like 0,1,2,3. The computer also has three registers named A, B, and C, but these registers aren't limited to 3 bits and can instead hold any integer. The computer knows eight instructions, each identified by a 3-bit number (called the instruction's opcode). Each instruction also reads the 3-bit number after it as an input; this is called its operand. A number called the instruction pointer identifies the position in the program from which the next opcode will be read; it starts at 0, pointing at the first 3-bit number in the program. Except for jump instructions, the instruction pointer increases by 2 after each instruction is processed (to move past the instruction's opcode and its operand). If the computer tries to read an opcode past the end of the program, it instead halts. So, the program 0,1,2,3 would run the instruction whose opcode is 0 and pass it the operand 1, then run the instruction having opcode 2 and pass it the operand 3, then halt. There are two types of operands; each instruction specifies the type of its operand. The value of a literal operand is the operand itself. For example, the value of the literal operand 7 is the number 7. The value of a combo operand can be found as follows: Combo operands 0 through 3 represent literal values 0 through 3. Combo operand 4 represents the value of register A. Combo operand 5 represents the value of register B. Combo operand 6 represents the value of register C. Combo operand 7 is reserved and will not appear in valid programs. The eight instructions are as follows: The adv instruction (opcode 0) performs division. The numerator is the value in the A register. The denominator is found by raising 2 to the power of the instruction's combo operand. (So, an operand of 2 would divide A by 4 (2^2); an operand of 5 would divide A by 2^B.) The result of the division operation is truncated to an integer and then written to the A register. The bxl instruction (opcode 1) calculates the bitwise XOR of register B and the instruction's literal operand, then stores the result in register B. The bst instruction (opcode 2) calculates the value of its combo operand modulo 8 (thereby keeping only its lowest 3 bits), then writes that value to the B register. The jnz instruction (opcode 3) does nothing if the A register is 0. However, if the A register is not zero, it jumps by setting the instruction pointer to the value of its literal operand; if this instruction jumps, the instruction pointer is not increased by 2 after this instruction. The bxc instruction (opcode 4) calculates the bitwise XOR of register B and register C, then stores the result in register B. (For legacy reasons, this instruction reads an operand but ignores it.) The out instruction (opcode 5) calculates the value of its combo operand modulo 8, then outputs that value. (If a program outputs multiple values, they are separated by commas.) The bdv instruction (opcode 6) works exactly like the adv instruction except that the result is stored in the B register. (The numerator is still read from the A register.) The cdv instruction (opcode 7) works exactly like the adv instruction except that the result is stored in the C register. (The numerator is still read from the A register.) Here are some examples of instruction operation: If register C contains 9, the program 2,6 would set register B to 1. If register A contains 10, the program 5,0,5,1,5,4 would output 0,1,2. If register A contains 2024, the program 0,1,5,4,3,0 would output 4,2,5,6,7,7,7,7,3,1,0 and leave 0 in register A. If register B contains 29, the program 1,7 would set register B to 26. If register B contains 2024 and register C contains 43690, the program 4,0 would set register B to 44354. The Historians' strange device has finished initializing its debugger and is displaying some information about the program it is trying to run (your puzzle input). For example: Register A: 729 Register B: 0 Register C: 0 Program: 0,1,5,4,3,0 Your first task is to determine what the program is trying to output. To do this, initialize the registers to the given values, then run the given program, collecting any output produced by out instructions. (Always join the values produced by out instructions with commas.) After the above program halts, its final output will be 4,6,3,5,6,3,5,2,1,0. Using the information provided by the debugger, initialize the registers to the given values, then run the program. Once it halts, what do you get if you use commas to join the values it output into a single string? --- Part Two --- Digging deeper in the device's manual, you discover the problem: this program is supposed to output another copy of the program! Unfortunately, the value in register A seems to have been corrupted. You'll need to find a new value to which you can initialize register A so that the program's output instructions produce an exact copy of the program itself. For example: Register A: 2024 Register B: 0 Register C: 0 Program: 0,3,5,4,3,0 This program outputs a copy of itself if register A is instead initialized to 117440. (The original initial value of register A, 2024, is ignored.) What is the lowest positive initial value for register A that causes the program to output a copy of itself? ================================================ FILE: exm/aoc/2024/aoc_2024_18.adb ================================================ -- Solution to Advent of Code 2024, Day 18 ------------------------------------------- -- RAM Run -- -- https://adventofcode.com/2024/day/18 -- Copy of questions in: aoc_2024_18_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_18 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 6; stop : constant := 12; input_name : constant VString := +"aoc_2024_18"; n : constant := 70; stop : constant := 1024; type Map_Type is array (0 .. n, 0 .. n) of Character; map, map_clear : Map_Type; -- map_clear : emulate Full Ada's `(others => others => '.'))` -- Dijkstra shortest path algorithm. -- Code simplified from AoC_2024_16. -- -- The following definitions belong to the Dijkstra algorithm, but -- we keep them less local because of the path tracking. list_length_max : constant := 500_000; subtype List_Range is Integer range 1 .. list_length_max; type State_Type is record pt : Point; end record; type Node is record len : Natural; state : State_Type; end record; list : array (List_Range) of Node; current, explored : Natural; -- 0 <= current <= explored type Score_Type is array (0 .. n, 0 .. n) of Natural; best, best_clear : Score_Type; inf : constant Natural := Integer'Last / 4; start, finish : Point; function Dijkstra_Algorithm return Natural is cur_len : Natural; cur_s : State_Type; s : State_Type; -- Test state derived from current state. procedure Visit (dir : Direction) is len_to, ins : Integer; new_node : Node; begin case dir is when north => s.pt.x := cur_s.pt.x; s.pt.y := cur_s.pt.y - 1; when east => s.pt.x := cur_s.pt.x + 1; s.pt.y := cur_s.pt.y; when south => s.pt.x := cur_s.pt.x; s.pt.y := cur_s.pt.y + 1; when west => s.pt.x := cur_s.pt.x - 1; s.pt.y := cur_s.pt.y; end case; if s.pt.x in 0 .. n and then s.pt.y in 0 .. n and then map (s.pt.x, s.pt.y) = '.' then len_to := cur_len + 1; -- Cost for a move. if len_to < best (s.pt.x, s.pt.y) then -- Found a better path to target state s. best (s.pt.x, s.pt.y) := len_to; -- -- Insert in a sorted way. -- ins := explored + 1; for i in current + 1 .. explored loop if len_to < list (i).len then ins := i; -- Insert here. -- Optional: remove another node -- with the same state and a larger length. exit; end if; end loop; for i in reverse ins .. explored loop list (i + 1) := list (i); end loop; new_node.len := len_to; new_node.state := s; list (ins) := new_node; explored := explored + 1; end if; end if; end Visit; begin current := 0; explored := 0; best := best_clear; cur_s.pt := start; cur_len := 0; loop for d in Direction loop Visit (d); end loop; -- -- Switch to the next best explored point. -- current := current + 1; if current > explored then -- Put_Line ("No way found."); return inf; end if; cur_s := list (current).state; exit when cur_s.pt.x = finish.x and then cur_s.pt.y = finish.y; cur_len := best (cur_s.pt.x, cur_s.pt.y); end loop; return best (cur_s.pt.x, cur_s.pt.y); end Dijkstra_Algorithm; block : array (1 .. 5000) of Point; last_block : Natural := 0; r : array (Part_Type) of VString; procedure Read_Data is dummy_separator : Character; f : File_Type; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop last_block := last_block + 1; Get (f, block (last_block).x); Get (f, dummy_separator); Get (f, block (last_block).y); end loop; Close (f); start.x := 0; start.y := 0; finish.x := n; finish.y := n; for y in 0 .. n loop for x in 0 .. n loop map_clear (x, y) := '.'; best_clear (x, y) := inf; end loop; end loop; end Read_Data; procedure Byte_Fall (to : Natural) is begin map := map_clear; for step in 1 .. to loop map (block (step).x, block (step).y) := '#'; end loop; end Byte_Fall; procedure Do_Part_1 is begin Byte_Fall (stop); r (part_1) := +"" & Dijkstra_Algorithm; end Do_Part_1; procedure Do_Part_2 is a, b, mid : Integer; begin a := stop; b := last_block; loop mid := (a + b) / 2; Byte_Fall (mid); if Dijkstra_Algorithm = inf then b := mid; else a := mid; end if; exit when abs (a - b) <= 1; end loop; r (part_2) := +"" & block (b).x & ',' & block (b).y; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 298 (mini: 22) -- Part 2: validated by AoC: 52,32 (mini: 6,1) end if; end AoC_2024_18; ================================================ FILE: exm/aoc/2024/aoc_2024_18.txt ================================================ 7,22 63,47 4,45 5,6 26,3 1,27 3,59 14,7 37,54 25,65 7,17 69,47 9,16 51,61 61,52 39,68 43,62 47,51 41,57 49,60 12,23 8,31 59,58 67,34 26,5 53,65 16,7 15,60 23,31 3,57 49,47 23,67 57,63 29,60 61,43 41,69 69,50 66,49 29,1 61,51 22,3 6,51 32,69 21,9 46,53 51,50 9,32 22,67 60,63 9,22 15,31 13,11 38,61 18,7 7,46 61,53 21,3 13,15 51,65 1,22 28,57 1,3 65,53 68,59 58,61 51,53 11,60 13,23 61,65 14,9 8,37 3,34 68,45 5,25 41,64 37,58 65,45 67,54 33,57 19,7 56,67 46,59 11,34 11,51 51,52 17,23 21,61 40,51 26,67 13,50 53,53 51,47 65,55 5,13 19,9 47,61 10,17 40,61 57,55 13,49 5,63 2,41 55,33 37,57 69,57 66,41 26,65 33,49 9,20 31,65 27,69 5,3 1,19 15,68 27,10 39,66 48,51 33,4 63,65 13,19 15,62 34,59 67,59 67,43 11,25 15,64 66,63 11,61 14,39 24,1 8,7 31,9 63,60 37,53 65,69 28,69 59,61 2,19 4,27 64,41 55,45 13,12 19,15 23,64 49,45 7,41 29,69 7,4 29,58 12,7 67,42 3,50 41,55 45,53 7,31 55,47 67,39 10,31 9,23 63,59 33,66 7,53 9,15 7,7 70,43 5,45 19,2 21,46 33,1 31,57 7,45 11,33 9,31 55,51 47,59 3,26 52,63 59,47 19,67 27,55 3,61 41,61 32,59 1,18 50,63 7,47 15,38 45,54 48,55 19,68 11,5 57,57 7,52 4,41 11,37 11,35 43,61 63,56 21,65 17,5 62,69 19,20 11,8 69,61 6,7 13,62 63,54 60,67 3,12 29,57 8,29 65,58 49,61 2,29 33,52 57,37 4,19 19,11 9,35 37,63 55,34 11,1 47,48 11,28 56,61 4,37 48,59 31,63 39,69 6,25 4,61 12,13 6,59 69,43 65,46 2,61 69,55 29,55 15,22 9,9 61,42 3,43 4,17 5,23 27,63 63,53 27,57 68,47 14,65 17,67 43,66 59,56 67,47 7,25 27,61 1,2 61,57 63,63 58,65 7,56 37,70 12,51 15,45 0,27 27,1 47,66 5,11 2,15 15,2 5,1 15,41 9,50 1,7 49,67 55,55 2,17 21,64 35,57 12,19 33,67 22,13 9,52 28,67 54,45 18,47 32,61 35,50 10,49 30,67 8,19 3,37 21,63 35,69 1,35 12,37 7,1 5,14 11,9 53,45 67,65 4,25 25,7 11,49 19,19 29,3 51,59 4,43 26,9 13,3 49,62 31,52 59,63 13,7 4,51 13,1 2,3 31,1 15,17 37,56 63,55 61,45 13,21 63,43 2,53 67,61 53,61 31,3 5,41 9,17 13,42 5,46 16,47 17,15 9,40 43,69 5,15 61,35 32,55 11,65 15,3 42,49 57,45 68,61 31,54 1,45 49,51 5,57 28,5 11,48 57,64 38,51 9,29 30,61 13,32 33,69 68,41 35,6 65,67 47,49 45,69 36,63 3,5 7,35 5,7 57,61 38,65 0,21 10,47 33,7 11,7 45,43 17,6 3,31 11,47 41,68 59,43 51,55 69,48 40,63 19,69 67,53 61,63 2,25 52,55 13,35 1,41 13,34 57,46 24,5 21,67 9,54 49,49 3,14 17,32 1,47 49,48 1,6 1,23 65,49 10,7 5,37 31,10 20,65 69,66 52,45 39,65 47,53 69,59 7,20 50,49 10,3 64,51 16,3 29,59 34,57 7,40 3,47 57,62 5,19 3,48 45,51 9,42 8,47 58,51 5,30 4,5 7,29 1,29 0,13 34,7 27,5 21,4 43,57 67,38 23,3 7,33 3,39 61,55 29,5 47,43 69,54 17,14 35,61 58,55 3,49 64,57 59,48 47,39 5,33 7,18 15,5 55,67 45,59 19,63 54,51 67,41 62,51 42,63 33,55 19,13 22,17 34,55 5,12 24,65 17,65 69,67 5,27 23,6 23,5 59,57 30,69 32,65 11,27 59,53 7,42 65,51 9,0 9,45 66,69 51,48 41,51 3,35 6,53 10,27 3,33 19,4 33,68 3,10 51,63 1,15 9,53 14,3 66,51 21,1 3,58 13,24 7,19 31,64 31,5 11,11 20,15 41,1 39,57 5,43 19,62 7,13 61,68 27,67 69,52 47,63 22,1 30,55 3,30 37,51 9,27 7,9 15,23 8,55 29,63 3,63 2,39 17,70 63,46 5,40 15,11 3,27 44,51 53,55 7,15 49,59 41,63 69,65 8,27 13,26 3,3 29,64 64,61 30,9 53,62 7,61 25,59 67,69 3,17 28,53 60,55 53,63 5,16 59,67 55,56 4,21 15,67 41,60 4,59 70,45 3,55 9,13 43,63 45,65 8,59 23,8 63,48 55,64 3,1 32,7 39,63 69,49 3,24 54,57 9,37 25,66 48,69 59,49 4,1 47,56 62,59 21,8 1,54 14,23 56,45 56,49 63,49 19,25 27,2 29,62 41,65 10,39 6,43 61,54 65,39 61,46 51,39 65,65 35,55 22,61 16,9 63,51 1,46 5,51 11,26 13,22 3,54 62,49 13,5 11,46 20,67 63,57 25,55 9,44 19,30 23,69 13,31 53,47 17,63 28,7 16,65 23,62 6,9 5,31 69,33 35,60 68,69 61,49 21,19 29,61 13,25 2,49 7,5 43,68 63,41 3,45 8,11 69,69 32,57 25,5 10,25 5,21 55,66 47,57 3,7 21,18 23,65 13,9 29,8 58,45 61,44 5,61 63,44 33,61 2,45 21,6 5,17 7,21 55,48 39,59 52,65 14,51 5,35 19,33 5,39 8,15 11,23 15,63 47,64 54,55 42,55 59,41 49,66 37,55 8,5 7,37 26,57 58,67 9,5 9,24 28,11 14,41 17,17 15,7 1,8 65,62 46,61 69,62 15,30 62,57 49,55 51,54 1,9 2,37 60,59 11,44 21,10 3,15 55,65 7,2 70,37 55,61 1,5 0,49 29,65 9,11 67,44 29,6 3,11 53,58 53,41 1,38 5,47 21,5 17,69 7,39 54,47 67,55 61,66 53,52 11,31 7,27 9,3 18,15 45,58 10,53 7,24 7,55 37,65 11,17 49,68 58,43 55,63 33,59 59,65 65,61 63,64 6,49 19,64 31,61 3,13 1,4 1,49 23,12 5,29 5,49 54,65 13,10 25,69 3,21 43,47 43,65 41,53 19,1 24,3 32,5 60,49 9,57 39,54 30,3 67,63 5,32 3,32 58,47 65,59 16,1 55,53 39,61 5,36 31,69 20,69 63,67 65,47 17,1 1,43 51,51 14,29 13,33 67,45 17,66 64,49 57,41 25,0 19,65 61,64 57,47 31,67 5,54 68,51 5,53 69,53 1,11 9,7 49,65 66,39 35,59 19,18 56,43 44,57 27,7 24,69 2,9 38,63 13,29 32,3 7,36 57,49 33,63 19,10 57,67 51,46 2,11 11,4 3,41 37,60 68,57 66,47 13,6 26,69 21,11 14,31 57,50 56,57 43,59 65,41 2,33 33,12 2,21 49,53 11,41 35,52 1,13 41,59 29,67 64,67 3,23 62,61 9,47 7,38 25,1 5,62 35,51 65,43 49,69 27,3 6,33 33,3 25,67 17,3 69,37 63,70 7,11 45,63 19,5 11,29 5,55 9,51 49,57 23,1 20,61 65,44 69,45 42,59 1,56 22,21 15,48 47,67 63,45 15,61 47,69 60,61 58,59 1,37 1,39 3,51 11,2 6,1 55,59 7,57 3,29 9,49 7,23 25,3 31,55 17,61 1,1 31,0 57,65 17,21 6,29 12,5 7,49 5,10 15,34 5,28 3,6 12,29 9,14 34,63 51,57 69,64 19,39 32,63 63,69 11,45 9,34 45,68 37,61 13,46 18,17 14,17 7,60 27,62 13,47 13,61 5,9 1,36 59,51 29,4 43,70 7,51 44,59 15,15 57,43 27,59 6,17 13,48 20,7 55,69 7,3 15,1 5,4 57,51 56,59 60,51 21,69 5,48 29,56 61,61 18,3 13,45 48,63 47,65 37,59 55,43 50,57 3,53 5,56 23,68 13,41 66,53 2,43 69,63 18,9 64,53 45,62 8,1 13,36 19,61 27,65 18,67 28,65 45,64 65,57 46,69 36,55 70,59 67,49 54,61 67,51 65,68 20,1 44,61 5,59 7,44 13,39 49,52 18,63 29,13 45,66 29,2 66,59 10,37 26,59 9,33 3,56 1,28 25,13 45,67 9,25 69,68 12,53 12,61 9,43 25,12 15,4 50,55 31,58 7,58 50,65 33,15 11,15 8,35 5,34 31,59 69,41 33,9 61,59 3,2 35,62 1,25 5,22 1,44 47,50 9,19 10,21 62,63 9,1 12,41 63,42 45,55 25,14 3,9 12,1 7,8 15,29 0,41 11,18 15,65 21,13 63,39 9,41 23,35 37,66 61,15 6,67 4,67 23,44 29,27 68,27 21,30 51,4 41,47 63,19 45,21 37,43 23,59 57,40 35,44 23,55 65,64 31,31 57,3 63,7 25,17 18,31 27,17 67,22 39,56 65,66 23,23 52,17 41,39 61,12 17,49 29,29 60,29 29,7 53,19 17,36 15,33 47,29 30,39 11,57 25,36 55,54 38,17 37,9 49,4 13,44 29,15 36,13 16,37 65,11 57,5 21,15 17,7 38,19 13,55 57,38 49,10 23,13 30,35 34,69 27,27 1,61 11,21 1,66 41,37 21,49 37,25 51,45 29,39 33,47 49,7 29,42 31,45 42,19 35,9 41,2 26,33 31,41 16,25 67,37 41,18 40,21 63,20 39,47 59,36 20,57 1,65 5,65 37,41 41,40 26,63 41,50 31,39 46,27 59,22 61,17 29,11 21,39 20,33 52,11 57,39 51,15 59,3 61,28 51,37 59,13 23,10 58,7 53,11 37,39 23,41 35,8 21,7 22,23 67,5 67,1 48,35 29,43 67,7 59,2 23,37 51,26 9,12 13,65 20,43 34,33 11,19 51,67 49,5 63,5 48,25 43,33 35,42 30,19 32,27 46,35 31,49 48,39 11,63 34,41 40,37 7,63 63,17 47,23 11,40 53,44 33,36 35,63 68,31 35,25 65,25 15,9 20,25 36,19 63,13 39,7 62,39 19,38 25,51 49,23 33,42 61,47 65,37 51,27 44,31 27,47 45,23 67,57 67,56 28,13 25,28 70,33 43,19 25,15 47,10 25,23 42,43 52,61 1,68 48,19 9,21 67,24 15,59 3,64 27,23 9,69 28,35 55,5 47,45 28,31 29,41 21,29 37,33 42,21 3,19 27,29 15,21 64,11 63,61 25,8 60,43 66,11 27,45 3,69 5,67 50,23 41,32 45,61 39,53 65,26 15,39 55,8 21,47 6,13 66,25 15,50 51,11 25,9 43,28 35,36 37,23 18,23 44,49 43,1 31,53 51,6 63,30 53,37 69,2 48,31 52,23 15,52 67,33 17,33 50,19 52,35 47,17 57,15 43,5 59,59 21,59 37,24 51,5 33,24 55,11 39,6 15,51 62,19 56,29 67,3 7,67 53,30 43,39 22,25 51,33 62,35 26,23 65,63 51,23 15,53 15,26 47,19 21,35 57,28 1,60 69,18 11,53 35,34 32,49 18,21 1,67 67,25 57,10 55,37 25,18 0,59 59,17 41,21 63,4 39,24 55,16 61,67 55,14 17,53 15,37 62,23 38,41 50,27 70,13 32,31 45,29 61,19 55,2 39,38 43,24 47,20 50,11 25,41 47,18 42,7 24,55 38,49 53,24 63,23 24,29 23,29 19,53 45,1 29,19 17,29 28,41 43,43 31,7 69,15 61,27 38,33 57,7 57,35 23,21 37,31 57,13 37,30 39,4 63,11 67,13 41,23 50,39 55,9 1,21 23,7 45,28 14,15 26,41 29,47 43,15 51,28 31,43 31,17 29,37 39,11 49,8 23,9 55,25 41,17 60,9 37,49 19,41 53,23 34,13 35,3 21,56 41,35 17,57 33,21 35,23 23,26 35,11 48,41 49,2 59,4 45,9 37,37 59,15 19,58 35,27 67,66 11,43 63,31 49,24 59,16 29,49 35,21 67,19 17,13 18,53 39,26 20,13 37,15 17,59 3,25 60,31 35,19 26,39 59,38 25,63 69,11 53,57 43,49 11,59 17,45 65,29 20,21 57,17 53,68 1,57 35,26 26,47 68,37 31,40 13,17 53,31 36,37 65,5 40,19 55,57 4,69 15,47 5,5 66,55 36,5 59,23 64,19 69,51 36,53 56,37 47,1 42,15 67,12 9,60 45,3 19,26 17,19 24,23 9,61 57,4 18,43 24,53 43,36 21,55 52,37 35,31 57,27 63,37 55,39 38,1 32,37 40,5 45,42 69,23 31,35 65,1 35,47 55,15 13,20 41,49 29,16 53,43 26,55 67,17 44,33 56,13 21,51 36,17 23,20 29,18 34,27 51,18 33,65 38,9 48,15 58,35 16,29 35,39 43,46 49,33 19,40 65,15 36,11 47,0 39,32 47,22 36,31 23,34 45,17 45,39 63,38 53,7 46,5 27,53 59,55 69,5 45,5 55,29 47,37 51,69 47,25 67,21 33,27 43,17 69,7 35,24 37,7 49,3 27,11 59,12 46,3 53,67 31,26 48,29 29,25 37,44 51,17 29,48 36,21 13,13 51,29 9,39 57,29 43,55 31,13 59,5 34,1 41,43 31,27 67,27 55,21 25,57 1,55 38,11 67,31 50,7 31,33 19,23 39,44 43,30 52,7 42,37 31,25 23,57 20,37 31,29 39,46 23,11 66,7 55,6 61,26 13,63 7,43 46,33 32,17 35,46 43,22 41,7 53,12 45,20 13,57 61,29 17,24 64,23 7,64 57,1 21,37 30,31 53,29 47,2 49,30 56,69 51,35 55,20 19,21 19,29 61,14 55,31 39,16 53,9 47,3 44,13 21,38 33,8 33,31 33,29 59,26 50,15 19,31 21,60 35,7 29,51 52,15 46,47 67,30 15,27 65,20 45,37 27,15 31,21 49,46 17,54 59,69 19,35 23,45 55,27 27,37 59,27 49,38 17,47 29,46 25,45 21,21 59,33 61,33 61,39 25,37 65,18 22,39 55,32 43,4 43,26 45,35 67,29 41,41 16,21 25,22 2,69 25,44 55,18 32,29 63,14 40,15 69,24 43,31 53,50 61,41 51,3 59,18 39,39 23,15 33,17 26,49 21,17 41,66 35,43 27,43 35,18 37,19 33,11 44,1 24,31 47,8 48,45 68,39 65,3 61,2 27,24 62,37 37,5 33,25 49,35 69,3 27,52 8,67 41,67 37,69 65,17 63,24 41,46 37,29 69,8 10,11 63,35 25,21 55,3 49,13 20,47 17,25 63,16 22,57 57,59 47,35 37,47 34,39 47,11 41,25 37,3 49,29 53,32 37,1 43,45 59,20 16,11 31,51 45,25 15,54 38,13 28,21 69,1 38,29 51,31 9,59 39,43 16,57 0,31 11,13 26,35 7,69 43,67 25,29 35,15 23,46 31,44 68,35 17,27 9,64 18,39 45,19 37,8 42,1 13,43 32,47 51,36 17,56 2,65 57,23 61,13 35,41 57,30 30,13 55,0 46,41 35,35 37,45 18,55 58,11 45,26 51,13 37,13 21,43 31,47 55,17 34,15 61,10 55,40 27,31 25,39 61,21 28,27 41,26 52,9 25,33 44,9 69,6 41,34 19,49 38,21 35,66 56,23 49,9 36,49 28,37 53,38 47,44 67,11 33,5 47,31 6,69 51,60 17,39 14,59 55,41 39,51 39,5 15,35 13,59 67,0 39,33 56,33 23,58 51,42 47,55 63,25 37,21 45,57 61,7 46,17 20,23 62,5 21,31 63,3 62,1 69,13 9,65 25,53 66,3 65,27 45,41 39,21 38,5 45,14 21,42 5,66 47,47 61,1 11,68 61,3 27,41 19,37 65,21 35,48 19,17 27,54 43,6 37,17 1,52 18,35 24,43 61,18 53,27 35,22 38,35 13,69 21,23 47,14 66,17 23,39 67,23 44,37 39,19 27,60 29,50 43,27 56,1 15,43 49,19 42,53 61,9 25,35 57,20 49,16 43,7 27,19 27,42 18,49 23,49 59,29 30,51 1,51 43,16 45,27 1,69 37,42 59,14 53,66 59,1 57,69 34,3 19,51 33,33 24,25 53,13 53,28 43,25 15,58 55,42 15,25 25,19 43,42 43,53 53,49 40,13 23,56 46,55 43,41 15,44 31,28 54,69 39,3 13,53 29,31 65,13 57,53 67,15 21,33 33,41 27,38 43,3 29,24 47,12 14,55 52,41 19,32 62,9 64,33 26,11 53,3 26,15 13,51 11,58 35,33 31,22 34,51 3,67 39,17 16,41 51,25 13,67 41,31 23,48 65,7 32,41 19,57 33,18 39,67 67,35 11,14 45,49 25,31 43,35 64,29 39,27 49,21 9,66 63,33 58,33 62,31 60,17 19,52 34,47 29,9 41,29 34,29 25,52 51,20 19,3 21,53 62,7 55,24 35,49 37,67 19,47 37,11 57,33 51,68 36,1 61,37 46,39 16,43 16,51 54,5 45,11 51,58 60,33 51,49 65,32 11,64 37,35 59,19 39,15 22,31 7,59 16,19 23,19 24,49 57,19 68,21 21,45 55,36 25,25 54,35 62,27 32,1 40,29 11,70 33,37 23,63 54,9 43,34 23,43 67,4 25,20 32,33 13,37 16,45 42,13 49,25 23,51 65,9 17,60 21,36 53,2 63,32 65,31 32,15 25,47 11,55 55,22 53,33 23,61 42,39 26,17 57,22 52,31 45,16 49,31 1,17 41,8 44,53 49,1 18,59 35,67 43,9 9,10 39,45 55,19 61,69 57,42 53,15 45,45 67,32 54,41 20,51 38,37 14,37 63,21 51,70 39,48 22,41 68,15 39,23 15,69 11,3 19,55 25,49 45,47 29,32 39,9 29,23 21,27 39,25 53,69 43,13 69,10 45,7 17,55 33,51 53,5 59,8 51,7 58,25 41,3 55,26 41,27 30,25 59,37 53,17 29,17 53,59 34,21 51,21 41,9 1,63 66,29 32,45 17,51 11,56 31,23 19,46 68,13 45,24 35,17 55,1 28,15 53,51 53,4 39,37 17,43 63,29 59,25 40,9 70,17 70,25 49,17 24,33 19,45 36,27 25,61 67,67 38,23 35,13 17,9 33,19 22,33 27,49 56,53 26,27 21,54 27,44 29,22 9,62 59,35 30,43 33,45 69,20 18,27 41,11 49,11 0,63 21,41 41,44 23,47 30,15 37,46 43,21 24,59 24,17 21,57 11,32 65,22 1,33 39,41 25,27 1,53 43,56 49,34 21,28 58,3 34,31 27,26 52,1 13,16 17,41 69,39 69,29 40,57 15,12 59,40 66,9 29,34 69,21 7,65 43,51 41,5 49,27 23,53 55,12 53,22 27,50 68,5 55,7 45,8 61,22 27,9 53,39 35,37 65,19 45,22 53,35 19,27 69,28 57,26 53,1 65,2 46,31 27,39 60,35 41,13 19,43 27,21 58,53 61,0 51,19 23,33 40,59 44,19 12,57 27,18 45,31 13,66 9,68 45,15 29,35 33,35 17,37 36,35 65,35 39,30 57,18 24,41 19,50 13,27 47,13 35,68 61,25 6,63 47,27 46,37 47,9 49,32 64,3 47,21 9,63 43,23 54,29 33,13 39,31 59,70 27,33 39,55 29,45 19,59 59,24 37,27 68,1 25,43 58,31 31,12 40,35 22,53 57,31 65,33 1,31 57,25 53,26 40,23 39,1 39,49 43,2 28,47 64,27 15,14 35,1 63,27 33,39 16,33 63,10 15,13 31,11 31,15 44,45 15,55 39,29 49,39 49,36 27,13 59,9 42,31 33,38 69,17 55,35 39,35 59,39 26,31 44,5 39,13 36,3 23,17 29,21 55,23 24,39 69,9 10,63 47,15 65,23 48,5 53,20 38,27 65,36 44,47 55,13 4,63 61,23 63,15 10,57 33,20 31,20 11,39 33,53 41,45 67,18 22,35 51,9 1,59 27,25 67,9 49,43 49,37 50,3 15,57 59,31 27,35 69,35 24,37 23,25 45,40 67,64 27,51 53,21 64,5 17,40 66,35 17,35 45,50 54,17 31,37 66,13 17,12 49,12 35,53 41,28 33,23 27,20 13,68 28,29 49,22 47,41 56,5 39,2 64,15 40,53 59,11 62,15 17,28 51,41 11,67 67,16 41,48 37,68 31,34 61,5 43,37 21,44 66,27 47,7 51,34 30,37 3,65 53,48 12,65 5,69 15,19 22,51 57,9 21,25 45,33 36,39 44,39 22,15 47,33 35,10 29,33 23,50 59,7 50,41 49,15 63,9 47,5 57,21 11,69 69,19 37,40 29,53 17,31 35,29 60,5 14,69 65,8 57,11 25,11 23,27 55,49 15,18 69,25 40,41 51,43 64,7 21,48 30,49 48,43 53,25 61,11 33,10 35,65 58,15 43,11 51,1 45,44 24,15 43,29 12,55 19,12 51,14 35,5 45,13 40,11 41,15 45,12 25,62 9,67 31,19 63,40 27,30 37,14 49,63 43,10 46,7 41,33 17,11 69,27 60,39 59,21 19,16 12,11 61,31 50,29 68,9 15,49 49,41 20,27 35,45 47,26 39,52 42,11 59,45 54,11 33,43 32,23 56,9 63,1 35,16 27,46 9,55 63,34 41,19 69,31 2,68 31,32 50,67 19,44 25,64 64,22 14,12 19,48 54,36 21,58 30,2 50,22 67,58 22,56 2,46 63,8 2,55 58,10 41,62 62,2 62,17 4,29 30,58 4,49 56,62 42,70 42,0 70,57 46,64 48,37 18,57 41,10 41,16 22,64 20,30 6,23 40,24 53,16 64,65 12,44 5,8 58,29 23,60 36,69 40,22 32,2 46,65 28,30 19,24 26,20 28,48 27,58 4,46 31,62 15,28 29,28 8,32 33,28 58,68 1,24 44,17 58,60 66,16 4,62 4,30 40,33 16,59 38,48 6,27 36,14 35,32 20,24 30,62 18,52 55,10 32,62 64,54 62,25 4,53 36,28 52,4 31,70 62,38 11,52 20,0 18,2 23,70 60,66 16,56 31,60 46,12 6,64 38,10 4,50 8,62 50,45 58,13 44,67 35,30 29,12 68,33 19,56 29,38 6,50 38,46 20,68 57,68 66,31 29,54 37,2 49,40 20,44 32,58 6,61 6,19 50,20 32,8 62,20 64,16 6,66 14,49 56,19 56,64 26,66 17,46 38,22 56,41 11,50 32,52 42,25 29,30 31,66 64,25 10,45 69,4 28,66 24,67 12,16 14,60 31,68 36,46 14,32 34,44 54,10 48,9 54,37 68,16 19,42 16,0 42,33 30,60 41,22 60,2 44,32 65,6 16,14 26,61 52,69 62,24 47,38 45,10 44,4 42,36 28,59 30,10 26,68 17,10 50,5 41,52 36,44 36,9 17,50 8,53 30,32 44,35 33,2 15,0 22,28 60,69 42,14 26,25 10,48 46,9 16,18 67,70 20,35 4,20 7,30 30,45 4,66 26,62 21,32 20,28 46,6 61,16 20,39 66,20 6,22 70,22 64,36 26,24 70,14 24,28 0,68 40,28 51,62 22,26 19,60 47,68 3,60 54,64 0,70 66,67 51,8 4,26 20,32 52,64 22,55 48,14 56,6 70,34 62,29 52,18 68,24 63,0 17,34 18,68 53,6 26,64 70,31 50,66 16,64 4,58 40,32 48,65 32,39 58,63 14,68 60,14 60,22 8,50 16,42 2,31 60,15 52,70 2,18 50,16 26,12 12,34 62,12 34,46 1,42 62,4 30,66 35,14 29,36 50,0 60,21 54,24 50,47 34,52 38,8 54,22 51,2 6,45 38,59 46,40 58,22 63,6 54,70 16,30 19,34 66,66 0,69 39,36 6,21 37,22 54,56 64,26 49,44 50,12 70,19 38,15 21,0 27,32 3,40 0,44 2,52 16,54 34,38 48,24 16,39 26,53 2,27 68,36 10,26 6,24 24,13 35,70 30,0 52,13 64,69 54,19 28,24 64,28 34,49 6,55 44,60 2,54 5,64 14,22 28,40 34,62 28,58 30,47 20,38 10,62 60,68 8,0 22,34 24,30 13,52 22,70 27,48 3,20 40,8 67,28 12,60 36,56 22,27 20,26 22,43 24,44 58,4 33,62 44,66 20,48 48,67 28,55 24,62 30,40 18,48 17,42 41,12 28,54 4,56 6,58 48,34 60,24 46,8 8,21 50,38 70,27 33,32 17,48 8,43 50,18 47,70 12,62 17,68 35,56 33,30 66,15 25,30 10,12 16,35 46,4 54,6 11,12 22,60 32,9 60,6 42,67 67,6 26,6 14,56 18,26 32,43 70,10 47,6 12,32 18,1 15,42 32,48 2,51 45,70 10,33 26,42 31,42 4,42 32,53 59,64 18,36 59,62 68,14 28,60 20,31 54,62 10,35 64,38 28,63 62,67 64,0 10,58 46,36 5,0 36,15 10,68 32,44 12,12 20,34 33,44 39,42 19,36 58,62 1,62 15,32 14,35 50,36 54,68 14,38 47,24 56,60 64,18 60,16 69,0 53,70 28,50 34,5 66,6 32,54 42,69 6,60 57,66 4,22 0,20 14,46 17,18 37,16 34,66 33,6 41,0 60,30 33,64 41,30 43,50 50,61 8,63 52,32 44,69 23,0 6,6 46,46 3,46 31,18 58,40 14,20 8,51 40,64 20,10 66,70 63,12 41,4 49,18 43,8 60,18 36,33 42,51 50,25 62,21 57,24 10,32 45,6 2,42 52,26 46,19 32,64 38,43 38,64 19,14 28,9 0,7 70,49 36,57 14,24 14,40 63,18 0,18 54,26 18,69 56,31 52,50 12,50 66,28 20,63 4,39 12,21 60,44 34,70 69,14 64,50 4,12 32,6 48,68 6,41 14,14 52,59 40,20 1,10 2,2 34,30 65,34 9,70 24,4 54,60 18,16 19,70 35,12 39,8 14,5 30,20 48,36 52,40 24,22 36,2 64,37 53,46 60,28 17,52 32,10 56,47 9,58 8,46 53,0 20,22 37,48 17,58 60,38 62,55 6,16 0,66 66,58 20,4 60,62 42,48 46,60 43,54 42,17 24,70 0,1 40,58 24,2 26,18 30,59 18,38 38,62 5,70 23,42 24,8 4,48 55,52 70,0 7,28 25,26 66,43 40,69 21,2 58,70 6,4 47,4 56,38 10,46 58,23 47,30 41,42 39,14 44,8 25,58 29,44 36,38 22,32 8,26 47,42 16,58 47,36 50,14 35,2 13,30 31,46 60,10 55,60 54,46 46,18 28,68 28,32 54,32 16,32 40,44 32,30 10,59 44,30 58,18 24,27 12,25 56,42 11,6 1,14 30,18 0,10 12,0 36,34 22,38 64,8 7,10 4,57 39,18 51,44 5,50 53,18 43,44 66,60 60,8 32,14 14,70 62,60 36,43 64,1 0,56 48,49 2,26 14,47 2,20 42,3 12,43 57,48 15,36 61,40 40,42 29,20 70,63 42,35 51,16 54,44 46,63 66,30 56,46 0,42 38,47 19,66 16,15 44,18 28,1 49,58 16,49 30,5 56,50 18,60 64,35 2,66 48,38 34,6 58,16 56,26 28,38 6,20 65,40 16,38 6,39 40,52 38,36 0,55 52,27 30,54 62,34 61,58 65,10 50,53 50,28 10,70 4,38 63,66 25,50 60,58 46,15 41,36 26,8 7,34 53,14 52,60 50,35 5,44 16,34 16,46 70,8 56,39 14,44 39,64 70,38 0,4 22,52 20,29 66,12 31,8 30,44 60,25 36,67 50,24 17,30 54,50 56,0 25,42 24,18 14,66 53,8 62,3 39,28 9,30 2,67 12,31 0,38 56,3 56,55 12,49 68,28 64,21 38,20 70,9 21,24 60,41 6,57 65,28 54,14 51,0 0,67 64,24 44,43 25,38 20,45 2,7 44,12 50,13 13,58 43,38 54,25 7,48 48,3 56,17 1,34 31,48 10,64 56,27 38,39 38,32 42,58 68,52 68,34 60,56 36,64 2,6 18,61 64,48 34,58 48,1 70,3 62,6 64,43 6,47 7,68 51,66 36,59 70,11 49,28 2,44 45,56 55,44 57,70 56,52 27,28 16,40 52,5 56,34 69,26 6,36 69,60 52,52 34,14 15,24 24,47 44,58 44,64 54,27 70,7 8,57 33,14 63,22 60,7 44,23 53,60 28,39 30,22 9,28 67,20 1,50 38,30 40,36 3,42 59,68 57,8 56,63 44,56 58,5 18,20 68,19 62,56 40,60 52,57 60,57 44,63 44,29 58,41 60,0 60,70 24,34 56,12 63,36 46,34 4,47 63,58 16,36 58,27 8,4 28,17 48,53 42,34 66,19 70,56 16,22 18,65 25,56 58,32 12,54 64,59 13,56 58,26 50,2 31,38 66,8 41,70 42,18 6,8 18,19 64,32 28,51 24,68 40,65 60,23 48,23 24,9 7,62 47,52 11,16 22,22 30,53 26,21 31,30 66,54 46,14 38,38 24,54 3,44 60,50 4,64 23,4 24,10 19,22 55,70 49,26 36,45 70,30 48,42 4,34 48,62 23,40 59,0 0,62 30,63 24,14 21,34 28,33 18,8 24,6 14,62 59,54 1,30 40,26 45,32 55,46 64,46 61,50 37,12 10,14 62,47 10,10 30,7 48,18 56,58 20,42 13,8 7,6 12,3 61,24 8,61 45,46 16,31 2,36 68,67 26,13 38,28 46,67 27,16 48,27 56,54 11,22 68,43 10,42 45,30 8,48 56,48 48,46 39,70 8,44 32,21 0,14 3,4 48,58 35,0 14,53 14,8 64,47 22,54 27,0 4,31 61,8 5,52 64,64 28,4 48,56 54,3 45,18 59,28 42,62 11,62 28,26 40,17 62,18 6,14 62,30 62,16 28,64 55,50 24,26 26,60 30,8 30,16 57,0 40,0 62,40 48,44 19,0 66,18 38,54 56,24 24,46 26,0 6,44 28,6 36,66 44,6 10,40 18,37 44,7 59,34 8,64 59,30 65,54 50,42 22,65 4,23 22,58 52,10 33,46 30,30 61,30 38,58 20,40 22,66 68,25 4,6 70,41 22,37 ================================================ FILE: exm/aoc/2024/aoc_2024_18_questions.txt ================================================ --- Day 18: RAM Run --- You and The Historians look a lot more pixelated than you remember. You're inside a computer at the North Pole! Just as you're about to check out your surroundings, a program runs up to you. "This region of memory isn't safe! The User misunderstood what a pushdown automaton is and their algorithm is pushing whole bytes down on top of us! Run!" The algorithm is fast - it's going to cause a byte to fall into your memory space once every nanosecond! Fortunately, you're faster, and by quickly scanning the algorithm, you create a list of which bytes will fall (your puzzle input) in the order they'll land in your memory space. Your memory space is a two-dimensional grid with coordinates that range from 0 to 70 both horizontally and vertically. However, for the sake of example, suppose you're on a smaller grid with coordinates that range from 0 to 6 and the following list of incoming byte positions: 5,4 4,2 4,5 3,0 2,1 6,3 2,4 1,5 0,6 3,3 2,6 5,1 1,2 5,5 2,5 6,5 1,4 0,4 6,4 1,1 6,1 1,0 0,5 1,6 2,0 Each byte position is given as an X,Y coordinate, where X is the distance from the left edge of your memory space and Y is the distance from the top edge of your memory space. You and The Historians are currently in the top left corner of the memory space (at 0,0) and need to reach the exit in the bottom right corner (at 70,70 in your memory space, but at 6,6 in this example). You'll need to simulate the falling bytes to plan out where it will be safe to run; for now, simulate just the first few bytes falling into your memory space. As bytes fall into your memory space, they make that coordinate corrupted. Corrupted memory coordinates cannot be entered by you or The Historians, so you'll need to plan your route carefully. You also cannot leave the boundaries of the memory space; your only hope is to reach the exit. In the above example, if you were to draw the memory space after the first 12 bytes have fallen (using . for safe and # for corrupted), it would look like this: ...#... ..#..#. ....#.. ...#..# ..#..#. .#..#.. #.#.... You can take steps up, down, left, or right. After just 12 bytes have corrupted locations in your memory space, the shortest path from the top left corner to the exit would take 22 steps. Here (marked with O) is one such path: OO.#OOO .O#OO#O .OOO#OO ...#OO# ..#OO#. .#.O#.. #.#OOOO Simulate the first kilobyte (1024 bytes) falling onto your memory space. Afterward, what is the minimum number of steps needed to reach the exit? --- Part Two --- The Historians aren't as used to moving around in this pixelated universe as you are. You're afraid they're not going to be fast enough to make it to the exit before the path is completely blocked. To determine how fast everyone needs to go, you need to determine the first byte that will cut off the path to the exit. In the above example, after the byte at 1,1 falls, there is still a path to the exit: O..#OOO O##OO#O O#OO#OO OOO#OO# ###OO## .##O### #.#OOOO However, after adding the very next byte (at 6,1), there is no longer a path to the exit: ...#... .##..## .#..#.. ...#..# ###..## .##.### #.#.... So, in this example, the coordinates of the first byte that prevents the exit from being reachable are 6,1. Simulate more of the bytes that are about to corrupt your memory space. What are the coordinates of the first byte that will prevent the exit from being reachable from your starting position? (Provide the answer as two integers separated by a comma with no other characters.) ================================================ FILE: exm/aoc/2024/aoc_2024_19.adb ================================================ -- Solution to Advent of Code 2024, Day 19 ------------------------------------------- -- Linen Layout -- -- https://adventofcode.com/2024/day/19 -- Copy of questions in: aoc_2024_19_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_19 is use AoC_Toolbox, HAT, Interfaces; -- input_name : constant VString := +"mini"; nt : constant := 8; nd : constant := 8; input_name : constant VString := +"aoc_2024_19"; nt : constant := 447; nd : constant := 400; towel : array (1 .. nt) of VString; design : array (1 .. nd) of VString; max_len_design : constant := 60; type Memo_Type is array (1 .. max_len_design) of Integer_64; memo_clear : Memo_Type; -- memo_clear: emulate `others =>`. unknown : constant := -1; r : array (Part_Type) of Integer_64; procedure Read_Data is c : Character; f : File_Type; s : VString; begin Open (f, input_name & ".txt"); for i in 1 .. nt loop s := +""; loop Get (f, c); exit when c = ','; s := s & c; exit when End_Of_Line (f); end loop; if c = ',' then Get (f, c); -- Consume ' ' after the ','. end if; towel (i) := s; end loop; Skip_Line (f, 2); for i in 1 .. nd loop Get_Line (f, design (i)); end loop; Close (f); for i in memo_clear'Range loop memo_clear (i) := unknown; end loop; end Read_Data; procedure Solve_Method_Memoization_by_Index is memo : Memo_Type; function Count_Options (design : VString; first, length_design : Positive) return Integer_64 is last : Natural; options : Integer_64; begin if memo (first) >= 0 then return memo (first); end if; -- Number is unknown -> we have to compute it... options := 0; for i in 1 .. nt loop last := first + Length (towel (i)) - 1; if last <= length_design and then Slice (design, first, last) = towel (i) then -- Match if last = length_design then options := options + 1; else options := options + Count_Options (design, last + 1, length_design); end if; end if; end loop; memo (first) := options; return options; end Count_Options; opt : Integer_64; begin r (part_1) := 0; r (part_2) := 0; for i in 1 .. nd loop memo := memo_clear; opt := Count_Options (design (i), 1, Length (design (i))); if opt > 0 then r (part_1) := r (part_1) + 1; r (part_2) := r (part_2) + opt; end if; end loop; end Solve_Method_Memoization_by_Index; procedure Solve_Method_Triage_by_Initial is -- Lists of towels, bucketed by their initial: towel_after_initial : array (Character, 1 .. nt) of VString; -- Number of towels starting by the character in question: towels_with_initial : array (Character) of Natural; memo : Memo_Type; -- memo_clear: emulate `others =>`. function Count_Options (design : VString; first, length_design : Positive) return Integer_64 is length_towel, last : Natural; options : Integer_64; c : Character; begin if memo (first) >= 0 then return memo (first); end if; -- Number is unknown -> we have to compute it... options := 0; c := Element (design, first); for i in 1 .. towels_with_initial (c) loop length_towel := Length (towel_after_initial (c, i)) + 1; last := first + length_towel - 1; if last <= length_design and then Slice (design, first + 1, last) = towel_after_initial (c, i) then -- Match if last = length_design then options := options + 1; else options := options + Count_Options (design, last + 1, length_design); end if; end if; end loop; memo (first) := options; return options; end Count_Options; opt : Integer_64; c : Character; s : VString; begin for ini in Character loop towels_with_initial (ini) := 0; end loop; -- Prepare hashing by the towel's first character. for i in 1 .. nt loop s := towel (i); c := Element (s, 1); towels_with_initial (c) := towels_with_initial (c) + 1; towel_after_initial (c, towels_with_initial (c)) := Slice (s, 2, Length (s)); end loop; r (part_1) := 0; r (part_2) := 0; for i in 1 .. nd loop memo := memo_clear; opt := Count_Options (design (i), 1, Length (design (i))); if opt > 0 then r (part_1) := r (part_1) + 1; r (part_2) := r (part_2) + opt; end if; end loop; end Solve_Method_Triage_by_Initial; procedure Solve_Method_Full_Hashing is use Hash_Maps; memo : Hash_Map_Type; function Count_Options (design : VString) return Integer_64 is length_design, length_towel : Natural; options : Integer_64; begin Find (memo, design, unknown, options); if options /= unknown then return options; end if; -- Number is unknown -> we have to compute it... options := 0; length_design := Length (design); for i in 1 .. nt loop length_towel := Length (towel (i)); if length_towel <= length_design and then Slice (design, 1, length_towel) = towel (i) then -- Match if length_towel = length_design then options := options + 1; else options := options + Count_Options (Slice (design, length_towel + 1, length_design)); end if; end if; end loop; Insert (memo, design, options, False, options); return options; end Count_Options; opt : Integer_64; begin Clear (memo); r (part_1) := 0; r (part_2) := 0; for i in 1 .. nd loop opt := Count_Options (design (i)); if opt > 0 then r (part_1) := r (part_1) + 1; r (part_2) := r (part_2) + opt; end if; end loop; end Solve_Method_Full_Hashing; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; type Method is (m1, m2, m3); choice : constant Method := m2; begin Read_Data; case choice is when m1 => -- Simple method with memoization (used for sending the answer to AoC). -- Time HAC: 13.4 seconds; time GNAT (mode: Fast_Unchecked): 0.84 seconds. Solve_Method_Memoization_by_Index; when m2 => -- Method with memoization and bucket triage by the towel's initial. -- Time HAC: 3.8 seconds; time GNAT (mode: Fast_Unchecked): 0.17 seconds. Solve_Method_Triage_by_Initial; when m3 => -- Method with memoization and hashing of the design string (idea: J.C. Moyer, -- https://github.com/jcmoyer/puzzles/blob/master/AdventOfCode2024/src/day19.adb). -- Adapted to our HAC-compatible Hash Maps (slower). -- Time HAC: 14.5 seconds; time GNAT (mode: Fast_Unchecked): 0.89 seconds. -- J.C. Moyer's code, GNAT & Release mode: 0.09 seconds. Solve_Method_Full_Hashing; end case; if compiler_test_mode then if Trim_Left (+r (part_1)'Image) /= Argument (1) or Trim_Left (+r (part_2)'Image) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1:" & r (part_1)'Image); Put_Line (+"Part 2:" & r (part_2)'Image); -- Part 1: validated by AoC: 260 -- Part 2: validated by AoC: 639963796864990 end if; end AoC_2024_19; ================================================ FILE: exm/aoc/2024/aoc_2024_19.txt ================================================ buu, ubg, gub, wbwu, rrgrgg, urrwr, grwb, ubw, ubrbr, ubgb, gbw, rbrwgw, wbrr, brg, urugggr, wgbb, uwwu, urgg, wwwr, wrub, rbr, brgwb, gruwwb, rrwuwbu, rub, urwwgu, bbbw, wrr, uwr, grr, ggwrb, wbrwwbur, brbg, rubrg, urwbbru, brwww, bu, gugwww, rbww, buw, rurwgrug, rugwr, ruubww, bgbu, bgbw, wuu, burw, uuwb, rug, grw, bbrugwr, wurwbg, uurwu, bgu, ruu, bgrg, uguub, bgug, burubb, ubuugb, bbww, grbrr, gubbww, gwbgrwu, ggu, bubgurub, wguu, gww, wuuu, wbgb, bgrw, gug, rwwbw, uru, rwr, ubwr, uwb, bubwbwbw, gggwr, brr, gbrrg, rrww, gwg, uurubb, ruwwgrw, brgrru, gbgrwb, wbbwgg, wuwr, ruwuwbw, ggwrr, gbu, gwr, uur, wbgu, gbwgbgr, bbb, bubu, rwwggw, ruw, rbwuw, ugbbrwu, uurrgrg, bwwubwwg, gruu, ubgwu, rww, bur, ubwrg, wgb, gurbbr, rgbr, wuw, gbwuwru, rgwbrg, wbbr, wr, bgrrgb, wwb, urgwubww, bwurw, ur, rgbu, rrurw, ubbu, ubur, wrbwwr, uugww, grg, rwb, rgb, gguggu, rwgr, gurbubg, guwwr, wwbgb, grbgwruw, wug, bgb, rb, ruuubggr, www, wbgg, gguu, bbur, gbub, bwg, uuugbw, brb, brrrggu, buwu, rbrg, bg, bwgrbw, bwb, u, guw, gwrwur, brgb, wrru, ruugu, wrgrg, wbrb, rg, buwrr, ugr, uwru, bub, wbb, ubr, brrwr, wgbuu, bguu, bubw, ug, ugwg, wurbww, bwrbuwu, wwuwb, brbubg, wwub, g, brw, bbrwrgb, bgr, rbuwb, gwur, bggg, gbuu, wbu, rubw, bguug, bbw, wuguw, uwbwrgb, wwwub, wwbugg, gwubbb, rugwg, rgwwbru, ugbbubr, wrrgr, bubg, wwbwu, wbw, bbr, wbggugw, wurw, wwgwgr, burgr, wbgbu, wwwuuw, buguu, gwrugg, wwgugg, bburg, urwbu, rrug, ggb, ggbg, rguwbu, guru, wwr, ggurrw, brbbbubg, bbguuwgw, rru, ugwu, wbggr, rgrbww, rrubw, ubwurwg, gbr, rwrgw, wwguwbu, wggrr, wru, wrgbb, bgburwg, wruwwg, uuu, rugr, rwbw, bwwbr, bbbrgwu, br, ubb, bbu, urg, brbuggb, uw, rbug, wbbrgugb, rgu, uubgrrgw, bru, rwgbu, wrgw, gwb, bwbr, bgw, wgwg, wbgrwwg, wwwwgr, gg, gwgggu, ugwuu, gugur, gggbw, bwbwguu, uwbr, gw, wrgg, rugwbgg, uwg, urb, uwggb, urgggb, bbg, gwbr, uub, gbg, gwuu, buwrrw, rbu, wbbu, ru, rbbw, rgugrbwg, ggbgrw, ugrwwww, uwgbwu, wwbw, wurr, wrwrrr, rrw, rbb, rwrgr, bbwwg, rbg, bbbgrbrw, ruubwb, ubbg, gr, gwwbuuuw, bwgr, rrwwggu, bbuugb, guwwbg, rguw, rur, gwbbbbr, rbwr, wb, uuwrbb, uruwbrrr, bb, bbubu, gruguu, urr, bwbrb, rbru, ugu, ugg, rwbgu, rbbuug, uguw, grwbg, bbgrrr, gur, urw, gguwbb, rburuug, w, wg, ggw, wur, ubwuw, bwggugb, gwbu, wbrg, gbrgw, wrugur, rbgb, uwbrrubg, bbugugw, rwbgwur, ubwu, rw, wurwggr, gru, brur, gwbuw, uwu, gurbb, rgbgr, bgg, rggg, rrg, wbbg, wwu, wbr, uww, ggr, wbwgu, rrgu, rgw, rrwugrg, wgug, wrw, rbw, bug, bruuubrb, rubwurr, rwub, bbbru, rr, gwu, ubbgwg, gbww, wwrgrgg, wbg, rwu, ugurw, bubwg, wbubw, urwur, wgu, ubuuug, wubu, rrb, rrru, bwr, rbbubbru, gbwb, ggrruw, bww, uu, wu, wwuww, gwguwbb, ubu, uug, gubgr, rwggb, ubwug, wrg, r, wbwgwu, ww, gggw, rubrw, ugw, wgg, buguurwr, grb, bwur, wgr, uubb, wuwbwrb, urbwr, bw, ggg, bgrgr, buguwr, rbgbg, rrr, wgwbrr, rgg, rububg, bwu, ub, gbb, wub, uuw, wgw, bbub, wbggbb, wwwbgg, rgr, rbbbu, wuwb, grubu, rruwu, gubu, urwu, wrurg wuuwwuwubwggbgggggwgurgwubwwrbwubgrbuubrwwgwgbbwugw gwbwwrurbbgwuubwwugbrgrrwrgurgwgggubbugb bugwwguwrbbgrbguguurbrrbwubbbrrwrgbguwrurbgwbg bugwgguwrwbrggwugwgguwrwrwubrgwgwrububwrgugb ruurguwurrwbgrrgwwbrrwgbrrbrbwwurwruuuuwbbbuwgggbugb bgrurbguuurrgbgggrggrbgwbbwwguuggrwbwrgbgrrbugbgguwr guggrwuugwrbbrwrubbbgwrrwruururgwubwwrbguugb grugwgrgwrbuwwruurgwwwbrbrbwrurbbwrrubuwugb gbwrgrgbubugggrwuwbugrrrrgurbbwbbgbggguwruwuubrurwrg wuwbbgbrbruuubrbwwwugwbbwrugrwruwggwbbwbbuurbgr rgbrbwugwrrgggbruuubruuubggrrrrgrbrgrwwrgrrgg guwuggggurwbwugwgruwubwrubbuwbrwurwubugrburwuwbw brbgwugbgggruwwugbwbguuugubwgrrrrruguwugubu uggrbbbuwrggbgwbrbwggugwbrgrbwwwbrrbrbrwguwbbuugug wurububrurruguubggbubbgwgwgguwbguubbwbwwwbrrubuuruuubbwgur rrbbrbrwbbrrgrbbrugwggrwbwgwrrwwggugrbugwbugbbwrwub ggwubrwrbwrubuwwrbguubwrrbbbbbrruuuruwbbrrbubgr brgubwrbbbrrrbbggwuggrugrggwbbuuwwwubwbggwwubbrgw wbbwurbrbgbrruugbbgrbubuuguwuruubbbgurugwbrubr bwbbuwwurbwgrubuurwwbrurwrbwggrrgwgrwggubruburbgrrg gurbuggubwrggugggbwuurbgbgugwguwrbwbgwgrgrgb rgwbuwrgurwbgubwurruugwgwrbuwrgrbrurrurguwwwrugb wrrugbguruuwwrbrrwbrggwrwrgwwuwrwbgwgrbwguggwbwugb rgbubguwbrwuuuwrbgruuwgrrrugugbbwrrwrrgruuubruggwrbrgubrw uguwgwwbubgwwwrugbururbbugugrwgbbbgwubwggbburwubwuuubgu bbwrgwbggwuwggwggurrrrbgbbgwurrwrgwuwbuggbgrgwwuguubrguuugb wbbrbguggurrbuuwbbugrwrbgwuguubuguwbrgrurgbbrbgruwuwwrugb uwgrbwuuwrugubggubgubrgrgrrwgrgbrbbwuwruwgbbgwubwww buwbgggwwrwbuuugwwbbugrgugurrrrbwrugbruuuwbwrruw ugrurwbgbwrbbgrwwgrwbugwbwgwrbugwgggugugugwrgugb wuwwwwbubgwwrwwuuguggrggrbggbwbwrbwuwubrgrr gugbwbuuwugwuwbrbwuguggbuurruwgugbbwbbwbrurgrrbbwrgurwgg ugurugrubrrbgwrubgwrrwgubbwgurgwwugrwbuwrbwrubbuwrggugg bubuwuggrbugburbwwbbwgwbbbwwgubgugugbrurbuubbgbrgbbgb wugbgwubugbbrrbgbrrwgbwuuububwuwgrugububrburbuu ubrubuurwgbrrrbgubbgwwrbgwwbgbububbbruwwwwgguguggrgggugb wubbwubgbwrrrggrubwbbwwggguugrgwgrwbgurgurgbuwuurbrbgwu gbwbwggrwgrurbbwwrbruwrguwgggrbuwrbbururrwrwrrrwwwwwburbwu ubgbrubbbgwbguburuwuggggbgrwbbguruwrrwbruggugwwuwbb bbbbgrbbbbbgbwrurbwbwruubrbrgwrbgwwrgbruwwgwururguggbb uguwbubguwrgrbgwgwbuurbuwrrgbuwbuurruwuggububu uwurbbuguwbwwgwurwwbgwuwggbwrwbgrrrrbuwruwbrbgguuubwggrugb ubbrwrbrrbgbrgrrwuwgrrwurwrbwubwbwggguwbwww brrrggwrgwruwgwwuwwwwwwbwbwguwbwwurbwbuggubbrgrugurugu urwbuuwgrurwgrgurrgbbwguwrgugurrwbwrwrrbugbwguugb wbrubrwubgruurwwwgugwwwbwbwbgbuguwgbubbwgrgbrgbrbguwugwbrb gbguugwwgggwbbbbbbwbguugrbrguuwuwwrgbwbgggw rbbrrrbbwwbugwbbgbubbrugwbbrwwbruuwubwrgwbuwrrbwu ggubwggwbbuwbwbwuwgrwbwrbugugbwuwrrugruwuurubbbw ubururrguubuugggubgggrgrwwwwgbgbuwrbggrwugrgbguu ruugbuwwbbrrbwurgguburrbgruugugbguwwrubrwuwrrwuuugb ugbgbbrrbrrggbwwgwwubuwwuggrugurbrbwgrgwburrrurgggwbugb guruwbrrrrrrbbwwwruwwubrurbgggwugwruuurwugwwwrgbuwgwwwugb urrbbrbrgwwrbgbbbbgbwgruuwuwgwwbwwwuguuggbg ubggggbbuurrrbruuwwbrwugrbbwrbbrubwwruggrrwwuuuggw ggbggbwguurugggwgwwgurrrgubgwrruguburgurwbwuurubbgrgwbbrww guurbugwuubgugrwurbuuwuwwuruwwrgwwwubbbbuubgbb ggugwggurgguurwgwwrburwrwwbgwgwbwgwugwubrbuuwubugb bwuwbwgwrwububgrbgrgwbwbwrrubuwrbgwgurbrwuwubwugb ubgbgggrrggrgrrwbrubrguuwbwurrrbbuuurguwubbuwguurw gruurubrugrgggurwgbguwwrbwwrrwwrwbgrrugwrrgrggrurggb rbwwgbwrwbbgrbuggrubgurggwbrrguuurbgrbgrrrwwbugb ruwugwubgwwgwruwwwwuurrgbbwbwwwrbbbggwubgbwuubrwbuubrggbw bwbrrrrwurrrbgggburgubwubrruwwwrrgwruugb urwwwbggugrrgwuwubbbburbugrguwubrbwbwwugb bbwrrwugugbgbbgbrrrrrbuwwuuuwrgubgwbwubrburwubwrrgwwurwbr bruubrrrwbruruurgrwbrbguwuwwrgrbbgbrbugggbguuwgbbub rgrburrwuruwrrgruruuubgrrrrwrubwwbwbbwbgwubuugwbgbww rwwgrrbbwbguurwggrurgwgwwgbbubrwgrurggbggurbbugbbrubwruub rugbguwubggwwrugbbuwbrwwwuuwbgrugrrrgruruwuuurwugwgrgubruugb bbwgbwwruuguuuggrgwrrwrugbggrbbgwrggrrgbgbguurrg wggbrguwbbrbbgwugbbgubrwgbbwgurbgwwrguruubbrbuwguwrrwgrugb rwgrrgwwwwwugbwuwgurguuwubwbuwrgggbrrruwbwugb gwrwbubuwurrubrrbrgbbggrrbugurrwwwruwubwubwuubwrgr wwrbwggwguwwbuwuwbrgrbwuuwgruurwrgbgwrubbgubwbrrgwrgugb wwwwugwwuwurrrrbwuuuguuwuwuwuurrrgwrwrrwwgbbbrwrrrubgu guuguwggwruwgwbuwrrwbbwrbbbbburrbuwbbrgbuuug uwuwurwwgwbgwrgrgugwgrbwwbwbbbuggugrbuuwggwwbguuwgw rwrrbwbgubbbwbrgwubwgbwuwwrrrwbugggwwwrbrg bgbbwurrrruwguuwwwgubwrwwgurrwwguwrwgrgubgubururrrrugb bwugruwgwbwbrrbbuwuuwwurwbrrgugbbubguwggggwwurrwb rrwuuwurrwwgwwwbuubgrruugrgurwuuwbggrbbwwug wgugrwuruwwgrbugbwbgbrrruuubggrbrwubwwgugrwbbrrbugb wrwgwwubuwbgwbgwgbubuwuwwwrubwuuwwwwwrwugb brggbuwgwrgguwgwgbrwwuwuuugwgbwwwrgugwbwwwguwuuubwu rrwuwburwgwbburbrwrgrbrbgbgrrrrrwgrggwwggrrwuwrr gwrrrgrwuruwrbrbbbubgrbgrugrrbbrwgrgbbuugbbbugb guwuuwrgbbgrrubwwuwbgwrwwbguwrguguubbuugrrubwwbruwrbw wbrrbuwruuuurggurrbgwburwwgurwbrwrbwuuuwwrrrwwgubwgruwrbwr rrwgrugbbgwgrwgrburugubuwrububuuugbugugbbgbrurwgrugbu wrgwbwbggruugbrrruggwbwwugrguruubgwwgwwwubbwwwwuruurwuru bwbrrrbwugubwggrgbuwrbubgubrbbbgwwrgwbrrbu ugbrrrgbbgrwrbwbwwuwbuuuwbuwuubbgwwurrrubwugggugbbgwrg rwgrwwbgwugbwrbuwrwwwgwwbrwrugurwgwbbguwbgruwrggbuubgrwuugb urugurwbrrwrruwwrbuubruugurwbrbrbbruururbwubuuugwgggwgugb ugggugwrwwwuubuubggbbuugbgguwrguubgrrgwurrwwuwubguurrrgugb rubrgrrbuwuruwgggbuuwbwubwugggbgguwbwubbbruwwgwwbbbbu uwbwgubrbbwgbugwggurbugrbwwwgrwubuuubwubwrw gggrggwbwgbbwuuugwbwwubguububggruwububgwwgbwbrrwbbbwu guuurwwbbuwgguuwwruubuurgbgwggrrbwwuurwbgwwbubbbgu bbgbbrurwrwbrwwbuguggwwwguwuubrrgruuwgururugububurrrb buwbrrubgubwbubgbrrwwwbrrggwrwwgwbruuugb grrbggubwggbbbuwggrubrrbbbggrbuuugbrrrurbbwbb wugggrrubwruruggbrbwrgwwugbwwbwbuuwwrbubggbggw rggugrbuggrwubrwuugrrugrrrrugwubguwbwwugb grbrgbwrwuugrrbugrugbwruwrwbbggbrwurbuubbwubrgbbgugb ruurubgrbgrwwgrwrwgwbwuggwwbbrgbgrbbgrugb gwbwgubgggbgrrbgwuwrrwwgbrbbbwwgubugrrbwgbgbrwgw gbrubwggubwruwwrrwbwrrrwuurwrgbubrrubbbugrbbwu gwgrrbwwgrubwrrrrwwrgwrgwgbbugrbrrgrubwgruruugbwugwuuubugb rrrwwubbuwuurrruubwbwugrwbwwgurbwwrwrruuguubbbbubbggwugb grwrwburgurbrwuuubgrrgwubwrbuwwwrbbwrgrrrubrwwgrrburwbbw ububgwuurwruwbwuburbuurwrgwrrguurbwgwwggrwbbugggr rgwugbgbbbbbrrbbwwgwguuwurbwbubwwgwwbbgwgbrbgbrwuuuw bgbbwugbrwuubuwrgggruuwubbbbgbruguugwrwrbu wugbrbrbbwubgbrrugubwugbugrwgubbugbwggugwug gbbbwguuwrruubrbgrgbwgubbbgggbbuwwbruugb bwgbrbwbbburubbbwwggrwbuwbruguurwruurgbgbrgww rbgrggruugbbgwbwuggbruuuurgwbbgubbrbbubgruwbuwgwr wgwugguuwubggguubbruugggrrbrrbrwburwrrggrgubrwbbbb gbbgwuuubwbrwwburuwwruubuwgwuuwuwgwgurbgrrgbb ubwgbgwggwwbuwwwbbggbbbwuubwrwggrbbgrrugwr gwugwgurgugguwubgbrgwgwbbwbwbuwwwbwugrbwugwgrrg rgbbbwruubuurruwbgugggwubwwuwgbbugbbrrrbrwgrrgbr uwbggrgrbuwbgwbrurwgbrbbbubgrwburrggwbrbuwugrbwrggub gwuuwgwrggbwrrbwwuruguwbrwbgwuggwrgwbuubuugbbrggw ugbwbrrbbwugggrwwbwubbwrbgrwrrwgbgrgurrurrwbg gggwbrggubgwgwrgrrgurubbguwrbwwurgbwrurubbwbrbgrbwrbw ruwwgurbbbguurgrbwwwgugbbrbguggbrwuurwgwbrr grgugrbwgbbrrugbuwubrgrgbwururggwrbrbgugb brurggwbgwrbbugwbgggwwbwruwbgbgbubgrgbwbwgwbgugw grrggguugwuguugrrrwwugbguugrbbubbrugrubgbgbwururbwbrguurwugb wuubwubwgrgurwurrwbbwgbwbgugbwbbbwggruwubgrgbgubb gburuuwwwwrubrwwurwgwbbrbuuuwgrrgurgwwwgwgugbwgug uruuwbwbbrwwrwruwrgruwuurwrgrguwwggggbuubbbbrrgrruugb wrrrbubruuwggbguurubrbuguwurwbgbrrbuwurwbwggbwgrwrbwwuuggugb ggwwrbgrgrgggbgwuwbgbgwwrrwburuwwgwbggrwgruuwwbwgrugubrru ubbbbgbugbwuuggubbwrugrbgwwrruwuwggwwuggbwguruw rgurwrbwuuuubwggrbuubwwubwwgbubgwugbgrgrurwuwbrwrbbgurgugb bgrgrrgrurbwrbrbruububwuwgububwgbwwwrugrgwr ubbggubwrgwgwwbbbwbbrgguubrbwguggrrguguwgbgg ruubwgbgugubbrrrbgrbwwuwwwwbgrbwwugrruwwrgbruwwrbugb bururubguggubwrurgbrurbubbuwgbwggrguwgggbbubugb grgrguuurwuwgubgrwbbwrwggggbguburrwbububrgb wubbwugruwbgbwbrubrrwggwwwubbgurwurwubuggbrruuurrrugb wubgbwguwbugbwgwwgrrbubgubgwrgrbgwruwgbwubbggwgwr bwwruugwruuruurgbwwrwgrwruguugruruggrrbgugrwrrrrbbgwururugb gurruwbwubrurwbuwruggurrgbubwwggwbubgwbbuw bwbggubwbbwbwgwrbwbrrgurugbrbrbrbwwrurugrwbggugu bwgwgrgwwguuwrwgbuurubwgbgbrwwwgbugwrbwrrggug ubugrwguuuwrrgbgbggwgbbbubgbgbwubwggwggrururgwr wgwwbguwwrburrrwrwwuruugugurbrbgubbgwrrrbbrrugrbbubbb wbgurwrbrgwburwrguurrggugurugrbrguwwrrbgruwgbwgrgwwuwgg brrrggwugbbgrwrwrgbbrgbuubwguuwwrwrrrugurugw gbubbgrgggbwuuwwgugbgrwbrgbbwwbgbuurwgurwbgbub ggrugwugrwuburugruruwwwrurbgwbwrbwgbuggwggrwwwrburguurgugb wwrrwrruwwwwrurwurrbbrgrbbuuurbwwbguwwwbgrwggbwr ubrbuurbrwbgrbrwbgubbbrrbrburggburbwwbggrguwg ugwrbwuwrbgrrubugwbbbbrbrbwuuruuwuwbrwbgguwrwgr urwgwwrubrrwrrwwbbrubggrbwrbwgrrbwgrgggbbubwrwwwwguguugb ubbugwgbwwruwruubwugburwurgbrgwwgbgubbgburrbuuwrbrwurggugb rwbgwbruwbguwbrwwburrrrgggbgwgbggrwuwuwbrwgwbggugb guggbuuggrgrwwrgrwguwggrbwrbggwwrbgrwbuwrwrgbrwww bgwugwubgggwwbuuuwgwubuugggbgbwurwbrgbuurbbb wggrrrgrbwruugrgbbguuwgwgwgrugrbgubwggbugwwrgwrgrugb uwguuwurgrbwggwbwrubbwgbwrwurwrwuwbwguuuguwuuug grwuwrgwbwbrwrbgggrbbwburbgbuwggrrrrrgbbwgu ugwrwbwgwrggwwgrrgubgwgrgwurgrwrrbururbuurrwgwgugugb wgwggrbrrwbubwurwgubguwrubgwbbrgbbugugguruwbbggruwuwgwwugb ugwbgbrgrurrurbgbgbruwrbgbugggrwwgrubugggwubbwu bbwugrggrwggrwwrugwuwbbgbbwurbgbgrrguwubwbrbrguwrruugb bbwggrwwbrrubwgbubguruburwbubbrwwruwrbbbgrburubruruwurwwugb wwgurbbwrwrwrubuuwuwgwrrbbwgururbrurbwwggwuuwrbbgrwrgrbg wbwbgwgrbrwrugbgwbwgbbgbgrubrrrbwruguugwrb wbburwwbggbbgrrbbwwrruuwrrbuguwugwwugbwgb uwwbwbuwrwrwggbwrbbwgwrgwwubbwbugbwuggrwrbugb gurwgrwwwgwggbubbubrgwwbbwgbwuwbbgwwbrrgbbu gbgburbwbburbrbrubwwubwwguubwguwguuburubrbbrrbruggg ubrbwggrbwururguwubggurbbbrwwrgurwwururuugwrrbbgwburrwrugb grbuurwbrbruugubrbwggbbggbuwruubgwubbrwgbwbwwwgwugbwgrgrb gbuugbbwggrurbwrbuwugwuwuuwbwrugbgrbubrbubrwuw wrwggugbgurrwbwrgbwubrurbwwgggbwgggwgbgubggrbuwwugb wgugbggggbrgrbbrwbruubrrrrggbuwgrwbrbrgwrrwbgbgwuuugb ggburgwguwggwrbugwgwurgrbggwwwubwrgrugbrugb wgubururrugrbbubbrbwwubwuruwwugrubuguwburgubrrwwbbbgbbgwg gwurwgwugbugurgubgubuguurwurrbburrbubwwbrwgub bwguuugwgugwbuwrwrrwrrubrggrwbbrgugbbgwrguwuwruwwugb urrrubrwbwgrgruuwwgbubrbubugguwwgrbwrwuwbu gruubbbubwrrrgrbwwbuwbwbrwrubgrrrurgwugbbbbbwggubwug ugbuwrruwrbbwggbrrgurwggwwgrubbwgwuwwrwugb rbrrwuwrrbrguuwuggwbrrubggwgrgwrrwrgbwgbgb rbggwgwgubrwbbrgwrwwbubuwgugwrwrgrrgbugb wwuwurrbrubbbubgggubwuwbrrrbrgbrwwgrbwurugbugb uuubuugggbwwgwrguruwuubbrrguwwuubwwubbbubggubugb wbgwbubwbwbwwbrrrwbwrwwgugurrgbbubuuwgrrgbbwuggubgug grwbbrwuwgggbuwgwugrubwubggrgbwbbugruwugrugu gbrbwggbbgbwwrwgruwwbwrbbuwburrwbugbbrbubgguugb brbwggbgbwgurwubwguuuugurwbgbwgggubwrubggurgugrbwggrub ugguuwgubgubrubbbbgwgbuguuubrgrbrbrruggbugb bwwbgwruwrrbruuurwugwwbbrurguwrguwrgwbugwguuugbugg bbwuwrrwgbgbbwrwwrgwrggubggubuwurugugugwrrwbrgwwguuw ugwubuguurwrbguruwurrrrgrggrugwguuggwgruwwbbwuu gwgwgwbwwrrrbburbugubbubuugugbwuggugwuubrwrggbrbgurgu rrrubgggbgwwwbbrrrgubuggbgwrrubgbubuwrggwruuwbuuuwurrw gwgrgbrgugbgguwbwubugwrgbrrrgrruggwgwbwbwwurbubgrbgwuw uuuubuuwgrwbwbrgwrwwuubwwgrbwrugugwwrwwgrurb wugrrgrgbuwggwuuwwbrrbrwbbwbgwuruuwurggugwrwwwug bguuwubgrrbwrrbgrubgwburwbwguggwrbbrurgbgrguwuwbbbgrurrbrugb rwurgubuwwggrwrrrbgrbgruwgbrwwuubwurgwrwbb wrbubrrugbgggburubruubgrugrwgbgwguugwwgrubwbrrguwgrug uwugwbuburwgrgbrgggrrrgbbggruubbuurgwuubwwgwbrbruwgg wbubuwgbwbwwbwbbgbbguuwgwugrruurbwbbrbggwuburgruugwwrb grgruggwgwbbrwrwuwwwuurrwurwwwwrgbrugbuurruwr urbgbbguuwgrwbrgrggwuwurbugbgugrurbrrrrrwrrgrgubw gwwrwwwbburgwggburruwugubwwwguuruubugubrwb wggggguwguwrrrbugbbgrbwbugbgurrbgugubuubgwuwwburwugb bguwgrwuubuwgwurgbrgugrwbrwbuwgurggbgbugb wbuubbwruguwuburwuwwrbgrgrrgbbgggrbrbwuwrgguu ugwwbuuuwwwwburuggubbrbubrurbrrrbwgbgugb ubggurbruuwgubgbrggugbbbbrbugbuubrrrbuugbrgwurgw uugbgugrbruugugwggwwrrbugbgrwbwrggrwwrbuuwgb gwgugwbugugwgrgbrbuuuwwbbbbrurrrurwwgwuuugb guwrbggbbwgrrwwwbgrgbgburwwbuggwggugguwbrugb guubbgubwurbbrbbruwrwbugruwuwuguubugugrruuggbgwgwwuggwugb bguwbrrgrrrggurwrrwurwrrrbrbuwrurbwrgrrrubug ggbgwrrbgbrgwubrbrgrwgrurwbgwbuwbrgbrugrwwwgrbbuwwurubbgw bbuurugwggurgwubwbbwgwgrbwuuwgbggurgwwbrbwuwuwbwb ugbbuurubuubggubwruubbgwubggbrggubgwwbuugwuwbrwgbwug brrggwbrburrwbwrgrwwubbwbbrwuguubugwrgugwugggugb wuwrbggbrrrbrgrggbgburrwggwgwgubgrrgbubrggbgbbgbwugb bwbwbgbugbgwguwwwbwwwugbggwwguwrbggruwgbwguwguugb rbgwwggbwrwggugurbgrbgrgrgbgrrbugrggrwwugb uugurugggugwwgrrwbuggbwgruwrbbwwrguwbbbrwrrgwruurbbuwugrwu rgggwgbbwguwwwugurwbuugrwbrururwburburbrurrwuwgugrurwwurrg ugrwwubgrwugwburbwruwgrbrgrgwwbubrbbgwwrgugbwurubggguugb ubbwubbbrggugrbbrrrgwuruugbuggubgrbwwbbbwbggwrugb buwgbbbbwugbwbruwuwgrwubbuwwbgggwguuwbbugwuugb uugrgrwgugwbwwgbwrrbuwwuuguwurggggrwugwuwbbuugb urguugrwuwwuurubuurbbwugrbggrgrgwwguubwwwrbbugb bwbwrbbggwrggggrgruwwuwwbuwrrbggrgrrurwggrgbbb bwbrwwrwwgrwggubwguubrgwbburwgurwbgrruugb bgggubwubwbwwbuurbrgbwbuurbrbgwwgrgbwwwrwwrbrrbbrggb urugbruwbrbgbbwbguuurruggwruuurrwrubbrrubbrwwwrggwwg gwwuggwbuwbbrubgbwgburruwgbwbgbbrgbwrugbbbwugbbuuwbrubrbr wbgbuuguuwwbuggwrruggbwurwrrrubbwrruurburrwbbbuurwu bgrgbruruuuugwrwuggwuwrbwgrwrbwbwbbuwbbbgggwwuwwgugb uwggubrrwuruwwuwwuuwubwbbgbbuuubgwbwgbwburrbrbuugbgguur grgbubwurbuwbbrgugbwuwwuwwrwbrugbrwbuugubbr guuwbuwrwwurubrggwurubbuwgrrurgwwugbwgruuguuugb wbbwwurwwwwggrrwbrbuwbbrguwgwwrubwrgggruruuugwuwbru gwggururwruuuubgrrrgggbguwbrrruguuwbbgguggurr ggbrruwgggwrrwggurbbubrbbbbgbgwwgggbuugrbrwwburggb wbubwgurwwgrgwuruurgwbrrugruwbugrrbbgwrguruwgurrwuwb rgrgbgwrrrgrbgbbwubgrggwwruugbbuurrubrbwbgbwuurruurugrugbr buwubbrwgbwbwruwrbrbgrrwrugbggbrbbbwbbgrwwruuuuugwgrgruww gggrbrbuugwgwgruwuurwuuggwwbwbuwgwggrgrrburuwguwbbrbwwub bgwwuwgbruuuwwgwwugwrbwurrgwubgwwrggbrggwuubgbrwugrbg rugwrurrggwwwbggwrrubrburbwrbubuwbrwrwwbuwugwuburubwugb ugguuwrwgrbuugbrbwbugbbgwbwwuurgruguuugurwuggwwugbwwb rbwrbbwrwuwrwgwuuwwrubbgrrwrbwuwwuurugwrugb bguwgwgbuguurwrbgrgrbwgwwgugwwwwwuuwbrbrgrugb rwgwwuuuwuuuuwwrubugbwuuubrurgbbbgrbbwguwbrrubgugwg bwbugruruuwbgrgbgwwbbrrguubuubgugwwwwuwrgrbuugb grgrgrwrbwuwwbwrrbgburubrgubrruurbbbgrrgrwubr urburrrbrrgrguubugrwgrwbbgwwwbbruuubgwguburrwu rwggbgwguuugubbbbrgggbuurgrugrbburbbwruwwuuwwbwbwwugb rubgbrguggrwwwubrbrwburrwgwurrbubwrwwgrrwbbbwgr uwwbwbwuwgrbrbbrwbwwgruburggbrgwwgrbrrrburgrbbbub wrgwrrwwwbgubrbrwbwbwuwuurwubggbgubrwrrbbwwbgbgrrbwwgrugw grrgwgbggbgbggrwgwurggurrggwgbwuwrbgwrubrg wuwgrrbbbrwwubrubwrurrrggrbgwbgrurgwgubuwubrgbbbuguugb rwgrgbgggbuwurwrbrrubbrrbrbwgbrgrwwguwgurrgggurbuuwgu bbwbbguwugrbbbbgrbrwbrggbuuurbgwgwgugbuwgwug rrrurububrburggurugurrubwgugwguwrbgbbggbwgw bgubrruugrwuugggwwbuwrwwugrwggbgwwwwwggrrgbubbgrgbgr bbuwburbgggruuwbuuwwbwuurwbuugugrgrgruwwwwb gubbruurbggbwuubruubugwurgwwbbgubrbwgrwwrggrguugb bwwgrrurwggugrguuwgrbwuwbuuwwgrrwggbuububgggugggbubbbgur rugrubwwbguwuwwwurwbbuubwwwuguwgurbubrggwrrubrrrrbwrbggb gwbuuwgrrgguuwbgrbgwruwugburbrruurgrurbwbuwrrugb gbwgwgrrgwrwwrbbwwbggbrbgwrwwrwrgwggrrrbgrwbubgurg wuubrguwbwuwugwurgbgbwgubwggbbrrurbwguurbw bugwwbrgwguwruuwgbguuwbbwgbgbburbwburbrbrrrbgrbw grwbwggwrbbbrgwbrwrruwubwbgbrwbgbbwwrwggwgwwuurgwurwgggrgugb uubgrwggrbubruuubrbrrrbggbgbbruugwwuwgrugurwuwwrwguggbugb ruwgugrggwuugrugbrwrbggugguggrggrbwuburbbbgrr wrububurgbbrgwrgbuguguwwbrbgbwwwwgrbbrwbugb wuuwurwbrwrgwrgrrwububrggwgbrrrbgburwgugb rgrrguwgwguubwrbruwugrwurbgurbbggbrwgubwbu ugwbgrbbbgwwrgggggrrbwurrbbwwgguwrwgwbbugb bgwrwrgwbwbwrggwuwbggrwwguwurbrggrguuubggwwwrurbuwwuugb bbgwwbbuwguggggwbbugbuuururbrwrrububbbbruugbgrrrbururrwrugb wbrwbrwgrgwrwuurguubrwguuwuubwrwwgugbrbrbbwbruwgrwwuuwuggw wbgwuurbwggurrrbugrbrugbguruwbwgubgbguurrbrwguwrrwgrbw rubrrbubgbuuugbbgggrgrgggrruruuwwurbgrugbwrrbgubugrwgwrbrb wugwrwwrbuwrggbugbwruugwgwbbgggwuruwwrgurbbrgrr brrubrwbbbrgbuwwguwgrgwbguuwrwrbruwwbrgrgwbugb ggwrrbgbwgrbrwbbrrwggugwuurrgurgrbgurwrbbubwwuwrwwugb rwrrbgrrwbbuubburbbwugwugwgbbwwbuwubuwguwgggrwbuugb wuuuwuruwbrrruwrrbwwwbbwrwwugurbbwgrwrguubg uwwgbbrgurbwggwbwwuuwuuuwbgwwwrwgwrguggrgwgrgrwwgbbrurrrgg brgwbbrgrrrrrwbwgbwwgruuubbbbwrugubggwgwrwruggugbgw rubgwrgbrwrwbwwbrrwrbrrwbwuurugrgwbrgrgubuubbubg rwrbwwwubgbwbubguurgbwwbbwggrgggbrrurwgbbbwwbrubbggrbg wuubgrrbrrgrburuggbbwruwbbrrwbwgrwwbwbggbbubbbugb gbuwbrruuwwwwwbrgguruubrbuuuubgwrrgugrguwwuwwg uurburbrugwurruwbrbgggwwubgwuwuwggrwwbbrrrbwbrwggbrg uwruguwwgwwbuwugurrbwguwurugrwrugrugrrgwuwugrb grwrbrbgwgwwrbwubbwurwrbwgrurbwgurubrgwbgruuubguuur gbugrwrgrbrrrrbbuuwubrugbgbgwrrbbuwgwwuwruggwgwwwgguurwguugb bbrbgrgrbguurgwuurrgwuurbrgwrugwbrgwbbuwgbubrwugbggb brwwwgruggguuwbwgbrbgwbrwbbbuggbubwrbwwruwbgrwgbrruw gwrgubwgwugrruwwrrugggbugurbubuurbwurgbbwgggwggwrub uwbuubrugwubbbbrgurbrrugwrbbrbubrwgbbbrurwbuugrbgwwgugb gubgbwrbruwwgrwggrrbgwwbgurgbwubgbrwbuwrgrrgg wwgbrgbubrwrguggrugwuwwwwwburgwrbgggguubwwurwbgggwru gubruugrgrggbgbbgbubgugwbrrguwbgurrrwrgbgggwbrubbubbwggbgugb rgubguuurugruggrguuuubggrwbgbwgbrbrburugwbwuwwuwgbw ruwbuurburwwgububgrbrwbbbrggrwrgrrrgugrubgrgwwgbgw uwurrrbbuwbgrwugbwgbwbrrwrwwuggwbbuuwubgwbwwugb gubguruubbrrugburbgrguurwrrurwbbuwgrrrruuugrwgrwrugb grurrwwbbuwwrwwrrrugbwgbrgbrugrrwrgwggrwbuwurgb uwrrgubrbbbwbggurrgbbrggwuubgrbgrguugugbwrgbwgbbugw wgurrguubuugburrwbggbrrbbbwbgwbrwbwgurgrgururgbbbruwuwb wwbbrgrgbubruuuwuurugrruwbuubwrgrrrbggurwurgurrr brbwwbguuugurruwguwgugbbgrbrgguwruuuuwwruugb rrbgwwwwwwbrguwbrgwwguwrurrwbgugggbggbwgubrgbubugb grgrgwbrruugwgbwguwwwbwwgrwugbgrbbwrrwgrrbwrbwwgwwbbw bgbugrgugugrugrgruuurwwrggbggwrrwurbbgggbwwwuwggwrgrgrb uwwrrgrbbwuuruwgwgggrwwrgwrwrruruwbggugrguuugbrrwrbrrgwb gburgwwgbwbwurbugurrgrruwubbububwgrrgwwgbuugb rguuwbururbwgwubbgrgbgrrwrwbuwwwwuggrbwrguub bbugwgugrrbugbgruwrugwwwbbwurrrurrgrgwrbwuuugb wbubbrggwwubruuurwrubrggbrgrugurwwugrbuwwgugb wggrwrwwburrgbwgbruuggbuwugwruugbwggrwrbbburwwbbugb ubwubuurrruugrbwggbgugrbgbbubbruwugbburgwugb uugwubbbubwrguugggrgugrgrwbwrwrgbbbgbggburrrbggbrwwbgg rwuubwwurruuwrwbwbbgrwbbgbbwurrggwugguwburgwwbuwrbu ugwbgbrwwrguubgwuwrbgurwggbggrurbuwruwgrbrgbbgb grugwbgwbubgurubbrwbrwgbrrbbwubuuwurbrgruwu wuwbbbwwwrbrgugwrwrwbwrrbubuwwgbbgurgwbbbuubugugwuggruggw rrrwwgrbburwrgbwrwbwuwuuguggubrurrrgrruruggwbwgwubuwu rrrgrrrrwwrbwugbwwgurwruwbgugwrggbbgwbugbugb rrwgruwgbrwurrrrguuubbwuuuruurruwgbrgbwubgbbggrwbbwww rgbugugurwgurrwuuuguggwggrbrbubgwrwuwbbwgbbgwuuugbggb urwruwbgrwgwgrrbuwurwwugrbggwwugrgbrggbrbbbguwugb urwruwurrgurrbrrgwwrbgbbbgrbrwggubguwggburggbwgrurrbubgrugb wgrubgrrwgubrgurubggrgrrrgrggbgbbuwwurburgrrr uwrruggugruruurugugbgwguruuruburwugwbugwgbbu wuugubwwuugubrwgwurrrrbruguwbwuwwwrrwbwbgbgwg urrggrrrbgubrrbwwrbwwrggbuwrrwgugrbwburrgrrbugrrbgbwub wgruwrrrgbubwbbuubuwbbgwgwrbwguwugrwuwgrbrwguwb urgwbbggugrwwuubrwrgwuugrgwrruwgwrbbwrwurrbguwwuwwggggrrg brwrwrrrrbubbgubwuuwbwuggruggbubbwbwugrgurubbbwrwgr brrruguggbwgurbwburrwrrbugubrrrwrubugggbugb wwguwbuuwrbwgrwwwwwrggbuwruuwgurwuugwuurggwgbwu rububwbrguuuuwrrbwbguwgrwgwuggugwgbgugrrguwru rgrwbuubwrwrwwbwgrugguwgbrwubwruwwbbgggurbwgwrugb urrbbubbrubwbwuggrurbbgbgurgbbrgbwbubgrwgrwb wrrwwbbwubrwuurbwuurbugrrgrrwurbubrwgrrgggguwr grguwbburbrurubggwwwgrwbgbbugrwrgbrggrugb gbwrruuurrwbgrgrwgrburbwwgwwuwbubburgrubgwrwgrbb wwwggwrwwubrggwrgrwgwrbggbbbggubwwwbruguwbwbrrruwgrg bbwwgwwurwgrgrrgubguggwbugrbuwuwgwgbruwgurgugb gwgwgwgbgrruwbruwgbguuuwwrubbgrrwgrruwbbbgww rwwwbggwggbbwggubgubwwrwgrbbubwbwbwbbugb wgwwgwrbuwbuwgbggwggrguwubggbrwugbbwrrurbrbgru rrrbgbwurrrbbbrbwgrugrrrrggbgbrgbbruguwwwbu ugbugwbuuuruggggrubrrugrrrrugbubwugbbwuuwbrrbugurwbrgwg gbbwuwwbbgwurgwguuwrbgbbgbguruuurrrgbwugwwbrgrgwgrwugbbgb rwbwggwuuwruuwgburgrubrrwugrwrgggugbgrwgwu wwwrrugrgrrrugbwgugrwuwrwuguruwuurugbbbwubbgbubr bwgrwrugrbrrurwgwrbgbbrrwrubbbgwwggugwgwrgruggrggbuwbuugb ggbgurbbgwbrwbuurrgrrwwurwgrwruwwwuguugubb wurwgbrgwguubuguugurrwbbrugrgwugruggbgbgbguugb grrbwbuubwbruggwbubwbwgbrugrrwbrrwgwrbugggbggwwgrugb uubwrgrrwggubggbwwgugwbrgbgbruwgwuwgrrurrwurbg gwgurrrwgrguguuuwugwurgrgrrurbwrwgbggggbgbrbwrwurgugbu rrwbwgugruwuubgbwrwbbbbbbbugwgbwrgggwwrurr wrrgbwrrbrgrbwuwrwbrrwgubwbgbugburugwgrugruwbgrugb grbbgrwggrggbrrbgwwguubbrbbbgburgrbwgurggru bwuwuwbwbugrurgrwbbburwwbrwbuubgggbwwubwwrwwuw wwwrwbbuubwrguruwwurwwubbgwbbgbrrurbgwwbuggurbwrugw wuuwwruuguuwbrbugubwrurwrggwuguwwgwwbbbugb bburuguugrgurugrbwgggbbugrurwgwrrguguuguwubbbbrrwgwurubrugb wbwgrbbwbrrubwurrgbwbugbrwgwwgwbuubggggguubwgwbbw bwrwurbwgrgrurbrwrbubrbugrbugubbrbbgrgbuwguguuuuu grbuuwbrugrbugurrwwwbwrubuwgwwubrbwwwgurrrbubbrubbwuggugg rurbwrrbwuguuwrurwgruguwrgggrbgbgubwgrwbbbwugb bbggbwwbwbururuwrgrgrbwggburwwgrrbwuwwwgwgbwgrwwugbg bwbbbbbwwgwwrgubrrguurwugwwbguugrbrwubgrwgrugbbgwrrwwubgg rrgwuuuwgwuubbrbwuuubggrrgbrubgbgrrrbbgugbgbguugb ggburbrwwbgbgwwgrubggggguuwwwrrbubrrgwububbruubggwrgggrbuw ggrugwrgbubrrrwbbwguuruuwgwrbggguwbgguwwggwbugwruubrugb buubwgrbbgwurububwgwbgbrrbrbbrwwbbrbbrwggwbbbuwuug wgwruubwbrwgbwugbwwbgruwuwbbgwrbwrrrurbrgrgwbgwrb rrrugrgbrrrrgggrbbbgubuwwurwrrrruwbwgwwruwubgwrbwgrbgw rwggrgrbgwgwgwrwwwrggwbwwrwgrguuugrrguwggruwb gggrbgwgruwwbbugggwrgurbwwwuugrwbburrrgwgwgrwguwwwgrwgbggr wwwuwrwggrrrrwuruwwbugbrbrguwuuuuwrrwrbugb ================================================ FILE: exm/aoc/2024/aoc_2024_19_questions.txt ================================================ --- Day 19: Linen Layout --- Today, The Historians take you up to the hot springs on Gear Island! Very suspiciously, absolutely nothing goes wrong as they begin their careful search of the vast field of helixes. Could this finally be your chance to visit the onsen next door? Only one way to find out. After a brief conversation with the reception staff at the onsen front desk, you discover that you don't have the right kind of money to pay the admission fee. However, before you can leave, the staff get your attention. Apparently, they've heard about how you helped at the hot springs, and they're willing to make a deal: if you can simply help them arrange their towels, they'll let you in for free! Every towel at this onsen is marked with a pattern of colored stripes. There are only a few patterns, but for any particular pattern, the staff can get you as many towels with that pattern as you need. Each stripe can be white (w), blue (u), black (b), red (r), or green (g). So, a towel with the pattern ggr would have a green stripe, a green stripe, and then a red stripe, in that order. (You can't reverse a pattern by flipping a towel upside-down, as that would cause the onsen logo to face the wrong way.) The Official Onsen Branding Expert has produced a list of designs - each a long sequence of stripe colors - that they would like to be able to display. You can use any towels you want, but all of the towels' stripes must exactly match the desired design. So, to display the design rgrgr, you could use two rg towels and then an r towel, an rgr towel and then a gr towel, or even a single massive rgrgr towel (assuming such towel patterns were actually available). To start, collect together all of the available towel patterns and the list of desired designs (your puzzle input). For example: r, wr, b, g, bwu, rb, gb, br brwrr bggr gbbr rrbgbr ubwu bwurrg brgr bbrgwb The first line indicates the available towel patterns; in this example, the onsen has unlimited towels with a single red stripe (r), unlimited towels with a white stripe and then a red stripe (wr), and so on. After the blank line, the remaining lines each describe a design the onsen would like to be able to display. In this example, the first design (brwrr) indicates that the onsen would like to be able to display a black stripe, a red stripe, a white stripe, and then two red stripes, in that order. Not all designs will be possible with the available towels. In the above example, the designs are possible or impossible as follows: brwrr can be made with a br towel, then a wr towel, and then finally an r towel. bggr can be made with a b towel, two g towels, and then an r towel. gbbr can be made with a gb towel and then a br towel. rrbgbr can be made with r, rb, g, and br. ubwu is impossible. bwurrg can be made with bwu, r, r, and g. brgr can be made with br, g, and r. bbrgwb is impossible. In this example, 6 of the eight designs are possible with the available towel patterns. To get into the onsen as soon as possible, consult your list of towel patterns and desired designs carefully. How many designs are possible? --- Part Two --- The staff don't really like some of the towel arrangements you came up with. To avoid an endless cycle of towel rearrangement, maybe you should just give them every possible option. Here are all of the different ways the above example's designs can be made: brwrr can be made in two different ways: b, r, wr, r or br, wr, r. bggr can only be made with b, g, g, and r. gbbr can be made 4 different ways: g, b, b, r g, b, br gb, b, r gb, br rrbgbr can be made 6 different ways: r, r, b, g, b, r r, r, b, g, br r, r, b, gb, r r, rb, g, b, r r, rb, g, br r, rb, gb, r bwurrg can only be made with bwu, r, r, and g. brgr can be made in two different ways: b, r, g, r or br, g, r. ubwu and bbrgwb are still impossible. Adding up all of the ways the towels in this example could be arranged into the desired designs yields 16 (2 + 1 + 4 + 6 + 1 + 2). They'll let you into the onsen as soon as you have the list. What do you get if you add up the number of different ways you could make each design? ================================================ FILE: exm/aoc/2024/aoc_2024_20.adb ================================================ -- Solution to Advent of Code 2024, Day 20 ------------------------------------------- -- Race Condition -- -- https://adventofcode.com/2024/day/20 -- Copy of questions in: aoc_2024_18_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_20 is use AoC_Toolbox, HAT; input_name : constant VString := +"aoc_2024_20_mini"; n : constant := 15; -- input_name : constant VString := +"aoc_2024_20"; n : constant := 141; verbose : constant Boolean := False; map : array (1 .. n, 1 .. n) of Character; -- Dijkstra shortest path algorithm. -- Code adapted from AoC_2024_18. -- -- The following definitions belong to the Dijkstra algorithm, but -- we keep them less local because of the path tracking. list_length_max : constant := 500_000; subtype List_Range is Integer range 1 .. list_length_max; type State_Type is record pt : Point; end record; type Node is record len : Natural; state : State_Type; pred : Natural; -- This is for backtracking the path. end record; list : array (List_Range) of Node; current, explored : Natural; -- 0 <= current <= explored type Score_Type is array (1 .. n, 1 .. n) of Natural; -- , 0 .. path_max, Direction best, best_clear : Score_Type; inf : constant Natural := Integer'Last / 4; start, finish, cheat_start, cheat_end : Point; function Dijkstra_Algorithm (cheat_start_step : Natural; cheat_dir : Direction_or_Nil) return Natural is cur_len : Natural; cur_s : State_Type; s : State_Type; -- Test state derived from current state. procedure Visit (dir : Direction) is len_to, ins : Integer; new_node : Node; begin s := cur_s; case dir is when north => s.pt.y := cur_s.pt.y - 1; when east => s.pt.x := cur_s.pt.x + 1; when south => s.pt.y := cur_s.pt.y + 1; when west => s.pt.x := cur_s.pt.x - 1; end case; len_to := cur_len + 1; if s.pt.x in 2 .. n - 1 and then s.pt.y in 2 .. n - 1 and then len_to < best (s.pt.x, s.pt.y) then if map (s.pt.x, s.pt.y) = '.' or else (len_to = cheat_start_step and then dir = cheat_dir) then -- Found a better path to target state s. best (s.pt.x, s.pt.y) := len_to; -- -- Insert in a sorted way. -- ins := explored + 1; for i in current + 1 .. explored loop if len_to < list (i).len then ins := i; -- Insert here. -- Optional: remove another node -- with the same state and a larger length. exit; end if; end loop; for i in reverse ins .. explored loop list (i + 1) := list (i); end loop; new_node.len := len_to; new_node.state := s; new_node.pred := current; list (ins) := new_node; explored := explored + 1; end if; end if; end Visit; begin current := 0; explored := 0; best := best_clear; cheat_end.x := -1; cheat_end.y := -1; cur_s.pt := start; cur_len := 0; loop for d in Direction loop Visit (d); end loop; -- -- Switch to the next best explored point. -- current := current + 1; if current > explored then Put_Line ("No way found."); return inf; end if; cur_s := list (current).state; exit when cur_s.pt.x = finish.x and then cur_s.pt.y = finish.y; cur_len := best (cur_s.pt.x, cur_s.pt.y); -- , cur_s.cheat, cur_s.cheat_dir end loop; return best (cur_s.pt.x, cur_s.pt.y); end Dijkstra_Algorithm; r : array (Part_Type) of VString; procedure Read_Data is c : Character; f : File_Type; begin Open (f, input_name & ".txt"); for y in reverse 1 .. n loop for x in 1 .. n loop Get (f, c); case c is when 'S' => start.x := x; start.y := y; c := '.'; when 'E' => finish.x := x; finish.y := y; c := '.'; when others => null; end case; map (x, y) := c; best_clear (x, y) := inf; end loop; end loop; Close (f); end Read_Data; procedure Show_Map is begin for y in reverse 1 .. n loop for x in 1 .. n loop if x = start.x and then y = start.y then Put ('S'); elsif x = finish.x and then y = finish.y then Put ('E'); elsif x = cheat_start.x and then y = cheat_start.y then Put ('C'); elsif x = cheat_end.x and then y = cheat_end.y then Put ('c'); else Put (map (x, y)); end if; end loop; New_Line; end loop; New_Line; end Show_Map; stat : array (1 .. 10_000) of Natural; compute_stats : constant Boolean := verbose; function Do_Part_1_Explicit_Cheat_Point return VString is len, count, save : Integer; procedure Find_Cheat_Points (cheat_step : Integer) is -- We record the optimal path found by latest -- run of Dijkstra's algorithm. i : Integer := current; step : Integer := len; begin while i /= 0 loop i := list (i).pred; step := step - 1; if step = cheat_step + 1 then cheat_end := list (i).state.pt; elsif step = cheat_step then cheat_start := list (i).state.pt; exit; end if; end loop; end Find_Cheat_Points; use Interfaces; cheats : Hash_Maps.Hash_Map_Type; value : Integer_64; key : VString; unknown : constant := -1; path_max : constant Natural := Dijkstra_Algorithm (0, nil); begin count := 0; if compute_stats then for i in 1 .. path_max loop stat (i) := 0; end loop; end if; Hash_Maps.Clear (cheats); for cheat_step in 1 .. path_max loop for cheat_dir in Direction loop len := Dijkstra_Algorithm (cheat_step, cheat_dir); save := path_max - len; if save > 0 then Find_Cheat_Points (cheat_step); key := Image (cheat_start.x) & "," & Image (cheat_start.y) & "x" & Image (cheat_end.x) & "," & Image (cheat_end.y); Hash_Maps.Find (cheats, key, unknown, value); if value = unknown then Hash_Maps.Insert (cheats, key, 1, True, value); if verbose then Put_Line (+"Saved: " & save); Show_Map; end if; if compute_stats then stat (save) := stat (save) + 1; end if; if save >= 100 then count := count + 1; end if; else if verbose then Put_Line (+"Duplicate for saved: " & save); Show_Map; end if; end if; end if; end loop; end loop; -- Finds 1361 cheats with save > 0 including 2 start/end point duplicates -> 1359 unique. -- 1360 is the correct value... if compute_stats and verbose then for i in 1 .. path_max loop if stat (i) > 0 then Put_Line (+"There are " & stat (i) & " cheats that save " & i & " picoseconds."); end if; end loop; end if; return +"" & count; end Do_Part_1_Explicit_Cheat_Point; -- The following is adapted from the very smart solution @ -- https://github.com/jcmoyer/puzzles/blob/master/AdventOfCode2024/src/day20.adb -- function Do_as_JC_Moyer (max_cheats : Positive; threshold : Natural) return VString is distance : Score_Type; -- No need for a shortest path algorithm: -- we know there is only one path. -- procedure Build_Distance_Map is c : Node; n : Point; last : Natural; begin distance := best_clear; list (1).len := 0; list (1).state.pt := start; last := 1; while last > 0 loop c := list (last); last := last - 1; distance (c.state.pt.x, c.state.pt.y) := c.len; for d in Direction loop n := c.state.pt; case d is when north => n.y := c.state.pt.y - 1; when east => n.x := c.state.pt.x + 1; when south => n.y := c.state.pt.y + 1; when west => n.x := c.state.pt.x - 1; end case; if distance (n.x, n.y) = inf and then map (n.x, n.y) = '.' then last := last + 1; list (last).len := c.len + 1; list (last).state.pt := n; end if; end loop; end loop; end Build_Distance_Map; count : Integer; c, n : Point; use Interfaces; cheats : Hash_Maps.Hash_Map_Type; value : Integer_64; key : VString; save : Integer; begin Build_Distance_Map; Hash_Maps.Clear (cheats); for x in map'Range (1) loop for y in map'Range (2) loop if distance (x, y) < inf then for dx in -max_cheats .. +max_cheats loop for dy in -max_cheats .. +max_cheats loop c.x := x; c.y := y; n.x := c.x + dx; n.y := c.y + dy; if n.x in map'Range (1) and then n.y in map'Range (2) and then Dist_L1 (n, c) <= max_cheats and then distance (c.x, c.y) > distance (n.x, n.y) -- Implied pathable; walls are = inf then -- Simulate all walls being removed horizontally from (say) c to (n.x, c.y), -- then vertically from (n.x, c.y) to n, or even on the whole rectangle with -- points c and n as opposite corners. The exact path doesn't matter: all -- lengths are the same (L1 / Manhattan distance) since there is no obstacle! -- Compute the gain obtained by having the "cheat" path: value := Integer_64 ((distance (c.x, c.y) - distance (n.x, n.y)) - Dist_L1 (n, c)); if compute_stats or else value >= Integer_64 (threshold) then key := Image (c.x) & "," & Image (c.y) & "x" & Image (n.x) & "," & Image (n.y); Hash_Maps.Insert (cheats, key, value, True, value); end if; end if; end loop; end loop; end if; end loop; end loop; count := 0; if compute_stats then for i in stat'Range loop stat (i) := 0; end loop; end if; -- Traverse the hash table for counting the stones: for i in cheats'Range loop for j in 1 .. cheats (i).slots loop save := Integer (cheats (i).slot (j).value); if save > 0 then if compute_stats then stat (save) := stat (save) + 1; end if; if save >= threshold then count := count + 1; end if; end if; end loop; end loop; if compute_stats and verbose then Put_Line (+"Max cheat length: " & max_cheats); for i in stat'Range loop if stat (i) > 0 then Put_Line (+"There are " & stat (i) & " cheats that save " & i & " picoseconds."); end if; end loop; end if; return +"" & count; end Do_as_JC_Moyer; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; threshold_part_1, threshold_part_2 : Natural; type Method is (m1, m2); choice : constant Method := m2; begin Read_Data; if Index (input_name, "mini") > 0 then threshold_part_1 := 1; threshold_part_2 := 50; else threshold_part_1 := 100; threshold_part_2 := 100; end if; case choice is when m1 => r (part_1) := Do_Part_1_Explicit_Cheat_Point; r (part_2) := +""; when m2 => r (part_1) := Do_as_JC_Moyer (2, threshold_part_1); r (part_2) := Do_as_JC_Moyer (20, threshold_part_2); end case; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 1360 (mini: 44 with threshold 1) -- Part 2: validated by AoC: 1005476 (mini: 285 with threshold 50) end if; end AoC_2024_20; ================================================ FILE: exm/aoc/2024/aoc_2024_20.txt ================================================ ############################################################################################################################################# #.....#.......#...#...#...#.....#.......###...###.......#.......###.....#.....#.....#...###.....#...#...###.........#.......#...#...###.....# #.###.#.#####.#.#.#.#.#.#.#.###.#.#####.###.#.###.#####.#.#####.###.###.#.###.#.###.#.#.###.###.#.#.#.#.###.#######.#.#####.#.#.#.#.###.###.# #.#...#...#...#.#.#.#...#.#...#.#...#...#...#.....#...#.#.....#...#...#...#...#...#...#.#...#...#.#.#.#.#...#.......#.....#...#...#...#.#...# #.#.#####.#.###.#.#.#####.###.#.###.#.###.#########.#.#.#####.###.###.#####.#####.#####.#.###.###.#.#.#.#.###.###########.###########.#.#.### #.#...#...#.#...#.#.....#.....#.#...#...#...#.......#...#...#.#...###...#...#####.....#.#.#...#...#.#.#.#...#.....#.....#...#.........#.#...# #.###.#.###.#.###.#####.#######.#.#####.###.#.###########.#.#.#.#######.#.###########.#.#.#.###.###.#.#.###.#####.#.###.###.#.#########.###.# #...#.#.#...#...#...#...#.....#.#.....#.....#.....#...###.#.#.#.#...#...#.#...#...#...#.#.#...#...#.#.#.###.#.....#.#...#...#...###.....#...# ###.#.#.#.#####.###.#.###.###.#.#####.###########.#.#.###.#.#.#.#.#.#.###.#.#.#.#.#.###.#.###.###.#.#.#.###.#.#####.#.###.#####.###.#####.### #...#.#.#.#...#...#.#...#...#...#...#...#...#...#.#.#.#...#.#.#.#.#.#...#.#.#.#.#.#...#.#...#.###.#.#.#.....#...#...#.....#...#...#.#.....### #.###.#.#.#.#.###.#.###.###.#####.#.###.#.#.#.#.#.#.#.#.###.#.#.#.#.###.#.#.#.#.#.###.#.###.#.###.#.#.#########.#.#########.#.###.#.#.####### #...#...#...#...#.#.###...#...#...#...#.#.#.#.#...#.#...#...#.#.#.#.#...#...#.#.#...#.#.###.#...#.#.#.....#.....#.#.....#...#.....#.#.......# ###.###########.#.#.#####.###.#.#####.#.#.#.#.#####.#####.###.#.#.#.#.#######.#.###.#.#.###.###.#.#.#####.#.#####.#.###.#.#########.#######.# #...#.....#...#...#.....#.#...#...#...#...#.#...#...#...#.#...#.#.#.#.....#...#...#...#.....#...#.#.###...#.###...#...#.#.#...#...#.#.......# #.###.###.#.#.#########.#.#.#####.#.#######.###.#.###.#.#.#.###.#.#.#####.#.#####.###########.###.#.###.###.###.#####.#.#.#.#.#.#.#.#.####### #...#...#.#.#.........#...#.#.....#...#...#.#...#.....#.#.#...#.#.#...###.#.#...#.....#.......#...#...#...#...#...#...#...#.#.#.#.#.#...#...# ###.###.#.#.#########.#####.#.#######.#.#.#.#.#########.#.###.#.#.###.###.#.#.#.#####.#.#######.#####.###.###.###.#.#######.#.#.#.#.###.#.#.# #...#...#...###...###...#...#...#.....#.#.#.#.#...###...#.#...#.#.#...#...#...#.#.....#.......#.#...#...#...#.#...#.....#...#...#...#...#.#.# #.###.#########.#.#####.#.#####.#.#####.#.#.#.#.#.###.###.#.###.#.#.###.#######.#.###########.#.#.#.###.###.#.#.#######.#.###########.###.#.# #.....#...#.....#...###.#.#####.#.#.....#.#.#.#.#.#...#...#.#...#.#...#.#.....#.#.....#.......#...#.#...#...#.#.#.......#.#...........#...#.# #######.#.#.#######.###.#.#####.#.#.#####.#.#.#.#.#.###.###.#.###.###.#.#.###.#.#####.#.###########.#.###.###.#.#.#######.#.###########.###.# ###.....#.#.....#...#...#...#...#.#.....#.#.#.#.#.#...#.###.#...#...#.#...#...#.....#.#...#...###...#...#.#...#.#...#...#.#.#...###.....#...# ###.#####.#####.#.###.#####.#.###.#####.#.#.#.#.#.###.#.###.###.###.#.#####.#######.#.###.#.#.###.#####.#.#.###.###.#.#.#.#.#.#.###.#####.### #...#...#...#...#...#...#...#...#...#...#...#.#.#...#.#...#.#...#...#.....#...#...#...#...#.#...#.....#.#.#.###.#...#.#...#...#...#.#.....### #.###.#.###.#.#####.###.#.#####.###.#.#######.#.###.#.###.#.#.###.#######.###.#.#.#####.###.###.#####.#.#.#.###.#.###.###########.#.#.####### #...#.#...#...#...#...#.#...#...#...#.#.....#.#.#...#...#.#.#...#.#.......###...#.....#...#.#...#...#.#.#.#.#...#.....#.........#...#.....### ###.#.###.#####.#.###.#.###.#.###.###.#.###.#.#.#.#####.#.#.###.#.#.#################.###.#.#.###.#.#.#.#.#.#.#########.#######.#########.### ###...###...#...#...#...#...#.#...###...#...#.#.#...#...#.#.#...#.#.......#...#...###.#...#.#.#...#.#.#.#.#...#...#...#.......#.....#...#...# ###########.#.#####.#####.###.#.#########.###.#.###.#.###.#.#.###.#######.#.#.#.#.###.#.###.#.#.###.#.#.#.#####.#.#.#.#######.#####.#.#.###.# #.....###...#.#...#.#...#.....#.#...#...#...#.#.#...#...#.#.#.#...#.......#.#.#.#.....#.###.#.#...#...#.#.#.....#...#.#.....#.....#...#.#...# #.###.###.###.#.#.#.#.#.#######.#.#.#.#.###.#.#.#.#####.#.#.#.#.###.#######.#.#.#######.###.#.###.#####.#.#.#########.#.###.#####.#####.#.### #...#...#.....#.#.#...#...#...#.#.#.#.#.#...#...#.#.....#...#.#...#.#...#...#.#.....#...#...#...#.....#.#.#.#.....#...#...#.#...#.#...#.#...# ###.###.#######.#.#######.#.#.#.#.#.#.#.#.#######.#.#########.###.#.#.#.#.###.#####.#.###.#####.#####.#.#.#.#.###.#.#####.#.#.#.#.#.#.#.###.# ###...#.........#.###...#...#.#.#.#.#.#.#.......#.#...#.......###.#.#.#.#.#...#...#.#.###.#.....#...#.#.#.#...#...#.......#...#.#...#.#.....# #####.###########.###.#.#####.#.#.#.#.#.#######.#.###.#.#########.#.#.#.#.#.###.#.#.#.###.#.#####.#.#.#.#.#####.###############.#####.####### #...#...........#.#...#.......#...#...#...#...#.#.#...#.#.....#...#.#.#.#.#.#...#.#.#...#.#.....#.#.#.#...#...#...#...........#.......#.....# #.#.###########.#.#.#####################.#.#.#.#.#.###.#.###.#.###.#.#.#.#.#.###.#.###.#.#####.#.#.#.#####.#.###.#.#########.#########.###.# #.#.............#...#.....#.............#...#.#.#.#...#.#.#...#.#...#.#...#.#.###.#.#...#...###.#.#...#.....#.#...#.#...#.....#...#...#.#...# #.###################.###.#.###########.#####.#.#.###.#.#.#.###.#.###.#####.#.###.#.#.#####.###.#.#####.#####.#.###.#.#.#.#####.#.#.#.#.#.### #.....................###...#...###...#...#...#.#.....#.#.#...#.#...#...#...#...#.#.#.....#...#.#.....#.....#...###.#.#...#.....#...#...#...# #############################.#.###.#.###.#.###.#######.#.###.#.###.###.#.#####.#.#.#####.###.#.#####.#####.#######.#.#####.###############.# #.............................#.....#.....#...#.......#.#.###...###...#.#.#.....#...###...#...#.#.....###...###...#.#.#...#...#.............# #.###########################################.#######.#.#.###########.#.#.#.###########.###.###.#.#######.#####.#.#.#.#.#.###.#.############# #.#...................#...#...#.....###...###.....#...#.#.....#.......#.#.#.#.....#.....#...###.#.#.......#...#.#.#.#...#...#.#.............# #.#.#################.#.#.#.#.#.###.###.#.#######.#.###.#####.#.#######.#.#.#.###.#.#####.#####.#.#.#######.#.#.#.#.#######.#.#############.# #...#...###...#.......#.#.#.#...###.....#.......#.#.###.......#...#...#.#.#.#...#...#...#.###...#.#.........#...#...#.......#.#...........#.# #####.#.###.#.#.#######.#.#.###################.#.#.#############.#.#.#.#.#.###.#####.#.#.###.###.###################.#######.#.#########.#.# #.....#.....#.#.........#...###...........#.....#...#.....#.....#.#.#.#.#...###...#...#.#...#.....###.........#.....#.#...###.#.#...#...#...# #.###########.#################.#########.#.#########.###.#.###.#.#.#.#.#########.#.###.###.#########.#######.#.###.#.#.#.###.#.#.#.#.#.##### #...#...#...#...#...#...###...#.........#.#.#...#...#...#.#.#...#.#.#...#...###...#...#...#.#...#...#.......#.#...#.#...#.....#...#...#.....# ###.#.#.#.#.###.#.#.#.#.###.#.#########.#.#.#.#.#.#.###.#.#.#.###.#.#####.#.###.#####.###.#.#.#.#.#.#######.#.###.#.#######################.# #...#.#...#...#.#.#...#...#.#...........#.#...#...#.....#...#.###.#.#.....#.....#...#.#...#.#.#...#.#.......#.....#...#.....#...#...#.......# #.###.#######.#.#.#######.#.#############.###################.###.#.#.###########.#.#.#.###.#.#####.#.###############.#.###.#.#.#.#.#.####### #.....#...###.#...#.....#.#.........#...#...........#...#...#...#.#.#.#.......#...#...#.....#.....#.#...........#...#.#.###.#.#.#.#...#...### #######.#.###.#####.###.#.#########.#.#.###########.#.#.#.#.###.#.#.#.#.#####.#.#################.#.###########.#.#.#.#.###.#.#.#.#####.#.### #.....#.#.#...#...#.###.#.#...#...#...#...........#.#.#.#.#.#...#.#.#.#.#.....#.#...###...#...#...#.........#...#.#.#.#...#...#...###...#...# #.###.#.#.#.###.#.#.###.#.#.#.#.#.###############.#.#.#.#.#.#.###.#.#.#.#.#####.#.#.###.#.#.#.#.###########.#.###.#.#.###.###########.#####.# #...#.#.#.#.....#...#...#...#...#.................#.#.#...#.#.###...#.#.#...#...#.#.....#...#...#...#.....#.#.....#.#...#.....###...#.#.....# ###.#.#.#.###########.#############################.#.#####.#.#######.#.###.#.###.###############.#.#.###.#.#######.###.#####.###.#.#.#.##### ###.#...#.#...#.....#.............................#.#...#...#.......#...###...###.........#...#...#.#...#.#.........###.....#.....#...#.....# ###.#####.#.#.#.###.#############################.#.###.#.#########.#####################.#.#.#.###.###.#.#################.###############.# #...#...#.#.#.#...#...............#.....#.........#.....#...#...#...###...................#.#...###.....#.....###.........#...#...#...#.....# #.###.#.#.#.#.###.###############.#.###.#.#################.#.#.#.#####.###################.#################.###.#######.###.#.#.#.#.#.##### #...#.#.#...#.....#.............#.#.###...#...###...#.....#.#.#...#.....#...#.....#...#...#.#.........###...#.....#.......###...#.#.#.#.....# ###.#.#.###########.###########.#.#.#######.#.###.#.#.###.#.#.#####.#####.#.#.###.#.#.#.#.#.#.#######.###.#.#######.#############.#.#.#####.# ###...#.............###...#.....#.#.........#...#.#.#.#...#.#.....#.....#.#.#.#...#.#...#.#.#.......#.....#.........#...........#...#.......# #######################.#.#.#####.#############.#.#.#.#.###.#####.#####.#.#.#.#.###.#####.#.#######.#################.#########.############# #.......................#...#...#.....#.......#...#...#...#.#.....#.....#.#...#.....###...#.#.......#.................#.........#...#.....### #.###########################.#.#####.#.#####.###########.#.#.#####.#####.#############.###.#.#######.#################.#########.#.#.###.### #...................#...#...#.#.#...#...#...#.....#.......#...#...#.......#...#.........#...#...#...#.#.......#...#.....#...#.....#.#...#...# ###################.#.#.#.#.#.#.#.#.#####.#.#####.#.###########.#.#########.#.#.#########.#####.#.#.#.#.#####.#.#.#.#####.#.#.#####.###.###.# #.....#...........#.#.#.#.#.#.#...#.......#.....#.#.........#...#.#.....#...#.#.....#.....#####.#.#...#.....#...#...###...#...#.....###.#...# #.###.#.#########.#.#.#.#.#.#.#################.#.#########.#.###.#.###.#.###.#####.#.#########.#.#########.###########.#######.#######.#.### #...#.#.........#...#.#...#...#.................#.....#...#.#...#.#...#.#...#.......#.#...###...#.#.........#...###.....#.......#.......#...# ###.#.#########.#####.#########.#####################.#.#.#.###.#.###.#.###.#########.#.#.###.###.#.#########.#.###.#####.#######.#########.# #...#.......###.......#.......#.......#.........#...#.#.#.#.....#...#.#...#.....#...#.#.#.....#...#...........#.....#.....###...#.#.......#.# #.#########.###########.#####.#######.#.#######.#.#.#.#.#.#########.#.###.#####.#.#.#.#.#######.#####################.#######.#.#.#.#####.#.# #.#...#...#.............#...#.........#.#.......#.#.#...#.#...#.....#.#...#.....#.#.#.#...#...#.#...........#...#...#.........#...#...###...# #.#.#.#.#.###############.#.###########.#.#######.#.#####.#.#.#.#####.#.###.#####.#.#.###.#.#.#.#.#########.#.#.#.#.#################.####### #.#.#...#...#...#.....#...#.............#.......#.#.....#.#.#.#.#.....#...#.......#...###...#...#.....#...#.#.#...#.#.....#.....#...#.......# #.#.#######.#.#.#.###.#.#######################.#.#####.#.#.#.#.#.#######.###########################.#.#.#.#.#####.#.###.#.###.#.#.#######.# #.#...#...#...#...###...#.......................#.#.....#.#.#...#.....#...###.....#...........#...###...#.#.#...#...#...#...###.#.#.......#.# #.###.#.#.###############.#######################.#.#####.#.#########.#.#####.###.#.#########.#.#.#######.#.###.#.#####.#######.#.#######.#.# #...#.#.#.............###...................#...#.#.#...#...#.....#...#...#...#...#.........#.#.#.#...#...#.....#...#...#...#...#.......#.#.# ###.#.#.#############.#####################.#.#.#.#.#.#.#####.###.#.#####.#.###.###########.#.#.#.#.#.#.###########.#.###.#.#.#########.#.#.# ###...#.............#.......................#.#...#...#...#...#...#.#.....#...#.....#.......#...#...#.#...........#.#.....#.#...#.......#.#.# ###################.#########################.###########.#.###.###.#.#######.#####.#.###############.###########.#.#######.###.#.#######.#.# #...#...#...........#...#...#.......#...#...#.#...........#...#...#.#...#...#.#.....#.....#.........#.............#.#.......###.#.......#.#.# #.#.#.#.#.###########.#.#.#.#.#####.#.#.#.#.#.#.#############.###.#.###.#.#.#.#.#########.#.#######.###############.#.#########.#######.#.#.# #.#...#...#.......#...#...#...#.....#.#.#.#.#.#.###....S#...#...#.#.#...#.#...#.#.....###...#...#...#.............#.#.........#.#...#...#...# #.#########.#####.#.###########.#####.#.#.#.#.#.###.#####.#.###.#.#.#.###.#####.#.###.#######.#.#.###.###########.#.#########.#.#.#.#.####### #...#...#...#.....#.###...#...#.......#...#...#...#.#####.#...#.#...#.###.#.....#.#...#...#...#.#.#...###.........#.......#...#.#.#.#.......# ###.#.#.#.###.#####.###.#.#.#.###################.#.#####.###.#.#####.###.#.#####.#.###.#.#.###.#.#.#####.###############.#.###.#.#.#######.# #...#.#.#.#...#...#.#...#...#.....................#.#####...#.#...#...#...#...#...#...#.#.#...#.#...#...#.....#.......###...###...#...#.....# #.###.#.#.#.###.#.#.#.#############################.#######.#.###.#.###.#####.#.#####.#.#.###.#.#####.#.#####.#.#####.###############.#.##### #.....#...#.....#...#.......................#.......#####...#...#.#...#.#.....#.#.....#.#.#...#.#...#.#.....#...#.....#...........###.#.....# ###########################################.#.###########.#####.#.###.#.#.#####.#.#####.#.#.###.#.#.#.#####.#####.#####.#########.###.#####.# #.........###...........#...................#.###########.....#.#.#...#.#...#...#...#...#.#...#.#.#.#.....#.......#...#.#.........#...#...#.# #.#######.###.#########.#.###################.###############.#.#.#.###.###.#.#####.#.###.###.#.#.#.#####.#########.#.#.#.#########.###.#.#.# #.......#.....#...#...#.#...............#...#.#####.....#...#.#.#.#.###.#...#.#.....#...#.#...#...#.#...#.........#.#...#.........#.#...#.#.# #######.#######.#.#.#.#.###############.#.#.#.#####.###.#.#.#.#.#.#.###.#.###.#.#######.#.#.#######.#.#.#########.#.#############.#.#.###.#.# ###...#.........#...#.#.#...............#.#...#####...#.#.#...#.#.#...#.#.#...#...#...#.#.#.#...#...#.#...........#.#...........#.#...###.#.# ###.#.###############.#.#.###############.###########.#.#.#####.#.###.#.#.#.#####.#.#.#.#.#.#.#.#.###.#############.#.#########.#.#######.#.# #...#...........#.....#...#...#.....#...#.....#######.#.#...#...#.#...#.#.#...#...#.#.#.#.#...#.#.###...............#.........#.#.......#...# #.#############.#.#########.#.#.###.#.#.#####.#######.#.###.#.###.#.###.#.###.#.###.#.#.#.#####.#.###########################.#.#######.##### #.#.....#.....#...#.....#...#...###...#...#...#######.#...#.#...#.#...#.#.#...#.#...#.#.#.#...#.#.#...#...#...#...#...#...#...#.#.....#.#...# #.#.###.#.###.#####.###.#.###############.#.#########.###.#.###.#.###.#.#.#.###.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.#.#.#.# #...###...###.......###...###...#...#.....#...#######...#.#.#...#.#...#.#.#...#.#.###...#.#.#.#.#.#.#...#.#.#...#.#.#...#...###...#...#...#.# #############################.#.#.#.#.#######.#########.#.#.#.###.#.###.#.###.#.#.#######.#.#.#.#.#.#####.#.#####.#.###############.#######.# #.......#...#.........#...#...#...#...#...#...#######...#.#.#...#.#...#.#.#...#.#...###...#.#.#.#.#.....#.#.....#.#...............#.....#...# #.#####.#.#.#.#######.#.#.#.###########.#.#.#########.###.#.###.#.###.#.#.#.###.###.###.###.#.#.#.#####.#.#####.#.###############.#####.#.### #.....#.#.#...#.....#.#.#...#...#.....#.#.#...#..E###...#.#.#...#.#...#.#...###...#...#...#.#.#.#.#...#.#.#...#.#.#...#...........#...#...### #####.#.#.#####.###.#.#.#####.#.#.###.#.#.###.#.#######.#.#.#.###.#.###.#########.###.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###########.#.####### #.....#...#...#.#...#...#...#.#.#.#...#.#.#...#.#...#...#...#.....#...#.###.......#...###.#.#.#.#...#.#.#...#.#.#.#.#.#.............#.......# #.#########.#.#.#.#######.#.#.#.#.#.###.#.#.###.#.#.#.###############.#.###.#######.#####.#.#.#.#####.#.#####.#.#.#.#.#####################.# #.#.........#...#...#...#.#.#.#.#.#...#.#...###...#.#...........#.....#...#.....#...#.....#.#.#...###.#.....#.#.#.#.#...#...................# #.#.###############.#.#.#.#.#.#.#.###.#.###########.###########.#.#######.#####.#.###.#####.#.###.###.#####.#.#.#.#.###.#.################### #...#.......#.......#.#.#.#...#.#.#...#...#.....#...#.....#...#.#.#.....#...###.#.###...#...#...#...#.#...#.#.#.#...###.#.........#.........# #####.#####.#.#######.#.#.#####.#.#.#####.#.###.#.###.###.#.#.#.#.#.###.###.###.#.#####.#.#####.###.#.#.#.#.#.#.#######.#########.#.#######.# ###...#...#.#.........#.#...#...#.#.#...#.#...#.#.#...###...#.#.#.#.#...#...#...#.....#...#.....#...#...#.#.#.#.......#...#...#...#.#.......# ###.###.#.#.###########.###.#.###.#.#.#.#.###.#.#.#.#########.#.#.#.#.###.###.#######.#####.#####.#######.#.#.#######.###.#.#.#.###.#.####### #...#...#.#.............#...#...#.#.#.#...#...#...#.........#.#.#...#...#...#...#.....#.....#...#.#.....#.#.#.#...#...###.#.#...###.#.....### #.###.###.###############.#####.#.#.#.#####.###############.#.#.#######.###.###.#.#####.#####.#.#.#.###.#.#.#.#.#.#.#####.#.#######.#####.### #...#...#.#.............#.#.....#.#.#.#.....#...#.....#.....#.#...#####...#.#...#.#.....#...#.#.#...#...#.#.#.#.#.#.#...#.#.........#...#...# ###.###.#.#.###########.#.#.#####.#.#.#.#####.#.#.###.#.#####.###.#######.#.#.###.#.#####.#.#.#.#####.###.#.#.#.#.#.#.#.#.###########.#.###.# #...#...#...###.........#.#.#...#.#.#.#...#...#.#...#.#.....#...#...#.....#.#.....#.#.....#.#.#...#...###...#.#.#.#...#.#...#.........#...#.# #.###.#########.#########.#.#.#.#.#.#.###.#.###.###.#.#####.###.###.#.#####.#######.#.#####.#.###.#.#########.#.#.#####.###.#.###########.#.# #.#...###.......#.....#...#.#.#.#.#.#.#...#...#.#...#.#.....#...#...#...#...###.....#.#.....#...#.#.........#.#.#.#...#.#...#.......#...#...# #.#.#####.#######.###.#.###.#.#.#.#.#.#.#####.#.#.###.#.#####.###.#####.#.#####.#####.#.#######.#.#########.#.#.#.#.#.#.#.#########.#.#.##### #...#...#.....#...#...#.###.#.#...#...#...#...#.#...#.#.....#...#.###...#.#.....#...#.#.#...#...#.#.........#.#.#.#.#.#.#.#...#...#...#.....# #####.#.#####.#.###.###.###.#.###########.#.###.###.#.#####.###.#.###.###.#.#####.#.#.#.#.#.#.###.#.#########.#.#.#.#.#.#.#.#.#.#.#########.# ###...#.......#...#...#.#...#...#...#...#.#.###.#...#.....#...#.#...#...#.#.....#.#.#.#...#.#.#...#.........#...#.#.#...#...#.#.#.......#...# ###.#############.###.#.#.#####.#.#.#.#.#.#.###.#.#######.###.#.###.###.#.#####.#.#.#.#####.#.#.###########.#####.#.#########.#.#######.#.### #...#.....#...#...#...#.#...#...#.#...#...#...#.#.###...#.....#.#...#...#.#.....#.#.#...###...#.#...#.....#.....#.#...#...###.#.......#.#...# #.###.###.#.#.#.###.###.###.#.###.###########.#.#.###.#.#######.#.###.###.#.#####.#.###.#######.#.#.#.###.#####.#.###.#.#.###.#######.#.###.# #...#.###...#.#...#...#.###.#.###.........#...#.#.....#.....###.#.###.....#...#...#...#.#.......#.#.#...#.#.....#.#...#.#...#...#.....#.....# ###.#.#######.###.###.#.###.#.###########.#.###.###########.###.#.###########.#.#####.#.#.#######.#.###.#.#.#####.#.###.###.###.#.########### #...#.#.......#...#...#.#...#...#.........#...#.#.....#...#...#.#.......#.....#.#.....#.#...#...#.#.#...#.#...#...#.....#...#...#...........# #.###.#.#######.###.###.#.#####.#.###########.#.#.###.#.#.###.#.#######.#.#####.#.#####.###.#.#.#.#.#.###.###.#.#########.###.#############.# #.....#.........###.....#.......#.............#...###...#.....#.........#.......#.......###...#...#...###.....#...........###...............# ############################################################################################################################################# ================================================ FILE: exm/aoc/2024/aoc_2024_20_mini.txt ================================================ ############### #...#...#.....# #.#.#.#.#.###.# #S#...#.#.#...# #######.#.#.### #######.#.#...# #######.#.###.# ###..E#...#...# ###.#######.### #...###...#...# #.#####.#.###.# #.#...#.#.#...# #.#.#.#.#.#.### #...#...#...### ############### ================================================ FILE: exm/aoc/2024/aoc_2024_20_questions.txt ================================================ --- Day 20: Race Condition --- The Historians are quite pixelated again. This time, a massive, black building looms over you - you're right outside the CPU! While The Historians get to work, a nearby program sees that you're idle and challenges you to a race. Apparently, you've arrived just in time for the frequently-held race condition festival! The race takes place on a particularly long and twisting code path; programs compete to see who can finish in the fewest picoseconds. The winner even gets their very own mutex! They hand you a map of the racetrack (your puzzle input). For example: ############### #...#...#.....# #.#.#.#.#.###.# #S#...#.#.#...# #######.#.#.### #######.#.#...# #######.#.###.# ###..E#...#...# ###.#######.### #...###...#...# #.#####.#.###.# #.#...#.#.#...# #.#.#.#.#.#.### #...#...#...### ############### The map consists of track (.) - including the start (S) and end (E) positions (both of which also count as track) - and walls (#). When a program runs through the racetrack, it starts at the start position. Then, it is allowed to move up, down, left, or right; each such move takes 1 picosecond. The goal is to reach the end position as quickly as possible. In this example racetrack, the fastest time is 84 picoseconds. Because there is only a single path from the start to the end and the programs all go the same speed, the races used to be pretty boring. To make things more interesting, they introduced a new rule to the races: programs are allowed to cheat. The rules for cheating are very strict. Exactly once during a race, a program may disable collision for up to 2 picoseconds. This allows the program to pass through walls as if they were regular track. At the end of the cheat, the program must be back on normal track again; otherwise, it will receive a segmentation fault and get disqualified. So, a program could complete the course in 72 picoseconds (saving 12 picoseconds) by cheating for the two moves marked 1 and 2: ############### #...#...12....# #.#.#.#.#.###.# #S#...#.#.#...# #######.#.#.### #######.#.#...# #######.#.###.# ###..E#...#...# ###.#######.### #...###...#...# #.#####.#.###.# #.#...#.#.#...# #.#.#.#.#.#.### #...#...#...### ############### Or, a program could complete the course in 64 picoseconds (saving 20 picoseconds) by cheating for the two moves marked 1 and 2: ############### #...#...#.....# #.#.#.#.#.###.# #S#...#.#.#...# #######.#.#.### #######.#.#...# #######.#.###.# ###..E#...12..# ###.#######.### #...###...#...# #.#####.#.###.# #.#...#.#.#...# #.#.#.#.#.#.### #...#...#...### ############### This cheat saves 38 picoseconds: ############### #...#...#.....# #.#.#.#.#.###.# #S#...#.#.#...# #######.#.#.### #######.#.#...# #######.#.###.# ###..E#...#...# ###.####1##.### #...###.2.#...# #.#####.#.###.# #.#...#.#.#...# #.#.#.#.#.#.### #...#...#...### ############### This cheat saves 64 picoseconds and takes the program directly to the end: ############### #...#...#.....# #.#.#.#.#.###.# #S#...#.#.#...# #######.#.#.### #######.#.#...# #######.#.###.# ###..21...#...# ###.#######.### #...###...#...# #.#####.#.###.# #.#...#.#.#...# #.#.#.#.#.#.### #...#...#...### ############### Each cheat has a distinct start position (the position where the cheat is activated, just before the first move that is allowed to go through walls) and end position; cheats are uniquely identified by their start position and end position. In this example, the total number of cheats (grouped by the amount of time they save) are as follows: There are 14 cheats that save 2 picoseconds. There are 14 cheats that save 4 picoseconds. There are 2 cheats that save 6 picoseconds. There are 4 cheats that save 8 picoseconds. There are 2 cheats that save 10 picoseconds. There are 3 cheats that save 12 picoseconds. There is one cheat that saves 20 picoseconds. There is one cheat that saves 36 picoseconds. There is one cheat that saves 38 picoseconds. There is one cheat that saves 40 picoseconds. There is one cheat that saves 64 picoseconds. You aren't sure what the conditions of the racetrack will be like, so to give yourself as many options as possible, you'll need a list of the best cheats. How many cheats would save you at least 100 picoseconds? --- Part Two --- The programs seem perplexed by your list of cheats. Apparently, the two-picosecond cheating rule was deprecated several milliseconds ago! The latest version of the cheating rule permits a single cheat that instead lasts at most 20 picoseconds. Now, in addition to all the cheats that were possible in just two picoseconds, many more cheats are possible. This six-picosecond cheat saves 76 picoseconds: ############### #...#...#.....# #.#.#.#.#.###.# #S#...#.#.#...# #1#####.#.#.### #2#####.#.#...# #3#####.#.###.# #456.E#...#...# ###.#######.### #...###...#...# #.#####.#.###.# #.#...#.#.#...# #.#.#.#.#.#.### #...#...#...### ############### Because this cheat has the same start and end positions as the one above, it's the same cheat, even though the path taken during the cheat is different: ############### #...#...#.....# #.#.#.#.#.###.# #S12..#.#.#...# ###3###.#.#.### ###4###.#.#...# ###5###.#.###.# ###6.E#...#...# ###.#######.### #...###...#...# #.#####.#.###.# #.#...#.#.#...# #.#.#.#.#.#.### #...#...#...### ############### Cheats don't need to use all 20 picoseconds; cheats can last any amount of time up to and including 20 picoseconds (but can still only end when the program is on normal track). Any cheat time not used is lost; it can't be saved for another cheat later. You'll still need a list of the best cheats, but now there are even more to choose between. Here are the quantities of cheats in this example that save 50 picoseconds or more: There are 32 cheats that save 50 picoseconds. There are 31 cheats that save 52 picoseconds. There are 29 cheats that save 54 picoseconds. There are 39 cheats that save 56 picoseconds. There are 25 cheats that save 58 picoseconds. There are 23 cheats that save 60 picoseconds. There are 20 cheats that save 62 picoseconds. There are 19 cheats that save 64 picoseconds. There are 12 cheats that save 66 picoseconds. There are 14 cheats that save 68 picoseconds. There are 12 cheats that save 70 picoseconds. There are 22 cheats that save 72 picoseconds. There are 4 cheats that save 74 picoseconds. There are 3 cheats that save 76 picoseconds. Find the best cheats using the updated cheating rules. How many cheats would save you at least 100 picoseconds? ================================================ FILE: exm/aoc/2024/aoc_2024_21.adb ================================================ -- Solution to Advent of Code 2024, Day 21 ------------------------------------------- -- Keypad Conundrum -- -- https://adventofcode.com/2024/day/21 -- Copy of questions in: aoc_2024_21_questions.txt -- -- HAC 0.40 "nice-to-have"'s detected in this exercise: -- -- * pass string literals directly! - Solved in HAC 0.41 -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox, Interfaces; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_21 is use AoC_Toolbox, HAT, Interfaces; -- The following algorithm is adapted for HAC subset from J.C. Moyer's solution: -- https://github.com/jcmoyer/puzzles/blob/master/AdventOfCode2024/src/day21.adb -- -- Differences from J.C.M.'s implementation: -- - Breadth First Search (BFS) algo for getting paths in keypads is -- replaced by a systematic search, "Manhattan-style" (there is -- no obstacle except one gap). -- - Memoization (cache-ing) is done via an array instead of a hash map. ---------------- -- Commands -- ---------------- -- A command is abstractly a single instruction for a robot to perform. -- Commands can be "lowered" in the code-gen sense to a sequence of -- commands for a robot controlling another robot. type Command is (c_west, c_east, c_north, c_south, c_press); ---------------------- -- Numeric keypad -- ---------------------- type Number_Pad_Key is (np_A, np_0, np_1, np_2, np_3, np_4, np_5, np_6, np_7, np_8, np_9); function Parse_Np_Key (c : Character) return Number_Pad_Key is begin case c is when '0' .. '9' => return Number_Pad_Key'Val (Number_Pad_Key'Pos (np_0) + Character'Pos (c) - Character'Pos ('0')); when others => return np_A; end case; end Parse_Np_Key; -- +---+---+---+ -- | 7 | 8 | 9 | -- +---+---+---+ -- | 4 | 5 | 6 | -- +---+---+---+ -- | 1 | 2 | 3 | -- +---+---+---+ -- | 0 | A | -- +---+---+ procedure Position_Num (k : Number_Pad_Key; p : out Point) is begin case k is when np_7 => p.y := 1; p.x := 1; when np_8 => p.y := 1; p.x := 2; when np_9 => p.y := 1; p.x := 3; when np_4 => p.y := 2; p.x := 1; when np_5 => p.y := 2; p.x := 2; when np_6 => p.y := 2; p.x := 3; when np_1 => p.y := 3; p.x := 1; when np_2 => p.y := 3; p.x := 2; when np_3 => p.y := 3; p.x := 3; when np_0 => p.y := 4; p.x := 2; when np_A => p.y := 4; p.x := 3; end case; end Position_Num; -------------------------- -- Directional keypad -- -------------------------- type Directional_Pad_Key is (dp_left, dp_up, dp_down, dp_right, dp_A); function Command_To_Key (c : Command) return Directional_Pad_Key is begin case c is when c_east => return dp_right; when c_south => return dp_down; when c_west => return dp_left; when c_north => return dp_up; when c_press => return dp_A; end case; end Command_To_Key; -- +---+---+ -- | ^ | A | -- +---+---+---+ -- | < | v | > | -- +---+---+---+ procedure Position_Dir (k : Directional_Pad_Key; p : out Point) is begin case k is when dp_up => p.y := 1; p.x := 2; when dp_A => p.y := 1; p.x := 3; when dp_left => p.y := 2; p.x := 1; when dp_down => p.y := 2; p.x := 2; when dp_right => p.y := 2; p.x := 3; end case; end Position_Dir; subtype Pad_Range_X is Integer range 1 .. 3; subtype Max_Pad_Range_Y is Integer range 1 .. 4; gap_numpad, gap_dirpad : Point; max_robot_level : constant := 25; type Cache_Type is array (Pad_Range_X, -- Memoization by location from.x Max_Pad_Range_Y, -- Memoization by location from.y Pad_Range_X, -- Memoization by location to.x Max_Pad_Range_Y, -- Memoization by location to.y 0 .. max_robot_level) -- Memoization by recursion depth of Integer_64; cache, cache_clear : Cache_Type; verbose : constant Boolean := False; inf : constant Integer_64 := Integer_64'Last; -- Approximation of infinity. function Lower_Commands (from, to, gap : Point; robot_count : Integer; depth : Integer) return Integer_64 is -- Directional pad controlling us, which we will lower commands to. dpad_key, next_key : Directional_Pad_Key; sum : Integer_64 := 0; procedure Single_Press (new_cmd : Command) is p1, p2 : Point; begin Position_Dir (dpad_key, p1); next_key := Command_To_Key (new_cmd); Position_Dir (next_key, p2); sum := sum + Lower_Commands (p1, p2, gap_dirpad, robot_count, depth + 1); dpad_key := next_key; end Single_Press; cmd : Command; valid : Boolean; cur_pos : Point; min : Integer_64; dx, dy, len_x, len_y, length, n, horizontal_steps : Integer; cached_val : Integer_64; begin if depth = robot_count then -- Direct command. return 1; else cached_val := cache (from.x, from.y, to.x, to.y, depth); if cached_val >= 0 then return cached_val; end if; min := inf; dx := Sgn (to.x - from.x); dy := Sgn (to.y - from.y); len_x := abs (to.x - from.x); len_y := abs (to.y - from.y); length := len_x + len_y; All_Paths : for comb in 0 .. 2 ** length - 1 loop n := comb; horizontal_steps := 0; for count in 1 .. length loop if n mod 2 = 1 then -- Binary representation of `comb` has 1's for -- horizontal moves and 0's for vertical moves. horizontal_steps := horizontal_steps + 1; end if; n := n / 2; end loop; if horizontal_steps = len_x then -- The numer of 1's in the code `comb` matches the number of -- horizontal moves. Then the number of vertical moves is also correct. sum := 0; dpad_key := dp_A; n := comb; cur_pos := from; valid := True; Path : for count in 1 .. length loop if n mod 2 = 1 then -- Horizontal move. if dx = 1 then cmd := c_east; else cmd := c_west; end if; cur_pos.x := cur_pos.x + dx; else -- Vertical move. if dy = 1 then cmd := c_south; else cmd := c_north; end if; cur_pos.y := cur_pos.y + dy; end if; -- "If a robot arm is ever aimed at a gap where no button is -- present on the keypad, even for an instant, the robot will -- panic unrecoverably. So, don't do that." -- valid := Dist_L1 (cur_pos, gap) > 0; exit Path when not valid; Single_Press (cmd); n := n / 2; end loop Path; if valid then -- Do "Press"! Single_Press (c_press); -- Take the minimum length of all lowered command sequences. if sum < min then if verbose and then min < inf then Put_Line (+"Depth: " & depth & ", from " & from.x & "," & from.y & " to " & to.x & "," & to.y & ": better length, from" & min'Image & " to" & sum'Image); end if; min := sum; end if; end if; end if; end loop All_Paths; end if; cache (from.x, from.y, to.x, to.y, depth) := min; return min; end Lower_Commands; subtype Digicode is String (1 .. 4); function Do_Code (s : Digicode; robot_count : Integer) return Integer_64 is npad_key, next_key : Number_Pad_Key := np_A; sum : Integer_64 := 0; p1, p2 : Point; numeric_part : String (1 .. 3); begin for i in s'Range loop -- We start the search with numpad parameters, and it will recurse -- with dirpad parameters. Position_Num (npad_key, p1); next_key := Parse_Np_Key (s (i)); Position_Num (next_key, p2); sum := sum + Lower_Commands (p1, p2, gap_numpad, robot_count, 0); npad_key := next_key; end loop; for i in numeric_part'Range loop numeric_part (i) := s (i); end loop; return Integer_64'Value (numeric_part) * sum; end Do_Code; r : array (Part_Type) of VString; data : constant Data_Type := input; procedure Do_Part (part : Part_Type) is score : Integer_64 := 0; robots : Positive; procedure Cumulate_Complexity (d : Digicode) is begin score := score + Do_Code (d, robots); end Cumulate_Complexity; begin case part is when part_1 => robots := 3; when part_2 => robots := max_robot_level + 1; end case; case data is when mini => Cumulate_Complexity ("029A"); Cumulate_Complexity ("980A"); Cumulate_Complexity ("179A"); Cumulate_Complexity ("456A"); Cumulate_Complexity ("379A"); when input => Cumulate_Complexity ("965A"); Cumulate_Complexity ("143A"); Cumulate_Complexity ("528A"); Cumulate_Complexity ("670A"); Cumulate_Complexity ("973A"); end case; r (part) := +"" & Trim_Left (+score'Image); end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin gap_numpad.y := 4; gap_numpad.x := 1; gap_dirpad.y := 1; gap_dirpad.x := 1; -- "Full Ada 2012+" does the following in a single loop (for ... of). for i1 in Cache_Type'Range (1) loop for i2 in Cache_Type'Range (2) loop for i3 in Cache_Type'Range (3) loop for i4 in Cache_Type'Range (4) loop for i5 in Cache_Type'Range (5) loop cache_clear (i1, i2, i3, i4, i5) := -1; end loop; end loop; end loop; end loop; end loop; for part in Part_Type loop cache := cache_clear; Do_Part (part); end loop; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 222670 -- Part 2: validated by AoC: 271397390297138 end if; end AoC_2024_21; ================================================ FILE: exm/aoc/2024/aoc_2024_21_questions.txt ================================================ --- Day 21: Keypad Conundrum --- As you teleport onto Santa's Reindeer-class starship, The Historians begin to panic: someone from their search party is missing. A quick life-form scan by the ship's computer reveals that when the missing Historian teleported, he arrived in another part of the ship. The door to that area is locked, but the computer can't open it; it can only be opened by physically typing the door codes (your puzzle input) on the numeric keypad on the door. The numeric keypad has four rows of buttons: 789, 456, 123, and finally an empty gap followed by 0A. Visually, they are arranged like this: +---+---+---+ | 7 | 8 | 9 | +---+---+---+ | 4 | 5 | 6 | +---+---+---+ | 1 | 2 | 3 | +---+---+---+ | 0 | A | +---+---+ Unfortunately, the area outside the door is currently depressurized and nobody can go near the door. A robot needs to be sent instead. The robot has no problem navigating the ship and finding the numeric keypad, but it's not designed for button pushing: it can't be told to push a specific button directly. Instead, it has a robotic arm that can be controlled remotely via a directional keypad. The directional keypad has two rows of buttons: a gap / ^ (up) / A (activate) on the first row and < (left) / v (down) / > (right) on the second row. Visually, they are arranged like this: +---+---+ | ^ | A | +---+---+---+ | < | v | > | +---+---+---+ When the robot arrives at the numeric keypad, its robotic arm is pointed at the A button in the bottom right corner. After that, this directional keypad remote control must be used to maneuver the robotic arm: the up / down / left / right buttons cause it to move its arm one button in that direction, and the A button causes the robot to briefly move forward, pressing the button being aimed at by the robotic arm. For example, to make the robot type 029A on the numeric keypad, one sequence of inputs on the directional keypad you could use is: < to move the arm from A (its initial position) to 0. A to push the 0 button. ^A to move the arm to the 2 button and push it. >^^A to move the arm to the 9 button and push it. vvvA to move the arm to the A button and push it. In total, there are three shortest possible sequences of button presses on this directional keypad that would cause the robot to type 029A: ^^AvvvA, ^AvvvA, and AvvvA. Unfortunately, the area containing this directional keypad remote control is currently experiencing high levels of radiation and nobody can go near it. A robot needs to be sent instead. When the robot arrives at the directional keypad, its robot arm is pointed at the A button in the upper right corner. After that, a second, different directional keypad remote control is used to control this robot (in the same way as the first robot, except that this one is typing on a directional keypad instead of a numeric keypad). There are multiple shortest possible sequences of directional keypad button presses that would cause this robot to tell the first robot to type 029A on the door. One such sequence is v<>^AAvA<^AA>A^A. Unfortunately, the area containing this second directional keypad remote control is currently -40 degrees! Another robot will need to be sent to type on that directional keypad, too. There are many shortest possible sequences of directional keypad button presses that would cause this robot to tell the second robot to tell the first robot to eventually type 029A on the door. One such sequence is >^AvAA<^A>A>^AvA^A^A^A>AAvA^AA>^AAAvA<^A>A. Unfortunately, the area containing this third directional keypad remote control is currently full of Historians, so no robots can find a clear path there. Instead, you will have to type this sequence yourself. Were you to choose this sequence of button presses, here are all of the buttons that would be pressed on your directional keypad, the two robots' directional keypads, and the numeric keypad: >^AvAA<^A>A>^AvA^A^A^A>AAvA^AA>^AAAvA<^A>A v<>^AAvA<^AA>A^A ^^AvvvA 029A In summary, there are the following keypads: One directional keypad that you are using. Two directional keypads that robots are using. One numeric keypad (on a door) that a robot is using. It is important to remember that these robots are not designed for button pushing. In particular, if a robot arm is ever aimed at a gap where no button is present on the keypad, even for an instant, the robot will panic unrecoverably. So, don't do that. All robots will initially aim at the keypad's A key, wherever it is. To unlock the door, five codes will need to be typed on its numeric keypad. For example: 029A 980A 179A 456A 379A For each of these, here is a shortest sequence of button presses you could type to cause the desired code to be typed on the numeric keypad: 029A: >^AvAA<^A>A>^AvA^A^A^A>AAvA^AA>^AAAvA<^A>A 980A: >^AAAvA^A>^AvAA<^A>AA>^AAAvA<^A>A^AA 179A: >^A>^AAvAA<^A>A>^AAvA^A^AAAA>^AAAvA<^A>A 456A: >^AA>^AAvAA<^A>A^AA^AAA>^AAvA<^A>A 379A: >^AvA^A>^AAvA<^A>AAvA^A^AAAA>^AAAvA<^A>A The Historians are getting nervous; the ship computer doesn't remember whether the missing Historian is trapped in the area containing a giant electromagnet or molten lava. You'll need to make sure that for each of the five codes, you find the shortest sequence of button presses necessary. The complexity of a single code (like 029A) is equal to the result of multiplying these two values: The length of the shortest sequence of button presses you need to type on your directional keypad in order to cause the code to be typed on the numeric keypad; for 029A, this would be 68. The numeric part of the code (ignoring leading zeroes); for 029A, this would be 29. In the above example, complexity of the five codes can be found by calculating 68 * 29, 60 * 980, 68 * 179, 64 * 456, and 64 * 379. Adding these together produces 126384. Find the fewest number of button presses you'll need to perform in order to cause the robot in front of the door to type each code. What is the sum of the complexities of the five codes on your list? --- Part Two --- Just as the missing Historian is released, The Historians realize that a second member of their search party has also been missing this entire time! A quick life-form scan reveals the Historian is also trapped in a locked area of the ship. Due to a variety of hazards, robots are once again dispatched, forming another chain of remote control keypads managing robotic-arm-wielding robots. This time, many more robots are involved. In summary, there are the following keypads: One directional keypad that you are using. 25 directional keypads that robots are using. One numeric keypad (on a door) that a robot is using. The keypads form a chain, just like before: your directional keypad controls a robot which is typing on a directional keypad which controls a robot which is typing on a directional keypad... and so on, ending with the robot which is typing on the numeric keypad. The door codes are the same this time around; only the number of robots and directional keypads has changed. Find the fewest number of button presses you'll need to perform in order to cause the robot in front of the door to type each code. What is the sum of the complexities of the five codes on your list? ================================================ FILE: exm/aoc/2024/aoc_2024_22.adb ================================================ -- Solution to Advent of Code 2024, Day 22 ------------------------------------------- -- Monkey Market -- -- https://adventofcode.com/2024/day/22 -- Copy of questions in: aoc_2024_22_questions.txt -- -- HAC 0.40 "nice-to-have"'s detected in this exercise: -- -- * Modular types (esp. Unsigned_X and bitwise operators) -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_22 is use AoC_Toolbox, HAT, Interfaces; input_name : constant VString := +"aoc_2024_22_mini"; -- input_name : constant VString := +"aoc_2024_22"; r : array (Part_Type) of VString; subtype U64 is Integer_64; -- Hack for HAC. "Full Ada": type U64 is mod 2 ** 64; total : U64 := 0; subtype Diff_Range is Integer range -9 .. +9; type Price_for_Diffs is array (Diff_Range, Diff_Range, Diff_Range, Diff_Range) of Integer; total_first_price : Price_for_Diffs; procedure Generate_2000 (seed : U64) is x : U64 := seed; x10, x10_old, d0, d1, d2, d3 : Integer := 0; unseen : constant := -1; first_price : Price_for_Diffs; begin -- "Full Ada" does it in a single expression (see AoC_2024_22_Full_Ada). for a in Diff_Range loop for b in Diff_Range loop for c in Diff_Range loop for d in Diff_Range loop first_price (a, b, c, d) := unseen; end loop; end loop; end loop; end loop; for count in 1 .. 2000 loop -- NB: a "Full Ada" compiler has the `xor` operator of course. x := Sim_XOR (x, x * 64) mod 16777216; x := Sim_XOR (x, x / 32) mod 16777216; x := Sim_XOR (x, x * 2048) mod 16777216; x10_old := x10; x10 := Integer (x mod 10); d3 := d2; d2 := d1; d1 := d0; d0 := x10 - x10_old; if count > 4 and then first_price (d3, d2, d1, d0) = unseen then -- First occurrence of the price difference sequence d3, d2, d1, d0. -- We record the price for that sequence. first_price (d3, d2, d1, d0) := x10; end if; end loop; total := total + x; for a in Diff_Range loop for b in Diff_Range loop for c in Diff_Range loop for d in Diff_Range loop if first_price (a, b, c, d) /= unseen then total_first_price (a, b, c, d) := total_first_price (a, b, c, d) + first_price (a, b, c, d); end if; end loop; end loop; end loop; end loop; end Generate_2000; procedure Read_Data is i : Integer; f : File_Type; begin -- "Full Ada" does it in a single instruction. for a in Diff_Range loop for b in Diff_Range loop for c in Diff_Range loop for d in Diff_Range loop total_first_price (a, b, c, d) := 0; end loop; end loop; end loop; end loop; Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get (f, i); Generate_2000 (U64 (i)); end loop; Close (f); end Read_Data; procedure Do_Part_1 is begin r (part_1) := Trim_Left (+total'Image); end Do_Part_1; procedure Do_Part_2 is max_price : Integer := 0; p : Integer; begin -- "Full Ada 2012+" does the following in a single loop (for ... of). for a in Diff_Range loop for b in Diff_Range loop for c in Diff_Range loop for d in Diff_Range loop p := total_first_price (a, b, c, d); if p > max_price then max_price := p; end if; end loop; end loop; end loop; end loop; r (part_2) := Trim_Left (+max_price'Image); end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 16619522798 (mini 1: 37327623, mini 2: 37990510) -- Part 2: validated by AoC: 1854 (mini 2: 23) end if; end AoC_2024_22; ================================================ FILE: exm/aoc/2024/aoc_2024_22.txt ================================================ 4080909 2254738 8155901 7477951 16431099 5408639 5157077 6843017 7343391 2516192 12286948 6805409 3330250 10938366 14374017 10957655 168758 5016772 2875289 9954275 8573337 12925507 12561359 14243976 2884223 428102 3248277 860940 15841288 13887317 6901633 7623423 3284294 14627437 16250818 13250706 6157588 6419581 1357452 6810417 11905247 163700 7127512 13449599 2282345 5558515 14163958 2136577 6713087 10042179 9873822 6425428 13878989 3967264 11792741 15545765 16340909 956959 6561178 2718465 12238209 7445788 9852068 191993 3991138 5605377 6714142 1594412 936933 6242706 6318558 7668085 13409399 3949685 8789051 12664487 16300624 4197308 9822144 13052208 11233910 4598392 4786565 3568973 4955243 14152345 8138308 7110676 1601907 8881468 11011123 7849771 1747179 16722201 4131945 10264257 4447491 918586 5398680 6629665 5507085 4038232 12977280 13355820 7312882 6013577 7531615 7216104 1457831 7662244 14501470 7696532 7533897 3204827 3108760 1595310 12073783 6429038 4981285 14916035 7042772 14590737 4422416 11176998 3594679 8657371 10924514 14998838 4895148 9948114 5083618 13799758 16413359 5679393 12305338 15077436 3773683 6906383 11599823 2695871 10008897 14041931 7934436 3550081 5901912 1456614 1892687 13642949 12798887 14553261 8945970 8327474 4249469 10644421 3016151 7589921 16115949 5431198 15989333 10181155 10039007 2059840 15689810 11636392 10763850 16122788 6208936 16512293 14268500 3840143 6290763 3707040 5418480 9727184 10341561 13383930 8562892 3759880 6326721 4825118 2445499 2192227 15519815 14946053 6797403 3333274 4528417 5461290 6079366 14003569 687350 5247557 12852533 12791205 2718818 11598594 594069 8695211 1246324 15655825 4983230 2671139 3080133 5174342 11416810 14337025 6069327 4032953 3919672 1973901 15284264 3264844 1138906 2736706 12947242 13138318 10149432 2196573 2255991 6154617 3154633 13721704 10004644 6149978 1336702 5352627 5223212 11015649 11348575 12789180 8132497 1550554 8406854 12001508 4022109 3746041 4145696 4765058 8265183 13632577 4555951 13160073 7457882 8580276 5799086 15468368 12718282 10079829 10688092 12465616 1768014 7785918 8217254 10316998 16205732 11030315 13201628 11797149 8831456 7333953 9448804 12013514 5415671 7522972 1944330 11076183 6269017 4319203 5163674 9653758 6574379 2842344 4154343 1653194 2986309 5773917 11895808 15974291 15098232 14004649 12328227 5464084 15314432 8270187 6796821 14799142 2593119 10381468 13747934 12858628 14950215 5406309 3670064 10691033 8817761 12849470 11317453 16321239 5095465 13365075 772052 16404559 5935409 14348256 11467856 10054845 9143658 9618106 13420692 5900989 1252135 8860717 12386972 8457497 8961996 15975681 12761455 5509037 9357853 16664243 4778395 14227423 14836540 9500578 12374006 10688177 4869766 804988 14277010 5154562 3749977 10731533 12261658 15323564 14981871 16413511 3206448 8087647 8229212 14690677 6045444 10494167 10225571 6278749 8326437 5998088 10534608 9724509 746187 14822703 16675006 15180198 6647761 11309929 10032169 8350763 4796528 6776456 6857306 14956025 2518327 5022503 5164951 8122521 9126630 6118357 9019931 4769584 3915459 310053 12627001 9199164 1789342 15601133 9474259 16716320 399878 10657198 3819781 6277888 1986650 15906402 6290044 10984939 5004543 610320 4252287 11512028 7821751 8848813 8353347 5621188 10369557 6416557 10494119 2823816 6491192 8361278 9073630 4955571 1538388 1507310 12250664 10978188 13580607 2274235 16711406 14684756 15170574 11837675 225594 10583137 5665986 707333 10165409 13703484 3716994 12765273 8344120 12173575 3703841 16083252 9122650 7498986 2052761 7823750 16154467 1459655 5503475 1011515 2336661 16721138 6617687 4604645 5804244 813951 1388591 4067674 15303870 6258775 8411182 10743066 13226772 6920756 7020925 7810829 4695112 1863082 9198769 9093335 16699984 1275456 9921055 1315236 5197992 7586302 8702174 1180051 1049526 5580261 1419325 15718959 11984262 8693038 13764491 16010362 7658984 11111063 4649724 12243177 4463064 7438227 5275669 16657537 10507524 15920825 10776369 8610258 8379413 8235685 4395766 16197132 13386304 7960105 16562197 13818784 1389659 11094950 7432271 6026775 12173978 695652 1114582 9371570 8391587 4920524 6889487 250433 5376908 12009609 3218265 3545914 9446102 8269581 3328717 12859576 1939528 9371909 14877711 9681723 8421364 1590283 3987950 7557214 16311677 8220222 5968441 9311893 4612876 14058792 224573 10877727 7353617 7017219 8410486 6947525 3004481 5284450 16518021 8556009 9373407 2782987 14549238 15643010 10151834 14280944 12970839 369436 5379814 7422290 16136238 13471466 7552723 5977903 16021636 6532603 1295600 9696672 13015149 14770535 6356209 7477492 1325694 13227760 12766496 476423 2181417 6964726 262869 14431432 4466472 342559 3288180 562844 2636893 12209405 12834690 7092247 10536262 11330357 15134630 281415 12818406 12080487 16304734 16426477 1526028 2937550 13991543 4672740 1310750 3820827 12552482 4673845 8064264 16710512 4307154 11974285 15444907 7419792 15653555 4448540 356588 15103361 3141328 1298775 6539219 12076194 6921130 15631258 12140380 469796 14704655 2375240 12502063 5823308 15692990 2353070 6898528 7794274 11895387 15987674 13081627 7062913 12652237 310869 13348241 10374549 3855147 13677265 7480261 10724297 1754053 2709206 15552662 3902342 551651 4506551 14073388 8026314 15005477 6647900 10261539 5825040 8842339 14232509 3584248 4945522 15162448 7016568 11289850 4892627 10731217 11146589 1804918 16203750 12745848 2560912 1581089 4985555 15909673 190078 3390886 15961321 6867277 13582799 9182941 11281259 14740102 10251114 5158830 16483550 11302201 2357396 14426255 4441232 16659869 301924 15286665 6177053 14361958 1764857 13342482 7233468 10860917 9226526 5111902 6598587 7888186 13580668 2904507 1508480 12667074 6590196 10049092 6785402 8601242 15376974 14445187 16766239 11949301 13333528 6669543 16725763 16508317 735578 4567188 4041496 818538 7546263 8143579 2382632 10240511 2783893 16036539 10278939 11671236 6040433 439290 3293508 1825784 16553624 14337006 16615754 9156570 5062556 16377009 9873521 13331914 7543572 719728 10265648 232780 3004977 657294 4345284 11183795 6420021 5130693 12777063 7460902 336796 2802675 340272 7849862 9225840 1196796 148039 5738393 8866582 1074247 15784512 15864992 10915284 12531319 7083162 3711300 4734253 3055998 15850335 13718660 16594282 12489682 10051765 8306438 9823161 10545500 818115 8895941 14078628 5272561 11903472 9178329 2586097 6016066 5032383 9884299 4085367 1860845 8434389 11031722 5958919 1408753 16277658 11973479 4207393 16535260 1027078 8497595 13463292 3279892 4056725 12349107 2464554 10776371 15003195 6723700 8220436 7401706 10858845 14466369 2507180 16449468 6290502 8659761 6119573 8482815 12064893 9926787 9501045 14493140 5569412 16310275 12330564 12772404 3065617 4776450 2176507 9125383 11506364 11964129 3073608 6475277 12900185 3313474 6571723 8028060 15954099 12743482 16029650 10826891 2468959 8812787 14363491 9390908 11273610 11837312 3177815 12927618 16537430 14370689 5051156 9060162 7269168 14496899 379809 15059123 7528423 4555492 5439990 8020963 7150315 14703158 2882434 12942486 14417930 3262171 567667 5400748 7888730 4352719 16429434 9923370 1232298 2000965 13584508 5112982 816086 12020920 1557536 861858 13395370 1463281 351474 11997484 2880436 15829844 6666125 15578454 3143050 15972989 4396359 12316917 14720307 13877787 13566365 14694343 883283 7100573 10077945 7092405 11304359 1335541 10262616 12294948 7550181 13014648 11547605 12020378 8412587 9991268 14068033 12811535 14232949 8901720 3939751 4053511 13579742 15822703 7005666 7054630 7809348 968302 13995349 15566334 12359182 11122889 16027483 10692609 8793935 9813215 5720058 3530712 11188793 5435446 7297096 13002532 11477542 1212639 4207103 527198 6195799 11789482 13980093 766128 5639810 8735500 13293013 7548137 5763928 9586448 1009071 16204073 4954081 13902540 6875458 10604946 4712765 2304332 351892 14866757 5334463 2863592 2523615 14968099 5043136 7687264 14690688 8321283 13606301 7488288 11513550 6750428 3369065 12526654 14605717 10494204 7229326 10698227 1008434 5154207 878227 10898229 14754055 1522240 8012898 1244506 2884213 11086772 5262133 7398019 6537606 15299737 11851308 3431082 9860332 4053420 1811433 4657411 14336864 12683935 10380613 14070121 11038946 7383945 6072854 7828585 14993431 2910811 4625789 2784317 5347731 14801612 7143605 1109277 13269704 8110333 10274981 6551236 7027499 14823286 774282 15642652 2207263 9426781 6571291 8285059 6668366 15272361 13332557 15269352 3999034 3902648 2105481 14024883 7177015 6875895 13469611 7946489 3169830 5311612 15425661 3732001 545276 12750339 14552452 15968702 14140012 5249926 11521039 6697436 3924735 479888 6071129 4104587 5136205 7047336 14394163 13788402 232480 256915 13345115 6660499 10679585 4746191 15325685 15801593 11195562 12309615 8431604 12918346 8604297 1535670 13471546 2689689 4648870 12786153 11517265 12471111 11042258 14309742 13254717 3584213 446841 15891201 1040057 4685580 9473090 9473189 9220973 10476633 10381694 3132734 5537602 3731899 1316019 9564926 14728930 7785846 7048590 4188042 1093292 7042357 12466230 2179680 2746374 10788636 416529 10231367 14849254 6789270 15173899 2631055 7496621 13435010 8337045 16749223 7901218 11496600 6960584 6428145 3356479 10474167 4073613 15089395 9213153 7852488 15404007 13978841 12526878 7710432 11148081 11321554 422115 14277910 6982299 3556146 16164868 16545119 10515212 15493678 4866929 8876732 6491174 1160682 756332 11940237 8429909 13310172 777949 3259115 11602313 15668468 16031942 16193889 5088395 5880978 4184241 16025421 11839960 6136388 775837 5491623 1372521 15157850 5361524 6497219 12463089 10179995 14293080 3230474 2421699 2368530 7003761 11755630 2836219 4708735 14920893 10035127 4668490 766483 5462380 5826166 12868445 7185724 12602101 5227717 4294100 7410855 9681840 15670407 4275086 11097939 14590754 7567916 6619684 8153692 7223143 5833609 10383745 12583714 8595790 3239803 14209994 12464098 11961248 10520461 5583609 12723244 6798285 2295571 9781281 14529909 14838010 3392609 15578259 3299549 5846974 6335774 11729399 8031627 5971535 13283541 10565841 13559333 1652713 7956737 15657712 14757845 11651169 6588202 595445 12014782 1381259 14674812 10164010 7918375 9068768 9442457 13236977 2504841 14269527 12674880 4234283 2472056 11266755 6348163 8321343 13394380 11424835 8518966 9134522 15452288 6630237 5420857 7751405 284608 5717337 10875173 13228169 16743710 5251347 8002517 7883167 461622 458548 4863747 7215211 13408032 8004135 8851505 11421919 9646017 4695893 12858537 9950449 5183618 4386693 1111908 1909640 11376952 15614714 11128606 11007274 13591241 6822131 205517 758149 14047981 6601387 13370939 1908836 7614606 8376736 16404772 12900554 4207994 307488 9141486 14436258 6449373 7259500 13410958 14182846 7741297 16519339 4544446 4135097 3375744 9412837 6671155 13014256 14116071 13609953 6936300 9461159 4805833 15650656 14451017 13400410 11008276 7585689 6225102 1413178 1297167 5993486 8406811 15558659 16131327 4668925 289979 10313597 13760349 906385 3523840 15091529 11844996 3118034 7633456 14453267 6715522 7556324 13101763 1310113 2849431 10162853 6364024 10962417 12652321 14448149 4785011 10000665 12577048 12342278 1449606 357272 3445953 14641840 13290014 6145639 8175645 15647618 3054152 16060494 5853093 15336785 11362664 6305745 14492171 3147397 12591662 4374632 9557340 13408066 10146699 1497532 12157265 7549648 11320598 6807598 3560901 15787665 7435175 5644327 10780722 16231854 11471975 1986406 3620752 10830993 6626546 2315756 15676012 14296984 12610447 6955287 14333667 1195820 10215350 7316484 12298016 13136237 5184418 6454917 5000763 7917808 14299036 9077922 11964622 5825014 13552211 2187774 2087200 15140173 12261960 7177069 1654991 3648466 4976399 5722999 13305811 12175330 6320312 10455473 2226970 7593350 8295519 2950806 14140038 4982607 8331621 11829945 14935737 3460810 5320552 12492582 15659591 11629946 2835620 11067968 7048909 7043036 9183920 12285570 8555820 9961642 12161094 9667621 5179243 9672929 14185708 16089618 8278759 3318372 13175526 2980421 12802381 307486 4333594 13955155 11841112 12735109 6023924 10922685 11523727 2789158 11806867 11745152 16295994 6868595 12816611 3513949 12806769 15121579 4482910 435817 10403469 11302360 3112849 6720674 13489518 4665893 2399871 4099456 16698317 14598103 4069703 3117049 7542398 16619497 12716401 14568359 15397022 6798627 7453542 916128 2621934 9626616 11151263 2420690 6334976 179425 13866540 4129253 15480222 6380824 4520446 16365054 12314031 6323143 9785756 6316834 8862212 9631089 16144530 12544920 11664836 12207715 2700276 2507559 437969 13338706 9789472 6536400 10226740 10954990 12194236 939645 6283675 5623896 8799158 1413613 7536211 305320 12505823 1793588 8395859 12248207 9701718 10156336 10237923 13210641 11848662 10564243 9853182 1225930 14345338 13999946 16084195 7682308 3181906 2945663 11851640 9328339 14744745 10784245 16490661 15712527 11542640 5274572 13193643 12386214 7895523 10669507 11792465 3249657 13494500 1052258 12663303 6176099 11840530 12754339 849527 3768805 12360228 977256 4100011 14250008 15404620 12597289 12004540 12173305 4509710 7458647 9659143 6658336 5358097 13997109 2865227 8479735 14544629 11971370 15738206 352824 10480215 15086576 3900706 9396411 12972713 3477138 7425286 2602740 14748033 8841911 1473495 1640181 6866786 4189788 9156536 488650 4534559 15042557 12317935 10295085 14396181 2351088 13796311 11439957 12217757 11242167 14701672 422740 12183853 2893861 2808064 7639046 16147358 3630663 1044361 14425592 15074846 796986 11028426 10064355 4427850 9795479 5572259 14911074 11346907 13380418 3344388 1557385 9177414 12357194 3519437 11805348 14158744 5117896 6319196 12849950 259210 3138477 8861509 8391156 4578538 16682761 11887040 11071828 9845726 5340766 786827 15639371 13755824 4766323 5161051 13242934 10369841 2119492 15286995 11177382 7510469 6778322 1282949 11516899 1266827 13965788 892658 6334697 9503998 3442149 4869511 11898089 12021711 5836651 2813004 235447 16278888 6684845 13704079 7187810 13727765 15378973 12360704 8729670 14737220 5572929 9911721 8918921 16573390 12728996 9539787 9978752 13529025 4988533 16082462 3673587 868459 9281622 8045022 12596085 9070314 10000669 8237854 8384268 14980562 15546729 13635109 11592569 8111305 8201276 3986683 11886355 11616592 2555461 13114424 16602599 6019381 276192 1794789 4275002 13607751 16418952 5835388 1293539 5536082 8998156 16400254 13365776 6661715 14928827 5638804 13997344 5636399 8354407 5455384 4306676 10601003 2521941 11651791 9663230 10169233 7470852 11008265 3706782 4106219 6651646 4900756 8767483 1805647 16368659 15988964 2520208 278801 10120124 7685757 14694367 14497116 10294213 3206137 2074235 11277789 16170493 10933305 5379723 1611217 14646564 6798586 15397969 13929307 9405982 13542850 11688156 1535522 3449409 10606357 2160438 2864332 941669 12268830 2598032 1700301 5614702 8312180 803567 9809834 12572436 12441899 14564495 7264926 14831581 14826345 10564357 9940234 10619526 16707496 9390219 3897599 13739371 5153332 15881794 11921035 12697854 6977541 354413 11151418 4370152 6686891 6456248 5752989 10973462 14136620 5219680 6672463 15996832 1286332 8740348 2398036 14385013 4625344 12559362 9589298 5943411 2004485 10121921 10731134 12740038 993812 4226201 13098765 11158616 9230460 7880320 8706373 5103241 14724686 10670005 15355500 700278 2553190 2696535 11028748 15194295 374518 4099898 232159 893121 6584471 12643278 15331025 3328994 9666931 6128941 13312004 4332371 14102336 9528237 4867518 10816190 15946147 4121399 15390837 9415252 7140648 7395978 16300338 7464884 6931738 13768527 6630812 6047670 4551878 14573895 12360707 1959047 11807797 14664562 3018470 6239135 15167985 10304793 13017633 6601610 16622226 1116111 8993105 419776 5625505 9944159 5187945 1234572 14596106 1265763 2030543 257892 1820816 5128916 15727064 1948906 2818767 5474396 8837245 7879316 16420373 6138474 16281831 8136679 5499584 10155849 9369129 11567114 13498401 8130393 11224893 8569297 11232669 10231140 2476321 421694 3827367 15779759 11357047 8526328 6435623 10528254 8175055 14471538 10112097 10330094 13404241 11209996 3895249 8321133 13959950 2835942 16012857 11173883 7165906 14468840 3083301 8393053 13948360 15860507 854596 5592319 1106128 2005086 11132519 2433035 7070406 11367526 13160860 9995879 9987956 16261376 826271 8905790 12875583 4499613 520193 2905524 1357066 15581832 16714916 11991917 15158291 8442933 5958552 14766652 1222351 5634263 14437191 7482642 3586872 10331783 16078494 8618908 14266104 14681893 11647787 11294585 3023445 6676392 14470262 2037483 1359546 225377 12896633 11067409 8198397 1012099 11027177 1848439 12692353 16246366 7030277 10320785 11269264 9602190 13406193 11545887 14724376 3588295 11362298 11846655 5887807 12908006 15610866 13658126 4263425 3121782 325549 11166687 5782308 13783583 661426 6906599 11113138 5617959 ================================================ FILE: exm/aoc/2024/aoc_2024_22_full_ada.adb ================================================ -- Solution to Advent of Code 2024, Day 22 ------------------------------------------- -- Monkey Market -- -- https://adventofcode.com/2024/day/22 -- Copy of questions in: aoc_2024_22_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_22_Full_Ada is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2024_22"; r : array (Part_Type) of VString; type U64 is mod 2 ** 64; total : U64 := 0; subtype Diff_Range is Integer range -9 .. +9; type Price_for_Diffs is array (Diff_Range, Diff_Range, Diff_Range, Diff_Range) of Integer; total_first_price : Price_for_Diffs := (others => (others => (others => (others => 0)))); procedure Generate_2000 (seed : U64) is x : U64 := seed; x10, x10_old, d0, d1, d2, d3 : Integer := 0; unseen : constant := -1; first_price : Price_for_Diffs := (others => (others => (others => (others => unseen)))); begin for count in 1 .. 2000 loop x := (x xor (x * 64)) mod 16777216; x := (x xor (x / 32)) mod 16777216; x := (x xor (x * 2048)) mod 16777216; x10_old := x10; x10 := Integer (x mod 10); d3 := d2; d2 := d1; d1 := d0; d0 := x10 - x10_old; if count > 4 and then first_price (d3, d2, d1, d0) = unseen then -- First occurrence of the price difference sequence d3, d2, d1, d0. -- We record the price for that sequence. first_price (d3, d2, d1, d0) := x10; end if; end loop; total := total + x; for a in Diff_Range loop for b in Diff_Range loop for c in Diff_Range loop for d in Diff_Range loop if first_price (a, b, c, d) /= unseen then total_first_price (a, b, c, d) := total_first_price (a, b, c, d) + first_price (a, b, c, d); end if; end loop; end loop; end loop; end loop; end Generate_2000; procedure Read_Data is i : Integer; f : File_Type; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get (f, i); Generate_2000 (U64 (i)); end loop; Close (f); end Read_Data; procedure Do_Part_1 is begin r (part_1) := Trim_Left (+total'Image); end Do_Part_1; procedure Do_Part_2 is max_price : Integer := 0; begin -- Traverse the 4-dimensional array total_first_price: for total_price of total_first_price loop max_price := Integer'Max (max_price, total_price); end loop; r (part_2) := Trim_Left (+max_price'Image); end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 16619522798 (mini 1: 37327623, mini 2: 37990510) -- Part 2: validated by AoC: 1854 (mini 2: 23) end if; end AoC_2024_22_Full_Ada; ================================================ FILE: exm/aoc/2024/aoc_2024_22_mini.txt ================================================ 1 2 3 2024 ================================================ FILE: exm/aoc/2024/aoc_2024_22_questions.txt ================================================ --- Day 22: Monkey Market --- As you're all teleported deep into the jungle, a monkey steals The Historians' device! You'll need get it back while The Historians are looking for the Chief. The monkey that stole the device seems willing to trade it, but only in exchange for an absurd number of bananas. Your only option is to buy bananas on the Monkey Exchange Market. You aren't sure how the Monkey Exchange Market works, but one of The Historians senses trouble and comes over to help. Apparently, they've been studying these monkeys for a while and have deciphered their secrets. Today, the Market is full of monkeys buying good hiding spots. Fortunately, because of the time you recently spent in this jungle, you know lots of good hiding spots you can sell! If you sell enough hiding spots, you should be able to get enough bananas to buy the device back. On the Market, the buyers seem to use random prices, but their prices are actually only pseudorandom! If you know the secret of how they pick their prices, you can wait for the perfect time to sell. The part about secrets is literal, the Historian explains. Each buyer produces a pseudorandom sequence of secret numbers where each secret is derived from the previous. In particular, each buyer's secret number evolves into the next secret number in the sequence via the following process: Calculate the result of multiplying the secret number by 64. Then, mix this result into the secret number. Finally, prune the secret number. Calculate the result of dividing the secret number by 32. Round the result down to the nearest integer. Then, mix this result into the secret number. Finally, prune the secret number. Calculate the result of multiplying the secret number by 2048. Then, mix this result into the secret number. Finally, prune the secret number. Each step of the above process involves mixing and pruning: To mix a value into the secret number, calculate the bitwise XOR of the given value and the secret number. Then, the secret number becomes the result of that operation. (If the secret number is 42 and you were to mix 15 into the secret number, the secret number would become 37.) To prune the secret number, calculate the value of the secret number modulo 16777216. Then, the secret number becomes the result of that operation. (If the secret number is 100000000 and you were to prune the secret number, the secret number would become 16113920.) After this process completes, the buyer is left with the next secret number in the sequence. The buyer can repeat this process as many times as necessary to produce more secret numbers. So, if a buyer had a secret number of 123, that buyer's next ten secret numbers would be: 15887950 16495136 527345 704524 1553684 12683156 11100544 12249484 7753432 5908254 Each buyer uses their own secret number when choosing their price, so it's important to be able to predict the sequence of secret numbers for each buyer. Fortunately, the Historian's research has uncovered the initial secret number of each buyer (your puzzle input). For example: 1 10 100 2024 This list describes the initial secret number of four different secret-hiding-spot-buyers on the Monkey Exchange Market. If you can simulate secret numbers from each buyer, you'll be able to predict all of their future prices. In a single day, buyers each have time to generate 2000 new secret numbers. In this example, for each buyer, their initial secret number and the 2000th new secret number they would generate are: 1: 8685429 10: 4700978 100: 15273692 2024: 8667524 Adding up the 2000th new secret number for each buyer produces 37327623. For each buyer, simulate the creation of 2000 new secret numbers. What is the sum of the 2000th secret number generated by each buyer? --- Part Two --- Of course, the secret numbers aren't the prices each buyer is offering! That would be ridiculous. Instead, the prices the buyer offers are just the ones digit of each of their secret numbers. So, if a buyer starts with a secret number of 123, that buyer's first ten prices would be: 3 (from 123) 0 (from 15887950) 6 (from 16495136) 5 (etc.) 4 4 6 4 4 2 This price is the number of bananas that buyer is offering in exchange for your information about a new hiding spot. However, you still don't speak monkey, so you can't negotiate with the buyers directly. The Historian speaks a little, but not enough to negotiate; instead, he can ask another monkey to negotiate on your behalf. Unfortunately, the monkey only knows how to decide when to sell by looking at the changes in price. Specifically, the monkey will only look for a specific sequence of four consecutive changes in price, then immediately sell when it sees that sequence. So, if a buyer starts with a secret number of 123, that buyer's first ten secret numbers, prices, and the associated changes would be: 123: 3 15887950: 0 (-3) 16495136: 6 (6) 527345: 5 (-1) 704524: 4 (-1) 1553684: 4 (0) 12683156: 6 (2) 11100544: 4 (-2) 12249484: 4 (0) 7753432: 2 (-2) Note that the first price has no associated change because there was no previous price to compare it with. In this short example, within just these first few prices, the highest price will be 6, so it would be nice to give the monkey instructions that would make it sell at that time. The first 6 occurs after only two changes, so there's no way to instruct the monkey to sell then, but the second 6 occurs after the changes -1,-1,0,2. So, if you gave the monkey that sequence of changes, it would wait until the first time it sees that sequence and then immediately sell your hiding spot information at the current price, winning you 6 bananas. Each buyer only wants to buy one hiding spot, so after the hiding spot is sold, the monkey will move on to the next buyer. If the monkey never hears that sequence of price changes from a buyer, the monkey will never sell, and will instead just move on to the next buyer. Worse, you can only give the monkey a single sequence of four price changes to look for. You can't change the sequence between buyers. You're going to need as many bananas as possible, so you'll need to determine which sequence of four price changes will cause the monkey to get you the most bananas overall. Each buyer is going to generate 2000 secret numbers after their initial secret number, so, for each buyer, you'll have 2000 price changes in which your sequence can occur. Suppose the initial secret number of each buyer is: 1 2 3 2024 There are many sequences of four price changes you could tell the monkey, but for these four buyers, the sequence that will get you the most bananas is -2,1,-1,3. Using that sequence, the monkey will make the following sales: For the buyer with an initial secret number of 1, changes -2,1,-1,3 first occur when the price is 7. For the buyer with initial secret 2, changes -2,1,-1,3 first occur when the price is 7. For the buyer with initial secret 3, the change sequence -2,1,-1,3 does not occur in the first 2000 changes. For the buyer starting with 2024, changes -2,1,-1,3 first occur when the price is 9. So, by asking the monkey to sell the first time each buyer's prices go down 2, then up 1, then down 1, then up 3, you would get 23 (7 + 7 + 9) bananas! Figure out the best sequence to tell the monkey so that by looking for that same sequence of changes in every buyer's future prices, you get the most bananas in total. What is the most bananas you can get? ================================================ FILE: exm/aoc/2024/aoc_2024_23.adb ================================================ -- Solution to Advent of Code 2024, Day 23 ------------------------------------------- -- LAN Party -- -- https://adventofcode.com/2024/day/23 -- Copy of questions in: aoc_2024_23_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_23 is use AoC_Toolbox, HAT, Interfaces; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2024_23"; r : array (Part_Type) of VString; dic : Hash_Maps.Hash_Map_Type; subtype Id_Range is Integer range 1 .. 1000; subtype Computer_Name is String (1 .. 2); historian : array (Id_Range) of Boolean; connected : array (Id_Range, Id_Range) of Boolean; name_of : array (Id_Range) of Computer_Name; last : Id_Range; procedure Read_Data is use Hash_Maps; dummy_separator : Character; name : Computer_Name; f : File_Type; last_64, v1, v2 : Integer_64; procedure Register (val : out Integer_64) is dummy : Integer_64; unknown : constant := 0; begin Find (dic, +name, unknown, val); if val = unknown then last_64 := last_64 + 1; Insert (dic, +name, last_64, False, dummy); val := last_64; if name (1) = 't' then historian (Id_Range (last_64)) := True; end if; name_of (Id_Range (last_64)) := name; end if; end Register; begin for i in Id_Range loop historian (i) := False; for j in Id_Range loop connected (i, j) := False; end loop; end loop; Clear (dic); last_64 := 0; Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get (f, name); Register (v1); Get (f, dummy_separator); Get (f, name); Register (v2); connected (Id_Range (v1), Id_Range (v2)) := True; connected (Id_Range (v2), Id_Range (v1)) := True; end loop; Close (f); last := Id_Range (last_64); end Read_Data; verbosity_level : constant := 0; procedure Do_Part_1 is count_with_historian : Natural := 0; begin for i in 1 .. last loop for j in i + 1 .. last loop if connected (i, j) then if verbosity_level > 1 then Put_Line (+"Connected: " & name_of (i) & ',' & name_of (j)); end if; for k in j + 1 .. last loop -- "[...] each computer in the set is connected to the other two computers." if connected (j, k) and then connected (i, k) and then (historian (i) or else historian (j) or else historian (k)) then if verbosity_level > 0 then Put_Line (+"Historian in triplet: " & name_of (i) & ',' & name_of (j) & ',' & name_of (k)); end if; count_with_historian := count_with_historian + 1; end if; end loop; end if; end loop; end loop; r (part_1) := +"" & count_with_historian; end Do_Part_1; -- Sorting is copy-pasted-adapted from the BWT example for HAC. -- Note the Ada standard has a generic sorting in its library. type Table is array (Id_Range) of Computer_Name; procedure Shell_Sort (b : in out Table; n : Natural) is i, j, step : Integer; step_size : array (1 .. 4) of Integer; stop : Boolean; temp : Computer_Name; begin -- 'steps' contains decreasing increments for each -- pass. The last pass has increment 1. step_size (4) := 1; for pass in reverse 1 .. 3 loop step_size (pass) := 2 * step_size (pass + 1); end loop; Passes : for pass in 1 .. 4 loop step := step_size (pass); -- Do a straight insertion sort with 'step' as -- an increment instead of 1. i := step + 1; while i <= n loop temp := b (i); j := i; stop := False; while j > step and not stop loop j := j - step; if b (j) > temp then b (j + step) := b (j); else b (j + step) := temp; stop := True; end if; end loop; if not stop then b (1) := temp; end if; i := i + step; end loop; end loop Passes; end Shell_Sort; procedure Do_Part_2 is elem_set : array (Id_Range) of Natural; set_size, set_last, best, name_count : Natural; valid : Boolean; t : Table; type Pass_Type is (find_largest_set_size, pick_largest_set); begin best := 0; Passes : for pass in Pass_Type loop Main_Vertex_Loop : for i in 1 .. last loop if verbosity_level > 1 then Put (+"From " & name_of (i) & ": "); end if; -- Create a group around computer i: set_last := 1; elem_set (set_last) := i; -- We gather all computers connected to i: for j in 1 .. last loop if connected (i, j) then set_last := set_last + 1; elem_set (set_last) := j; if verbosity_level > 1 then Put (name_of (j) & ' '); end if; end if; end loop; if verbosity_level > 1 then New_Line; end if; -- Now we have *the* set of all computers connected to i. -- Check mutual connections in the set: set_size := set_last; Check_Connections : for elem_i in 1 .. set_last loop valid := True; for elem_j in elem_i + 1 .. set_last loop valid := valid and then connected (elem_set (elem_i), elem_set (elem_j)); if not valid then if verbosity_level > 1 then Put_Line (+" Eliminated: " & name_of (elem_set (elem_i)) & " not connected to " & name_of (elem_set (elem_j))); end if; exit; end if; end loop; if not valid then set_size := set_size - 1; elem_set (elem_i) := 0; -- Cancel the element (no packing) end if; end loop Check_Connections; -- Now we have *a* set of computers connected to i, where computers -- are directly connected to each others. -- Note that vertex i can belong to multiple such sets. if verbosity_level > 0 then Put (+"Set size: " & set_size & ": "); for elem_i in 1 .. set_last loop if elem_set (elem_i) > 0 then Put (name_of (elem_set (elem_i)) & ' '); end if; end loop; New_Line; end if; case pass is when find_largest_set_size => best := Max (best, set_size); when pick_largest_set => if set_size = best then -- We found a set with the maximum size (hope this is the expected one!): name_count := 0; for elem_i in 1 .. set_last loop if elem_set (elem_i) > 0 then name_count := name_count + 1; t (name_count) := name_of (elem_set (elem_i)); end if; end loop; Shell_Sort (t, name_count); r (part_2) := +""; for i in 1 .. name_count loop r (part_2) := r (part_2) & t (i); if i < name_count then r (part_2) := r (part_2) & ','; end if; end loop; exit Main_Vertex_Loop; end if; end case; end loop Main_Vertex_Loop; end loop Passes; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 1227 -- Part 2: validated by AoC: cl,df,ft,ir,iy,ny,qp,rb,sh,sl,sw,wm,wy end if; end AoC_2024_23; ================================================ FILE: exm/aoc/2024/aoc_2024_23.txt ================================================ jm-oz el-mn aa-jt ag-mt fg-bt tm-xh ag-si tx-mk ig-zj fd-tp sj-ln rp-zo np-mr qq-ny tf-ku fp-fo lp-pu ht-zn sf-pw ln-aw mt-tg ft-ny sw-rb fh-vq ec-xk fo-ko if-ka uv-bl mv-ph ua-vq yw-tj lb-pp yr-nv rm-km yf-ww tx-ij dz-oq wn-qv yw-ow ay-cp ps-hv ke-lj dq-xi na-pu ux-cn pb-vb th-pg va-ut em-mc mi-un jk-bg fc-bo ke-ei yf-fp ec-yc om-ip ss-gd lp-mk jj-sj ru-je fp-sd wg-gj dj-cm th-ue zf-cz wg-gb xv-ss uw-ms up-hc pp-sp my-bh mp-hj yy-ko dm-ru ax-ja up-vh dr-sp fg-fy wh-or bl-mb ic-wn ws-sg mm-nk dq-ti kv-yh cc-ev jg-vr ga-fj kp-jb me-nf ad-jd wy-qp fj-uz my-tw fu-zc xq-cx hs-wk ah-zv sn-kb ay-ch la-hr qj-jn ae-gt mb-eu mu-yg ei-fd rh-gp rd-ua vg-ou jd-on fo-ww ue-sb rz-so fa-cp wl-jo ko-ww si-nx rz-jf pb-zi gd-kc li-wo mw-xf mj-dv vl-rh rk-bp ew-in dn-xd ka-ip ws-jt eb-ho ez-ow wa-hw aa-vy cb-fq ll-xv lb-qs dz-zm fk-ss qs-xw yd-wo tk-zg kv-kn wg-ld nk-av ry-fm td-km bu-fa lo-mz xw-pp zj-ew he-nx bo-ya wv-oy yu-pd mj-na hc-qt mv-ej bp-yg wl-hc ya-fg kr-wn yt-ij xm-sp kn-yk uz-qj hv-uu nt-wq in-jx ge-up te-uv bs-ku gd-sa cj-xo yx-nd ds-pp ba-nu tg-xe fo-mg bn-bk fw-nj mh-jj vy-tp ua-ic az-il ee-yi rs-ju rw-wf qh-js so-dz es-xo ha-zv ya-wh ln-jj kq-nu ya-vk gz-bf bl-ra wz-jl fd-hj yb-pj fb-fv df-ir xm-qs rs-fq au-sh ah-oj ax-ds cb-wy zn-xx dv-tx bj-mb ph-uk id-yi sh-rb hi-yn yq-bp pu-tx qc-fh ho-zj lh-xx tk-js rj-we ml-we qx-yc ax-af pl-sg ur-ho pu-pi xw-ds io-te yi-tl ts-lt zn-fz sw-ft pr-uz mh-qw yn-bz wk-rw ve-ti ha-fc oh-ib lw-mw ys-pi tm-sa qb-yw du-sx jm-ha dw-mk qm-dn pm-wx wn-ip rc-jd jn-ql gl-us en-bn ub-ch oz-ha cq-dj kh-ty yx-xv pj-ww hz-zv xk-pm wn-bu zz-dz dz-jp yr-az na-yt nf-zx ln-vr lq-zz sg-ju mg-gv jh-bs wm-cl sm-wo fa-ub cp-ch qq-se lj-gl fw-wo nt-co ya-be pr-df va-ok ml-nz mb-yp rs-hf hz-eu vk-be wu-mi js-gi ib-jf fo-eb ln-nt cm-ns wn-za ad-ru lg-zi bd-vl em-mo qt-up kp-sm vg-gu fv-jh qh-zg ik-pu se-vk ss-im pj-zp fy-mx gl-ti ro-zn xt-en ku-jh fu-lc ai-sv kp-kq la-xq xh-oe vy-yc tx-mj uk-zo rc-zc ad-on rc-gv aa-sg zz-yr az-en zv-nz hx-az md-kd wg-fa ru-ms fv-jz ch-tr sg-cb ef-rd kv-xx th-fc cf-wb id-vw lq-bc nx-mt cv-ok ez-ip mn-nz ky-ht wi-tq xo-su id-tl qj-pr zr-mm uz-re oo-cx yy-yh th-kd xv-do ke-gl yr-il pz-jh zf-nu iq-pt vg-lg gq-jm on-dm hl-ao id-er ur-ew fj-tc xd-bu oo-ao pi-yt fx-bz no-uz ym-ea gx-qo li-zf uw-rc pw-yy vw-wu mg-eb xf-of fj-no rq-tp ur-in it-zt rd-bg sm-nj ki-te vv-kz cf-aw mv-rp ko-ar wc-yz of-rm sv-mn uy-oa tz-ax pm-mn oy-sq lq-if jz-hv jh-zg nl-ci bi-wn up-wc gu-xo ze-ky gq-jv yj-fv jp-so cz-jb ti-zb fa-iz uk-ej ae-hv oe-fk cq-oy om-bi ph-rg et-bc wz-st cj-zi mz-nl bn-ub ar-uj ku-yg fp-ko km-ux ag-mz ds-dr vr-cf bi-ow wv-dj wq-sj sn-rp wy-df ff-qy tr-ld vy-sv fm-gz hz-pe bt-yc eq-ne si-lk kt-hv ui-ka et-gb yr-hx gn-is lv-qt df-cl kn-vn nf-km ki-bl pt-ff xf-um td-yq zx-oa ti-ev jw-gh en-pa oz-jv kw-hj wz-cc ok-yy nn-kj cp-wg sl-qp wf-nn xu-ts rs-cb se-ya lb-ja ba-sm es-gr lp-ij hm-id cm-sq ut-yy xd-ay wv-aj bg-uy fl-vn hn-rj qy-ek ex-ww bi-tj lj-zt fy-wh vy-rq dj-gz kb-rp bh-tw lg-av ne-qo xi-st fc-mm ua-qa ch-et pz-ku ei-gl kn-ze st-ti ee-wt hc-xt lq-qe ec-hk cb-hf sw-cl xv-iz nv-pa vh-hc zm-gd ci-be yt-ys nf-gk ld-gb kz-lm xf-in sj-co zc-jd we-hz vj-gt kp-li go-nc no-lx lp-tx ns-wu wg-ef en-ce xq-rs lm-ab mh-xu mi-ac ch-xd ui-rh xp-er ko-yf om-kr qy-lr ea-va th-bo pg-au go-oh th-mm xk-yc rh-fh wi-je qy-kh io-md mr-wc bd-qc ci-or ys-pu ut-fe ho-ig yu-im wy-ir qe-ib vu-fi qz-vd mx-be fl-ht fq-ju yw-zh nx-nl wq-aw ss-pd ay-fa ce-pf jj-co px-la fx-yn vq-qc fw-li ml-jv md-eu ag-tg ki-eu jv-ah ns-vw ic-oa gk-qa ci-mx zz-qe yu-kc gs-oe fe-ct lk-xe hw-tw ir-qp xu-wa av-th oe-zm ll-ph fh-ui vv-vd wv-jr iq-lr hs-wf zk-pf bm-gh zg-gi og-bk su-zi pc-rs pa-yr iy-wy tk-gi zp-eb yz-xt wu-hm rs-ws km-yq cb-uz nu-wo ze-fz md-bl ms-cp ij-on zc-lc rd-gk vt-vu ir-sl tr-xd ra-ki ft-sl ni-xf rg-hd cl-zl ph-rp jg-wq fd-vp wl-np hb-zd ea-ct jx-ig wb-qw zy-ue et-ub ke-vp kh-hi bp-rm lw-ig dm-uw pt-hi kb-mv bi-za ur-jx wl-mr jg-jj hn-rs ve-xi tf-tk hv-fv vy-mn lo-yd st-cc ek-fx qb-ez tt-dz xl-ay yw-bi uz-ql qy-ty vd-rt vj-bh fz-ky ap-tk cp-xd mu-km it-pg ou-zi on-ms xu-cw gi-pz mv-sn jw-jn bn-pf ll-ww zj-lw jd-rz om-qe kt-ps hx-pf vr-ik la-iv ae-yj mn-qx jv-nz si-xe vm-ke hz-jv fw-hc tf-jh ss-zm ir-hj ec-sv sh-df ad-tm rq-xk lp-dw ej-zo ev-zb we-gq mj-mk eb-ww xv-go pc-ju iq-ty mm-zt fm-aj pm-rq td-gd ab-hs kz-rt va-yh pi-dv fm-cm kv-ze ua-gk ro-ze zd-xo qo-jg mb-uv ml-ha hx-og pj-fo ur-ni xf-zj sp-tz gb-fa qv-yw yu-ss ro-lh ha-pe qh-jh dz-jf ln-co um-ur ni-jy pb-su ne-ae oy-vx vy-qx vu-vq ba-li aj-sq kh-lr nf-ic ea-yy iy-hk xm-xw fj-jn qa-rd fc-nk mq-pr yd-ge yx-kj gs-xh iq-hy hz-ah mb-ra hi-rd ps-fb oe-ss iv-ao jz-yj ui-lu hl-bm tc-pr ve-ev dz-ib ne-ps pg-ue ge-nx ai-hk tj-zh wb-sj fu-dm lj-mp ec-rq vb-gu mc-se mw-ig id-ee rm-mu yp-eu xl-du ew-xf vr-wb ap-qh oj-nz of-wi vj-ze or-vk uj-la et-fa ou-su ct-va xq-sb eq-ae pm-sv dn-tf sx-zo va-hb jo-vh fo-ac oq-if qb-ow te-bl an-gn qh-gi mr-qt gp-vu ev-jl ii-kd sw-wm bg-me zz-ib oh-kj pe-gq wa-cr jf-tt ag-ft yh-ok om-ow xw-dr av-it su-eq kr-ez wa-vj cz-nj xx-fz nn-vv mh-jg vw-yi dq-ev yx-nc ht-yk lq-dz bo-it oa-qa hc-mr bs-tf kq-fw mi-tl fc-ue kw-ei ct-sf ke-fd ao-sb rd-zx my-ts bn-hx xo-zi rd-me wo-zf pt-gp gs-tm zl-lx qq-bt mx-qq wo-kq kw-lj ez-bi pc-cz ry-jr qp-wm sn-yu io-mb mu-am up-pk mo-vm du-ej bf-sq ue-zr fu-jd wq-mh ez-zh qt-jo qc-ka bm-sb ym-js hc-ke zn-zx kj-do df-ft es-qs be-or kq-zf wz-be re-it aj-cq na-ij eq-yj ds-ja lu-qc sg-jt nd-iz nu-jb pc-cb fz-ln cz-nu uw-zc xf-ho ml-jm zx-qa kc-xh ra-ai st-mf kt-yj fq-hn td-mu jr-sq sx-xl us-ds uv-bj vw-wt pi-dw gq-nz ew-jx ek-yn fe-cv np-pk zr-zt qj-jw dm-jd io-ra oh-yx ff-yn cw-bh ig-xf nv-hx ht-lh it-zr na-dw id-wt fd-mo qs-ja im-xh an-yx tj-qb er-yi gk-zx ag-xe qz-hs mq-gh an-rk kr-zh yx-is nv-bn vl-lu hw-xu ah-jm qo-uu lm-nn wh-fg fi-vq pr-ga yj-uu fi-fh qy-hi ps-eq gr-xo zb-xi og-nv qj-mq bf-wv ty-qe em-lj qq-be oo-la hd-ej we-nz ui-qm ki-uv rm-am rk-oh bo-zy hd-uk fy-hr mf-ti ek-ps wf-kz rk-yx mt-nl ff-ty mc-be st-dq pl-zt rp-sx lx-zb wh-be rm-td mg-ar bt-wh pf-en iv-hr kt-jz fi-vt on-uw hy-wk cf-qw wi-rm eu-uv wl-lv yk-vn vg-es ch-gb uu-ht pt-lr ne-uu fd-lj zk-az ua-me he-lo kc-sa gv-uw je-dm pe-ah bl-eu oa-rd sh-wy ce-zk an-iz ou-cj vb-zd nn-kz xk-tp ns-ee vu-ui ce-il bl-bj zg-il qb-za tk-dn jg-cf vm-mb bi-yk lm-wk sp-ik he-io er-wt kw-mp vg-pi ge-lo zf-jb pl-aa pr-jn yb-mg qp-df wz-dq sl-iy vd-ab sa-ys zh-ow sx-sn fq-sg dr-af lt-wa hs-vv pf-og du-lm lg-su kw-us px-io sg-rj kt-gx wt-un ze-yk ge-mz id-wu sj-jg et-cp iv-cx sf-ym np-jo um-jx ys-ac zv-jv tc-uz tq-rm vd-uw fj-tf th-zt au-fc aw-wb px-bm zo-du px-hl hk-xk il-en xm-af ek-kh ac-pu zb-cc iy-cl hd-sx az-pa fi-gp nu-mm rj-mp pp-lh rw-ab ii-mb ba-jl jn-re ad-dm pu-mj ax-xm zt-bo nl-lk ft-ir sd-yb cv-ym zd-lg mo-ke go-an zr-fc nz-jm ip-bi uu-fb oh-nd wx-bm fb-dr yc-pm nc-nd tm-pd bk-nv qc-vl nl-lo oj-ml jr-cm jn-ga lv-mr np-up cc-ve gj-cp mj-ij es-gu qh-id gb-xd cv-pw ei-vp hr-hl fq-hf wi-am mq-fj sd-mg yb-ll ky-bd ko-pj hz-oj rc-lc sh-ny uy-zk lq-ib do-oh ea-ok nc-gn ol-rt ja-an yn-iq pg-mm en-nv wa-tw zg-bs vv-rt zk-en jj-wq je-uw wn-qb ux-wi sp-ds vp-kw km-yg ny-ir qz-jk rh-ka pd-lw of-td kj-an za-zh pt-kh ux-rm zz-oq vk-bt zg-pz oz-dm bn-pa jf-oq gs-fk pw-fe rt-qz wf-lm ek-pt iv-uj cm-vx wg-xd et-ay gk-zb iy-sw ha-jv yz-jo lj-us zc-ru hl-uj kz-ez xw-tz bk-hx vd-wk ym-fe gx-fb un-tl wl-tc tm-fk lb-sp tq-yg hs-kz vr-sj wh-qq wq-cf vw-tl pp-af kt-uu fx-ty sj-se ci-qq bg-zx xh-zm so-jf wu-fe we-jv je-jd sq-ry bj-md io-kd kt-qo fy-ya er-fl hw-bh wu-er wq-wb fv-ps ni-fm gd-tm lo-mo rj-rs yh-ym mx-bt im-tm ik-ds jf-jp mk-ac og-bn ga-no id-ns ss-tm ds-qs cc-zl ns-yi ab-wk ef-jk uk-jp st-zl qc-gp un-xp gl-vm ku-tk jt-hn fc-pg tx-yt mo-lj ge-tg vh-np ur-jy aa-ju um-jy rw-vd zn-ze bm-cx ny-iy af-tz mj-ea jn-tc sg-lv ze-ht oy-sp xh-yu pe-jn st-jl tq-am oh-gn fc-av kd-ra ip-ow sd-ll ei-lj cw-cr sd-ww cl-rb wh-vk lg-vb tg-nx ad-rc vb-cj lw-xf ci-fg yr-zk ww-mg or-fg dw-pu mg-yf nt-wb az-nv rh-vu sw-qp is-iz pc-fq ll-ar au-mm ic-zx zh-ip fz-ht ja-xw hn-cb rb-ny tm-oe dv-lp kr-qv wq-vr qv-ow sd-eb bu-ch og-vu dn-hi yw-va pm-qx zk-bk bt-mc tr-bu xw-ik yn-lr yb-fp jy-in kc-im qq-ju md-ii fi-mr pr-re sa-fk jt-pc kd-ki su-gr wz-ti ff-bz mf-dq bh-gt lw-ew ts-vj mq-jw dv-ij sw-sl dn-gi oy-aj fg-vk se-or vg-pb iy-wm zz-jf ae-kt ag-nl np-xt uy-zx rp-uk kv-zn ft-rb un-wu fm-bf qm-js pj-wv xv-kj gu-zi an-oh zy-fc af-ad ec-tc du-hd ej-rp lq-tt wy-ft zb-ve ar-fo pc-rj wo-ba gu-gr vg-gr jx-jy fk-bf kz-wk ge-si kc-pd nf-bg dw-ys ip-qv kb-hd oq-qe rb-wy qk-vp rg-mv fj-gh ex-ts eq-qo zi-vb yn-ty rq-hk wa-bh mf-zl yp-uv cx-uj ga-gh vn-iq cr-ex mw-ew aw-vr pe-zv zf-nj ha-nz ki-mb xm-ds ej-ph ln-qw du-kb ra-md ee-hm ff-hy wu-wt rb-qp lm-ol aa-rj co-mh zg-ap oa-ef jo-up cl-ir nc-mw ka-vu pg-av nd-do hz-gq gr-zi ai-tp zv-ml il-pf ww-yb iz-rk lk-mz ph-du kt-ne jk-oa fv-gx ah-ml dv-mk ml-gq rw-hs mr-pk qv-bi rt-wk gz-cm wv-vx qz-ol sn-zo ja-ik my-tz ct-hb bc-ic sq-ut lg-xo cf-ln dm-ms oz-nz jb-nj aw-qw lb-ax jt-rs px-wx fq-aa ym-ct oq-bc px-ao af-xw xh-fk yt-pu ua-ef fh-ch va-cv ft-wm ag-he wm-sh bz-iq we-oj zk-pa mf-lx wt-ns lt-cw rq-sv qj-gh za-ip si-yd ce-bk gs-lt yd-ag et-wg hs-lm ts-gt bl-vh tw-lp cp-gb ky-zn lv-xt re-fj wc-jo sl-cl hl-la qs-ax yf-zp jy-ho ic-bg zt-fc vm-ei gr-ou gt-hw so-ig tx-dw na-zo ac-mj qm-tf co-jg jz-gx zl-jl ve-jl mz-si mm-bo gx-uu vm-fd hw-lt ad-je tg-lk fu-ad jo-hc rd-jk zx-me qj-fj vm-us ut-hb rd-ic hf-aa xp-id bs-gi xm-tz xd-fa yd-lk np-lv bu-yn oz-pe wl-qt wn-ez nd-rp cj-su vl-fi hz-ml rw-nn mw-ni rt-ab cm-oy dm-lc uk-mv gp-ui oj-zv bf-oy yj-qo ya-mx ke-hj fk-zm ti-cc st-ve ou-lg mr-up iq-hi xv-an md-mb ut-ok cq-sq wc-pk oj-ha rc-ru fm-cq md-ki um-in ea-ut uy-me yg-ux ee-gx xp-yi em-gl hb-pw tq-of aw-sj xu-lt lb-xw xh-gd yz-wl ke-us na-pi zp-mg lt-my nc-is jy-cr bd-vt bi-zh fb-jz eb-yf hw-ry fe-sf kc-tm yd-nl ok-pw rb-iy ty-hy lx-jl qx-ec hf-sg el-yc yp-bj uj-sb do-an lk-lo uu-fv az-pf eb-ar mn-ec lx-dq gp-vt li-nj ro-ht rz-oq ac-tx rj-ws wc-wl vt-vq bn-il mw-zj zt-au qz-vv qy-pt lp-mj rh-lu hc-yz gj-fa jt-pl cr-tw sl-wy tq-td ax-yf xo-vg cr-my js-ap xd-ub ay-ld lb-af bg-yx ei-us yt-mk of-ux qz-lm ll-fp tf-zg ar-yf hb-fe hk-el go-do gv-ad va-fe nx-ag me-ef lv-jo su-vg js-ku ms-lc gl-fd em-vm ir-sh hv-eq wx-cx zh-qv nx-lo wu-ee nt-jj ll-fo bo-nk ij-ew ut-ct kc-pw hk-tp hw-cr ve-wz ce-yr du-rg hf-pl fk-yu li-kq cl-qp qp-iy fj-jw yp-ii vm-kw pl-fq iv-sb ju-rj js-zg or-qq ra-eu ge-ag vh-pk tg-yd xt-mr qa-ic mg-ll or-fy vj-cr sp-ja nf-uy bt-ya ki-yp jw-pr qp-ft wv-fm jv-oj xi-lx yw-om kj-gn na-dv it-ue bm-ao zi-im hd-rp oh-is mu-wi vr-jj ej-kb zh-wn ua-jk vw-un ax-dr vq-ka hm-un ba-kq pe-we bp-km wh-se ww-ar il-nv pr-ql fp-eb gn-vp up-wl wn-ow qm-jh kz-ol se-be pm-hk et-wf vn-fz ht-kn an-nd vd-ol oo-bm qb-qv qh-tk pk-qt km-tq bg-gk ym-yy zc-ms au-it vd-wf zp-ww ky-fl fb-kt ct-jt ny-cl mb-te tj-wn ef-gk nv-ce qe-jp og-zk yq-mu aj-gz xv-gn ga-tc pz-dn ga-uz qt-np fy-mc gn-do gt-cr ko-zp xp-hm rh-fi zy-av uy-qa ut-sf el-vy um-ew vq-bd ka-bd qv-pf sh-ft zt-nk qm-qh tq-yq pb-ou rk-kj yj-ry gp-wb av-bo pt-bz el-xk th-au sh-cl bf-dj yj-ps ph-sx il-hx sh-sw kv-fz vy-hk hs-qj gd-yu hv-yj gb-rm xi-av of-am sv-sm pc-hf mx-mc xq-hl zc-on lv-wc ws-aa ve-zl gv-fu ga-mq za-qv or-mx pi-mk ru-fu vp-hj tw-xu ue-bo kn-fz sn-hd hn-ws qb-zh of-cn zm-gs yr-og ol-rw ay-wg fy-qq ub-wg sx-kh cb-pl he-lk td-cn av-ue lr-hi nj-kp bd-rh zb-st fb-yj is-go ha-we lb-tz xl-uk vk-mx jf-ab mo-gl pm-el we-ah pa-pf uu-eq ki-cq vv-hx ko-mg vl-ui bj-ki dq-zl tz-qs uy-gk sv-el sf-va aj-dj hi-hy mx-ga yx-iz lv-vh sm-jb yf-yb ra-ii zj-bk gb-bu zy-mm qb-om sb-px wk-eb tt-zz yu-zm tk-pz ik-dr oq-so jb-qk rm-yq yx-gn dq-cc us-em te-bj bs-ap rw-kz jl-mf kp-cx vu-bd er-ns wo-jb wz-mf bj-kd gi-qm sm-nu sf-ea pg-zy kz-qz js-jh qe-if zf-sm gd-pd qb-cf rz-dz ss-gs ib-rz is-kj io-ii qc-ui bi-kr uj-xq ae-jz xp-vw ue-au jp-ib ay-ub em-ei az-bn oo-xq yr-pf zv-jm vy-ai ge-nl cv-ct sv-tp tr-fa li-sm pd-xh ym-ut qa-jk lc-jd oj-np yz-zr oq-lq ns-hm yn-kh oe-yu pr-fj rc-ms fg-be ni-um hc-pk be-fy vk-mc eq-fb vr-co pg-zt lh-fz ky-kv qa-ef yk-lh lq-jf zd-gr xu-gt mt-gh qp-ny ln-jg kh-ff yg-rm sp-xw wx-iv bh-ts tr-ro uv-md xq-wx su-gu oz-gq ay-tr wv-sq cj-zd yw-ip nn-rt px-hr jx-kb hy-pt kp-zf md-wz vk-fy am-km ry-dj gd-gs gk-oa ru-gv ej-sn jx-mw wc-qt zk-tq nu-qk ff-lr sb-wx ut-pw mg-fp lc-uw qx-rq an-nc ph-sn yg-cn wm-ny zb-mf uk-rg ts-tw pd-gs oe-sa hk-yc kh-iq vl-vu lt-cr zo-kb ja-af ho-ni jm-jv te-kp nc-xv ai-xk aj-jr ql-fj fv-ae dn-jh vu-qc cq-cm iq-ff hc-wc bc-tt ut-cv qp-wc gq-vm il-bk th-zy ub-gb bz-qy uk-du za-tj yh-ct ao-fx vn-ze rc-bh hw-ts wm-xq ds-tz og-il qw-vr ky-vn xi-cc ws-fq wz-zl oz-im fh-gp mp-ke nf-jk wc-vh hy-qy co-cf uv-ra xp-me mz-yd ub-ld fu-rc uz-gh gp-vl ax-sp fw-nu sa-zm hr-bm pk-lv ok-ym yp-kd hb-sf fi-lu ue-nk gq-ha ex-bh pk-jo qt-bm sx-rg pl-hn ua-nf cj-es ql-nj rb-wm ej-sx zz-rz mn-ai jw-tc ni-jx kz-vd cz-sm ao-wx fu-on em-hj yr-en pl-ju th-zr sq-vx zn-fl vx-dj ba-zf et-tr gp-vq lr-bz of-km kr-pz qe-dz aa-cb vn-lh el-tp no-pr um-ig ei-oo ci-ya ue-zt jk-ic ln-wb co-wq sd-pj tq-cn zp-ar fo-yf jv-pe sa-pd lr-ek co-aw bc-jf xv-nd my-xu cc-jl bg-qa md-yp rb-ir qv-ez xl-rg vr-mh vp-us tc-mq wc-np pp-tz im-fk iz-nc pw-yh ga-ql lu-vu zy-nk qo-fb uv-sl ab-ol vh-qt ml-wh ek-ff hf-jt qy-yn qw-sj ce-az fx-iq zr-nk lc-gv go-iz dj-sq ba-qk bd-fi pw-ea li-cz mw-ho vv-lm ts-cr kw-fd tt-qe gj-ub sd-gr gj-ay ms-pa jb-kq cj-pb vp-gl sf-yh ho-ew wm-sl ql-qj ho-jx oq-tt lg-gu qh-ku fl-ro ys-mj jn-gh lg-gr ah-la tl-ns cz-kq zk-bn qx-zj tp-qx dw-ij eb-yb sj-nt js-dn vt-qc hd-zo xq-hr zp-fo kr-qb cc-lx pp-ik lq-rz yz-up ae-ps fl-yk ld-tl he-yc ch-ld sn-mz hx-ce fc-it oh-nc qk-zf pb-gu he-tg fq-jt zl-zb vx-fm rk-gu cl-ft ml-oz my-wa re-ql pj-fp jj-yt qk-wo yz-vh pb-es oe-gd mt-ge xh-sa za-om mb-kd ax-xw er-tl bz-hx sh-sl wx-hr my-vj bc-jp fh-vl so-if gt-cw ux-cj ae-gx ol-xh jj-aw xm-ja pi-ij fg-se ib-bc nx-xe hj-vm xp-tj jw-yp hl-sb qp-sh sx-mv ex-hw ty-pt ap-rw ad-zc pa-og om-zh kc-ss ze-lh gi-jh mp-mo wg-bu ui-fi em-mp hm-vw hn-pc ea-hv uy-ic zb-jl tz-dr ou-es ge-lk xm-lb sa-im zc-je nj-nu vm-mp gx-ps ds-lb bm-la ow-tj bc-rz vj-cw jp-if ha-hz zn-yk uv-kd bc-zz lu-vq ex-cw td-am na-tx it-nk tf-gi cz-qk av-au tr-cp qs-ik hl-cx wt-mi un-er ti-zl tl-wt cv-yh me-oa yr-bn ap-jh gj-ld lw-in kn-fq ys-dv dr-ja rk-do sx-uk tr-gj rg-kb am-yp rt-hs ik-lb cn-bp wt-yi ur-mw df-sw ee-xp yg-yb og-az me-jk on-gv up-xt tp-yc fy-bt ka-fi ph-kb jd-ms jk-zx dq-hz ky-ro yn-pt yy-sf ou-zd rp-rg wx-uj jb-fw tg-si fe-ea oq-ib bj-ra ur-lw px-cx wy-cl je-ms jr-oy rg-ej iq-ek xk-vy jl-xi yp-te cq-bf jd-gv fo-yb ff-fx pu-dv vn-kv om-tj om-wn xi-ti ec-pm sm-fw rq-el ch-gj mt-lk gj-gb tt-rz nx-lk ni-ew wm-ir rs-pl aw-mh mx-fg jg-qw ko-yb jt-rj zm-pd un-wq vb-su oq-yq mg-pj pw-ct ar-yb ol-vv rk-go zi-zd kh-fx ao-xq ps-qo hk-qx na-mk zb-wz uj-ao tw-gt ns-mi mh-oa vy-ec mu-bp bd-gp yf-pj yg-yq vg-zd ts-sf qs-af rc-je pa-ce uw-ru wz-ev xf-jx ab-wf rk-gn gz-cq fa-ch of-ty vx-ry ax-pp iv-nx yi-hm ps-uu fl-lh qe-jf fh-ka df-wm fv-qo ev-lx vw-er tl-ee vk-wo sg-rs hb-cv cp-bu pk-yz si-mk zm-tm us-fd lq-jp uj-px cc-mf ro-xx vl-vq km-wi ny-wy zr-au fp-zp em-fd na-ac ro-vn js-tf ne-hv go-yx ub-cp ir-sw fm-dj cr-bh ow-kr bf-cm ce-og jr-bf pp-ja kh-bz qb-bi xt-vh ve-lx fg-np do-tx no-mq ci-fy rq-mn zo-rg tz-ja is-rk vj-xu ka-vt lp-na ti-lx si-he nk-pg ik-xm du-mv tg-mf rg-me gv-je aj-ry dv-gz no-tc qo-jz pr-gh hf-bj yt-dw ii-eu fg-mc hl-st cz-wo jv-xe do-yx ik-ax hd-mv df-iy pw-ym nz-hz us-mp wb-co st-ev xx-fl ky-yk wl-pk cx-ao zg-qm rd-nf is-do wg-ch qj-ga oz-ah im-pd xt-wc kr-za pu-mk sv-qx aw-nt pg-el gq-zv cn-mu wf-wk qm-pz zv-oz bs-tk dj-oy sp-qs lw-ni yt-lp ok-hb ns-xp bu-ld wf-qz ez-za zr-zy ew-jy fi-qc lg-es vb-gr kn-xx vh-wl qy-iq ht-xx za-ow ee-un ju-jt xh-ss wa-gt ra-yp wv-cq il-zk df-ny fu-ms bz-ek oj-pe ti-jl ab-kz jz-eq cf-sj ty-bz fb-hv lu-ka wg-tr sj-gi pa-bk qa-nf mu-of iv-xq dn-ku bt-or pa-il vl-hw jw-uz qy-qw zx-ef jt-cb ho-in lr-fx kb-xl si-mt gv-zc om-ez ze-xx mi-yi lj-vp nd-rk sd-ar lg-pb ct-yy qw-nt ne-jz xt-qt jn-no ua-oa bj-eu tk-jh ai-yc ky-kn cj-vg in-tz ef-nf gq-oj la-ao ej-xl bs-qh dn-zg sv-xk ah-gq ae-qo ro-fz yq-wi jx-lw dn-bs rw-qz mm-ue ju-ws wv-gz ko-sd um-xo jj-wb rt-rw xm-dr ll-zp ux-mu kw-mq sf-cv rz-jp wl-xt ru-lc ba-cz pg-bo sl-ny wh-ci gz-vx cb-ju bp-ux uv-ii mk-ys gv-ms ez-tj kp-ba vd-nn wu-tl xm-oe vq-ui ig-ur tw-ex mr-jo pi-ac qc-hm yc-mn va-ym jm-oj in-ni nd-is nv-zk ww-fp ic-ef qc-rh jn-uz dr-pp ii-ki rh-vt tl-vj fw-kp qv-tj ac-dv zf-fw hv-qo td-bp rg-sn io-ki ph-zo vp-em ad-uw rh-wv zd-su hn-sg bn-ce um-lw oe-pd my-cw lx-st vw-xw am-yq ex-my mq-ql gb-tr of-bp af-ik wk-qz lv-yz hy-yn ay-bu he-nl eb-pj nu-li hx-pa no-ql ky-lh az-xx md-te ju-hn ha-ah hf-hn pc-pl ko-eb uk-ru hz-jm oq-jp ig-in kw-ke ds-af xv-oh ae-fb ld-fa ij-mk im-zm xt-pk vt-lu sw-ny aj-bf bo-zr re-no zp-kt rb-zv ai-qx cn-am ex-gt et-ld ct-ok fv-ne tf-pz vj-tw sd-yf hr-ao ys-ij qm-bs cn-rm zj-jy mq-re or-ya zr-av ut-yh vk-qq zb-dq on-je ro-yk js-bs so-bc tg-nl gv-dm cp-ld xk-qx te-ii qs-dr ry-bf so-tt pz-qh gh-re hk-sv bh-xu kd-eu tt-jp pp-xm yz-mr gn-iz zp-yb lq-so gs-kc rs-aa dm-zc no-qj ne-yj zj-um ru-on mn-hk wf-rt yh-hb az-bk el-ec so-ib rw-vv ok-fe ci-bt ws-ev kn-aj wh-mc rb-df ry-cq cf-jj er-mi ex-wa nk-ne et-xd hl-oo do-iz it-th cx-la un-ns ku-gi kh-hy sx-kb zo-xl ow-xi ol-wf uu-jz ws-pc um-mw wy-wm gp-lu qt-yz gu-ou td-ux vv-wf vk-ci yr-bk ux-am fm-jr vw-mi ev-zl ya-qq ll-pj yd-mt lo-tg jp-zz ec-tp mq-uz im-gs hr-uj ir-iy jr-cq gh-ql zn-lh sn-du jb-yi ku-zg xu-ex mv-ce jj-qw rq-yc vt-ui sp-af pt-fx cj-vx go-kj nc-rk pz-js bj-ii jr-gz bp-wi hr-oo rp-du mr-vh kr-ip ol-nn lm-rt gl-hj un-yi pe-jm vb-xo iv-bm gi-ap nc-kj hl-iv we-zv hr-sb oj-oz zy-zt my-hw xd-gj fu-uw xp-wu if-rz fq-rj ne-gx iv-px qa-bs qm-ku uj-bm hy-bz qz-nn bu-ub ur-fu xd-ld hw-cw cj-lg mx-se au-zy ic-gk mi-id tg-mz va-yy or-ii sh-iy wi-yg yp-bl yw-kr gx-yj lu-bd kp-qk tw-lt jw-no fp-ar yu-sa ph-hd hi-bz tx-pi ll-ko sd-zp lh-kn yd-zy ty-lr uw-jd sq-fm lo-mt gk-jk tm-yu ol-hs gz-oy gb-ay aa-pc cm-aj iz-kj hs-nn qm-tk ai-rq ee-er we-oz kq-jm iy-ft if-zz ag-lo xl-sn fl-kn wo-nj cz-fw bd-ui za-ff ac-dw wi-cn jb-ba wq-qw mh-cf ib-if uu-ae gt-lt oe-kc mc-ya kv-lh ts-wa in-ol pi-lp ai-pm xx-ky co-dj vx-bf nv-pf sw-li uy-jk ys-na lc-on ze-fl gx-hv uv-io pb-zd xu-cr jr-vx es-vb zi-es ig-jy yy-fe em-kw ju-hf jf-if eq-kt hy-ek lw-ho lt-bh lc-is mo-us ro-kn bl-kd np-yz fu-je yt-ac if-bc yt-mj fw-qk nu-kp xx-vn se-ci mc-or mi-hm nd-go jy-xf sq-gz an-is ok-sf nk-au hi-ek ec-ai ab-qz nt-vr ou-vb kt-fv lo-si wt-lr oo-uj jy-mw ig-ni uk-kb ph-xl no-gh jo-xt mn-tp nc-do we-jm he-mz dq-jl lc-ad nt-ok nz-pe cv-ea ga-jw gu-zd jr-dj re-qj vx-cq kc-fk uy-rd fz-fl hj-ei cn-ej hx-en wx-oo pb-gr ux-tq he-xe pj-ar el-qx cf-nt tq-mu gk-me on-rc aa-hn ab-vv sm-qk zl-xi bk-pf nz-ah dm-rc td-wi pu-ij us-hj xi-ev ts-cw vu-fh pl-ws hc-lv xl-rp sg-pc fy-se vp-mo fd-mp vj-lt qv-om oy-ry jo-cc bc-dz pb-xo mo-kw hd-gr im-oe ht-kv dw-jz hd-xl zx-ua bd-fh ez-yw sa-ss hj-mo ml-pe mz-nx mq-jn ur-zj ry-cm hi-ff gn-go fk-pd hy-fx tl-hm av-mm lk-ag wa-mc lm-rw cz-kp xq-px ys-tx yg-td er-hm kv-yk ys-lp ex-lt dv-yt zc-vb bp-tq hi-fx va-pw jw-ql ga-re fz-yk mj-pi wk-vv vn-ht ef-bg tt-tk lo-xe mf-ve kv-ro wy-sw sb-cx ho-um lj-hj ux-yq gd-fk fo-sd ve-rq rz-qe zy-it mf-ev zj-jx te-eu ql-tc bu-gj ii-bl ws-cb sv-pk qh-zn se-bt ac-lp ek-ty me-qa kq-sm gx-eq tw-cw qh-tf cw-wa tf-ap xe-mt ap-pz gj-et zr-pg wu-yi qy-fx he-ge yd-nx ln-wq bl-io sl-rb vn-zn pl-rj nt-mh ru-jd nd-gn vl-ka yw-za lk-hn xe-mz xk-lq ou-xo vb-vg qb-ip tt-if oh-iz yd-xe ke-em ry-gz qj-tc he-mt lm-vd yq-of bs-pz mh-ln ne-fb xe-ge vy-pm nk-th zi-vg kr-tj nl-si mp-vp cx-hr ym-hb id-un jr-zh so-zz it-mm yg-am xk-mn dw-dv rh-vq mt-mz fl-kv vl-vt lc-je aw-jg fg-qq so-qe mj-dw mv-zo la-wx sb-la es-su bg-ua ew-ig qm-ap qs-pp yw-eq cv-yy lw-jy mh-wb ba-fw nj-qk rt-mu au-bo rj-hf hl-wx mi-xp te-ra mv-xl co-qw jz-ps ba-nj re-tc xe-nl jg-nt zf-gj mf-xi qk-li ex-vj fp-gd vd-hs uy-ua gu-cj xf-ur bp-am yy-hb lx-wz dq-ve vm-lj iv-oo re-jw mp-gl hy-lr yk-xx zm-kc pb-cw ef-uy mp-ei ap-ku bk-en cn-km fh-lu in-mw cv-vt pm-tp hf-ws te-kd gl-kw lb-dr fh-vt ub-tr xp-wt cn-yq vx-aj fe-yh my-gt yu-gs wh-mx mc-ci nf-oa ni-zj yh-ea ap-dn jb-li zd-es tt-ib hm-wt aw-ou nd-kj ei-mo dz-if ll-yf xv-is ee-mi nn-ab nj-kq wb-jg oo-sb qk-kq fm-oy nn-wk og-en bt-be df-sl eu-io bg-oa lv-up ai-el bj-io vw-ee lb-hb oo-px go-nv cm-wv fv-lu gs-sa tj-ip ================================================ FILE: exm/aoc/2024/aoc_2024_23_questions.txt ================================================ --- Day 23: LAN Party --- As The Historians wander around a secure area at Easter Bunny HQ, you come across posters for a LAN party scheduled for today! Maybe you can find it; you connect to a nearby datalink port and download a map of the local network (your puzzle input). The network map provides a list of every connection between two computers. For example: kh-tc qp-kh de-cg ka-co yn-aq qp-ub cg-tb vc-aq tb-ka wh-tc yn-cg kh-ub ta-co de-co tc-td tb-wq wh-td ta-ka td-qp aq-cg wq-ub ub-vc de-ta wq-aq wq-vc wh-yn ka-de kh-ta co-tc wh-qp tb-vc td-yn Each line of text in the network map represents a single connection; the line kh-tc represents a connection between the computer named kh and the computer named tc. Connections aren't directional; tc-kh would mean exactly the same thing. LAN parties typically involve multiplayer games, so maybe you can locate it by finding groups of connected computers. Start by looking for sets of three computers where each computer in the set is connected to the other two computers. In this example, there are 12 such sets of three inter-connected computers: aq,cg,yn aq,vc,wq co,de,ka co,de,ta co,ka,ta de,ka,ta kh,qp,ub qp,td,wh tb,vc,wq tc,td,wh td,wh,yn ub,vc,wq If the Chief Historian is here, and he's at the LAN party, it would be best to know that right away. You're pretty sure his computer's name starts with t, so consider only sets of three computers where at least one computer's name starts with t. That narrows the list down to 7 sets of three inter-connected computers: co,de,ta co,ka,ta de,ka,ta qp,td,wh tb,vc,wq tc,td,wh td,wh,yn Find all the sets of three inter-connected computers. How many contain at least one computer with a name that starts with t? --- Part Two --- There are still way too many results to go through them all. You'll have to find the LAN party another way and go there yourself. Since it doesn't seem like any employees are around, you figure they must all be at the LAN party. If that's true, the LAN party will be the largest set of computers that are all connected to each other. That is, for each computer at the LAN party, that computer will have a connection to every other computer at the LAN party. In the above example, the largest set of computers that are all connected to each other is made up of co, de, ka, and ta. Each computer in this set has a connection to every other computer in the set: ka-co ta-co de-co ta-ka de-ta ka-de The LAN party posters say that the password to get into the LAN party is the name of every computer at the LAN party, sorted alphabetically, then joined together with commas. (The people running the LAN party are clearly a bunch of nerds.) In this example, the password would be co,de,ka,ta. What is the password to get into the LAN party? ================================================ FILE: exm/aoc/2024/aoc_2024_24.adb ================================================ -- Solution to Advent of Code 2024, Day 24 ------------------------------------------- -- Crossed Wires -- -- https://adventofcode.com/2024/day/24 -- Copy of questions in: aoc_2024_24_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; with Interfaces; procedure AoC_2024_24 is use AoC_Toolbox, HAT, Interfaces; r : array (Part_Type) of VString; procedure Do_Part_1 is -- Example: -- -- x00: constant Boolean := true; -- x01: constant Boolean := false; -- x02: constant Boolean := true; -- x03: constant Boolean := true; -- x04: constant Boolean := false; -- y00: constant Boolean := true; -- y01: constant Boolean := true; -- y02: constant Boolean := true; -- y03: constant Boolean := true; -- y04: constant Boolean := true; -- -- djm : constant Boolean := y00 and y03; -- ffh : constant Boolean := x03 xor y03; -- fgs : constant Boolean := y04 or y02; -- kjc : constant Boolean := x04 and y00; -- nrd : constant Boolean := y03 or x01; -- ntg : constant Boolean := x00 xor y04; -- pbm : constant Boolean := y01 and x02; -- psh : constant Boolean := y03 or y00; -- tnw : constant Boolean := y02 or x01; -- vdt : constant Boolean := x03 or x00; -- fst : constant Boolean := x00 or x03; -- -- bfw : constant Boolean := vdt or tnw; -- bqk : constant Boolean := ffh or nrd; -- frj : constant Boolean := tnw or fst; -- gnj : constant Boolean := tnw or pbm; -- hwm : constant Boolean := nrd and vdt; -- kpj : constant Boolean := pbm or djm; -- kwq : constant Boolean := ntg or kjc; -- mjb : constant Boolean := ntg xor fgs; -- qhw : constant Boolean := djm or pbm; -- rvg : constant Boolean := kjc and fst; -- tgd : constant Boolean := psh xor fgs; -- wpb : constant Boolean := nrd xor fgs; -- -- z00 : constant Boolean := bfw xor mjb; -- z01 : constant Boolean := tgd xor rvg; -- z02 : constant Boolean := gnj and wpb; -- z03 : constant Boolean := hwm and bqk; -- z04 : constant Boolean := frj xor qhw; -- z05 : constant Boolean := kwq or kpj; -- z06 : constant Boolean := bfw or bqk; -- z07 : constant Boolean := bqk or frj; -- z08 : constant Boolean := bqk or frj; -- z09 : constant Boolean := qhw xor tgd; -- z10 : constant Boolean := bfw and frj; -- z11 : constant Boolean := gnj and tgd; -- z12 : constant Boolean := tgd xor rvg; ------ x00 : constant Boolean := True; x01 : constant Boolean := True; x02 : constant Boolean := False; x03 : constant Boolean := False; x04 : constant Boolean := False; x05 : constant Boolean := True; x06 : constant Boolean := False; x07 : constant Boolean := True; x08 : constant Boolean := True; x09 : constant Boolean := False; x10 : constant Boolean := True; x11 : constant Boolean := False; x12 : constant Boolean := False; x13 : constant Boolean := True; x14 : constant Boolean := False; x15 : constant Boolean := True; x16 : constant Boolean := False; x17 : constant Boolean := True; x18 : constant Boolean := True; x19 : constant Boolean := True; x20 : constant Boolean := True; x21 : constant Boolean := False; x22 : constant Boolean := False; x23 : constant Boolean := True; x24 : constant Boolean := True; x25 : constant Boolean := False; x26 : constant Boolean := False; x27 : constant Boolean := True; x28 : constant Boolean := True; x29 : constant Boolean := True; x30 : constant Boolean := True; x31 : constant Boolean := False; x32 : constant Boolean := False; x33 : constant Boolean := True; x34 : constant Boolean := False; x35 : constant Boolean := True; x36 : constant Boolean := False; x37 : constant Boolean := True; x38 : constant Boolean := False; x39 : constant Boolean := False; x40 : constant Boolean := True; x41 : constant Boolean := True; x42 : constant Boolean := False; x43 : constant Boolean := True; x44 : constant Boolean := True; y00 : constant Boolean := True; y01 : constant Boolean := False; y02 : constant Boolean := True; y03 : constant Boolean := True; y04 : constant Boolean := False; y05 : constant Boolean := False; y06 : constant Boolean := True; y07 : constant Boolean := True; y08 : constant Boolean := False; y09 : constant Boolean := True; y10 : constant Boolean := True; y11 : constant Boolean := True; y12 : constant Boolean := True; y13 : constant Boolean := True; y14 : constant Boolean := False; y15 : constant Boolean := True; y16 : constant Boolean := True; y17 : constant Boolean := False; y18 : constant Boolean := True; y19 : constant Boolean := False; y20 : constant Boolean := False; y21 : constant Boolean := True; y22 : constant Boolean := True; y23 : constant Boolean := True; y24 : constant Boolean := True; y25 : constant Boolean := False; y26 : constant Boolean := True; y27 : constant Boolean := False; y28 : constant Boolean := False; y29 : constant Boolean := True; y30 : constant Boolean := True; y31 : constant Boolean := True; y32 : constant Boolean := True; y33 : constant Boolean := True; y34 : constant Boolean := False; y35 : constant Boolean := True; y36 : constant Boolean := False; y37 : constant Boolean := True; y38 : constant Boolean := True; y39 : constant Boolean := False; y40 : constant Boolean := False; y41 : constant Boolean := False; y42 : constant Boolean := False; y43 : constant Boolean := True; y44 : constant Boolean := True; cvk : constant Boolean := y44 and x44; qjp : constant Boolean := y42 and x42; kfp : constant Boolean := y41 and x41; qhf : constant Boolean := y40 and x40; nbc : constant Boolean := y37 and x37; prn : constant Boolean := y35 xor x35; qph : constant Boolean := y35 and x35; rkq : constant Boolean := y34 and x34; pmg : constant Boolean := y33 xor x33; wrd : constant Boolean := y32 xor x32; tkw : constant Boolean := y31 xor x31; gpp : constant Boolean := y31 and x31; rvc : constant Boolean := y30 and x30; qgc : constant Boolean := y30 xor x30; qrw : constant Boolean := y27 xor x27; fjr : constant Boolean := y27 and x27; jkt : constant Boolean := y26 xor x26; dbt : constant Boolean := y25 and x25; kdn : constant Boolean := y24 xor x24; nrw : constant Boolean := y23 and x23; sbs : constant Boolean := y21 xor x21; vwh : constant Boolean := y20 and x20; gpq : constant Boolean := y18 and x18; jbp : constant Boolean := y18 xor x18; fhn : constant Boolean := y16 and x16; vch : constant Boolean := y15 and x15; pvj : constant Boolean := y15 xor x15; tfh : constant Boolean := y14 xor x14; wbw : constant Boolean := y13 and x13; wgb : constant Boolean := y13 xor x13; bcw : constant Boolean := y10 and x10; qpg : constant Boolean := y08 and x08; vjc : constant Boolean := y07 and x07; gjv : constant Boolean := y07 xor x07; knd : constant Boolean := y06 and x06; sfn : constant Boolean := y05 xor x05; dtn : constant Boolean := y04 and x04; ptv : constant Boolean := y04 xor x04; rtt : constant Boolean := y03 and x03; qpd : constant Boolean := y02 xor x02; tng : constant Boolean := y02 and x02; jrb : constant Boolean := x44 xor y44; bmf : constant Boolean := x43 and y43; nsb : constant Boolean := x43 xor y43; sbn : constant Boolean := x42 xor y42; krk : constant Boolean := x41 xor y41; qwt : constant Boolean := x40 xor y40; ksf : constant Boolean := x39 xor y39; z39 : constant Boolean := x39 and y39; spg : constant Boolean := x38 xor y38; crp : constant Boolean := x38 and y38; vjg : constant Boolean := x37 xor y37; pfc : constant Boolean := x36 and y36; dkj : constant Boolean := x36 xor y36; bgg : constant Boolean := x34 xor y34; hbn : constant Boolean := x33 and y33; ttt : constant Boolean := x32 and y32; bqn : constant Boolean := x29 and y29; wtw : constant Boolean := x29 xor y29; shp : constant Boolean := x28 and y28; rtb : constant Boolean := x28 xor y28; jck : constant Boolean := x26 and y26; nfm : constant Boolean := x25 xor y25; frv : constant Boolean := x24 and y24; gcj : constant Boolean := x23 xor y23; qgd : constant Boolean := x22 xor y22; dpg : constant Boolean := x22 and y22; knb : constant Boolean := x21 and y21; vdc : constant Boolean := x20 xor y20; mcv : constant Boolean := x19 xor y19; hhb : constant Boolean := x19 and y19; tdb : constant Boolean := x17 xor y17; fpk : constant Boolean := x17 and y17; vgb : constant Boolean := x16 xor y16; ktg : constant Boolean := x14 and y14; htr : constant Boolean := x12 xor y12; njd : constant Boolean := x12 and y12; cbm : constant Boolean := x11 and y11; ksb : constant Boolean := x11 xor y11; cvv : constant Boolean := x10 xor y10; mnm : constant Boolean := x09 xor y09; ptc : constant Boolean := x09 and y09; jhr : constant Boolean := x08 xor y08; hsn : constant Boolean := x06 xor y06; fkt : constant Boolean := x05 and y05; npk : constant Boolean := x03 xor y03; sqk : constant Boolean := x01 xor y01; hnj : constant Boolean := x01 and y01; z00 : constant Boolean := x00 xor y00; jcq : constant Boolean := x00 and y00; bmc : constant Boolean := sqk and jcq; kpf : constant Boolean := hnj or bmc; pwk : constant Boolean := kpf and qpd; tpv : constant Boolean := tng or pwk; hrr : constant Boolean := tpv and npk; bdk : constant Boolean := hrr or rtt; nnq : constant Boolean := ptv and bdk; svk : constant Boolean := dtn or nnq; wnq : constant Boolean := sfn and svk; cjh : constant Boolean := fkt or wnq; hds : constant Boolean := cjh and hsn; wcs : constant Boolean := knd or hds; nbb : constant Boolean := gjv and wcs; bwm : constant Boolean := nbb or vjc; tvw : constant Boolean := bwm and jhr; gqb : constant Boolean := tvw or qpg; gwh : constant Boolean := mnm xor gqb; pgn : constant Boolean := gwh and cvv; jbk : constant Boolean := bcw or pgn; hgb : constant Boolean := ksb and jbk; jgf : constant Boolean := cbm or hgb; dmc : constant Boolean := jgf and htr; qwr : constant Boolean := dmc or njd; dqm : constant Boolean := wbw and qwr; nkd : constant Boolean := dqm or wgb; jrd : constant Boolean := tfh and nkd; bgh : constant Boolean := jrd or ktg; vcd : constant Boolean := bgh and pvj; nhh : constant Boolean := vcd or vch; btr : constant Boolean := vgb and nhh; ctv : constant Boolean := btr or fhn; ffh : constant Boolean := tdb and ctv; wtc : constant Boolean := fpk or ffh; pfh : constant Boolean := jbp and wtc; ppf : constant Boolean := pfh or gpq; gvt : constant Boolean := ppf and mcv; tjc : constant Boolean := gvt or hhb; vvc : constant Boolean := vdc and tjc; kgk : constant Boolean := vwh or vvc; rcb : constant Boolean := kgk xor sbs; tvj : constant Boolean := rcb or knb; vsb : constant Boolean := qgd and tvj; grk : constant Boolean := dpg or vsb; cdw : constant Boolean := gcj and grk; pbv : constant Boolean := nrw or cdw; mhd : constant Boolean := kdn and pbv; vsw : constant Boolean := frv or mhd; dfq : constant Boolean := nfm and vsw; kgs : constant Boolean := dfq or dbt; wtd : constant Boolean := kgs and jkt; mjf : constant Boolean := jck or wtd; jgh : constant Boolean := mjf and qrw; whc : constant Boolean := fjr or jgh; jsf : constant Boolean := rtb and whc; vmj : constant Boolean := jsf or shp; nbw : constant Boolean := vmj and wtw; bqb : constant Boolean := nbw or bqn; nth : constant Boolean := qgc and bqb; mwg : constant Boolean := nth or rvc; vmq : constant Boolean := tkw and mwg; mrg : constant Boolean := gpp or vmq; vcm : constant Boolean := mrg and wrd; rnc : constant Boolean := vcm or ttt; dmp : constant Boolean := pmg and rnc; kvw : constant Boolean := hbn or dmp; gwm : constant Boolean := kvw and bgg; bhd : constant Boolean := rkq or gwm; drv : constant Boolean := prn and bhd; dmj : constant Boolean := drv or qph; vnw : constant Boolean := dmj and dkj; jgc : constant Boolean := pfc or vnw; mqh : constant Boolean := vjg and jgc; bwb : constant Boolean := nbc or mqh; wjg : constant Boolean := spg and bwb; wjf : constant Boolean := crp or wjg; hvf : constant Boolean := ksf and wjf; jct : constant Boolean := wjf xor ksf; nhk : constant Boolean := jct or hvf; qwh : constant Boolean := nhk and qwt; sgk : constant Boolean := qhf or qwh; qvv : constant Boolean := sgk and krk; pwt : constant Boolean := kfp or qvv; qwg : constant Boolean := sbn and pwt; gdt : constant Boolean := qwg or qjp; dnc : constant Boolean := nsb and gdt; dsk : constant Boolean := gqb and mnm; tdh : constant Boolean := dnc or bmf; pjg : constant Boolean := jrb and tdh; z01 : constant Boolean := jcq xor sqk; z02 : constant Boolean := kpf xor qpd; z03 : constant Boolean := tpv xor npk; z04 : constant Boolean := ptv xor bdk; z05 : constant Boolean := svk xor sfn; z06 : constant Boolean := cjh xor hsn; z07 : constant Boolean := wcs xor gjv; z08 : constant Boolean := bwm xor jhr; z09 : constant Boolean := dsk or ptc; z10 : constant Boolean := cvv xor gwh; z11 : constant Boolean := ksb xor jbk; z12 : constant Boolean := htr xor jgf; z13 : constant Boolean := qwr xor wbw; z14 : constant Boolean := nkd xor tfh; z15 : constant Boolean := bgh xor pvj; z16 : constant Boolean := nhh xor vgb; z17 : constant Boolean := ctv xor tdb; z18 : constant Boolean := wtc xor jbp; z19 : constant Boolean := mcv xor ppf; z20 : constant Boolean := vdc xor tjc; z21 : constant Boolean := kgk and sbs; z22 : constant Boolean := qgd xor tvj; z23 : constant Boolean := grk xor gcj; z24 : constant Boolean := kdn xor pbv; z25 : constant Boolean := nfm xor vsw; z26 : constant Boolean := jkt xor kgs; z27 : constant Boolean := qrw xor mjf; z28 : constant Boolean := rtb xor whc; z29 : constant Boolean := wtw xor vmj; z30 : constant Boolean := bqb xor qgc; z31 : constant Boolean := mwg xor tkw; z32 : constant Boolean := mrg xor wrd; z33 : constant Boolean := pmg xor rnc; z34 : constant Boolean := bgg xor kvw; z35 : constant Boolean := bhd xor prn; z36 : constant Boolean := dkj xor dmj; z37 : constant Boolean := vjg xor jgc; z38 : constant Boolean := spg xor bwb; z40 : constant Boolean := qwt xor nhk; z41 : constant Boolean := sgk xor krk; z42 : constant Boolean := pwt xor sbn; z43 : constant Boolean := gdt xor nsb; z44 : constant Boolean := tdh xor jrb; z45 : constant Boolean := pjg or cvk; z : constant Integer_64 := Boolean'Pos (z00) * 2 ** 0 + Boolean'Pos (z01) * 2 ** 1 + Boolean'Pos (z02) * 2 ** 2 + Boolean'Pos (z03) * 2 ** 3 + Boolean'Pos (z04) * 2 ** 4 + Boolean'Pos (z05) * 2 ** 5 + Boolean'Pos (z06) * 2 ** 6 + Boolean'Pos (z07) * 2 ** 7 + Boolean'Pos (z08) * 2 ** 8 + Boolean'Pos (z09) * 2 ** 9 + Boolean'Pos (z10) * 2 ** 10 + Boolean'Pos (z11) * 2 ** 11 + Boolean'Pos (z12) * 2 ** 12 + Boolean'Pos (z13) * 2 ** 13 + Boolean'Pos (z14) * 2 ** 14 + Boolean'Pos (z15) * 2 ** 15 + Boolean'Pos (z16) * 2 ** 16 + Boolean'Pos (z17) * 2 ** 17 + Boolean'Pos (z18) * 2 ** 18 + Boolean'Pos (z19) * 2 ** 19 + Boolean'Pos (z20) * 2 ** 20 + Boolean'Pos (z21) * 2 ** 21 + Boolean'Pos (z22) * 2 ** 22 + Boolean'Pos (z23) * 2 ** 23 + Boolean'Pos (z24) * 2 ** 24 + Boolean'Pos (z25) * 2 ** 25 + Boolean'Pos (z26) * 2 ** 26 + Boolean'Pos (z27) * 2 ** 27 + Boolean'Pos (z28) * 2 ** 28 + Boolean'Pos (z29) * 2 ** 29 + Boolean'Pos (z30) * 2 ** 30 + Boolean'Pos (z31) * 2 ** 31 + Boolean'Pos (z32) * 2 ** 32 + Boolean'Pos (z33) * 2 ** 33 + Boolean'Pos (z34) * 2 ** 34 + Boolean'Pos (z35) * 2 ** 35 + Boolean'Pos (z36) * 2 ** 36 + Boolean'Pos (z37) * 2 ** 37 + Boolean'Pos (z38) * 2 ** 38 + Boolean'Pos (z39) * 2 ** 39 + Boolean'Pos (z40) * 2 ** 40 + Boolean'Pos (z41) * 2 ** 41 + Boolean'Pos (z42) * 2 ** 42 + Boolean'Pos (z43) * 2 ** 43 + Boolean'Pos (z44) * 2 ** 44 + Boolean'Pos (z45) * 2 ** 45; begin r (part_1) := Trim_Left (+z'Image); end Do_Part_1; procedure Do_Part_2 is function Add (x, y : Integer_64) return Integer_64 is x00 : constant Boolean := Boolean'Val ((x / (2 ** 0)) mod 2); x01 : constant Boolean := Boolean'Val ((x / (2 ** 1)) mod 2); x02 : constant Boolean := Boolean'Val ((x / (2 ** 2)) mod 2); x03 : constant Boolean := Boolean'Val ((x / (2 ** 3)) mod 2); x04 : constant Boolean := Boolean'Val ((x / (2 ** 4)) mod 2); x05 : constant Boolean := Boolean'Val ((x / (2 ** 5)) mod 2); x06 : constant Boolean := Boolean'Val ((x / (2 ** 6)) mod 2); x07 : constant Boolean := Boolean'Val ((x / (2 ** 7)) mod 2); x08 : constant Boolean := Boolean'Val ((x / (2 ** 8)) mod 2); x09 : constant Boolean := Boolean'Val ((x / (2 ** 9)) mod 2); x10 : constant Boolean := Boolean'Val ((x / (2 ** 10)) mod 2); x11 : constant Boolean := Boolean'Val ((x / (2 ** 11)) mod 2); x12 : constant Boolean := Boolean'Val ((x / (2 ** 12)) mod 2); x13 : constant Boolean := Boolean'Val ((x / (2 ** 13)) mod 2); x14 : constant Boolean := Boolean'Val ((x / (2 ** 14)) mod 2); x15 : constant Boolean := Boolean'Val ((x / (2 ** 15)) mod 2); x16 : constant Boolean := Boolean'Val ((x / (2 ** 16)) mod 2); x17 : constant Boolean := Boolean'Val ((x / (2 ** 17)) mod 2); x18 : constant Boolean := Boolean'Val ((x / (2 ** 18)) mod 2); x19 : constant Boolean := Boolean'Val ((x / (2 ** 19)) mod 2); x20 : constant Boolean := Boolean'Val ((x / (2 ** 20)) mod 2); x21 : constant Boolean := Boolean'Val ((x / (2 ** 21)) mod 2); x22 : constant Boolean := Boolean'Val ((x / (2 ** 22)) mod 2); x23 : constant Boolean := Boolean'Val ((x / (2 ** 23)) mod 2); x24 : constant Boolean := Boolean'Val ((x / (2 ** 24)) mod 2); x25 : constant Boolean := Boolean'Val ((x / (2 ** 25)) mod 2); x26 : constant Boolean := Boolean'Val ((x / (2 ** 26)) mod 2); x27 : constant Boolean := Boolean'Val ((x / (2 ** 27)) mod 2); x28 : constant Boolean := Boolean'Val ((x / (2 ** 28)) mod 2); x29 : constant Boolean := Boolean'Val ((x / (2 ** 29)) mod 2); x30 : constant Boolean := Boolean'Val ((x / (2 ** 30)) mod 2); x31 : constant Boolean := Boolean'Val ((x / (2 ** 31)) mod 2); x32 : constant Boolean := Boolean'Val ((x / (2 ** 32)) mod 2); x33 : constant Boolean := Boolean'Val ((x / (2 ** 33)) mod 2); x34 : constant Boolean := Boolean'Val ((x / (2 ** 34)) mod 2); x35 : constant Boolean := Boolean'Val ((x / (2 ** 35)) mod 2); x36 : constant Boolean := Boolean'Val ((x / (2 ** 36)) mod 2); x37 : constant Boolean := Boolean'Val ((x / (2 ** 37)) mod 2); x38 : constant Boolean := Boolean'Val ((x / (2 ** 38)) mod 2); x39 : constant Boolean := Boolean'Val ((x / (2 ** 39)) mod 2); x40 : constant Boolean := Boolean'Val ((x / (2 ** 40)) mod 2); x41 : constant Boolean := Boolean'Val ((x / (2 ** 41)) mod 2); x42 : constant Boolean := Boolean'Val ((x / (2 ** 42)) mod 2); x43 : constant Boolean := Boolean'Val ((x / (2 ** 43)) mod 2); x44 : constant Boolean := Boolean'Val ((x / (2 ** 44)) mod 2); y00 : constant Boolean := Boolean'Val ((y / (2 ** 0)) mod 2); y01 : constant Boolean := Boolean'Val ((y / (2 ** 1)) mod 2); y02 : constant Boolean := Boolean'Val ((y / (2 ** 2)) mod 2); y03 : constant Boolean := Boolean'Val ((y / (2 ** 3)) mod 2); y04 : constant Boolean := Boolean'Val ((y / (2 ** 4)) mod 2); y05 : constant Boolean := Boolean'Val ((y / (2 ** 5)) mod 2); y06 : constant Boolean := Boolean'Val ((y / (2 ** 6)) mod 2); y07 : constant Boolean := Boolean'Val ((y / (2 ** 7)) mod 2); y08 : constant Boolean := Boolean'Val ((y / (2 ** 8)) mod 2); y09 : constant Boolean := Boolean'Val ((y / (2 ** 9)) mod 2); y10 : constant Boolean := Boolean'Val ((y / (2 ** 10)) mod 2); y11 : constant Boolean := Boolean'Val ((y / (2 ** 11)) mod 2); y12 : constant Boolean := Boolean'Val ((y / (2 ** 12)) mod 2); y13 : constant Boolean := Boolean'Val ((y / (2 ** 13)) mod 2); y14 : constant Boolean := Boolean'Val ((y / (2 ** 14)) mod 2); y15 : constant Boolean := Boolean'Val ((y / (2 ** 15)) mod 2); y16 : constant Boolean := Boolean'Val ((y / (2 ** 16)) mod 2); y17 : constant Boolean := Boolean'Val ((y / (2 ** 17)) mod 2); y18 : constant Boolean := Boolean'Val ((y / (2 ** 18)) mod 2); y19 : constant Boolean := Boolean'Val ((y / (2 ** 19)) mod 2); y20 : constant Boolean := Boolean'Val ((y / (2 ** 20)) mod 2); y21 : constant Boolean := Boolean'Val ((y / (2 ** 21)) mod 2); y22 : constant Boolean := Boolean'Val ((y / (2 ** 22)) mod 2); y23 : constant Boolean := Boolean'Val ((y / (2 ** 23)) mod 2); y24 : constant Boolean := Boolean'Val ((y / (2 ** 24)) mod 2); y25 : constant Boolean := Boolean'Val ((y / (2 ** 25)) mod 2); y26 : constant Boolean := Boolean'Val ((y / (2 ** 26)) mod 2); y27 : constant Boolean := Boolean'Val ((y / (2 ** 27)) mod 2); y28 : constant Boolean := Boolean'Val ((y / (2 ** 28)) mod 2); y29 : constant Boolean := Boolean'Val ((y / (2 ** 29)) mod 2); y30 : constant Boolean := Boolean'Val ((y / (2 ** 30)) mod 2); y31 : constant Boolean := Boolean'Val ((y / (2 ** 31)) mod 2); y32 : constant Boolean := Boolean'Val ((y / (2 ** 32)) mod 2); y33 : constant Boolean := Boolean'Val ((y / (2 ** 33)) mod 2); y34 : constant Boolean := Boolean'Val ((y / (2 ** 34)) mod 2); y35 : constant Boolean := Boolean'Val ((y / (2 ** 35)) mod 2); y36 : constant Boolean := Boolean'Val ((y / (2 ** 36)) mod 2); y37 : constant Boolean := Boolean'Val ((y / (2 ** 37)) mod 2); y38 : constant Boolean := Boolean'Val ((y / (2 ** 38)) mod 2); y39 : constant Boolean := Boolean'Val ((y / (2 ** 39)) mod 2); y40 : constant Boolean := Boolean'Val ((y / (2 ** 40)) mod 2); y41 : constant Boolean := Boolean'Val ((y / (2 ** 41)) mod 2); y42 : constant Boolean := Boolean'Val ((y / (2 ** 42)) mod 2); y43 : constant Boolean := Boolean'Val ((y / (2 ** 43)) mod 2); y44 : constant Boolean := Boolean'Val ((y / (2 ** 44)) mod 2); -- Half-Adder 1: Carry cvk : constant Boolean := y44 and x44; bmf : constant Boolean := x43 and y43; qjp : constant Boolean := y42 and x42; kfp : constant Boolean := y41 and x41; c40_1_qhf : constant Boolean := y40 and x40; c38_1_crp : constant Boolean := x38 and y38; c37_1_nbc : constant Boolean := y37 and x37; pfc : constant Boolean := x36 and y36; qph : constant Boolean := y35 and x35; rkq : constant Boolean := y34 and x34; hbn : constant Boolean := x33 and y33; ttt : constant Boolean := x32 and y32; gpp : constant Boolean := y31 and x31; rvc : constant Boolean := y30 and x30; bqn : constant Boolean := x29 and y29; shp : constant Boolean := x28 and y28; fjr : constant Boolean := y27 and x27; jck : constant Boolean := x26 and y26; dbt : constant Boolean := y25 and x25; frv : constant Boolean := x24 and y24; nrw : constant Boolean := y23 and x23; dpg : constant Boolean := x22 and y22; c21_1_knb : constant Boolean := x21 and y21; c20_1_vwh : constant Boolean := y20 and x20; hhb : constant Boolean := x19 and y19; gpq : constant Boolean := y18 and x18; fpk : constant Boolean := x17 and y17; fhn : constant Boolean := y16 and x16; vch : constant Boolean := y15 and x15; ktg : constant Boolean := x14 and y14; c13_1_wbw : constant Boolean := y13 and x13; c12_1_njd : constant Boolean := x12 and y12; c11_1_cbm : constant Boolean := x11 and y11; c10_1_bcw : constant Boolean := y10 and x10; c09_1_ptc : constant Boolean := x09 and y09; c08_1_qpg : constant Boolean := y08 and x08; c07_1_vjc : constant Boolean := y07 and x07; knd : constant Boolean := y06 and x06; fkt : constant Boolean := x05 and y05; dtn : constant Boolean := y04 and x04; rtt : constant Boolean := y03 and x03; tng : constant Boolean := y02 and x02; hnj : constant Boolean := x01 and y01; jcq : constant Boolean := x00 and y00; -- Half-Adder 1: Sum jrb : constant Boolean := x44 xor y44; nsb : constant Boolean := x43 xor y43; sbn : constant Boolean := x42 xor y42; krk : constant Boolean := x41 xor y41; s40_1_qwt : constant Boolean := x40 xor y40; s39_1_ksf : constant Boolean := x39 xor y39; s38_1_spg : constant Boolean := x38 xor y38; s37_1_vjg : constant Boolean := x37 xor y37; s36_1_dkj : constant Boolean := x36 xor y36; prn : constant Boolean := y35 xor x35; bgg : constant Boolean := x34 xor y34; pmg : constant Boolean := y33 xor x33; wrd : constant Boolean := y32 xor x32; tkw : constant Boolean := y31 xor x31; qgc : constant Boolean := y30 xor x30; wtw : constant Boolean := x29 xor y29; rtb : constant Boolean := x28 xor y28; qrw : constant Boolean := y27 xor x27; jkt : constant Boolean := y26 xor x26; nfm : constant Boolean := x25 xor y25; kdn : constant Boolean := y24 xor x24; gcj : constant Boolean := x23 xor y23; qgd : constant Boolean := x22 xor y22; s21_1_sbs : constant Boolean := y21 xor x21; s20_1_vdc : constant Boolean := x20 xor y20; mcv : constant Boolean := x19 xor y19; jbp : constant Boolean := y18 xor x18; tdb : constant Boolean := x17 xor y17; vgb : constant Boolean := x16 xor y16; pvj : constant Boolean := y15 xor x15; c14_1_tfh : constant Boolean := y14 xor x14; s13_1_wgb : constant Boolean := y13 xor x13; s12_1_htr : constant Boolean := x12 xor y12; s11_1_ksb : constant Boolean := x11 xor y11; s10_1_cvv : constant Boolean := x10 xor y10; s09_1_mnm : constant Boolean := x09 xor y09; s08_1_jhr : constant Boolean := x08 xor y08; s07_1_gjv : constant Boolean := y07 xor x07; hsn : constant Boolean := x06 xor y06; sfn : constant Boolean := y05 xor x05; ptv : constant Boolean := y04 xor x04; npk : constant Boolean := x03 xor y03; qpd : constant Boolean := y02 xor x02; sqk : constant Boolean := x01 xor y01; z00 : constant Boolean := x00 xor y00; -- No carry in. bmc : constant Boolean := sqk and jcq; kpf : constant Boolean := hnj or bmc; pwk : constant Boolean := kpf and qpd; tpv : constant Boolean := tng or pwk; hrr : constant Boolean := tpv and npk; bdk : constant Boolean := hrr or rtt; nnq : constant Boolean := ptv and bdk; svk : constant Boolean := dtn or nnq; wnq : constant Boolean := sfn and svk; cjh : constant Boolean := fkt or wnq; hds : constant Boolean := cjh and hsn; wcs : constant Boolean := knd or hds; nbb : constant Boolean := s07_1_gjv and wcs; c08_bwm : constant Boolean := nbb or c07_1_vjc; c08_2_tvw : constant Boolean := c08_bwm and s08_1_jhr; c09_gqb : constant Boolean := c08_2_tvw or c08_1_qpg; c09_2_dsk : constant Boolean := c09_gqb and s09_1_mnm; z09 : constant Boolean := s09_1_mnm xor c09_gqb; c10_gwh : constant Boolean := c09_2_dsk or c09_1_ptc; c10_2_pgn : constant Boolean := c10_gwh and s10_1_cvv; c11_jbk : constant Boolean := c10_1_bcw or c10_2_pgn; c11_2_hgb : constant Boolean := s11_1_ksb and c11_jbk; c12_jgf : constant Boolean := c11_1_cbm or c11_2_hgb; c12_2_dmc : constant Boolean := c12_jgf and s12_1_htr; c13_qwr : constant Boolean := c12_2_dmc or c12_1_njd; c13_2_dqm : constant Boolean := c13_1_wbw and c13_qwr; -- !! nkd : constant Boolean := c13_2_dqm or s13_1_wgb; -- c14? jrd : constant Boolean := c14_1_tfh and nkd; bgh : constant Boolean := jrd or ktg; vcd : constant Boolean := bgh and pvj; nhh : constant Boolean := vcd or vch; btr : constant Boolean := vgb and nhh; ctv : constant Boolean := btr or fhn; ffh : constant Boolean := tdb and ctv; wtc : constant Boolean := fpk or ffh; pfh : constant Boolean := jbp and wtc; ppf : constant Boolean := pfh or gpq; gvt : constant Boolean := ppf and mcv; c20_tjc : constant Boolean := gvt or hhb; c20_2_vvc : constant Boolean := s20_1_vdc and c20_tjc; c21_kgk : constant Boolean := c20_1_vwh or c20_2_vvc; z21 : constant Boolean := c21_kgk xor s21_1_sbs; c21_2_rcb : constant Boolean := c21_kgk and s21_1_sbs; tvj : constant Boolean := c21_2_rcb or c21_1_knb; vsb : constant Boolean := qgd and tvj; grk : constant Boolean := dpg or vsb; cdw : constant Boolean := gcj and grk; pbv : constant Boolean := nrw or cdw; mhd : constant Boolean := kdn and pbv; vsw : constant Boolean := frv or mhd; dfq : constant Boolean := nfm and vsw; kgs : constant Boolean := dfq or dbt; wtd : constant Boolean := kgs and jkt; mjf : constant Boolean := jck or wtd; jgh : constant Boolean := mjf and qrw; whc : constant Boolean := fjr or jgh; jsf : constant Boolean := rtb and whc; vmj : constant Boolean := jsf or shp; nbw : constant Boolean := vmj and wtw; bqb : constant Boolean := nbw or bqn; nth : constant Boolean := qgc and bqb; mwg : constant Boolean := nth or rvc; vmq : constant Boolean := tkw and mwg; mrg : constant Boolean := gpp or vmq; vcm : constant Boolean := mrg and wrd; rnc : constant Boolean := vcm or ttt; dmp : constant Boolean := pmg and rnc; kvw : constant Boolean := hbn or dmp; gwm : constant Boolean := kvw and bgg; bhd : constant Boolean := rkq or gwm; drv : constant Boolean := prn and bhd; dmj : constant Boolean := drv or qph; vnw : constant Boolean := dmj and s36_1_dkj; jgc : constant Boolean := pfc or vnw; mqh : constant Boolean := s37_1_vjg and jgc; bwb : constant Boolean := c37_1_nbc or mqh; c38_2_wjg : constant Boolean := s38_1_spg and bwb; c39_wjf : constant Boolean := c38_1_crp or c38_2_wjg; c39_2_hvf : constant Boolean := s39_1_ksf and c39_wjf; z39_ok : constant Boolean := c39_wjf xor s39_1_ksf; c39_1_jct : constant Boolean := x39 and y39; nhk : constant Boolean := c39_1_jct or c39_2_hvf; qwh : constant Boolean := nhk and s40_1_qwt; sgk : constant Boolean := c40_1_qhf or qwh; qvv : constant Boolean := sgk and krk; pwt : constant Boolean := kfp or qvv; qwg : constant Boolean := sbn and pwt; gdt : constant Boolean := qwg or qjp; dnc : constant Boolean := nsb and gdt; tdh : constant Boolean := dnc or bmf; pjg : constant Boolean := jrb and tdh; -- Half-Adder 2: Sum z01 : constant Boolean := jcq xor sqk; z02 : constant Boolean := kpf xor qpd; z03 : constant Boolean := tpv xor npk; z04 : constant Boolean := ptv xor bdk; z05 : constant Boolean := svk xor sfn; z06 : constant Boolean := cjh xor hsn; z07 : constant Boolean := wcs xor s07_1_gjv; z08 : constant Boolean := c08_bwm xor s08_1_jhr; z10 : constant Boolean := s10_1_cvv xor c10_gwh; z11 : constant Boolean := s11_1_ksb xor c11_jbk; z12 : constant Boolean := s12_1_htr xor c12_jgf; z13 : constant Boolean := c13_qwr xor c13_1_wbw; -- should be c13 xor s13_1 z14 : constant Boolean := nkd xor c14_1_tfh; z15 : constant Boolean := bgh xor pvj; z16 : constant Boolean := nhh xor vgb; z17 : constant Boolean := ctv xor tdb; z18 : constant Boolean := wtc xor jbp; z19 : constant Boolean := mcv xor ppf; z20 : constant Boolean := s20_1_vdc xor c20_tjc; z22 : constant Boolean := qgd xor tvj; z23 : constant Boolean := grk xor gcj; z24 : constant Boolean := kdn xor pbv; z25 : constant Boolean := nfm xor vsw; z26 : constant Boolean := jkt xor kgs; z27 : constant Boolean := qrw xor mjf; z28 : constant Boolean := rtb xor whc; z29 : constant Boolean := wtw xor vmj; z30 : constant Boolean := bqb xor qgc; z31 : constant Boolean := mwg xor tkw; z32 : constant Boolean := mrg xor wrd; z33 : constant Boolean := pmg xor rnc; z34 : constant Boolean := bgg xor kvw; z35 : constant Boolean := bhd xor prn; z36 : constant Boolean := s36_1_dkj xor dmj; z37 : constant Boolean := s37_1_vjg xor jgc; z38 : constant Boolean := s38_1_spg xor bwb; z40 : constant Boolean := s40_1_qwt xor nhk; z41 : constant Boolean := sgk xor krk; z42 : constant Boolean := pwt xor sbn; z43 : constant Boolean := gdt xor nsb; z44 : constant Boolean := tdh xor jrb; z45 : constant Boolean := pjg or cvk; -- Last carry z : constant Integer_64 := Boolean'Pos (z00) * 2 ** 0 + Boolean'Pos (z01) * 2 ** 1 + Boolean'Pos (z02) * 2 ** 2 + Boolean'Pos (z03) * 2 ** 3 + Boolean'Pos (z04) * 2 ** 4 + Boolean'Pos (z05) * 2 ** 5 + Boolean'Pos (z06) * 2 ** 6 + Boolean'Pos (z07) * 2 ** 7 + Boolean'Pos (z08) * 2 ** 8 + Boolean'Pos (z09) * 2 ** 9 + Boolean'Pos (z10) * 2 ** 10 + Boolean'Pos (z11) * 2 ** 11 + Boolean'Pos (z12) * 2 ** 12 + Boolean'Pos (z13) * 2 ** 13 + Boolean'Pos (z14) * 2 ** 14 + Boolean'Pos (z15) * 2 ** 15 + Boolean'Pos (z16) * 2 ** 16 + Boolean'Pos (z17) * 2 ** 17 + Boolean'Pos (z18) * 2 ** 18 + Boolean'Pos (z19) * 2 ** 19 + Boolean'Pos (z20) * 2 ** 20 + Boolean'Pos (z21) * 2 ** 21 + Boolean'Pos (z22) * 2 ** 22 + Boolean'Pos (z23) * 2 ** 23 + Boolean'Pos (z24) * 2 ** 24 + Boolean'Pos (z25) * 2 ** 25 + Boolean'Pos (z26) * 2 ** 26 + Boolean'Pos (z27) * 2 ** 27 + Boolean'Pos (z28) * 2 ** 28 + Boolean'Pos (z29) * 2 ** 29 + Boolean'Pos (z30) * 2 ** 30 + Boolean'Pos (z31) * 2 ** 31 + Boolean'Pos (z32) * 2 ** 32 + Boolean'Pos (z33) * 2 ** 33 + Boolean'Pos (z34) * 2 ** 34 + Boolean'Pos (z35) * 2 ** 35 + Boolean'Pos (z36) * 2 ** 36 + Boolean'Pos (z37) * 2 ** 37 + Boolean'Pos (z38) * 2 ** 38 + Boolean'Pos (z39_ok) * 2 ** 39 + Boolean'Pos (z40) * 2 ** 40 + Boolean'Pos (z41) * 2 ** 41 + Boolean'Pos (z42) * 2 ** 42 + Boolean'Pos (z43) * 2 ** 43 + Boolean'Pos (z44) * 2 ** 44 + Boolean'Pos (z45) * 2 ** 45; begin return z; end Add; function Check (x, y : Integer_64) return Boolean is begin return Add (x, y) = x + y; end Check; begin for i in 0 .. 44 loop for j in 0 .. 44 loop if not Check (2**i, 2**j) then Put_Line (i'Image & ", " & j'Image); end if; end loop; end loop; r (part_2) := +"gwh,jct,rcb,wbw,wgb,z09,z21,z39"; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Do_Part_1; if not compiler_test_mode then Do_Part_2; end if; if compiler_test_mode then if r (part_1) /= Argument (1) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 57270694330992 -- Part 2: validated by AoC: gwh,jct,rcb,wbw,wgb,z09,z21,z39 end if; end AoC_2024_24; ================================================ FILE: exm/aoc/2024/aoc_2024_24_questions.txt ================================================ --- Day 24: Crossed Wires --- You and The Historians arrive at the edge of a large grove somewhere in the jungle. After the last incident, the Elves installed a small device that monitors the fruit. While The Historians search the grove, one of them asks if you can take a look at the monitoring device; apparently, it's been malfunctioning recently. The device seems to be trying to produce a number through some boolean logic gates. Each gate has two inputs and one output. The gates all operate on values that are either true (1) or false (0). AND gates output 1 if both inputs are 1; if either input is 0, these gates output 0. OR gates output 1 if one or both inputs is 1; if both inputs are 0, these gates output 0. XOR gates output 1 if the inputs are different; if the inputs are the same, these gates output 0. Gates wait until both inputs are received before producing output; wires can carry 0, 1 or no value at all. There are no loops; once a gate has determined its output, the output will not change until the whole system is reset. Each wire is connected to at most one gate output, but can be connected to many gate inputs. Rather than risk getting shocked while tinkering with the live system, you write down all of the gate connections and initial wire values (your puzzle input) so you can consider them in relative safety. For example: x00: 1 x01: 1 x02: 1 y00: 0 y01: 1 y02: 0 x00 AND y00 -> z00 x01 XOR y01 -> z01 x02 OR y02 -> z02 Because gates wait for input, some wires need to start with a value (as inputs to the entire system). The first section specifies these values. For example, x00: 1 means that the wire named x00 starts with the value 1 (as if a gate is already outputting that value onto that wire). The second section lists all of the gates and the wires connected to them. For example, x00 AND y00 -> z00 describes an instance of an AND gate which has wires x00 and y00 connected to its inputs and which will write its output to wire z00. In this example, simulating these gates eventually causes 0 to appear on wire z00, 0 to appear on wire z01, and 1 to appear on wire z02. Ultimately, the system is trying to produce a number by combining the bits on all wires starting with z. z00 is the least significant bit, then z01, then z02, and so on. In this example, the three output bits form the binary number 100 which is equal to the decimal number 4. Here's a larger example: x00: 1 x01: 0 x02: 1 x03: 1 x04: 0 y00: 1 y01: 1 y02: 1 y03: 1 y04: 1 ntg XOR fgs -> mjb y02 OR x01 -> tnw kwq OR kpj -> z05 x00 OR x03 -> fst tgd XOR rvg -> z01 vdt OR tnw -> bfw bfw AND frj -> z10 ffh OR nrd -> bqk y00 AND y03 -> djm y03 OR y00 -> psh bqk OR frj -> z08 tnw OR fst -> frj gnj AND tgd -> z11 bfw XOR mjb -> z00 x03 OR x00 -> vdt gnj AND wpb -> z02 x04 AND y00 -> kjc djm OR pbm -> qhw nrd AND vdt -> hwm kjc AND fst -> rvg y04 OR y02 -> fgs y01 AND x02 -> pbm ntg OR kjc -> kwq psh XOR fgs -> tgd qhw XOR tgd -> z09 pbm OR djm -> kpj x03 XOR y03 -> ffh x00 XOR y04 -> ntg bfw OR bqk -> z06 nrd XOR fgs -> wpb frj XOR qhw -> z04 bqk OR frj -> z07 y03 OR x01 -> nrd hwm AND bqk -> z03 tgd XOR rvg -> z12 tnw OR pbm -> gnj After waiting for values on all wires starting with z, the wires in this system have the following values: bfw: 1 bqk: 1 djm: 1 ffh: 0 fgs: 1 frj: 1 fst: 1 gnj: 1 hwm: 1 kjc: 0 kpj: 1 kwq: 0 mjb: 1 nrd: 1 ntg: 0 pbm: 1 psh: 1 qhw: 1 rvg: 0 tgd: 0 tnw: 1 vdt: 1 wpb: 0 z00: 0 z01: 0 z02: 0 z03: 1 z04: 0 z05: 1 z06: 1 z07: 1 z08: 1 z09: 1 z10: 1 z11: 0 z12: 0 Combining the bits from all wires starting with z produces the binary number 0011111101000. Converting this number to decimal produces 2024. Simulate the system of gates and wires. What decimal number does it output on the wires starting with z? --- Part Two --- After inspecting the monitoring device more closely, you determine that the system you're simulating is trying to add two binary numbers. Specifically, it is treating the bits on wires starting with x as one binary number, treating the bits on wires starting with y as a second binary number, and then attempting to add those two numbers together. The output of this operation is produced as a binary number on the wires starting with z. (In all three cases, wire 00 is the least significant bit, then 01, then 02, and so on.) The initial values for the wires in your puzzle input represent just one instance of a pair of numbers that sum to the wrong value. Ultimately, any two binary numbers provided as input should be handled correctly. That is, for any combination of bits on wires starting with x and wires starting with y, the sum of the two numbers those bits represent should be produced as a binary number on the wires starting with z. For example, if you have an addition system with four x wires, four y wires, and five z wires, you should be able to supply any four-bit number on the x wires, any four-bit number on the y numbers, and eventually find the sum of those two numbers as a five-bit number on the z wires. One of the many ways you could provide numbers to such a system would be to pass 11 on the x wires (1011 in binary) and 13 on the y wires (1101 in binary): x00: 1 x01: 1 x02: 0 x03: 1 y00: 1 y01: 0 y02: 1 y03: 1 If the system were working correctly, then after all gates are finished processing, you should find 24 (11+13) on the z wires as the five-bit binary number 11000: z00: 0 z01: 0 z02: 0 z03: 1 z04: 1 Unfortunately, your actual system needs to add numbers with many more bits and therefore has many more wires. Based on forensic analysis of scuff marks and scratches on the device, you can tell that there are exactly four pairs of gates whose output wires have been swapped. (A gate can only be in at most one such pair; no gate's output was swapped multiple times.) For example, the system below is supposed to find the bitwise AND of the six-bit number on x00 through x05 and the six-bit number on y00 through y05 and then write the result as a six-bit number on z00 through z05: x00: 0 x01: 1 x02: 0 x03: 1 x04: 0 x05: 1 y00: 0 y01: 0 y02: 1 y03: 1 y04: 0 y05: 1 x00 AND y00 -> z05 x01 AND y01 -> z02 x02 AND y02 -> z01 x03 AND y03 -> z03 x04 AND y04 -> z04 x05 AND y05 -> z00 However, in this example, two pairs of gates have had their output wires swapped, causing the system to produce wrong answers. The first pair of gates with swapped outputs is x00 AND y00 -> z05 and x05 AND y05 -> z00; the second pair of gates is x01 AND y01 -> z02 and x02 AND y02 -> z01. Correcting these two swaps results in this system that works as intended for any set of initial values on wires that start with x or y: x00 AND y00 -> z00 x01 AND y01 -> z01 x02 AND y02 -> z02 x03 AND y03 -> z03 x04 AND y04 -> z04 x05 AND y05 -> z05 In this example, two pairs of gates have outputs that are involved in a swap. By sorting their output wires' names and joining them with commas, the list of wires involved in swaps is z00,z01,z02,z05. Of course, your actual system is much more complex than this, and the gates that need their outputs swapped could be anywhere, not just attached to a wire starting with z. If you were to determine that you need to swap output wires aaa with eee, ooo with z99, bbb with ccc, and aoc with z24, your answer would be aaa,aoc,bbb,ccc,eee,ooo,z24,z99. Your system of gates and wires has four pairs of gates which need their output wires swapped - eight wires in total. Determine which four pairs of gates need their outputs swapped so that your system correctly performs addition; what do you get if you sort the names of the eight wires involved in a swap and then join those names with commas? ================================================ FILE: exm/aoc/2024/aoc_2024_25.adb ================================================ -- Solution to Advent of Code 2024, Day 25 ------------------------------------------- -- Code Chronicle -- -- https://adventofcode.com/2024/day/25 -- Copy of questions in: aoc_2024_25_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2024.gpr . with HAT; procedure AoC_2024_25 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2024_25"; verbose : constant Boolean := False; subtype Pin_Range is Integer range 1 .. 5; type Pin_Height is array (Pin_Range) of Natural; key, lock : array (1 .. 500) of Pin_Height; last_key, last_lock : Natural := 0; r : array (Part_Type) of VString; procedure Read_Data is subtype Pattern is String (Pin_Range); pat : Pattern; f : File_Type; begin Open (f, input_name & ".txt"); Get (f, pat); while not End_Of_File (f) loop exit when pat = "STOP."; if pat = "#####" then -- Lock last_lock := last_lock + 1; for i in 0 .. 6 loop for j in Pin_Range loop if pat (j) = '#' then lock (last_lock)(j) := i; end if; end loop; Get (f, pat); end loop; if verbose then Put ("Lock "); for j in Pin_Range loop Put (lock (last_lock)(j), 0); end loop; New_Line; end if; else -- Key last_key := last_key + 1; for j in Pin_Range loop key (last_key)(j) := 0; end loop; for i in 0 .. 6 loop for j in Pin_Range loop if pat (j) = '#' and then key (last_key)(j) = 0 then key (last_key)(j) := 6 - i; end if; end loop; Get (f, pat); end loop; if verbose then Put ("Key "); for j in Pin_Range loop Put (key (last_key)(j), 0); end loop; New_Line; end if; end if; end loop; Close (f); end Read_Data; procedure Do_Part_1 is count : Natural := 0; ok : Boolean; begin for k in 1 .. last_key loop for l in 1 .. last_lock loop ok := True; for j in Pin_Range loop ok := ok and then key (k)(j) + lock (l)(j) <= 5; end loop; if ok then count := count + 1; end if; end loop; end loop; r (part_1) := +"" & count; end Do_Part_1; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; if compiler_test_mode then if r (part_1) /= Argument (1) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); -- Part 1: validated by AoC: 3395 end if; end AoC_2024_25; ================================================ FILE: exm/aoc/2024/aoc_2024_25.txt ================================================ ##### ##### ##### #.##. ...#. ..... ..... ..... .#.#. .###. .###. .###. .#### ##### ..... ..... ..... ....# .#..# ##.## ##### ##### .#### .##.# .#..# ..... ..... ..... ..... .#... .#... ##... ##... ###.# ##### ..... ..... ..... ....# #..## ##.## ##### ..... ...#. #..#. #..#. #..#. ##.#. ##### ..... ....# ..#.# .##.# .##.# .##.# ##### ##### ##.## ##.## ##..# #.... #.... ..... ..... ..... ..... #.... #.... #.#.# ##### ..... #..#. #..#. ##.#. ##### ##### ##### ..... #.#.. #.#.. ###.# ###.# ##### ##### ..... .#.#. ##.## ##### ##### ##### ##### ##### ###.# ##... ##... #.... ..... ..... ##### .###. ..#.. ..#.. ..... ..... ..... ##### ##### #.#.# ..#.# ..#.# ..#.. ..... ..... #.... #..#. #..## ##.## ##### ##### ##### ##.## ##.## #..#. #..#. ..... ..... ##### ##.#. .#... ..... ..... ..... ..... ..... .#... ##... ##.#. ####. ##### ##### ..... #.#.# #.### ##### ##### ##### ##### ..... ...#. .#.#. .#.#. .#.#. .#.#. ##### ..... ..#.. #.#.# #.### #.### ##### ##### ##### ####. ####. ####. #.##. #.#.. ..... ##### .#.## .#.#. .#.#. .#... .#... ..... ##### #.### #.### #..## #...# #...# ..... ##### ##.#. #..#. #..#. ...#. ...#. ..... ..... ..#.. ..#.. .##.# .#### ##### ##### ##### .#.#. .#.#. ...#. ...#. ...#. ..... ..... ...#. #..#. #..#. ##.## ##.## ##### ##### #.### ...## ....# ..... ..... ..... ..... ..#.. #.#.. #.#.# ###.# ##### ##### ..... ..... ...#. #..#. #..## ##.## ##### ##### ##### ##.## ##.## ##..# .#... ..... ##### ##### ###.# ###.# ###.. #.#.. ..... ..... ..... .#... .#... .##.. ####. ##### ..... .#..# .#..# .#.## .#.## ##### ##### ..... .#... .##.. .###. ####. ##### ##### ..... .#... ##... ##..# ##..# ###.# ##### ..... ...#. .#.#. .#.## .#.## ##### ##### ##### .#### .##.# .##.. .#... .#... ..... ..... #..#. ##.#. ##.#. ##.## ##### ##### ##### ##### ##### .#.## .#.## ....# ..... ##### ##### ###.# #.#.# ..#.. ..#.. ..... ..... #.... #...# ##..# ###.# ##### ##### ..... ..... ...#. ...#. .#.#. .#### ##### ##### ##### ##### ##.## .#..# .#..# ..... ##### ##.## #..## ...#. ...#. ...#. ..... ..... ..... ...#. ...#. ..##. .#### ##### ##### ##### #.#.# #.#.# #.#.# #.#.# ..... ##### ###.# ###.. ##... #.... #.... ..... ..... .#.#. ####. ####. ####. ##### ##### ##### ##### ##.## .#.#. .#.#. ..... ..... ..... ..... ..#.. #.#.# #.#.# #.### ##### ..... ....# ....# ....# .#.## .#.## ##### ##### ##.## ##.## .#.## ...#. ...#. ..... ..... ..#.. ..#.# .#### .#### .#### ##### ##### ####. #.##. #.##. ..#.. ..#.. ..... ##### #.### #.### ..### ..##. ..#.. ..... ..... .#... .#... ##.#. ##.#. ##### ##### ##### ##### ##### ####. #.##. #.#.. ..... ##### ##.#. ##... .#... .#... .#... ..... ##### ##.## ##..# #...# ..... ..... ..... ##### ##### #.### #.#.# #.#.# ..... ..... ..... #.... #.... #.#.# ###.# ##### ##### ##### #.#.# #...# #...# #...# #...# ..... ..... ..#.. ..#.. #.#.. ####. ##### ##### ..... .#..# .#..# .#..# ##.## ##### ##### ..... ....# .#..# ##..# ##.## ##.## ##### ..... ..... ....# ...## #.### #.### ##### ..... ..#.. ..#.. ..#.. ..#.. #.#.# ##### ##### .##.# .#..# .#..# .#..# ..... ..... ##### ##### ##.## ##.## ##.## .#..# ..... ..... .#... .#... .#..# ##.## ##### ##### ..... ..... ...#. #.##. #.##. #.### ##### ..... ..... #...# #.#.# #.#.# #.### ##### ..... ..#.. ..#.. ..#.. .##.# ###.# ##### ..... ...#. .#.#. .#.#. .#.#. .#### ##### ..... ..... ..... #..#. #.### #.### ##### ..... ..... .#..# ##..# ##.## ##.## ##### ..... #.#.# #.#.# #.#.# #.### #.### ##### ..... ..... .#..# ##.## ##### ##### ##### ##### ##.## ##.## ##.#. ##.#. #.... ..... ..... ..#.. ..#.. ..#.# .#### ##### ##### ..... ..... ..... .#.#. ##.#. ##### ##### ##### ##.## #..#. ...#. ...#. ...#. ..... ##### #.##. #.##. ..##. ..#.. ..... ..... ##### ###.# ###.# ##..# #.... ..... ..... ##### .#.#. .#.#. ...#. ..... ..... ..... ##### ##### .#### ..### ..#.# ..#.. ..... ..... ...#. ...#. #.##. ####. ##### ##### ..... ..... ....# ..#.# ..### .#### ##### ##### ##.## ##.## .#.## .#.## .#..# ..... ..... ..... ..... .#... ###.. ###.# ##### ##### ##### ##.## .#.## ...## ...#. ..... ..... ...#. ...#. ..### .#### ##### ##### ..... #.#.. #.#.. ###.# ##### ##### ##### ..... ..#.# ..#.# #.### #.### #.### ##### ..... ..... .#.#. ##.#. ##.#. ##### ##### ##### #.### #.### ..##. ...#. ..... ..... ##### .#### .#### .#.#. .#... .#... ..... ##### .##.# .##.# .##.. .##.. ..#.. ..... ##### .#### .#.## .#.#. ...#. ..... ..... ..... #.... #.... #...# ##.## ##.## ##### ..... ..... ..... ...#. .#.#. .#.#. ##### ..... ..... ..#.. ..#.. #.#.# ##### ##### ##### ###.# #.#.# ..#.. ..... ..... ..... ##### ##### .#.## .#..# .#..# .#..# ..... ##### ####. .###. .#.#. .#.#. ..... ..... ##### ##### #.#.# #.#.# ..... ..... ..... ##### #.### #.### ..### ..##. ...#. ..... ..... .#... .#.#. .#.#. .#### ##### ##### ..... ...#. #..#. #..#. ##.#. ####. ##### ..... #.#.. #.#.. #.#.. #.#.# #.#.# ##### ..... ..... .#... .#... .#.#. .###. ##### ..... ..... #.... #.... ##.#. ##### ##### ..... ..... ..#.. ..#.# #.#.# ###.# ##### ##### #.##. #.##. #.#.. #.... ..... ..... ##### ##### #.### #..## #..#. #..#. ..... ..... ..#.. ..#.. #.##. #.##. ##### ##### ##### ##### ##### .#### ..##. ...#. ..... ..... ..#.. #.#.# ###.# ###.# ##### ##### ##### ###.# #.#.# #.#.# #...# #.... ..... ..... #..#. #..#. #.##. ####. ##### ##### ##### ##### #.### #.### #..## #...# ..... ##### #.##. ..#.. ..#.. ..#.. ..#.. ..... ..... #.... #.... #.... #.#.# #.### ##### ##### ##### ##.## .#.#. .#.#. .#... ..... ..... ..#.# ..#.# #.#.# #.#.# #.### ##### ##### #.#.# ....# ....# ..... ..... ..... ##### ##### .#.## .#.#. .#.#. .#... ..... ..... ..... ..#.# #.#.# #.#.# #.#.# ##### ##### ##### ##### .#.## .#.#. .#... ..... ##### #.### #.### #.#.# ....# ..... ..... ##### #.### #.##. #..#. #.... #.... ..... ..... ..#.. ..#.# .##.# .##.# ###.# ##### ##### .#### ..#.# ..#.. ..... ..... ..... ..... ..... ..#.. ..#.. ..#.# #.### ##### ..... #.#.# #.#.# ###.# ###.# ##### ##### ##### ##### .#### .#### ..#.# ..#.. ..... ##### ##.## ##.## ##.## .#.#. ..... ..... ##### #.#.# #.#.. #.... #.... #.... ..... ..... ..... ..... ..#.. ..##. .#### ##### ##### ####. ##.#. ##... .#... .#... ..... ..... ..... ..... .#... ##.#. ##.#. ##### ..... ..... .#.#. .#.## ##### ##### ##### ..... ...#. .#.#. ##.## ##.## ##### ##### ..... #.... ##.#. ##### ##### ##### ##### ##### ##### ##### #.#.# ..#.. ..... ..... ..... ..#.# #.#.# #.#.# #.### #.### ##### ..... ..... #...# #...# ##.## ##.## ##### ##### ##### ##### #.### #..## ...#. ..... ##### .#.## .#.## ...#. ...#. ...#. ..... ..... .#... ###.. ####. ####. ##### ##### ##### ###.# ###.# ##..# ##..# #.... ..... ##### #.#.# #.#.# #...# #.... #.... ..... ##### ##### #.##. #.#.. ..... ..... ..... ##### ##### ##### ##.## #...# #.... ..... ##### ##### ##### ####. .###. ..#.. ..... ..... ....# ....# #.#.# #.#.# ##### ##### ..... ..... ..#.. ..##. ..##. #.### ##### ..... .#..# .#.## ##.## ##.## ##.## ##### ..... ..... #.#.# #.#.# ###.# ##### ##### ..... ..#.. .##.. .##.# ###.# ###.# ##### ##### .##.# .##.# ..#.# ....# ..... ..... ..... ..#.. #.#.. #.#.# #.#.# #.### ##### ##### ##### #.### #.##. ..#.. ..... ..... ..... ..... #.#.# #.#.# #.### ##### ##### ..... ...#. #..## ##.## ##.## ##.## ##### ##### ##### ####. .##.. .##.. ..#.. ..... ..... ..... #.... ##... ##.#. ##.#. ##### ##### ###.# ###.# ##..# .#..# .#..# ..... ##### ##### ##.## .#.#. ..... ..... ..... ##### ####. .##.. .#... .#... .#... ..... ..... #.... #..#. #.### #.### #.### ##### ..... ....# ..#.# ..### ..### #.### ##### ..... ....# #..## #..## #.### ##### ##### ..... ..#.. ..##. .#### .#### ##### ##### ..... ..... ..... ..#.. #.##. #.### ##### ##### ##### .###. .#.#. .#... .#... ..... ##### ##### ####. #.#.. #.#.. #.... ..... ##### ##.#. ##.#. #..#. #..#. #..#. ..... ..... #..#. ##.#. ##.## ##### ##### ##### ##### ##### ##### #.### #.#.# ..#.# ..... ..... ..... ..... ..#.. ..#.# .##.# ##### ..... ....# ..#.# .##.# ###.# ###.# ##### ##### ##### ##.#. ##.#. .#.#. .#.#. ..... ##### ##.## .#.## .#.## ...## ....# ..... ##### .#### .#### ..### ..### ...#. ..... ##### ##### .##.# .##.# .##.. ..#.. ..... ##### ##### ###.# #.#.. ..... ..... ..... ##### ##### #.### ..### ..#.# ..#.# ..... ..... #.#.# #.#.# #.#.# ##### ##### ##### ##### ##### ##### ##.## ##.#. .#... ..... ..... ...#. ..### ..### .#### .#### ##### ##### #.### #.### #.##. #.#.. #.#.. ..... ..... ..... ..... ..... #..#. #.### ##### ##### ##### ###.# .#..# ....# ..... ..... ..... #.#.. #.#.# #.#.# ###.# ###.# ##### ..... #...# #.#.# ###.# ##### ##### ##### ..... ..#.. #.##. #.##. #.### ##### ##### ##### ##.## .#..# .#..# ....# ..... ..... ##### ##### ####. ##.#. ##.#. .#.#. ..... ##### .#.## .#.## .#.#. ...#. ..... ..... ..... ..... ..... ...#. ...## .#.## ##### ##### .##.# ..#.. ..#.. ..#.. ..#.. ..... ##### #.### ...## ...## ....# ....# ..... ##### #.### #.### ..#.# ..#.# ..#.# ..... ##### #.### #.### #..#. #..#. ...#. ..... ##### .###. .###. .##.. .#... .#... ..... ##### ##.## ##.## ##.## #..#. ..... ..... ..... .#... ##... ##... ##.#. ####. ##### ##### ##### .#.#. .#... .#... ..... ..... ##### #.### #..## #...# ..... ..... ..... ..... ...#. ..##. ..##. ..##. #.##. ##### ##### ##### .##.# .#..# ....# ....# ..... ##### #.### #.##. #.##. #..#. #.... ..... ##### .#### .#### .#### .##.# ..#.. ..... ..... ..... ..#.# #.#.# #.#.# ###.# ##### ..... ..... ...#. .#.#. ####. ##### ##### ..... ..... ..#.# .##.# .##.# .#### ##### ..... .#... ###.. ####. ####. ####. ##### ..... ..#.. ..#.. #.#.. #.#.. ####. ##### ..... ..... #.#.. #.#.. ###.. ###.# ##### ##### ####. .###. .##.. .#... ..... ..... ##### .##.# .##.# .#..# .#..# .#..# ..... ..... ...#. ...#. #..#. ##.#. ##.## ##### ##### ##### #.### #.### #.#.# ....# ..... ..... ..... .#.#. .#.#. ##.#. ##### ##### ..... ..... .#... ##... ##... ##.#. ##### ##### #.### #.### #.#.# #.... ..... ..... ..... .#... .#..# .#..# .##.# .##.# ##### ..... ..... ...#. ..##. ..##. #.### ##### ..... .#..# .#..# .#.## .#.## ##.## ##### ##### #.##. ..##. ..##. ...#. ...#. ..... ..... ..... #..#. #.##. #.##. ####. ##### ##### .#### .#### .##.# .#... ..... ..... ##### ##### #.### #.##. ..##. ...#. ..... ##### .##.# ..#.# ..#.# ..#.# ..... ..... ..... ..#.. ..#.. ..#.# #.### #.### ##### ..... ...#. ..### ..### #.### ##### ##### ..... ....# #..## #.### #.### #.### ##### ..... .#.#. .#.## .#### .#### ##### ##### ..... ..#.# .#### .#### .#### ##### ##### ##### ##### ##### #.### ..#.# ..#.. ..... ##### ####. .###. ..##. ..##. ...#. ..... ##### ##.## #..#. #..#. ...#. ..... ..... ##### ##### ####. ###.. ##... .#... ..... ##### #.### ..### ..### ..##. ...#. ..... ..... #...# #.#.# #.### ##### ##### ##### ..... #.... #..#. #.##. #.##. #.##. ##### ##### ##### ###.# ###.# ##..# .#... ..... ##### ####. .###. .#.#. ...#. ...#. ..... ..... #..#. #..#. #..#. #..#. ##.## ##### ..... #.... ##... ##... ###.# ###.# ##### ..... ....# ...## ...## ..### .#### ##### ##### ##### .##.# .##.. .#... .#... ..... ##### ##.## ##.## .#.#. .#... .#... ..... ##### ##### ##### ###.# #.#.# ..#.# ..... ##### .#.## .#.## .#.#. .#.#. .#.#. ..... ##### ##### #.##. ..##. ..##. ..#.. ..... ..... ...#. .#.#. .###. .#### .#### ##### ##### ##### ###.# ###.# #.#.# #.#.# ..... ..... ..... ..... .#.#. ##.#. ##.## ##### ..... ..... ...#. ..##. #.##. #.##. ##### ##### ##### ###.# #.#.# ..#.# ..... ..... ..... ..... ..... .#..# ###.# ##### ##### ##### ####. ##.#. #..#. #..#. #.... ..... ##### ##.## #...# #.... #.... ..... ..... ##### ##### ##### #.### #..#. #..#. ..... ##### ##### .#.## .#.## ...#. ...#. ..... ..... ..... .#... .#... ##.#. ##.#. ##### ##### ##### ##.#. ##.#. ##... #.... ..... ..... ...#. ...## ..### ..### .#### ##### ..... ..... ..#.. ..#.. ..#.. .##.# ##### ..... ..#.. .##.. ###.# ###.# ###.# ##### ..... #..#. #..#. ##.#. ##.#. ####. ##### ..... ....# #...# #..## #.### #.### ##### ..... ..... .#..# .##.# .##.# ##### ##### ##### #.#.# #.#.# #...# #...# ..... ..... ##### ##### ####. ####. #.##. #..#. ..... ..... .#.#. .#.#. .#.#. .#### .#### ##### ##### ##### ##### ####. ##.#. #..#. ..... ##### ###.# .##.# .##.# ..#.. ..... ..... ..... .#... .#..# .##.# .#### ##### ##### ##### ####. ##.#. .#.#. .#.#. .#... ..... ##### ###.# ###.# ##... .#... ..... ..... ##### ##.## ##.## ##.## ##..# .#..# ..... ..... ..#.. #.#.. #.#.. ####. ####. ##### ..... ..... ....# #..## ##.## ##.## ##### ..... ..... ..... .#..# .##.# ##### ##### ..... ..... .#... .#... .#... ##.#. ##### ##### #.### #..#. #.... #.... ..... ..... ..... .#... .#..# .#..# .#.## .#.## ##### ..... .#... .#..# .#.## .#.## ##### ##### ##### #.#.# ..#.# ..#.# ..... ..... ..... ..... ....# #...# #.#.# #.#.# ##### ##### ##### .#### ..### ..##. ...#. ...#. ..... ##### .#### .##.# .##.# .##.# ..#.. ..... ##### .###. .##.. .#... .#... .#... ..... ..... .#... .#... ##.#. ##.## ##.## ##### ..... #.... #.#.. #.#.# #.### #.### ##### ..... ..... .#... .#.#. .#.#. ####. ##### ##### #.### ..### ..#.# ..#.# ..... ..... ##### ##### ##### .#### .##.# .#... ..... ..... ..... ....# ..#.# #.#.# #.#.# ##### ##### .#.## .#..# .#..# .#..# .#... ..... ##### ##.## ##.## .#.## ....# ....# ..... ##### ##### ##### ##### #.#.# ..... ..... ##### ##### ####. ##.#. #..#. ...#. ..... ..... ....# #..## #..## #.### #.### ##### ##### ###.# ###.# .##.# ..#.# ....# ..... ..... ....# ....# #..## ##.## ##.## ##### ##### ####. ##.#. .#.#. .#.#. ...#. ..... ##### .#### .###. ..##. ..#.. ..... ..... ##### ##### .#.## .#.## .#.## .#.#. ..... ##### .#### .##.# .##.# ..#.. ..... ..... ##### ####. ##.#. #..#. ...#. ..... ..... ..... ..... ...#. #.### #.### ##### ##### ..... #.... #..#. #..#. ##.#. ##### ##### ##### ##### ###.# .##.# ..#.# ..#.. ..... ##### ##.#. ##.#. .#.#. .#... .#... ..... ..... ..#.. ..#.. ..#.# .##.# .#### ##### ..... ..#.. ..#.. .##.. .##.# .#### ##### ..... ..#.. ..#.. #.#.# ###.# ###.# ##### ##### #.### ..### ..#.# ..... ..... ..... ..... ..#.. #.##. #.##. #.##. ##### ##### ##### ####. ###.. ##... ##... #.... ..... ..... #.... ##... ###.. ####. ####. ##### ##### ###.# ###.. ###.. .##.. ..#.. ..... ..... ..... ..... #.... ##... ###.# ##### ..... #.#.# #.#.# #.#.# ###.# ##### ##### ..... ..... ..... .#... ##... ###.# ##### ..... ....# ....# .#.## .#.## .#### ##### ..... #..#. #..## #..## #..## ##.## ##### ##### ##### .#.#. ...#. ...#. ..... ..... ##### ###.# ###.# ###.# ##..# .#... ..... ##### ##### ##.## ##..# .#..# .#... ..... ##### #.### #.### #.### #..#. ...#. ..... ##### ##.## .#.## .#.#. ..... ..... ..... ..... ..... ..... .#..# .##.# .##.# ##### ##### ##.## ##.## #..#. #..#. #.... ..... ##### .#### .##.# .##.# .#... .#... ..... ##### ##### .#### .#### .#.#. .#... ..... ##### ###.# .##.# ..#.# ....# ....# ..... ..... #.... #..#. #.##. #.### #.### ##### ##### ##### ##### #.##. ..##. ..#.. ..... ##### ###.# #.#.# #.#.# #.#.# #.#.. ..... ##### .###. .#.#. .#.#. ...#. ..... ..... ##### .#.## .#.#. ...#. ..... ..... ..... ##### ####. .###. .#.#. .#.#. .#... ..... ##### ##### ##.## ##.## #..## #..#. ..... ##### #.#.# ..#.# ..... ..... ..... ..... ..... ..... ....# ....# .#..# ###.# ##### ##### ##### ##.#. #..#. #.... #.... ..... ..... ...#. ...#. ..##. ..### .#### ##### ..... ..... ...#. ...#. .#.#. ##.#. ##### ##### .##.# .##.# .##.# .##.# ..#.# ..... ##### .#### .###. ..##. ...#. ...#. ..... ..... #.... #.#.. #.##. #.##. #.##. ##### ..... ..#.. ..#.# ..### ..### .#### ##### ..... #..#. ##.#. ##.#. ##.#. ####. ##### ##### ##### .#### .##.# ..#.# ..... ..... ..... #.#.. #.##. #.##. #.##. ##### ##### ..... .#... ##..# ##..# ###.# ###.# ##### ..... ..... ..... #.... #.#.# #.### ##### ..... ..... #...# #.#.# ###.# ###.# ##### ..... ...#. #..#. ##.#. ##.#. ####. ##### ##### ##.## #..## #...# #.... ..... ..... ##### #.### ..### ..### ..#.# ..... ..... ..... .#... .##.. ###.. ####. ####. ##### ..... ..#.. ..#.. ..#.. ..##. #.### ##### ##### .#### .#.## ...## ....# ....# ..... ..... ..... .#... .#... .##.# .##.# ##### ##### ##.## ##.#. ##... #.... #.... ..... ##### ##### .#### ..#.# ..#.# ..#.# ..... ..... .#... .#... .#.#. ##.#. ##### ##### ..... ..... ..... #..#. #..#. #.### ##### ..... .#.#. .###. .###. .###. ##### ##### ##### ##### ##.#. #.... #.... #.... ..... ..... .#... .#... .#..# .##.# ###.# ##### ..... ..#.. .###. .###. ##### ##### ##### ..... ..... ..#.# ..#.# .##.# ###.# ##### ##### ##### ##### .#### .#.## .#.#. ..... ##### .###. .#.#. ..... ..... ..... ..... ##### ##### #.### #.### ..### ..#.# ..... ..... #..#. #.##. #.##. ####. ##### ##### ..... ..#.. ..#.. #.#.# ##### ##### ##### ..... ..... ....# ....# ..#.# .##.# ##### ..... #.... #.... ##..# ##.## ##### ##### ##### ##### #.#.# #...# #.... #.... ..... ..... ..... #.#.. #.#.. #.#.. ###.# ##### ..... #.... #.... ##... ##..# ###.# ##### ##### ###.# ###.# ###.. ###.. #.#.. ..... ..... .#... ##... ##... ##..# ##.## ##### ..... ..... ..... ..#.. #.#.. ####. ##### ##### .#### ..### ..##. ..#.. ..#.. ..... ..... ..... ..#.. #.#.# #.### ##### ##### ..... ..... ..#.. #.#.. #.#.# #.### ##### ##### ###.# .##.. .##.. ..#.. ..#.. ..... ##### ##### .#.## ...## ...## ....# ..... ..... ..... .#... ##... ##..# ##.## ##### ..... ..#.. ..#.. ..#.. #.##. ####. ##### ##### .#.#. .#.#. .#.#. ...#. ...#. ..... ##### ##### #.### #.#.# ..#.# ..#.# ..... ##### ##### #.### #.### ..### ...#. ..... ..... ..... ..... ..#.. #.#.. #.##. ##### ##### ##### .##.# .#... .#... ..... ..... ##### .##.# ..#.. ..#.. ..... ..... ..... ..... ...#. ...#. ...#. ..### #.### ##### ##### .##.# ..#.# ..#.. ..#.. ..... ..... ##### ##.## ##.## .#..# .#..# .#... ..... ##### .##.# ..#.# ..#.# ..#.# ....# ..... ##### ##### ##### .#.## .#..# .#... ..... ##### #.### #..## ...## ...## ....# ..... ..... #.... #..#. #.### ##### ##### ##### ##### ##.#. #.... #.... #.... #.... ..... ..... ..... ...#. #..## #.### #.### ##### ##### ##.## ##.## ##.#. .#.#. ...#. ..... ..... ..#.. #.##. ####. ####. ##### ##### ##### ##.#. .#.#. .#... .#... ..... ..... ..... #...# ##.## ##.## ##.## ##### ##### ##### ##### ###.# #.#.# ....# ....# ..... ..... ..#.. ..#.. ..##. ..##. #.##. ##### ..... .#... .#... .##.. .##.# .##.# ##### ##### .#### ..### ...## ...## ....# ..... ..... ..#.. ..#.. ..##. ..### .#### ##### ..... .#.#. .#.#. .#.#. .#.#. .#.## ##### ..... ...#. ...#. ..### #.### #.### ##### ##### #.#.# #.#.# #.#.. #.#.. ..... ..... ##### ##### ##### .##.# .##.. .#... ..... ##### ##.## ##..# .#..# .#... ..... ..... ..... ....# #...# #...# #...# #.#.# ##### ##### ####. ####. .###. .###. .#.#. ..... ..... ..... ....# .#..# ##..# ##.## ##### ##### ##.## ##.## ##.## ##.#. .#.#. ..... ..... #.#.. #.#.# #.#.# ###.# ##### ##### ##### ###.# ##..# ##... .#... ..... ..... ##### ##.## .#.#. ...#. ...#. ...#. ..... ..... #.... #.... #..#. #..#. ##.## ##### ##### .##.# .##.# .##.# ..#.# ..... ..... ##### ##### ##### ##.## ##.#. #.... ..... ..... ..... ..... ...#. .#.#. ##### ##### ##### ##### #.### #.### ..##. ..#.. ..... ##### ###.# .##.. ..#.. ..#.. ..#.. ..... ..... .#.#. ##.#. ##.#. ##.## ##### ##### ..... ..#.# #.### #.### ##### ##### ##### ##### ##.#. .#.#. .#... ..... ..... ..... ..... #.... #.... #..#. #.##. ##### ##### ..... ....# #...# #...# ##..# ###.# ##### ..... ..... .#... ##.#. ##.#. ##.#. ##### ##### .###. .#.#. .#.#. ..... ..... ..... ..... ..... ...#. .#.## ##.## ##.## ##### ..... ..... #.... ##... ##.#. ##.## ##### ##### ####. ###.. .##.. ..#.. ..#.. ..... ..... ..#.. .##.. .###. ##### ##### ##### ##### #.### #.### #..## #..## #..#. ..... ..... ..... ...#. ...## ...## .#.## ##### ##### ##### #.##. #.#.. #.#.. ..... ..... ..... .#... .##.. .##.# .##.# ###.# ##### ..... #..#. #..## ##.## ##.## ##.## ##### ##### #.#.# #.#.# #.#.# #.#.. #.#.. ..... ..... ..#.. .##.# .##.# ##### ##### ##### ##### #.### #.### #.#.# ..#.. ..#.. ..... ..... ..... ...#. ..##. ..##. .###. ##### ..... ..... .#... ##..# ##..# ###.# ##### ##### ##### .###. .###. .##.. ..#.. ..... ..... #.... ##... ##..# ##..# ##.## ##### ##### ##### ##### #.##. #..#. ..... ..... ..... .#... .#... ##..# ###.# ###.# ##### ..... ...#. ...#. ...## #..## ##.## ##### ##### ###.# ##..# ##..# ##..# .#... ..... ..... ..... .#.#. .#.#. .#.#. .#.## ##### ##### #.##. #.##. #.##. #.#.. ..#.. ..... ##### ##### #.##. #.##. #..#. ..... ..... ##### ##### ##### ##### ###.# .#... ..... ..... ..... #.#.. ###.. ####. ####. ##### ##### .#### .#### ..##. ..#.. ..#.. ..... ..... ..... #.#.. #.#.. #.#.# ###.# ##### ..... ..... .#... .##.. .###. .###. ##### ..... #.... #.#.. ####. ####. ####. ##### ##### ##.## ##.## ##..# .#..# ....# ..... ..... ..... ..#.. ..#.. ..##. #.##. ##### ##### ###.# .##.# .#..# ....# ..... ..... ..... #..#. ##.## ##.## ##.## ##### ##### ##### ###.# ###.# .#..# .#..# .#... ..... ..... .#... .##.# .##.# .#### ##### ##### ##### ##### ###.# ##..# #...# #...# ..... ..... ..... #.... #...# ##..# ##.## ##### ##### ##.## .#..# .#..# .#..# .#... ..... ##### ##### ###.# #.#.# #.#.# #.... ..... ##### ##.## .#.#. .#.#. ...#. ..... ..... ##### ##### ##### .###. ..##. ..#.. ..... ..... ....# ..#.# .##.# .#### .#### ##### ..... .#... .#.#. .#.#. ##### ##### ##### ..... ..#.# .##.# .##.# ###.# ##### ##### ##### ##### ##.#. #..#. #..#. ...#. ..... ##### ##.## ##.#. ##.#. #.... ..... ..... ..... #.... #.... ##.#. ##.#. ##.#. ##### ##### ##### ###.# ##..# ##..# #.... ..... STOP. ================================================ FILE: exm/aoc/2024/aoc_2024_25_questions.txt ================================================ --- Day 25: Code Chronicle --- Out of ideas and time, The Historians agree that they should go back to check the Chief Historian's office one last time, just in case he went back there without you noticing. When you get there, you are surprised to discover that the door to his office is locked! You can hear someone inside, but knocking yields no response. The locks on this floor are all fancy, expensive, virtual versions of five-pin tumbler locks, so you contact North Pole security to see if they can help open the door. Unfortunately, they've lost track of which locks are installed and which keys go with them, so the best they can do is send over schematics of every lock and every key for the floor you're on (your puzzle input). The schematics are in a cryptic file format, but they do contain manufacturer information, so you look up their support number. "Our Virtual Five-Pin Tumbler product? That's our most expensive model! Way more secure than--" You explain that you need to open a door and don't have a lot of time. "Well, you can't know whether a key opens a lock without actually trying the key in the lock (due to quantum hidden variables), but you can rule out some of the key/lock combinations." "The virtual system is complicated, but part of it really is a crude simulation of a five-pin tumbler lock, mostly for marketing reasons. If you look at the schematics, you can figure out whether a key could possibly fit in a lock." He transmits you some example schematics: ##### .#### .#### .#### .#.#. .#... ..... ##### ##.## .#.## ...## ...#. ...#. ..... ..... #.... #.... #...# #.#.# #.### ##### ..... ..... #.#.. ###.. ###.# ###.# ##### ..... ..... ..... #.... #.#.. #.#.# ##### "The locks are schematics that have the top row filled (#) and the bottom row empty (.); the keys have the top row empty and the bottom row filled. If you look closely, you'll see that each schematic is actually a set of columns of various heights, either extending downward from the top (for locks) or upward from the bottom (for keys)." "For locks, those are the pins themselves; you can convert the pins in schematics to a list of heights, one per column. For keys, the columns make up the shape of the key where it aligns with pins; those can also be converted to a list of heights." "So, you could say the first lock has pin heights 0,5,3,4,3:" ##### .#### .#### .#### .#.#. .#... ..... "Or, that the first key has heights 5,0,2,1,3:" ..... #.... #.... #...# #.#.# #.### ##### "These seem like they should fit together; in the first four columns, the pins and key don't overlap. However, this key cannot be for this lock: in the rightmost column, the lock's pin overlaps with the key, which you know because in that column the sum of the lock height and key height is more than the available space." "So anyway, you can narrow down the keys you'd need to try by just testing each key with each lock, which means you would have to check... wait, you have how many locks? But the only installation that size is at the North--" You disconnect the call. In this example, converting both locks to pin heights produces: 0,5,3,4,3 1,2,0,5,3 Converting all three keys to heights produces: 5,0,2,1,3 4,3,4,0,2 3,0,2,0,1 Then, you can try every key with every lock: Lock 0,5,3,4,3 and key 5,0,2,1,3: overlap in the last column. Lock 0,5,3,4,3 and key 4,3,4,0,2: overlap in the second column. Lock 0,5,3,4,3 and key 3,0,2,0,1: all columns fit! Lock 1,2,0,5,3 and key 5,0,2,1,3: overlap in the first column. Lock 1,2,0,5,3 and key 4,3,4,0,2: all columns fit! Lock 1,2,0,5,3 and key 3,0,2,0,1: all columns fit! So, in this example, the number of unique lock/key pairs that fit together without overlapping in any column is 3. Analyze your lock and key schematics. How many unique lock/key pairs fit together without overlapping in any column? --- Part Two --- You and The Historians crowd into the office, startling the Chief Historian awake! The Historians all take turns looking confused until one asks where he's been for the last few months. "I've been right here, working on this high-priority request from Santa! I think the only time I even stepped away was about a month ago when I went to grab a cup of coffee..." Just then, the Chief notices the time. "Oh no! I'm going to be late! I must have fallen asleep trying to put the finishing touches on this chronicle Santa requested, but now I don't have enough time to go visit the last 50 places on my list and complete the chronicle before Santa leaves! He said he needed it before tonight's sleigh launch." One of The Historians holds up the list they've been using this whole time to keep track of where they've been searching. Next to each place you all visited, they checked off that place with a star. Other Historians hold up their own notes they took on the journey; as The Historians, how could they resist writing everything down while visiting all those historically significant places? The Chief's eyes get wide. "With all this, we might just have enough time to finish the chronicle! Santa said he wanted it wrapped up with a bow, so I'll call down to the wrapping department and... hey, could you bring it up to Santa? I'll need to be in my seat to watch the sleigh launch by then." You nod, and The Historians quickly work to collect their notes into the final set of pages for the chronicle. ================================================ FILE: exm/aoc/2025/aoc_2025.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the Advent of Code 2025 examples. -- -- Some programs work with both HAC and "full Ada" compilers like, -- GNAT some (titled *_full_ada.adb) work only with "full Ada". -- project AoC_2025 is for Source_Dirs use (".", "..", -- For the AoC_Toolbox package "../../../src"); -- GNAT's access to the explicit version of the HAT package. for Exec_Dir use "."; for Create_Missing_Dirs use "True"; type AoC_Build_Mode_Type is ("Debug", "Fast", "Fast_Unchecked"); AoC_Build_Mode : AoC_Build_Mode_Type := external ("AoC_Build_Mode", "Debug"); type AoC_Styles_Checks_Type is ("Level_0", "Level_1", "Level_2"); AoC_Styles_Checks : AoC_Styles_Checks_Type := external ("AoC_Styles_Checks", "Level_1"); for Main use ("aoc_2025_11.adb", "aoc_2025_10.adb", "aoc_2025_09.adb", "aoc_2025_08.adb", "aoc_2025_07.adb", "aoc_2025_06.adb", "aoc_2025_05.adb", "aoc_2025_04.adb", "aoc_2025_03.adb", "aoc_2025_02.adb", "aoc_2025_01.adb"); case AoC_Build_Mode is when "Debug" => for Object_Dir use "obj_debug"; when "Fast" => for Object_Dir use "obj_fast"; when "Fast_Unchecked" => for Object_Dir use "obj_fast_unchecked"; end case; Common_Compiler_Options := ("-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatwCijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ"); -- Don't quit, write ali/tree file even if compile errors Style_Checks_1 := ("-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens "-gnatye", -- Style: check e:end/exit labels present "-gnatytc"); -- Style: check t:token separation rules, c:comment format (two spaces) Style_Checks_2 := ("-gnatye", -- Style: check e:end/exit labels present "-gnaty2"); -- Style: check indentation case AoC_Styles_Checks is when "Level_0" => null; when "Level_1" => Common_Compiler_Options := Common_Compiler_Options & Style_Checks_1; when "Level_2" => Common_Compiler_Options := Common_Compiler_Options & Style_Checks_1 & Style_Checks_2; end case; Fast_Options := ("-Ofast", "-gnatn", "-ffunction-sections"); Fast_Unchecked_Options := ("-Ofast", "-gnatpn", "-ffunction-sections"); Debug_Options := ( -- "-gnateV", -- Validity check for parameters, GNAT > 4.6, redundant with -gnatVim ? "-gnatVa", -- Turn on all validity checking options "-gnato", -- Enable overflow checking in STRICT (-gnato1) mode "-g", "-fno-inline", "-fstack-check" ); package Compiler is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Compiler_Options & Debug_Options ; when "Fast" => for Default_Switches ("ada") use Common_Compiler_Options & Fast_Options; when "Fast_Unchecked" => for Default_Switches ("ada") use Common_Compiler_Options & Fast_Unchecked_Options; end case; end Compiler; Common_Linker_Options := ("-g", "-Xlinker", "--stack=0x20000000,0x200000"); -- ^ Absent that, GNAT-compiled programs using lots of recursion -- die with error code 16#C0000005# (Windows, Access Violation) -- - no Ada exception, no trace-back... package Linker is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Linker_Options; when "Fast" | "Fast_Unchecked" => for Default_Switches ("ada") use Common_Linker_Options & ("-s", "-Wl,--gc-sections"); end case; end Linker; package Binder is -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks for Default_Switches ("ada") use ("-Es"); end Binder; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-j0"); end Builder; end AoC_2025; ================================================ FILE: exm/aoc/2025/aoc_2025_01.adb ================================================ -- Solution to Advent of Code 2025, Day 1 ------------------------------------------ -- Secret Entrance -- -- https://adventofcode.com/2025/day/1 -- Copy of questions in: aoc_2025_01_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; procedure AoC_2025_01 is use HAT; input_name : constant VString := +"aoc_2025_01"; type Rotation_Instruction is record l_r : Character; amount : Natural; end record; instr : array (1 .. 5000) of Rotation_Instruction; type Part_Type is (part_1, part_2_dumb, part_2_smart); r : array (Part_Type) of VString; n : Natural := 0; procedure Read_Data is f : File_Type; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop n := n + 1; Get (f, instr (n).l_r); Get (f, instr (n).amount); end loop; Close (f); end Read_Data; procedure Do_Part_1 is dial : Integer := 50; pwd : Natural := 0; begin for i in 1 .. n loop if instr (i).l_r = 'L' then dial := dial - instr (i).amount; else dial := dial + instr (i).amount; end if; dial := dial rem 100; if dial = 0 then pwd := pwd + 1; end if; end loop; r (part_1) := +"" & pwd; end Do_Part_1; procedure Do_Part_2_Dumb is dial : Integer := 50; pwd : Natural := 0; begin for i in 1 .. n loop -- Straightforward but unefficient method. -- This part completes in 0.47 second (29x slower) with HAC on some powerful machine. for j in 1 .. instr (i).amount loop if instr (i).l_r = 'L' then dial := dial - 1; else dial := dial + 1; end if; dial := dial rem 100; if dial = 0 then pwd := pwd + 1; end if; end loop; end loop; r (part_2_dumb) := +"" & pwd; end Do_Part_2_Dumb; procedure Do_Part_2_Smart is dial : Integer := 50; new_dial, a, b, delta_pwd : Integer; pwd : Natural := 0; begin for i in 1 .. n loop -- This part completes in 0.016 second (29x faster) with HAC on some powerful machine. delta_pwd := 0; if instr (i).l_r = 'L' then -- new_dial <- a <- b <- dial -- a, b are multiples of 100. new_dial := dial - instr (i).amount; b := (dial / 100) * 100; if dial > b and then b >= new_dial then delta_pwd := delta_pwd + 1; end if; if new_dial rem 100 = 0 then a := new_dial; elsif new_dial < 0 then a := (new_dial / 100) * 100; else a := ((new_dial + 100) / 100) * 100; end if; if b > a then delta_pwd := delta_pwd + (b - a) / 100; end if; else -- dial -> a -> b -> new_dial -- a, b are multiples of 100. new_dial := dial + instr (i).amount; if dial rem 100 = 0 then a := dial; else a := ((dial + 100) / 100) * 100; if a <= new_dial then delta_pwd := delta_pwd + 1; end if; end if; b := (new_dial / 100) * 100; if b > a then delta_pwd := delta_pwd + (b - a) / 100; end if; end if; dial := new_dial rem 100; pwd := pwd + delta_pwd; end loop; r (part_2_smart) := +"" & pwd; end Do_Part_2_Smart; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2_Dumb; Do_Part_2_Smart; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2_dumb) /= Argument (2) or r (part_2_smart) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2 (dumb algo): " & r (part_2_dumb)); Put_Line (+"Part 2 (smart algo): " & r (part_2_smart)); -- Part 1: validated by AoC: 989. -- Part 2: validated by AoC: 5941. end if; end AoC_2025_01; ================================================ FILE: exm/aoc/2025/aoc_2025_01.txt ================================================ L45 R35 R42 R33 L6 L32 R32 R10 L9 L46 R25 L32 L47 R32 L18 L18 R38 L43 R39 R6 R7 R1 R37 R7 L19 R17 L41 L9 R25 L1 R30 R16 R17 L28 L23 R45 L49 R38 R47 R25 L49 L26 L29 L40 R40 L20 L29 L20 L3 L12 R27 L27 L73 R65 L9 R25 R84 R8 R52 L65 L44 R25 R32 R38 L38 L57 L75 L38 R94 R17 R59 L57 L12 L64 L41 R74 L22 R52 R96 L96 L82 L48 L85 L39 R24 L75 R10 L85 R62 R52 R21 R15 L77 R99 R78 R50 L60 L61 R71 L93 R30 L64 R96 L819 L7 R638 R90 L71 L76 L31 L693 R44 R60 L4 R84 R382 R34 R155 L55 R124 R857 L92 R71 L651 L9 L967 L33 R72 R28 L48 L386 R978 L20 R93 L84 L33 R60 L25 R84 L17 R64 L66 L19 R19 L37 R49 L12 L40 R44 R96 R65 L65 L43 L98 R741 R814 L17 R3 R185 L85 R83 R17 L22 L2 R27 L78 R13 L678 L69 L91 R34 L34 L545 L43 R40 R98 L50 L558 R46 L95 R79 R747 L97 L25 L97 L49 R56 L44 R37 L20 L75 L33 L370 L74 R672 L10 L902 R12 R66 R43 R91 R76 L65 L11 R922 L334 L88 L17 R783 R34 R31 L43 R12 L67 L68 L2 L41 R78 R1 R83 R16 L17 R236 R81 L76 R76 L705 L345 L30 L90 R70 L763 L43 R498 L72 R36 R44 R69 R56 L61 L23 R35 R46 R78 R98 R839 L38 L87 L99 L1 R626 R62 R681 L81 L78 R878 L15 L785 R413 R787 L31 L41 R840 L68 R87 L960 L92 R65 L30 L370 L35 L4 R39 R27 R604 R70 R199 R69 R28 L49 L65 R70 R51 R39 L543 R90 R45 R15 R54 L4 L379 L21 R98 L7 R76 L767 R227 R84 R92 L30 L273 L33 L67 R46 R11 L36 R179 L264 R63 R49 R52 L52 L48 R5 L535 R530 L23 L77 R96 L40 L56 L30 L467 L63 L640 R75 L57 R80 R56 L54 L475 L25 R93 L518 L16 L126 R60 R7 L7 R7 L4 R51 R53 R369 R49 R382 R24 R76 L944 R11 L91 R169 R47 R1 L93 R18 L18 R56 R32 L88 R62 L62 R5 R17 R78 L33 R32 R13 L12 L59 L4 R90 L95 L83 R51 R34 R66 R479 R72 L51 L341 R97 R89 R80 R103 L38 L26 L63 L54 L53 L94 L86 R20 R38 L72 L319 R26 L30 R656 L80 L1 L52 L78 R78 L1 L99 L523 L50 L76 R49 R19 R536 L662 L70 R656 L79 R99 R201 R99 R82 L81 R61 R89 L50 R92 L192 L81 R75 L40 L65 R38 L27 L65 L81 R52 L11 R25 R15 L71 R36 L436 L21 L336 R72 R886 L65 L262 R46 R16 R543 R868 R32 L13 R70 R32 R47 R21 R90 R10 R105 R25 L30 L26 L373 L20 L29 R45 R3 R61 L61 R76 R538 R60 R25 L99 R215 L23 L92 L98 L87 R48 L42 R462 L95 L788 L69 L980 R83 L92 L80 L62 L21 R178 L66 L53 R85 R377 L46 L82 R28 L246 R68 R83 R17 L22 R52 L29 R9 L32 L92 L37 R29 R12 R85 L97 L34 L66 L90 R55 R12 R23 L707 L781 L12 L66 R66 R744 R19 L19 L911 L49 R38 L653 L237 R597 R89 L18 L60 L36 R94 L51 R5 L94 R36 R6 R39 L13 L26 R15 L25 L27 R58 L21 R11 L61 R711 L39 L47 L97 L878 L8 R61 R73 R22 L948 R97 L97 L55 R55 R62 L62 R79 R68 L447 R32 R81 R34 L36 L30 L716 R89 R415 L69 L37 L23 L73 L67 L85 L458 L78 L98 R10 L91 R53 R96 L85 R436 L45 R763 L18 R9 L1 L8 R11 R37 L699 R151 R64 R36 R58 R58 L14 R468 R62 R16 R52 R85 L72 R87 L687 L606 L975 R87 L19 L39 R5 R84 R50 L52 L69 R6 R50 R19 R46 L95 L62 R50 L593 L17 L64 L19 L95 R56 L966 L72 R37 R40 L45 R4 R907 L71 L95 L15 R84 R44 R11 R76 L37 R13 L92 L53 R69 R1 L14 R13 R589 L89 L569 L406 R60 R15 R57 L80 R52 L63 R34 R32 R81 R287 R58 R42 L13 R63 L50 R63 R37 L88 R88 R1 R62 L29 L60 L17 R54 L11 L71 L29 R35 L86 R58 L43 L293 R59 L106 L24 R84 R2 L26 R40 R473 R3 L397 R42 R93 L14 R96 L41 L93 L90 L76 L96 L35 R67 L60 R28 L72 R72 L85 R13 R486 R612 L26 L93 L7 R62 R17 R821 R191 R16 L69 L18 L15 R12 R18 L1 R23 L49 R62 L70 L72 R98 R87 R45 R961 L44 R37 R756 L90 R626 R28 L32 R77 R79 R91 R551 L67 L83 R452 L11 R11 R2 R98 R391 L430 R864 L26 R99 R2 R89 L89 R68 R6 R26 L428 R211 L70 R97 L10 R70 L86 R22 R45 R749 R38 R62 R94 L94 R32 R880 L19 R88 R219 R76 L43 L658 R15 R2 R8 L42 R242 L95 R97 L2 R86 R14 L46 L48 R94 L38 L69 L93 L25 R25 L84 R81 R33 R215 L445 R95 R521 R61 R523 R72 R28 R75 R98 L73 L14 L351 L63 R28 L93 R93 R97 L91 R659 R33 L98 R40 L27 R387 R77 R881 R42 L477 R77 R65 R35 R79 L460 R497 L70 R54 R95 R673 R32 L119 L81 R47 R53 R119 R46 L25 R60 R97 L44 L53 L53 L52 L87 R2 R17 L10 R568 L3 L63 R928 R318 R159 R76 R35 R146 L94 R36 R88 L2 R91 R679 L34 R55 R11 L23 R78 L76 L84 L6 L338 R83 R91 R878 R35 L49 R898 R837 R67 R96 L60 R5 R44 R837 L55 L11 L90 L696 L26 L57 R74 L63 L8 R8 R606 L6 R8 L8 R27 R54 L81 R604 L639 R66 L31 L102 L11 R95 L70 R488 L19 R381 L42 R41 L23 L704 L50 L11 R409 R44 R26 R74 L64 R938 R60 L16 R17 L99 R656 R173 L91 L40 R5 R6 R39 L656 L7 R53 R675 R29 L4 L15 L66 L54 R79 R3 R63 R21 L32 R96 L96 L53 R225 R6 R47 L22 L94 R92 L68 L32 R57 R633 R79 L69 L17 L612 L92 R83 L62 R14 R64 R27 L605 R62 R9 L13 L64 R83 L67 L91 R82 L59 L42 L494 R94 R75 L782 L93 L56 L244 R50 R86 L36 R545 L82 L63 R80 L87 L93 L23 L177 L28 R67 R361 R92 R42 R470 L4 L34 L44 R33 R45 R726 L55 R32 L15 R412 L12 L418 R30 L65 R581 R81 L12 R17 L2 R55 R35 R53 L98 L45 R797 L10 L51 L9 L182 R70 R85 L52 R52 L51 L34 R46 R15 L76 L490 R40 L50 R255 L55 L478 L94 R943 L2 L69 R11 L11 L13 R86 L59 L614 R799 L21 L55 R28 L30 R84 R74 L87 L23 L52 L61 L83 L97 L870 L6 R82 R69 R49 R65 R335 L393 R63 L70 L356 R56 R54 R78 R68 L43 L57 R51 R649 L64 R91 L63 L864 L26 R26 R21 R72 L299 R6 L26 R27 R95 L69 L74 R91 R54 L83 L54 L69 R8 R39 R57 R4 R645 R455 L194 R282 L23 R35 L47 R66 L75 R72 R3 R81 R86 R14 L780 L75 R47 R48 R60 L40 L25 L35 L411 R532 L41 L80 L31 L27 L677 R35 R68 L51 R51 L68 R32 R22 L42 R18 L30 R55 L155 L494 R161 L67 L421 R54 L97 L436 L87 R98 R689 L24 L76 L30 R27 R3 R39 L39 L502 R45 R528 R76 R53 R858 L58 R95 R18 R767 R887 L53 R3 R817 R89 R13 R55 R9 R934 L18 L16 L86 R86 R450 R31 R819 R79 R21 R66 R14 R20 R30 L30 R2 R98 L92 L98 L10 R74 L914 L64 L96 L88 L15 L839 L658 R236 L919 R53 R86 R76 R2 L18 R467 R98 R19 R97 L88 L71 R48 R14 L95 L52 L329 L28 R65 R901 L52 L930 R20 R6 L6 L64 R83 L721 L28 L70 L75 L273 R48 L753 R74 L743 L78 L26 L590 L18 L893 L20 L53 R98 R47 R655 R53 L11 R909 R69 L89 R35 R30 R4 R52 R68 R793 R87 L4 R74 R99 R31 L845 L55 L43 L57 R56 R43 L99 L98 L2 L8 R42 R66 R72 L470 L2 L6 L94 R89 R911 R18 L618 R939 L39 L45 R92 R43 L58 L932 R43 L43 L82 L68 R50 L80 L2 L69 R93 R79 R279 L6 R23 L78 R77 R384 L46 R8 L67 R40 R62 R578 L8 R91 R37 R5 R24 R349 R65 R27 R35 R78 R22 L48 L52 R98 R2 L835 L16 L49 R817 L52 R35 L8 L92 R32 L32 R87 R814 L9 L46 R72 R38 R16 R10 R25 L7 L13 R67 R2 L15 L964 L777 R1 L91 L10 R39 R62 R99 R38 R70 L13 R5 R1 L96 L5 L13 R13 R88 L15 R627 R8 R92 L1 L36 L522 L75 L66 R49 R98 L47 R72 L55 R9 L909 L519 R2 R465 L77 R33 R3 R19 L43 L15 L2 L47 L36 R73 R23 R4 L75 L25 L960 R81 R79 L60 L88 L91 L61 L4 L954 R3 L14 L42 L46 R31 R26 R51 R70 L73 L48 R94 L94 L934 R29 L55 R60 L94 R94 R871 R16 L64 R34 L57 L80 R80 L68 L27 L263 R9 L807 L442 L2 L586 L14 L25 L84 R71 R11 R89 L48 R86 R28 R89 R7 R64 R12 L67 R96 L218 R818 L29 L13 R54 L41 R69 R81 L66 L208 R24 R28 R72 R71 R29 L97 L55 L42 L83 R44 R18 L36 L941 L208 R76 L46 L37 R31 R57 R19 L12 R46 R60 R927 R33 R9 R429 L92 L91 L2 L93 L17 L759 L40 R2 R325 R48 R336 L61 L54 L34 R62 R29 L40 L38 R31 L68 L81 L13 L69 L6 L67 L85 R85 L2 R70 R701 L89 L80 R38 L38 R31 L31 R477 L77 R63 R82 R55 R167 L67 L63 R25 R938 L891 R91 R16 R91 L981 R61 L61 R74 L80 L86 L359 L63 R88 R46 R84 R8 L11 L32 L64 L331 R60 R440 L45 L806 R51 R83 L56 L82 R55 L92 R176 L93 L91 L527 L973 L41 R547 R21 R842 R49 R882 L390 R122 L97 L53 R18 R65 R30 L95 L865 L35 R80 R965 L145 L97 L97 R94 L729 R93 R89 R669 R8 L30 R72 R702 L2 L72 R183 L18 L765 L4 R80 L76 L30 L870 L521 L879 L52 R80 L45 L15 L68 L73 R1 L32 R4 R563 L63 L32 L68 L41 L76 L83 R39 L10 R71 R78 L59 R81 R43 L177 L70 L96 R66 R34 L29 R763 R66 L13 L310 L8 L66 R14 R90 R393 R5 R795 R89 R27 R670 R319 L43 L60 R743 L33 R88 R84 R281 R699 L12 R36 L56 L32 R27 L4 L40 R44 R20 R12 L1 R79 L37 R491 R9 L360 R689 R571 R89 L89 L54 R17 L63 L56 R688 L975 R343 L19 R19 L19 L77 L4 R30 R770 L84 R216 R68 L6 R57 L51 R12 L5 L348 R63 R95 L7 L132 L78 R296 R525 R79 L3 L414 L59 R2 R74 R50 L37 R87 L8 L20 R45 L970 R359 L23 L58 R850 R4 L31 R53 R99 R43 L6 R79 R284 L46 L33 R79 R992 R6 R62 R26 R921 R27 R9 L522 R79 R24 R76 R4 L32 L72 R50 L50 L50 R30 R84 R95 R41 R81 R19 R159 L22 L27 L10 R30 L30 R45 L845 L82 R31 L53 L96 R15 L43 L72 R71 L71 R54 L83 L71 L71 R871 R46 L434 L181 R81 L955 R643 R47 R53 R80 R912 L92 R76 L76 R87 R34 L502 R64 L83 L538 L962 R567 L67 L56 L76 R6 L744 L830 L17 R61 L433 L3 R8 L792 R38 L62 R29 R7 R32 L68 R56 R96 R63 L61 L77 L593 L819 L573 R841 L32 L64 R63 L51 L573 L64 R93 L29 L276 L35 R35 R3 L47 L40 L81 R65 R897 L28 L69 R21 R31 R648 L78 L22 L88 L49 R8 R98 R56 R2 R65 R8 L71 L31 R38 L87 R51 R593 L93 L77 L23 R97 L95 R55 L49 R92 R93 L95 R2 R678 R80 L65 R55 R35 R417 R928 L29 L67 L47 R15 R45 L72 R23 R64 L5 L55 L29 R28 R632 L15 L36 L57 L565 R43 L45 L97 L621 R62 L47 L53 L31 R31 R33 R12 L125 L71 L14 L35 L92 L97 R537 R86 L34 L61 L39 L363 R63 L80 L60 R40 R42 L25 L79 L738 L40 R70 R40 R624 L80 R33 R77 L82 L26 L16 R79 R721 L975 L24 R284 R15 R527 L27 R83 R17 R14 R86 L9 R9 R42 R58 R85 L420 L97 R9 L23 L1 L53 R99 L846 R995 R47 R37 R168 L46 R46 R208 R9 L10 L96 L11 L35 L44 R250 L50 L24 L63 R55 R68 R343 R84 L84 L15 L585 L713 L50 R63 R6 L6 R80 R39 R53 L72 R15 R85 L32 L210 L167 R9 L90 R15 L397 R699 R73 L89 R61 R40 R873 L985 L80 R18 L31 L107 L19 L82 R12 L35 L146 L30 L31 L69 R20 R61 L81 R23 R390 R93 L24 L576 R601 R3 R90 R6 R94 L774 R2 R281 L709 R460 R31 L46 L38 L21 R14 R14 L27 R2 R747 L297 R78 R89 R36 L599 R79 L616 R34 L40 R15 R77 L592 R67 R21 R552 L40 L12 R12 R49 R51 R7 L108 L99 L71 R71 L28 R55 L20 L907 R77 R23 R7 R47 R146 L83 R80 L97 L684 L211 R57 L62 R20 L164 L256 L22 L99 L37 L34 L70 R29 L96 R32 R45 L48 L27 R74 R70 R83 R4 L4 R14 R23 R15 L44 L8 R787 R55 R42 R82 R34 L51 L291 L58 R28 R73 L5 R4 R617 R96 L16 R903 L91 R91 R80 L41 R61 R350 R64 L992 L22 R72 R28 L78 R29 R36 L87 R12 L393 R81 L93 L8 L96 R95 R45 R12 L94 R39 L80 L77 L59 R91 R47 R478 R22 L15 R685 L76 R7 L23 R95 L95 R64 R39 L745 L11 R130 L27 L50 L62 L34 R50 R41 L95 R27 R91 L25 L93 R722 L95 L27 L44 L841 R73 L88 R36 L83 L91 R531 L49 L342 R74 R951 R73 R56 L321 L45 L45 L28 L535 R18 R185 R319 R58 R30 R741 R9 L35 R42 R51 R58 L12 R54 L203 R7 L204 L63 R34 L62 L42 R209 L27 R51 L50 L50 L59 L61 L88 R246 L97 L41 L67 R29 R16 R99 R54 L68 L63 R52 L52 R24 L24 L363 R32 R31 L18 R18 L13 L50 L37 R39 R7 L90 R80 R64 L92 L8 L581 R77 L16 L85 L95 L286 L14 R29 L58 L232 L463 R24 R76 L76 R36 R564 R26 R274 L5 L95 R61 L94 L73 R94 R12 R18 L65 R77 L55 L75 L42 L85 L73 L461 L605 L679 R8 R9 R57 R71 R49 L73 R489 L63 L2 L575 L536 R999 L32 L25 R969 R63 L730 R24 L22 R41 L76 R19 L319 R26 R883 L7 R50 R48 R43 R57 R92 L41 L23 R72 R48 R93 R4 L15 L211 L60 R230 R611 L58 R4 R69 R575 L57 L33 R30 R70 L71 R36 L170 L13 L82 L1 R34 L33 L76 L843 L81 R8 R92 L353 L1 L13 R67 L34 L4 L16 R654 R11 R89 R30 L82 R52 L45 L89 R90 L45 L31 L1 R33 L81 L31 L48 L445 L92 L15 R49 L67 L86 R90 R33 R81 R53 L41 L51 L86 L75 R749 R78 R45 R35 R93 R3 L99 L4 L33 R75 L42 R46 R97 L131 L13 R1 L58 R20 L3 R41 L33 L67 L15 R15 L30 R31 L13 L88 R66 R26 R8 R50 L41 L94 L815 R42 L34 R853 R68 L75 L76 R86 L822 L72 R75 L955 R10 L28 L81 L19 L63 R87 R904 L413 L87 R280 L94 R62 R52 L13 R13 L343 R43 L54 L546 R49 R51 L90 L97 L915 R2 R763 R20 L459 L46 L78 L28 R21 R7 L3 R3 L92 R92 R53 R30 L283 R46 R69 R42 R43 R37 L49 L87 R30 L28 R44 R53 L77 R93 R34 R50 L667 R467 R15 R73 L74 L63 L19 L46 L1 L85 R42 L542 L34 R90 L76 L636 L490 L11 L12 R13 R56 L68 L27 L25 R93 R55 L94 R66 L18 L404 R322 L842 L59 L6 L41 L62 R40 L54 R24 R102 L48 R93 L47 L70 L30 L41 L59 R19 R16 L61 L37 R87 L70 L54 R6 L421 R73 L58 L88 R52 L973 R9 R830 R70 L55 L94 R439 L49 R54 L27 L234 L7 R73 R72 L62 R504 L96 R590 L8 R66 L96 L73 R179 R18 L28 L325 R59 R33 R79 L986 L826 L18 L82 L65 R428 L63 R38 R1 L22 L17 R16 L25 L42 L45 L269 R31 R92 L63 R42 R63 L26 R26 R7 R71 R85 R118 L26 R11 R34 L25 L82 L493 L90 R88 L62 R47 L26 L1 L869 R13 R4 L9 L19 R6 L81 R92 R16 L8 R899 L259 L41 R26 R74 L554 R54 L59 L41 L50 R42 R32 R3 R73 R5 R93 L92 L6 L89 R89 L743 L26 L231 R18 R82 R28 R29 R143 R57 L74 R17 R20 L75 L21 R76 R60 R239 L43 R44 L244 L17 R161 R36 L31 R47 R390 L42 L209 L78 L54 L307 L47 L5 R53 L53 R481 R6 R13 L725 R25 R28 L33 L95 R69 R31 L42 R18 R62 R62 L182 R78 R4 R496 R4 L401 R1 L25 R325 L31 L54 L44 R87 L443 L35 R55 L35 R24 R88 R33 R87 L86 L18 L95 L7 R99 L87 R62 L36 R31 R9 R93 R703 R68 R53 R1 L28 R62 L341 L2 R87 R92 L92 R49 R51 R44 R56 L768 L287 R28 L19 R46 R168 L4 R636 L4 L28 L45 R77 R76 R99 R74 R92 R59 L41 R34 L22 L318 R18 R3 L7 L509 L58 R31 L81 L98 L206 R54 R995 R505 L699 R99 L947 R6 R32 L66 L23 R9 L214 R3 R558 L67 R41 L32 L54 L51 R28 R77 R82 R18 R638 L38 R20 L63 L89 L218 L750 L31 L69 L90 R19 R49 R86 R36 L71 L9 L36 L57 R73 R23 L323 R63 R37 L74 L226 R4 R21 R69 L94 R559 L70 R86 L75 R9 R26 R76 R98 R91 L518 R64 L10 R164 R788 L988 R92 L594 L62 L36 L8 R108 R26 R82 L33 R12 R413 R834 L749 R47 R68 R516 L43 R715 R881 L69 R915 R85 R17 R450 R20 R13 R80 L80 L26 L213 R403 R36 R49 L24 L77 L49 R8 R79 L46 L40 L844 L363 R18 L444 R33 R65 L833 L963 L69 R71 L71 R83 L7 L88 L186 R592 L14 R38 L18 L58 R58 L31 R22 R582 R27 L72 L41 R56 L43 L67 L33 R93 L93 R59 L59 R30 R38 R47 R43 R42 L63 L837 R77 R59 R37 L73 L99 L1 R79 L494 L59 R74 R61 L911 R50 L39 L16 R122 L68 R1 L48 L930 L22 R10 R90 L8 R6 L635 L38 R75 R26 L80 R81 L27 R414 L73 R57 L62 R664 L151 L35 R86 L79 R37 R14 R20 R32 L8 R20 L36 L809 L98 L41 R62 L72 L36 R94 L65 L835 L86 R78 R39 R76 R971 R22 R9 R91 L50 L99 R49 L73 R43 R30 L393 L40 R33 R12 R71 R108 R45 L718 R69 L87 L144 R11 R16 L97 R14 R896 L80 L16 R40 R11 L28 R9 L63 R59 L377 L51 R63 L42 L821 R35 L35 R69 L49 R16 L36 L88 R3 R685 R98 L77 L67 R46 L59 L31 L13 R3 R81 L33 R49 L84 R587 R97 R58 R590 R19 L15 R60 R91 L55 R85 R2 R22 L954 L77 R72 L53 R58 L11 R711 L64 R71 L7 R710 R490 L74 L11 R98 L79 L83 L51 R60 R802 R38 R737 R468 L11 R13 L9 L990 L87 R96 R371 L2 L386 R19 L19 R80 R18 R35 L95 L12 R20 R33 R21 R15 L615 L14 L31 R12 L67 L358 L42 R42 L42 R7 L6 L55 L48 R7 R34 R211 R28 L86 R2 L494 L50 L56 L20 L29 L45 R56 R94 L91 R777 L36 R47 R53 L385 L15 R16 L16 L43 R43 R36 R43 R21 R38 L31 L314 L42 L51 L8 L56 L519 L17 R168 R810 L17 R64 R75 R24 L605 L76 R57 L64 L36 R9 L9 R78 R22 R70 R985 L55 R8 R92 R283 L83 L32 L778 R74 R1 L65 L97 L903 L958 R6 L948 L13 L63 L24 R273 R27 L74 L26 R81 R11 L50 R664 R694 R34 L34 L18 R73 R60 L15 L89 L11 L8 L92 L31 L559 L78 R68 R52 R95 R92 L15 R38 R38 R43 L22 R79 L72 R43 R50 L21 R42 R58 L93 L7 R15 L15 R78 R89 R53 L23 L54 R57 L629 R8 R38 R926 L953 L286 L21 R17 R55 R67 R178 L13 R113 L53 R50 R73 L70 L26 R1 R22 L97 L823 L91 R56 R13 L42 L13 L52 R17 R245 L23 L143 R92 R64 R206 R15 L21 R83 L50 L21 L17 R47 R68 R90 R48 L44 R831 R917 R48 L56 L914 L30 R64 R218 R18 L414 R58 R850 L490 R96 L903 L75 R78 L26 L81 L90 R8 R33 R931 R625 L68 R77 L9 L543 R25 L682 R31 L31 L685 L15 L66 R91 R63 L46 L42 L28 L1 L22 R92 L865 L95 R781 R82 R72 R59 R98 L753 L19 R56 L157 L13 R13 R18 L55 L65 R21 L910 L9 L40 L159 R99 L75 R75 R47 R96 R57 L92 L71 R63 R59 L49 R90 R81 R19 R84 R16 R94 R6 L549 R477 L32 L43 L68 R70 L55 L23 L77 L1 L85 L14 R37 R6 R3 R27 R37 L75 L769 R94 R540 R72 L965 R85 R8 R79 L33 L28 L84 L10 L24 L79 R498 L19 L15 R14 L94 L482 L64 R252 L11 L93 L7 L591 R540 L75 L65 R91 R42 L42 L72 R72 L94 R19 L25 L21 L57 R22 R856 L17 L83 R439 L39 L92 R80 R78 R844 L45 L42 R477 R92 R5 L97 R57 R143 L73 L89 R59 R3 L76 R76 R816 R29 L28 R53 R36 L39 R25 R979 L6 L54 R47 L440 R82 L430 L9 R332 L1 L92 L50 R26 L76 L565 L27 R711 L46 R17 R29 R81 L64 R96 L38 R6 R96 R67 R93 R44 L36 R436 L184 L27 R11 R97 L55 R81 R37 R40 R521 R779 R94 R45 L65 L71 R71 R26 L737 R37 L94 R68 R81 L580 R886 L73 R728 R84 R9 L586 L95 R30 L1 R94 L95 R83 L9 R70 R21 L821 L15 R15 R33 L33 L74 R58 R16 L718 L26 R544 R64 L64 R930 L18 L12 L56 R53 R67 R236 L534 L95 L57 R60 L74 L848 L201 L60 R73 L740 L85 R13 L91 L61 L502 R51 R96 L45 R18 R82 L952 R36 R16 L56 L417 R17 R51 L54 L41 R94 L929 R35 R13 L613 R312 R99 R51 L17 L866 L679 R594 R6 L22 R32 R90 R19 L54 L341 L87 R63 L38 R38 L5 R5 L84 R62 L5 L25 L70 R22 L358 R58 L10 L41 R51 L63 R63 R87 R99 R24 L76 R94 L28 L73 L27 L26 R29 R10 R87 L24 L60 R84 R55 L54 L99 R72 L38 R64 R22 L37 R15 R940 R60 L88 R39 R7 R15 L73 R743 R60 R35 R26 R66 L22 R70 R23 L609 R8 L737 L63 L81 R25 R74 R82 R36 L51 R28 L21 L30 R538 R656 R40 L96 R66 L52 R29 R202 L76 R31 R73 R37 L734 R24 R77 L77 L68 R54 R7 R98 L91 L32 L49 R11 L4 R43 R80 R2 R20 R653 R89 R787 L11 L17 R28 L59 R59 L82 R75 R35 R70 L898 R198 L79 L27 L92 L13 R35 R534 R12 R58 L26 R386 L27 L12 R80 L83 L30 L17 L54 L43 R77 L77 L38 L962 R96 R451 R61 L8 R962 L94 L68 R64 R36 L14 L11 R15 L12 L62 R985 L25 L76 L51 R34 R217 R61 L913 R52 R86 R11 L69 L18 R90 L379 L70 R92 R57 R9 L81 R37 R35 R92 L5 L63 R776 L611 L585 L60 R79 R15 L923 L92 L97 R37 L85 R19 R703 L81 L60 R962 L96 L897 L28 L155 L45 L18 R61 R793 R49 R522 L31 L176 L3 L33 L89 R861 L40 L22 R35 R91 L40 R40 L1 L32 R51 R36 L546 L50 L90 L468 L76 R76 R87 L184 R90 L76 L17 L82 L79 L913 L77 R80 L29 L95 L58 R53 R52 L68 R92 L50 L39 R213 L99 L1 R845 L45 L94 R99 R31 L37 L95 R96 L94 R67 L673 R24 L24 L26 R823 L397 R93 R48 R69 R90 L82 L6 L62 R50 L17 R117 R10 R658 R846 R59 L5 L68 R42 L48 R5 L99 L839 L49 L137 L75 L47 R47 R68 L68 L108 L64 L28 R43 L43 L6 R6 L21 L611 L568 R33 L25 L8 L37 R35 L53 L18 L90 R875 R88 R69 L69 R498 L98 L33 L67 L448 R3 R40 L81 R74 R15 R72 R625 L86 R86 R4 L78 R92 L96 R20 R58 L2 L98 L20 R86 L16 L21 R22 L92 L59 L3 R98 R5 L61 L80 R58 L17 R73 R90 R3 R4 R97 R33 L32 R72 R20 R49 L14 L95 R53 L53 R93 R7 L17 R33 R56 L22 L49 L81 R80 L93 R58 R35 R70 L18 R33 R10 R21 L40 R8 R11 L2 L3 L45 L30 L3 R5 L46 R37 L25 R16 R9 R9 L40 R6 L6 R26 L44 R27 L47 R25 R20 R30 R28 L45 L33 L42 R18 R34 L14 L37 L43 R25 R28 R26 R31 R6 R21 R28 L40 R5 L39 R13 L7 L35 ================================================ FILE: exm/aoc/2025/aoc_2025_01_questions.txt ================================================ --- Day 1: Secret Entrance --- The Elves have good news and bad news. The good news is that they've discovered project management! This has given them the tools they need to prevent their usual Christmas emergency. For example, they now know that the North Pole decorations need to be finished soon so that other critical tasks can start on time. The bad news is that they've realized they have a different emergency: according to their resource planning, none of them have any time left to decorate the North Pole! To save Christmas, the Elves need you to finish decorating the North Pole by December 12th. Collect stars by solving puzzles. Two puzzles will be made available on each day; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck! You arrive at the secret entrance to the North Pole base ready to start decorating. Unfortunately, the password seems to have been changed, so you can't get in. A document taped to the wall helpfully explains: "Due to new security protocols, the password is locked in the safe below. Please see the attached document for the new combination." The safe has a dial with only an arrow on it; around the dial are the numbers 0 through 99 in order. As you turn the dial, it makes a small click noise as it reaches each number. The attached document (your puzzle input) contains a sequence of rotations, one per line, which tell you how to open the safe. A rotation starts with an L or R which indicates whether the rotation should be to the left (toward lower numbers) or to the right (toward higher numbers). Then, the rotation has a distance value which indicates how many clicks the dial should be rotated in that direction. So, if the dial were pointing at 11, a rotation of R8 would cause the dial to point at 19. After that, a rotation of L19 would cause it to point at 0. Because the dial is a circle, turning the dial left from 0 one click makes it point at 99. Similarly, turning the dial right from 99 one click makes it point at 0. So, if the dial were pointing at 5, a rotation of L10 would cause it to point at 95. After that, a rotation of R5 could cause it to point at 0. The dial starts by pointing at 50. You could follow the instructions, but your recent required official North Pole secret entrance security training seminar taught you that the safe is actually a decoy. The actual password is the number of times the dial is left pointing at 0 after any rotation in the sequence. For example, suppose the attached document contained the following rotations: L68 L30 R48 L5 R60 L55 L1 L99 R14 L82 Following these rotations would cause the dial to move as follows: The dial starts by pointing at 50. The dial is rotated L68 to point at 82. The dial is rotated L30 to point at 52. The dial is rotated R48 to point at 0. The dial is rotated L5 to point at 95. The dial is rotated R60 to point at 55. The dial is rotated L55 to point at 0. The dial is rotated L1 to point at 99. The dial is rotated L99 to point at 0. The dial is rotated R14 to point at 14. The dial is rotated L82 to point at 32. Because the dial points at 0 a total of three times during this process, the password in this example is 3. Analyze the rotations in your attached document. What's the actual password to open the door? --- Part Two --- You're sure that's the right password, but the door won't open. You knock, but nobody answers. You build a snowman while you think. As you're rolling the snowballs for your snowman, you find another security document that must have fallen into the snow: "Due to newer security protocols, please use password method 0x434C49434B until further notice." You remember from the training seminar that "method 0x434C49434B" means you're actually supposed to count the number of times any click causes the dial to point at 0, regardless of whether it happens during a rotation or at the end of one. Following the same rotations as in the above example, the dial points at zero a few extra times during its rotations: The dial starts by pointing at 50. The dial is rotated L68 to point at 82; during this rotation, it points at 0 once. The dial is rotated L30 to point at 52. The dial is rotated R48 to point at 0. The dial is rotated L5 to point at 95. The dial is rotated R60 to point at 55; during this rotation, it points at 0 once. The dial is rotated L55 to point at 0. The dial is rotated L1 to point at 99. The dial is rotated L99 to point at 0. The dial is rotated R14 to point at 14. The dial is rotated L82 to point at 32; during this rotation, it points at 0 once. In this example, the dial points at 0 three times at the end of a rotation, plus three more times during a rotation. So, in this example, the new password would be 6. Be careful: if the dial were pointing at 50, a single rotation like R1000 would cause the dial to point at 0 ten times before returning back to 50! Using password method 0x434C49434B, what is the password to open the door? ================================================ FILE: exm/aoc/2025/aoc_2025_02.adb ================================================ -- Solution to Advent of Code 2025, Day 2 ------------------------------------------ -- Gift Shop -- -- https://adventofcode.com/2025/day/2 -- Copy of questions in: aoc_2025_02_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; with Interfaces; procedure AoC_2025_02 is use AoC_Toolbox, HAT, Interfaces; input_name : VString := +"aoc_2025_02"; first, last : array (1 .. 100) of Integer_64; n : Natural := 0; r : array (Part_Type) of VString; procedure Read_Data is dummy_separator : Character; f : File_Type; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop n := n + 1; Get (f, first (n)); Get (f, dummy_separator); Get (f, last (n)); exit when End_Of_File (f); Get (f, dummy_separator); end loop; Close (f); end Read_Data; procedure Do_Part (part : Part_Type) is invalid : Integer_64 := 0; procedure Check (x : Integer_64) is original : constant VString := Image (x); pattern, constructed : VString; total_len, total_len_new : Natural; begin for len in 1 .. 1 + Length (original) / 2 loop pattern := Slice (original, 1, len); constructed := pattern; total_len := len; Repeats : loop total_len_new := total_len + len; exit Repeats when total_len_new > Length (original); constructed := constructed & pattern; total_len := total_len_new; if constructed = original then invalid := invalid + x; return; end if; exit Repeats when part = part_1; end loop Repeats; end loop; end Check; begin for i in 1 .. n loop for id in first (i) .. last (i) loop Check (id); end loop; end loop; r (part) := Image (invalid); end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin if compiler_test_mode then input_name := +"aoc_2025_02_mini"; end if; Read_Data; Do_Part (part_1); Do_Part (part_2); if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 55916882972 (mini: 1227775554). -- Part 2: validated by AoC: 76169125915 (mini: 4174379265). end if; end AoC_2025_02; ================================================ FILE: exm/aoc/2025/aoc_2025_02.txt ================================================ 8123221734/8123333968,2665/4538,189952/274622,4975/9031,24163352/24202932,1233/1772,9898889349/9899037441,2/15,2147801/2281579,296141/327417,8989846734/8989940664,31172/42921,593312/632035,862987/983007,613600462/613621897,81807088/81833878,13258610/13489867,643517/782886,986483/1022745,113493/167913,10677/16867,372/518,3489007333/3489264175,1858/2534,18547/26982,16/29,247/366,55547/103861,57/74,30/56,1670594/1765773,76/129,134085905/134182567,441436/566415,7539123416/7539252430,668/1146,581563513/581619699 ================================================ FILE: exm/aoc/2025/aoc_2025_02_mini.txt ================================================ 11/22,95/115,998/1012,1188511880/1188511890,222220/222224,1698522/1698528,446443/446449,38593856/38593862,565653/565659,824824821/824824827,2121212118/2121212124 ================================================ FILE: exm/aoc/2025/aoc_2025_02_questions.txt ================================================ --- Day 2: Gift Shop --- You get inside and take the elevator to its only other stop: the gift shop. "Thank you for visiting the North Pole!" gleefully exclaims a nearby sign. You aren't sure who is even allowed to visit the North Pole, but you know you can access the lobby through here, and from there you can access the rest of the North Pole base. As you make your way through the surprisingly extensive selection, one of the clerks recognizes you and asks for your help. As it turns out, one of the younger Elves was playing on a gift shop computer and managed to add a whole bunch of invalid product IDs to their gift shop database! Surely, it would be no trouble for you to identify the invalid product IDs for them, right? They've even checked most of the product ID ranges already; they only have a few product ID ranges (your puzzle input) that you'll need to check. For example: 11-22,95-115,998-1012,1188511880-1188511890,222220-222224, 1698522-1698528,446443-446449,38593856-38593862,565653-565659, 824824821-824824827,2121212118-2121212124 (The ID ranges are wrapped here for legibility; in your input, they appear on a single long line.) The ranges are separated by commas (,); each range gives its first ID and last ID separated by a dash (-). Since the young Elf was just doing silly patterns, you can find the invalid IDs by looking for any ID which is made only of some sequence of digits repeated twice. So, 55 (5 twice), 6464 (64 twice), and 123123 (123 twice) would all be invalid IDs. None of the numbers have leading zeroes; 0101 isn't an ID at all. (101 is a valid ID that you would ignore.) Your job is to find all of the invalid IDs that appear in the given ranges. In the above example: 11-22 has two invalid IDs, 11 and 22. 95-115 has one invalid ID, 99. 998-1012 has one invalid ID, 1010. 1188511880-1188511890 has one invalid ID, 1188511885. 222220-222224 has one invalid ID, 222222. 1698522-1698528 contains no invalid IDs. 446443-446449 has one invalid ID, 446446. 38593856-38593862 has one invalid ID, 38593859. The rest of the ranges contain no invalid IDs. Adding up all the invalid IDs in this example produces 1227775554. What do you get if you add up all of the invalid IDs? --- Part Two --- The clerk quickly discovers that there are still invalid IDs in the ranges in your list. Maybe the young Elf was doing other silly patterns as well? Now, an ID is invalid if it is made only of some sequence of digits repeated at least twice. So, 12341234 (1234 two times), 123123123 (123 three times), 1212121212 (12 five times), and 1111111 (1 seven times) are all invalid IDs. From the same example as before: 11-22 still has two invalid IDs, 11 and 22. 95-115 now has two invalid IDs, 99 and 111. 998-1012 now has two invalid IDs, 999 and 1010. 1188511880-1188511890 still has one invalid ID, 1188511885. 222220-222224 still has one invalid ID, 222222. 1698522-1698528 still contains no invalid IDs. 446443-446449 still has one invalid ID, 446446. 38593856-38593862 still has one invalid ID, 38593859. 565653-565659 now has one invalid ID, 565656. 824824821-824824827 now has one invalid ID, 824824824. 2121212118-2121212124 now has one invalid ID, 2121212121. Adding up all the invalid IDs in this example produces 4174379265. What do you get if you add up all of the invalid IDs using these new rules? ================================================ FILE: exm/aoc/2025/aoc_2025_03.adb ================================================ -- Solution to Advent of Code 2025, Day 3 ------------------------------------------ -- Lobby -- -- https://adventofcode.com/2025/day/3 -- Copy of questions in: aoc_2025_03_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; procedure AoC_2025_03 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 15; input_name : constant VString := +"aoc_2025_03"; n : constant := 100; r : array (Part_Type) of VString; procedure Do_Part (part : Part_Type) is bank : String (1 .. n); f : File_Type; jolts, total, max_n, pos, d, digits_amount : Natural; begin total := 0; Open (f, input_name & ".txt"); case part is when part_1 => digits_amount := 2; when part_2 => digits_amount := 12; end case; while not End_Of_File (f) loop Get (f, bank); pos := 1; jolts := 0; for rest in reverse 1 .. digits_amount loop max_n := 0; for k in pos .. n - rest + 1 loop -- We always need the highest possible n-th digit. -- And, the first occurrence of it is always the best: you have -- more choice for the next digit. d := Ord (bank (k)) - Ord ('0'); if d > max_n then max_n := d; pos := k + 1; end if; end loop; jolts := jolts * 10 + max_n; end loop; total := total + jolts; end loop; r (part) := +"" & total; Close (f); end Do_Part; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Do_Part (part_1); Do_Part (part_2); if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 17613. -- Part 2: validated by AoC: 175304218462560. end if; end AoC_2025_03; ================================================ FILE: exm/aoc/2025/aoc_2025_03.txt ================================================ 5435113354324445355543423523324245133533362334234141663246333323544553332443432533433423343343453463 1233344353772433633431345263345236724342224345344274554423535244944463342134833266322656314543515475 5576745375324233563243233436732333523533636533753554414665233366234224423732347223363713264622236523 5222525121222422563623622342122222236224232431233222533412222434244222222262316223222221232342213323 4435354664423232224355463421531435433224734524344224733444432436344243244533362444545674243542634543 4522223113123312224212222214121243522823123223524255222321162314152221321122221252541223223242221222 7715743377257934377437237862344454824443325453755356866767684636467643544764752724362417343657567342 6523864515231325622456222644174686462454428234444724653576263285224336446352253264246244362929656426 3466625654666454445665346665665566663732483655475855164647326366527566566576544415865645575644536643 1122223224244222152222512545122212231222232225321122221142122212232222972214212121252221221222242212 6534268233326239326648265632335833323223473631923422723291654523333235236322423363342536153322378532 4555732424665482324835745822333631633662252934516556533232242524111354282289422476516222469234477234 5255425253426533545444555452546163525345456341782353554252552254425252815554455314542525554524443323 2222332232222333253221233222422237322333323392322322332432923322222322243222233322142243322343322222 3223324233332323233331332231233432334433324222133313332122242331723132231233223433224333352333331333 2224221562223224212221221222211321422221112422233232122222222422222222211422423222222232232221222224 2121353331232222324224322223222322214432232232425224423312121143432222225225213227244425428223234442 3234233235333632753353333333353443133453342443233344543333423321334414534334533222421213323234333435 2233222122322234444342132337329431322374222124134233214351233243123356375442213234123432433445422447 5657353272375262725544726457535473426755734112433642575265223147226544316261275624736211753727152289 3622453333455615313535433655542422333436542533364235535441325345214445441345553426543422433444525443 4223235316324333322242343433353133233232422632272221443321633233443433346133232424672433343342333343 2633323323234534236333623333231383322237233323613341113123322463235435374462643925254353223449625333 4442214735222532221438725223533336343336321323222434383443322223434327255131333142255253243443232335 5563487886335668666493846844554285575656758566669368646867373678668657565486656866535846283366546865 3228253234225312424353215214532221422322331222412232113232224224222362415222243342343223118433422314 3435363333233337453396343373348343427893363353369344243243325493323333436842339593335318333393552322 3222224452224155723555286536491525222352645618332474753245446634235343235355696244573463247423542633 7343454543352456557554525555524355335555433434445555553754535534456464535654565553345333534455555555 4333133331321433343233254233333333332233315323233343123343435333232434334334233373322334313353323323 2212322122212222122332314123222222122221222224233324212322332412222222522242221422322121222342123322 2721232121354232244426234143554822344132544338463131422132316223221228422243143322122332282222615742 2123226223122322213721223222281212622222365421224133222222224212147729423252222634272233243222224122 8225444321227231186352525234212242556552221443231635325642443523412463536763524265133344424724433342 4333442233124833223436324123232243531342133433224442534433395326333321343432233234133221323434333333 5352445253512235254443446435333455241543543463453243415533345853464462334353543335454274434554245413 4342222333222552432344333226352334325633232224232352515784433423322242855223332546543524165246342232 4223344323422223336343262363372316345322453232533333234334234663643424346423333242415653353424234253 6263428246423623363264635654526226372222142355668223314566214265246312541261245543227662623653454362 2273336331272235254713332422332643342223343333332332122314226323332345323582253242445223323322245231 4322234845232662236324224322182245247244367242522424212234232422723218198225222915521222268564411521 3433253332333532345333323422433233423243313324333631254243244255333253113363285452224245324232232235 1143492333422423336912623553424421324742531223446629632732242332333351329224544322343972221431323364 3342424231333335733152322226323124214225367372627223275332422333413352564363432246323232215433252153 5587829445884636482654145646782533363348738488965858788843452546373544894477994653421555279386445548 2312325132575255433332362232222542242333723534452522572563552254242525534341234533333233334356225351 2331122213133321222223232222322332322312332232222233522271233231332232312222241223333113223222422223 3534325413554232325254512334336633252323573674321152427628233553273152333233122822353523483332725543 2222722322222213322222212222222122221222225222221222113251223212112111122123121222222322232122222242 5652234232663254118444532444552564425764453426742955425324162723845341436551358415354422522433432538 2932122232253211521222132232232122322333232125423231222322332323332232123223322233222222212422332252 7253223242547732357534512342433333233357423332342332433343335343335333343433452143834333361533352444 2222242211224427263221122213221423252222211237422222223824212612224422441633222222223322722312123422 1122242322422227124312493231242262322237183233234627223323235223222232252211432135322322252423222522 5513625653443564554544344548444541545526656445244544545145456455355534545535718246455415357363556546 1222228264622222463264252352326422143123231223143321435422225412221242221322136231143254124622823234 4668655544562525244555555544446946543646543355559525455645534443552558655353454153564261573555554336 2226252126147222222251281225222225225244522425263222212622213313222212132223223423221142432221322231 5332537364333222353314336342213343762334364344343343394342443142523434334612433445942634344332233678 1344233339652845433647536439442146443343744444322363643731834964839444264654262944433343433826243433 2781552142222524723162423423633311152243332625235412335422524232332254233222525211251424311252112165 2333633213542313212234421262313265392221232353422523221333725322252342421521522223433331353155223333 6544843557445454477544654583334434553455434445755275835548425348455674843754457238464753439339545443 2225176232246822422522222662292212683372222835212732945285522562265232933535122252663386222634521223 3648323653333216232535332325333533342283232533322353233227432452713234332339213552328322226323323323 5633646655526971582281363775455439333363266535582936666553663763728566456535855129699264355358363534 4232433332333242293431232133222121322223222132332323222182321222262323223231121322333321233223232222 4344655422352142552342346612445323644352236344423264345233324253246254343342853322643334364544265443 1222222422242421244263322222431244361323314122322332321232332222342282122343124252863343371223323234 2233234232231314332243323331333231661223222322232224323223223312224212643432331222221325212314321223 4585424333435123142334435344324333574424332335462323548645541234334448243435664387123224234252834335 4353263232264352321123922232651211342343131233335433334436323121224122132246123222233533225324441326 2342322432223332233223382322453263222224411331223342323224222123326222632133222212323223343232212231 4434733735542454444153446353344654324426337649333636353744513333334863333275429244556244247635232724 4334741434328231357433211143614362384322446224492442232224342244243713344422143443333243324316234423 2552111222222443333241232223126232322722223251122242211623324431222166622222222237523214222232623282 4444454545455444555446543543474515654454445254425425145346556442233235555453445545434545555435247463 2222222223222232221122222221123215122221222112212212222222123251222222222132222222232212222132232632 5453569247722653252223751462234539228856835215912364562123224222422532666382422243732223234644437564 3513532323323333532325333232332223923634433433333433352343254253332535233334324442333323423233323322 1232226215227211127143232324662232312221153212282442254222135122522221223552211222215262222222643221 3373363325372233496622336333343338425322233643333323333643232932333339326234243733431313333335333233 5262252725375673844565695677452742643652556466757653467842466346476564477365286656766645476936777773 4973939623777674483526515657982389568693527229486547957994869795857776395649577557776894577538959518 4336244332323333333323333343333133432233343362142233432223213333933343234243242333424423234242332343 3444444223424334144244429344324944434344434544354433443442344434343452344445344322344635443444493344 3134521222132222522523312211223521422272411223212322222223243263543224221223252222221432422421443153 6272924132234218127342331776264225555237327229315115823162121273732437124425493327441532325337425174 5444223542325425263316442615743475443122663533254273433623144442223422522424442444624443346522116444 9233225522332222321253326264423823733236476632624235521362112522232342422222123223522375134323227323 7255323516928543264677235524667867238278726776253467657396529967766779551356475764333433375547256665 2525472336544743374233436955267423422865435344464666322481446384332154333423364636534222723428328743 2314335931264432514533231544626253323363453223644332346364434658435335442643732654332327244329373247 3252352322313255332322123222422331355322232322622233333332333234152243332235723329332243121222323234 2272313213422153212211222262222221422423322513322233212313322133223321222114432322422352321231322221 2774253153222333243133353233546433372434253323657733732323333133433252234323335311565654323333333133 2223232131222421229222225423221222254332422222231323234229213122222215342755342337122332332333322225 3573532537264315533523224443354666214638246321444334459334465233632455631725246534552945844826253572 3444756323537363556473235735567622746225263423552566645533552244533564224743536342534664662627337862 1555336343554522213334442333353343759485347445426524533942563425323255845145535354323433263345653453 4461384744645548434423434448454466534444424844494144363466424347478484433781448425434838434423842743 7621285337423873536653937774342223274456333763347273384742335728658544332388467665374434547784345814 5633233233232332334232332333223333332333333332333373333332333323333343322343233442323333335353311332 3231211324231444321523322222322423443224224223221222334222552222522333244422223345352341421222242242 4553354423444151311141144535243411314142443545545252145415445554223341551441145244122143242312336789 5765565899996897799687787574486889887452869954459964296566698748644956887995746559946786584673999966 7946769529775566672759756265976475746769585777765755555579455668646858686768566744675485479575765575 6421524236223452962453524162367626796541132586422323734221212617537753232425315524231322722532765252 2123125234345422522337352225553352523241234312232225221113222251134563333114423454272522245334333342 2241323413334212324373343923342335312122214739252312235313342232231348323233333344333432743445429636 4223233223153822333323322443314762442355223443444233432463323332533422113313524353435427434376312231 4215422122222151725111222211224451212122242252121611223222232225232422222123222222262212224121431221 2413214275164556258388122372217112266222232522222266142222224212111252351223425122224152526223212846 1323636363685335369223652333465762165568722532352251552382145357234293353563233532222433374335623365 3442425244554423133535453555423545252153443442222543544244425546464553532425454515553435454435442453 3745545555562535543645555446454433553535594566525577454634524446475546755553445654554445545555445455 5616268445219212622135525627573525824722682234476427236414263262292667744321525113564225627522762223 3122241222231222332212322242232224123222223212432242112222222212222243212221312222132224132342222224 5235464435334631424362246264134234334673344436523552323544242334322344523343453422365447321473433345 1224224224322222152218122222432132439826224269283291242432225122222271846158526211214228522926362492 4522345233524223213497361443343144233434432233242434967323442443244333637533143434111412453413274443 1334332444354334413433144333313732344432234443345132261223333131324343213234422132233132334333232423 2525527445536165529424545542423125262243442255135552522742443535424521462323442552421334344444155234 2323522233242652331114234233324132172222222232132222243222222332532422332317273323623213434232232223 3484655554943975444624244445443468352345344933455434414648544483446433456463525733546333344446488665 5565562332353673457513264254523646353325333422554652452235525285456236946425443525564653226536425512 8616225642214422558634267662262565424543462453368356272861513564575263632632616422323232661343285438 6333224463434353443335332333433323334333435243243344333331323431436333337323334325232334634234332443 1233222334412421444424144343131231414221443422441221213322143421443143334243421243222223431142256789 2212223525232234223415253222234233363232352331353632533223322333233563333223335332222442131242132173 3816323383284643928733322242344833684774363323343232536384342363537353134331331334352373224323423333 6447955463327313384577448539764343367429555473755247738464358653477334343945547838875456754784823363 5434244323433433434343563364819474374543273633435344824232473244334642337428465423344423353434434432 7442353261225224522233323727572533332445331623222295232752228372231217852632161238231232436342232232 4526223432124145422142222124182121671242223222412363212524223173261245333435214641242663245322223521 4263562733555685663522242313434726124643355533558226544138654644475352425436253456366735666544332657 4341315536331534333454535744123633456334333453636333736334424533343432424333345656476243523443763633 1324343444393434423414443244234444453535444644449544444253433444534446244451456464424434443433363252 2112224231241221222232222222422134222222132122231312132242122221213224222242222222342222232122211528 4385535213555333232225523228265793216328622226632332472262222222512265533322225342324275352223326143 5243532545945342334345364434154433431494628952782552473755525425725244643565443433826551333322254353 4223212323322422243324113232221222223231233112242232321622231332222222222233254422222326224222342232 3332255342242343826166532324242524432445172341231245387335235422322763423221467272263529933268437351 1542466264121455566412665243646411646141116516454156662516544663655241155331421243266641413226665789 5554455445427145865432355555555547145442454345543745554534654333235553533256845325355455535262245524 2354232552352524723356231424552455123563645522461245542424544242444233335463442422432552432454523532 4316625313325234514328252432321244774244214583222554353534735222834347321373732211464264412343722652 2124923223212136421292213223223282224332281722423725222215376282163226251235212313228726112233226922 7437652335153364536533537533545238334435524343424523463631142485285343335238233624733457334345273584 4432228273343343215583433543323212333224236223355337222323333332345234332434333235242435462732332333 7553547893569536378624439279549153554453536866554549468525592874454477737666779494576549796896643415 2124221834224131213222323122212233232172125222323231324222325221422624317561223232422221222232332422 5344434563445335453343447245666334345455593633333359553532842724354855675395434569426346449336343359 7323134454424646623244626222222425623272821225253221462263224424732533741329123223432218165238335233 2333353433134553232323333235213322333435333234332362433311434234333332333363434333333331433633337313 3344332343443435344254248353434433644437346254423333343444234777124334243235241442141441642344443433 4133222221222563554332222274323243563533453254329772432235442432232223331236122512252143332535822253 2122322321123522222329232322232412322222254123232162321222223124451615214232212212324245221222424422 6652684336373647767544333643438577743841633347337636653377258533793368685635326838763284323453332833 2222242223416222242432122322222122223222242121212121223322212222422223442222212214112222242212122322 2332223222822452222442212722232111221224312212212422212231222262534224332122522112111222431252242222 5586633437564634774847177673758536498678467645435726969787134233753534533523834354823836766899569987 3265182213234225423251133242336323233333343443322232323244334213223434233324453333833112222323223322 4311225222222342222212221222122222222114531223251222462222326331221223222222222222535222231221222215 8353353532212327242242223333233633734342332362231221233633312338342222262293134224272363372232425535 6637568865784585854864857854884827877786646684697458554354466886856487448336888567884488456377585735 8764876657764358887668956357793774525775795784756969553336626979755347473689447936775685248575571643 3324222333321123232533222112341324233322325333232124232362222251122123223332125222223333333326112322 5154454432334412668333483246547544634434544444244643134643564443345555542415445424363344454544442444 5529595579554725215997464852546265545525545496757145285786556596357946559343572694858563555726254435 3236113122412222222143211221112261222222272223322242241222223312223322232222321322225232222212212275 2222227231322342222222222221122213222121222242222122222222233112233322212122422221222222221221222322 5545555234513444744563336433465534426473325262565223624554382644444325465643444148645473535674442431 2234333232244344332712342623134322412344224443274524412432411243323131224222343422222333472233432424 4223333224415333332433332333543342632343333333343335424442345321334453232433153323432334332332333343 6364543445435432334632254455423526234534363333535534435335534454593343534443475325454435624238833314 2533344296437155726714623465525736434473253844437436344546323746844152742433564335743236383447552556 4435653443755434445263653255358645637345224332433333544534375353336342534765354445643443454543224153 7343213233483342331333372222333232174436323523432223343342325232383323244321565332143341333323333232 3343341322433346345412332444333332333341633253323532142134423242343433343644337341333253333334331333 4954666664556733566643675747683864546956336546796534255726645435447545665546566525455333537324765633 2561463486484556662526656544762655655734756665375447745726633527236646723726674574373726747516742546 2523232233321432322233232353323343221444346331442232332313214224284223444133631432742312424225444423 1225135534233234226463225963263632342756423233542334357454312452542627472425252374763432465354636447 3659362562686326315225343345488676426546362326734463634384445632725635233726625565443734652757782223 5533153332326424444355455444542424524424333242534263414455242443431442544642543434433353322321433243 5512532522364334355422295343634723372235223144393222652155225337335336323353233373235232533253322724 2223232222211244223222312412233223222231313222241224222142232221322212424223222242322322223322222241 4525848623523725652313133544563445546234954552333457744253585372323765554133679483636944549315344393 3215232333333322114333343334335343253334432434133213223133153222134423223323333532133333623222233323 3835154427421885116485134521856581134543364365776468584466324358784887887164711752653158338583868759 4544417321543442725422244543474244423344345272322237122262441444213354224454162814547423444841431371 3252383844525728554545655333544472757555545565555543542555555345463123455473256426436465512545275964 2277638522444242216243373936387272431444175333323743425266473745412476747122633514112862137734246355 4316444535443343344466624434646444645443464544434467335443435443444334374443244464444433443641443434 2235443543325832223264242433624436343523234643924632439321341235415312231532424232434212532425593132 3221234342643222211233221513434732257113432222322312421234323322321253433334124122444423372322122422 5638224368353237455587341753633943585755645442635743383273437235552587573346531353335563334585357234 9494545546464453366456345474434544756854463344455364335951544545522334434443475832244534923386454453 4212222344622233366212256216226628462122221625532232326322455222225242622256243112325252252221222242 ================================================ FILE: exm/aoc/2025/aoc_2025_03_questions.txt ================================================ --- Day 3: Lobby --- You descend a short staircase, enter the surprisingly vast lobby, and are quickly cleared by the security checkpoint. When you get to the main elevators, however, you discover that each one has a red light above it: they're all offline. "Sorry about that," an Elf apologizes as she tinkers with a nearby control panel. "Some kind of electrical surge seems to have fried them. I'll try to get them online soon." You explain your need to get further underground. "Well, you could at least take the escalator down to the printing department, not that you'd get much further than that without the elevators working. That is, you could if the escalator weren't also offline." "But, don't worry! It's not fried; it just needs power. Maybe you can get it running while I keep working on the elevators." There are batteries nearby that can supply emergency power to the escalator for just such an occasion. The batteries are each labeled with their joltage rating, a value from 1 to 9. You make a note of their joltage ratings (your puzzle input). For example: 987654321111111 811111111111119 234234234234278 818181911112111 The batteries are arranged into banks; each line of digits in your input corresponds to a single bank of batteries. Within each bank, you need to turn on exactly two batteries; the joltage that the bank produces is equal to the number formed by the digits on the batteries you've turned on. For example, if you have a bank like 12345 and you turn on batteries 2 and 4, the bank would produce 24 jolts. (You cannot rearrange batteries.) You'll need to find the largest possible joltage each bank can produce. In the above example: In 987654321111111, you can make the largest joltage possible, 98, by turning on the first two batteries. In 811111111111119, you can make the largest joltage possible by turning on the batteries labeled 8 and 9, producing 89 jolts. In 234234234234278, you can make 78 by turning on the last two batteries (marked 7 and 8). In 818181911112111, the largest joltage you can produce is 92. The total output joltage is the sum of the maximum joltage from each bank, so in this example, the total output joltage is 98 + 89 + 78 + 92 = 357. There are many batteries in front of you. Find the maximum joltage possible from each bank; what is the total output joltage? --- Part Two --- The escalator doesn't move. The Elf explains that it probably needs more joltage to overcome the static friction of the system and hits the big red "joltage limit safety override" button. You lose count of the number of times she needs to confirm "yes, I'm sure" and decorate the lobby a bit while you wait. Now, you need to make the largest joltage by turning on exactly twelve batteries within each bank. The joltage output for the bank is still the number formed by the digits of the batteries you've turned on; the only difference is that now there will be 12 digits in each bank's joltage output instead of two. Consider again the example from before: 987654321111111 811111111111119 234234234234278 818181911112111 Now, the joltages are much larger: In 987654321111111, the largest joltage can be found by turning on everything except some 1s at the end to produce 987654321111. In the digit sequence 811111111111119, the largest joltage can be found by turning on everything except some 1s, producing 811111111119. In 234234234234278, the largest joltage can be found by turning on everything except a 2 battery, a 3 battery, and another 2 battery near the start to produce 434234234278. In 818181911112111, the joltage 888911112111 is produced by turning on everything except some 1s near the front. The total output joltage is now much larger: 987654321111 + 811111111119 + 434234234278 + 888911112111 = 3121910778619. What is the new total output joltage? ================================================ FILE: exm/aoc/2025/aoc_2025_04.adb ================================================ -- Solution to Advent of Code 2025, Day 4 ------------------------------------------ -- Printing Department -- -- https://adventofcode.com/2025/day/4 -- Copy of questions in: aoc_2025_04_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; procedure AoC_2025_04 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; n : constant := 10; np1 : constant := 11; input_name : constant VString := +"aoc_2025_04"; n : constant := 136; np1 : constant := 137; type Map_Type is array (0 .. np1, 0 .. np1) of Character; map : array (0 .. 1) of Map_Type; initial : Map_Type; r : array (Part_Type) of VString; procedure Read_Data is f : File_Type; begin Open (f, input_name & ".txt"); for w in 0 .. np1 loop initial (w, 0) := 'W'; initial (w, np1) := 'W'; initial (0, w) := 'W'; initial (np1, w) := 'W'; end loop; while not End_Of_File (f) loop for y in 1 .. n loop for x in 1 .. n loop Get (f, initial (x, y)); end loop; end loop; end loop; Close (f); end Read_Data; procedure Do_Part_1 is rolls, res : Natural; begin res := 0; for y in 1 .. n loop for x in 1 .. n loop rolls := 8; if map (0)(x, y) = '@' then rolls := 0; for xx in -1 .. 1 loop for yy in -1 .. 1 loop if abs xx + abs yy /= 0 and then map (0)(x + xx, y + yy) = '@' then rolls := rolls + 1; end if; end loop; end loop; end if; if rolls < 4 then res := res + 1; end if; end loop; end loop; r (part_1) := +"" & res; end Do_Part_1; procedure Do_Part_2 is rolls : Natural; m : Natural := 0; moved, total : Natural; begin total := 0; loop moved := 0; map (1 - m) := map (m); -- Clone current map. for y in 1 .. n loop for x in 1 .. n loop rolls := 8; if map (m)(x, y) = '@' then rolls := 0; for xx in -1 .. 1 loop for yy in -1 .. 1 loop if abs xx + abs yy /= 0 and then map (m)(x + xx, y + yy) = '@' then rolls := rolls + 1; end if; end loop; end loop; end if; if rolls < 4 then map (1 - m)(x, y) := '.'; moved := moved + 1; end if; end loop; end loop; total := total + moved; exit when moved = 0; m := 1 - m; end loop; r (part_2) := +"" & total; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; map (0) := initial; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 1320. -- Part 2: validated by AoC: 8354. end if; end AoC_2025_04; ================================================ FILE: exm/aoc/2025/aoc_2025_04.txt ================================================ .@.@@@@@@@@@@@@.@.@..@@.@@@.@@.@@@@@@@.@.@@@@...@..@@.@@@.@@@@@@@@@...@@..@...@@...@..@.@.@.@.@.@@@@@.@..@@.@.@.@@@@.@@.@@@@..@@@@.@..@@ @@@@@.@@@.@@@.@@@@..@@@..@@@.@@@...@@@@@..@.@@@@@..@.@@.@@@.@.@.@@.@@.@@@@@.....@@..@@.@.@@.@@@@@@@@@@@@@@@.@@@@.@..@@@.@.@@@@@@.@@.@..@ @.@..@@@@@.@@@.@.@@.@@@@@@@..@@@@@@@..@@@@@@@.@@@@.@@.@@@.@.@@@.@@@.@@.@.@.@@.@@@.@.@@@.@..@@..@..@@..@@@@@@.@@...@@.....@@@@@@@..@@..@@ @.@@.@..@..@@@..@@@.@.@@.@.@@@@@.@@......@@@.@@@.@@@@@@.@.@.@@@@..@.@.@..@.@..@.@@.@...@@..@@@@@.@...@@@..@.@.@@@@@@@.@@@@@.@@@..@@@@.@. .@.@..@.@@.@@@@.@@.@.@.@@@@@@.@@@@.....@@..@@.@.@@@@@@@@.@.@@@...@.@@...@@@@@@@@.@@...@@.@@@@@.@...@..@.@..@.@@@@@@@@@@@@@@@@@@@@.@@.@.. @@@@@.@@@@@.@@.@@@@@@@@.@@@.@..@@.@.@@@@@.@@@@.@..@.@@.@@@.@@.@@@@@.@.@@@.@@@..@@.@@@..@@@.@@@..@@..@@.@..@@@@.@.@@@.@.@@@@@.@@@@@@.@@.. @.@@@..@@@.@@@@@@@.@@@.@.@@@@@...@.@@@@@@@.@@.@.@@..@@@@.@.@.@.@@@@@@@@.@@@@@@@@.@.@@@.@@@@.@@@@.@@.@@@..@@@@.@@@@.@@@@@@..@@.@@.@@@@@.@ @@@.@@.@@@.@...@@@@...@.@@@..@@@@@@..@.@@@@@@.@..@@.@@@@@@@@@.@.....@@@@@@@@@@.@@..@@@.@@@.@.@@@@.@@..@@.@@.@@@@@..@@@@.@..@@.@.@...@@.. @@@@@.@.@..@@@@.@@@@@.@@.@.@..@@..@@@@@@.@@@@@@..@.@@@@@@..@@@.@@@@@@.@.@.@@@.@@..@@@@.@.@@@@.@@@@@@@.@@@@@@@@.@.@@@@...@@@.@@@@@@@...@@ .@.@@@..@@@.@@@.@@@@@..@.@.@..@..@@@....@@.@@.@@@.@.@@..@.@@@.@@@.@..@.@..@@@@@@@..@.@.@@@@@.@@@@.@.....@..@@@@@@@.@@.@@@@@.@..@@@@@@.@@ .@@..@@@.@@....@@@@.@@@@@.@@@@.@...@.@...@@@@@.@@@@@@.@@@@..@@.@@...@@@@@@@..@@@..@.@.@.@.@..@.@.@@..@@@@@@.@@@@@@.@.@@.@@@@.@.@@...@.@@ .@@.@@.@@@@@@.@@.@.@.@@@@.@@.@@.@@@@@@.@@@@@@@@@@.@@.@@.@@.@...@@@..@@@.@@.@@@@@.....@@@..@@.@@@@.@@.@.@@@@@@@@@@..@@..@.@.@.@@..@.@@@@@ @@@@@@@@@.@@@.@.@@@@@@@.@@@@@@@@@.@.@@@..@@@@.@..@@@....@...@..@@....@@@@@@@@.@@.@@..@@@@@@.@@@@.@@@@@@@@.@@@@...@.@.@@@@@.@@@..@@@@@@@@ @.@@@@@..@@.@@@@@.@..@@@@.@.@@@@..@.@..@@@@@@@@@@.@..@@.@..@.@.@..@.@@@@@@@@@.@@@.@@@@@@@@@@.@@@@@@..@@@...@@@@@@@.@@.@@@.@.@...@@....@@ @@@@@.@@..@@..@.@@@..@.@.@@@@@@..@@@@@@@@..@..@@@@@@@@@...@@@@@@@@@@@@..@@..@.@.@.@.@@.@@.@.@@..@@@@@@@.@@@@.@@@@@@@@..@@@@@.@.@@..@@@.. ..@.@@@.@@@.@@.@@@@@@..@.@@@@@@.@.@@@@@@@@@@@@@.@...@.@...@@@@.@.@@@@@@@@..@@@@.@..@.@@.@@@.@@@@@@.@@@.@@@@@.@@@@.@@@@.@.@.@@..@@@@@.@@@ @@@.@@@@.@@@..@.@@.@@@@.@.@@@@@@.@@@..@@@@..@@.@.@@@@.@@@@.@.@@@..@@@@@@@@.@...@@@@@@@@@@@@@@@@@@@.@.@@.@@@.@.@@..@..@.@....@.@@.@..@..@ @.@@@@..@.@@.@@@@.@....@@@.@@.@.@@@.@.@@..@@.@@@.@@.@@@@@@@..@.@@@@@@@@@@..@@@@.@.@.@@@@.@@@@@.@@@...@@@@....@.@.@.@@@@@@@@@.@@@.@@.@@.@ .@@@..@@@....@@.@.@@@@@.@@.@@@@@@...@@.@@@@@@@@.@.@@@@@.@@.@.@@@@.@@.@@@@.@@.@@@@@...@.@@.@@@@@@@@.@.@.@@.@@..@.@.@@.@@.@.@@@@@.@.@.@@.@ @.@.@.@@@.@@@.....@.@@@@.@@@@.@@@@@...@.@@@.@@@@@@@@@.@@.@.@@@.@@@@.@@@@@@@..@.@@.@@@...@.@@@.@@@@.@@@@@@..@@@@@...@..@.@@@.@@.@@@@@@@@@ .@@.@.@@@.@@.@@@@@.@.@.@@.@@@@.@..@@@@..@@@@.@@@@.@@@@.@@..@@....@@@@@@..@@@.@@@@.@.@@..@.@@@@..@@@@@@@@@@.@@@.@@.@@@@..@@@.@@@.@@@@@..@ @@@@..@@@.@@.@@@@.@@@..@.@.@.@@@@@.@..@@@@.@@..@@@@.@@@@@@@@@@@@@.@..@@@@.@@@@@@@..@@.@@@@@@@.@@.@@@@@.@....@.@..@@@@@.@..@@...@.@@@.@@. .@..@@.@@.@@@...@@@.....@@@...@@@@@@@....@.@@@.@@@..@@@@@@.@@@...@@@@@@..@@.@@@.@.@.@.@@@...@..@@@@.@@@.@..@@@@.@.@@@.@@@@@..@.@@@@..@@. @@@@.@@@@..@@.@@..@@@.@.@@.@.@.@@@.@@.@@....@.@@...@@...@@@@@.@.@.@@@@.@@@@@@@.@.@.@@.@..@@@@.@..@..@@.@.@..@@@...@.@@@@@@@@@@@@@@@@.@@@ @@@@@..@.@@..@@@.@@.@@@@@.@.@@@@@.@..@@.@@@.@...@@@@@@@@.@@.@@..@@.@@@@@@@@.@..@@..@@..@.@@.@@...@.@.@@@@@@@@@@..@@@@@@@.@@@@.@@@@.@@@@. @@@@@.@@@@@@.@@@@@..@@.@..@@@@@@.@.@@.@@@@@.@@@.@@.@@.@@..@...@@.@.@@@@@.@@@.@@@.@@.@@@@.@@@.@@@...@.@...@..@@@@@..@.@@@@.@@@...@@...@@. @..@.@@.@..@@....@.@@@.@@@@@@@@.@@@..@.@@@@@@.@...@@.@@@..@......@.@@.@@....@.@@..@@@@@@@@@@@@@@..@@.@@.@@.@@@..@@@@@@@@..@.@@@@@.@@.@@@ .@@.@@@..@@@.@@@@@..@.@.@@.@@@@@@@@@.@@@.@@@@@..@@..@@@@.@..@...@@.@@..@...@@.@@@@@@.@..@@@.@.@@@@.@.@@.@.@@@@.@@@@@@@@.@.@@.@@@@@.@@... @@@..@.@@....@@..@...@@.@..@@.@.@@..@@@@....@.@@@@.@@@@@@.@@@@.@@@.@@@@@@@@@@@.@..@@@@@@@@@@.@@@.@@@@@@@..@...@.@@@.@@.@.@@@....@@@.@@@@ .@@.@@@@@.@@.@@.@@..@@@@..@.@@...@..@@@@@.@.@@.@..@.@@@@@@.@@.@@...@.@@@@@@@@@.@.@.@...@.@.@@@...@.@@@@@@@@..@@...@.@@@@@@...@@.@@@@...@ @@@@@...@...@@@@..@@@@@.@@@@..@@@@@@@.@.@@@@@@.@@@@@@@@@@@@.@@@.@@@@.@@@.@.@@@@@.@..@@...@...@.@@..@@@.@.@@..@..@@@@@@...@@@@@@@@@@.@.@. @.@@.@@@@@@@@@..@@@@@.@.@@@@.@....@@@@.@@@@..@..@@@.@@@@@@@..@@@@@@@..@.@...@@....@@@@@@@@@.@@@.@@@..@@@@@...@.@@@..@@.@@.@.@@@.@.@@.@@@ @@.@@@@@@@@@@@@@@@.@@@@@@..@..@.@@...@.@.@@@@@@@@@@@.@.@@@@@@.@.@@@@@@.@@@@.@@@...@@@@@@@.@@@..@@@@@@@@@@.@@@@@..@@.@@..@...@.@@@@@.@@@@ ..@...@.@@@@@@..@@@.@@@@@@@@@.@@.@@@.@.@@.@@@.@.@@@.@.@@@@@@..@@.@.@@....@@@...@@@@@@@@@@@@@@@@@@@.@@@@@@.@@.@@@@@@@...@@@@@@@@@@.@..@@@ @@@.@@.@@.@.@@.@@.@@@@...@@@@@.@...@@.@.@.@.@@@.@.@.@@@@@@..@@..@...@.@@@.@.@@@@.@@@...@@@@@@.@@@@@@@@@.@@..@.@..@..@@.@.@@@@@@...@@..@@ @.@@.@@@@.@@@@@@@@@@.@@@.@@@.@@@@@@@@@@.@@@..@.@@......@.@@@@@@@@@@@@@....@@@@.@..@.@...@@@@@@.@..@@..@@@.@.@@@.@.@@.@..@..@@@.@..@@..@@ @@@@@@.@.@@@...@@.@@@@...@@@@@@..@@@@.@.@.@..@@@@.@..@@@@.@.@...@@@@@@@@@..@@@.@.@.@@@..@@@@@@@..@@@@@@@.@.@@@..@@.@@@..@@.@@@..@@.@@.@@ @@..@@@@.@.@.@@@@.@@.@@...@@@.@@@@.@@.@@@@@.@@@@.@.@.@@.@@@@@..@..@@@.@..@.@..@@.@.@@@@@@.@.@@@@@@@@.@@@@@@@@@.@@.@@.@..@....@@@@@@@@.@. .@@.@.@@..@.@.@@@@@.@@@@@@.@@@.@@.@@@@.@.@@@@@@@@@@.@.@@@@@.@..@.@@.@.@....@.@.@@.@@.@..@@@@@@@@@@@@@...@@@@.@...@@@@.@@@@..@@..@.@.@@.@ @.@@@@@@@@@@@@@@.@.@@@.@.@.@@.@..@@@...@@.@@.@.@@.@@.@@@@@@@.@.@..@@...@@@@.@.@.@@.@...@@@@@..@@@@@@@@@..@@.@....@@@@@@@@.@@...@@@@@.@@. ..@@@.@@@@@@.@.@@@@@@@@@@@@@.@.@.@@@.@...@.@@@...@@.@@@..@@...@@..@.@@.@@@@@@@.@.@@@@@@.@.@@.@@.@@@@@@...@@@.@@@.@.@.@@.@..@.@@..@@@@@@@ ...@.@.@.@.@@..@@.@@.@.@@.@..@@@.@.@..@@..@@@..@@@.@@.@...@@.@@.@@@@....@.@.@@.@@.@.@.@.@@.@@.@@@....@@@@@.@@@.@.@.@@@.@.@..@@..@@@@.@@@ @@@@@@@@@@@@@.@.@@@.@..@@@.@.@.@.@@..@..@@@@@@@@@..@.@..@.@@..@.@@@@.@@@@@@@@@@@@..@..@@@.@..@@..@..@@@@.@@@@@.@@..@.@@@@.....@@..@..@@@ @@.@..@@.@..@@.@@.@..@@...@@.@.@@...@.@..@@@@@@@@..@@@.@@@@@@@@.@@...@@..@@@@@@@@@.@@....@@...@.@@.@@.@.@@@@@.@@@@.@@@..@...@.@.@@.@@@@@ @@.@@@@@@..@.@@@@@.@@@@.@@..@@@@@@@.@@@.@.@.@@@@@@@@.@.@@@@..@..@.@.@@@...@@@@@.@@.@.@@..@.@.@.@@.@@.@@....@@..@@.@.@@@@@@....@.....@@.. @@@@@.@@.@.@@@.@@@..@@@@@@@@@@@.@.@..@@@@@@..@.@@@@@@@.@@@@@.@@@@@@@@@@@@.@.@@@...@@...@.@.@@@.@@@@.@.@.....@@@@@@..@@@@@@@@..@..@@.@@@@ @.@.@@@@@.@@..@@@@@@.@.@@.@@@@@.@.@@.@@@.@@.@.@....@@@.@@.@@@.@@.@@@@@.@.@@@.@...@@@.@.@@@@@@@.@...@.....@..@@@.@@...@@.@.@@.@.@.@.@.@@@ @@@@.@@@@.@.@.@.@@@@@@@@@@.@@@@@@@@@@@.@.@@.@.@@@...@@@..@@.@..@.@@@@..@..@.@@..@.@@@@@.@@@@@.@.@@...@@@@@@@.@@.@@@@@.@.@@@.@...@...@@.@ @@@.@@@.@@@@..@@...@@.@@@@@@@.@.@.@.@.@.@..@..@@..@@@.@@@@@..@.@@.@@...@.@@..@@@.@@....@@.@@..@@@@.@@.@@@@..@@..@@@@..@@@.@.@@@@.@@@@@.@ @@..@@.@.@@@@.@@@@@@@@.@@@@@.@@@.@.@.@.@.@@@@..@@@@.@@@..@..@..@@@@@@@@@@.@.@.@@@@..@@@@@..@@@@..@..@@@@@@@@...@@.@.@@@@@@@@@@@...@@@.@. @@.@@@@@.@@@.@@.@.@...@@@.@.....@@@@.@..@@..@..@@@@@.@@..@@@@@@@@@@@.@@.@@.@@..@.@@@@@.@@@@@@@@..@@@....@@@.@@@.@.@....@@.@@.@@..@.@@@.. @@@.@@@.@@.@.@@@@@@@..@@@..@@..@@@..@@@.@.@@.@@@@.@.@@@.@@....@@@.@@.@.@@.@..@....@.@@@@@@@@@.@...@@.@@.@@@@@.@....@@.@..@.@.@@@@@.@.@@. .@..@@@@.@@@@.@@@@.@.@..@.@....@@@.@@@.@@.@.@..@@@.@@.@.@@.@@@@..@@@@@@@@@.@@@@@@@..@.@@@@@@..@@@@@.@.@@@@@@.@@@.@@@@@@@@@..@@.@@@@@@..@ .@@@.@@...@@@@@..@@..@@@@@@@@@.@@@.@.@@.@@@.....@@.@.@@@@@...@@.@..@@..@@.@@...@@.@...@...@@.....@@@.@..@@@..@@@@@@..@@.@@..@@@.@@@.@@@@ @@@@@@@@@@@@@@@@..@...@..@@.@@@@@..@.@@@@@.@@@@@..@.@@@@@@@.@@@@@...@@@@@@.@...@@@.@@@.@.@@@@.@.@@.@.@..@@.@@@...@@@@@@.@...@.@@@@.@@@@@ .@.@@@@@@.@..@@@@@@@@.@@..@@@@@@...@..@@@@..@@@@.@@.@@@@.@.@@@@.@@@..@@@@@.@@@@@@@..@.@@@.@@@@.@.@@@.@@@.@@@@.@@....@.@..@.@@...@.@..@.@ .@.@.@@.@@@..@@.@@@@@@@@@@@@@@...@@.@@@@@@@..@..@.@@@@@@.....@@.@@.@.@@.@@@@@..@@@@@.@@@..@@.@@.@@@.@.@@@@..@@@.@@@.@@@@@@@.@@.@.@@@@.@. @.@@@..@@.@.@.@.@@.@..@.@@@.@.@@.@@@@@@@@@.@@@@@@@..@@..@@.@@..@.@@@.@.@@.@.@@@..@..@@@@.@...@..@@@.@@@@.@@@@@.@@.@.@@@@.@@@@@@@..@@@@.. @@@.@@@.@@.@@@@@@@......@.....@.@..@..@@@..@.@@@@..@@.@...@.@@.@@@..@@@@@.@@.@@@.@@@..@.@@..@.@@@@@.@@@@@.@@@.@@@@....@@@@@@.@@.@@@....@ ..@@@@@.@@@@.@@..@@@@@@.@.@@.@@@@.......@..@..@.@@@.@@@@@@@.@@@.@@@.@.@..@@@@@.@@@@@.@@.@..@@@@@...@.@..@@@@@.@@@@.@...@@@@@@.@.@@.@@@@@ ..@@@@.@.@@@@....@.@@@..@@....@@.@@@.@@@@@.@@@@@@@.@@.@@..@@..@..@@..@@@.@@@@.@.@.@.@@@@.@@.@.@@@..@.@..@@@@@...@.@@..@@@@@..@@@@@..@..@ .@@.@@.@@@@@..@@@@@@@@.@@@@@@@@@.@@.@.@..@@@@..@@..@@.@@...@.@@@@@@@.@@@.@@@..@.@@@.@@@.@@@@@@@.@@.@.@@.@.@@@.@.@.@@@.@@.@...@@@@...@@@@ @@.@@@.@.@@@@@@@...@.@..@@@.@@@@.@.@.@@@@...@@@@@.....@@...@@@@@..@.@@..@@@.@@@.@....@@...@@@.@.@@@@@@@..@@@.@.@@@.@.@..@.@.@@@@....@@.. .@@@@.@@..@.@.@@@@.@@.@@.@@@.@@@.@@..@@@@.@@.@...@@@@@@@@.@@@@....@@@@...@@...@@@...@.@.@@.@..@@@@.@@@.@@@.@@@.@@@@@@@@@@.@@..@.@@@.@@@. @.@.@@@.@.@.@@@@@@@@..@@@.@.@@@.@@@.@@.@@@..@@@@..@.@..@@@@@.@....@@@@@.@@@@@@.@@@@@.@.@@@@@@@.@@...@.@@@@@@@@.@@@@@.@@..@.@...@.@..@.@@ @..@..@@@@.@@@@@@@.@@@@@@.@@.@@..@.@@@.@@@@@.@@@@@@@.@@@.@@@.@@.@..@@@@@.@...@.@..@.@@.@...@@@.@@.@@.@@@@@@.@@@@@@@@@..@@.@.@@.@@.@..@@@ @.@.@@....@@@.@@@.@.@@...@.@.....@@@@.@.@@.@..@@@.@@@.@@@...@..@@@@.@@@@.@@@@..@@@..@@@@..@@.@@@@.@@@@@@@@@.@@...@..@.@..@@.@@...@@@.@@. .@@@.@.@@@@@@@..@.@@..@.@..@@@@..@@.@@@.@@.@.@...@.@@@@@..@@.@@.@@@@@..@@...@@@@@@.@@@@@.@....@.@..@@@.@@.@..@.@@@@.@.@@@..@@@@.@@....@@ @@@@@.@.@@@@@@@@@@..@@@@.@@.@@.@.@@@@@@@@@@@@..@@@@@..@@.@..@@@@@.@@...@@@@@@@@@@@@@.@@@@.@@.@@@@@.@@..@@...@@@@.@@@@@@@@@.@.@@@.@@...@@ .@..@@@.@.@@@@.@@@..@@.@....@@@@.@..@.@@..@@@@@@@@.@@..@..@@@@@@@@.@@.@@@.@.@@.@.@.@...@.@.@@.@..@.@@.@.@@@@@@....@@.@@.@@@@@.@@@@@.@@@@ ...@.@@@@..@@...@..@@.@@@@@@@@..@@..@@@.@@...@@.@.@.@@@@.@@@.@...@.@@.@@@..@@@@@@@@.@@@@@@..@.@@..@@..@@...@@@......@.@@@.@@.@@@@@@..@@. @@@@@..@.@.@.@@.@@@.@.@@.@@@@@.@@@@@@@@@@@...@@@@.@@@@@.@@@@@@@..@@@@.@@.@.@..@@..@@..@@@.@@.@@@.@.@@@.@@.@.@@@@.@@@.@@.@@@.@.@..@.@.@@@ .@@@@.@@...@@@@@@@@@..@@@.@..@.@@@@@@@@@.@@.@.@@@.@@.@.@.@@@@@@@.@@@@@@@@@@@....@@@@.@.@.@@@@..@@@@@@.@..@.@@@@.@@@@@@.@@@....@.@@.@...@ @@@@.@...@@@@.@..@.@@.@@.@@@@@@.@@.@@.@@@@@@@@@@@..@..@@.@.@.@@@@.@@@@..@.@@.@@@@...@@@@..@...@.@@@@@@..@.@@.@...@@..@@@@.@.@@@@@@@@@.@. .@.@@@..@@@..@@.@.@@@@@@@@@.@@.@@@@@@.@@...@.@@@@@@@@@@.@@@@.@.@@..@@@@@.@@.@@@..@@@@@@@@.@@..@..@@@@@@..@.@@.@..@.@.@.@..@@@..@.@@@@.@@ @@......@@@.@@@.@@@.@.@@@@@@.@.@@@@@@@.@@@@@.@.@@@@@.@@.@@@@@.@.@.@@@@@@@@.@@@@@@@.@......@@@.@@@@.@.@@@@@@@.@@@@.@@.@@@.@@.@@@@@@@@@@@@ @@.@@..@....@@.@.@@@@@@@@@@@@..@@.@..@.@@.@@.@.@@.@.@@@.@@..@..@.@@@..@@@.@.@@@..@...@@@@...@@@@@@....@.....@@@@@.@.@@@@.@@@@@.@@@@..@.@ ...@..@.@@@.@.@@@...@.@@@@.@.@@.@@.......@@@..@@@@.@.@@@@..@.@@@.@@@@@@@.@.@@@.@@@@.@@@@@@.@..@@@..@..@..@..@@@@@.@@@...@...@@@.@.@.@..@ @@@..@@@.@.@@@..@@...@@.@.@.@@@@@@@.@@@@@..@@@@@@@.@@.@@@.@@@@@@.@.@@@@..@.@..@@@@@@@@@..@.@.@..@@@@@.@@@@@@.@@@@@..@.@@..@.@@@@@@@@@@.@ ...@@..@.@@@@@@@.@...@@.@@@@@@@@@@.@.@.@@@@.@@@@@@@.@..@.@@@@...@@@@@.@@@@...@@@@@@@.@...@@@@..@@..@@@..@@.@@@@...@@.@@@@...@@@.@@.@@@@. .@@.@.@.....@@@@@@@@...@@.@@@...@@@@@.@@@@.@@@..@@@.@.@@@@.@.@@@@@...@@.@@@.@.@@@@..@@@@@@.@.@.@@@.@@@..@..@.@.@@@.@.@..@@@.....@..@..@. ..@.@@@@.@...@.@@@.@@...@.@@@.@..@....@@@@@@..@@@@@.@@.@@@@...@@@..@@@...@.@@@..@@@@@..@@.@@..@...@@..@@@@.@@.@@@.@.@@@@.@@@@@..@@@@@@@. @..@.@@....@..@@@.@@.@@@..@@@.@@@@@.@@@@..@@.@.@@.@@@@@@@@@.@@@..@@@@@.@@@.@.@@@.@....@@@@@@@@@...@@@@@@@@@@@@.@@@.@@.@@@@....@@@.@@.... @@.@@..@@..@@..@.@@@@@...@...@@..@@@@@.@@.@@@@....@@@.@@@..@@.@@@@@@.@@..@..@.@@.@@@@@..@.@@@.@@.@@.@@.@@.@@@@@@@..@@@@@@.@@.@@@@@..@.@. .@@.@@....@@..@..@@@.@@.@.@.@..@@@@.@@@.@@@@.@@@..@@@...@..@..@..@@@@@@..@@.@@@@@@@@@@.@@@@..@@.@@@..@.@@@@....@@@@@@.@..@.@@.....@.@@@@ @@@.@@...@@..@@@@.@@@@@@@..@...@@@@.@@@.@.@@@.@@@@@@@@..@.@@.@@@..@..@@@@..@@.@@@@@.@@.@@.@@@@@@@@@@..@.@.@.@@@.@.@@..@.@.@@@@@.@@.@@.@@ @@@.@.@@@@@@@.@@@@.@@@@@@@@.@@@@@.@@@@.@@@.@.@@@.@@@@@@@@@@.@@.@...@@@@..@@@@.@..@@@@@..@@.@@@.@@...@@..@.@.@@@@@@@..@@.@@.@..@..@@@@.@@ .@@.@@.@@@.@.@@@@@.@@.@@@.@.....@@@@@@....@@@@@.@@.@.@@@@@.@@..@..@..@......@.@@@.@@@@..@@..@@@.@...@@.@@@.@@@@@@@.@.@@@.@@@.@@@@@.@@@@. @@@@..@..@@@.@@.@.@@@@....@...@@.@@.@..@.@@.@@@..@.@.@@@..@.@..@@.......@@@.....@@@@.@.@@@.@.@@..@.@@.@.@..@.@...@.@.@.@@@@@@@@@@@@@.... @@@@@@.@@@@.@....@@.@@@@@@@@@@.@@.@@@..@...@.@@@.@@...@@..@@@@@.@@.@.@@@@@@@@@@.@...@.@@...@..@.@...@.@@@@@@@@@@@..@@...@@@@..@.@@....@@ @@@.@@.@@@@..@@..@.@@.@.@@.@..@.@@@@@..@.@.@@@.@.@..@@@@@@@@@@@..@.@.@.@@.@@@@@@@...@@@.@@.@..@@.@@@@@@@.@@@@@@@@@@@@@@.@@@@.@@@.@.@@@.. @@@.@@@@@.@@@@@@@@@@@@@@..@@.@@.@@.@.@...@@@@@..@@.@@..@..@.@@@..@..@.@@.@@@.@@@@.@@@..@@.@@@@.@.@.@@.@.@@.@@@@@@.@@@@@.@@..@@@@@@@.@.@@ ..@@...@@@@@@@.@.@@.@.@@@@@@@.@.@@@@@@@@.@@.@@@@@@@@@.@@@@..@@@@@....@.@@@.@@@@.@@@@@.@...@.@@@@@@@@@.@.@.@.@@@....@@@@.@@.@...@@@@@.@.@ .@...@..@..@@.@@@@@.@...@.@@@.@@@@@.@@@@...@.@.@@@@.@@..@@@@.@@@@.@.@.@..@@.@@.@@........@@.....@.@@@@.@@...@..@@@@@..@@@.@.@@@.@@@.@@@. ..@@@@@@...@@@@@.@@.@@@..@@@@@@@..@@@@.@@@@..@.@@@@@@.@@@@.@@..@@@@@@@.@@.@.@.@@@@.@...@@.@.@@@@.@@@@.@..@@.@@@.@@@@.@.@.@@@@@..@.@....@ @@.@......@@@@@@@@.@.@@@@@@..@..@@.@.@@....@@.@@@@@..@.@@....@.@@@@@.@..@@@.@@..@@@@@@.@@@@.@.@@@@.@.@.@.@@@@.@@@@@.@@.@@@@..@@@.@@@@..@ .@@@@....@....@@@...@@@.@@@@.@@.@@.@..@.@.@.@.@@@.@@...@.@@.@@.@..@@..@.@.@@....@..@@.@@@@@@.@@@..@@...@@.@@@.@@...@@...@@.@@@@@.@@.@@.. @@.@.@@@@@..@...@@@@.@.@@@.@@@@@@@@@@@.@@.@.@.@@.@@.@@@@.@.@.@.@@@...@@@@@.@@..@@@..@@@@@@@@@.@@@@.....@@@@.@@.@@..@..@..@@.@.@@@@@...@. @.@.@@@@...@@@@.....@@@.@.@@@..@@..@.@@@@.@@.@@@@.@@..@@.@@@@@@@..@.@..@@@.@..@@@@@.@.@.@..@@.@@@.@@@@@....@@@@@.@@@@..@@.@@@@...@..@@.@ @...@@...@@@@.@@@@@.@..@@@...@.@@@..@@...@.@.@@@@@..@..@.@@..@@.@@.@@@.@@.@@@@@.@@@@@..@@@@@@@.@.@@@@.@@@@..@@.@@@.@@@@@@.@@@@@@.@@@@.@@ .@@.....@.@@.@@..@@@@@.@..@@@..@.@@@@@@...@.@@@...@.@@@@@@..@@....@..@.@@.@@.@@@.@@.@..@.@@.@@.@@@@@@@@@@.@@..@@@@@@...@.@@@.@@.@@.@..@@ .@@.@.@.@@@@@.@@@@@@.@.@@.@@.@@.@@@@.@@@@@@@@.@@@@.@@.@....@.@@@@@@.@@.@.@@@.@@@..@.@@.@@@@.@@@@.@.....@.@.@@.@@.@@....@@.@..@.@@.@@@.@@ @.@@.@@..@@@@.@@@@.@@@@..@@@.@@@@@@.@@@@@.@@@..@@@..@@.@..@@@.@@@..@@@@@.@@..@@@@...@@@@@@@@@.@.@.@..@@@.@.@@.@.@@@..@@@@..@@.@@@@@.@@@@ .@@..@.@@..@..@@@@@.@@.@@@.@.@.@@.@@@.@@@.@.@.@@.@.@.@@@.@.....@@.......@.@@@@@.@@@@@..@@.@@..@@@@@.@@.@.@@@@.@@.@@@@@@@@.@.@@.@.@...@@. @@@.@.@@.@@@@@@.@@@.@.@@@..@@@@@.@@@@.@@.@@.@@.@.@@@.@@@@.@@@@..@@@@@.@@@..@@@.@@@.@.@.@@@@..@@@@.....@.@.@.@@@.@.@..@@.@@@@@.@@@@@@.@@@ ....@@@@..@.@@.@@.@@@.@@@.@@..@@@.....@..@...@@@@@.@....@@..@.@@@@@@@@@..@@@@@@.@@@.@@@@@@@@@.@.@@..@@@@@@@@@@@.@@@...@@..@@@@@@@@..@@@@ ..@@@@@@@.@@@@.@....@...@@@@@.@.@@..@.@@@@@.@@@@..@.@@.@.@@@@@@@.@@.@.@@@....@@..@@@@@@@@.@@.@.@@.@@.@@.@@.@@@..@@@@@@@@@@@.@.@...@@@@@@ @@@@@.@.@@@@@..@@@@@@@.@@@@@@.@@...@.@..@@.@@@@.@@@@@@@@@@..@...@@.@@@@@@..@@@..@@@.@@@.@@@@@@@@..@@.@@@@..@@.@.@@@...@@@@..@@.@@..@@@@@ ...@@...@@@@@..@.@.@..@@.@@.@@.@@@..@@@@@.....@@@@@@@@@@.@..@.@@@@..@@@.@@.@..@@....@.@@@@@@@@@@@@.@@.@@.@@@@@..@@@@@@@@@@@@@..@.@@@@@@@ ..@@@..@@@@@@.@@@@@@@.@@@@@@@.@@@@@@...@.@@.@.@.@..@.@@@..@@@@@@.@@@@@@..@@.@@@....@@.@.@.@.@@@@@@@@@.@@@.@.@@@.@@@@.@....@@...@@@@...@@ .@@.@.@..@@@..@@@@@.@@@@@@@@@.@.@..@@@@@@@@@@.@@@@@@@@.@@..@@.@..@@.@..@@.@@...@@@@.@@..@.@.@@@.@@@..@.@@..@@.@@@@...@@.@@@@@@@@.@.....@ @.@.@@@@@.@.@@@@@@..@@@@@@...@@@@@@@@@..@@@.......@.@@@@@@@.@@@@@@@@@@@@@@@.@.@@@@@@@@@@@..@@..@@@@@@@@.@@..@@@@@.@.@@@@@@@@@@@@@@@@@@@. @@.@.@@..@@@@.@@@@.@.@@@@...@@@..@@@.@@@@.@..@@...@@.@@.@@.@.@..@.@@@@..@@@@@@@@@@@@.@@@@@@@..@@@@@@@@@@.@.@.@@.@@@@@.@.@..@@@..@@.@@@.. ..@@@...@@@@@@.@.@@.@@@@@...@.@@@.@@....@@@@@@@@@@.@@.@@@.@@..@@@@@.@..@@@@@.@@@@@.@.@.@@...@.@@.@.@@.@@@@@.@@@@..@@@@@@..@@..@@@@@@@@@. @@..@@.@@@@@@@@@@@.@.@@@@@.@..@@@.@@@@@@@@@@..@@@@.@..@@@@@.@.@@@.@.@....@@.@..@..@@@@@@@@@@.@@..@@@..@.@@.@@.@.@@@@@...@@@.@@@.@@@.@@@@ @@.@@.@.@@.@@@@@@@@..@@@@@@@.@@@..@@.@..@@.@..@@@@@@.@@@@@@.@@@..@..@@@@..@@.@@@@@@.@@.@@.@@@.@@.@@@.@...@.@@.@.@@.@@....@@@@@...@@..@.@ @...@@@@..@..@@.@@@.@@@@@@@@@..@.@@...@@@@@@@....@@.@...@@.@@.@@.@@.@@@@@@@.@@@..@.@@@@@.@@..@@@@@@@.@@@.@@.@@@.@@@..@...@@...@@@@@@.@.. @..@..@.@@@@@..@@@@.@@@@@@.@@..@@..@@.@..@@.@@.@@@.@.@.@@..@@...@@.@.@@.@..@@@...@@.@@@.@@@@.@@.@@@...@@@.@@@.@@@.@@@.@@@@@@.@@@..@@@@@@ .@@.@@@@@@@@@@@.@.@@@@@.@.@.@@@@.@@.@@..@@@.@@@@..@@...@@..@@@@@@.@@.@@..@@@@@.@...@.@@@@@@@.@@...@@@.@@...@@@@...@@.@@.@.@..@.@@@.@@@@@ @.@..@@.@@..@@@@@@@@@@@@..@..@@@@@@@@.@...@..@@@..@@@@.@@@@@..@@@@@@.@@@@@@@@@.@@@.@@@.@@......@@@..@@@.@..@.@@.@.@@.@....@..@@@.@@@.@.@ ..@@@.@@@@.@@@@.@@@@@@@@@@@@@@@@..@..@@@..@@@..@@@@@.@@.@...@@.@@@@..@@..@@.@.@.@@..@.@@@@@@.@.@.@..@@@.@@.@@.@..@@@@@.@..@@@@@@@@@.@.@@ @.@@.@@@@.@@@@@@@@@@.@.@@@@@@@@@.@.@@@@...@....@@@@@@@@.@@..@@@..@@.@@@@@@@@@@@.@@@@..@@.@.@@..@@@.@@@@@@@..@...@@..@@@@.@@@@@.@.@@...@. .@.@@@@..@@@@@.@..@@.@@.@@@@..@@..@.@@@..@.@.@@@@@.@..@@@..@.@@@.@@@@..@.@.@@@@@@...@..@@@...@.@..@@@@......@@@@.@@@@@@.@@@..@..@@@@@@.@ .@..@.@.@..@.@@@.@.@@.@.@@.@.@@.@@@@@.@@@@@@@...@@@@@.@.@.@@.@@.@.@@.@@.@..@@.....@@@@@.@.@...@.@.@@@.@@@.@..@@@@.@.@.@@@@@..@@@.@@@.@@@ @@..@@.@.@..@.@@@@.@@@@.@@@@@@..@@@@.@.@@..@@@@..@@.@@@@@@@@@...@@.@@.@.@@@@@@.@@@.@@@@@@@@@.@@.@@@@@@.@@@@@@.@@@@@@@@@@.@@...@.@.@@...@ .@.@@@@@@@.@.@@.@..@.@.@@@@@@@.@.@@@@@@.@@....@@@@.@@.@@..@.@@..@@@@@@@....@@@..@@.@..@@@.@@.@...@@@@..@..@@@@@...@@..@@@.@@@..@@@..@@@. @..@@@@.@..@@@@@.@@.@@.@@@@.@@@..@@.@@@@@.@@@@@.@@@@@@.@..@@...@@...@.@.@@.@@@....@....@@@@@..@@@@@@.@@@@@.@.@@.@@@.@@.@.@.@@@@@@@@@.@.. @..@@.@.@.@@@.@..@@@.@.@.@@@@..@@....@@@.@@@@.@@...@@.@@@....@..@.@..@.@@...@@.....@...@@@@.@..@.@.@..@@...@@.@....@@@@@@@@@@@@@@...@@.@ @@@..@.@....@@@@.@@@.@@@.@@@@@@@@@@.@@...@@@..@@.@.@@.@..@@@.@@..@.@.@@@@@@...@@..@@@@...@@.@@@@...@.@.@@@@@.@@@@.@@@@..@@..@..@@@.@...@ @@.@@.@@.@..@@@..@@@@..@@@@.@@@.@.@@@@.@@.....@.@@@.@.@..@@.@@@@@@@.@@@.@.@@@@@@@@@@.@@@.@.@@@.@@@@@@.@.@..@@@..@@@.@@.@..@@..@@@@@@@@@@ @@@...@.@...@@.@@@.@@..@@@.@@@@.@@..@@.@.@.@@.@@.@@.@@@@@@@@.@.@@@@.@.@@..@@.@.@@@@@.@..@@@@@@@@......@@@@@@@@@@.@....@..@@@.@.@@@@.@..@ .@@@@@@@@.@@@@@.@.@@@@@@@@@.@@@.@@@.@@@.@.....@@@@@@@.@@@@@@.@@@@@@.@@@@.@.@.@.@@@@.@@@@@@.@@@@..@@@.@@@.@.@@@.@@@@@@@@@@@.@.@.@...@...@ ...@@@@@.@.@..@@.@@@@.@@@@@@@.@@@@.@@@..@.@@@@@@@.@.@@..@@..@@.@@@@@@.@@@@.@.@..@@@.@@.@@@@..@.@@@@@@@@@@@.@@.@@@...@@@@@.@@.@.@@@.@@@.@ ..@.@@@@@@.@.....@.@@..@...@..@@@@@@.@..@@@.@.@.@@.@.@@@@..@@@..@@@@@@@.@@@.@.@@@@@@..@@...@.@@.@..@@@@@.@..@@@..@@@.@@@@.@.@@...@@@.@@@ @@@.@@@@@@@@@....@@@.@@@@@@...@@@.@@@.@.@@@@@.@@@@...@@.@@@...@@@@@@@@@@@@@@@.@.@@@.@@@@@@@@@@.@@@@@@..@@.@.@@@..@@@.@@@@@@@.@@@@@@@@..@ @.@@@@@.@..@..@@@.@@..@@@@@@@@@.@@@@@@@@.@..@@.@@@.@@.@.@@@@.....@.@@.@.@@@.@.@@@...@@@.@.@.@.@..@.@@@@.@@...@@..@@..@.@@.@@.@@@@.@.@@@@ ================================================ FILE: exm/aoc/2025/aoc_2025_04_questions.txt ================================================ --- Day 4: Printing Department --- You ride the escalator down to the printing department. They're clearly getting ready for Christmas; they have lots of large rolls of paper everywhere, and there's even a massive printer in the corner (to handle the really big print jobs). Decorating here will be easy: they can make their own decorations. What you really need is a way to get further into the North Pole base while the elevators are offline. "Actually, maybe we can help with that," one of the Elves replies when you ask for help. "We're pretty sure there's a cafeteria on the other side of the back wall. If we could break through the wall, you'd be able to keep moving. It's too bad all of our forklifts are so busy moving those big rolls of paper around." If you can optimize the work the forklifts are doing, maybe they would have time to spare to break through the wall. The rolls of paper (@) are arranged on a large grid; the Elves even have a helpful diagram (your puzzle input) indicating where everything is located. For example: ..@@.@@@@. @@@.@.@.@@ @@@@@.@.@@ @.@@@@..@. @@.@@@@.@@ .@@@@@@@.@ .@.@.@.@@@ @.@@@.@@@@ .@@@@@@@@. @.@.@@@.@. The forklifts can only access a roll of paper if there are fewer than four rolls of paper in the eight adjacent positions. If you can figure out which rolls of paper the forklifts can access, they'll spend less time looking and more time breaking down the wall to the cafeteria. In this example, there are 13 rolls of paper that can be accessed by a forklift (marked with x): ..xx.xx@x. x@@.@.@.@@ @@@@@.x.@@ @.@@@@..@. x@.@@@@.@x .@@@@@@@.@ .@.@.@.@@@ x.@@@.@@@@ .@@@@@@@@. x.x.@@@.x. Consider your complete diagram of the paper roll locations. How many rolls of paper can be accessed by a forklift? --- Part Two --- Now, the Elves just need help accessing as much of the paper as they can. Once a roll of paper can be accessed by a forklift, it can be removed. Once a roll of paper is removed, the forklifts might be able to access more rolls of paper, which they might also be able to remove. How many total rolls of paper could the Elves remove if they keep repeating this process? Starting with the same example as above, here is one way you could remove as many rolls of paper as possible, using highlighted @ to indicate that a roll of paper is about to be removed, and using x to indicate that a roll of paper was just removed: Initial state: ..@@.@@@@. @@@.@.@.@@ @@@@@.@.@@ @.@@@@..@. @@.@@@@.@@ .@@@@@@@.@ .@.@.@.@@@ @.@@@.@@@@ .@@@@@@@@. @.@.@@@.@. Remove 13 rolls of paper: ..xx.xx@x. x@@.@.@.@@ @@@@@.x.@@ @.@@@@..@. x@.@@@@.@x .@@@@@@@.@ .@.@.@.@@@ x.@@@.@@@@ .@@@@@@@@. x.x.@@@.x. Remove 12 rolls of paper: .......x.. .@@.x.x.@x x@@@@...@@ x.@@@@..x. .@.@@@@.x. .x@@@@@@.x .x.@.@.@@@ ..@@@.@@@@ .x@@@@@@@. ....@@@... Remove 7 rolls of paper: .......... .x@.....x. .@@@@...xx ..@@@@.... .x.@@@@... ..@@@@@@.. ...@.@.@@x ..@@@.@@@@ ..x@@@@@@. ....@@@... Remove 5 rolls of paper: .......... ..x....... .x@@@..... ..@@@@.... ...@@@@... ..x@@@@@.. ...@.@.@@. ..x@@.@@@x ...@@@@@@. ....@@@... Remove 2 rolls of paper: .......... .......... ..x@@..... ..@@@@.... ...@@@@... ...@@@@@.. ...@.@.@@. ...@@.@@@. ...@@@@@x. ....@@@... Remove 1 roll of paper: .......... .......... ...@@..... ..x@@@.... ...@@@@... ...@@@@@.. ...@.@.@@. ...@@.@@@. ...@@@@@.. ....@@@... Remove 1 roll of paper: .......... .......... ...x@..... ...@@@.... ...@@@@... ...@@@@@.. ...@.@.@@. ...@@.@@@. ...@@@@@.. ....@@@... Remove 1 roll of paper: .......... .......... ....x..... ...@@@.... ...@@@@... ...@@@@@.. ...@.@.@@. ...@@.@@@. ...@@@@@.. ....@@@... Remove 1 roll of paper: .......... .......... .......... ...x@@.... ...@@@@... ...@@@@@.. ...@.@.@@. ...@@.@@@. ...@@@@@.. ....@@@... Stop once no more rolls of paper are accessible by a forklift. In this example, a total of 43 rolls of paper can be removed. Start with your original diagram. How many rolls of paper in total can be removed by the Elves and their forklifts? ================================================ FILE: exm/aoc/2025/aoc_2025_05.adb ================================================ -- Solution to Advent of Code 2025, Day 5 ------------------------------------------ -- Cafeteria -- -- https://adventofcode.com/2025/day/5 -- Copy of questions in: aoc_2025_05_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; procedure AoC_2025_05 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; ranges : constant := 4; ingredients : constant := 6; input_name : constant VString := +"aoc_2025_05"; ranges : constant := 187; ingredients : constant := 1000; from, to : array (1 .. ranges) of Integer; id : array (1 .. ingredients) of Integer; r : array (Part_Type) of VString; procedure Read_Data is f : File_Type; begin Open (f, input_name & ".txt"); for i in 1 .. ranges loop Get (f, from (i)); -- NB: replaced all '-' by ' '. Get (f, to (i)); end loop; for i in 1 .. ingredients loop Get (f, id (i)); end loop; Close (f); end Read_Data; procedure Do_Part_1 is count : Natural := 0; begin for i in 1 .. ingredients loop for j in 1 .. ranges loop if id (i) in from (j) .. to (j) then count := count + 1; exit; end if; end loop; end loop; r (part_1) := +"" & count; end Do_Part_1; procedure Do_Part_2 is count : Natural := 0; modified : Boolean; enabled : array (1 .. ranges) of Boolean; begin for i in 1 .. ranges loop enabled (i) := True; end loop; Merging : loop modified := False; for i in 1 .. ranges loop for j in 1 .. ranges loop if i /= j and then enabled (i) and then enabled (j) then if from (j) in from (i) .. to (i) then to (i) := Max (to (i), to (j)); enabled (j) := False; modified := True; end if; if to (j) in from (i) .. to (i) then from (i) := Min (from (i), from (j)); enabled (j) := False; modified := True; end if; end if; end loop; end loop; exit Merging when not modified; end loop Merging; for i in 1 .. ranges loop if enabled (i) then count := count + to (i) - from (i) + 1; end if; end loop; r (part_2) := +"" & count; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 798. -- Part 2: validated by AoC: 366181852921027. end if; end AoC_2025_05; ================================================ FILE: exm/aoc/2025/aoc_2025_05.txt ================================================ 484155089502467 484512074248320 327626855857871 327839020372374 537199009780696 541029389615243 324153507327596 324355964932738 173465989350447 174041788222911 272663544666906 272663544666906 152868490671419 154360265852862 334565314570930 336048544225520 106674076603254 107536478616833 363046535191057 365733424846852 143852691024200 149853768977406 513247409695401 521804010955295 330373417143016 330956155155726 33228806536288 34781051094522 104978535117550 105727571504542 105727571504542 106382462636384 480181317870752 481376655879090 392619573203723 399658137237572 507064558575642 510928211367973 31269013157556 32964221268164 70746675484895 79383949442561 488384911502333 488739524722600 245264863918656 248440699812419 66108233250077 69763977702508 158354044192140 159602837769606 352968125118640 359903538807905 177637503356342 177768248104438 425225371783345 428185880910613 337517774842228 338699568015001 413116823808052 421482453687743 324355964932738 324787726958767 21031505924359 29336206500785 178762017395739 179306786525152 283124359892576 288153917955743 104238754491838 104978535117550 156665511220055 158040260496243 338247146166164 339788754907221 179536222619975 180228661508492 474667184537974 475812255497205 513247409695401 521804010955295 106887900874655 107536478616833 175392398092002 175732866298956 526139005782144 526139005782144 35410277445200 36916358845884 164076435824111 169840064957070 133425032733176 139934998714644 490674555618697 490885111740712 179786208538406 180553730844907 302346553875535 307433027610821 179974705855165 180553730844907 535002393179139 538558642399142 44042155826769 48485113111141 213624552370199 219348371651378 172619324074780 172877499427963 94528043269341 98873034317961 205261145714311 209868219379161 184779217941336 186667644665468 322101662480758 322234504977633 262039770461003 262039770461003 41875022229570 45906391518435 123353799692990 123353799692990 472616439285348 474000437648419 164076435824111 169840064957070 177768248104438 177966938826842 171117176820731 171869292146532 547332612003149 547332612003149 37424193557969 39105929131744 101571946459934 102315599870875 494764112303360 500892212366204 215878956252212 219348371651378 332071647060451 333275653431219 172223413862387 172619324074780 343059617550421 349658206244594 32398106302077 33821920045244 62268552683460 69763977702508 479178474644199 480641496160741 103399160626151 103679584369887 526139005782145 530329158936682 477382678085753 478659206508893 352968125118640 352968125118640 252193370768120 260075547729033 503954701580 6201080066693 6201080066694 7139048210272 491761166450629 491902594324657 324983512198420 325884415693302 316494299906814 320522086960363 467509841566778 471811317565211 154583318057153 156059831409040 307433027610822 309166768178612 241735356768237 245264863918655 106189609258943 106887900874655 113184461842736 113184461842736 157309114531452 158807509412759 405794282692748 410151465111344 322562853182400 323349337173519 329392752538402 329600089281791 416454584217619 418657627464396 476445154558831 477740195072234 52321883454900 57264044440557 285940653177318 290122783606908 139934998714644 139934998714644 104238754491838 104978535117550 435069087551255 438068571490810 106674076603254 106887900874655 494764112303360 498339466050479 488384911502333 488739524722600 433395071188269 441714193170789 483173469016124 483876364342976 382952029544932 382952029544932 272663544666907 278898829344501 30517568996683 31934161587780 446467331372924 449790867859745 480957198725802 482308516753345 340216156305507 341718829614154 335576964661675 337073420302056 171269045448034 171869292146532 322234504977633 322838357184566 328299411279389 329144168796675 36486032858102 37779434330475 482564738939348 483424624675311 329843762496517 330062103963728 343059617550421 346964428300776 141909036863330 147391313413681 327247289135445 327839020372374 10922455590682 18048485396100 339273504804747 340626526043886 453340687216566 461539243082300 24552273221200 26517533186483 374979031812261 378129333728028 510928211367974 510928211367974 478218077956627 479645063914504 174041788222911 174346031234314 559173122141199 562097848259759 113184461842737 118169846892007 382952029544933 390301071864488 81543407926368 84497261070632 105408705742278 106024442272978 491531238739012 491902594324657 428185880910613 428185880910613 260075547729034 260075547729034 313883655354623 320522086960363 174041788222911 174346031234314 191717416530192 199687058207157 336507649028291 337969660720965 153577994966155 155092017715908 103183231617090 103399160626151 70746675484895 76153416335407 57264044440558 57264044440558 332803389475321 334388906138526 171269045448034 171869292146532 38316177713166 40091262905581 84497261070634 87512083133515 106189609258943 106674076603254 378129333728029 378129333728029 547332612003149 548435610366690 410151465111344 410151465111344 486966262648163 487773819017583 464168729967780 467509841566777 173265729856132 173465989350447 155722135599830 156927657943610 473459660138827 475150269845108 333858227074656 335312735045959 487773819017583 488249317523391 330373417143016 330623658555129 94528043269341 98873034317961 392619573203723 399658137237572 203106437735893 205261145714309 232703951471611 239341944463919 172223413862387 173033171008712 182821432918211 190283971945510 151130743713884 152260090603062 475285443653571 476657816081333 199687058207157 199687058207157 221829521326154 229542350570658 159395463557657 160782166956609 179306786525152 179786208538406 174041788222911 174805432404479 262039770461003 269736060293387 554841339364567 559173122141197 123353799692990 128560306281572 444809669679604 449790867859745 101831951224850 102162268389164 365733424846854 370976617474324 34440576402312 36063022673365 152001032352489 153287102386040 292589544764606 298318988515383 232703951471611 234901660011328 465648994325263 485726374948528 475690590637294 196300608673016 325500055841075 200391175665352 17944830705256 319006389890415 151008315208808 330762627717238 540107358809277 56579943828298 304827419309353 218793968762758 558979672005912 463149947708692 207132310251074 27688126629980 410787718804716 266815787492858 349549957351422 453161293260865 440124194013821 224935111486614 458189929672612 222354803951091 385496645295297 159737743445676 435085730350147 339049336984817 108289691196866 63269002874293 6685408969929 560711096442918 447842282857842 384258392057600 418317339187012 526232998972781 318185626019900 173954241244574 76885713250977 138953839992455 38446781284879 2993091307541 89328498019533 287583058061187 253388687193171 65815885278170 143667792195956 56993769071203 158687367691714 315658700075614 158128483336434 222191777973717 272622212776187 545192047362089 376186038765117 242947268747893 471085877835535 129965216056599 207778752587957 252471880342054 262906375116580 534224313922897 413878652736777 197035964264903 279549224671724 44153866205768 25490437132400 456047749271344 460454825298853 269978250340095 25320286312005 273115319581907 150161800308438 110871266684605 319420592547997 345738432687570 305793320149559 148713889489739 499294517093216 31226367130878 172612656724594 430075577395089 539700736071107 248490622736321 357783308268551 265119880018962 231291290345527 226150538134399 510440855670848 557968955261200 366753606894739 548046875564109 487949898298134 508297681301651 85813530184312 26085582228207 248098174814414 74638591550079 308178419048394 95835736571751 275218649532607 394868159876364 10285869395759 465200373669687 286750097376153 420455004515755 338547854534866 348720612223320 12958774971518 245763283083902 332351236310594 276158906164860 59042749656947 451943792959362 330391629603314 48157493287167 398240465941344 414801973326926 378550285283921 22163595467061 480779429139335 556351665029871 559638909723239 347211750008710 324727023947861 177948083905540 62813318066679 339398092073741 400934619177864 86790992465901 15852914116516 154253986279527 42345202069561 107418220431964 327726786214697 479901768278245 490972852957601 501860254654435 187476104076465 515234099215970 105613677798811 76576992517982 63602685134794 370446294064094 125293600622010 348624405047279 229414892467206 550111725377520 253601022800835 246015599038208 26716224090075 106628682325906 149367265754691 344227585534865 414436225034212 373044568770668 508032292480710 538747633140176 239129875011217 267903056026239 269079461276087 390868090347716 138622100881942 38844613237894 322994927085853 454018508978606 311534498907291 329122626881814 180970002094700 376068250617145 177634058757307 490881830234258 7017946450359 410609014613452 358602206782982 230210485077799 166311033674041 254871960396830 479583246001450 418333891442833 13018415298209 110436931200781 377848248759981 37055407062199 395771536090537 285625857320076 457071547846483 454462175815748 243572281764729 493838152934481 136306603477083 272965132772929 359523134895474 218062604316076 196080099320404 62242223744221 147151311756565 146316101931905 146976702862809 510395092805891 131718330043246 449648193586388 435829963434261 440625359718663 365172596783271 540396006775329 234779165152900 264534238804314 66806025266187 275069701001412 366062798029719 244456093804383 527700086323868 166529351298605 362955521436431 482919085310378 283257341505810 153232880696306 394552242781153 343768049178508 333950895480298 551853617580089 143677863519490 74060167453409 456310322303431 134025061222202 408728099607080 34573640312491 193928098114300 490066275814021 86303373869837 245645106780938 52636102151296 297258182795550 278363025356332 119956165401884 39912089231581 427018367648629 487183658692128 223315477094328 517175429318316 68881075516914 33094051437104 388410883822250 531869844960512 256328382826175 175275083136438 83289029741724 465763280963667 31646298618953 333168648755117 366242861943763 75156722777953 508265614839503 98796946465642 559020601116488 5467108109577 105366513196271 164428413619744 83151142391341 185014262064857 497629158286618 31153262748994 298043610770489 283925378412319 28694803075972 455906018804610 151868806777935 363620235563789 36347910669144 196354303370134 388483018172112 360582809724943 232150072570533 96237634389515 505851323146100 168577897920329 268532747533171 414271786676737 510738155126151 42288604743357 464845452560036 350521576763663 2790553607883 286601432695738 68581668330233 497747478353430 488060165737320 210394112436035 531938419333390 235733370183364 499411335343391 406594297115866 534179913427567 141237867072244 518890750016543 25086593475095 276643782014667 103653487570393 33747448093872 85394611729114 180863610744209 230621930891177 65398129849574 106310501531592 105863422604792 378489487582599 331387514827061 6561622918944 432933925759374 499456656539730 222338928476450 394316775471077 306705011159801 517178697140196 148102225673100 55116866718253 301492363170310 424350017261844 104156598979714 6368571580028 145394106705778 517700100504249 455652082476752 421442262713380 373884444959820 420923707716902 529939677020279 263306921865810 415279461779662 158195109422211 554221248253924 193383508459957 217823095636530 441869358121903 286873626157484 34675944352140 274323027667503 264311656855279 387673053556249 82868052293172 316511965956741 151612982915105 425826466685883 491238761663825 350486059871862 413513421497176 236567477096492 408896153104255 467470679972033 164704456622599 63685936847397 390979670666774 474928971607942 135026465304050 359056540419958 66745809311184 126018096549244 305062744049016 194071199277840 501509723548996 476827185200581 275626747234735 430013005023040 518410150791484 72131242700198 340383414749962 477665601493098 535561806427643 407555137195755 217291279819907 557986608664834 16142893632580 182124459880116 404140756484309 296110516420275 171643098351907 486931627408613 207113534380670 524077154282500 228864907023232 383365617894903 70103795249694 50512979173728 397605945336496 26013092471759 395241421268710 465334300964440 261858369021755 527684923283476 427630216321229 198238026697491 457457910251150 401506984329048 349178450263450 546647139996296 184462947778898 306367401529528 539563594059532 39345489728847 103010746227197 98116787456608 386846358756692 104610778208354 26576694008613 156565542157075 192084240612390 259556465772815 15904195560740 236132852584233 434644090364311 99881487051684 426905232171523 522034565059278 314506139726295 299499714003961 183820232806506 206850974659307 135663766665821 102089365540214 425945138241774 414725338716582 84837001135774 226352656640955 288721160221131 116097857625794 468257741655738 349131393125042 97858344250848 475522348864872 472826892261099 69455870488880 131805399737993 216094584070180 58455712847916 366711602802177 357054615859808 78357619210085 152990852088797 342524073993073 450043621091613 201845269573400 142430583159100 556503021827212 85161652291815 290058445580149 178728724583453 418131998829096 427697703225770 25904543179754 105297352146790 418123737779902 383678551854912 468730983371397 124787414786575 308383651669639 53248099552727 171498826192589 376406135890811 445258595316244 263231728643009 324208810777119 388583324784949 458331277070896 148031092492796 382018948513853 136077295163143 308555646984109 14614285259270 461653649248830 158318118603163 435013238520636 326150076739969 475399121253465 156106959019712 208688809717157 29842605290273 202268072059860 282993801201526 153365611642795 540921552967436 320960886502819 469707792686103 105242779432445 479012505415829 118156584567709 70836294505690 528644756078017 102749524223928 343794580364717 556579065871742 38122311901867 312016631085668 505198292111546 144563040821956 406991234444632 160317680143063 350140714964482 66925480163405 232902001009144 536755664481759 21196120357836 173665364262475 5420853189190 101147507820255 284293797695935 461399398995401 464546187321105 541878525900454 279404587265427 550800427007755 235673928376398 452515441844173 509555045565249 481221087162142 415796518011797 555464484523481 245486050836754 1312729187484 461351154425133 446085579349094 539735263671492 324308812517461 267452870204054 179862138942359 87063631074434 77676965428230 47495874689531 83250190393567 287503596941017 396444990457477 124519706839242 157839982935656 495062791439310 154512214075405 208785614070698 418534616900849 487111934977198 116686672775696 17278207794169 297792271040321 545485324397541 26910544487003 227986077033638 331470468561325 396739005101185 420261747916524 60882138247537 314400885398908 507321940974182 479607363750629 274028634022721 290214480779409 255150656469724 406333418726889 209633642668851 82851650413018 174415875855808 347647962998358 142865843659110 346951844710054 145296662557462 370773076584528 126214747850220 547652353458667 1023351263968 169755175398654 518599429906635 33846742681732 168672976381620 224753538745291 484122613844692 204986873429997 548186280004784 151971816872087 2413001123517 215217411624094 252715157090472 246882536494029 314841111397180 45576108912322 274774894152420 364637463845199 158997318823023 467729730148300 364161875382173 27548860861942 118010407564078 153109272880074 341236750027155 548263482896529 354565236617873 426774118014985 203943800062495 364485490818434 347129355238045 389282748200872 402591881455477 37109245860638 322524359738963 23352577264101 60112554654836 99069004043586 335518138579949 557705378914003 332954879797108 159249252478289 192303686883130 84311997851419 323811763014534 397881987568871 41263853930161 314204432093487 94630391383561 125537195647648 455484220609279 275106701648714 161582427450661 136613479485433 196012947779387 498418367271002 343934545259218 2109961804682 225347192591111 187751534783876 62432768102721 90240593769245 243347328031763 180262096694629 400611561547347 68580731244073 448857492874889 162511353947722 174067633194412 174454835018391 6733952033973 512566408826733 196428147016599 173987768218259 438425145431191 98795447051414 562151356355741 511061394152804 464834443408759 258839398859279 63647412759537 500359969724673 414674931688430 486342755507303 383495876744797 247959228222071 478395383849061 335314989684365 401680212074279 54662260419310 195575312971134 329701660363513 557203258155487 303934913812278 549196383540217 316558010658840 388894303598071 508495705576650 365382037848947 434160208706186 490719268527649 22757508593407 74173060080537 394529116580444 198579420316664 218648394504284 250844719945739 519177115726079 210995283950867 478926704240966 322125338086841 222231141633906 24243547233806 475228412705872 538016030134645 539685388009141 112200167208259 34998189396523 242034427621752 481097694329618 162102242581143 171163156509241 417698127705874 289327511951933 150231091159121 86318216985599 212157894516578 211034711980000 352280810580118 215902883235127 501602712242483 275284982144704 228519292815627 255308739610203 388103293212389 11062160873834 211605059954128 409504977518037 166887900685401 269906845954803 242809833732335 70542864360841 29246218481549 28171334842885 408392861262973 25987925230493 69690389331629 64881435704887 538200095965370 464951259269603 62530051010143 481562836269822 275588779592943 121462168598953 294262042995506 362773254065101 185452277418500 253776377158625 553020845442987 450981282843183 482825359338299 92951712090079 401789488969013 82691587449395 460547332437770 550369009765200 204765006219353 383424935026763 411451885278109 544768399768969 354106107278808 351814733606870 345205736531054 553990438058685 234530753617837 142037700543505 166205529744183 282574350096660 349310470286847 461168096150528 174088527209052 273407649865353 560772075847388 373669265382428 527940044219641 526220055349415 61333301482305 277381088312766 398653996346101 537358286465034 420041777878728 190904884792541 414135951466143 307427122957800 175496838477939 224045469192409 396641535383079 12932297615290 29305595689889 320494881948653 35634989953013 463400091256918 364308441200109 287733984223493 286312417663097 14476535040100 72345157790618 467979218411243 398300177864406 509810162779476 86494614774768 337887243617068 183004315538293 301315508280444 32819467122530 364101460589897 272127482531487 14661880480118 558085063855258 477774912319456 149379002920977 182144611410986 261364167690385 297193844543228 368675600885719 217918407064700 250917765917926 485979592516414 27419266468566 281119855989076 53342876607506 168385081690418 68071599924640 295085841498947 433634500661453 98210283393150 417925823041044 118046126998437 125931519008518 54101783039771 296563685725698 125385974251141 140596318930571 297613888680909 556556247766534 77556654164724 520726672992536 527962296094224 314838704938152 104567359857678 229378218651487 535163096560007 421878548905206 22292022004456 226694762920368 325433562224972 350927689838638 68747614466057 278288373610990 123329215731971 127638721913602 262467205139544 439437567436922 33169828276782 365819063105421 107419826143114 159492842181615 245826906772378 33701292015819 111130590303550 143267425161404 88518370001945 99709748831684 507144340395665 17005295074631 394597409724205 456109774133764 220266796928414 194337113829451 168376744056032 196324880604945 316303815900806 260225614006305 126676005306073 287800426485627 296010450965831 452327757155989 386915979105242 12884154162742 178299434462745 289780425057671 524692852474367 8049748421905 287512776418562 497495353423812 356953912190227 105152422060130 75715726194756 449471922988083 178960727226775 16506135862435 380008863901350 484802537945341 487269642070212 257689206088793 437162197656802 167690406405337 295131584027702 423128589715610 247857337979598 447294653683025 528754659447288 197150348372392 85527781232882 325643026875656 85416649290624 343351960079471 222144605855719 95242848385552 418257702534682 479749851030221 439327119253406 216007727430876 159556006351623 285136231800700 266346349408836 213204893467649 132329408393058 167396552278400 13430771760342 272999234705345 2181291406670 354267124354129 3915477000394 275667302930232 355703471654279 171573697499122 476108734602434 250333255771422 284187391074728 542883247228251 268388512130581 348724909067450 560982897255963 82425178945262 36793327303651 472679026025886 533185603352637 440862633593872 314693292941017 377142702705622 146391068281354 436927110770106 195928939466611 464708458561253 534281577040719 112247600527291 76450436291102 297995326049950 13894251352689 124192647936767 459599244668614 283615760282882 431457068564814 514669417032595 393253024342883 303594090232073 216329092129347 451781660318266 538732013128567 51394498892905 97563862042322 555360678665621 77125009216030 6152085147952 479065478792799 106892288326794 425624436244334 364781708077558 23520178833448 52848164391780 216773473113383 64529056817782 366397062395405 533542103965367 506373117858768 204343504228015 126207040767367 245758805851139 255365791457351 403718281368516 431078684518872 136406177504001 14152106004280 481612673665150 5255589275675 556247473776668 146648767168484 534052369132154 255694301437722 174802115600729 85420697896041 9915837268881 356870117868642 312389014496808 526053044616034 368205286083856 216240149607142 204496240924157 533836527185372 376000060036219 552828975199029 53503756659340 185432188845668 524669951477891 455840130412128 5212891951706 442635246848462 459658055857457 163443771410584 12527116890639 344961051023748 117138982479414 198297242149820 283663699949587 424555341493375 435688311529195 342348741243927 38933572204739 554703298864698 395433357795370 93543372994982 495748168198728 ================================================ FILE: exm/aoc/2025/aoc_2025_05_questions.txt ================================================ --- Day 5: Cafeteria --- As the forklifts break through the wall, the Elves are delighted to discover that there was a cafeteria on the other side after all. You can hear a commotion coming from the kitchen. "At this rate, we won't have any time left to put the wreaths up in the dining hall!" Resolute in your quest, you investigate. "If only we hadn't switched to the new inventory management system right before Christmas!" another Elf exclaims. You ask what's going on. The Elves in the kitchen explain the situation: because of their complicated new inventory management system, they can't figure out which of their ingredients are fresh and which are spoiled. When you ask how it works, they give you a copy of their database (your puzzle input). The database operates on ingredient IDs. It consists of a list of fresh ingredient ID ranges, a blank line, and a list of available ingredient IDs. For example: 3-5 10-14 16-20 12-18 1 5 8 11 17 32 The fresh ID ranges are inclusive: the range 3-5 means that ingredient IDs 3, 4, and 5 are all fresh. The ranges can also overlap; an ingredient ID is fresh if it is in any range. The Elves are trying to determine which of the available ingredient IDs are fresh. In this example, this is done as follows: Ingredient ID 1 is spoiled because it does not fall into any range. Ingredient ID 5 is fresh because it falls into range 3-5. Ingredient ID 8 is spoiled. Ingredient ID 11 is fresh because it falls into range 10-14. Ingredient ID 17 is fresh because it falls into range 16-20 as well as range 12-18. Ingredient ID 32 is spoiled. So, in this example, 3 of the available ingredient IDs are fresh. Process the database file from the new inventory management system. How many of the available ingredient IDs are fresh? --- Part Two --- The Elves start bringing their spoiled inventory to the trash chute at the back of the kitchen. So that they can stop bugging you when they get new inventory, the Elves would like to know all of the IDs that the fresh ingredient ID ranges consider to be fresh. An ingredient ID is still considered fresh if it is in any range. Now, the second section of the database (the available ingredient IDs) is irrelevant. Here are the fresh ingredient ID ranges from the above example: 3-5 10-14 16-20 12-18 The ingredient IDs that these ranges consider to be fresh are 3, 4, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, and 20. So, in this example, the fresh ingredient ID ranges consider a total of 14 ingredient IDs to be fresh. Process the database file again. How many ingredient IDs are considered to be fresh according to the fresh ingredient ID ranges? ================================================ FILE: exm/aoc/2025/aoc_2025_06.adb ================================================ -- Solution to Advent of Code 2025, Day 6 ------------------------------------------ -- Trash Compactor -- -- https://adventofcode.com/2025/day/6 -- Copy of questions in: aoc_2025_06_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; procedure AoC_2025_06 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; l : constant := 15; m : constant := 3; n : constant := 4; input_name : constant VString := +"aoc_2025_06"; l : constant := 3772; m : constant := 4; n : constant := 1000; a : array (1 .. m, 1 .. n) of Integer; op : array (1 .. n) of Character; pos_op : array (1 .. n) of Positive; dig_it : array (1 .. m, 1 .. l) of Character; r : array (Part_Type) of VString; procedure Read_Data is k : Integer; f : File_Type; s : VString; begin -- Read the numbers: Open (f, input_name & ".txt"); for i in 1 .. m loop for j in 1 .. n loop Get (f, a (i, j)); end loop; end loop; Close (f); -- Parse operator row: Open (f, input_name & ".txt"); Skip_Line (f, m); Get_Line (f, s); Close (f); k := 0; for i in 1 .. Length (s) loop case Element (s, i) is when ' ' => null; when others => k := k + 1; pos_op (k) := i; -- put_line(i); op (k) := Element (s, i); end case; end loop; -- Parse digits or blanks individually for Part 2: Open (f, input_name & ".txt"); for i in 1 .. m loop for j in 1 .. l loop Get (f, dig_it (i, j)); end loop; end loop; Close (f); end Read_Data; procedure Do_Part_1 is total : Integer := 0; sumprod : Integer; begin for j in 1 .. n loop if op (j) = '+' then sumprod := 0; else sumprod := 1; end if; for i in 1 .. m loop if op (j) = '+' then sumprod := sumprod + a (i, j); else sumprod := sumprod * a (i, j); end if; end loop; total := total + sumprod; end loop; r (part_1) := +"" & total; end Do_Part_1; procedure Do_Part_2 is last : Integer; s : VString; total : Integer := 0; sumprod : Integer; begin for j in 1 .. n loop if j = n then last := l; else last := pos_op (j + 1) - 2; end if; if op (j) = '+' then sumprod := 0; else sumprod := 1; end if; -- Parse each cephalopod number, with possible -- leading or trailing blanks: for k in pos_op (j) .. last loop s := +""; for i in 1 .. m loop s := s & dig_it (i, k); end loop; if op (j) = '+' then sumprod := sumprod + Integer_Value (s); else sumprod := sumprod * Integer_Value (s); end if; end loop; -- NB: the "right-to-left" mention in "Cephalopod math is -- written right-to-left in columns" is irrelevant, it's -- just to confuse readers. total := total + sumprod; end loop; r (part_2) := +"" & total; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 4449991244405. -- Part 2: validated by AoC: 9348430857627. end if; end AoC_2025_06; ================================================ FILE: exm/aoc/2025/aoc_2025_06.txt ================================================ 95 62 793 567 8181 73 5 55 76 59 3498 51 3 53 59 7821 93 45 2 5 4 8 517 341 5 472 24 55 59 6 67 525 499 4 178 323 8 9912 1 78 43 666 758 473 39 9634 96 952 5 8344 2 3 42 8 3 452 521 85 81 2 61 92 26 8683 683 99 2 11 825 4493 92 853 549 6 1 21 226 826 218 9 182 7672 88 9596 71 56 13 6146 59 41 631 751 556 373 83 1 93 158 47 9 41 67 75 7666 7936 1 8 217 3289 57 47 59 74 3 96 49 53 82 789 51 561 7 85 5 2174 6 586 6684 782 45 41 38 73 378 47 53 4 6 161 23 4331 13 384 5 19 8 2115 191 13 35 835 7 51 3 948 323 19 269 4 3 87 15 26 195 39 623 73 35 767 8292 71 29 38 2547 15 833 522 9 1281 323 6 4 285 69 234 7229 6 4 962 16 33 45 236 8 445 4337 8 21 384 7 1593 44 9 5517 18 3425 36 6 91 7 5855 311 725 25 2 2 3 753 812 978 647 29 618 95 51 8851 9 874 47 366 9 88 7 22 879 182 65 36 365 344 4799 781 25 72 714 311 69 5 27 83 769 8788 25 95 29 15 12 1 6 13 385 4354 22 73 22 587 278 17 54 13 7 2 226 849 36 16 51 333 75 27 4 5631 3 54 28 66 47 56 522 7 637 17 687 8743 76 77 196 54 3 11 317 172 2 99 6 5 14 76 368 8 1 7953 23 56 5 82 782 4 23 3693 48 34 23 16 53 61 22 474 7 8 6 912 296 8 2 19 776 19 6 317 8732 955 17 7 2 21 291 46 95 1 9 4433 617 8 14 793 3825 3864 696 44 12 96 16 78 84 73 26 88 8 96 27 4 57 27 8 556 832 53 8596 4 5 351 5888 18 141 873 87 858 891 4 699 491 82 35 9 92 9 15 3 85 11 3 4 78 21 65 5 418 867 6 84 3551 6866 7 38 32 5832 48 352 91 45 9 9 161 9338 78 783 9 514 27 345 1 39 1 218 84 4543 7 54 318 981 9 2 48 88 56 7973 9 92 5 793 27 26 39 88 62 363 97 6 865 62 14 739 553 7 72 2 6 5 67 859 963 1652 16 718 67 5 31 86 23 569 4 6 71 79 4 33 8 39 26 21 8 37 41 9 14 871 5 4 88 53 34 2 651 89 99 344 2 359 5 5 3425 235 545 13 23 9751 686 3697 68 66 63 253 1166 267 52 88 7152 57 819 245 28 2616 781 2 984 925 71 71 7 246 83 89 41 9 336 97 272 4 685 8 46 753 3 4 56 13 64 976 14 276 11 18 837 6 597 29 17 6 45 5947 3 92 7 7 5575 43 236 44 222 8 34 671 2612 18 9 235 75 269 9158 38 81 2 74 9 5 4767 336 683 1317 98 86 9227 7 2 16 8464 529 25 32 84 23 29 233 38 37 621 383 9763 171 44 489 81 75 17 59 25 12 68 655 7 93 89 71 72 8 7 6 419 7 96 652 4 3 3142 49 28 656 9498 49 582 1 884 885 85 439 6 53 22 2857 3 6 337 93 5154 94 68 659 82 8 33 73 16 13 68 862 35 81 515 48 43 1 5833 8 34 271 7 6 45 22 48 81 4 2 224 819 22 22 4 176 47 38 67 745 592 8547 758 6 75 562 24 77 43 6923 32 34 1464 461 177 898 47 2423 98 182 2491 2593 9 57 96 65 556 284 94 3 7173 8126 7345 62 77 1 2 87 12 21 1 16 1 7689 29 532 72 843 3 33 176 78 11 1813 21 94 779 86 544 398 84 6 36 28 674 37 98 363 644 37 2 96 73 91 86 58 65 6413 53 739 81 2869 135 16 93 6348 395 48 21 285 5 15 187 13 33 6862 47 592 231 9984 691 218 21 81 982 2 3 47 91 3697 819 874 638 65 11 16 375 528 47 93 77 43 48 78 83 215 75 51 88 93 24 44 2 5 395 35 68 6585 564 48 911 1616 91 83 646 328 76 5 656 166 48 21 992 3 892 894 977 18 39 85 2255 5484 2464 743 1 4 1 4 7 272 5 53 5 1 272 57 895 46 79 91 311 59 62 7743 61 457 17 395 462 11 768 99 49 431 61 558 34 2381 5463 1 384 3 34 42 185 22 591 557 36 31 419 86 134 5 2 9 622 897 354 1318 383 5 86 145 876 54 181 63 837 46 78 195 4 4 12 64 25 11 49 357 973 822 68 241 674 416 247 5458 49 3 541 54 61 553 53 36 515 478 9711 12 8 5154 93 1315 278 5 92 726 596 37 67 49 9 77 1 35 896 21 32 74 82 699 3 4 741 9 3 11 5461 688 889 9537 398 729 298 5 67 21 33 613 4255 65 5 73 69 27 2623 72 6 25 56 5812 29 76 58 73 4 65 135 139 3 797 717 212 32 44 44 712 7161 73 879 726 7 7535 1 775 92 482 572 226 82 1466 89 2971 34 2541 66 77 97 94 7 153 253 65 62 67 42 2325 35 2644 356 44 4 88 355 3629 64 977 985 43 6 13 85 163 44 7 925 915 93 5423 737 957 17 432 25 58 97 246 514 194 752 2 55 286 26 71 14 9 398 1826 8113 85 9 892 9293 22 922 2649 42 74 5759 326 41 62 186 28 259 5 35 52 8761 11 437 7389 711 51 69 75 656 649 87 94 3 6 184 91 5313 47 9564 21 14 878 9229 332 366 35 365 7 222 47 311 719 453 567 816 8 74 74 14 295 849 563 66 793 693 9877 61 56 8 7661 71 915 712 49 449 6693 25 6 438 22 114 1625 7 28 234 87 19 163 674 59 791 4994 41 39 421 88 748 92 65 4148 22 9685 5 4 36 67 1827 9552 817 54 1195 53 919 542 587 13 886 85 939 7897 24 1582 75 291 52 851 9 89 1 14 46 253 11 328 275 6 341 698 46 64 865 289 73 4 55 423 898 199 891 51 43 98 24 64 74 283 334 3712 63 75 14 931 354 51 44 38 65 64 693 762 45 93 19 57 419 65 69 6893 945 91 26 38 82 857 681 392 916 73 781 7633 64 42 623 96 85 94 179 522 97 82 55 82 84 69 245 9 5 8667 39 62 3 233 26 7 77 6289 426 77 5689 353 23 2 97 275 7 7 71 26 594 12 46 42 472 5428 81 655 2313 672 414 5 22 618 476 48 71 65 37 3114 411 2 123 361 1355 134 914 84 476 67 43 71 82 14 26 34 223 15 19 7 81 53 8 971 7789 74 2883 615 9 732 6985 1 889 783 12 925 511 69 652 392 89 819 77 65 47 62 12 19 96 97 76 66 96 66 78 599 822 96 892 8491 1368 93 89 52 411 93 247 27 26 81 2 843 2171 26 412 14 181 38 891 59 72 6 494 738 412 58 53 621 923 8 23 41 68 4 3756 414 212 3 665 21 588 26 46 95 163 926 24 76 68 61 736 514 5 77 17 56 3 67 798 56 7932 87 374 48 8 391 99 72 433 15 19 61 82 4 8 44 522 24 66 8 53 77 6431 513 978 76 9 99 98 94 574 268 39 56 194 14 323 5 264 1682 729 979 62 68 3187 394 1883 44 12 58 414 8373 969 8 882 7187 63 166 155 57 1528 66 73 642 423 52 113 48 752 87 11 31 89 245 55 991 17 259 3 2 553 6 3 97 775 59 243 56 445 222 36 455 674 459 15 668 3 12 645 14 895 62 13 1116 26 523 48 225 24 58 652 997 274 78 889 25 46 755 576 3 39 96 548 68 1252 2628 273 7414 53 126 1238 56 3 25 1457 42 65 88 83 36 53 73 28 12 997 265 8571 876 755 579 66 27 64 58 64 57 23 724 31 66 44 815 98 12 1 8 294 78 79 479 38 12 2957 77 32 557 4384 31 993 84 1142 674 52 9268 68 36 41 4856 62 98 933 797 3875 99 11 488 21 626 348 11 67 18 18 163 25 27 21 61 774 9 4451 32 15 774 58 76 86 59 37 89 5 4 895 563 44 26 9 597 54 27 6 812 355 9464 214 25 35 989 4 63 99 8958 92 9963 392 788 397 458 29 4824 71 366 5873 566 34 8519 81 36 867 662 366 913 9482 191 8272 39 89 22 25 19 225 3428 54 46 315 8788 35 346 84 441 24 56 619 58 8 1496 59 321 592 44 662 994 88 44 69 585 733 16 28 687 538 14 24 58 26 444 963 42 35 7683 442 553 21 7561 773 49 24 9565 698 59 46 993 1 248 143 73 98 1633 72 528 297 7191 48 251 4417 37 855 43 9 89 74 138 613 827 637 18 631 51 241 817 421 53 161 18 471 516 589 482 93 92 77 75 29 98 2 3 185 77 98 7965 842 68 881 4455 258 59 899 382 67 6 194 737 87 27 564 57 3359 422 159 43 78 528 6464 5329 7429 249 91 43 2 2 9 764 311 15 88 3426 165 27 559 844 31 32 466 93 56 6757 65 86 48 351 711 31 729 72 93 694 89 157 77 6466 1552 21 524 81 73 452 984 43 67 794 11 95 456 97 785 95 81 2 555 576 581 783 711 39 299 548 417 51 657 55 699 58 26 713 97 1 611 38 93 24 48 578 564 464 66 739 888 863 195 8871 797 888 313 64 783 514 41 35 162 978 2786 86 4 9423 896 2546 93 2 494 157 523 52 1811 72 89 99 33 32 933 85 79 818 83 655 32 1 791 1 49 999 2691 423 237 1966 235 227 789 3 47 46 5 57 416 83 9 62 9769 29 8739 4 784 43 6 4593 48 83 33 41 84 71 83 616 254 181 874 865 691 63 367 447 5358 77 579 179 76 6671 61 796 66 829 46 868 19 5774 52 2421 11 56 19 99 576 264 5 445 113 45 55 62 73 1319 94 6221 417 66 93 9 34 4711 58 614 195 637 71 13 2 855 78 95 713 349 6 1442 371 185 114 772 62 53 26 31 426 681 949 56 1 22 32 56 5 8 889 765 2159 19 56 13 613 3 611 1998 69 13 9777 4979 33 61 968 35 971 55 8673 44 614 11 56 1975 4237 56 69 486 173 377 886 32 89 64 311 2 152 49 9898 12 18 543 6731 589 689 33 494 25 996 99 24 675 8542 116 788 82 27 75 2 57 295 2 644 731 886 119 29 75 5 17 75 7911 367 96 631 1269 971 42 127 74 95 7963 23 348 814 27 9 161 922 88 687 3179 512 95 96 73 128 81 43 9739 837 6987 7 852 391 8878 156 5896 72 773 8125 42 3568 429 461 95 43 96 598 8551 14 993 88 276 49 827 25 9 16 67 35 83 13 184 169 2 7 189 27 11 6797 893 55 654 32 828 451 532 6241 78 46 46 4 54 562 526 317 145 941 39 27 254 87 64 396 6 73 839 125 23 53 67 431 32 669 166 64 17 787 279 39 11 16 168 434 866 268 53 54 8569 42 269 953 5 65 85 98 168 95 4 68 913 83 91 437 42 61 1172 86 36 39 854 92 63 75 593 782 29 9112 174 928 8 16 197 44 64 27 24 88 74 876 85 966 8883 83 63 727 292 163 62 43 114 157 99 25 66 18 1932 178 3 6549 78 5561 896 336 62 729 49 63 832 38 92 98 99 265 6 39 96 65 65 69 597 2825 8 8148 875 377 72 7534 8 355 541 46 3981 958 87 838 129 93 357 89 68 476 29 65 39 29 546 122 75 37 24 21 792 769 73 537 9834 687 977 48 12 987 47 41 75 9629 65 84 513 8417 37 458 86 28 58 744 83 358 63 35 159 161 98 65 65 63 595 91 45 69 9 733 482 257 57 684 39 767 76 58 47 618 386 325 21 14 7 483 291 88 62 61 132 3 6 72 73 2722 62 728 79 863 1915 15 73 76 54 18 78 77 15 3 976 711 82 8 86 13 67 1594 841 655 26 63 14 48 94 567 14 794 2 8 57 21 615 521 4781 18 168 394 62 913 937 5235 93 97 313 6842 5146 616 9 178 217 46 448 76 83 166 33 92 733 491 77 248 51 556 67 2 567 62 51 43 313 646 743 74 5 56 19 62 1 1845 29 65 477 56 951 49 74 961 428 662 226 73 17 754 579 624 15 68 839 1 791 11 487 836 2 211 364 131 298 414 83 42 952 679 1 42 43 3492 22 368 2468 49 63 7 883 2444 849 69 85 4469 38 58 12 9 1 81 52 881 68 287 771 8292 783 112 426 84 24 5 9371 44 1 75 73 82 86 572 613 7 25 212 52 723 35 21 18 746 224 7726 38 1 852 755 275 628 44 3238 735 46 3118 841 16 57 411 391 847 134 5118 89 72 7 559 13 361 843 17 81 92 1 832 66 53 1 64 3757 28 9283 63 13 792 987 272 912 51 22 99 65 59 48 476 44 43 69 575 61 21 6 73 46 65 261 592 13 188 5 43 55 2253 87 1761 753 28 646 866 78 123 39 953 4283 26 42 5838 2 85 32 61 7424 9494 86 947 265 59 56 333 6773 65 452 6267 89 38 485 237 6 558 94 488 463 77 533 12 6 946 16 192 947 46 7 227 5 82 33 114 492 38 63 126 36 92 455 26 82 589 319 75 66 762 779 1151 16 23 271 23 94 13 59 62 78 5 83 621 24 64 56 339 35 998 26 7917 77 674 9523 66 179 87 15 87 322 86 845 135 252 51 6189 61 475 57 973 71 758 8 722 4147 246 948 133 331 55 16 837 33 73 412 411 27 71 667 27 38 929 7596 487 54 843 3485 67 66 37 59 93 55 647 57 4185 454 396 689 99 385 331 642 7679 748 123 21 66 8 91 936 8715 13 19 3549 22 97 857 6496 263 83 839 57 51 5236 78 68 87 443 778 28 553 36 54 814 34 561 272 477 9589 17 9354 73 86 765 811 21 66 22 61 97 643 23 657 51 663 2 537 756 63 518 447 992 244 335 8 23 25 93 521 79 4 785 42 4 691 85 929 43 84 632 55 84 2279 78 362 863 775 5443 475 2799 248 19 356 326 6 49 64 879 7437 37 3 378 863 3866 42 994 1851 48 46 4 3491 27 94 46 945 246 23 1 33 533 39 734 73 93 625 143 317 991 639 897 669 8621 9922 162 733 8 35 73 1 3 2 52 76 15 5435 5 1352 4 355 31 6 55 99 41 75 79 93 96 66 72 694 378 431 498 254 77 298 94 3299 47 838 158 21 367 94 137 17 865 87 4 75 666 84 2424 13 3 44 51 353 6115 72 56 186 64 366 817 85 4987 998 318 359 7 65 7 34 5166 92 6 252 326 31 34 9 9 6 88 456 659 9 17 539 418 386 598 47 34 8 43 29 96 254 69 7 96 5 95 8 4 1348 5 14 41 55 53 25 6 245 8867 57 22 9696 5687 2 32 198 7 43 92 6494 76 113 77 56 551 8359 55 3 317 912 159 355 42 96 48 772 7 94 98 5598 97 74 691 253 56 856 85 389 47 483 94 4 345 5273 796 378 12 6 94 8 6 934 9 276 516 564 392 3 15 8 27 52 2794 25 273 577 7714 186 94 56 37 33 688 72 668 137 958 6 951 97 14 227 6641 281 6 59 468 74 2 75 48 171 56 2 9822 817 7273 99 6162 31 214 8833 49 2847 49 768 8 37 41 721 7638 59 813 51 77 35 917 12 9 95 3 13 92 3 675 79 2 7 1 64 79 9482 328 68 351 358 165 33 91 9858 64 828 53 5 89 176 311 399 731 163 75 94 83 2 27 372 5 43 544 87 37 1 71 731 9 277 856 11 4 414 213 15 31 54 843 161 674 23 11 7 45 15 235 9 9 89 777 9 558 93 6 27 327 16 34 98 97 86 53 394 32 11 695 6 95 28 715 416 71 9227 528 714 7 34 867 47 985 32 46 26 65 798 63 539 2641 59 61 17 61 418 52 24 738 43 89 9 61 77 387 62 22 1698 4 2978 28 1 54 181 2 56 578 69 36 33 62 514 1 95 55 19 85 65 74 3275 2 5167 174 468 35 6378 4 7537 19 93 6563 118 74 61 939 647 592 66 18 6328 66 44 75 68 813 373 82 57 66 42 787 511 19 531 999 2 6536 2 53 38 1 8 76 9659 78 87 6878 7219 87 666 46 6 75 439 32 227 88 45 631 54 17 32 81 2 275 12 7 6 7 44 998 922 495 97 25 614 36 95 87 83 296 493 9 41 9 767 252 24 42 64 255 61 5 45 6 57 46 89 57 986 4663 4 53 3 847 51 65 78 13 4 423 374 89 6 81 5 18 9191 259 485 28 36 8 88 584 757 9 653 3 7 15 24 1549 818 973 5 328 587 16 675 644 2328 81 76 9981 2684 39 461 6 668 3 177 282 29 68 38 7 65 936 69 73 156 375 76 8 7 783 83 4 8 7 341 91 41 5 82 38 97 4 9876 15 3 514 76 353 84 29 913 83 192 939 28 45 54 861 373 223 92 884 3 331 7 3 476 7 816 573 999 746 872 88 57 23 6628 1 41 23 9274 711 35 3767 46 8 4 5868 64 574 68 67 9668 92 94 95 9 9 88 2 556 423 121 729 829 286 4617 253 62 2 7 3694 74 1 93 1 74 96 629 895 6 78 2963 66 521 48 92 68 769 889 594 9 8 3 745 291 5 71 9252 38 7 1346 998 76 83 12 127 346 99 5217 3 6 8 79 44 395 734 29 1 67 2 11 55 71 3 2 9849 38 8325 44 66 55 446 816 945 6 716 68 43 91 5 894 9 16 25 26 57 64 5 42 6 7 465 212 4 18 7 43 648 1454 19 2922 3 66 83 253 1 68 83 2 318 52 71 2248 3 14 53 95 1827 3515 71 94 8 6 74 287 8924 84 668 8777 17 14 131 68 4 328 63 2 823 25 971 2 5 137 37 777 2 68 6 25 4 763 52 483 583 34 2 9 36 67 555 81 81 955 239 59 3 26 261 1641 7 38 914 48 4 17 12 28 4 4 13 593 9 16 49 28 3 939 47 281 7 649 2367 58 72 395 31 4 114 9 361 43 37 28 6914 5 881 2 993 54 637 1 3392 8142 828 9 885 982 1 75 694 31 355 859 936 71 656 76 55 98 368 629 895 48 33 4434 66 25 8 54 35 11 93 34 4995 378 373 554 6 639 465 439 6313 712 491 682 23 52 66 19 6258 18 65 6678 93 5 725 3643 458 95 24 88 89 235 15 6 3 91 211 38 75 36 91 85 56 74 331 292 25 65 4558 349 49 431 494 64 21 15 97 9 51 43 24 62 948 48 32 985 24 4 66 973 456 8 1 99 56 1 82 49 4 57 66 279 795 7 273 2 39 42 64 9 7448 5 492 794 6 855 127 8163 38 9 198 268 2 395 8 29 347 68 46 462 977 6832 9 312 5169 56 72 5 5121 32 46 71 968 892 7 3 8 125 72 462 22 73 581 264 263 829 245 6 851 16 6411 175 62 31 * + + + + + + * + * + + + * + + + + + * + * + + * * + * + + + * + + + * * + + + * * + * * + * + + + * * * + * + * * + + + + * + + + * * * + * * + + * + * + + * + + * + + * * + + * * * + + * * + * + * * * + + + + * + + + * + + + + + * + * + + * + * + * * + + + * * * * * * + * + * + * + * * * + * + + + * + + + * + * * + * * * + * * + + + + * * + + * + * * + + + * + + * + * * + * * * + + + + + * + * + * * + * + * + * + + + * * + * + * * * * * + + + + + * + * + * * * * * * + * + + * + + + + * * + * * + + * * * * + * * * + * * + * + + + * * + + + + * * * * * * + * * * + + + + * + + + + * + * * + * + * * + + * * + + * * + * + + * * * * + + * + * + + + * + + * + + + * + + + * + + * * * * * * + + + + + * * + * + + * * * * + * * + + * + * * + + + + + + + + * * * + * + + * + + + * * * + * * + * + * * + * + + + * * * + + + + + * * + + + + + + * + + + + * + * + + + * * + + + * * + * * + * * + * * + * + * * + * * + * * * + * * + + + * + + + + + * * + * + * * * * * + * * + + + * * * + + + * * * * + * * * * * * + * * + * + * * + * + * + + * + + + * + * + * * * + + * + + + * * * + + * + + * * * * * + * + + + + + + * * * + + * * + * + + * + * * * * + * * * * + * * + * * + + * + + + * * + * + + + + + + + + + + + * + + + + * * + + * * + + + + + + * + * * + * * * * + + + + * + + * * * * + + * + + * + + + * * + * + * + * * * + + * * * * + * * * * + + + * * + + * + * * + * * + * + * * * * + + * + + + * + * + + * + + * * * * + + + + + * * * + * + + + + + * * * + + + + + + + * * + + * + + + * + * + * * * * + * * + + * + * * + * * * * * * + + * + + + + + * * * + * + * + + * * + + * * + * + + * * + * * + + * * + + + * * + * + + + * * + * + + * + * + + + * * * * * + * * * * * + * + * + + + * * * + * + + + + * * + + * * + * + + + + * * + * + + + + * * + * * * + + * * + * + + + + * + * + * * + * + * + + * + + * + * * * * + + + * * * + * * + * + + + * * + * * + * + + * + * * + + * * * * + + * + * + + + + * * + + + * * * + + * + * + + * + * + * + + * * + * * * * * * + + * + * + * + * * + + + * + ================================================ FILE: exm/aoc/2025/aoc_2025_06_questions.txt ================================================ --- Day 6: Trash Compactor --- After helping the Elves in the kitchen, you were taking a break and helping them re-enact a movie scene when you over-enthusiastically jumped into the garbage chute! A brief fall later, you find yourself in a garbage smasher. Unfortunately, the door's been magnetically sealed. As you try to find a way out, you are approached by a family of cephalopods! They're pretty sure they can get the door open, but it will take some time. While you wait, they're curious if you can help the youngest cephalopod with her math homework. Cephalopod math doesn't look that different from normal math. The math worksheet (your puzzle input) consists of a list of problems; each problem has a group of numbers that need to either be either added (+) or multiplied (*) together. However, the problems are arranged a little strangely; they seem to be presented next to each other in a very long horizontal list. For example: 123 328 51 64 45 64 387 23 6 98 215 314 * + * + Each problem's numbers are arranged vertically; at the bottom of the problem is the symbol for the operation that needs to be performed. Problems are separated by a full column of only spaces. The left/right alignment of numbers within each problem can be ignored. So, this worksheet contains four problems: 123 * 45 * 6 = 33210 328 + 64 + 98 = 490 51 * 387 * 215 = 4243455 64 + 23 + 314 = 401 To check their work, cephalopod students are given the grand total of adding together all of the answers to the individual problems. In this worksheet, the grand total is 33210 + 490 + 4243455 + 401 = 4277556. Of course, the actual worksheet is much wider. You'll need to make sure to unroll it completely so that you can read the problems clearly. Solve the problems on the math worksheet. What is the grand total found by adding together all of the answers to the individual problems? --- Part Two --- The big cephalopods come back to check on how things are going. When they see that your grand total doesn't match the one expected by the worksheet, they realize they forgot to explain how to read cephalopod math. Cephalopod math is written right-to-left in columns. Each number is given in its own column, with the most significant digit at the top and the least significant digit at the bottom. (Problems are still separated with a column consisting only of spaces, and the symbol at the bottom of the problem is still the operator to use.) Here's the example worksheet again: 123 328 51 64 45 64 387 23 6 98 215 314 * + * + Reading the problems right-to-left one column at a time, the problems are now quite different: The rightmost problem is 4 + 431 + 623 = 1058 The second problem from the right is 175 * 581 * 32 = 3253600 The third problem from the right is 8 + 248 + 369 = 625 Finally, the leftmost problem is 356 * 24 * 1 = 8544 Now, the grand total is 1058 + 3253600 + 625 + 8544 = 3263827. Solve the problems on the math worksheet again. What is the grand total found by adding together all of the answers to the individual problems? ================================================ FILE: exm/aoc/2025/aoc_2025_07.adb ================================================ -- Solution to Advent of Code 2025, Day 7 ------------------------------------------ -- Laboratories -- -- https://adventofcode.com/2025/day/7 -- Copy of questions in: aoc_2025_07_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; procedure AoC_2025_07 is use AoC_Toolbox, HAT; -- input_name : constant VString := +"mini"; m : constant := 16; n : constant := 15; input_name : constant VString := +"aoc_2025_07"; m : constant := 142; n : constant := 141; map : array (1 .. m, 1 .. n) of Character; j0 : Positive; r : array (Part_Type) of VString; procedure Read_Data is f : File_Type; c : Character; begin Open (f, input_name & ".txt"); for i in 1 .. m loop for j in 1 .. n loop Get (f, c); map (i, j) := c; if c = 'S' then j0 := j; end if; end loop; end loop; Close (f); end Read_Data; procedure Do_Part_1 is total : Integer := 0; begin map (2, j0) := '|'; for i in 3 .. m loop for j in 1 .. n loop if map (i - 1, j) = '|' then if map (i, j) = '^' then map (i, j - 1) := '|'; map (i, j + 1) := '|'; total := total + 1; else map (i, j) := '|'; end if; end if; end loop; end loop; r (part_1) := +"" & total; end Do_Part_1; procedure Do_Part_2 is beam : array (1 .. m, 1 .. n) of Natural; total : Integer := 0; begin for i in 1 .. m loop for j in 1 .. n loop beam (i, j) := 0; end loop; end loop; beam (2, j0) := 1; for i in 3 .. m loop for j in 1 .. n loop if beam (i - 1, j) > 0 then if map (i, j) = '^' then beam (i, j - 1) := beam (i, j - 1) + beam (i - 1, j); beam (i, j + 1) := beam (i, j + 1) + beam (i - 1, j); else beam (i, j) := beam (i, j) + beam (i - 1, j); end if; end if; end loop; end loop; for j in 1 .. n loop total := total + beam (n, j); end loop; r (part_2) := +"" & total; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 1562. -- Part 2: validated by AoC: 24292631346665. end if; end AoC_2025_07; ================================================ FILE: exm/aoc/2025/aoc_2025_07.txt ================================================ ......................................................................S...................................................................... ............................................................................................................................................. ......................................................................^...................................................................... ............................................................................................................................................. .....................................................................^.^..................................................................... ............................................................................................................................................. ....................................................................^.^.^.................................................................... ............................................................................................................................................. ...................................................................^.....^................................................................... ............................................................................................................................................. ..................................................................^.^.^.^.^.................................................................. ............................................................................................................................................. .................................................................^.^...^...^................................................................. ............................................................................................................................................. ................................................................^.^.^.^.^.^.^................................................................ ............................................................................................................................................. ...............................................................^.^.^.....^.^.^............................................................... ............................................................................................................................................. ..............................................................^.^.^.^...^.^.^.^.............................................................. ............................................................................................................................................. .............................................................^.^.^.^.......^.^.^............................................................. ............................................................................................................................................. ............................................................^.^.^...^.^...^.^.^.^............................................................ ............................................................................................................................................. ...........................................................^.^.^...^.^...^.^.^.^.^........................................................... ............................................................................................................................................. ..........................................................^...^.....^.^.^.^.^.^...^.......................................................... ............................................................................................................................................. .........................................................^.^.......^.^...^.^.^...^.^......................................................... ............................................................................................................................................. ........................................................^.^.^.^.^...^.....^.^.....^.^........................................................ ............................................................................................................................................. .......................................................^.^.^.^.^.^...^.^.....^.^...^.^....................................................... ............................................................................................................................................. ......................................................^.^.^...^...^...^...^.^.^.^.^.^.^...................................................... ............................................................................................................................................. .....................................................^.^...^...^...^.^.^.^.^.^...^.^...^..................................................... ............................................................................................................................................. ....................................................^.^.^.....^.^.........^...^.^.^.....^.................................................... ............................................................................................................................................. ...................................................^...^.^.^.....^.^.^...^...^.....^.^.^.^................................................... ............................................................................................................................................. ..................................................^.^.^.^.^.^.^...^.^.^...^...^.......^...^.................................................. ............................................................................................................................................. .................................................^...^.....^.^.^.^.....^.^...^.....^.^.^...^................................................. ............................................................................................................................................. ................................................^...^.....^.^.^.^.^.^.^.^.^.^.............^.^................................................ ............................................................................................................................................. ...............................................^.^.^.....^.^.....^.^.^.^.^.....^.....^...^.^.^............................................... ............................................................................................................................................. ..............................................^...^.^.^.^.^.^.^.^.^.^.^.^.^.....^...^.^.^.^...^.............................................. ............................................................................................................................................. .............................................^.^.^...^.^.^...^...^.^.^.....^...^.....^.^.^...^.^............................................. ............................................................................................................................................. ............................................^.^.......^.^.^.^.....^.......^.^.^...^.^.........^.^............................................ ............................................................................................................................................. ...........................................^...^...^...^...^.^.........^.^...^.^.....^.....^.^.^.^........................................... ............................................................................................................................................. ..........................................^...^.^...^.^.^.^.^...^.^.^.^.^.^.....^...^...^.^.^.^.^.^.......................................... ............................................................................................................................................. .........................................^.^...^.^...^.^.....^.^.......^.^.....^.^.^.^.^.^...^.^.^.^......................................... ............................................................................................................................................. ........................................^.^...^.^...^.^.......^.......^.^.^.^.^.^.^.......^.^.^...^.^........................................ ............................................................................................................................................. .......................................^.^.^...^.^...^.^...^.^...^.....^.^.^...^.......^...^.^.^.^.^.^....................................... ............................................................................................................................................. ......................................^.....^.^.....^.....^...^...^.^.^...^.^.^.^.....^.^.^...^.^.^...^...................................... ............................................................................................................................................. .....................................^.^.....^.^.^...^.....^.^.^.^...^.^.......^.^...^.^.^...^.^.^.^.^.^..................................... ............................................................................................................................................. ....................................^.^.^.^...^.......^.^...^...^.....^...^...^.^...^.^.^.......^.^.^...^.................................... ............................................................................................................................................. ...................................^.^.....^.....^.^.^.^.^.^...^.^.^.^.^.^.....^.^...^.^...^.^.^...^.....^................................... ............................................................................................................................................. ..................................^...^...^.^.^...^.^.^.....^.^.^.....^.^.^.^.^.^.^.^.......^.^...^.^.^.^.^.................................. ............................................................................................................................................. .................................^.^...^.^.^.^.^...^.^...^.^.^.^.......^.^.^.^.^...^...^.^.^.^.^.^.^.......^................................. ............................................................................................................................................. ................................^...^.^.^...^.^.^.^.^...^.^.^...^...^.^...^.^.......^.^.^.^.^.....^.^.^.^.^.^................................ ............................................................................................................................................. ...............................^.^.^.^.^...^.^.^.....^.^...^...^.^...^.^.^.^.^...^.^.^.^.^...^.^.^.^.^.^.^.^.^............................... ............................................................................................................................................. ..............................^.^.^.....^...^.^.^.^...^...^.^.^.^.^.^.^...^.^.^.......^...^.^.^.^.^.^...^.^.^.^.............................. ............................................................................................................................................. .............................^.....^.^...^.^.^.^...^.^.^.^...^...^...^.^.^.^.....^.^.......^...^.^...^.^.^.^...^............................. ............................................................................................................................................. ............................^.^.^...^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^...^.^.^.^.^.^.......^.^.^...^.^...^.....^............................ ............................................................................................................................................. ...........................^.^...^...^...^.^.^.^...^.....^...^.^.^.^.^.^.^...^.......^.^.^.^.^...^...^.......^.^.^........................... ............................................................................................................................................. ..........................^.....^...^.^.^.....^.^.^...^...^...^.....^...^...^.^.^.^.^.^.^.^.^.....^...^.^.^.......^.......................... ............................................................................................................................................. .........................^.^.^...^.^.....^.^...^.^.^...^.....^.^.^.^.....^...^...^.^.^...^.^...^.....^.^.^.^.....^.^......................... ............................................................................................................................................. ........................^...^.^.^.^.^.......^.^.^.......^.^.^...^.^.....^.^.^.^.^...^.^.^.......^.^.^.........^.^.^.^........................ ............................................................................................................................................. .......................^.^.^.^.^.....^.^...^.^.^...^.^.^.^...^.^...^...^...^.....^.^.^.^...^.^.^.^...^.......^.^.^.^.^....................... ............................................................................................................................................. ......................^.^.^.^.^.^.....^.^.......^.^.^...^.^.^.^.^.^...^.^.^.^...^.^...^...^.......^.^.^.^...^.^.^.^...^...................... ............................................................................................................................................. .....................^.^.^.^...^.^.^.^.^.^.^...^...^.^.^.....^.^.^...^.^.^.....^.^.^.....^...^.^.^.^.^.^.^.^.^.^...^...^..................... ............................................................................................................................................. ....................^.^...^.^.^.^...^...^.........^.^...^...^...^...^.^...^.^.^...^...^...^...^.^.^.^.^.^.^...^.^.^.....^.................... ............................................................................................................................................. ...................^.^.^...^...^...^.^.^...^.^.^...^.....^.^.^.^.....^.^...^...^.^...^...^.^.^.^.^.^...^.^.^.^...^.....^.^................... ............................................................................................................................................. ..................^.^.......^.^.^...^.^.^...^.^.....^.^.^.^.^.^.^.^.....^...^.^.^.........^.............^.......^...^.^.^.^.................. ............................................................................................................................................. .................^.^.........^...^.^.......^.^.^.^.^.^.^.^.^...^.....^.^.^.^.........^.^.^.^.^.....^...^...^.^.^.^.^...^...^................. ............................................................................................................................................. ................^.^.^...^.^.^.....^.^.^...^.^.^.^...^...^.^...^.^.^.^.^.^...^.^...^.^.^.....^...^.^...^...^.^...^.^.^.....^.^................ ............................................................................................................................................. ...............^.^.^.^.^.^.^.^.....^...^.^.^.^.^...^.........^.^.^.^...^.^.^.....^...^...^.^.^.^.^.^.^.^.^.^...^...^.^.^.^.^.^............... ............................................................................................................................................. ..............^.^.^...^.^.^.^...^.^...^.^.^.^.^.^.^.^.^.^...^.^...^.....^.^...^.............^.^...^.^.^.^.^...^.^.^.^.....^.^.^.............. ............................................................................................................................................. .............^.^.^.^.....^...^...^.....^.^...^...^.......^...^...^.^...^...^.^.^.^.^.^.^.^.^.....^.^.^.^.^.^.^...^...^.^.^.....^............. ............................................................................................................................................. ............^...^.^.^.^.^...^...^.^.^.....^.^.^.^...^.^...^...^...^...^.^.......^.^.^.....^...^...^.^.^.^.^.^.......^.^.^...^.^.^............ ............................................................................................................................................. ...........^.^.^.^.^.^.^.^...^.^...^.^.^.^.^.......^.^.^...^.^.^.^.^.^.^.^...^.^...^.........^.^.^.^.....^...^.^...^.^.^.^.....^.^........... ............................................................................................................................................. ..........^.....^.^.^.....^.....^.....^.^.^.^.^.^.^.^.^.....^.^.^.^.^...^.^.^...^.......^.^...^...^...^.....^...^.^.^.^.^.^.^.^.^.^.......... ............................................................................................................................................. .........^...^...^.^.^.....^.^.^.^.^.^...^...^...^...^.......^.^.^.^.^.^.^...^.^.^.^.^.^.........^...^.^.^...^.^.....^.^.^.^.^.....^......... ............................................................................................................................................. ........^.^.....^.^.^.^...^.^.^.^...^.^.^.^.^.^...^.^.^...^.^.^.^...^...^...^.........^.^.^.^.^.....^.^.^...^.^.^.^.^...^...^.^.^...^........ ............................................................................................................................................. .......^.^.^.^.^.^.^.......^.^.........^.^.^.^.^.^.^.^.^.^.^...^...^.^...^...^...^...^...^.^.....^...^...^...^.^.^.....^...^...^.....^....... ............................................................................................................................................. ......^.^.^...^.^.^.^.^.^.^.......^.^.^.^.^.^.^.^.....^.....^.....^.^.^.^.^.^.^.^...^.^.^.^.^.^...^.^.^.......^.^.....^.^.^.^.....^.^.^...... ............................................................................................................................................. .....^...^.^.^.^.....^...^...^.....^.^.^.^.^.^.^.....^.^.^...^...^.^.^.^.^.^...^...^.^.^.^.....^.^.^.^...^.....^.^...^...^.^...^.^.^.^.^..... ............................................................................................................................................. ....^.^.^...^.^.^.^.^.^...^...^.^.^.^.^...^.^.^.^...^...^.^...^.^.^...^.^.^.^.^.^.....^.^.^.^.^.^.....^...^.^.^.^.^...^.......^...^.....^.... ............................................................................................................................................. ...^.^.^.....^.^.^.^.^.....^...^.....^...^.^.^.^.^...^...^.^.^.^.^.^.^...^.^.^...^.^.^.....^.....^...^.^.^.^.^...^.^...^...^.^...^.^.^.^.^... ............................................................................................................................................. ..^.^.......^.^.^.^...^...^.^.....^.^.^.^.^.^...^.^.....^...^.^.....^.^...^.^.^...^...^.^.^.^.....^.^.^...^...^...^.^.^.^...^.^.^...^.^...^.. ............................................................................................................................................. .^.^...^.^.^...^...^...^.^.....^.^.....^.^.^.^...^.....^.^.^.^...^.^.^.^.^.^...^.^.^.....^.^.^.^.^.^.^...^.^.^.^.....^.^.^.^.^.^.^.^.....^.^. ............................................................................................................................................. ================================================ FILE: exm/aoc/2025/aoc_2025_07_questions.txt ================================================ --- Day 7: Laboratories --- You thank the cephalopods for the help and exit the trash compactor, finding yourself in the familiar halls of a North Pole research wing. Based on the large sign that says "teleporter hub", they seem to be researching teleportation; you can't help but try it for yourself and step onto the large yellow teleporter pad. Suddenly, you find yourself in an unfamiliar room! The room has no doors; the only way out is the teleporter. Unfortunately, the teleporter seems to be leaking magic smoke. Since this is a teleporter lab, there are lots of spare parts, manuals, and diagnostic equipment lying around. After connecting one of the diagnostic tools, it helpfully displays error code 0H-N0, which apparently means that there's an issue with one of the tachyon manifolds. You quickly locate a diagram of the tachyon manifold (your puzzle input). A tachyon beam enters the manifold at the location marked S; tachyon beams always move downward. Tachyon beams pass freely through empty space (.). However, if a tachyon beam encounters a splitter (^), the beam is stopped; instead, a new tachyon beam continues from the immediate left and from the immediate right of the splitter. For example: .......S....... ............... .......^....... ............... ......^.^...... ............... .....^.^.^..... ............... ....^.^...^.... ............... ...^.^...^.^... ............... ..^...^.....^.. ............... .^.^.^.^.^...^. ............... In this example, the incoming tachyon beam (|) extends downward from S until it reaches the first splitter: .......S....... .......|....... .......^....... ............... ......^.^...... ............... .....^.^.^..... ............... ....^.^...^.... ............... ...^.^...^.^... ............... ..^...^.....^.. ............... .^.^.^.^.^...^. ............... At that point, the original beam stops, and two new beams are emitted from the splitter: .......S....... .......|....... ......|^|...... ............... ......^.^...... ............... .....^.^.^..... ............... ....^.^...^.... ............... ...^.^...^.^... ............... ..^...^.....^.. ............... .^.^.^.^.^...^. ............... Those beams continue downward until they reach more splitters: .......S....... .......|....... ......|^|...... ......|.|...... ......^.^...... ............... .....^.^.^..... ............... ....^.^...^.... ............... ...^.^...^.^... ............... ..^...^.....^.. ............... .^.^.^.^.^...^. ............... At this point, the two splitters create a total of only three tachyon beams, since they are both dumping tachyons into the same place between them: .......S....... .......|....... ......|^|...... ......|.|...... .....|^|^|..... ............... .....^.^.^..... ............... ....^.^...^.... ............... ...^.^...^.^... ............... ..^...^.....^.. ............... .^.^.^.^.^...^. ............... This process continues until all of the tachyon beams reach a splitter or exit the manifold: .......S....... .......|....... ......|^|...... ......|.|...... .....|^|^|..... .....|.|.|..... ....|^|^|^|.... ....|.|.|.|.... ...|^|^|||^|... ...|.|.|||.|... ..|^|^|||^|^|.. ..|.|.|||.|.|.. .|^|||^||.||^|. .|.|||.||.||.|. |^|^|^|^|^|||^| |.|.|.|.|.|||.| To repair the teleporter, you first need to understand the beam-splitting properties of the tachyon manifold. In this example, a tachyon beam is split a total of 21 times. Analyze your manifold diagram. How many times will the beam be split? --- Part Two --- With your analysis of the manifold complete, you begin fixing the teleporter. However, as you open the side of the teleporter to replace the broken manifold, you are surprised to discover that it isn't a classical tachyon manifold - it's a quantum tachyon manifold. With a quantum tachyon manifold, only a single tachyon particle is sent through the manifold. A tachyon particle takes both the left and right path of each splitter encountered. Since this is impossible, the manual recommends the many-worlds interpretation of quantum tachyon splitting: each time a particle reaches a splitter, it's actually time itself which splits. In one timeline, the particle went left, and in the other timeline, the particle went right. To fix the manifold, what you really need to know is the number of timelines active after a single particle completes all of its possible journeys through the manifold. In the above example, there are many timelines. For instance, there's the timeline where the particle always went left: .......S....... .......|....... ......|^....... ......|........ .....|^.^...... .....|......... ....|^.^.^..... ....|.......... ...|^.^...^.... ...|........... ..|^.^...^.^... ..|............ .|^...^.....^.. .|............. |^.^.^.^.^...^. |.............. Or, there's the timeline where the particle alternated going left and right at each splitter: .......S....... .......|....... ......|^....... ......|........ ......^|^...... .......|....... .....^|^.^..... ......|........ ....^.^|..^.... .......|....... ...^.^.|.^.^... .......|....... ..^...^|....^.. .......|....... .^.^.^|^.^...^. ......|........ Or, there's the timeline where the particle ends up at the same point as the alternating timeline, but takes a totally different path to get there: .......S....... .......|....... ......|^....... ......|........ .....|^.^...... .....|......... ....|^.^.^..... ....|.......... ....^|^...^.... .....|......... ...^.^|..^.^... ......|........ ..^..|^.....^.. .....|......... .^.^.^|^.^...^. ......|........ In this example, in total, the particle ends up on 40 different timelines. Apply the many-worlds interpretation of quantum tachyon splitting to your manifold diagram. In total, how many different timelines would a single tachyon particle end up on? ================================================ FILE: exm/aoc/2025/aoc_2025_08.adb ================================================ -- Solution to Advent of Code 2025, Day 8 ------------------------------------------ -- Playground. -- -- https://adventofcode.com/2025/day/8 -- Copy of questions in: aoc_2025_08_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; with Interfaces; procedure AoC_2025_08 is use AoC_Toolbox, HAT, Interfaces; n : Natural := 0; rounds : Positive; input_name : VString; r : array (Part_Type) of VString; subtype max_range is Integer range 1 .. 1000; box : array (max_range) of Point_3D; procedure Read_Data is dummy_comma : Character; f : File_Type; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop n := n + 1; Get (f, box (n).x); Get (f, dummy_comma); Get (f, box (n).y); Get (f, dummy_comma); Get (f, box (n).z); end loop; Close (f); end Read_Data; verbose : constant Boolean := False; procedure Do_Parts is size, size_1, size_2, size_3, max_size : Natural; best_i, best_j : Positive; best, dist2 : Integer_64; pair_connected : array (max_range, max_range) of Boolean; -- We use only the upper triangle (i < j). circuit : array (max_range) of Natural; c_j : Positive; begin for i in 1 .. n loop circuit (i) := i; for j in 1 .. n loop pair_connected (i, j) := False; end loop; end loop; for round in Positive loop best := Integer_64'Last; for i in 1 .. n loop for j in i + 1 .. n loop dist2 := Integer_64 (box (i).x - box (j).x) ** 2 + Integer_64 (box (i).y - box (j).y) ** 2 + Integer_64 (box (i).z - box (j).z) ** 2; if dist2 < best and then not pair_connected (i, j) then best := dist2; best_i := i; best_j := j; end if; end loop; end loop; pair_connected (best_i, best_j) := True; -- Merge circuits. for i in 1 .. n loop for j in i + 1 .. n loop if pair_connected (i, j) then c_j := circuit (j); for k in 1 .. n loop if circuit (k) = c_j then circuit (k) := circuit (i); end if; end loop; end if; end loop; end loop; if round = rounds then size_1 := 1; size_2 := 1; size_3 := 1; for c in 1 .. n loop size := 0; for i in 1 .. n loop if circuit (i) = c then size := size + 1; end if; end loop; if verbose then if size > 1 then Put_Line (+"Size: " & size); for i in 1 .. n loop if circuit (i) = c then Put_Line (+" " & box (i).x & ", " & box (i).y & ", " & box (i).z); end if; end loop; end if; end if; if size > size_1 then size_3 := size_2; size_2 := size_1; size_1 := size; elsif size > size_2 then size_3 := size_2; size_2 := size; elsif size > size_3 then size_3 := size; end if; end loop; r (part_1) := +"" & size_1 * size_2 * size_3; end if; if verbose then Put_Line (+"Circuit list, round " & round); for c in 1 .. n loop size := 0; for i in 1 .. n loop if circuit (i) = c then size := size + 1; end if; end loop; Put_Line (+" circuit " & c & ": " & size); end loop; end if; max_size := 0; for c in 1 .. n loop size := 0; for i in 1 .. n loop if circuit (i) = c then size := size + 1; end if; end loop; max_size := Max (max_size, size); end loop; if max_size = n then if verbose then Put (+"" & box (best_i).x & ", " & box (best_j).x); Put_Line (+"Final round = " & round); end if; r (part_2) := Trim_Both (+"" & Integer_64'Image (Integer_64 (box (best_i).x) * Integer_64 (box (best_j).x))); exit; end if; end loop; end Do_Parts; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin if compiler_test_mode then input_name := +"aoc_2025_08_mini"; rounds := 10; else input_name := +"aoc_2025_08"; rounds := 1000; end if; Read_Data; Do_Parts; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 72150 (mini: 40). -- Part 2: validated by AoC: 3926518899 (mini: 25272). end if; end AoC_2025_08; ================================================ FILE: exm/aoc/2025/aoc_2025_08.txt ================================================ 97087,38864,23753 75016,36080,24819 30660,97751,22587 59383,11790,81126 2600,8401,80432 46494,70797,47058 81732,20950,69200 15728,92220,74530 54831,40458,91147 89441,6168,34566 72454,92628,51454 77856,17035,10876 28523,97878,71598 76225,80828,17571 26470,5547,70927 51295,63717,52536 46497,18958,68258 23193,28622,49485 87424,10885,44181 80738,63528,37589 87670,55102,94358 40880,50031,6830 38549,67920,77663 39036,36994,88345 41639,71553,74006 16909,80500,83974 28873,7268,88436 85846,41546,93048 20012,74589,27198 77547,71990,24027 60618,14924,38900 17154,20294,52963 61320,56700,36468 79242,41846,68987 50563,1498,73464 49557,33592,11047 46615,73849,67322 1081,95388,30075 98047,4511,38627 93255,83340,57782 29717,94577,66723 5774,68659,95647 3861,20635,53818 26628,92003,85496 68241,15467,7597 77509,49485,24373 66205,98086,82794 22386,85405,29848 68704,89280,51779 27029,38642,47315 84271,60574,49976 11589,10437,71306 66803,96256,61748 29100,89168,98830 77224,36565,3825 45689,29133,50145 99081,32962,44012 56545,77873,53900 50439,38918,62693 8911,940,85181 66969,41485,68611 34252,96481,2757 34091,67890,85439 91267,50465,43388 92272,41303,92974 21735,14555,92943 77443,87368,98735 96458,22360,28460 43795,10997,60603 64382,36955,7627 99601,71857,30302 85775,25087,89886 18421,43215,30783 31479,15815,87092 91888,16999,48348 48416,36846,78393 62755,27322,82861 88363,52398,90553 4342,5515,84104 6651,88662,21598 60674,5603,84490 64962,45338,7046 68766,84441,19302 69877,98980,77998 10918,73415,97647 72818,76946,69416 51249,29239,92705 20590,31927,65323 11300,16278,47940 56199,33153,82920 49505,90987,18854 65720,6827,97637 22227,79692,3627 13700,90239,21153 64704,69760,3780 3981,42328,6289 32918,74804,1547 98004,74426,55201 66870,60013,83220 21170,65747,43971 15997,26311,41519 51096,70514,97639 19266,31988,31206 25481,21444,64953 57703,52068,21290 97883,71478,59023 35513,60856,84330 10616,34277,53701 55678,27448,46413 45081,81211,20837 67270,86441,79006 89774,11792,8916 8838,74779,67897 86338,2446,32523 87014,79452,95714 74768,36728,30740 94847,39339,42645 25677,17350,90584 65448,33374,72148 94754,17905,60155 61769,70908,93806 5573,41174,71348 95137,77478,73268 14174,39334,65991 9099,43383,59702 74631,52496,74418 78580,78403,63883 41996,4722,5589 18059,76201,48913 93374,65858,17110 50787,32689,2465 39373,95901,18892 16125,99439,76959 50709,63568,69224 12876,47512,83549 62337,1315,76088 41578,50487,6477 23129,78865,67689 6812,13357,81241 94658,74821,39149 61762,42645,81381 33585,69019,29317 3381,21718,54835 74742,29928,25553 5822,85342,67749 66525,16866,31768 20311,9342,47353 33425,82189,65834 97164,9726,45411 34171,96115,44692 48152,83544,52553 87344,19009,17575 21844,2043,37966 10414,59050,18808 74498,21361,20396 68487,95430,59021 91459,27696,2332 1344,95089,26735 47281,38607,75772 74663,44615,12423 59019,40304,97320 83624,41669,58905 63437,98368,12025 50587,18468,96639 15403,79238,13253 46540,41850,16584 67042,6189,96944 24460,77059,41763 35394,24430,18341 33221,59517,84585 71127,10737,63046 42389,62869,6006 94508,74728,83658 8576,16759,73620 8549,62635,245 41541,89066,62477 40807,63838,5828 32755,79201,78529 71412,54033,93124 53882,49789,95670 64994,11008,98088 91276,14645,28240 16226,70709,47843 24061,7987,94376 64254,99744,57075 7507,5168,97602 17110,94723,97769 87947,14709,8846 72638,81464,99053 26168,30767,94065 14264,36722,10196 90440,67746,69309 27159,48948,58556 23527,27433,24272 75493,94978,98072 12181,81043,34540 33237,20822,40668 41440,78891,30192 8916,5360,65669 32015,36246,51336 76250,19182,50586 8479,39839,71581 2936,89039,41326 24696,49678,86903 23853,21266,98765 56820,30926,23841 41077,29519,15927 97872,60801,29118 63702,78420,3699 52853,49378,77354 34018,28210,65230 17691,29302,96959 96408,44150,17404 71708,22734,27940 17064,39333,76512 84050,87993,32554 37935,52797,59518 80068,760,67110 89823,65558,74789 62930,7116,53954 99398,73462,16668 71075,47813,36713 85803,80701,86889 99366,74952,85960 86220,4479,94918 73271,15883,43426 86385,14786,39331 48142,31080,86006 59639,13618,78614 40122,59427,15235 67900,99276,40995 14643,16596,79707 9738,1839,71027 5367,95212,72069 47415,90466,97234 82421,43336,81569 13931,24834,66914 54588,22617,16232 76084,10716,67901 70894,67753,21239 73159,39718,28408 36858,47337,82183 95455,19011,58014 62319,69732,24372 90399,14470,21458 97528,22412,92748 25330,40385,14771 54176,97326,86283 23527,4059,79184 12494,1187,15340 48189,32635,45117 20993,62162,1649 58430,21013,11653 36354,55533,80407 51555,4208,16732 23506,35498,97147 12781,41393,84711 24838,7923,30341 42623,13249,83124 20249,50445,31548 38137,66623,7317 39323,59312,8610 82379,14132,21119 13000,33556,98438 3725,61686,68124 77716,1382,12277 89522,45666,431 90922,778,26277 69218,17908,41670 49347,11962,33388 89957,29719,45466 78407,48963,90138 1535,98811,18448 22561,92883,13140 23332,77652,99553 14428,77470,52243 93184,36989,35893 49848,64379,97641 38727,80723,13988 34111,50181,51288 11691,87027,24574 44344,78325,64232 93402,82927,64200 53290,19013,93764 40881,8937,34625 78373,4052,93527 21698,68368,69717 29872,24871,89301 93915,84546,84709 7604,30053,16046 68237,56253,69615 33915,87610,65579 67487,43129,35435 56,97068,21103 114,74538,92093 54139,1569,93859 29379,65242,53686 97940,71942,97926 88512,66095,96121 90974,93502,24459 54834,29548,18878 40604,6153,89253 10381,80502,50447 84923,43384,41815 47771,86172,58692 80772,21564,91094 86320,79991,25548 39556,50692,93847 52702,62960,64854 84463,81908,80455 80337,72986,87213 67520,77081,71166 13314,4667,70361 91051,49801,7491 20996,14923,5861 97994,55231,22907 394,87554,1993 46598,83159,48246 9588,38611,97472 78566,10013,10592 80575,56769,6868 6409,84174,87719 99139,99092,34197 12870,46012,55785 48879,75969,82216 26089,367,35539 15546,17717,53511 37934,60968,16358 2156,18652,73749 41817,67383,74060 48153,62469,32874 38199,11270,88171 92193,39995,2424 46302,33500,93042 28224,5474,14651 53920,88869,30662 879,54364,1708 36418,77206,79028 98612,1282,76592 93152,41576,36372 14504,75370,9366 79830,12599,39998 32492,51968,63413 32973,45535,34502 9048,6900,38414 82524,17894,56443 1219,86357,72135 66927,2107,39110 66425,70179,22370 46767,45416,44338 6658,23585,19397 52881,5422,24167 26680,15054,78641 73090,6569,90207 58853,6785,94331 55470,3263,54221 627,55248,91425 62063,32138,6106 90666,45543,1834 87892,36256,93235 59273,35892,79574 17082,935,46226 93425,58824,43809 2752,89509,1113 22686,45768,75470 91800,2072,6582 36085,49807,40813 85673,69891,51719 63765,21907,5185 92212,46650,84911 90738,5352,13316 79174,41350,35540 48380,16036,77356 59173,1563,36051 43245,3900,75540 29297,12517,60515 58782,43041,74848 71383,64326,5664 74496,43278,29925 61400,94826,25783 3237,63742,8011 18807,96040,35506 78529,94262,25741 72644,97496,2854 42055,56754,57153 72947,46890,90506 52880,25537,80370 81523,26830,28645 54178,56698,72729 92748,42199,81839 86751,82836,79461 14638,32648,54698 4132,14156,49913 45569,98378,31740 57759,90110,26102 88989,32657,40042 26465,13138,77308 33031,38733,12161 69911,47438,7020 76670,26697,53304 33020,46987,21881 5959,14824,68024 57667,51474,73325 16037,34918,18025 31892,46976,40897 44195,75894,20887 94377,55260,86724 68367,96915,97204 69381,8839,60516 2151,86900,14725 71042,9488,81357 56655,9814,46142 16348,11387,75966 64461,75285,73100 13589,4488,13261 69527,61607,41848 96196,44461,73370 76288,92388,57670 36061,27373,70076 60190,98192,21928 26302,98043,53735 66476,41918,59430 52872,1522,54236 20612,7161,82969 30497,33430,28248 48994,44256,84612 7527,23866,24058 3703,84491,19072 94720,95134,15639 97604,40476,71296 96825,20717,24427 587,89769,44435 27867,98619,89297 42442,67298,55778 49804,14974,87181 42048,76779,82463 57122,74951,18116 35737,57033,865 47917,19796,60588 79232,86740,8944 12809,86091,12502 1139,92760,63788 77734,27950,97055 41389,5578,72847 28132,71397,9010 89381,16213,67420 87564,57238,2513 61194,51435,48362 9930,10953,4787 58186,86280,4036 64716,94209,23552 80463,78007,82189 97897,19201,29296 20531,91777,41105 67923,78001,18086 91114,49451,25864 72064,23657,26048 30445,59703,69292 88808,8850,50060 54428,77003,92151 46101,59895,13632 15376,76132,76071 93968,770,51631 63096,61546,54198 82027,82888,22882 8540,61971,96861 23761,22278,69762 38433,82952,46190 19062,74821,27384 71393,61018,78100 21164,53740,25712 73566,31104,3528 44638,24851,26635 37042,98309,33021 2268,4147,62286 62357,17088,50839 72554,82457,26318 9664,27860,16593 94127,66582,86790 74267,10578,58220 84962,94230,26636 56431,90261,37790 83536,91393,68549 14230,62298,13615 49459,36301,58067 58490,51813,47588 86160,33731,54801 21668,22427,24813 27421,49475,42044 1578,61932,33255 46417,625,93425 27841,7768,63756 37261,80327,41744 88462,88485,43053 68357,18556,15673 80501,95412,93074 48461,74266,62739 21527,19901,714 2883,50427,37025 19927,88922,87659 35636,61735,63760 10078,36629,22217 40250,69242,84237 22445,66961,48673 72963,18199,11022 2235,85760,55838 84556,1386,86000 24052,53657,43383 59042,65235,13933 72842,53789,53031 91514,65344,62697 66127,56426,29413 21323,52624,91608 37692,41149,76855 97254,80681,86172 21902,79654,97991 3172,19548,56351 29515,44965,36138 36260,8991,26964 31711,12626,7341 10397,62529,47511 5515,55359,28405 65195,14091,67132 98219,95841,57781 17564,35112,84308 50711,46772,99788 67756,16635,89678 32200,21952,66222 67006,2019,23861 60588,85271,13324 97550,41036,98149 42956,23597,34580 49380,62149,47716 93544,91424,22172 22197,55993,14609 94454,30620,27975 27694,19602,60591 64766,66326,95976 5415,38063,22773 93459,50343,11312 55508,10287,64973 43337,56036,57465 15150,8468,92363 95541,86293,62600 72694,9980,88090 21878,51678,74106 77068,22682,46969 50636,79453,36939 21650,44892,39184 59601,83296,73668 23890,19868,32010 14619,40348,93992 75807,71371,87575 85442,4364,31317 83571,52976,42457 15998,66167,94639 77917,71029,90885 66619,99564,13879 32570,31633,77153 36974,72466,88699 44900,41673,99871 51530,4507,79369 35241,78709,73079 81386,49281,47748 60742,33672,96105 34861,55665,68163 35496,61052,18458 5131,4012,86307 80239,52844,22653 41069,60,98392 42498,36880,57616 59896,22862,75475 40506,2308,79623 2353,74441,90560 6297,22087,47304 92117,55824,98570 89633,80927,26914 14703,5433,3917 51845,18745,47416 75124,61084,64848 13322,69549,58708 84777,7125,14942 87798,48438,77430 74054,79572,69722 70584,78929,48532 48917,37690,12296 29385,66279,21490 26385,12502,26563 43750,76610,62379 19716,78060,14630 38743,97415,52902 3109,49764,52656 205,61577,70284 34697,74523,40669 50351,83909,85449 19860,17672,50588 43039,83737,65418 83835,34128,13617 89211,76890,61630 27714,45734,14694 63592,64541,3477 39356,22317,63994 23509,76013,3704 99921,76025,12390 74528,30693,74884 12229,11380,92105 6721,48296,83914 74588,79658,42650 687,26223,6625 98455,95913,60027 34074,42306,96793 30966,94206,82517 94444,81330,89796 36258,87021,35840 59422,16153,25121 96645,37623,69727 60300,37557,41178 77871,34497,3270 27977,81664,97542 68072,88852,81099 62133,17119,21920 40388,99748,57286 81685,18960,10603 2340,96209,96469 18106,74532,61280 66095,10117,20970 83802,70279,80908 14702,91861,54392 89043,37110,17290 19397,95815,67242 585,87616,59349 15250,56852,24610 42787,69227,65880 23736,26885,98193 26671,92232,62970 97334,15685,33095 40442,36435,54087 95248,91876,97783 69365,35631,611 67917,4371,66070 81388,88171,7269 30968,59753,14754 30597,9687,4451 90614,80007,61498 57774,71813,12947 27550,38725,71720 75996,90425,54865 10990,44608,29738 81078,71667,50165 34322,42040,14513 32545,65809,53452 2011,79434,62823 33035,80864,20516 51205,66931,67009 17631,9040,25834 70119,44501,10001 1712,80500,47067 42391,16412,20824 72408,84358,29262 39221,2209,56280 18927,51552,65180 91163,23427,55521 84002,31474,61757 49021,55725,83294 78468,85980,99608 68236,14192,95210 3075,45352,86176 76896,49112,23516 35046,25239,26606 69247,3663,34279 61162,56123,62688 2797,54066,89510 88104,40344,17460 31908,3484,69138 97856,83332,44447 93511,925,10842 97198,74425,96961 82986,2624,50762 66901,17935,99361 11785,74995,50193 20274,97142,63246 34727,86842,27466 83431,98880,2404 47460,42966,72805 14773,52946,36804 46177,98401,82349 15042,64973,56242 67918,2083,1391 95715,61126,70761 41596,86269,89916 54544,69471,73217 61448,73245,46184 8208,42084,9281 84638,73887,92129 16242,45377,24704 98649,78396,76452 41186,79384,98196 37931,37636,44755 43568,85323,67395 25163,82769,92331 12660,45834,12220 18098,12058,61339 2591,27949,86670 23388,56573,58661 49173,26735,64334 42980,79805,63797 31366,25948,92873 75295,30072,83990 97505,44723,28280 2302,33083,83235 82392,46430,72749 49684,52921,38839 84992,60535,28924 93315,3694,55539 3670,81274,19203 87926,65650,80092 87817,19927,90793 49603,92966,94322 97819,77737,40036 66078,58928,48114 47242,61638,12261 93269,9334,61000 66350,78393,69083 94045,5567,97094 76144,9645,30438 77288,44428,16918 98864,79991,20973 42495,70301,4260 42423,77076,11815 79050,3735,56900 64736,58088,79181 82772,83512,96545 11632,6234,25620 40682,38105,32750 88366,72664,15106 56907,73279,13979 43754,91376,88401 28812,84230,71721 76369,53652,95893 50450,19245,14254 89708,80403,66093 92858,4795,96776 47371,99339,37775 46433,30006,70921 19042,26837,33089 55381,27212,16518 28339,86391,91524 4993,86696,86838 93950,11853,74348 45118,85580,35699 80711,84942,32998 13572,67055,2186 62612,9096,54828 35347,47510,5454 57539,8465,733 19442,87321,77467 89715,1008,7668 90357,53130,53874 36170,57067,87801 36014,36563,11742 29573,42009,47387 35571,97887,64788 27167,15647,24804 3111,12929,19716 80863,58628,82921 19876,23518,26876 36041,53376,80120 68333,82903,45529 83218,76290,27992 69708,68119,79161 82676,90347,33430 6630,16910,36290 37255,56220,47647 19788,32609,53327 96781,38467,33598 51051,85936,37925 92516,53261,82681 36899,70904,16048 68519,17552,13931 28965,66879,4098 16643,52330,85868 14259,77250,83318 89754,91750,11827 98854,92349,62816 96915,23471,49270 5715,72073,55778 32305,55832,79486 57066,73279,68782 18600,23471,25062 34459,21821,81285 70023,32672,4730 30085,10037,78802 48012,15777,53938 60173,36039,15212 17637,71773,11560 14249,16247,35966 30379,34911,36857 24224,82701,26308 72780,80367,27817 54283,96257,91532 99942,71064,75133 34083,39909,97745 61444,82204,89495 27106,15435,54056 22735,34314,79203 57590,46698,39619 89935,10550,68794 85448,66157,48469 29412,94761,12055 3868,39104,56379 48062,69056,35013 13821,81691,25451 98754,8365,4824 24285,72533,76682 8929,65860,58032 72261,81579,10533 88192,43583,19907 30592,36415,70874 49191,55612,39300 90630,8994,59667 12957,39653,15578 75402,63757,96091 99487,93938,86111 66282,24638,46413 15359,86925,5073 10266,68540,61484 73473,76011,9735 38112,31705,15896 46511,19969,77599 40019,28038,3703 67085,16462,28339 89708,39172,85855 66383,40530,19662 66587,21109,68487 83376,31151,28546 67961,13780,26611 10956,24518,61807 10132,46986,5292 95309,4143,86319 81389,8482,33022 83018,42103,52992 54943,35907,16650 74081,27377,783 26326,14721,54072 73481,98095,57078 24460,31638,99743 35140,25260,90144 22113,96585,38650 45719,71360,51154 34184,11422,24409 91106,63368,25590 95260,45351,9585 41281,5044,59769 73100,93301,11565 46879,68240,77853 76624,16520,84602 54342,88502,9387 164,23736,12809 50980,25318,51545 74715,48232,66808 71341,78988,35249 45112,12542,12230 7133,32688,35326 24218,21233,32049 91827,3032,88490 94490,71539,18298 48359,59665,64611 6588,97509,23673 33973,97767,76096 89916,81291,29986 68469,97610,59838 89976,98632,90360 5922,40508,39414 5331,52238,24507 9392,69230,56837 22212,37422,88297 82,23376,92265 18408,27596,8256 16873,21576,22596 89210,62535,24880 87957,87043,78072 36013,82721,23684 90729,70294,54540 33892,87468,61499 17692,94984,13137 62996,63877,64164 92631,66348,42217 89,31181,37204 76780,38666,75303 78532,89946,35303 28548,9979,92242 72265,96865,89733 8201,51540,55425 34180,73070,49991 82275,86599,64994 68767,55950,7841 94953,33155,52611 10540,37851,32736 63843,28266,90505 46810,46250,67049 19169,86971,57378 24788,90951,26680 5217,16735,94019 9497,45319,2518 11624,37497,86799 42260,49644,82150 60365,88395,21309 38955,85146,44219 56511,60372,81349 40117,37322,59504 28729,6877,27752 30921,76568,64616 64328,62288,54858 44233,29192,94595 43275,73412,21145 57412,35118,9085 90027,5293,46425 55229,86387,17947 58880,53907,86088 15746,28160,79814 83064,53153,5244 56022,92557,19902 54700,71667,56164 25164,25890,99761 7457,67770,69496 96488,38407,55668 60856,81510,99247 50098,25278,3998 91253,89827,80191 51246,48411,33877 49753,48413,1599 28390,43793,79664 31065,5976,63062 66187,19388,10525 24154,6119,49051 74088,31615,89471 54304,67120,42305 79323,45387,81692 12566,13402,10702 67127,25955,50135 56574,16878,15918 15417,29112,47971 10617,13723,43966 33662,87159,45652 19968,55148,69481 27035,15283,58794 92304,68860,20563 15823,75833,46738 94280,27101,69365 40385,79811,36588 73031,42629,21727 77056,46483,51353 42038,74034,15366 7599,81590,10921 2971,8477,51843 67250,60901,5164 2660,52130,40769 927,86458,73579 41527,59739,77996 2514,15223,77131 51961,12275,18636 16012,76663,58925 87939,43418,58421 26535,34787,85202 40996,18184,93284 74329,27058,45897 21343,79720,34290 1961,93477,51723 5165,7158,59952 41305,181,45353 73637,92392,78341 63799,72495,33147 25406,85728,91343 67511,7049,95359 86986,24910,95388 4636,39605,51761 93286,40880,37919 52610,34343,53928 70442,69310,53632 56192,84261,61879 53491,30361,94651 46019,53412,35427 17955,32048,34772 36000,6425,47825 25279,54374,64627 39192,58669,15436 38696,19599,66771 72625,25967,41598 9403,54588,55088 34063,9437,11862 94931,68541,84476 41578,3340,67354 79559,349,91967 94504,43232,23839 2375,87408,99546 34707,46653,55301 65551,82963,62266 13109,13500,15659 62101,58633,77195 26584,78201,28603 ================================================ FILE: exm/aoc/2025/aoc_2025_08_mini.txt ================================================ 162,817,812 57,618,57 906,360,560 592,479,940 352,342,300 466,668,158 542,29,236 431,825,988 739,650,466 52,470,668 216,146,977 819,987,18 117,168,530 805,96,715 346,949,466 970,615,88 941,993,340 862,61,35 984,92,344 425,690,689 ================================================ FILE: exm/aoc/2025/aoc_2025_08_questions.txt ================================================ --- Day 8: Playground --- Equipped with a new understanding of teleporter maintenance, you confidently step onto the repaired teleporter pad. You rematerialize on an unfamiliar teleporter pad and find yourself in a vast underground space which contains a giant playground! Across the playground, a group of Elves are working on setting up an ambitious Christmas decoration project. Through careful rigging, they have suspended a large number of small electrical junction boxes. Their plan is to connect the junction boxes with long strings of lights. Most of the junction boxes don't provide electricity; however, when two junction boxes are connected by a string of lights, electricity can pass between those two junction boxes. The Elves are trying to figure out which junction boxes to connect so that electricity can reach every junction box. They even have a list of all of the junction boxes' positions in 3D space (your puzzle input). For example: 162,817,812 57,618,57 906,360,560 592,479,940 352,342,300 466,668,158 542,29,236 431,825,988 739,650,466 52,470,668 216,146,977 819,987,18 117,168,530 805,96,715 346,949,466 970,615,88 941,993,340 862,61,35 984,92,344 425,690,689 This list describes the position of 20 junction boxes, one per line. Each position is given as X,Y,Z coordinates. So, the first junction box in the list is at X=162, Y=817, Z=812. To save on string lights, the Elves would like to focus on connecting pairs of junction boxes that are as close together as possible according to straight-line distance. In this example, the two junction boxes which are closest together are 162,817,812 and 425,690,689. By connecting these two junction boxes together, because electricity can flow between them, they become part of the same circuit. After connecting them, there is a single circuit which contains two junction boxes, and the remaining 18 junction boxes remain in their own individual circuits. Now, the two junction boxes which are closest together but aren't already directly connected are 162,817,812 and 431,825,988. After connecting them, since 162,817,812 is already connected to another junction box, there is now a single circuit which contains three junction boxes and an additional 17 circuits which contain one junction box each. The next two junction boxes to connect are 906,360,560 and 805,96,715. After connecting them, there is a circuit containing 3 junction boxes, a circuit containing 2 junction boxes, and 15 circuits which contain one junction box each. The next two junction boxes are 431,825,988 and 425,690,689. Because these two junction boxes were already in the same circuit, nothing happens! This process continues for a while, and the Elves are concerned that they don't have enough extension cables for all these circuits. They would like to know how big the circuits will be. After making the ten shortest connections, there are 11 circuits: one circuit which contains 5 junction boxes, one circuit which contains 4 junction boxes, two circuits which contain 2 junction boxes each, and seven circuits which each contain a single junction box. Multiplying together the sizes of the three largest circuits (5, 4, and one of the circuits of size 2) produces 40. Your list contains many junction boxes; connect together the 1000 pairs of junction boxes which are closest together. Afterward, what do you get if you multiply together the sizes of the three largest circuits? --- Part Two --- The Elves were right; they definitely don't have enough extension cables. You'll need to keep connecting junction boxes together until they're all in one large circuit. Continuing the above example, the first connection which causes all of the junction boxes to form a single circuit is between the junction boxes at 216,146,977 and 117,168,530. The Elves need to know how far those junction boxes are from the wall so they can pick the right extension cable; multiplying the X coordinates of those two junction boxes (216 and 117) produces 25272. Continue connecting the closest unconnected pairs of junction boxes together until they're all in the same circuit. What do you get if you multiply together the X coordinates of the last two junction boxes you need to connect? ================================================ FILE: exm/aoc/2025/aoc_2025_09.adb ================================================ -- Solution to Advent of Code 2025, Day 9 ------------------------------------------ -- . -- -- https://adventofcode.com/2025/day/9 -- Copy of questions in: aoc_2025_09_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; with Interfaces; procedure AoC_2025_09 is use AoC_Toolbox, HAT, Interfaces; -- input_name : constant VString := +"mini"; input_name : constant VString := +"aoc_2025_09"; red : array (1 .. 1000) of Point; n : Natural := 0; r : array (Part_Type) of VString; procedure Read_Data is unused_separator : Character; f : File_Type; begin Open (f, input_name & ".txt"); while not End_Of_File (f) loop n:= n + 1; Get (f, red(n).x); Get (f, unused_separator); Get (f, red(n).y); end loop; Close (f); end Read_Data; procedure Do_Part_1 is s, s_max : Integer_64; begin s_max := 0; for i in 1 .. n loop for j in i + 1 .. n loop s := Integer_64(abs(red(i).x-red(j).x)+1) * Integer_64(abs(red(i).y-red(j).y)+1); if s > s_max then s_max := s; end if; end loop; end loop; r (part_1) := +"" & Trim_Left (+Integer_64'Image(s_max)); end Do_Part_1; procedure Do_Part_2 is s, s_max : Integer_64; mouth_top : constant := 50174; -- Top part of the pacman's mouth. mouth_bottom : constant := 48596; -- Bottom part of the pacman's mouth. mouth_x : constant := 94582; is_top, ok, point_k_in_rect : Boolean; begin s_max := 0; for i in 1 .. n loop if red(i).x = mouth_x and then (red(i).y = mouth_top or else red(i).y = mouth_bottom) then is_top := red(i).y = mouth_top; for j in 1 .. n loop if red(j).x < mouth_x then if (is_top and then red(j).y > mouth_top) -- Point j above mouth. or else ((not is_top) and then red(j).y < mouth_bottom) -- Point j below mouth. then ok := True; for k in 1 .. n loop point_k_in_rect := red(k).x in red(j).x + 1.. mouth_x - 1; if is_top then point_k_in_rect := point_k_in_rect and then red(k).y in mouth_top + 1.. red(j).y - 1; else point_k_in_rect := point_k_in_rect and then red(k).y in red(j).y + 1 .. mouth_bottom - 1; end if; ok := ok and not point_k_in_rect; exit when not ok; end loop; if ok then s := Integer_64(abs(red(i).x-red(j).x)+1) * Integer_64(abs(red(i).y-red(j).y)+1); end if; if s > s_max then s_max := s; end if; end if; end if; end loop; end if; end loop; r (part_2) := +"" & Trim_Left (+Integer_64'Image(s_max)); end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 4749838800. -- Part 2: validated by AoC: 1624057680. end if; end; ================================================ FILE: exm/aoc/2025/aoc_2025_09.m ================================================ % Matlab / Octave script to plot the figure % x = csvread('aoc_2025_09.txt'); plot(x(:,1),x(:,2)); ================================================ FILE: exm/aoc/2025/aoc_2025_09.txt ================================================ 97839,50187 97839,51418 98477,51418 98477,52600 97593,52600 97593,53826 97775,53826 97775,55054 97845,55054 97845,56233 97465,56233 97465,57483 97608,57483 97608,58579 96811,58579 96811,59852 97008,59852 97008,61033 96717,61033 96717,62334 96880,62334 96880,63489 96457,63489 96457,64646 96051,64646 96051,65657 95227,65657 95227,66837 94921,66837 94921,68027 94622,68027 94622,69047 93911,69047 93911,70060 93212,70060 93212,71120 92635,71120 92635,72596 92849,72596 92849,73389 91754,73389 91754,74603 91423,74603 91423,75740 90939,75740 90939,76321 89599,76321 89599,77746 89534,77746 89534,78350 88294,78350 88294,79381 87652,79381 87652,80751 87413,80751 87413,81696 86631,81696 86631,82560 85757,82560 85757,83382 84844,83382 84844,84206 83940,84206 83940,84858 82877,84858 82877,85750 82046,85750 82046,86260 80883,86260 80883,87208 80098,87208 80098,88347 79444,88347 79444,88713 78195,88713 78195,89333 77149,89333 77149,90043 76167,90043 76167,90587 75078,90587 75078,91641 74294,91641 74294,92071 73137,92071 73137,92508 71993,92508 71993,93110 70937,93110 70937,93943 69982,93943 69982,94328 68818,94328 68818,94683 67646,94683 67646,95050 66484,95050 66484,95138 65231,95138 65231,96310 64331,96310 64331,95940 62951,95940 62951,96391 61818,96391 61818,96987 60710,96987 60710,97190 59505,97190 59505,96879 58213,96879 58213,97722 57119,97722 57119,97166 55819,97166 55819,97745 54666,97745 54666,97742 53448,97742 53448,98007 52246,98007 52246,98267 51034,98267 51034,98470 49810,98470 49810,98262 48588,98262 48588,98022 47376,98022 47376,97624 46185,97624 46185,97999 44929,97999 44929,98024 43692,98024 43692,97280 42567,97280 42567,96960 41393,96960 41393,96827 40185,96827 40185,96238 39079,96238 39079,96684 37717,96684 37717,96571 36476,96571 36476,95754 35447,95754 35447,95464 34260,95464 34260,94960 33148,94960 33148,94733 31928,94733 31928,94380 30749,94380 30749,93612 29754,93612 29754,92588 28902,92588 28902,92325 27680,92325 27680,92040 26449,92040 26449,91353 25438,91353 25438,90516 24525,90516 24525,90387 23155,90387 23155,89486 22287,89486 22287,88416 21558,88416 21558,88164 20219,88164 20219,86821 19735,86821 19735,86167 18705,86167 18705,85155 17987,85155 17987,84913 16550,84913 16550,84073 15658,84073 15658,83006 15003,83006 15003,82108 14180,82108 14180,80918 13697,80918 13697,80382 12440,80382 12440,79182 11992,79182 11992,78337 11092,78337 11092,77091 10750,77091 10750,76233 9854,76233 9854,75223 9177,75223 9177,74226 8474,74226 8474,73087 8018,73087 8018,72269 6957,72269 6957,70795 7182,70795 7182,69951 6125,69951 6125,68563 6271,68563 6271,67731 5101,67731 5101,66547 4778,66547 4778,65200 4955,65200 4955,64241 3978,64241 3978,62979 3960,62979 3960,61794 3701,61794 3701,60765 2769,60765 2769,59574 2468,59574 2468,58225 3049,58225 3049,57049 2747,57049 2747,55867 2442,55867 2442,54643 2487,54643 2487,53478 1841,53478 1841,52227 2406,52227 2406,51018 2473,51018 2473,50174 94582,50174 94582,48596 2009,48596 2009,47397 2365,47397 2365,46143 1843,46143 1843,45001 2683,45001 2683,43797 2775,43797 2775,42479 2160,42479 2160,41424 3205,41424 3205,40171 3106,40171 3106,38868 2869,38868 2869,37745 3423,37745 3423,36645 4010,36645 4010,35554 4580,35554 4580,34404 4951,34404 4951,33049 4777,33049 4777,31917 5239,31917 5239,30850 5852,30850 5852,29916 6735,29916 6735,28754 7113,28754 7113,27735 7780,27735 7780,26320 7728,26320 7728,25544 8824,25544 8824,24250 9045,24250 9045,23184 9655,23184 9655,22440 10732,22440 10732,21595 11633,21595 11633,20324 11970,20324 11970,19659 13085,19659 13085,18479 13572,18479 13572,17583 14400,17583 14400,16906 15457,16906 15457,15867 16133,15867 16133,15383 17351,15383 17351,14556 18228,14556 18228,13309 18750,13309 18750,12641 19780,12641 19780,12253 21017,12253 21017,11069 21646,11069 21646,10560 22777,10560 22777,9597 23598,9597 23598,8853 24576,8853 24576,8780 25951,8780 25951,7864 26827,7864 26827,7601 28063,7601 28063,6935 29084,6935 29084,5913 29952,5913 29952,5397 31065,5397 31065,5302 32347,5302 32347,4647 33404,4647 33404,4202 34545,4202 34545,4010 35768,4010 35768,4073 37052,4073 37052,3941 38266,3941 38266,2861 39255,2861 39255,3369 40606,3369 40606,3042 41773,3042 41773,2609 42929,2609 42929,2225 44105,2225 44105,1748 45283,1748 45283,2332 46557,2332 46557,1675 47738,1675 47738,2385 48979,2385 48979,1804 50188,1804 50188,1737 51411,1737 51411,1988 52623,1988 52623,2448 53808,2448 53808,1826 55089,1826 55089,1951 56310,1951 56310,2824 57415,2824 57415,2496 58705,2496 58705,3475 59750,3475 59750,3658 60944,3658 60944,3202 62312,3202 62312,4128 63319,4128 63319,3826 64685,3826 64685,4784 65652,4784 65652,4734 66966,4734 66966,5412 68012,5412 68012,5604 69257,5604 69257,6711 70095,6711 70095,7060 71271,7060 71271,7843 72230,7843 72230,8110 73464,8110 73464,9092 74296,9092 74296,9127 75698,9127 75698,9689 76793,9689 76793,10879 77456,10879 77456,11732 78331,11732 78331,11970 79675,11970 79675,12644 80703,12644 80703,13616 81482,13616 81482,14818 82035,14818 82035,15485 83066,15485 83066,16276 83987,16276 83987,17268 84703,17268 84703,18250 85418,18250 85418,19090 86290,19090 86290,19787 87349,19787 87349,20771 88066,20771 88066,21986 88463,21986 88463,22781 89434,22781 89434,23591 90412,23591 90412,24650 91025,24650 91025,25931 91254,25931 91254,26923 91962,26923 91962,28166 92198,28166 92198,28940 93359,28940 93359,30162 93623,30162 93623,31247 94173,31247 94173,32499 94314,32499 94314,33454 95216,33454 95216,34580 95692,34580 95692,35889 95596,35889 95596,36999 96114,36999 96114,38116 96649,38116 96649,39319 96857,39319 96857,40464 97338,40464 97338,41631 97767,41631 97767,42884 97695,42884 97695,44173 97221,44173 97221,45292 98160,45292 98160,46525 98102,46525 98102,47740 98289,47740 98289,48979 97634,48979 97634,50187 ================================================ FILE: exm/aoc/2025/aoc_2025_09_questions.txt ================================================ --- Day 9: Movie Theater --- You slide down the firepole in the corner of the playground and land in the North Pole base movie theater! The movie theater has a big tile floor with an interesting pattern. Elves here are redecorating the theater by switching out some of the square tiles in the big grid they form. Some of the tiles are red; the Elves would like to find the largest rectangle that uses red tiles for two of its opposite corners. They even have a list of where the red tiles are located in the grid (your puzzle input). For example: 7,1 11,1 11,7 9,7 9,5 2,5 2,3 7,3 Showing red tiles as # and other tiles as ., the above arrangement of red tiles would look like this: .............. .......#...#.. .............. ..#....#...... .............. ..#......#.... .............. .........#.#.. .............. You can choose any two red tiles as the opposite corners of your rectangle; your goal is to find the largest rectangle possible. For example, you could make a rectangle (shown as O) with an area of 24 between 2,5 and 9,7: .............. .......#...#.. .............. ..#....#...... .............. ..OOOOOOOO.... ..OOOOOOOO.... ..OOOOOOOO.#.. .............. Or, you could make a rectangle with area 35 between 7,1 and 11,7: .............. .......OOOOO.. .......OOOOO.. ..#....OOOOO.. .......OOOOO.. ..#....OOOOO.. .......OOOOO.. .......OOOOO.. .............. You could even make a thin rectangle with an area of only 6 between 7,3 and 2,3: .............. .......#...#.. .............. ..OOOOOO...... .............. ..#......#.... .............. .........#.#.. .............. Ultimately, the largest rectangle you can make in this example has area 50. One way to do this is between 2,5 and 11,1: .............. ..OOOOOOOOOO.. ..OOOOOOOOOO.. ..OOOOOOOOOO.. ..OOOOOOOOOO.. ..OOOOOOOOOO.. .............. .........#.#.. .............. Using two red tiles as opposite corners, what is the largest area of any rectangle you can make? --- Part Two --- The Elves just remembered: they can only switch out tiles that are red or green. So, your rectangle can only include red or green tiles. In your list, every red tile is connected to the red tile before and after it by a straight line of green tiles. The list wraps, so the first red tile is also connected to the last red tile. Tiles that are adjacent in your list will always be on either the same row or the same column. Using the same example as before, the tiles marked X would be green: .............. .......#XXX#.. .......X...X.. ..#XXXX#...X.. ..X........X.. ..#XXXXXX#.X.. .........X.X.. .........#X#.. .............. In addition, all of the tiles inside this loop of red and green tiles are also green. So, in this example, these are the green tiles: .............. .......#XXX#.. .......XXXXX.. ..#XXXX#XXXX.. ..XXXXXXXXXX.. ..#XXXXXX#XX.. .........XXX.. .........#X#.. .............. The remaining tiles are never red nor green. The rectangle you choose still must have red tiles in opposite corners, but any other tiles it includes must now be red or green. This significantly limits your options. For example, you could make a rectangle out of red and green tiles with an area of 15 between 7,3 and 11,1: .............. .......OOOOO.. .......OOOOO.. ..#XXXXOOOOO.. ..XXXXXXXXXX.. ..#XXXXXX#XX.. .........XXX.. .........#X#.. .............. Or, you could make a thin rectangle with an area of 3 between 9,7 and 9,5: .............. .......#XXX#.. .......XXXXX.. ..#XXXX#XXXX.. ..XXXXXXXXXX.. ..#XXXXXXOXX.. .........OXX.. .........OX#.. .............. The largest rectangle you can make in this example using only red and green tiles has area 24. One way to do this is between 9,5 and 2,3: .............. .......#XXX#.. .......XXXXX.. ..OOOOOOOOXX.. ..OOOOOOOOXX.. ..OOOOOOOOXX.. .........XXX.. .........#X#.. .............. Using two red tiles as opposite corners, what is the largest area of any rectangle you can make using only red and green tiles? ================================================ FILE: exm/aoc/2025/aoc_2025_10.adb ================================================ -- Solution to Advent of Code 2025, Day 10 ------------------------------------------- -- Factory -- -- https://adventofcode.com/2025/day/10 -- Copy of questions in: aoc_2025_10_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; with Interfaces; procedure AoC_2025_10 is use AoC_Toolbox, HAT, Interfaces; input_name : VString; max_lights : constant := 10; max_buttons : constant := 20; r : array (Part_Type) of VString; verbose : constant Boolean := False; do_part_2 : constant Boolean := False; procedure Read_Data is c : Character; light, lights : Integer; f : File_Type; buttons : Natural; diagram, test : Integer_64; button_bits : array (1 .. max_buttons) of Integer_64; -- Light is 0-based. button : array (1 .. max_buttons, 1 .. max_lights) of Boolean; -- All 1-based. fewest_presses, presses, res_1, res_2 : Natural; type Press_Combination is array (1 .. max_buttons) of Natural; type Counters is array (1 .. max_lights) of Natural; target : Counters; procedure Explore (press : Press_Combination; joltage : Counters; shift : Natural) is ok : Boolean := True; new_button : Integer; new_press : Press_Combination; new_joltage : Counters; begin if verbose then Put ("Presses: "); for b in 1 .. buttons loop Put (press (b), 2); end loop; Put (". Jolts: "); for l in 1 .. lights loop Put (joltage (l), 3); end loop; Skip_Line; end if; for l in 1 .. lights loop ok := ok and joltage (l) = target (l); if joltage (l) > target (l) then return; end if; end loop; if ok then -- This combination of buttons makes the joltages match. presses := 0; for b in 1 .. buttons loop presses := presses + press (b); end loop; fewest_presses := Min (presses, fewest_presses); return; end if; -- From here we know we have an incomplete joltage. -- We try something: press each button individually. for b in 1 .. buttons loop new_button := 1 + (b + shift - 1) mod buttons; for pow in 0 .. 0 loop new_press := press; new_joltage := joltage; new_press (new_button) := new_press (new_button) + 2 ** pow; for l in 1 .. lights loop if button (new_button, l) then new_joltage (l) := new_joltage (l) + 2 ** pow; end if; end loop; Explore (new_press, new_joltage, shift + 1); end loop; end loop; end Explore; press_0 : Press_Combination; joltage_0 : Counters; begin res_1 := 0; res_2 := 0; Open (f, input_name & ".txt"); while not End_Of_File (f) loop light := -1; Get (f, c); -- [ diagram := 0; loop Get (f, c); exit when c = ']'; light := light + 1; if c = '#' then diagram := diagram + 2 ** light; end if; end loop; lights := light + 1; buttons := 0; loop Get (f, c); case c is when '(' => buttons := buttons + 1; button_bits (buttons) := 0; for l in 1 .. max_lights loop button (buttons, l) := False; end loop; -- Put ('b'); -- Put (buttons,0); -- Put ('('); when ')' => null; -- Put (')'); when '{' => exit; when '0' .. '9' => light := Ord (c) - Ord ('0'); button_bits (buttons) := button_bits (buttons) + 2 ** light; button (buttons, light + 1) := True; -- Put (button (buttons, l) - 1, 2); when others => null; end case; end loop; if verbose then for b in 1 .. buttons loop for l in 1 .. lights loop if button (b, l) then Put ("1 "); else Put ("0 "); end if; end loop; New_Line; end loop; end if; for l in 1 .. lights loop Get (f, target (l)); Get (f, c); end loop; if c /= '}' then Put_Line ("Data error on joltage"); end if; -- Puzzle 1, light diagram. -- The order of the button presses is not relevant, and two presses are equivalent to zero presses. fewest_presses := buttons; -- !! HAC borks on that : "for n in Integer_64 range 0 .. 2 ** buttons - 1 loop" for n in 0 .. 2 ** buttons - 1 loop -- Test all button combinations. test := 0; presses := 0; for b in 1 .. buttons loop if Sim_AND (2 ** (b - 1), Integer_64 (n)) /= 0 then presses := presses + 1; test := Sim_XOR (test, button_bits (b)); end if; end loop; if test = diagram then -- This combination of buttons makes the light diagram match. fewest_presses := Min (presses, fewest_presses); end if; end loop; res_1 := res_1 + fewest_presses; -- Puzzle 2, joltages. -- It is actually an underdetermined linear equations system -- with integer solutions. if do_part_2 then for b in 1 .. buttons loop press_0 (b) := 0; end loop; for l in 1 .. lights loop joltage_0 (l) := 0; end loop; fewest_presses := Integer'Last; Explore (press_0, joltage_0, 0); res_2 := res_2 + fewest_presses; end if; end loop; Close (f); r (part_1) := +"" & res_1; r (part_2) := +"" & res_2; end Read_Data; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin input_name := +"aoc_2025_10_mini"; Read_Data; if compiler_test_mode then if r (part_1) /= Argument (1) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); if do_part_2 then Put_Line (+"Part 2: " & r (part_2)); end if; -- Part 1: validated by AoC: 477 (mini: 7). -- Part 2: validated by AoC: . end if; end AoC_2025_10; ================================================ FILE: exm/aoc/2025/aoc_2025_10.txt ================================================ [.##......] (0,1,3,4,6,7,8) (1,2,3,5,6,8) (0,1) (3,5,6,7) (2,5,7) (1,2,3,4,5,7,8) (7) (0,1,3) (0,3,7) (1,4,6) {36,63,29,56,28,48,43,52,23} [.##....#] (0,1,2,3,4,5,7) (0,2,3,7) (1,3,5,6) (0,1,2,6) (2,3,5,6,7) (2,4) (0,1,2,3,7) (0,2,3,5,6,7) {171,166,199,75,30,65,170,64} [.#.#.] (0,2,3,4) (1,3) (0,2) (1,4) {1,27,1,7,20} [#...#] (1,4) (2,3) (0,2,3) (1,2,3) (0,1,4) {7,22,11,11,15} [##.#.#.] (1,3,4,6) (4,5) (0,1,3,4) (0,4,6) (1,2,3,4) (1,2,4,5) (0,1,4,5,6) (0,3) (0,2,4,5) {46,44,15,39,72,45,31} [.##.] (1,3) (1) (0,3) (0,1,3) (1,2,3) (3) {23,40,20,64} [...#] (0,2) (0,1,2) (3) (2,3) (1,2) {27,177,206,19} [.###.] (2,3,4) (0,3,4) (0,4) (3) (0,2,3) (0,1,3) {24,3,19,41,20} [##.#] (0,1,3) (0,1,2) (2,3) {19,19,14,31} [#..#] (0,3) (1,2,3) (0,1,3) {139,13,6,145} [.#..##] (0,2,3) (1,4) (1,2,4) (5) (0,1,2,4,5) (4,5) (2) (2,3) {34,30,58,25,36,30} [##..#] (0,2,3) (2) (0,1,2,4) {25,5,45,20,5} [..#..] (0,3) (0,1) (3) (1,2,4) (0,2) (0,2,4) (1,2,3,4) {35,10,22,23,20} [#.#..###..] (3) (3,5,6) (0,1,2,3,4,9) (0,4,5,6) (5,6) (0,1,2,3,5,6,7,9) (1,2,3,4,5,7,8,9) (1,2,3,6,7,8,9) (9) (0,6) (2,3,4,5,6,7,9) (1,2,3,4,5,6,9) (8) {28,40,43,64,44,35,39,5,21,58} [.....#.#.] (3,4) (1,4) (0,2,3,5,6,8) (1,4,5,7) (0,3,4,6,7,8) (0,1,2,3,5,8) (2,4,5) (2,5) (2,3,5,8) (6) {24,29,22,43,58,28,19,16,24} [#.#.] (0,2) (1,3) {3,14,3,14} [#.#...] (1) (0,2,3,4) (1,2,3,5) (3,4) (0,2) (3) (0,1,2,3,5) {31,28,36,57,23,17} [#.#...#] (0,2,4,5) (0,1,2,3,4,6) (0,6) (2,3,4,5,6) (0,2,6) (0,3,4,6) {42,11,33,34,42,21,47} [.###...#.#] (1,2,3,4,5,7,8) (0,1,2,4,5,6,7,9) (3,5) (0,1,2,3,4,6,7,8,9) (1,2,9) (0,1,2,4,6,7,9) (7) (0,2,3,4,5,6,8,9) {59,58,77,52,67,61,59,60,34,69} [##......#.] (1,3,5,6,7,8) (1,2,6,7) (0,6) (0,3,4,5,6,8) (4,9) (0,1,2,3,4,5,6,7,8) (0,3,4,6,8,9) (1,4,6,7) (0,4) (1,2,4,5,8) (1,2,5) {38,41,30,18,50,30,44,27,31,4} [.####.#.] (0,4,6,7) (1,2,3) (1,2,3,4,6) (1,5,7) (4,5) (0,1,2,4,5,6) {21,165,163,162,40,4,39,22} [.###] (0,3) (1,2) (0,1) (2) {5,5,1,1} [...#.#..#] (0,3,4,5,6,7,8) (1,4,6,8) (1,6) (1,2,3,4,5,6,8) (1,2,3,4,5,7,8) (2,3,4,5,8) (0,1,3,7) (0,1,4,5,6) {27,78,35,46,74,54,64,20,58} [####..#] (2,4) (3,4,5,6) (2,3,5,6) (0,1,3) (1,2,4,5,6) (0,1,3,5) (0,2,5,6) (1,2,3,4) {33,56,57,48,53,46,36} [.##.#] (0,2,3) (0,3,4) (0,1,2,3) (2,4) (0,1) {132,20,31,121,118} [#.#.#.#..#] (1,2) (5,7,8) (0,2,3,5,9) (3,4,5,7,8) (1,2,3,7,9) (0,2,9) (2,4,5) (0,2,3,4,5,6,7,9) (0,1,4,6,7,8,9) (1,3,4,6) (0,1,2,4,5,7,8,9) (0,2,3,4,6,7,9) {185,26,193,179,185,183,154,188,37,194} [...#..] (2,3,4,5) (2,3) (0,1,3,4) (1,2,5) (5) (0,1) {23,42,42,29,15,33} [...#.#] (2,5) (0,1) (0,3,4) (3,5) (4) (1,4) (0,1,2,3) (0,1,2,5) {43,48,41,28,198,42} [#####.#] (0,1,6) (0,3,4,5,6) (0,1,5) (1,4,6) (0,2,4,5) (0,1,2,3) (1,2,3,6) (0,1,4,5,6) (0,2,3,4) {96,62,44,46,75,71,60} [.#..###..] (0,2,3,5,8) (2,3,5,6) (6,7) (0,3,4,8) (1,2,3,4,8) (4,5,8) (1,2,4,5,6,7,8) (2,3,4,5,6,7,8) (1,2,4,5,8) (0,6) (0,2,7) {41,46,237,193,211,214,195,187,219} [#..#.##.#.] (5,6) (8) (1,3) (0,1,3,5,6,8,9) (6,9) (0,2,4,5,6,7,8,9) (1,2,3,6,8) (2,3,4,5,6,8,9) (1,2,4,5,7) {21,47,49,49,42,64,61,24,56,45} [#.##....#] (0,1,4,5,6) (0,2,4,5,6) (1,2,3,4,5,6) (0,1,2,5,7,8) (3,6,7) (0,2,4,5) (1,3,5,6,7,8) (0,4,6,7) (2,4,8) (2,5,6,7,8) {37,37,58,24,51,69,68,43,51} [##..] (1,2) (3) (1,3) (0,3) (0,2,3) (0,1) {140,133,7,34} [.#..#] (1,2,4) (3,4) (2,3,4) (0,4) {20,19,25,11,50} [##..####.] (0,2,6,8) (1,2,3,5,6,7) (4,6,7,8) (0,2,3,4,5,6,7,8) (2,4,6,8) (1,2,3,4,5,6,7,8) (3,8) (5) (0,1,6,8) (2,4,7,8) {15,25,37,25,48,22,58,43,63} [.#.#####] (0,1,3,4,6) (2,3,5,6,7) (0,5,6,7) (4,7) (0,2,3,4,6,7) (0,1,2,3,5,6,7) (0,1,5) (0,2,6,7) {48,36,47,56,33,43,60,61} [##..#.#] (0,1,2,4,6) (2,6) (2,4,6) (0,1,5) (1,3,4,5) (0,2,3,4,6) (1,3,4,5,6) (2,3,5) (3,4) {44,46,150,42,44,44,151} [##.#.] (1,3,4) (0,2,4) (0,2,3) (0,1,4) (0,1,3) (1,3) {41,36,30,44,33} [..##.#....] (0,1,2,4,5,7,8,9) (0,3,4,8) (0,1,2,3,4,5,8,9) (2,7,8,9) (0,1,2,3,5,8,9) (0,2,4,5,7,8,9) (3,4,8) (0,1,2,3,5,6) (1,6) (0,1,3,4,9) (0,2,4,7) {265,241,259,62,261,233,13,231,262,264} [#.....#.] (3,4,5,7) (2,4,6,7) (0,1,4,5,6,7) (1,5,6) (4,6) (0,5,7) (0,3) (1,3,5,7) (0,3,4,5,6,7) {59,31,5,34,49,65,68,51} [##.#] (0,1) (0,1,3) (1,2) (1,3) {28,52,16,20} [.#.#] (0,3) (3) (2,3) (0,1) (1,2,3) (2) {16,25,49,48} [.#......#] (0,3,4,5,6,7,8) (2,4,5) (0,1,2,4,6,7,8) (0,2,3,4,5,6,8) (1,2,4,8) (3) (0,1,5) (0,1,2,5,6,7) (3,5,6) (1,8) {49,64,37,31,34,51,39,29,43} [..#.#..] (2,4) (2,5,6) (4,5,6) (2,3,4,6) (0,1,3,4,5,6) (0,3,4) (1,2,4,5,6) (0,2,3,4) (0,2,3,4,5,6) {34,7,54,50,73,26,42} [#...#] (1,2,3,4) (0,1,3) (0,1,2,3) {35,43,25,43,8} [..#.#..#..] (0,2,4,6) (2,4) (5,6,7,9) (0,1,2,3,4,6,7,8) (1,2,3,8,9) (0,1,4,5,6,8,9) (3,4,7,9) (0,2,5,7,8,9) (3,4,5,6,7,8) (2,3,5,6,7,8,9) (1,2,3,4,5,6,7,9) (4,9) {46,48,71,47,69,77,71,62,66,95} [.#.#.###.] (0,6) (0,2) (5,8) (4,7,8) (1,2,3,5,8) (0,2,7) (1,3,5,6,7) {41,28,44,28,5,48,25,20,45} [#.###.##] (1,2,3,5,6,7) (2,4,6,7) (5,6,7) (0,1,2,4,5,6) (0,2,3,4,6,7) (3,4,5,6) (1,2,3,4) {12,28,55,47,62,27,54,38} [...#.#####] (0,4,5) (0,1,8,9) (6,8,9) (0,1,3,4,5,6,7,8) (0,3,7) (0,5,7) (3) (4,6,9) (5,7) (1,2,5,9) (0,1,2,5,6,7,8,9) (3,4,5,6,8) (0,1,2,3,4,5,6,7,8) {43,42,29,38,32,67,33,46,36,30} [..#.#####] (2,3,5,6,7) (3,7) (0,5,7,8) (0,1,2,4,5,6,7) (0,1,3,4,5,6,7,8) (0,1,2,3,4,5,7,8) (0,2,3,4,5,6,7) {58,23,30,51,38,59,30,76,38} [.##.....#.] (0,3,5) (3,6) (1,3,4,5,6,7,9) (0,1,2,3,4,6,7,8) (0,2,4,5,6,7,8) (0,2,4,5,7,8) (1,2,3,5,6,7,9) (0,3,9) (0,5,6) (0,1,2,3,6,8,9) {81,59,50,114,49,58,87,57,42,61} [##....] (0,1,2,3,5) (0,1,2,4) (2,4) (1,3) (0,1,3) {26,42,18,40,7,11} [.##.#...#.] (4,5,9) (0,1,4,7,8) (3,5,9) (0,9) (5,6) (0,1,2,4,5,7,8,9) (3,5) (1,2,6,9) (1,3,4,5,6,8,9) {29,48,23,23,46,51,30,25,30,62} [.#..#.#] (2,6) (2,3,5,6) (0,1,2,3,4,5) (0,1,6) (0,5) (0,3,4,5,6) (1,3,4) {48,51,46,56,47,41,56} [.#..#] (0,4) (1,3,4) (0,2,3,4) (1,4) (0,2,4) (2,3,4) (0,2,3) {39,20,30,33,45} [#.##.] (2,4) (1,2,4) (0,2,3) {111,5,134,111,23} [.##.] (0,1,2) (1,2) (0,1,3) {11,14,13,1} [..#.#.] (0,4) (0,2,5) (1,3) (0,1,3,4,5) (0,1,2,3,4) {61,36,39,36,41,22} [.##.] (0,1,2) (0) (2) (0,2) (2,3) (3) {32,15,160,136} [##.###] (1,3) (0,4,5) (1,2,4) (1,2) (2) (0,2,3,4) (0,1,3,5) {23,37,41,11,36,19} [.##.] (2,3) (0,1,3) (0,2,3) (0,1) {9,3,14,16} [...##.####] (0,1,3,5,6) (2,6,7,8) (1,2,4,5,6,7,8,9) (0,1,5,7,8,9) (0,3,4,7,8,9) (1,4,8) (0,2,3,6,7,9) (1,4,5,7,8,9) (0,2,5,8) (1,6,8,9) (0,1,2,4,6,7) (0,1,2,3,4,5,6,7) {72,112,79,37,80,63,96,108,88,75} [#.##..#] (0,3) (0,6) (2,4,5) (0,3,4,5,6) (0,2,4,5,6) (2,4) (0,4) (0,1,2,3,4,5) {36,10,20,24,29,22,9} [..##.###.#] (5,6,7,8) (1,4,7) (0,5,9) (7,9) (1,2,3,4,5,6,7,8,9) (1,2,3,6,8) (3,7,8) (4,6,9) (1,2,3,6,9) {11,26,21,23,37,27,43,27,19,54} [...####..#] (1,2,5,7,8) (0,2,6,7) (1,2,8,9) (0,1,3,4,5,9) (0,2,4,5,6,7,8) (7) (1,4,7) (1,2,3,5,7,8) (0) (1,6,9) (1,2,3,4,5,6,7,8) (0,4,5,7,8,9) (0,1,3,4,5,6) {49,58,68,37,50,67,60,92,62,24} [#####..#] (0,3,7) (0,1,2,3,4,5,7) (0,2,3,4,6) (0,2,4,5) (0,4) (1,2,4,5,6,7) (0,1,3,5,6) (0,2,5,6,7) {82,36,60,55,63,53,47,52} [##.###..#] (2,4,8) (2,3) (0,4,5,8) (0,1,2,3,5) (1,2,4,7) (6,7,8) (0,2,4,6,8) (0,1,2,4,5,6,8) (0,1,3,4,5,6,7) (0,3,7,8) {55,42,60,14,66,35,50,40,64} [###..#####] (1,2,4,5,6,7,8) (0,1,2,5,6,7,8,9) (2,4) (0,4,6,8) (2,3,4,6,9) (1,3,4,5,6,7,8,9) (0,1,2,3,6,7,9) (2,4,5,6,7) {23,34,192,173,193,28,192,41,26,178} [.#..#] (1,4) (2,3) (0) (1) (1,2,3) {14,42,18,18,12} [.##..] (0,3,4) (0,2) (1,3,4) (1,3) (1,4) (0,1,2,3) (1,2,3,4) {29,44,36,45,47} [#....#..##] (3,5,9) (2,3) (1,2,3,4,5,7,8,9) (4,5,6) (0,1,2,4,6,8,9) (0,1,2,3,4,7,9) (3,6) (0,1,2,3,4,8) {28,44,64,76,146,135,137,17,43,54} [..###.#..] (0,2,5,7) (0,1,3,5,6) (4) (1,8) (0,1,4,6,7,8) (0,2,3,6) (0,1,2,6,7,8) (0,1,2,5,6,7) (1,5,7,8) {36,67,25,6,25,27,31,48,63} [##.....] (1,3,5,6) (0,3) (0,5) (3,4) (1,2) (0,2,3,4,6) (0,1,5,6) (1,2,3,6) {13,19,21,39,18,1,16} [##.####] (0,1,5,6) (0,2,4) (1,3,6) (0,1,2,3,5,6) (1,2,3,4,6) {222,226,215,209,30,202,226} [.##.#] (3,4) (2,4) (1,2,3,4) (0,2,4) (0,2) {35,12,60,17,50} [...#..#] (2,3) (0,2,3,5,6) (1,2,4,5,6) (1,4,5) (2,3,4,5) (1,3) {18,204,46,33,202,220,38} [..##.#.#.#] (1,3,4,6,8) (2,5,7,9) (5,8) (2,4,5,7,8) (1,2,3,4,5,6,7) (0,1,3,4,5,6,7,8,9) (1,5,6) (0,1,8,9) (2,5,6,7,9) {9,42,53,34,44,54,48,54,33,33} [###..##.] (2,6) (0,1,3,4) (0,1,2,3,4,5,6) (3,4) (2,4,5,6,7) (1,2,4,6) (5,7) (0,1,3) {4,9,19,9,16,14,19,14} [#.#######.] (2,8,9) (0,5,6) (8) (1,2,4,6,7,8,9) (2,3,4,6,9) (0,1,2,4,6,8) (0,2,3,4,9) (0,1,2,3,5,7,8,9) (0,1,5,6,7,8) (1,3,5,7,8) (0,2,3,6) {35,15,60,42,39,4,31,9,30,44} [.##..##..] (0,5,6) (1,3,4) (0,1,3,5) (3,5,6,7) (0,1,5,7) (3,4,5,7,8) (1,2,5,6,8) (0,1,2,3,7) (0,2,3) {44,43,22,70,34,68,36,57,25} [.#...] (2) (1,2,3) (0,1) (3,4) (0,3,4) (1) {1,11,7,25,18} [..##] (0,3) (1,2,3) (0,2) (0) (1,3) {24,10,8,16} [.##.] (1,2,3) (1,3) (0,3) (0,1,2) (0) {44,28,16,40} [..#......] (1,3,4,5,6,7,8) (0,2,3,4,6,7,8) (0,1,5,6,8) (2,3,4,8) (0,1,2,5,6,8) (5,6) (3,4,6,8) (0,1,2,3,4,5,8) (0,2,3,6,8) (0,7) {51,42,37,24,16,52,64,5,63} [#.#.#] (1,2) (1,3) (0,1,2) (3) (1,4) {16,41,25,20,5} [.########.] (0,1,3,9) (0,1,2,7) (0,1,2,3,4,6,7,9) (0,2,3,4,5,8,9) (2,7) (0,1,2,3,6,8) (0,1,2,3,4,5,8,9) (0,1,2,5,7) (0,1,3,4,5,6) (1,2,4,5,6,9) (2,4) {79,87,96,54,60,50,48,42,26,44} [#.#.] (0,3) (1,2,3) (2,3) (2) {11,18,47,48} [#...] (1,2) (1,3) (2) (0,2,3) (0,3) (0,1,2) {36,27,39,36} [###.#.#.##] (0,1,2,4,6,8,9) (1,2,3,4,5,6,7,8,9) (0,1,3,5,6,8) (0,1,2,3,4,5,7) (0,1,2,3,4,6,7,8,9) (1,2,3,4,5,6,8) (0,1,2,5,6) (6,7,9) (4,5) (0,1,3,4,5,6,7,8,9) {71,81,42,58,57,91,252,217,54,213} [#.#####.] (0,2,3,4,5,7) (0,2,3,4,5,6) (3,5,6,7) (2,4,5) (2,3) (1,7) (0,2,3,4,5,6,7) {44,19,64,59,54,59,30,51} [###..] (0,2,4) (0,1,2,3) (1,4) {25,135,25,13,134} [#..###.#..] (3,4,6) (2,5,9) (8) (0,3,4,5,6,7,8) (0,1,2,4,6,8) (0,2,8) (0,2,3,5,6,7) (1,2,5,7,8) (2,3,4,5,6,7,8,9) (0,5,6,7,8) (1,2,3,4,5,6,7) (1,3,4,5,7,9) {20,27,175,49,47,190,41,40,39,171} [..#..##..] (0,3,4,5,6,8) (4,5,6,8) (3,6,8) (5,8) (0,1,2,4,5,6,8) (0,1,2,7) (0,2,3,4,7,8) {39,19,28,28,47,40,46,9,57} [#####] (0,1,3) (0) (0,1,2,3) (2,4) (3,4) (2) (0,1,3,4) {247,47,35,62,32} [..##..##] (0,1,3,4,5,6) (0,3,6) (2,5,6) (1,2,4) (1,2,3,4,5,7) (0,2,3,4,6) {21,19,30,23,25,27,36,2} [#...#.####] (1,2,3,7,8,9) (2,4,6,7,8) (0,1,2,3,4,7,8,9) (0,1,5,7,9) (0) (2,9) (1,2,5,8) (0,3,4,6,8) (0,1,2,3,5,6,7,9) (4,7) {56,47,58,52,41,25,32,47,53,47} [#...##] (1,2,4,5) (1,2,4) (1,2,3,5) (0,4) {1,21,21,14,8,16} [...#] (0,2) (1,2) (1,3) (0,1,2) (3) {21,19,33,19} [.#.#..] (2,5) (0,2,3,5) (1,2,3,5) (3,4,5) (0,1,4,5) {13,14,40,27,6,46} [#.#.#.###] (0,3,4,7) (2,3,5,7,8) (0,1,3,7,8) (0,5,7) (2) (2,5,6,7,8) (0,1,4,7) (3,4) {29,11,180,33,22,44,17,60,35} [##.######] (0,1,3,4,5,6,7,8) (0,3) (1,2,3,4,5,6,8) (0,3,5,6,7) (0,2,3,4,5,6,7) (0,1,2,4,5,7) (2,3,4) {58,27,40,56,46,50,37,42,14} [.#...] (0,1,3) (1) (0,4) (0,2,3) (1,2) (0,1,2) {13,33,18,9,3} [.#..###] (2,5,6) (0,1,2,3,4,5) (0,2,3,5,6) (1,4,5,6) (1,2,4,6) {19,33,40,19,33,25,31} [.#..#####.] (1,4,5,6,7,8) (1,3,5,9) (0,1,2,3,6,7,8,9) (2,5,6) (0,1,2,3,6,8) (3,7,9) (2,4,6,8,9) (1,3,6,7,8) {26,75,40,62,27,39,75,57,69,44} [##.#..] (2,3,4,5) (1,2,3) (3,4) (1,3) (0,5) {176,21,36,47,26,195} [##...#] (0,1,2,4,5) (1,4) (0,2,3,5) (0,1,2,3) (1,3,4,5) (0,3,4,5) {31,34,25,36,31,27} [#..##.#] (0,1,3,5,6) (1,2,5,6) (1,3,4,5,6) (0,1,2,3,4,5) (0,1,3,5) {27,56,30,45,37,56,30} [.##...##] (1,3,4,5,6,7) (1,2,6,7) (0,3,6,7) (0,4,5,6) (1,3,4,6,7) (1,2,5,6) {35,225,212,29,32,37,260,224} [...##.#.] (3,4,6) (3,4,5,6) (1,2,4,6) (0,1,2,7) (0,1,3,4,6,7) (0,1,3,6) {31,43,20,54,54,12,66,19} [....#.#..#] (4,7,9) (2,8) (0,2,3,4,6,7,9) (4,5,6,7,8,9) (0,1,2,3,4,5,8) (0,1,2,3,5,7,9) (2,6,8,9) (2,3,4,8) (1,8) (0,1,2,4,5,6,7,8) {7,20,36,14,34,15,33,23,60,34} [#.##...] (1,4) (0,1,3,4,6) (0,4) (3,4,6) (1,2,4,6) (1,2,6) (0,5) {46,39,13,15,56,19,28} [#.#.##.] (5,6) (4,6) (0,2,3,4,5,6) (4,5) (0,1,5) (0,1,2,4,6) (2,3,5) (1,2,3) (1,5,6) {32,40,29,14,39,61,55} [####..#..] (4,8) (1) (6,7) (0,2,5,6,7,8) (0,1,2,4,6,8) (1,2,8) (0,1,3,5,7) (0,1,2,4) (0,4,5,7,8) (2,3,5,6) (0,5) {61,56,61,33,31,64,38,32,49} [###.] (1,2,3) (0,1,3) (1,3) (0,2,3) (0,3) (0,2) {69,20,34,51} [..#...] (1,2) (5) (1,2,3,5) (0,2,4,5) (0,1,2,4) (0,3,5) (2) {38,40,55,27,22,45} [#.#.#..] (1,2,3,4,6) (0,1,4,5,6) (0,1,2,4,5) (2,4,5) (2,3) (3,4,6) (2,3,4,5) (0,1,2,3,4,5) (5,6) {19,24,49,36,44,37,22} [..###..] (1,3,6) (0,4,5) (4,5,6) (0,3,5,6) (0,4,6) (0,2,4) (1,2,3,4,5,6) {42,36,25,53,49,43,75} [.#####.] (1,2,4,6) (0,1,2,3,6) (0,2,3,4,5) (0,4,5,6) (1,3,4,6) {27,26,20,22,41,21,42} [#######.##] (4,6) (1,3,4) (0,3,4,5,8,9) (1,2,4,5,6,7) (2,3,4,6,7,8,9) (4,8) (0) (0,1,2,3,4,5,9) (0,2,3,4,5,8) (0,1,3,4,5,6,7,8,9) (0,1,4,5,6) {60,40,41,48,86,67,43,19,41,28} [..#..#..] (1,2,4,5,6) (6) (0,3) (0,3,4,7) (0,2,4,5,6,7) (1,7) (0,1,2,4,5,6) {31,17,23,13,33,23,32,20} [.##..#] (1,2,4,5) (1,2) (2,3,4,5) (1,4) (0,3) (5) {20,29,17,26,33,18} [.##.#.#] (1,2,4,6) (0,1,3,4) (0,6) (0,1,2,3,5) (1,4,5,6) (0,2,3,6) (1,3) (2,4,5) {36,47,49,42,35,36,30} [.##..##.#] (2,6) (0,3,4,5,6,8) (0,1,4) (3) (0,4,6,8) (1,8) (0,2,4,5,6) (2,3,4,5,6,8) (1,4) (4,5,8) (0,3,6,7,8) {36,46,18,30,64,23,37,0,49} [......##] (0,1,2,4,5,7) (2,3,7) (1,3,4,5,6,7) (2,3,4,7) (5,7) (1,4,7) (0,7) (0,1,4,7) {30,37,14,8,39,21,4,55} [.#..###.] (1) (4,6) (0,1,2,3,4,7) (0,1,4,7) (2,3,7) (0,1,5,7) (1,4,5) (0,3,5,6,7) (0,2,6,7) (0,1,2,3,5) {47,38,32,16,26,22,39,44} [##..] (0,2) (0,1,3) (1,2) {28,38,26,20} [#..###.] (0,1,2,3,5) (2,3,6) (0,3,4,6) (0,2,4,6) (0,1,6) (5,6) {43,20,39,44,23,19,53} [.#.##...] (0,4) (0,2,3,4,5,7) (1,3,4) (1,2,3,5,6,7) (0,1,3,4,7) (1,2,4,5,6,7) (3,4,6) (1,2,5,6) (1,3,6,7) (1,2,3,5) {22,81,47,79,52,47,66,50} [####] (0,1,2,3) (1,3) {12,15,12,15} [##..##.#] (0,1,2,3,5,6) (1,2,3,4,6,7) (1,2,6) (1,4,5,7) (2,5) (2,4) (0,2,3) (0,1,2,3,4) (6) (6,7) {22,62,78,42,51,26,52,27} [##..#.###] (3,4,5,6,8) (1,5,7) (0,3,4,5,6,7,8) (0,1,3,5,7) (0,1,2,3,5,6,8) (2,3,4,5,7) (0,1,2,3,5,6,7,8) {45,42,41,73,46,88,51,58,51} [###.] (1,2,3) (0,1,2) {11,29,29,18} [#..##.] (0,2,5) (1,4) (1,2,4) (1,2,4,5) (4,5) (1,3) (3,5) (0,1,5) {29,35,30,25,24,59} [##...#] (2) (1,4,5) (0,2,3,5) (0,1,4) (0,1,2,3,5) {33,31,39,25,25,42} [###.] (0,3) (3) (0,2) (0,1) (1,3) {17,17,7,18} [..##..#.] (0,6) (0,2,3,4,5,7) (0,2,3,5,6) (0,4,5) (0,1,2,3,4) (0,1,2,3,6) (5) (3,5) (0,7) {72,23,42,43,38,45,27,8} [..###.#.#] (0,1,2,3,4,5,6,8) (1,2,7,8) (3,4,6,7) (0,2,4,5,6,7) (0,1,2,4,5,6,7) (2,3,4,6,7,8) (0,1,4) {29,36,52,175,200,19,190,206,37} [.#.###] (0,4) (0,1,3,5) (2,3) (0,1,3) {31,26,5,31,5,7} [#.##] (0,1) (1,3) (1,2) (0,2) (0,1,3) (2,3) {35,37,27,16} [.....###.] (4,5,6) (0,2,6) (0,2,3,4,6,7,8) (0,2,3,4,7,8) (1,6,8) (0,2,5,6,7) (4,6,7) (0,5,6,7) (3,4) (3,7) (1,2,3,5,6,7,8) {62,9,54,42,56,36,85,68,34} [#....##] (4) (1,2,3,4) (0,1,3,4,5,6) (0,3,4,5) (0,5,6) (2,3,4) (0,1,4,5,6) (3) (0,1,2,4,6) {53,26,21,65,64,44,33} [..###] (0,1,3) (2,3,4) (0,2,4) (0,1,2) {53,38,39,22,19} [###...##..] (3,5,7,8,9) (8,9) (3,4,6,8,9) (0,3,7,9) (2,4) (1) (0,1,2,4,6,7,8,9) (0,1,2,6,7) (1,3,4,5,6,8,9) (1,2,4,5,7,9) (0,1,3,4,5,8,9) (2,4,5,7) (1,5,6,9) {34,63,41,50,64,53,33,64,52,88} [##.##..#.#] (4,6) (2,9) (0,1,2,3,4,5,7,8) (0,1,4,5,6,7) (0,1) (0,1,3,4,5,6,7,8) (2,6,9) (3,4,5,7,8,9) (0,2,3,8) (0,1,2,3,4,6,7) (2,7,9) (0,1,3,6,7,8) (2) {84,67,61,63,75,47,73,79,54,34} [.#.#..#...] (0,2,3,4,5,6,8,9) (1,2,3,4,6,9) (0,2,3,6,7,8) (0,1,3,6,7,8) (0,2,4,5,9) (1,3,5,6,9) (0,1,3,6,8,9) (1,2,6,7,8) (0,1,4,5,6,7,8) (4,6,7) (4,9) (0,1,2,3,4) {61,72,50,71,51,31,90,44,70,61} [#.#.#.] (1,3,4) (2,5) (0,1,2,4) (5) (0,1,3,4) (0,1,2,4,5) (2,4) {36,50,34,34,58,140} [.#.....#.] (4,5,6,7) (5) (0,1,4,5,6,8) (1,2,3,4,6,7,8) (0,2,6,7) (4,7) (1,6,7) (0,1,3,4,5,8) (1,7) {31,43,34,20,56,30,58,71,31} [####.#.] (4,6) (0,1,2,3,4,5,6) (1,2,6) (2,3,4,5) (0,1,2,3,5) {28,48,54,34,26,34,40} [...#.#...] (1,8) (0,2,4,5,6,8) (1,3,5,8) (0,2,4,5,7) (0,1,3,4,8) (0,3,5,6,7,8) (0,7,8) (0,6,7,8) {69,38,25,31,30,51,36,58,83} [.#...###.] (2,3,7) (0,3,4,5,8) (1,2,5) (1,2,3,4,5,7,8) (1,3,4,5,6,7,8) (0,1,2,3,4,5,6,7) (0,1,4,8) (2,3,6,7,8) {36,45,56,58,46,46,19,45,42} [##.#####] (0,1,2,3,5) (0,1,3,4,7) (1,3,4,5,6,7) (4,5,6) (2,3,6) (2,3,4,5,6,7) (1,4,5) (0,2,3,4,5,6,7) (2,7) {48,181,46,185,198,203,169,172} [#.#####.#] (2,4,5,6,7,8) (0,2,5) (1,3,4,6,7) (0,1,2,3,5,6,7,8) (0,2,3,4,5,6,8) (1,4,5,6,7,8) (0,1,2,7) (3,8) (0,2,5,6,8) {60,229,73,56,213,231,240,242,234} [.....#] (0,2,4) (1,2,3,4) (2) (0,1,2,4) (1,2,4,5) (5) (0,2,3,4,5) (3,4) {25,26,71,32,67,28} [.#.##.####] (0,2,3,4,6,7,8,9) (5,6,7,8) (1,2,3,4,6,7,9) (0,3,7,8,9) (0,2,3,5,7,9) (2,4,7) (0,1,2,3,4,6,7,9) (0,1,3,6,7) (0,3,8) (2,3,6,9) {65,49,53,83,40,22,67,88,32,53} [.###.] (0,2,3,4) (1,4) (2,3,4) {20,12,22,22,34} [..#..#] (0,1,2) (0,1,3,4,5) (0,1,2,5) (0,4) (1,3,5) (2,3,4,5) (0,1) {45,50,19,23,18,23} [.##.##...] (3,7) (0,1,2,3,5,6,7) (1,2,3,4,6,8) (1,2,5,8) (1,3) (0,1,2,5,6,7) (0,1,2,3,4,5,6,8) (0,3,5,7,8) (0,4,5,8) (4,7) {217,237,232,233,38,236,213,202,64} [###..#.] (0,3,4) (0,1,2,3,4,6) (3,4,5,6) (0,1,3,6) (0,1,5) (0,2,4) (3,4) {61,46,20,73,66,39,47} [#.#.#...] (0,1,2) (0,1,3,4,5,7) (2,3) (0,2,5,7) (3,4,5,6) (0,1,2,3,6) (2,4,5,6,7) {16,15,163,38,138,139,153,132} [#.###.] (1,3) (1,3,5) (5) (0,1,5) (0,2,3,4,5) (2,4,5) (2,3,5) (0,1) {23,19,34,32,26,47} [..####.] (3,4,6) (2,3,4,5) (0,3,5) (3,5) (1,2,4,5) (1,3,4,5) (3,4) (0,6) {18,8,26,63,63,34,32} [..##.#] (1,2,4) (0,1,2,5) (2,3,5) (0,1,2,4,5) {152,172,184,12,28,164} [.##....#] (1,2,4,5,6) (1,2,4) (0,1,2,3,5,6,7) (0,1,2,3,4,5) (3,5,6) (0,1,6) (3,5,7) (0,3) (1,2,4,5) {42,68,53,45,35,69,49,28} [..#.##] (2,4,5) (0,1,4) (1,4,5) (3,5) (1,2,3,4,5) (0,1,3,4) {29,200,26,46,209,199} [#.#.] (0,2) (1,3) {11,6,11,6} [.##......#] (1,3,4,6,8,9) (1,2,9) (0,1,3,4,7,8) (2,4,5,6,7,8,9) (0,1,2,3,4,7,8,9) (0,4,9) (6,7,8) (0,1,2,3,5,6,8,9) (0,2,3,5) {74,67,166,73,187,143,149,152,180,189} [##.####..] (2,4,5,7,8) (5,7) (0,1,3) (0,1,2,3,4,5,6,7) (1,2,4,5,7,8) (0,1,3,4,5,6) (0,1,2) (0,2,5,6,7,8) {54,58,56,44,63,68,40,51,33} [..#..] (0,1,3) (2,3,4) (1,2) (3,4) (0,4) (1,2,3,4) {21,32,27,29,22} [#..####] (0,3,5,6) (2,3,5) (1,3,4) (1,2,4) (0,4,5) (2,3,4,5) {9,24,14,28,34,18,0} [..#.#...#] (0,2,5) (1,3,6) (3,4) (1,2,7) (1,2,3,4,5) (0,2,4,7,8) (4,6) (0,3,4,5,6,7,8) (0,2,3,5,7,8) {41,32,60,52,58,50,26,32,26} [.##.##.#] (0,3,4,7) (0,7) (1,2,3,4,6) (2,6) (1,2,3,4) (0,1,2,5,6,7) (1,3,5,7) (0,2,3,6) {36,7,10,21,14,5,10,37} [#####.#.] (0,1,2,3,4,5) (1,2,6) (0,1,2,3,5,7) (3,7) (0,1,2,7) (5,6) (6) (0,3,6) (1,2,4) (0,5) {219,62,62,53,18,203,35,34} [#.###] (0) (0,1,2,4) (0,2) (1,2,4) (0,3) (0,1,3) (3,4) {200,188,30,185,17} [#..#..] (1,4) (0,3) (0,2,3,4) (0,2,4) (1,4,5) (0,5) {34,20,21,9,41,19} [#.#..] (2,4) (3) (0,1,4) (1,2,4) {8,10,12,4,20} [...#####.] (1,4,5,6,7,8) (1,4) (0,1,2,3,6,7,8) (2,5,6) (0,3,4,5,7,8) (1,2,3,5,7,8) (0,1,2,4) (1,4,8) (0,5,7,8) {26,53,208,23,36,206,218,40,43} [####.##.#] (0,3,5,6,8) (3) (2,3,5,6,7,8) (0,1,2,3,6,7,8) (1,2,3,8) (0,1,2,8) (0,1,2,3,4,6,8) (0,2,3,4,6) (0,5,6,7,8) (0,2,3,7) (2,3,8) {101,50,99,117,34,40,81,50,99} [....##] (0,1,2,3) (1,5) (0,3) (0,1,2,3,4) (0,1,4,5) (0,2,3,4,5) (4,5) {217,191,198,217,194,18} [##.##.] (1,4,5) (0,1,3,4) (0,2) (0,4) {7,8,2,3,10,5} [#...#...] (0,2,4,7) (0,1,2,4,5,6) (0,1) (3) (0,2,4) (1,2,5,6) (0,1,2,3,5,6) (1,2,3,5,6,7) (2,5) (1,2,3,5) {32,56,65,50,17,56,42,10} [...#.#..] (0,3,4,5) (2,3,4,5,6,7) (2,4,6,7) (2) (0,1,4,5,7) (0,1,2,4,5,6) {34,21,44,22,56,43,28,37} [#..#.#....] (0,1,2,3,4,6,7,8) (0,7,8,9) (2,5,6) (3,4,7,9) (0,1,2,3,5,6,7,8,9) (0,2,5,6,9) (3,8) (1,5,7,8,9) {213,24,58,30,26,47,58,209,200,212} ================================================ FILE: exm/aoc/2025/aoc_2025_10_mini.txt ================================================ [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7} [...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2} [.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5} ================================================ FILE: exm/aoc/2025/aoc_2025_10_questions.txt ================================================ --- Day 10: Factory --- Just across the hall, you find a large factory. Fortunately, the Elves here have plenty of time to decorate. Unfortunately, it's because the factory machines are all offline, and none of the Elves can figure out the initialization procedure. The Elves do have the manual for the machines, but the section detailing the initialization procedure was eaten by a Shiba Inu. All that remains of the manual are some indicator light diagrams, button wiring schematics, and joltage requirements for each machine. For example: [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7} [...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2} [.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5} The manual describes one machine per line. Each line contains a single indicator light diagram in [square brackets], one or more button wiring schematics in (parentheses), and joltage requirements in {curly braces}. To start a machine, its indicator lights must match those shown in the diagram, where . means off and # means on. The machine has the number of indicator lights shown, but its indicator lights are all initially off. So, an indicator light diagram like [.##.] means that the machine has four indicator lights which are initially off and that the goal is to simultaneously configure the first light to be off, the second light to be on, the third to be on, and the fourth to be off. You can toggle the state of indicator lights by pushing any of the listed buttons. Each button lists which indicator lights it toggles, where 0 means the first light, 1 means the second light, and so on. When you push a button, each listed indicator light either turns on (if it was off) or turns off (if it was on). You have to push each button an integer number of times; there's no such thing as "0.5 presses" (nor can you push a button a negative number of times). So, a button wiring schematic like (0,3,4) means that each time you push that button, the first, fourth, and fifth indicator lights would all toggle between on and off. If the indicator lights were [#.....], pushing the button would change them to be [...##.] instead. Because none of the machines are running, the joltage requirements are irrelevant and can be safely ignored. You can push each button as many times as you like. However, to save on time, you will need to determine the fewest total presses required to correctly configure all indicator lights for all machines in your list. There are a few ways to correctly configure the first machine: [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7} You could press the first three buttons once each, a total of 3 button presses. You could press (1,3) once, (2,3) once, and (0,1) twice, a total of 4 button presses. You could press all of the buttons except (1,3) once each, a total of 5 button presses. However, the fewest button presses required is 2. One way to do this is by pressing the last two buttons ((0,2) and (0,1)) once each. The second machine can be configured with as few as 3 button presses: [...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2} One way to achieve this is by pressing the last three buttons ((0,4), (0,1,2), and (1,2,3,4)) once each. The third machine has a total of six indicator lights that need to be configured correctly: [.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5} The fewest presses required to correctly configure it is 2; one way to do this is by pressing buttons (0,3,4) and (0,1,2,4,5) once each. So, the fewest button presses required to correctly configure the indicator lights on all of the machines is 2 + 3 + 2 = 7. Analyze each machine's indicator light diagram and button wiring schematics. What is the fewest button presses required to correctly configure the indicator lights on all of the machines? --- Part Two --- All of the machines are starting to come online! Now, it's time to worry about the joltage requirements. Each machine needs to be configured to exactly the specified joltage levels to function properly. Below the buttons on each machine is a big lever that you can use to switch the buttons from configuring the indicator lights to increasing the joltage levels. (Ignore the indicator light diagrams.) The machines each have a set of numeric counters tracking its joltage levels, one counter per joltage requirement. The counters are all initially set to zero. So, joltage requirements like {3,5,4,7} mean that the machine has four counters which are initially 0 and that the goal is to simultaneously configure the first counter to be 3, the second counter to be 5, the third to be 4, and the fourth to be 7. The button wiring schematics are still relevant: in this new joltage configuration mode, each button now indicates which counters it affects, where 0 means the first counter, 1 means the second counter, and so on. When you push a button, each listed counter is increased by 1. So, a button wiring schematic like (1,3) means that each time you push that button, the second and fourth counters would each increase by 1. If the current joltage levels were {0,1,2,3}, pushing the button would change them to be {0,2,2,4}. You can push each button as many times as you like. However, your finger is getting sore from all the button pushing, and so you will need to determine the fewest total presses required to correctly configure each machine's joltage level counters to match the specified joltage requirements. Consider again the example from before: [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7} [...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2} [.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5} Configuring the first machine's counters requires a minimum of 10 button presses. One way to do this is by pressing (3) once, (1,3) three times, (2,3) three times, (0,2) once, and (0,1) twice. Configuring the second machine's counters requires a minimum of 12 button presses. One way to do this is by pressing (0,2,3,4) twice, (2,3) five times, and (0,1,2) five times. Configuring the third machine's counters requires a minimum of 11 button presses. One way to do this is by pressing (0,1,2,3,4) five times, (0,1,2,4,5) five times, and (1,2) once. So, the fewest button presses required to correctly configure the joltage level counters on all of the machines is 10 + 12 + 11 = 33. Analyze each machine's joltage requirements and button wiring schematics. What is the fewest button presses required to correctly configure the joltage level counters on all of the machines? ================================================ FILE: exm/aoc/2025/aoc_2025_11.adb ================================================ -- Solution to Advent of Code 2025, Day 11 ------------------------------------------- -- Reactor -- -- https://adventofcode.com/2025/day/11 -- Copy of questions in: aoc_2025_11_questions.txt -- -- Related links: -- https://forum.ada-lang.io/ -- https://www.reddit.com/r/adventofcode/ -- The files aoc_toolbox.ad* are located in the upper directory: .. --!hac_add_to_path .. -- with AoC_Toolbox; -- For building this program with a "full Ada" compiler, -- such as GNAT, you need the explicit version of the HAT package. -- The files hat*.ad* are located in ../../../src -- See also the GNAT project file aoc_2025.gpr . with HAT; with Interfaces; procedure AoC_2025_11 is use AoC_Toolbox, HAT, Interfaces; input_name : constant VString := +"aoc_2025_11"; r : array (Part_Type) of VString; type Device is (you, imt, grh, yae, luf, ypt, rlf, xls, ggr, xgr, mze, xfb, wms, lpm, wov, oop, cnb, xaz, svr, vya, zuk, gvw, ztu, jmg, hxf, dsq, jpr, qba, zyt, wke, hbz, xru, wsw, ifh, xpt, elr, bbg, bye, ceb, msa, gzq, ufd, jev, gix, see, rnu, axr, efu, cnf, vzq, ehj, xup, tak, omn, kmj, hpe, xzx, qiu, sar, wur, zvs, bez, esf, taz, fgw, wqf, zab, ars, pmn, lay, imd, rak, ixj, pka, wrm, bik, slz, wxx, hju, dcs, yuo, ucg, vtp, znh, slu, qeh, ing, ogh, mlo, nhx, wrf, ihw, yut, drp, ywc, bsl, uhu, mcp, lce, vax, fdo, lmn, ebx, cdt, oka, zny, bxj, azn, aps, pvr, kxq, fry, tth, ize, vfi, qtx, qck, lft, iur, dqs, xci, ayn, frn, fhh, jkp, fka, lcc, yrq, zaw, ggb, vkw, nmm, kak, ejn, yba, hlb, lka, gfk, arh, gtw, imk, mox, fuu, nfe, bdv, asn, yas, cyr, wdt, mef, ihs, box, sqj, olv, hsh, ifc, nko, oim, fwk, djs, pew, vka, mbw, mgz, lvp, bxp, lgw, mbu, jdx, boq, ltz, com, fll, obk, vht, zyh, hni, vsy, kfc, mka, uoh, byu, pwf, rxh, zxf, lvi, mfj, one, qsj, gko, boe, pum, tvs, irl, bqb, qsl, kyx, the, fob, nfq, ams, cwr, gia, fmh, ndx, fpc, ysn, cwa, lfq, wth, hjx, vkn, afp, zgd, fph, riq, ajh, qvo, vzk, wld, xym, akx, mmq, nft, ppl, dkm, wgp, vlb, gou, vwe, qpu, rho, han, swp, wji, sef, jje, xly, lkw, tvg, tat, fft, tym, cqz, xbu, enr, sjd, piz, kgv, cwm, ogu, cxx, qfb, ptb, pui, zkr, pif, oaw, qjd, pcx, pwt, szq, lfc, haj, etc, jdz, sjq, cuq, qun, pny, fwa, mgf, uxl, vzo, alf, xvf, dyq, yek, wcn, xcd, jcv, gqb, rab, srf, kme, ahr, ljd, kmd, swz, qnt, pqj, bio, pbv, gip, dus, vzx, tii, sve, fcg, irm, osd, ftn, xpf, dlh, boc, lke, fbf, zuj, kwq, dac, vcd, cju, ayb, jna, hfg, ajl, dxs, vwv, iwf, mcy, qhv, ove, gdl, fhl, oiu, fbj, lff, rxs, hxe, bkg, jaf, xhd, yor, zpc, ovj, ixl, hlr, gbv, kdd, osb, tfa, qvu, jdy, nkv, ojn, rfy, xmm, jzt, mio, frk, kqf, kft, pqr, kcx, ytn, wau, ljj, jzg, ryr, xcb, uco, pqf, mgb, diw, aak, vha, pgu, phe, zir, vbv, fwb, ipq, xlv, aai, qnf, sym, ppg, nak, vqp, hca, tla, xmh, brj, ohg, mck, bne, uug, wuh, how, glc, isf, elg, mgq, upa, agt, kot, ftb, uzi, brh, aev, ats, eae, foi, qdl, ngp, yir, cfh, asf, vwl, lyf, hlc, etm, zrk, fse, rus, nei, izt, ptn, ebd, rcr, txb, lkh, zal, wpb, ooc, wjd, ona, qqj, zco, izi, hpj, rpb, miw, qte, wpu, awd, byh, fac, rbx, dwc, wbn, hly, sdj, une, ujn, ouy, swg, amb, dap, nnz, xfk, nik, nmz, bic, enh, pcm, qnw, dhn, dqx, skx, mpw, wyd, nso, mjd, cmu, jdo, cxk, gua, ewp, fzl, gkv, cnt, bja, kbq, ums, mjn, qdj, ulf, gcc, sjy, kow, xjh, ogt, znt, jox, bhg, xnn, wzm, pgr, kwb, elm, tei, gvy, ryk, dkw, epu, vwt, hwr, jjf, cir, yxm, jvd, byz, rrt, vjs, wax, xdb, ozj, bao, pue, fgc, hkw, xob, smv, vnu, gir, hou, lne, sfj, qmn, otd, qfo, ujb, ped, dcm, hai, vns, kjs, aso, rpp, fjw, ezl, huk, mzm, zzp, ahf, auy, xva, wci, bhk, tur, zvu, nkt, pdz, fnj, tco, jix, cwe, jmd, cji, aod, kdb, xos, -- Example: aaa, bbb, ccc, ddd, eee, fff, ggg, hhh, iii, -- Other example: tty, hub, -- tuo); -- Out connection : array (Device, 1 .. 50) of Device; connections, paths : array (Device) of Natural; procedure Read_Data is unused_separator : Character; asm : String (1 .. 3); i : Integer; f : File_Type; s : VString; row : Device; begin for d in Device loop connections (d) := 0; end loop; Open (f, input_name & ".txt"); while not End_Of_File (f) loop Get (f, asm); row := Device'Value (asm); Get (f, unused_separator); -- put (row'image & ':'); i := 0; Get_Line (f, s); loop Delete (s, 1, 1); -- ' ' i := i + 1; connection (row, i) := Device'Value (To_String (Slice (s, 1, 3))); -- put (i, 0); put (" " & connection(row,i)'Image); Delete (s, 1, 3); exit when Length (s) = 0; end loop; connections (row) := i; -- new_line; end loop; Close (f); end Read_Data; procedure Reset_Paths is begin for d in Device loop paths (d) := Integer'Last; end loop; end Reset_Paths; function Count_Paths (from, to : Device) return Natural is res : Natural; begin if from = to then return 1; elsif from = tuo then -- Put_Line ("OUT"); return 0; else -- Memoization, get: if paths (from) < Integer'Last then return paths (from); else res := 0; for i in 1 .. connections (from) loop -- Put (+"From: " & from'Image & ", Node: " & i & "/" & connections (from) 'image & ": " & connection (from, i)'Image); -- Skip_Line; res := res + Count_Paths (connection (from, i), to); end loop; -- Memoization, set: paths (from) := res; return res; end if; end if; end Count_Paths; procedure Do_Part_1 is begin Reset_Paths; r (part_1) := +"" & Count_Paths (you, tuo); end Do_Part_1; procedure Do_Part_2 is res : Integer; begin Reset_Paths; res := Count_Paths (svr, fft); Reset_Paths; res := res * Count_Paths (fft, dac); Reset_Paths; res := res * Count_Paths (dac, tuo); r (part_2) := +"" & res; end Do_Part_2; compiler_test_mode : constant Boolean := Argument_Count >= 1; T0 : constant Time := Clock; begin Read_Data; Do_Part_1; Do_Part_2; if compiler_test_mode then if r (part_1) /= Argument (1) or r (part_2) /= Argument (2) then Set_Exit_Status (1); -- Compiler test failed. end if; else Put_Line (+"Done in: " & (Clock - T0) & " seconds"); Put_Line (+"Part 1: " & r (part_1)); Put_Line (+"Part 2: " & r (part_2)); -- Part 1: validated by AoC: 423. -- Part 2: validated by AoC: 333657640517376. end if; end AoC_2025_11; ================================================ FILE: exm/aoc/2025/aoc_2025_11.txt ================================================ you: wms hkw ove qba ats imt: swz aev ams bhg yir grh: fph cuq pcx yae: qiu mef luf: zir jdx jmg ypt: ahf wov hai rlf: haj yxm xls: qnw ppg ggr: xmh vka xgr: hlc mzm mze: ljj ppg ysn qnw xfb: diw cxx vlb mgf wms: xcd hni lpm: dap wov: rbx skx ztu oop: djs rfy cnb: haj xaz: tur kmd wsw svr: qnf jjf xjh omn vya: mgq qqj asn zuk: xvf lff cju gvw: xfk jje gir ztu: hlr lka jmg: dap tei hxf: mjd vns mlo dsq: vkw vtp cwm jpr: izt esf qba: cju xvf lff fcg zyt: yek imd qsl wke: tuo hbz: nnz qck xru: wuh wsw: mgq ifh: ejn pif xpt: ouy elr: izi wke ljd oim bbg: xnn ove hbz gkv fdo frn vfi uxl rrt wms dcs vkn bye: jna xgr vcd ceb: cwa msa: hly gir gzq: byz ufd: ihs ped jev: wbn gix: wdt see: nfq rnu: nei wdt azn axr: oop pgu efu: aai ejn cnf: oaw ryk wpb vzq: lka hlr zkr aps ehj: tuo xup: esf tak: wld xob omn: xfb fry tvg fll pwt oka vwe rpp bja miw boq elm kmj: bsl xzx tco hpe: une tvs xzx: bbg gia fwk you qiu: bdv nkt uco sar: boc tfa qvo vzq wur: pdz wld xob zvs: bbg bez: kow tvs hju une esf: tuo taz: nft fgw: mzm hlc wqf: mka gko zab: wuh xzx ars: mjn jmd pmn: uug vzx lay: you bbg fwk imd: see rak: tuo ixj: kow tvs une pka: txb wrm: sjq kme bik: aps slz: tvs kow une wxx: nfe hju: ypt xls swg wci wth dcs: qvu yuo: xhd ryk ucg: lpm zaw zir vtp: tuo znh: vya phe wsw kmd slu: ulf msa gvw amb nkv qeh: yor ing: cji hlb ogh: gfk haj yxm mlo: ptn mmq alf nft nhx: skx wrf: jkp fhl ihw: cwa rlf xbu yut: hjx xmm drp: vkw vqp vtp ywc: com wxx ize bsl: fwk gia zvu bbg uhu: foi wrm qnt mcp: vqp cwm lce: nak uzi vax: auy fgw cwr fdo: qck lvi nnz lmn: han obk fuu ebx: nko kdd boe vht cdt: qiu oka: uug lkh zny: sef dxs fac elg bxj: gcc huk azn: tth aps aps: ufd ogt bxj jaf zpc ptb jev pvr: mjd vns kxq: vns fry: uug tth: hxe jev zpc bio yba enr mbw ujb bxj ogt ryr dkw slu ize: nfe hlc vfi: lvi qck qtx: xup ouy qck: piz ohg lft: ogh kgv iur: dlh lcc dqs: aps zkr hlr xci: ahf bhk hai ayn: tth hlr lka frn: lff fhh: lka tth zkr aps jkp: fnj vbv fka: fnj vbv lcc: hju tvs yrq: wrm zaw: dap ggb: pew lgw vkw: tuo nmm: ona ums vha xos kak: tuo ejn: ixj kyx yba: ftb hlb: vht lka: ryr zrk ufd slu lfc ptb bio zpc cqz hxe mbw jaf dkw cxk jzg smv jev ogt bxj ujb enr yba gfk: fmh znh aso qdl jdy qeh kot arh: fft eae gtw: tth lka imk: pdz wld xob mox: irm fuu: ftn nfe: cwe ndx etc qhv agt vzk dcm cmu oiu fwb ahr zgd mgz wyd byh ajh lkw fob rho sve sfj lce riq znt yut ogu bdv: you fwk zvu bbg asn: hju une yas: pif ejn cyr: fwa qpu mpw wdt: lka mef: bdv ihs: gua box: tuo sqj: ehj olv: dlh lcc rpb hsh: rnu gix nfq dus ifc: xup jpr nko: you zvu fwk gia oim: tuo fwk: ove dcs hbz gkv cnt frn vzo brh rrt djs: uco bdv nkt pew: dsq sjy epu vka: tvs kow hju mbw: amb ulf msa gvw mgz: zab xru pui kmj lvp: zny mgf bxp: hlc mzm lgw: epu mcp sjy drp mbu: tuo jdx: dap tei boq: lft ltz: sjy mcp dsq com: nfe fll: pqr luf gko obk: frk ftn vht: zvu gia fwk zyh: lgw mfj pew ltz hni: xym ggb bkg vsy: cdt dac yae kfc: gou fpc mka: zaw lpm jmg uoh: fwa qpu byu: rak mck pwf: rcr rxh: qtx zxf: tco wuh lvi: ohg kft dqx mfj: drp one: lka qsj: pif gko: jmg lpm jdx zaw zir boe: zvu bbg gia fwk pum: aps lka tth tvs: wci wji zyt dhn hwr vwl wrf ojn rab irl: gip bqb: kjs qmn lft qsl: see hsh kyx: hju the: yrq zco xcb uhu kbq fob: gzq uzi osb nfq: nei wdt azn ams: afp cwr: mzm gia: xnn brh hkw hbz irl dcs zuk cnt gkv gbv fmh: rxs xpf ndx: hou uoh qdj vwt fpc: hlc nfe ysn: wjd zuj pum cwa: yxm haj gfk lfq: kak ujn ehj box wth: imd hjx: hlb ebx cji aak vkn: hxf wax kxq afp: dkm lyf zgd: hjx fph: bao ewp riq: uoh hou qdj cyr vwt ajh: akx axr qvo: aps lka hlr tth zkr vzk: zab xru pui kmj wld: haj xym: pew mfj vnu akx: yae pgu oop cdt dac mmq: jzt byu nft: sdj byu ppl: bxp gou fpc dkm: yxm haj gfk wgp: aps hlr zkr vlb: sef gou: hlc nfe mzm vwe: ams aev qpu: you bbg zvu fwk gia rho: vwt hou han: ftn frk elr swp: dlh rpb wji: sar xos vha ums sef: wur jje: szq kfc xly: hlc nfe lkw: uoh hou cyr tvg: vzx uug tat: ljj ppg ysn fft: olv dyq tym: yxm haj cqz: gcc nmz xbu: haj yxm gfk enr: amb sjd: iwf piz: cuq pcx fph fgc kgv: haj yxm cwm: tuo ogu: zxf zab pui cxx: elg osd qfb: une ptb: ftb wbn pui: bsl zkr: dkw zrk jzg ryr cxk ufd lfc slu smv cqz bio ptb hxe jev ujb ogt jaf enr yba mbw pif: vjs ixj oaw: cir qjd: uhu xcb zco yrq pcx: otd sqj bao ewp pwt: lkh vzx szq: fpc bxp lfc: jvd haj: pwf yuo xdb znh aso asf aod kot srf fmh xaz qdl fzl etc: ing jdz: fwk gia zvu bbg sjq: aps lka hlr tth zkr cuq: ewp bao sqj qun: cwr fgw fbj pny: kjs lft qmn fwa: gia bbg zvu you mgf: fac uxl: hni vzo: cju xvf fcg lff alf: byu sdj xvf: pqj mgb isf pqf rxh dyq: rpb lcc yek: hca hsh wcn: rxs xcd: bkg ggb jcv: yxm haj gfk gqb: tuo rab: hpj jkp srf: efu qsj kme: hlr aps ahr: awd mcy ljd: tuo kmd: mgq swz: enh tla qnt: sjq gtw pqj: zzp bio: nmz gcc pbv: hlr tth zkr gip: taz dus: wdt nei vzx: ooc ceb ihw jix tii: ovj jna xly sve: uoh fcg: isf mgb pqj pqf irm: piz ohg kft grh osd: xlv imk ftn: ljd mbu izi xpf: lne bez hpe wau dlh: kow tvs une hju boc: zkr hlr lke: tuo fbf: bbg zvu fwk you zuj: hlr lka zkr tth kwq: gia bbg dac: mef djs vcd: nfe cju: pqf rxh ayb: xbu rlf jna: mzm hlc hfg: mzm ajl: fka hpj fhl dxs: imk tak vwv: kdb xpf iwf: ytn pgr jdz mcy: ytn qhv: osb gzq ove: hni gdl gdl: xym zyh fhl: vbv ebd oiu: xmm ing fbj: hlc lff: isf pqj rxs: hpe wau bez hxe: vax bkg: pew mfj jaf: nmz huk xhd: ggr cir how yor: eae zpc: qun nik ovj: mzm ixl: sjq kme gtw hlr: bxj bio dkw cxk ryr jzg zrk gbv: hni gdl kdd: you zvu fwk osb: lay zvs kwq fbf tfa: tth zkr lka qvu: lmn mjn jdy: ifh qsj efu yas nkv: jje ojn: ahf wov hai nhx bhk rfy: nkt xmm: ebx aak jzt: mck rak mio: lcc frk: izi oim kqf: hlc kft: fgc pqr: zir jdx kcx: zny ytn: fwk gia zvu bbg wau: une hju tvs ljj: wjd pum zuj jzg: huk gcc ryr: nik xcb: qnt uco: fwk bbg you pqf: xpt ifc mgb: zzp ifc diw: fac dxs elg osd aak: vht nko kdd boe vha: fhh vzq qvo boc pgu: rfy phe: mgq asn zir: dap bic vbv: pbv bik fwb: vsy ipq: swp olv dyq iur xlv: pdz gvy wld xob aai: ixj vjs qnf: kcx fjw tvg wqf pcm fry sym: aai ejn ppg: wjd zuj pum nak: fbf kwq zvs vqp: tuo hca: gix rnu tla: cnb dkm tym jcv xmh: tvs brj: iwf ohg: pcx fgc fph mck: tuo bne: zxf uug: ceb ooc wuh: gia fwk zvu you how: qfb slz vka glc: xcb yrq zco isf: ifc zzp elg: imk xlv wur mgq: hju kow upa: sdj jzt agt: xmm kot: phe wsw kmd tur ftb: ywc jox uzi: byz lay kwq fbf brh: wax pvr kxq aev: afp tla ats: nso jdo eae: mio olv iur swp foi: kme qdl: arh zal rcr yor ngp: yxm haj yir: enh cfh: tuo asf: yor arh zal vwl: ona ums xos sar lyf: yxm gfk hlc: sve lce sfj oiu brj zgd wyd byh ajh sjd etc vzk qhv cmu bne etm: tuo zrk: ihs jvd fse: nfe mzm rus: yek nei: zkr tth hlr lka izt: tuo ptn: jzt ebd: bik one rcr: ipq fft txb: ozj lkh: ceb ihw jix ayb zal: fft wpb: how ooc: rlf wjd: tth hlr lka ona: boc tfa fhh vzq qqj: tvs hju zco: qnt izi: tuo hpj: ebd fnj vbv rpb: tvs une miw: swz bhg ams qte: luf gko wpu: vcd xgr jna xly awd: pgr jdz byh: akx axr vsy fac: imk rbx: aps tth zkr lka hlr dwc: wpb oaw ryk wbn: txb jox hly: szq ppl sdj: mck lke une: qjd dhn rus wrf ojn ajl the ezl ujn: tuo ouy: gqb esf izt swg: yek amb: hly gir xfk dap: haj yxm nnz: ohg piz dqx kft grh xfk: ppl kfc nik: cwr hfg fgw auy nmz: bye bic: haj gfk enh: jcv tym dkm cnb lyf pcm: vlb cxx zny qnw: wgp pum zuj dhn: nhx dqx: pcx fgc fph skx: aps lka zkr tth mpw: gia fwk bbg wyd: zxf kmj pui xru nso: mjn mjd: nft alf upa mmq cmu: awd mcy jdo: mjn lmn jmd cxk: ihs ped jvd gua: nfe hlc ewp: etm ehj fzl: kmd tur wsw gkv: jdo qvu wzm cnt: lvi irm bja: diw cxx zny kbq: ixl ums: qvo boc tfa fhh vzq mjn: han pue qdj: fwa ulf: gir hly gcc: tii sjy: cwm cfh vqp vkw kow: ojn nmm wrf vwl qjd mze xci swg xls wth glc tat ypt rab hwr dhn rus zyt the wji ajl xjh: fjw fll pcm xfb pwt miw bja vwe rpp pmn kcx pny qte bqb ogt: vax qun nik znt: vsy akx jox: wxx ozj ize com bhg: afp tla xnn: wzm jdo ars wzm: lmn pgr: you zvu bbg kwb: ngp ogh elm: gko ucg luf pqr tei: yxm gfk gvy: gfk ryk: cir how dkw: nik epu: cwm vtp vqp vkw vwt: qpu hwr: qnw ysn jjf: pny oka kcx bqb lvp vwe rpp fjw xfb fry pcm imt cir: slz xva qfb yxm: srf kot cnf aod dwc asf aso qfo wcn znh xdb pwf yuo qeh jdy vwv qdl xaz fmh jvd: kqf fse byz: zvu bbg you rrt: cju xvf lff vjs: tvs kow une wax: taz xdb: yas sym efu qsj ozj: mzm bao: ehj box ujn pue: ftn fgc: lfq bao otd hkw: hni gdl xob: yxm haj smv: jvd ped vnu: sjy gir: kfc hou: mpw fwa lne: kow sfj: osb nak uzi qmn: ngp kgv otd: ujn kak box qfo: ifh yas ujb: ftb pka wbn ped: gua kqf fse dcm: gzq nak osb hai: ztu vns: upa alf kjs: ngp kgv aso: xpf rxs rpp: luf pqr gko ucg fjw: qmn kwb ezl: fka jkp fhl huk: wpu tii bye mzm: sve rho fob lkw yut riq brj fwb ajh byh zgd mgz etc sjd ndx dcm cmu vzk qhv bne cwe zzp: jpr ahf: skx rbx dqs auy: mzm nfe hlc xva: kow tvs wci: hpj bhk: skx ztu rbx tur: qqj zvu: wms vzo vfi brh mox fdo ove zuk irl vkn hbz nkt: you zvu bbg gia pdz: gfk haj fnj: ayn bik pbv tco: bbg fwk gia you jix: cwa cwe: mcy jmd: fuu obk pue cji: boe aod: vya kmd kdb: wau lne bez xos: vzq ================================================ FILE: exm/aoc/2025/aoc_2025_11_questions.txt ================================================ --- Day 11: Reactor --- You hear some loud beeping coming from a hatch in the floor of the factory, so you decide to check it out. Inside, you find several large electrical conduits and a ladder. Climbing down the ladder, you discover the source of the beeping: a large, toroidal reactor which powers the factory above. Some Elves here are hurriedly running between the reactor and a nearby server rack, apparently trying to fix something. One of the Elves notices you and rushes over. "It's a good thing you're here! We just installed a new server rack, but we aren't having any luck getting the reactor to communicate with it!" You glance around the room and see a tangle of cables and devices running from the server rack to the reactor. She rushes off, returning a moment later with a list of the devices and their outputs (your puzzle input). For example: aaa: you hhh you: bbb ccc bbb: ddd eee ccc: ddd eee fff ddd: ggg eee: out fff: out ggg: out hhh: ccc fff iii iii: out Each line gives the name of a device followed by a list of the devices to which its outputs are attached. So, bbb: ddd eee means that device bbb has two outputs, one leading to device ddd and the other leading to device eee. The Elves are pretty sure that the issue isn't due to any specific device, but rather that the issue is triggered by data following some specific path through the devices. Data only ever flows from a device through its outputs; it can't flow backwards. After dividing up the work, the Elves would like you to focus on the devices starting with the one next to you (an Elf hastily attaches a label which just says you) and ending with the main output to the reactor (which is the device with the label out). To help the Elves figure out which path is causing the issue, they need you to find every path from you to out. In this example, these are all of the paths from you to out: Data could take the connection from you to bbb, then from bbb to ddd, then from ddd to ggg, then from ggg to out. Data could take the connection to bbb, then to eee, then to out. Data could go to ccc, then ddd, then ggg, then out. Data could go to ccc, then eee, then out. Data could go to ccc, then fff, then out. In total, there are 5 different paths leading from you to out. How many different paths lead from you to out? --- Part Two --- Thanks in part to your analysis, the Elves have figured out a little bit about the issue. They now know that the problematic data path passes through both dac (a digital-to-analog converter) and fft (a device which performs a fast Fourier transform). They're still not sure which specific path is the problem, and so they now need you to find every path from svr (the server rack) to out. However, the paths you find must all also visit both dac and fft (in any order). For example: svr: aaa bbb aaa: fft fft: ccc bbb: tty tty: ccc ccc: ddd eee ddd: hub hub: fff eee: dac dac: fff fff: ggg hhh ggg: out hhh: out This new list of devices contains many paths from svr to out: svr,aaa,fft,ccc,ddd,hub,fff,ggg,out svr,aaa,fft,ccc,ddd,hub,fff,hhh,out svr,aaa,fft,ccc,eee,dac,fff,ggg,out svr,aaa,fft,ccc,eee,dac,fff,hhh,out svr,bbb,tty,ccc,ddd,hub,fff,ggg,out svr,bbb,tty,ccc,ddd,hub,fff,hhh,out svr,bbb,tty,ccc,eee,dac,fff,ggg,out svr,bbb,tty,ccc,eee,dac,fff,hhh,out However, only 2 paths from svr to out visit both dac and fft. Find all of the paths that lead from svr to out. How many of those paths visit both dac and fft? ================================================ FILE: exm/aoc/aoc_check_list.txt ================================================ https://adventofcode.com/ 1 coffee 2 prepare aoc_20xx_yy.adb in LEA 3 prepare aoc_20xx.gpr in case GNAT is needed 4 prepare empty mini.txt in Notepad++ ----- Start! ----- 5 open today's aoc web page 6 download input.txt and have a glimpse on it 7 read the instructions as quickly as possible... 8 paste the example into mini.txt 9 code and train with mini.txt 10 run with input.txt ================================================ FILE: exm/aoc/aoc_toolbox.adb ================================================ package body AoC_Toolbox is procedure GCD_and_Bezout (a, b : in Integer; s, t, the_gcd : out Integer) is -- Finds the GCD and s, t for the -- ` GCD (a, b) = a * s + b * t ` factorization (Bezout theorem). -- Program 1.8, Introduction to number theory, RBJT Allenby & EJ Redfern ta, tb : array (1 .. 3) of Integer; q, r : Integer; begin ta (1) := 1; tb (1) := 0; ta (2) := 0; tb (2) := 1; ta (3) := a; tb (3) := b; while tb (3) /= 0 loop q := ta (3) / tb (3); for i in 1 .. 3 loop r := ta (i) - q * tb (i); ta (i) := tb (i); tb (i) := r; end loop; end loop; s := ta (1); t := ta (2); the_gcd := ta (3); end GCD_and_Bezout; function GCD (a, b : Integer) return Integer is dummy_s, dummy_t, the_gcd : Integer; begin GCD_and_Bezout (a, b, dummy_s, dummy_t, the_gcd); return the_gcd; end GCD; function LCM (a, b : Integer) return Integer is begin return abs (a * b) / GCD (a, b); end LCM; procedure GCD_and_Bezout_64 (a, b : in Integer_64; s, t, the_gcd : out Integer_64) is -- Finds the GCD and s, t for the -- ` GCD (a, b) = a * s + b * t ` factorization (Bezout theorem). -- Program 1.8, Introduction to number theory, RBJT Allenby & EJ Redfern ta, tb : array (1 .. 3) of Integer_64; q, r : Integer_64; begin ta (1) := 1; tb (1) := 0; ta (2) := 0; tb (2) := 1; ta (3) := a; tb (3) := b; while tb (3) /= 0 loop q := ta (3) / tb (3); for i in 1 .. 3 loop r := ta (i) - q * tb (i); ta (i) := tb (i); tb (i) := r; end loop; end loop; s := ta (1); t := ta (2); the_gcd := ta (3); end GCD_and_Bezout_64; function GCD_64 (a, b : Integer_64) return Integer_64 is dummy_s, dummy_t, the_gcd : Integer_64; begin GCD_and_Bezout_64 (a, b, dummy_s, dummy_t, the_gcd); return the_gcd; end GCD_64; function LCM_64 (a, b : Integer_64) return Integer_64 is begin return abs (a * b) / GCD_64 (a, b); end LCM_64; function Dist_L1 (a, b : Point) return Natural is begin return abs (a.x - b.x) + abs (a.y - b.y); end Dist_L1; function Dist_Max (a, b : Point) return Natural is begin return HAT.Max (abs (a.x - b.x), abs (a.y - b.y)); end Dist_Max; procedure Rotate (x, y : in out HAT.Real; a : HAT.Real) is use HAT; nx : Real; begin nx := Cos (a) * x - Sin (a) * y; y := Sin (a) * x + Cos (a) * y; x := nx; end Rotate; function Opposite (d : Direction) return Direction is begin case d is when north => return south; when south => return north; when east => return west; when west => return east; end case; end Opposite; function Turn_Right (d : Direction) return Direction is begin case d is when north => return east; when south => return west; when east => return south; when west => return north; end case; end Turn_Right; function Dist_L1_3D (a, b : Point_3D) return Natural is begin return abs (a.x - b.x) + abs (a.y - b.y) + abs (a.z - b.z); end Dist_L1_3D; function Dist_L1_3D_R (a, b : Point_3D_R) return HAT.Real is use HAT; begin return abs (a.x - b.x) + abs (a.y - b.y) + abs (a.z - b.z); end Dist_L1_3D_R; procedure Skip_till_Space (f : in out HAT.File_Type; times : Positive) is c : Character; use HAT; begin for repeat in 1 .. times loop while not End_Of_File (f) loop Get (f, c); exit when c = ' '; end loop; exit when End_Of_File (f); end loop; end Skip_till_Space; function Sgn_64 (i : Integer_64) return Integer_64 is begin if i > 0 then return 1; elsif i < 0 then return -1; else return 0; end if; end Sgn_64; function Image (i : Integer_64) return HAT.VString is use HAT; res : VString := +i'Image; begin if i < 0 then return res; else -- Remove the leading ' '. Delete (res, 1, 1); return res; end if; end Image; function Deg_2_Rad (a : HAT.Real) return HAT.Real is use HAT; begin return (Pi / 180.0) * a; end Deg_2_Rad; function Sim_AND (a, b : Integer_64) return Integer_64 is x : Integer_64 := a; y : Integer_64 := b; res : Integer_64 := 0; m : Integer_64 := 1; x1, y1 : Integer_64; begin if a < 0 or else b < 0 then HAT.Put ("XOR on negative values!"); end if; while x > 0 or else y > 0 loop x1 := x mod 2; y1 := y mod 2; if x1 = 1 and y1 = 1 then res := res + m; end if; x := x / 2; y := y / 2; m := m * 2; end loop; return res; end Sim_AND; function Sim_XOR (a, b : Integer_64) return Integer_64 is x : Integer_64 := a; y : Integer_64 := b; res : Integer_64 := 0; m : Integer_64 := 1; x1, y1 : Integer_64; begin if a < 0 or else b < 0 then HAT.Put ("XOR on negative values!"); end if; while x > 0 or else y > 0 loop x1 := x mod 2; y1 := y mod 2; if (x1 = 1 or y1 = 1) and then not (x1 = 1 and y1 = 1) then res := res + m; end if; x := x / 2; y := y / 2; m := m * 2; end loop; return res; end Sim_XOR; package body Hash_Maps is -- Hash map code extended from AoC_2023_15's implementation. -- HASH = Holiday ASCII String Helper :-). function HASH (s : HAT.VString) return Natural is h : Natural := 0; use HAT; begin for i in 1 .. Length (s) loop h := ((h + Ord (Element (s, i))) * 17) rem 256; end loop; return h; end HASH; procedure Clear (hm : out Hash_Map_Type) is begin for i in hm'Range loop hm (i).slots := 0; end loop; end Clear; procedure Insert (hm : in out Hash_Map_Type; key : in HAT.VString; new_value : in Integer_64; replace : in Boolean; -- Replace existing value ? value : out Integer_64) -- If key exists, we get previous value. is b : constant Natural := HASH (key); new_slots_total : Natural; use HAT; begin for s in 1 .. hm (b).slots loop if hm (b).slot (s).key = key then value := hm (b).slot (s).value; if replace then hm (b).slot (s).value := new_value; end if; return; end if; end loop; -- Append new value. new_slots_total := hm (b).slots + 1; hm (b).slot (new_slots_total).key := key; hm (b).slot (new_slots_total).value := new_value; hm (b).slots := new_slots_total; value := new_value; end Insert; procedure Find (hm : in out Hash_Map_Type; key : in HAT.VString; not_found_value : in Integer_64; value : out Integer_64) is b : constant Natural := HASH (key); use HAT; begin for s in 1 .. hm (b).slots loop if hm (b).slot (s).key = key then value := hm (b).slot (s).value; return; end if; end loop; value := not_found_value; end Find; end Hash_Maps; end AoC_Toolbox; ================================================ FILE: exm/aoc/aoc_toolbox.ads ================================================ with HAT, Interfaces; package AoC_Toolbox is use Interfaces; ---------------- -- AoC game -- ---------------- type Part_Type is (part_1, part_2); type Data_Type is (mini, input); subtype Digit_Type is Natural range 0 .. 9; subtype Alpha is Character range 'a' .. 'z'; subtype Upcase_Alpha is Character range 'A' .. 'Z'; subtype Binary is Natural range 0 .. 1; --------------- -- Algebra -- --------------- -- Greatest Common Denominator -- procedure GCD_and_Bezout (a, b : in Integer; s, t, the_gcd : out Integer); function GCD (a, b : Integer) return Integer; -- Least Common Multiple -- function LCM (a, b : Integer) return Integer; procedure GCD_and_Bezout_64 (a, b : in Integer_64; s, t, the_gcd : out Integer_64); function GCD_64 (a, b : Integer_64) return Integer_64; function LCM_64 (a, b : Integer_64) return Integer_64; ---------------------- -- Plane Geometry -- ---------------------- type Point is record x, y : Integer; end record; function Dist_L1 (a, b : Point) return Natural; function Dist_Max (a, b : Point) return Natural; procedure Rotate (x, y : in out HAT.Real; a : HAT.Real); type Direction_or_Nil is (nil, north, east, south, west); subtype Direction is Direction_or_Nil range north .. west; function Opposite (d : Direction) return Direction; function Turn_Right (d : Direction) return Direction; ------------------- -- 3D Geometry -- ------------------- type Point_3D is record x, y, z : Integer; end record; type Point_3D_R is record x, y, z : HAT.Real; end record; function Dist_L1_3D (a, b : Point_3D) return Natural; function Dist_L1_3D_R (a, b : Point_3D_R) return HAT.Real; ----------------------- -- Text processing -- ----------------------- procedure Skip_till_Space (f : in out HAT.File_Type; times : Positive); -------------------- -- Miscellaneous -- -------------------- function Sgn_64 (i : Integer_64) return Integer_64; function Image (i : Integer_64) return HAT.VString; function Deg_2_Rad (a : HAT.Real) return HAT.Real; -- Simulate AND, XOR for HAC which hasn't modular types... function Sim_AND (a, b : Integer_64) return Integer_64; function Sim_XOR (a, b : Integer_64) return Integer_64; --------------------------------------------- -- Hash maps (extended from AoC_2023_15) -- --------------------------------------------- package Hash_Maps is type Hash_Slot_Type is record key : HAT.VString; value : Integer_64; end record; type Hash_Slot_Array_Type is array (1 .. 2_000) of Hash_Slot_Type; type Hash_Box_Type is record slot : Hash_Slot_Array_Type; slots : Natural; -- HAC wish: initialized value := 0; end record; type Hash_Map_Type is array (0 .. 255) of Hash_Box_Type; -- ^ HAC wish: ideally that type would be private and the -- only publicly visible identifier... procedure Clear (hm : out Hash_Map_Type); procedure Insert (hm : in out Hash_Map_Type; key : in HAT.VString; new_value : in Integer_64; replace : in Boolean; -- Replace existing value ? value : out Integer_64); -- If key exists, we get previous value. procedure Find (hm : in out Hash_Map_Type; key : in HAT.VString; not_found_value : in Integer_64; value : out Integer_64); end Hash_Maps; end AoC_Toolbox; ================================================ FILE: exm/arguments.adb ================================================ with HAT; use HAT; procedure Arguments is begin Put ("Command-line arguments:"); Put (Argument_Count); New_Line (2); Put_Line ("Argument list:"); Put_Line ("--------------"); for A in 1 .. Argument_Count loop Put_Line (" --> [" & Argument (A) & ']'); end loop; end Arguments; ================================================ FILE: exm/attributes.adb ================================================ with HAT; procedure Attributes is type Enum is (aa, bb, cc, dd); subtype Sub_Enum is Enum range bb .. cc; d : constant Duration := 123.456; i : constant Integer := 123; r : constant HAT.Real := HAT.Pi; b : constant Boolean := True; c : constant Character := 'x'; e : constant Enum := dd; subtype Some_Range is Integer range -123 .. 456; subtype A_to_Z is Character range 'A' .. 'Z'; dummy_e : Enum; dummy_i, sum : Integer; type A is array (Sub_Enum) of HAT.Real; type M is array (-5 .. -2, bb .. dd) of Integer; mm : M; use HAT; begin --------------------------------------------------- -- If you uncomment any of the following lines -- -- you'll get a Constraint_Error on run time: -- --------------------------------------------------- -- dummy_i := Some_Range'Succ (Some_Range'Last); -- dummy_i := Some_Range'Pred (Some_Range'First); -- dummy_e := Enum'Value ("ff"); -- Put_Line ("Attributes S = Standard subtype, indicated with '*'"); Put_Line ("========== or HAT subtype, indicated with '#'"); New_Line; Put_Line ("S'First and S'Last attributes for scalar subtype S"); Put_Line ("--------------------------------------------------"); New_Line; Put_Line (+" * Integer's bounds : " & Integer'First & " .. " & Integer'Last); Put_Line (+" * Natural's bounds : " & Natural'First & " .. " & Natural'Last); Put_Line (+" * Positive's bounds : " & Positive'First & " .. " & Positive'Last); Put_Line (+" Some_Range's bounds : " & Some_Range'First & " .. " & Some_Range'Last); Put_Line (+" * Boolean's bounds : " & Boolean'First & " .. " & Boolean'Last); Put_Line (+" A_to_Z's bounds : " & A_to_Z'First & " .. " & A_to_Z'Last); -- Alternative using VString and the direct concatenation VString & Real: Put_Line (+" # Real's bounds : " & Real'First & " .. " & Real'Last); -- Alternative using String and the 'Image attribute: Put_Line (" # Real's bounds : " & Real'Image (Real'First) & " .." & Real'Image (Real'Last)); Put_Line (" Enum's bounds : " & Enum'Image (Enum'First) & " .. " & Enum'Image (Enum'Last)); Put_Line (" Sub_Enum's bounds : " & Enum'Image (Sub_Enum'First) & " .. " & Enum'Image (Sub_Enum'Last)); New_Line; Put_Line ("S'Pred and S'Succ attributes"); Put_Line ("----------------------------"); New_Line; Put_Line (+" * Integer'Succ (100) : " & Integer'Succ (100)); Put_Line (+" * Integer'Pred (100) : " & Integer'Pred (100)); Put_Line (+" Some_Range'Succ (Some_Range'First) : " & Some_Range'Succ (Some_Range'First)); New_Line; Put_Line ("S'Pos and S'Val attributes"); Put_Line ("--------------------------"); New_Line; Put_Line (+" * Boolean'Pos (True) : " & Boolean'Pos (True)); Put_Line (+" * Boolean'Val (0) : " & Boolean'Val (0)); Put_Line (+" * Character'Pos (' ') : " & Character'Pos (' ')); Put_Line (+" * Character'Val (65) : " & Character'Val (65)); Put_Line (+" Enum'Pos (aa) : " & Enum'Pos (aa)); Put_Line (+" Enum'Val (3) : " & Enum'Image (Enum'Val (3))); New_Line; Put_Line ("S'Image (...) attribute"); Put_Line ("-----------------------"); New_Line; Put_Line (" * Integer'Image (123) : [" & Integer'Image (123) & ']'); Put_Line (" # Real'Image (Pi) : [" & Real'Image (Pi) & ']'); Put_Line (" * Boolean'Image (True) : [" & Boolean'Image ( -- Here we test "<" on values of the internal type Strings_as_VStrings. Enum'Image (bb) < Enum'Image (cc) ) & ']' ); Put_Line (" * Character'Image ('x') : [" & Character'Image ('x') & "] (purely academic!)"); Put_Line (" * Duration'Image (123.456) : [" & Duration'Image (d) & ']'); Put_Line (" Enum'Image (bb) : [" & Enum'Image (bb) & ']'); New_Line; Put_Line ("X'Image attribute"); Put_Line ("-----------------"); New_Line; Put_Line (" i'Image : [" & i'Image & ']'); Put_Line (" r'Image : [" & r'Image & ']'); Put_Line (" b'Image : [" & b'Image & ']'); Put_Line (" c'Image : [" & c'Image & ']'); Put_Line (" d'Image : [" & d'Image & ']'); Put_Line (" e'Image : [" & e'Image & ']'); New_Line; Put_Line ("S'Value attribute, re-displayed via S'Image for Enum and,"); Put_Line (" otherwise, via ""nice"" HAT.Image and VString concatenation"); Put_Line ("------------------------------------------------------------"); New_Line; Put_Line (+" * Integer'Value (""1e3"") : [" & Integer'Value ("1e3") & ']'); Put_Line (+" # Real'Value (""1e3"") : [" & Real'Value ("1e3") & ']'); Put_Line (+" * Boolean'Value (""True"") : [" & Boolean'Value ("True") & ']'); Put_Line (+" * Character'Value (""'x'"") : [" & Character'Value ("'x'") & ']'); Put_Line (+" * Duration'Value (""543.21"") : [" & Duration'Value ("543.21") & ']'); Put_Line (+" Enum'Value (""dd"") : [" & Enum'Image (Enum'Value ("dd")) & ']'); New_Line; -- Test Strings_as_VStrings on some operators and HAT overloaded subprograms. for x in Enum loop Set_Env (Enum'Image (x), +"Set_to_" & Enum'Image (x)); end loop; -- for x in Enum'First .. Enum'Last loop -- Identical to `for x in Enum loop` Put_Line (+"Env. variable " & Enum'Image (x) & " has the value " & Get_Env (Enum'Image (x))); end loop; New_Line; for x in Enum'Range loop -- `Enum'Range` is a shortcut for `Enum'First .. Enum'Last` Put_Line (+"Env. variable " & Enum'Image (x) & " has the value " & Get_Env (Enum'Image (x))); end loop; New_Line; Put_Line ("A'First, A'Last, A'Range, A'Length attributes for array type A"); Put_Line ("--------------------------------------------------------------"); New_Line; Put_Line (" * A'First (should be BB of type Enum) : " & Enum'Image (A'First)); Put_Line (" * A'Last (should be CC of type Enum) : " & Enum'Image (A'Last)); Put_Line (+" * A'Length (should be 2) : " & A'Length); for x in A'Range loop Put_Line (+"Env. variable " & Enum'Image (x) & " has the value " & Get_Env (Enum'Image (x))); end loop; New_Line; Put_Line ("M'First (N), M'Last (N), M'Range (N), M'Length (N) attributes"); Put_Line ("--- M = Multidimensional array type, mm = object of type M."); Put_Line ("-------------------------------------------------------------"); New_Line; Put_Line (+" * M'First (1) (should be -5) : " & M'First (1)); Put_Line (+" * mm'Last (1) (should be -2) : " & mm'Last (1)); Put_Line (" * M'First (2) (should be BB) : " & Enum'Image (M'First (2))); Put_Line (" * mm'Last (2) (should be DD) : " & Enum'Image (mm'Last (2))); for i in M'Range (1) loop for j in M'Range (2) loop mm (i, j) := i * Enum'Pos (j); end loop; end loop; sum := 0; for j in M'Range (2) loop for i in M'Range (1) loop sum := sum + mm (i, j); end loop; end loop; Put_Line (+"Sum of elements in the matrix: " & sum); end Attributes; ================================================ FILE: exm/auto_complete.adb ================================================ -- Algo for auto-complete (e.g. in LEA): -- Find_Possible_Declarations in HAC_Sys.Targets.Semantics -- -- Identifier table: hac -d auto_complete.adb -- procedure Auto_Complete is a : Integer := 0; procedure Sub (b: Boolean) is c : Integer := a; begin -- Here a, c, b are visible c := c + a; end; d : Integer; begin -- Here a, d are visible d := a; end Auto_Complete; ================================================ FILE: exm/barnes.adb ================================================ -- Puzzle presented by John Barnes in the restaurant "De Abt" in Ghent, -- the 15th of June 2022, during the Ada-Europe 2022 conference -- http://www.ada-europe.org/conference2022/ -- -- The question is (from memory): -- -- "Find the integer (there is only one) with all decimal digits appearing -- once and only once, for which the number formed by the first -- two digits can be divided by two, the number formed by the -- first three digits can be divided by three, and so on." -- -- Solution by J-P Rosen, adapted to the HAC subset and added to HAC's regression suite. -- The original solution is reproduced as a comment at the bottom of this procedure. with HAT; with Interfaces; procedure Barnes is use HAT, Interfaces; subtype My_Int is Interfaces.Integer_64 range 0 .. 1e11; subtype Digit_Range is My_Int range 1 .. 10; type Digit_String is array (Digit_Range) of My_Int; subtype Coeff_Range is My_Int range 0 .. 9; Coeff : array (Coeff_Range) of My_Int; compiler_regression_test_mode : constant Boolean := Argument_Count > 0; procedure Put_Solution (S : Digit_String) is Chars : constant array (Coeff_Range) of Character := "0123456789"; Res : My_Int := 0; begin if compiler_regression_test_mode then for I in S'Range loop Res := Res * 10 + Character'Pos (Chars (S (I))) - Character'Pos ('0'); end loop; if Res /= My_Int'Value (To_String (Argument (1))) then Put_Line (" ----> Compiler test failed."); Set_Exit_Status (1); end if; else Put ("Solution = "); for I in S'Range loop Put (Chars (S (I))); end loop; New_Line; end if; end Put_Solution; function Is_Possible (S : Digit_String; Last : My_Int) return Boolean is Seen : array (Coeff_Range) of Boolean; Accu : My_Int := 0; begin for K in Seen'Range loop Seen (K) := False; end loop; for I in S'First .. Last loop if Seen (S (I)) then return False; end if; Seen (S (I)) := True; Accu := Accu + S (I) * Coeff (Last - I); end loop; return Accu mod Last = 0; end Is_Possible; subtype My_Positive_Digit is My_Int range 1 .. 9; subtype My_One_To_Four_Digit is My_Int range 1 .. 4; Candidate : Digit_String; procedure Try_Combinations is D5 : constant := 5; begin Candidate (5) := D5; -- Small optimizations: -- Last digit is 0 (dividable by 10) => not other digit is 0 -- Fifth digit is 5 (dividable by 5 and not a 0) -- Second digit is even => 2, 4, 6, 8 for D1 in My_Positive_Digit loop Candidate (1) := D1; for D2 in My_One_To_Four_Digit loop Candidate (2) := 2 * D2; if Is_Possible (Candidate, 2) then for D3 in My_Positive_Digit loop Candidate (3) := D3; if Is_Possible (Candidate, 3) then for D4 in My_Positive_Digit loop Candidate (4) := D4; if Is_Possible (Candidate, 4) then for D6 in My_Positive_Digit loop Candidate (6) := D6; if Is_Possible (Candidate, 6) then for D7 in My_Positive_Digit loop Candidate (7) := D7; if Is_Possible (Candidate, 7) then for D8 in My_Positive_Digit loop Candidate (8) := D8; if Is_Possible (Candidate, 8) then for D9 in My_Positive_Digit loop Candidate (9) := D9; if Is_Possible (Candidate, 9) then Candidate (10) := 0; Put_Solution (Candidate); return; end if; end loop; end if; end loop; end if; end loop; end if; end loop; end if; end loop; end if; end loop; end if; end loop; end loop; end Try_Combinations; begin if not compiler_regression_test_mode then Put_Line ("Find the integer (there is only one) with all decimal digits appearing"); Put_Line ("once and only once, for which the number formed by the first"); Put_Line ("two digits can be divided by two, the number formed by the"); Put_Line ("first three digits can be divided by three, and so on."); New_Line; end if; -- Coeff (0) := 1; for I in My_Positive_Digit loop Coeff (I) := Coeff (I - 1) * 10; end loop; -- Try_Combinations; end Barnes; ------------------------------------------------ -- Original "full Ada" program by J-P Rosen -- ------------------------------------------------ -- -- -- with Ada.Text_IO; -- procedure Barnes is -- use Ada.Text_Io; -- -- type My_Int is range 0 .. 10**11; -- Terminated : exception; -- D5 : constant My_Int := 5; -- type Digit_String is array (My_Int range <>) of My_Int; -- Coeff : array (My_Int range 0 .. 9) of My_Int; -- -- procedure Put (S : Digit_String) is -- Chars : constant array (My_Int range 0 .. 9) of Character := "0123456789"; -- begin -- for I in S'Range loop -- Put (Chars (S (I))); -- end loop; -- end Put; -- -- function Is_Possible (S : Digit_String) return Boolean is -- Seen : array (My_Int range 0..9) of Boolean := (others => False); -- Accu : My_Int := 0; -- begin -- for I in S'Range loop -- if Seen (S(I)) then -- return False; -- end if; -- Seen (S(I)) := True; -- Accu := Accu + S (I) * Coeff (S'Last - I); -- end loop; -- return Accu mod S'Length = 0; -- end Is_Possible; -- -- begin -- Coeff (0) := 1; -- for I in My_Int range 1 .. 9 loop -- Coeff (I) := Coeff (I - 1) * 10; -- end loop; -- -- -- Small optimizations: -- -- Last digit is 0 (dividable by 10) => not other digit is 0 -- -- Fifth digit is 5 (dividable by 5 and not 0) -- -- Second digit is even (hence not 1 or 9) -- for D1 in My_Int range 1 .. 9 loop -- for D2 in My_Int range 2 .. 8 loop -- if Is_Possible ((D1, D2)) then -- for D3 in My_Int range 1 .. 9 loop -- if Is_Possible ((D1, D2, D3)) then -- for D4 in My_Int range 1 .. 9 loop -- if Is_Possible ((D1, D2, D3, D4)) then -- for D6 in My_Int range 1 .. 9 loop -- if Is_Possible ((D1, D2, D3, D4, D5, D6)) then -- for D7 in My_Int range 1 .. 9 loop -- if Is_Possible ((D1, D2, D3, D4, D5, D6, D7)) then -- for D8 in My_Int range 1 .. 9 loop -- if Is_Possible ((D1, D2, D3, D4, D5, D6, D7, D8)) then -- for D9 in My_Int range 1 .. 9 loop -- if Is_Possible ((D1, D2, D3, D4, D5, D6, D7, D8, D9)) then -- Put ("Solution = "); -- Put (Digit_String'(D1, D2, D3, D4, D5, D6, D7, D8, D9, 0)); -- New_Line; -- raise Terminated; -- end if; -- end loop; -- end if; -- end loop; -- end if; -- end loop; -- end if; -- end loop; -- end if; -- end loop; -- end if; -- end loop; -- end if; -- end loop; -- end loop; -- exception -- when Terminated => -- null; -- end Barnes; ================================================ FILE: exm/binomials.adb ================================================ with HAT; procedure Binomials is function Factorial (n : Natural) return Positive is begin if n = 0 then return 1; else return n * Factorial (n - 1); end if; end Factorial; -- Returns the binomial coefficient /n\ -- \k/ function Binomial (n, k : Natural) return Positive is begin return Factorial (n) / (Factorial (k) * Factorial (n - k)); end Binomial; use HAT; begin for n in 1 .. 10 loop Put ("n = "); Put_Line (n, 0); Put_Line ("k= binomial (n,k)="); for k in 1 .. n - 1 loop Put (k, 0); Put (": "); Put_Line (Binomial (n, k), 0); end loop; New_Line; end loop; end Binomials; ================================================ FILE: exm/bwt.adb ================================================ -- Burrows-Wheeler Transform: block-sorting -- preprocessing for improving data compression. -- This technique is used in the BZip2 format. -- -- https://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform -- -- HAC example derived from extras/bwt* files in Zip-Ada project. -- with HAT; procedure BWT is use HAT; n : constant := 52; default : constant VString := +"Mary had a little lamb, its fleece was white as snow"; subtype Row is String (1 .. n); type Table is array (1 .. n) of Row; procedure Shell_Sort (b : in out Table) is i, j, step : Integer; step_size : array (1 .. 4) of Integer; stop : Boolean; temp : Row; begin -- 'steps' contains decreasing increments for each -- pass. The last pass has increment 1. step_size (4) := 1; for pass in reverse 1 .. 3 loop step_size (pass) := 2 * step_size (pass + 1); end loop; Passes : for pass in 1 .. 4 loop step := step_size (pass); -- Do a straight insertion sort with 'step' as -- an increment instead of 1. i := step + 1; while i <= n loop temp := b (i); j := i; stop := False; while j > step and not stop loop j := j - step; if b (j) > temp then b (j + step) := b (j); else b (j + step) := temp; stop := True; end if; end loop; if not stop then b (1) := temp; end if; i := i + step; end loop; end loop Passes; end Shell_Sort; procedure Show (m : Table; message : VString; original : Natural) is begin Put_Line ("---- BWT Table: " & message & " ----"); for i in 1 .. n loop if i = original then Put ("--original-->"); else Put (" "); end if; Put (i, 4); Put (' '); for j in 1 .. n loop Put (m (i)(j)); end loop; New_Line; end loop; end Show; s, t, u : Row; m : Table; row_index : Positive; line : VString; begin -- Put_Line (+"Enter " & n & " characters (until and including '*' position"); -- Put_Line ((n - 1) * '.' & '*'); -- Get_Line (line); line := default; -- for i in 1 .. n loop s (i) := Element (line, i); end loop; New_Line; -- Fill the matrix for i in 1 .. n loop for j in 1 .. n loop m (i)(j) := Element (line, (1 + (j - 1 + i - 1) mod n)); end loop; end loop; -- Show (m, +"unsorted ( (i-1) rotations for row i )", 1); ----------------- -- Transform -- ----------------- Shell_Sort (m); for i in 1 .. n loop t (i) := m (i)(n); if m (i) = s then row_index := i; -- Found row with the message with 0 rotation. end if; end loop; Show (m, +"sorted", row_index); -- Put_Line ("BWT output (last column of matrix):"); Put_Line (n * '-'); Put_Line ("t = " & t); Put_Line (n * '-'); Put_Line (+"Index of row containing the original message is: " & row_index); -------------------- -- De-transform -- -------------------- for i in 1 .. n loop for j in 1 .. n loop m (i)(j) := ' '; end loop; end loop; Shift_Insert_Sort : for iter in 1 .. n loop -- Shift columns right for i in 1 .. n loop for j in reverse 2 .. n loop m (i)(j) := m (i)(j - 1); end loop; end loop; -- Insert transformed string t as first column (again and again). -- -- The miracle: after iteration #1, t(i) is the correct predecessor -- of the character on sorted partial row i (1 character). -- This gives the full list of pairs. -- -- After 2nd sorting (end of iteration #2), t(i) is also the correct -- predecessor each sorted pair. -- We have then the list of all triplets. And so on. -- for i in 1 .. n loop m (i)(1) := t (i); end loop; Show (m, +"insert #" & iter, 0); Shell_Sort (m); Show (m, +"sort #" & iter, 0); end loop Shift_Insert_Sort; -- After iteration n we have a sorted list of all rotated -- versions of the original string. The table is identical -- to the table after encoding. -- The original string is at row 'row_index'. u := m (row_index); -- -- Output of table. -- Show (m, +"reconstructed", row_index); -- Put_Line ("BWT output de-transformed."); -- Put_Line (n * '-'); Put_Line (u); end BWT; ================================================ FILE: exm/ce_b_2.adb ================================================ -- Run-time Constraint_Error following a subtype Range Check procedure CE_b_2 is subtype Yes_Men is Boolean range True .. True; i : Yes_Men; j : Boolean := False; begin i := j; end CE_b_2; ================================================ FILE: exm/ce_b_4.adb ================================================ -- Run-time Constraint_Error following a array Range Check procedure CE_b_4 is subtype Yes_Men is Boolean range True .. True; key : array (Yes_Men) of Boolean; i : Boolean := False; begin key (i) := True; end CE_b_4; ================================================ FILE: exm/ce_c_2.adb ================================================ -- Run-time Constraint_Error following a subtype Range Check procedure CE_c_2 is subtype Alpha is Character range 'A' .. 'Z'; i : Alpha; j : Character := 'a'; begin i := j; end CE_c_2; ================================================ FILE: exm/ce_c_4.adb ================================================ -- Run-time Constraint_Error following a array Range Check procedure CE_c_4 is subtype Alpha is Character range 'A' .. 'Z'; key : array (Alpha) of Boolean; i : Character := 'a'; begin key (i) := True; end CE_c_4; ================================================ FILE: exm/ce_e_1.adb ================================================ -- Compile-time Constraint_Error following a subtype Range Check procedure CE_e_1 is type Compression_Method is (Store, -- Deflate_Fixed, Deflate_0, Deflate_1, Deflate_2, Deflate_3, Deflate_R, -- LZMA_0, LZMA_1, LZMA_2, LZMA_3); subtype Deflation_Method is Compression_Method range Deflate_Fixed .. Deflate_R; subtype Correct is Deflation_Method range Deflate_1 .. Deflate_3; subtype Wrong is Deflation_Method range LZMA_0 .. LZMA_3; begin null; end CE_e_2; ================================================ FILE: exm/ce_e_2.adb ================================================ -- Run-time Constraint_Error following a subtype Range Check procedure CE_e_2 is type Compression_Method is (Store, Shrink, Reduce_1, Reduce_2, Reduce_3, Reduce_4, -- Deflate_Fixed, Deflate_0, Deflate_1, Deflate_2, Deflate_3, Deflate_R, -- LZMA_0, LZMA_1, LZMA_2, LZMA_3); subtype Reduction_Method is Compression_Method range Reduce_1 .. Reduce_4; subtype Deflation_Method is Compression_Method range Deflate_Fixed .. Deflate_R; i : Deflation_Method; j : Compression_Method := Reduce_3; k : Reduction_Method; begin i := j; end CE_e_2; ================================================ FILE: exm/ce_e_4.adb ================================================ -- Run-time Constraint_Error following a array Range Check procedure CE_e_4 is type Compression_Method is (Store, Shrink, Reduce_1, Reduce_2, Reduce_3, Reduce_4, -- Deflate_Fixed, Deflate_0, Deflate_1, Deflate_2, Deflate_3, Deflate_R, -- LZMA_0, LZMA_1, LZMA_2, LZMA_3); subtype Reduction_Method is Compression_Method range Reduce_1 .. Reduce_4; subtype Deflation_Method is Compression_Method range Deflate_Fixed .. Deflate_R; key : array (Deflation_Method) of Boolean; i : Deflation_Method; j : Compression_Method := Reduce_3; k : Reduction_Method; begin key (j) := True; end CE_e_4; ================================================ FILE: exm/ce_i_1.adb ================================================ -- Compile-time Constraint_Error following a subtype Range Check procedure CE_i_1 is i : Positive; begin i := -1; end CE_i_1; ================================================ FILE: exm/ce_i_2.adb ================================================ -- Run-time Constraint_Error following a subtype Range Check procedure CE_i_2 is subtype Zero_to_Nine is Integer range 0 .. 9; subtype Negative_Temp is Integer range -273 .. -1; i : Positive; j : Integer := 1; begin i := -j; end CE_i_2; ================================================ FILE: exm/ce_i_3.adb ================================================ -- Compile-time Constraint_Error following an array Range Check procedure CE_i_3 is a : array (1 .. 5) of Integer; begin a (7) := 2; end CE_i_3; ================================================ FILE: exm/ce_i_4.adb ================================================ -- Run-time Constraint_Error following a array Range Check procedure CE_i_4 is subtype Zero_to_Nine is Integer range 0 .. 9; key : array (Zero_to_Nine) of Boolean; i : Integer := -3; begin key (i) := True; end CE_i_4; ================================================ FILE: exm/console_io.adb ================================================ -- Demo of Get / Get_Immediate / Get_Line / Skip_Line / Put / Put_Line / New_Line -- on the console. -- No file involved, unless using: "hac console_io.adb out_file.txt" with HAT; use HAT; procedure Console_IO is procedure Test_Get is C1, C2 : Character; I1, I2 : Integer; R1, R2 : Real; V : VString; begin if Get_Needs_Skip_Line then -- Console mode (via the "hac" command, or when compiled with a "full Ada" compiler). Put ("Type 2 characters, then Return."); else -- GUI mode, like from the LEA editor. Put_Line ("Type 2 characters - one each time!"); end if; Get (C1); Get (C2); if Get_Needs_Skip_Line then Skip_Line; end if; Put_Line (+"You have typed [" & C1 & "] [" & C2 & "]"); -- if Get_Needs_Skip_Line then Put_Line ("Type 2 characters. This time there is no need for pressing Return."); Get_Immediate (C1); Put (+"[" & C1 & ']'); Get_Immediate (C2); Put (+"[" & C2 & ']'); New_Line; Put_Line (+"You have typed [" & C1 & "] [" & C2 & "]"); end if; -- if Get_Needs_Skip_Line then Put ("Type 2 integers (with a space inbetween), then Return."); else Put_Line ("Type 2 integers."); end if; Get (I1); Get (I2); if Get_Needs_Skip_Line then Skip_Line; end if; Put_Line (+"You have typed the numbers [" & I1 & "] [" & Image (I2) & "]"); -- if Get_Needs_Skip_Line then Put ("Type 2 floats, then Return."); else Put_Line ("Type 2 floats."); end if; Get (R1); Get (R2); if Get_Needs_Skip_Line then Skip_Line; end if; Put_Line (+"You have typed the numbers [" & R1 & "] [" & Image (R2) & "]"); -- Put ("Type whatever you want, then Return."); Get_Line (V); Put_Line ("Congrats, you just typed: [" & V & ']'); end Test_Get; begin Put_Line ("Do we have a real console/terminal ? "); if Get_Needs_Skip_Line then Put_Line ("Yes! Ada.Text_IO can get multiple inputs from the same line."); Put_Line ("Skip_Line (a ""Return"" keypress) is needed after one or more Get"); else Put_Line ("No! Perhaps this program is run from LEA ?..."); end if; Put ("Please Press Return!"); Skip_Line; Put_Line ("Bravo, you did it!"); New_Line; -- Test_Get; end Console_IO; ================================================ FILE: exm/covid_19_s.adb ================================================ -- *** This HAC demo is a version of the COVID_19 -- *** program in MathPaqs. The program is scaled down for -- *** meeting HAC v.0.074 syntax subset. -- *** We mark the downscaling with "!" in comments. -- *** -- *** For the original verion in full Ada, see "covid_19.adb" @ -- *** https://mathpaqs.sourceforge.io/ or -- *** https://github.com/zertovitch/mathpaqs . ---------------------------------------------------------------------------- -- "SEIR" model for simulating the outbreak of the Coronavirus -- disease (COVID-19). -- This program solves a vectorial ordinary differential equation -- (or a system of ordinary differential equations). -- -- * The unknown is a vector containing the values S, E, I, R. -- The letters stands for: -- S: Susceptible -- E: Exposed -- I: Infectious -- R: Recovered -- * There is a propagation of population in the -- direction S ---> E ---> I ---> R, plus new -- infections: ^------<--- -- -- Related publication: -- Nowcasting and forecasting the potential domestic and -- international spread of the 2019-nCoV outbreak originating -- in Wuhan, China: a modelling study -- -- https://www.thelancet.com/journals/lancet/article/PIIS0140-6736(20)30260-9/fulltext -- -- Simplification here: -- - no flights: L_{W,I}, L_{W,C}, ... = 0 -- - zoonotic force = 0. with HAT; procedure COVID_19_S is use HAT; type Status is (Susceptible, Exposed, Infectious, Recovered); type Status_Vector is array (Status) of Real; -- ! Full Ada: programmable operators (*, +, ...). -- ! function "*" (l : Real; v : Status_Vector) return Status_Vector is -- ! r : Status_Vector; -- ! begin -- ! for i in v'Range loop r(i) := v(i) * l; end loop; -- ! return r; -- ! end "*"; -- ! function "+" (a, b : Status_Vector) return Status_Vector is -- ! r : Status_Vector; -- ! begin -- ! for i in a'Range loop r(i) := a(i) + b(i); end loop; -- ! return r; -- ! end "+"; procedure Times (l : Real; v : Status_Vector; r : out Status_Vector) is begin for i in Status loop r (i) := v (i) * l; end loop; end Times; procedure Plus (a, b : Status_Vector; r : out Status_Vector) is begin for i in Status loop r (i) := a (i) + b (i); end loop; end Plus; inv_incubation_period : constant Real := 1.0 / 5.2; inv_infective_period : constant Real := 1.0 / 2.9; -- We solve numerically x' (t) = f (x (t), t) over the time step h. -- procedure Evolution (xt : in out Status_Vector; reproductive_number : Real; h : Real) is -- -- ! function f (x : Status_Vector) return Status_Vector is -- ! Full Ada: functions with non-atomic results. procedure f (x : Status_Vector; res_f : out Status_Vector) is n, inv_n, s_to_e, e_to_i, nb_infected_over_period, susc_rate : Real; -- begin -- Count the population at time t. n := 0.0; for s in Status loop n := n + x (s); end loop; inv_n := 1.0 / n; nb_infected_over_period := x (Infectious) * inv_infective_period; -- Some Susceptible persons get the virus -- from Infectious people and become Exposed. susc_rate := x (Susceptible) * inv_n; -- As proportion of the population. s_to_e := susc_rate * reproductive_number * nb_infected_over_period; -- Exposed persons become Infectious after incubation. e_to_i := x (Exposed) * inv_incubation_period; -- Infectious people recover after infective period. -> Recovered. -- This rate is already computed: nb_infected_over_period; res_f (Susceptible) := -s_to_e; res_f (Exposed) := s_to_e - e_to_i; res_f (Infectious) := e_to_i - nb_infected_over_period; res_f (Recovered) := nb_infected_over_period; end f; k1, k2, k3, k4, tmp_a, tmp_b, dbk2, dbk3 : Status_Vector; begin -- -- ! Full Ada: sooooo much simpler with operators! -- -- ! k1 := f (x ); -- ! k2 := f (x + h * 0.5 * k1); -- ! k3 := f (x + h * 0.5 * k2); -- ! k4 := f (x + h * k3); -- ! x := x + h * (1.0/6.0) * (k1 + 2.0 * k2 + 2.0 * k3 + k4); -- f (xt, k1); -- Times (h * 0.5, k1, tmp_a); Plus (xt, tmp_a, tmp_b); -- tmp_b = xt + h * 0.5 * k1 f (tmp_b, k2); -- Times (h * 0.5, k2, tmp_a); Plus (xt, tmp_a, tmp_b); -- tmp_b = xt + h * 0.5 * k2 f (tmp_b, k3); -- Times (h, k3, tmp_a); Plus (xt, tmp_a, tmp_b); -- tmp_b = xt + h * k3 f (tmp_b, k4); -- Times (2.0, k2, dbk2); Times (2.0, k3, dbk3); Plus (k1, dbk2, tmp_a); Plus (tmp_a, dbk3, tmp_b); Plus (tmp_b, k4, tmp_a); -- tmp_a = (k1 + 2.0 * k2 + 2.0 * k3 + k4) Times (h * (1.0 / 6.0), tmp_a, tmp_b); Plus (xt, tmp_b, tmp_a); xt := tmp_a; end Evolution; type Scenario is (No_Lockdown, Lockdown, Lockdown_in_two_Steps); procedure Simulation (s : Scenario) is -- ! use Ada.Text_IO, Ada.Integer_Text_IO, PFIO; x : Status_Vector; dt : Real; reproductive_number : Real; n_iter : Integer; out_step : Integer; rf : File_Type; sep : constant Character := ';'; -- ! use Ada.Characters.Handling; basic_reproductive_number : constant := 3.5; begin dt := 1.0; n_iter := 365; out_step := 1; -- ! x := -- ! ( Susceptible => 1_000_000.0, -- ! Exposed => 0.0, -- ! Infectious => 1.0, -- Patient 1. -- ! Recovered => 0.0 -- ! ); x (Susceptible) := 1_000_000.0; x (Exposed) := 0.0; x (Infectious) := 1.0; -- Patient 1. x (Recovered) := 0.0; -- Status numbers at time t = 0. Create (rf, "covid_19_s_" & To_Lower (+Scenario'Image (s)) & ".csv"); Put (rf, "t"); for l in Status loop Put (rf, sep); Put (rf, Status'Image (l)); end loop; New_Line (rf); for i in 0 .. n_iter loop if i mod out_step = 0 then Put (rf, i); for l in Status loop Put (rf, sep); Put (rf, x (l), 4, 5, 0); end loop; New_Line (rf); end if; case s is when No_Lockdown => reproductive_number := basic_reproductive_number; when Lockdown => if i < 40 then reproductive_number := basic_reproductive_number; else reproductive_number := 1.0; end if; when Lockdown_in_two_Steps => if i < 40 then reproductive_number := basic_reproductive_number; elsif i < 60 then reproductive_number := 2.0; else reproductive_number := 1.0; end if; end case; Evolution (x, reproductive_number, dt); end loop; Close (rf); end Simulation; begin Put_Line ("COVID_19_S Simulation"); Put_Line (" - SEIR prediction model. "); Put_Line ("Output in : covid*.csv"); for s in Scenario loop Simulation (s); end loop; Put_Line ("Done"); end COVID_19_S; ================================================ FILE: exm/cross_a.adb ================================================ -- Example of cross-dependency in bodies with Cross_B; with HAT; package body Cross_A is procedure A (n : Natural) is use HAT; begin if n > 0 then Put_Line ("A: " & Image (n)); Cross_B.B (n - 1); end if; end A; end Cross_A; ================================================ FILE: exm/cross_a.ads ================================================ -- Example of cross-dependency in bodies package Cross_A is procedure A (n : Natural); end Cross_A; ================================================ FILE: exm/cross_b.adb ================================================ -- Example of cross-dependency in bodies with Cross_A; with HAT; package body Cross_B is procedure B (n : Natural) is use HAT; begin if n > 0 then Put_Line ("B: " & Image (n)); Cross_A.A (n - 1); end if; end B; end Cross_B; ================================================ FILE: exm/cross_b.ads ================================================ -- Example of cross-dependency in bodies package Cross_B is procedure B (n : Natural); end Cross_B; ================================================ FILE: exm/days_1901.adb ================================================ -- Prototype developed using HAC [1] and LEA [2], for portable date output of Excel Writer [3]. -- -- [1]: http://hacadacompiler.sf.net/ -- [2]: http://l-e-a.sf.net/ -- [3]: http://excel-writer.sf.net/ with HAT; use HAT; procedure Days_1901 is -- 1901 is the lowest year supported by Ada.Calendar. -- 1900 is not a leap year, but Lotus 1-2-3 then Excel consider it as a leap year. -- So, with 1901, we skip that issue anyway... -- function Days_since_1901 (y, m, d : Integer) return Integer is function Is_leap (y : Integer) return Boolean is begin if y mod 4 = 0 then if y mod 100 = 0 then if y mod 400 = 0 then return True; else return False; end if; else return True; end if; else return False; end if; end Is_leap; days_of_previous_months : Integer; days_of_previous_years : Integer; y_diff, y_diff_4, y_diff_100, y_diff_400 : Integer; begin case m is when 02 => days_of_previous_months := 31; when 03 => days_of_previous_months := 59; when 04 => days_of_previous_months := 90; when 05 => days_of_previous_months := 120; when 06 => days_of_previous_months := 151; when 07 => days_of_previous_months := 181; when 08 => days_of_previous_months := 212; when 09 => days_of_previous_months := 243; when 10 => days_of_previous_months := 273; when 11 => days_of_previous_months := 304; when 12 => days_of_previous_months := 334; when others => days_of_previous_months := 0; end case; if (m > 2) and Is_leap (y) then -- February has 29 days in leap years. days_of_previous_months := days_of_previous_months + 1; end if; -- y_diff := (y - 1) - 1900; y_diff_4 := (y - 1) / 4 - 1900 / 4; y_diff_100 := (y - 1) / 100 - 1900 / 100; y_diff_400 := (y - 1) / 400 - 1900 / 400; -- Add leap years from 1901 (included) to now (excluded). days_of_previous_years := 365 * y_diff + y_diff_4 - y_diff_100 + y_diff_400; -- return days_of_previous_years + days_of_previous_months + d - 1; end Days_since_1901; -- begin for y in 1901 .. 2200 loop Put ("Days from 1/1/1901 to : ... 12/31/"); Put (y); Put_Line (Days_since_1901 (y, 12, 31)); end loop; end Days_1901; ================================================ FILE: exm/directories.adb ================================================ -- This demo creates a few directories and then deletes them. with HAT; procedure Directories is use HAT; begin Create_Directory ("dir_a"); Create_Path ("dir_b/dir_c/dir_d"); Put ("Check your current directory and spot ""dir_a"", ""dir_b""."); Skip_Line; Delete_Directory ("dir_a"); Put_Line ("""dir_a"" has been deleted."); Delete_Directory ("dir_b/dir_c/dir_d"); Put_Line ("""dir_b/dir_c/dir_d"" has been deleted."); Delete_Directory ("dir_b/dir_c"); Put_Line ("""dir_b/dir_c"" has been deleted."); Delete_Directory ("dir_b"); Put_Line ("""dir_b"" has been deleted."); end Directories; ================================================ FILE: exm/doors.adb ================================================ -- Special version (for HAC) of https://rosettacode.org/wiki/100_doors#Ada -- "There are 100 doors in a row that are all initially closed. -- You make 100 passes by the doors. -- The first time through, visit every door and toggle the door (if the -- door is closed, open it; if it is open, close it). -- The second time, only visit every 2nd door (door #2, #4, #6, ...), -- and toggle it. -- The third time, visit every 3rd door (door #3, #6, #9, ...), etc, -- until you only visit the 100th door. -- -- Rosetta Task: Answer the questions: -- What state are the doors in after the last pass? -- Which are open, which are closed? -- -- Alternate: As noted in https://rosettacode.org/wiki/Talk:100_doors -- the only doors that remain open are those whose numbers are perfect squares." with HAT; procedure Doors is type Door_State is (Closed, Open); last_door : constant := 100; subtype Door_Range is Integer range 1 .. last_door; type Door_List is array (Door_Range) of Door_State; the_doors : Door_List; -- := (others => Closed); begin for i in Door_Range loop the_doors (i) := Closed; end loop; for i in Door_Range loop for j in Door_Range loop if j mod i = 0 then if the_doors (j) = Closed then the_doors (j) := Open; else the_doors (j) := Closed; end if; end if; end loop; end loop; for i in Door_Range loop HAT.Put_Line ("Door" & i'Image & " is " & the_doors (i)'Image); end loop; end Doors; ================================================ FILE: exm/draw_sphere.adb ================================================ -- https://rosettacode.org/wiki/Draw_a_sphere -- This version is inspired from the ASCII Art C program with -- some improvements and explanations. with HAT; procedure Draw_Sphere is use HAT; type Point is record x, y, z : Real; end record; shades : constant String (1 .. 14) := "@%&$#XMIeo!*:."; procedure Normalize (x, y, z : Real; pt : out Point) is len : constant Real := Sqrt (x * x + y * y + z * z); begin pt.x := x / len; pt.y := y / len; pt.z := z / len; end Normalize; function dot_product (a, b : Point) return Real is begin return a.x * b.x + a.y * b.y + a.z * b.z; end dot_product; light : Point; procedure Draw_Sphere (r, k : Integer; ambient : Real) is clarity, x, y, z2 : Real; surface_point : Point; shade_index : Integer; begin Normalize (30.0, 30.0, -50.0, light); for i in -r .. r loop x := Real (i) + 0.5; for j in (-2) * r .. 2 * r loop y := Real (j) / 2.0 + 0.5; z2 := Real (r * r) - x * x - y * y; if z2 >= 0.0 then Normalize (x, y, Sqrt (z2), surface_point); clarity := Max (0.0, -dot_product (light, surface_point)) ** k + ambient; shade_index := shades'First + Integer (clarity * Real (shades'Length)); -- Clamp: shade_index := Min (shades'Last, Max (shades'First, shade_index)); Put (shades (shade_index)); else Put (' '); end if; end loop; New_Line; end loop; end Draw_Sphere; begin Draw_Sphere (25, 4, 0.02); Draw_Sphere (16, 2, 0.02); Draw_Sphere (9, 2, 0.05); Draw_Sphere (4, 3, 0.10); end Draw_Sphere; ================================================ FILE: exm/e.cmd ================================================ @echo off echo (Re-)building HAC cd.. gprbuild -P hac.gpr hac cd exm set hacbuild=done if "%1"=="" goto gallery rem Try without extension if exist %1.adb ..\hac -v2 %1.adb %2 %3 %4 %5 %6 %7 %8 %9 if exist %1.adb goto fin rem Try with extension ..\hac -v2 %1 %2 %3 %4 %5 %6 %7 %8 %9 goto fin :gallery ..\hac gallery.adb :fin ================================================ FILE: exm/echo.adb ================================================ -- Example from command-line: hac echo.adb echo.txt with HAT; use HAT; procedure Echo is s : VString; begin Put_Line ("Type your messages (""STOP!"" or Ctrl-Z to stop):"); while not End_Of_File loop Get_Line (s); -- Exit door if program run from a console without Ctrl-Z : exit when s = "STOP!"; Put_Line ("This is the echo... [" & s & ']'); end loop; end Echo; ================================================ FILE: exm/einmaleins.adb ================================================ -- Example of use, just written "live" using the -- LEA editor, during a homeschooling session. with HAT; use HAT; procedure Einmaleins is x, y : Integer; begin x := 2 + Rand (7); -- Random, 2 to 9 y := 2 + Rand (7); -- Random, 2 to 9 -- if Rnd < 0.5 then x := x * 10; else y := y * 10; end if; -- Put (x, 0); Put (" * "); Put (y, 0); Put (" = "); Put (x * y, 0); end Einmaleins; ================================================ FILE: exm/embed_text.adb ================================================ -- This tool reads a text file and writes -- an Ada package with its contents. -- -- https://www.reddit.com/r/ada/comments/1l3i9wl/embedding_a_text_file_in_an_ada_exe/ with HAT; procedure Embed_Text is use HAT; s, pkg : VString; f1, f2 : File_Type; lines : Natural := 0; c : Character; type Output_Mode is (hac, full_ada); output : Output_Mode := hac; begin if Argument_Count < 2 then Put_Line ("Embed_Text reads a text file and writes an Ada package with its contents."); Put_Line ("Usage - "); Put_Line ("from HAC: hac embed_text.adb TEXT_FILE Ada_Package_Name [-h] [-f]"); Put_Line ("built as executable: embed_text TEXT_FILE Ada_Package_Name [-h] [-f]"); New_Line; Put_Line ("Produces: ada_package_name.ads, ada_package_name.adb, demo_ada_package_name.adb"); New_Line; Put_Line ("Options: -h : produce sources for HAC, with HAT package (default)"); Put_Line (" -f : produce sources for ""full Ada"", with Ada.* packages"); return; end if; Open (f1, Argument (1)); pkg := Argument (2); for i in 3 .. Argument_Count loop if Argument (i) = "-h" then output := hac; elsif Argument (i) = "-f" then output := full_ada; end if; end loop; Create (f2, To_Lower (pkg) & ".adb"); Put_Line (f2, "package body " & pkg & " is"); Put_Line (f2, " procedure Fill_Contents (text : out Embedded_Text) is"); case output is when hac => Put_Line (f2, " use HAT;"); when full_ada => Put_Line (f2, " use Ada.Strings.Unbounded;"); Put_Line (f2, " function ""+"" (S : String) return Unbounded_String renames To_Unbounded_String;"); end case; Put_Line (f2, " begin"); while not End_Of_File (f1) loop lines := lines + 1; Get_Line (f1, s); Put (f2, +" text (" & lines & ") := +"""); for i in 1 .. Length (s) loop c := Element (s, i); if c = '"' then Put (f2, """"""); else Put (f2, c); end if; end loop; Put_Line (f2, """;"); end loop; Close (f1); Put_Line (f2, " end Fill_Contents;"); Put_Line (f2, "end " & pkg & ";"); Close (f2); Create (f2, To_Lower (pkg) & ".ads"); case output is when hac => Put_Line (f2, "with HAT;"); when full_ada => Put_Line (f2, "with Ada.Strings.Unbounded;"); end case; Put_Line (f2, "package " & pkg & " is"); Put (f2, +" type Embedded_Text is array (1 .. " & lines & ") of "); case output is when hac => Put_Line (f2, "HAT.VString;"); when full_ada => Put_Line (f2, "Ada.Strings.Unbounded.Unbounded_String;"); end case; Put_Line (f2, " procedure Fill_Contents (text : out Embedded_Text);"); Put_Line (f2, "end " & pkg & ";"); Close (f2); Create (f2, "demo_" & To_Lower (pkg) & ".adb"); case output is when hac => Put_Line (f2, "with HAT;"); when full_ada => Put_Line (f2, "with Ada.Strings.Unbounded, Ada.Text_IO;"); end case; Put_Line (f2, "with " & pkg & ';'); Put_Line (f2, "procedure Demo_" & pkg & " is"); Put_Line (f2, " e : " & pkg & ".Embedded_Text;"); Put_Line (f2, "begin"); Put_Line (f2, " " & pkg & ".Fill_Contents (e);"); Put_Line (f2, " for l in e'Range loop"); case output is when hac => Put_Line (f2, " HAT.Put_Line (e (l));"); when full_ada => Put_Line (f2, " Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (e (l)));"); end case; Put_Line (f2, " end loop;"); Put_Line (f2, "end Demo_" & pkg & ';'); Close (f2); end Embed_Text; ================================================ FILE: exm/env.adb ================================================ -- System's Environment Variables: Set & Get. with HAT; procedure Env is use HAT; path, path_v : VString; begin path := Get_Env ("PATH"); -- String argument path_v := Get_Env (+"PATH"); -- VString argument -- Put_Line ("The PATH (to happiness) is : " & path); if path /= path_v then Put_Line ("Uh ?"); end if; Set_Env ("HAC_Rules", "Good Day, Ladies and Gentlemen!"); New_Line; Put_Line ( "Important message from the environment variables: " & Get_Env ("HAC_Rules") ); end Env; ================================================ FILE: exm/existence.adb ================================================ with HAT; use HAT; procedure Existence is procedure Check (Name : VString) is procedure Tell (Existing : Boolean; As : VString) is begin Put (Name); if Existing then Put (" exists "); else Put (" does not exist "); end if; Put_Line (+"as " & As); end Tell; begin Tell (Exists (Name), +"anything in the file system"); Tell (Directory_Exists (Name), +"a directory"); Tell (File_Exists (Name), +"a file"); end Check; begin Check (+"existence.adb"); Check (+"aoc"); end Existence; ================================================ FILE: exm/file_append.adb ================================================ -- This demo creates a file in multiple steps, via the Append procedure. with HAT; procedure File_Append is use HAT; f : File_Type; n : constant VString := To_VString ("file_append.txt"); begin Create (f, n); Put_Line (f, "0"); Close (f); -- for i in 1 .. 9 loop Append (f, n); Put_Line (f, i, 0); Close (f); end loop; end File_Append; ================================================ FILE: exm/file_copy.adb ================================================ -- This demo reads a text file (itself) and writes -- its contents in another text file. -- -- NB: for copying a file (of any kind) with a single command, -- you can use Copy_File. See binary copy at the end of this demo. with HAT; procedure File_Copy is use HAT; s : VString; f1, f2 : File_Type; begin Put_Line ("Line-by-line text copy"); Open (f1, "file_copy.adb"); Create (f2, "file_copy.txt"); while not End_Of_File (f1) loop Get_Line (f1, s); Put_Line (f2, s); end loop; Close (f1); Close (f2); -- Put_Line ("Binary copy"); -- It's an opportunity to test some Ada.Directories-like subprograms. -- Copy_File ("file_copy.adb", "file_copy_bin_$$.txt"); if Exists ("file_copy_bin.txt") then Delete_File ("file_copy_bin.txt"); end if; Rename ("file_copy_bin_$$.txt", "file_copy_bin.txt"); end File_Copy; ================================================ FILE: exm/file_read.adb ================================================ -- This demo reads a text file (itself) and displays -- its contents on the console. with HAT; procedure File_Read is use HAT; s : VString; f : File_Type; begin Open (f, "file_read.adb"); while not End_Of_File (f) loop Get_Line (f, s); Put_Line (s); end loop; Close (f); end File_Read; ================================================ FILE: exm/fill_drive.adb ================================================ -- This script is useful for clearing the unused space of a drive. -- Typically, you have deleted sensitive data files, but you would like to -- prevent recovery of those file contents, but you would still like to -- keep other files (so, you avoid a new formatting or wipeout of the drive). with HAT; use HAT; procedure Fill_Drive is f : File_Type; begin Create (f, "garbage_delete_me.txt"); loop Put_Line (f, "Bla bla bla bla bla bla and more bla bla bla bla bla!"); -- TBD: randomized version. end loop; end Fill_Drive; ================================================ FILE: exm/gallery.adb ================================================ -- We launch new instances of HAC (possibly from HAC itself, too). -- Usage: hac gallery.adb with HAT; use HAT; procedure Gallery is procedure Launch_Demos is procedure Shell (command : VString; echo : Boolean) is begin if echo then Put_Line ("Executing: [" & command & ']'); end if; Shell_Execute (command); end Shell; procedure Launch_HAC (Ada_file_name : VString) is dummy : Character; begin Shell ( +".." & Directory_Separator & "hac -v2 " & Ada_file_name, False ); Put ("--- Press any key to continue in the HAC gallery..."); Get_Immediate (dummy); New_Line; end Launch_HAC; procedure Build_HAC is begin if Get_Env ("hacbuild") = "done" then return; end if; Put_Line ("(Re-)building HAC, in case the present program isn't run from HAC..."); Shell (+"gprbuild -p -P .." & Directory_Separator & "hac", True); end Build_HAC; begin Build_HAC; -- Redundant if this program is itself run through HAC. -- Launch_HAC (+"hello.adb"); Launch_HAC (+"attributes.adb"); Launch_HAC (+"maze_gen.adb"); Launch_HAC (+"strings_demo.adb"); Launch_HAC (+"env.adb"); Launch_HAC (+"arguments.adb arg1 arg2 ""arg 3 ..."" arg4"); Launch_HAC (+"ackermann.adb"); Launch_HAC (+"anti_primes.adb"); Launch_HAC (+"doors.adb"); Launch_HAC (+"hofstadter.adb"); Launch_HAC (+"mandelbrot.adb"); Launch_HAC (+"shell_sort.adb"); Launch_HAC (+"merge_sort.adb"); Launch_HAC (+"days_1901.adb"); Launch_HAC (+"shell.adb"); Launch_HAC (+"file_read.adb"); Launch_HAC (+"existence.adb"); Launch_HAC (+"timing.adb"); Launch_HAC (+"bwt.adb"); Launch_HAC (+"unit_a.adb"); -- The following demos write files. Launch_HAC (+"file_copy.adb"); Launch_HAC (+"three_lakes_s.adb"); Launch_HAC (+"covid_19_s.adb"); end Launch_Demos; begin Launch_Demos; end Gallery; ================================================ FILE: exm/hac_exm.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the examples of the HAC project ( https://sf.net/projects/hacadacompiler/ ). -- -- These examples give (or should give...) the same output on a real -- Ada compiler as when compiled and run by HAC. -- -- Build me with "gprbuild -P hac_exm", or open me with GNAT Studio. -- project HAC_Exm is type HAC_Build_Mode_Type is ("Debug", "Fast"); HAC_Build_Mode : HAC_Build_Mode_Type := external ("HAC_Build_Mode", "Debug"); for Main use -- -- 1) HAC and GNAT OK (correct Ada, same output) -- ("ackermann.adb", "arguments.adb", "anti_primes.adb", "attributes.adb", "barnes.adb", -- John Barnes' Ada-Europe 2022 puzzle "binomials.adb", "bwt.adb", "console_io.adb", "covid_19_s.adb", "days_1901.adb", "doors.adb", -- Rosetta Code "draw_sphere.adb", -- Rosetta Code "echo.adb", "einmaleins.adb", "embed_text.adb", "env.adb", "existence.adb", "file_append.adb", "file_copy.adb", "file_read.adb", "fill_drive.adb", "hello.adb", "hello_big.adb", "gallery.adb", "hilbert_curve.adb", -- PDF demo, Rosetta Code "hofstadter.adb", "koch_curve.adb", -- PDF demo, Rosetta Code "mandelbrot.adb", "maze_gen.adb", -- Maze generator from Rosetta Code "md2html.adb", -- Markdown to HTML converter "merge_sort.adb", "names_in_boxes.adb", "native.adb", -- Example that works also for native targets. "peano_curve.adb", -- PDF demo, Rosetta Code "pdf_hello.adb", -- PDF demo "prc.adb", "random.adb", "record_code_gen.adb", "remarks.adb", "series.adb", "shell_sort.adb", "shell.adb", "strings_demo.adb", "sudoku_sample.adb", "tasks_01.adb", "tasks_02.adb", "three_lakes_s.adb", "timing.adb", "triangles_overlap.adb", -- Rosetta Code "unit_a.adb"); -- -- 2) * GNAT OK -- * HAC KO (feature not yet supported) -- -- "overloading.adb" -- -- 3) * GNAT OK -- * HAC KO (crash) -- -- 4) * GNAT OK (detects correctly incorrect Ada code) -- * HAC KO (compiles instead of outputting a compilation error; likely a Pascal-ism) -- See places with "!!" in the parser code. -- -- -- 5) Code wrong, incomplete, HAC showing wrong output, or whatever - to be sorted... -- -- "dinersmo.adb", -- "din_sm.adb", -- "din_ws.adb", -- "newrace.adb", -- "pgm0.adb", -- "pgm1.adb", -- "pgm2.adb", -- "race.adb", -- "racedead.adb" case HAC_Build_Mode is when "Debug" => for Object_Dir use "../obj/debug"; when "Fast" => for Object_Dir use "../obj/fast"; end case; for Source_Dirs use (".", "../src", "pdf", "tasking"); for Exec_Dir use "."; for Create_Missing_Dirs use "True"; -- Flips by default the "-p" switch package Pretty_Printer is for Default_Switches ("ada") use ("-i2"); end Pretty_Printer; Compiler_Common_Options := ("-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatwcijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ", -- Don't quit, write ali/tree file even if compile errors "-g", -- Generate debugging information -- "-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens "-gnatye", -- Style: check e:end/exit labels present "-gnatytc"); -- Style: check t:token separation rules, c:comment format (two spaces) Debug_Options := ("-gnata", -- Assertions enabled "-gnato", -- Enable overflow checking in STRICT mode "-gnatVa", -- Enable all validity checking options "-fstack-check", "-fno-inline"); Fast_Options := ("-Ofast", "-gnatpn"); package Compiler is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Compiler_Common_Options & Debug_Options; when "Fast" => for Default_Switches ("ada") use Compiler_Common_Options & Fast_Options; end case; end Compiler; package Binder is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use ("-Es"); when "Fast" => end case; end Binder; package Linker is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use ("-g"); when "Fast" => for Default_Switches ("ada") use ("-s", "-Wl,--gc-sections"); end case; end Linker; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-g", "-j0"); end Builder; end HAC_Exm; ================================================ FILE: exm/hello.adb ================================================ with HAT; procedure Hello is begin HAT.Put ("Hello world!"); end Hello; ================================================ FILE: exm/hello_big.adb ================================================ with HAT; procedure Hello_Big is use HAT; f : Real := 0.0; begin Put ("Hello"); Put_Line (" world! I am the program file: " & Command_Name); Put_Line ( " i i ** 2 2 ** i 2.0 ** i 2.0 ** f"); Put_Line ( "-------------------------------------------------------------"); for i in 1 .. 10 loop Put (i, 11); Put (i ** 2, 11); Put (2 ** i, 11); Put (2.0 ** i, 11, 2, 0); -- Fore, Aft, Exp. f := f + 1.0; Put_Line (2.0 ** f, 5, 3, 4); -- Fore, Aft, Exp. end loop; end Hello_Big; ================================================ FILE: exm/hofstadter.adb ================================================ -- Hofstadter Female and Male sequences -- Code taken from: -- http://rosettacode.org/wiki/Mutual_recursion#Ada -- with HAT; procedure Hofstadter is function M (N : Integer) return Integer; function F (N : Integer) return Integer is begin if N = 0 then return 1; else return N - M (F (N - 1)); end if; end F; function M (N : Integer) return Integer is begin if N = 0 then return 0; else return N - F (M (N - 1)); end if; end M; -- F(n) is not equal to M(n) if and only if n+1 is a Fibonacci number. -- https://oeis.org/A005378 function Fibonacci (N : Integer) return Integer is begin if N = 0 then return 0; elsif N = 1 then return 1; else return Fibonacci (N - 1) + Fibonacci (N - 2); end if; end Fibonacci; n_max : constant := 35; dig_it : constant := 3; is_fibo : array (0 .. n_max) of Boolean; fn : Integer; use HAT; begin Put_Line ("Hofstadter Female and Male sequences (mutual recursion)"); for n in 0 .. n_max - 1 loop is_fibo (n) := False; end loop; for n in 0 .. n_max - 1 loop fn := Fibonacci (n); exit when fn > is_fibo'Last; is_fibo (fn) := True; end loop; Put ("n = "); for n in 0 .. n_max - 1 loop Put (n, dig_it); end loop; New_Line; Put_Line (" " & n_max * dig_it * '_'); Put_Line ("Is n+1 "); Put ("Fibo ? "); for n in 0 .. n_max - 1 loop Put ((dig_it - 1) * ' '); if is_fibo (n + 1) then Put ('Y'); else Put (' '); end if; end loop; New_Line; Put ("F: "); for n in 0 .. n_max - 1 loop Put (F (n), dig_it); end loop; New_Line; Put ("M: "); for n in 0 .. n_max - 1 loop Put (M (n), dig_it); end loop; New_Line; Put ("F = M "); for n in 0 .. n_max - 1 loop Put ((dig_it - 1) * ' '); if F (n) /= M (n) then Put ('N'); else Put (' '); end if; end loop; New_Line; end Hofstadter; ================================================ FILE: exm/mandelbrot.adb ================================================ with HAT; procedure Mandelbrot is use HAT; -- NB: there is a complete Complex package in the Ada library: -- Ada.Numerics.Generic_Complex_Types. type Complex is record Re, Im : Real; end record; -- function Sqr (c: Complex) return Complex is -- !! functions with non-standard return types not yet available for HAC. procedure Sqr (c : in out Complex) is res : Complex; begin res.Re := c.Re ** 2 - c.Im ** 2; res.Im := 2.0 * c.Re * c.Im; c := res; end Sqr; -- !! Programmable operators (like "+") are not yet available for HAC. procedure Add (c : in out Complex; added : Complex) is begin c.Re := c.Re + added.Re; c.Im := c.Im + added.Im; end Add; function Square_Modulus (c : Complex) return Real is begin return c.Re ** 2 + c.Im ** 2; end Square_Modulus; -- function Mandelbrot_Iterate (z0 : Complex; max_iter : Integer) return Integer is z : Complex; begin z.Re := 0.0; z.Im := 0.0; for i in 1 .. max_iter loop Sqr (z); Add (z, z0); if Square_Modulus (z) > 4.0 then return i; end if; end loop; return max_iter; end Mandelbrot_Iterate; -- Display the Mandelbrot set for a given area, in "ASCII art". -- procedure Mandelzoom (x_min, y_min, x_max, y_max : Real) is c_max : constant := 98; r_max : constant := 20; i_max : constant := 24; aart : constant String (1 .. i_max) := "0123456789abcdefghijklm "; -- here we give up ----^ z0 : Complex; width : constant Real := x_max - x_min; height : constant Real := y_max - y_min; begin for r in 0 .. r_max loop for c in 0 .. c_max loop z0.Re := x_min + (width / Real (c_max) * Real (c)); z0.Im := y_min + (height / Real (r_max) * Real (r)); Put (aart (Mandelbrot_Iterate (z0, i_max))); end loop; New_Line; end loop; end Mandelzoom; begin Mandelzoom (-2.2, -1.0, 0.6, 1.0); end Mandelbrot; ================================================ FILE: exm/mathe_kal/2022/mathe_plus_2022_02.adb ================================================ -- https://www.mathekalender.de/wp/de/kalender/aufgaben/2022-02-de/ -- -- Brute-Force-Methode zum Raestsel "Bogenmatik" -- -- a*5 = Punkte pro Treffer im weissen Ring. -- b*5 = Punkte pro Treffer im violetten Ring. -- c*5 = Punkte pro Treffer im gelben Ring. -- d*5 = Punkte pro Treffer im Zentrum. with HAT; procedure Mathe_Plus_2022_02 is lim : constant := 22; use HAT; begin for a in 1 .. lim loop for b in a + 1 .. lim + 1 loop for c in b + 1 .. lim + 2 loop for d in c + 1 .. lim + 3 loop if 3 * a + b + d = 25 -- 125 Punkte gesamt. and 2 * b + c + 2 * d = 46 -- 230 Punkte gesamt. and a + b + 2 * c + d = 37 -- 185 Punkte gesamt. then HAT.Put_Line (+"Moeglichkeit: " & a * 5 & ", " & b * 5 & ", " & c * 5 & ", " & d * 5); end if; end loop; end loop; end loop; end loop; end Mathe_Plus_2022_02; ================================================ FILE: exm/mathe_kal/2022/mathe_plus_2022_04.adb ================================================ -- https://www.mathekalender.de/wp/de/kalender/aufgaben/2022-04-de/ -- -- Brute-Force-Methode um Raestsels "Geschenkeversand" -- Moeglichkeit Nr 4 ("Fuer jede Anfangsreihe von Geschenken mit einer -- ungeraden Anzahl von ordentlich verpackten Geschenken") zu testen. -- Das Programm ist kein Beweis, dass es immer geht, aber man sieht, -- dass dieselbe Muster immer wieder kommen, von '-' getrennt. -- -- P = ordentlich verpackt -- D = Verpackungsmaterial beschaedigt -- -- Fuer die anderen Moeglichkeiten gibt es Gegenbeispiele: -- PPPP hat keine Loesung aber gilt fuer Nr 1, 3, 7, 8, 9. -- PDP hat keine Loesung aber gilt mindestens fuer Nr 2, 5, 6. -- PPDDD hat keine Loesung aber gilt mindestens fuer Nr 10. with HAT; procedure Mathe_Plus_2022_04 is verbose : constant Boolean := True; subtype Test_String is String (1 .. 10); s : Test_String; successes, failures : Natural := 0; use HAT; procedure Solve is run : Test_String := s; -- procedure Flip (i : Integer) is begin if i in run'Range then case run (i) is when 'P' => run (i) := 'D'; when 'D' => run (i) := 'P'; when others => null; end case; end if; end Flip; -- Ps, Ds, done : Boolean; begin if verbose then Put_Line (+run & " <------"); end if; for count in 1 .. run'Length * 2 loop Ps := False; Ds := False; for i in run'Range loop case run (i) is when 'P' => -- Simple choice: just choose the first 'P' on the line. Ps := True; Flip (i - 1); Flip (i + 1); run (i) := '-'; -- Send gift number i. exit; when 'D' => Ds := True; when others => null; end case; end loop; if verbose then Put_Line (run); end if; done := not (Ps or Ds); -- ^ done = True: no more gifts in either state: line is empty. exit when done; end loop; if done then successes := successes + 1; else failures := failures + 1; end if; end Solve; procedure Test (start : Positive; number_of_Ps : Natural; length : Positive) is begin if number_of_Ps = 0 then for i in start .. length loop s (i) := 'D'; end loop; for i in length + 1 .. s'Last loop s (i) := ' '; end loop; Solve; else if start + number_of_Ps - 1 < length then s (start) := 'D'; Test (start + 1, number_of_Ps, length); end if; s (start) := 'P'; Test (start + 1, number_of_Ps - 1, length); end if; end; begin -- Test all setups up to a certain -- length and with an odd number of 'P'. for length in 1 .. s'Length loop for np in 1 .. length loop if np mod 2 = 1 then Test (1, np, length); end if; end loop; end loop; Put_Line (+"successes . . " & successes); Put_Line (+"failures . . " & failures); end Mathe_Plus_2022_04; ================================================ FILE: exm/mathe_kal/2022/mathe_plus_2022_09.adb ================================================ -- https://www.mathekalender.de/wp/de/kalender/aufgaben/2022-09-de/ with HAT; procedure Mathe_Plus_2022_09 is type Gift is (warm_socks, candle, bobble_hat, flute, woolen_sweater); size, joy : array (Gift) of Positive; type Child is (Nasti, Manu, Jona, Uli); list : array (Child, 1 .. 5) of Gift; total_size : Natural; total_joy : array (Child) of Natural; use HAT; begin size (warm_socks) := 2; size (candle) := 4; size (bobble_hat) := 6; size (flute) := 24; size (woolen_sweater) := 16; joy (warm_socks) := 4; joy (candle) := 5; joy (bobble_hat) := 8; joy (flute) := 20; joy (woolen_sweater) := 10; list (Nasti, 1) := flute; list (Nasti, 2) := woolen_sweater; list (Nasti, 3) := bobble_hat; list (Nasti, 4) := candle; list (Nasti, 5) := warm_socks; list (Manu, 1) := warm_socks; list (Manu, 2) := candle; list (Manu, 3) := bobble_hat; list (Manu, 4) := woolen_sweater; list (Manu, 5) := flute; list (Jona, 1) := warm_socks; list (Jona, 2) := bobble_hat; list (Jona, 3) := candle; list (Jona, 4) := flute; list (Jona, 5) := woolen_sweater; list (Uli, 1) := flute; list (Uli, 2) := bobble_hat; list (Uli, 3) := candle; list (Uli, 4) := warm_socks; list (Uli, 5) := woolen_sweater; for c in Child loop Put (Child'Image (c) & " "); end loop; New_Line; for bag_size in 2 .. 52 loop for c in Child loop total_size := 0; total_joy (c) := 0; for i in 1 .. 5 loop if total_size + size (list (c, i)) <= bag_size then -- In the bag! total_size := total_size + size (list (c, i)); total_joy (c) := total_joy (c) + joy (list (c, i)); end if; end loop; Put (total_joy (c), 8); end loop; Put (" " & Boolean'Image (total_joy (Jona) >= total_joy (Manu))); New_Line; end loop; end Mathe_Plus_2022_09; ================================================ FILE: exm/mathe_kal/2022/mkp_2022.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the Mathe Kalender Plus examples. -- Some programs work with both HAC and "full Ada" compilers like, -- GNAT some (titled *_full_ada.adb) work only with "full Ada". -- project MKP_2022 is for Source_Dirs use ( ".", "../../../src" -- GNAT's access to the HAT package. ); for Exec_Dir use "."; for Create_Missing_Dirs use "True"; type AoC_Build_Mode_Type is ("Debug", "Fast" ); AoC_Build_Mode : AoC_Build_Mode_Type := external ("AoC_Build_Mode", "Debug"); for Main use ( "mathe_plus_2022_09", "mathe_plus_2022_04", "mathe_plus_2022_02" ); case AoC_Build_Mode is when "Debug" => for Object_Dir use "obj_debug"; when "Fast" => for Object_Dir use "obj_fast"; end case; Common_Options := ( "-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatwCijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ", -- Don't quit, write ali/tree file even if compile errors -- "-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens -- "-gnatye", -- Style: check e:end/exit labels present "-gnatytc" -- Style: check t:token separation rules, c:comment format (two spaces) ); Fast_Options := ( "-O3", "-funroll-loops", "-fpeel-loops", "-funswitch-loops", "-ftracer", "-fweb", "-frename-registers", "-ftree-vectorize", "-fipa-cp-clone", "-fgcse-after-reload" ); Debug_Options := ( -- "-gnateV", -- Validity check for parameters, GNAT > 4.6, redundant with -gnatVim ? "-gnatVa", -- Turn on all validity checking options "-gnato", -- Enable overflow checking in STRICT (-gnato1) mode "-g", "-fno-inline", "-fstack-check" ); package Compiler is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Options & Debug_Options ; when "Fast" => for Default_Switches ("ada") use Common_Options & Fast_Options & ("-gnatpn", "-ffunction-sections"); end case; end Compiler; package Linker is case AoC_Build_Mode is when "Debug" => for Default_Switches ("ada") use ("-g"); when "Fast" => for Default_Switches ("ada") use ("-g", "-s", "-Wl,--gc-sections"); end case; end Linker; package Binder is -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks for Default_Switches ("ada") use ("-Es"); end Binder; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-j0"); end Builder; end MKP_2022; ================================================ FILE: exm/maze_gen.adb ================================================ -- Special version (for HAC) of -- http://rosettacode.org/wiki/Maze_generation#Ada with HAT; procedure Maze_Gen is type Direction is (North, South, West, East); type Cell_Walls is array (Direction) of Boolean; type Cells is record Walls : Cell_Walls; Visited : Boolean; end record; Height : constant := 15; Width : constant := 24; type Maze_Grid is array (1 .. Height, 1 .. Width) of Cells; type Point is record Row, Col : Integer; end record; type Maze_Type is record Start : Point; Grid : Maze_Grid; end record; function Opposite (D : Direction) return Direction is begin case D is when North => return South; when South => return North; when East => return West; when West => return East; end case; end Opposite; procedure Move (P : in out Point; D : Direction; Valid_Move : out Boolean) is begin Valid_Move := False; case D is when North => if P.Row > 1 then Valid_Move := True; P.Row := P.Row - 1; end if; when East => if P.Col < Width then Valid_Move := True; P.Col := P.Col + 1; end if; when West => if P.Col > 1 then Valid_Move := True; P.Col := P.Col - 1; end if; when South => if P.Row < Height then Valid_Move := True; P.Row := P.Row + 1; end if; end case; end Move; function Val (I : Integer) return Direction is -- ! Full Ada: use 'Val(...) begin case I is when 0 => return North; when 1 => return South; when 2 => return West; when others => return East; end case; end Val; procedure Depth_First_Algorithm (Maze : in out Maze_Grid; P : Point) is -- https://en.wikipedia.org/wiki/Maze_generation_algorithm Next_P : Point; Next_D : Direction; Valid_Direction : Boolean; Checked_Wall : array (Direction) of Boolean; All_Checked : Boolean; begin for D in Direction loop -- ! Full Ada ":= (others => False)" Checked_Wall (D) := False; end loop; -- Mark as visited: Maze (P.Row, P.Col).Visited := True; loop -- Use random direction: loop Next_D := Val (HAT.Rand (3)); exit when not Checked_Wall (Next_D); -- At least one wall is unchecked. end loop; Next_P := P; Move (Next_P, Next_D, Valid_Direction); if Valid_Direction then if not Maze (Next_P.Row, Next_P.Col).Visited then -- Connect the two cells by breaking the wall. Maze (P.Row, P.Col).Walls (Next_D) := False; Maze (Next_P.Row, Next_P.Col).Walls (Opposite (Next_D)) := False; -- Recurse from next cell. Depth_First_Algorithm (Maze, Next_P); end if; end if; Checked_Wall (Next_D) := True; -- Neighbour is either visited or invalid. -- All_Checked := True; for D in Direction loop All_Checked := All_Checked and Checked_Wall (D); end loop; -- Neighbours in all directions are either visited -- (either from here, or previously visited), or invalid: exit when All_Checked; -- Continue until there is no unvisited neighbour left. end loop; end Depth_First_Algorithm; procedure Initialize (Maze : in out Maze_Type) is All_Walls : Cell_Walls; use HAT; begin for D in Direction loop All_Walls (D) := True; end loop; -- ! Full Ada: initialized record. for i in 1 .. Height loop for j in 1 .. Width loop Maze.Grid (i, j).Walls := All_Walls; Maze.Grid (i, j).Visited := False; end loop; end loop; -- Choose starting cell Maze.Start.Row := Rand (1_000_000) mod Height + 1; Maze.Start.Col := Rand (1_000_000) mod Width + 1; Put_Line (+"Height: " & Height & ", Width: " & Width); Put_Line (+"Starting generation at " & Maze.Start.Row & ", " & Maze.Start.Col & " (marked with an X)"); Depth_First_Algorithm (Maze.Grid, Maze.Start); end Initialize; procedure Put_Grid (Item : Maze_Type) is use HAT; H_Bar : array (Boolean) of VString; V_Bar : array (Boolean) of Character; S_Cell : array (Boolean) of VString; Line : VString; begin H_Bar (False) := +" +"; H_Bar (True) := +"---+"; V_Bar (False) := ' '; V_Bar (True) := '|'; S_Cell (False) := +" "; S_Cell (True) := +" X "; -- North border of top row: Line := +"+"; for Col in 1 .. Width loop Line := Line & H_Bar (Item.Grid (1, Col).Walls (North)); end loop; Put_Line (Line); -- All rows: for Row in 1 .. Height loop -- West border of leftmost column: Line := +"" & V_Bar (Item.Grid (Row, 1).Walls (West)); -- All columns: for Col in 1 .. Width loop Line := Line & S_Cell (Row = Item.Start.Row and Col = Item.Start.Col) & V_Bar (Item.Grid (Row, Col).Walls (East)); end loop; Put_Line (Line); -- South border of current row: Line := +"+"; for Col in 1 .. Width loop Line := Line & H_Bar (Item.Grid (Row, Col).Walls (South)); end loop; Put_Line (Line); end loop; end Put_Grid; My_Maze : Maze_Type; begin Initialize (My_Maze); Put_Grid (My_Maze); end Maze_Gen; ================================================ FILE: exm/md2html.adb ================================================ -- MD2HTML - a Markdown to HTML converter. -- -- Useful for viewing Markdown files offline. with HAT; procedure MD2HTML is use HAT; f1, f2 : File_Type; type List_Descriptor is record indent : Positive; ordered : Boolean; end record; list_top : Natural := 0; list_stack : array (1 .. 10) of List_Descriptor; bold, italic, underline, strikethrough : Boolean := False; procedure Process (s : VString; indent : Positive) is function Is_Separator (c : Character) return Boolean is begin case c is when ' ' | ',' | ';' | '.' => return True; when others => return False; end case; end Is_Separator; function Process_Content (ct : VString) return VString is -- Assumption: ct is never empty. r : VString; c, cp1, cp2 : Character := ' '; item : Boolean := False; ordered : Boolean; begin for i in 1 .. Length (ct) loop c := Element (ct, i); case cp1 is when '*' | '_' | '~' | '-' => if c = cp1 then -- "**, "__", "~~" case cp1 is when '*' => bold := not bold; if bold then r := r & ""; else r := r & ""; end if; when '_' => underline := not underline; if underline then r := r & ""; else r := r & ""; end if; when '~' => strikethrough := not strikethrough; if strikethrough then r := r & ""; else r := r & ""; end if; when others => r := r & cp1; end case; elsif cp2 /= cp1 then if c = ' ' and cp2 = ' ' then if i = 2 and then (cp1 = '-' or cp1 = '*') then -- " * item" item := True; ordered := False; else r := r & cp1; end if; elsif Is_Separator (cp2) and then (cp1 = '*' or cp1 = '_') then -- " *x" if not italic then r := r & ""; end if; italic := True; elsif Is_Separator (c) and then (cp1 = '*' or cp1 = '_') then -- "x* " if italic then r := r & ""; end if; italic := False; else r := r & cp1; end if; elsif cp2 = cp1 then -- "**x": treated at previous step. null; else r := r & cp1; end if; when others => r := r & cp1; end case; cp2 := cp1; cp1 := c; end loop; if item then r := "
  • " & r; if list_top = 0 or else indent > list_stack (list_top).indent then list_top := list_top + 1; list_stack (list_top).indent := indent; list_stack (list_top).ordered := ordered; if ordered then r := "
      " & r; else r := "
        " & r; end if; end if; end if; return r; end Process_Content; hc : Integer := 0; i : Positive := 1; r : VString; begin if Length (s) = 0 then bold := False; italic := False; underline := False; strikethrough := False; return; end if; -- Headings while Element (s, i) = '#' loop hc := hc + 1; i := i + 1; end loop; if hc > 0 then r := r & "'; end if; r := r & Process_Content (Slice (s, 1 + hc, Length (s)) & ' '); while list_top > 0 and then indent < list_stack (list_top).indent loop if list_stack (list_top).ordered then r := "
    " & r; else r := "" & r; end if; list_top := list_top - 1; end loop; if hc > 0 then r := r & "'; end if; Put_Line (f2, r); end Process; s : VString; begin if Argument_Count = 0 then Open (f1, "../readme.md"); else Open (f1, Argument (1)); end if; Create (f2, "output.html"); Put_Line (f2, ""); while not End_Of_File (f1) loop Get_Line (f1, s); for indent in 1 .. Length (s) loop if Element (s, indent) /= ' ' then Process (Slice (s, indent, Length (s)), indent); exit; end if; end loop; end loop; Close (f1); Put_Line (f2, ""); Close (f2); end MD2HTML; ================================================ FILE: exm/merge_sort.adb ================================================ with HAT; procedure Merge_Sort is procedure Merge is subtype Vector is String (1 .. 26); v : Vector; temp_array : Vector; max : Integer; cur_length : Integer; m : Integer; left, top_left : Integer; right, top_right : Integer; c2 : String (1 .. 3); use HAT; begin v := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; c2 := " rl"; max := 26; Put_Line ("Merge Sort"); New_Line; Put_Line ("String at start:"); Put_Line ("----------------"); Put_Line (v); New_Line; -- cur_length := 1; while cur_length < max loop -- New phase temp_array := v; for k in 1 .. 26 loop Put (temp_array (k)); Put (c2 (1)); end loop; New_Line; left := 1; m := 1; while left <= max loop -- Find pair of subarrays right := left + cur_length; top_left := right; if top_left > max then top_left := max + 1; end if; top_right := right + cur_length; if top_right > max then top_right := max + 1; end if; -- Merge subarrays -- Go until one subarray runs out while left < top_left and right < top_right loop if temp_array (left) <= temp_array (right) then v (m) := temp_array (left); Put (v (m)); Put (c2 (2)); left := left + 1; else v (m) := temp_array (right); Put (v (m)); Put (c2 (3)); right := right + 1; end if; m := m + 1; end loop; -- Now "copy tail" of whichever subarray remains while left < top_left loop v (m) := temp_array (left); Put (v (m)); Put (c2 (2)); m := m + 1; left := left + 1; end loop; while right < top_right loop v (m) := temp_array (right); Put (v (m)); Put (c2 (3)); right := right + 1; m := m + 1; end loop; left := top_right; end loop; New_Line; -- Now double size of subarrays and go back for next phase cur_length := cur_length * 2; end loop; New_Line; Put_Line ("Result of Merge Sort:"); Put_Line ("---------------------"); Put_Line (v); end Merge; begin Merge; end Merge_Sort; ================================================ FILE: exm/names_in_boxes.adb ================================================ -- https://stackoverflow.com/questions/61719343/storing-and-using-strings-of-varying-length-ada with HAT; use HAT; procedure Names_in_Boxes is Max : constant := 100; type Names_List is array (1 .. Max) of VString; procedure Object_Catcha (N : out Integer) is begin Put ("Enter amount of objects: "); Get (N); -- Console vs. GUI input: if Get_Needs_Skip_Line then Skip_Line; else New_Line; end if; end Object_Catcha; procedure Names_Catcha (Names : out Names_List; N : in Integer) is begin for I in 1 .. N loop Put (+"Object " & I & ": "); Get_Line (Names (I)); end loop; end Names_Catcha; procedure Space_Box (Names : in Names_List; N : in Integer) is begin Put_Line (N * "+-----------+ "); for I in 1 .. N loop Put ("| " & Names (I) & (10 - Length (Names (I))) * ' ' & '|'); if I < N then Put ("<>---"); end if; end loop; New_Line; Put_Line (N * "+-----------+ "); end Space_Box; -- "Global" variables, unknown to -- Object_Catcha, Names_Catcha, Space_Box: N : Integer; Names : Names_List; begin Object_Catcha (N); if N > Max then Put_Line (+"Too many objects! Maximum is " & Max); else Put_Line ("Enter the name of the objects: "); Names_Catcha (Names, N); Space_Box (Names, N); end if; end Names_in_Boxes; ================================================ FILE: exm/native.adb ================================================ -- Summary of what can be done with -- compilation for native targets. -- Currently (v.0.26): not much! -- -- Command sample: -- hac -tamd64_windows_console_fasm exm/native.adb with HAT; procedure Native is use HAT; -- a : Integer; begin -- a := 1; -- Variables: TBD. Put_Line ("Hello ..."); Put_Line ("... world!"); -- 12345 in various forms: Put_Line (12000 + 340 + 5 * 1); Put_Line (12355 * (13 - 12) - 20 / (1414 / 707)); Put_Line (2469 * 5); Put_Line (61725 / 5); end Native; ================================================ FILE: exm/not_working/din_sm.adb ================================================ with HAT; use HAT; procedure Din_SM is task SCREEN is entry SEIZE; entry RELEASE; end SCREEN; task DIJKSTRA is entry GIVE_BIRTH; end DIJKSTRA; task HOPPER is entry GIVE_BIRTH; end HOPPER; task SAMMET is entry GIVE_BIRTH; end SAMMET; task GEHANI is entry GIVE_BIRTH; end GEHANI; task CHOPSTICK1 is entry PICKUP; entry PUTDOWN; end CHOPSTICK1; task CHOPSTICK2 is entry PICKUP; entry PUTDOWN; end CHOPSTICK2; task CHOPSTICK3 is entry PICKUP; entry PUTDOWN; end CHOPSTICK3; task CHOPSTICK4 is entry PICKUP; entry PUTDOWN; end CHOPSTICK4; NO_MEALS : integer := 3; task body DIJKSTRA is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do SCREEN.SEIZE; PUT("Eddy Dijkstra living and breathing"); NEW_LINE; SCREEN.RELEASE; end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK1.PICKUP; CHOPSTICK2.PICKUP; LENGTH_OF_MEAL := RANDOM(9) + 1; SCREEN.SEIZE; PUT("Eddy Dijkstra eating meal"); PUT(x:2); PUT(" with chopsticks 1 and 2"); PUT(" for"); PUT(LENGTH_OF_MEAL:2); PUT(" seconds"); NEW_LINE; SCREEN.RELEASE; delay LENGTH_OF_MEAL; SCREEN.SEIZE; PUT("Eddy Dijkstra done"); NEW_LINE; SCREEN.RELEASE; CHOPSTICK1.PUTDOWN; CHOPSTICK2.PUTDOWN; delay 5.0; end loop; SCREEN.SEIZE; PUT("Eddy Dijkstra burp"); NEW_LINE; SCREEN.RELEASE; end DIJKSTRA; task body HOPPER is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do SCREEN.SEIZE; PUT(" Gracie Hopper living and breathing"); NEW_LINE; SCREEN.RELEASE; end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK2.PICKUP; CHOPSTICK3.PICKUP; LENGTH_OF_MEAL := RANDOM(9) + 1; SCREEN.SEIZE; PUT(" Gracie Hopper eating meal"); PUT(x:2); PUT(" with chopsticks 2 and 3"); PUT(" for"); PUT(LENGTH_OF_MEAL:2); PUT(" seconds"); NEW_LINE; SCREEN.RELEASE; delay LENGTH_OF_MEAL; SCREEN.SEIZE; PUT(" Gracie Hopper done"); NEW_LINE; SCREEN.RELEASE; CHOPSTICK2.PUTDOWN; CHOPSTICK3.PUTDOWN; delay 5.0; end loop; SCREEN.SEIZE; PUT(" Gracie Hopper burp"); NEW_LINE; SCREEN.RELEASE; end HOPPER; task body SAMMET is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do SCREEN.SEIZE; PUT(" Jeannie Sammet living and breathing"); NEW_LINE; SCREEN.RELEASE; end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK3.PICKUP; CHOPSTICK4.PICKUP; LENGTH_OF_MEAL := RANDOM(9) + 1; SCREEN.SEIZE; PUT(" Jeannie Sammet eating meal"); PUT(x:2); PUT(" with chopsticks 3 and 4"); PUT(" for"); PUT(LENGTH_OF_MEAL:2); PUT(" seconds"); NEW_LINE; SCREEN.RELEASE; delay LENGTH_OF_MEAL; SCREEN.SEIZE; PUT(" Jeannie Sammet done"); NEW_LINE; SCREEN.RELEASE; CHOPSTICK3.PUTDOWN; CHOPSTICK4.PUTDOWN; delay 5.0; end loop; SCREEN.SEIZE; PUT(" Jeannie Sammet burp"); NEW_LINE; SCREEN.RELEASE; end SAMMET; task body GEHANI is LENGTH_OF_MEAL : FLOAT; begin accept GIVE_BIRTH do SCREEN.SEIZE; PUT(" Narain Gehani living and breathing"); NEW_LINE; SCREEN.RELEASE; end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK1.PICKUP; CHOPSTICK4.PICKUP; LENGTH_OF_MEAL := RANDOM(9) + 1; SCREEN.SEIZE; PUT(" Narain Gehani eating meal"); PUT(x:2); PUT(" with chopsticks 1 and 4"); PUT(" for"); PUT(LENGTH_OF_MEAL:2); PUT(" seconds"); NEW_LINE; SCREEN.RELEASE; delay LENGTH_OF_MEAL; SCREEN.SEIZE; PUT(" Narain Gehani done"); NEW_LINE; SCREEN.RELEASE; CHOPSTICK1.PUTDOWN; CHOPSTICK4.PUTDOWN; delay 5.0; end loop; SCREEN.SEIZE; PUT(" Narain Gehani burp"); NEW_LINE; SCREEN.RELEASE; end GEHANI; task body SCREEN is begin loop select accept SEIZE; accept RELEASE; or terminate; end select; end loop; end SCREEN; task body CHOPSTICK1 is begin loop accept PICKUP; accept PUTDOWN; end loop; end CHOPSTICK1; task body CHOPSTICK2 is begin loop accept PICKUP; accept PUTDOWN; end loop; end CHOPSTICK2; task body CHOPSTICK3 is begin loop accept PICKUP; accept PUTDOWN; end loop; end CHOPSTICK3; task body CHOPSTICK4 is begin loop accept PICKUP; accept PUTDOWN; end loop; end CHOPSTICK4; begin DIJKSTRA.GIVE_BIRTH; HOPPER.GIVE_BIRTH; SAMMET.GIVE_BIRTH; GEHANI.GIVE_BIRTH; end Din_SM; ================================================ FILE: exm/not_working/din_ws.adb ================================================ with HAT; use HAT; procedure Din_WS is task DIJKSTRA is entry GIVE_BIRTH; end DIJKSTRA; task HOPPER is entry GIVE_BIRTH; end HOPPER; task SAMMET is entry GIVE_BIRTH; end SAMMET; task GEHANI is entry GIVE_BIRTH; end GEHANI; task CHOPSTICK1 is entry PICKUP; entry PUTDOWN; end CHOPSTICK1; task CHOPSTICK2 is entry PICKUP; entry PUTDOWN; end CHOPSTICK2; task CHOPSTICK3 is entry PICKUP; entry PUTDOWN; end CHOPSTICK3; task CHOPSTICK4 is entry PICKUP; entry PUTDOWN; end CHOPSTICK4; NO_MEALS : integer := 5; task body DIJKSTRA is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do PUT("Eddy Dijkstra living and breathing"); NEW_LINE; end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK1.PICKUP; CHOPSTICK2.PICKUP; LENGTH_OF_MEAL := Float(RANDOM(9)) + 1.0; PUT("Eddy Dijkstra eating meal"); PUT(x, 2); PUT(" with chopsticks 1 and 2"); PUT(" for"); PUT(LENGTH_OF_MEAL, 2); PUT(" seconds"); NEW_LINE; delay LENGTH_OF_MEAL; PUT("Eddy Dijkstra done"); NEW_LINE; CHOPSTICK1.PUTDOWN; CHOPSTICK2.PUTDOWN; delay 5.0; end loop; PUT("Eddy Dijkstra burp"); NEW_LINE; end DIJKSTRA; task body HOPPER is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do PUT(" Gracie Hopper living and breathing"); NEW_LINE; end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK2.PICKUP; CHOPSTICK3.PICKUP; LENGTH_OF_MEAL := RANDOM(9) + 1; PUT(" Gracie Hopper eating meal"); PUT(x:2); PUT(" with chopsticks 2 and 3"); PUT(" for"); PUT(LENGTH_OF_MEAL:2); PUT(" seconds"); NEW_LINE; delay LENGTH_OF_MEAL; PUT(" Gracie Hopper done"); NEW_LINE; CHOPSTICK2.PUTDOWN; CHOPSTICK3.PUTDOWN; delay 5.0; end loop; PUT(" Gracie Hopper burp"); NEW_LINE; end HOPPER; task body SAMMET is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do PUT(" Jeannie Sammet living and breathing"); NEW_LINE; end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK3.PICKUP; CHOPSTICK4.PICKUP; LENGTH_OF_MEAL := RANDOM(9) + 1; PUT(" Jeannie Sammet eating meal"); PUT(x:2); PUT(" with chopsticks 3 and 4"); PUT(" for"); PUT(LENGTH_OF_MEAL:2); PUT(" seconds"); NEW_LINE; delay LENGTH_OF_MEAL; PUT(" Jeannie Sammet done"); NEW_LINE; CHOPSTICK3.PUTDOWN; CHOPSTICK4.PUTDOWN; delay 5.0; end loop; PUT(" Jeannie Sammet burp"); NEW_LINE; end SAMMET; task body GEHANI is LENGTH_OF_MEAL : FLOAT; begin accept GIVE_BIRTH do PUT(" Narain Gehani living and breathing"); NEW_LINE; end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK1.PICKUP; CHOPSTICK4.PICKUP; LENGTH_OF_MEAL := RANDOM(9) + 1; PUT(" Narain Gehani eating meal"); PUT(x:2); PUT(" with chopsticks 1 and 4"); PUT(" for"); PUT(LENGTH_OF_MEAL:2); PUT(" seconds"); NEW_LINE; delay LENGTH_OF_MEAL; PUT(" Narain Gehani done"); NEW_LINE; CHOPSTICK1.PUTDOWN; CHOPSTICK4.PUTDOWN; delay 5.0; end loop; PUT(" Narain Gehani burp"); NEW_LINE; end GEHANI; task body CHOPSTICK1 is begin loop select accept PICKUP; accept PUTDOWN; or terminate; end select; end loop; end CHOPSTICK1; task body CHOPSTICK2 is begin loop select accept PICKUP; accept PUTDOWN; or terminate; end select; end loop; end CHOPSTICK2; task body CHOPSTICK3 is begin loop select accept PICKUP; accept PUTDOWN; or terminate; end select; end loop; end CHOPSTICK3; task body CHOPSTICK4 is begin loop select accept PICKUP; accept PUTDOWN; or terminate; end select; end loop; end CHOPSTICK4; begin DIJKSTRA.GIVE_BIRTH; HOPPER.GIVE_BIRTH; SAMMET.GIVE_BIRTH; GEHANI.GIVE_BIRTH; end Din_WS; ================================================ FILE: exm/not_working/dinersmo.adb ================================================ with HAT; use HAT; procedure dinersmo is SCREEN: SEMAPHORE := 1; -- task SCREEN is -- entry WAIT; -- entry SIGNAL; -- end SCREEN; task DIJKSTRA is entry GIVE_BIRTH; end DIJKSTRA; task HOPPER is entry GIVE_BIRTH; end HOPPER; task SAMMET is entry GIVE_BIRTH; end SAMMET; task GEHANI is entry GIVE_BIRTH; end GEHANI; task CHOPSTICK1 is entry PICKUP; entry PUTDOWN; end CHOPSTICK1; task CHOPSTICK2 is entry PICKUP; entry PUTDOWN; end CHOPSTICK2; task CHOPSTICK3 is entry PICKUP; entry PUTDOWN; end CHOPSTICK3; task CHOPSTICK4 is entry PICKUP; entry PUTDOWN; end CHOPSTICK4; NO_MEALS : integer := 5; task body DIJKSTRA is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do WAIT(SCREEN); PUT("Eddy Dijkstra living and breathing"); NEW_LINE; SIGNAL(SCREEN); end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK1.PICKUP; CHOPSTICK2.PICKUP; LENGTH_OF_MEAL := RANDOM(10); WAIT(SCREEN); PUT("Eddy Dijkstra eating meal"); PUT(x, 2); PUT(" with chopsticks 1 and 2"); PUT(" for"); PUT(LENGTH_OF_MEAL, 2); PUT(" seconds"); NEW_LINE; SIGNAL(SCREEN); delay LENGTH_OF_MEAL; WAIT(SCREEN); PUT("Eddy Dijkstra done"); NEW_LINE; SIGNAL(SCREEN); CHOPSTICK1.PUTDOWN; CHOPSTICK2.PUTDOWN; delay 5.0; end loop; WAIT(SCREEN); PUT("Eddy Dijkstra burp"); NEW_LINE; SIGNAL(SCREEN); end DIJKSTRA; task body HOPPER is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do WAIT(SCREEN); PUT(" Gracie Hopper living and breathing"); NEW_LINE; SIGNAL(SCREEN); end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK2.PICKUP; CHOPSTICK3.PICKUP; LENGTH_OF_MEAL := RANDOM(10); WAIT(SCREEN); PUT(" Gracie Hopper eating meal"); PUT(x, 2); PUT(" with chopsticks 2 and 3"); PUT(" for"); PUT(LENGTH_OF_MEAL, 2); PUT(" seconds"); NEW_LINE; SIGNAL(SCREEN); delay LENGTH_OF_MEAL; WAIT(SCREEN); PUT(" Gracie Hopper done"); NEW_LINE; SIGNAL(SCREEN); CHOPSTICK2.PUTDOWN; CHOPSTICK3.PUTDOWN; delay 5.0; end loop; WAIT(SCREEN); PUT(" Gracie Hopper burp"); NEW_LINE; SIGNAL(SCREEN); end HOPPER; task body SAMMET is LENGTH_OF_MEAL: FLOAT; begin accept GIVE_BIRTH do WAIT(SCREEN); PUT(" Jeannie Sammet living and breathing"); NEW_LINE; SIGNAL(SCREEN); end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK3.PICKUP; CHOPSTICK4.PICKUP; LENGTH_OF_MEAL := RANDOM(10); WAIT(SCREEN); PUT(" Jeannie Sammet eating meal"); PUT(x, 2); PUT(" with chopsticks 3 and 4"); PUT(" for"); PUT(LENGTH_OF_MEAL, 2); PUT(" seconds"); NEW_LINE; SIGNAL(SCREEN); delay LENGTH_OF_MEAL; WAIT(SCREEN); PUT(" Jeannie Sammet done"); NEW_LINE; SIGNAL(SCREEN); CHOPSTICK3.PUTDOWN; CHOPSTICK4.PUTDOWN; delay 5.0; end loop; WAIT(SCREEN); PUT(" Jeannie Sammet burp"); NEW_LINE; SIGNAL(SCREEN); end SAMMET; task body GEHANI is LENGTH_OF_MEAL : FLOAT; begin accept GIVE_BIRTH do WAIT(SCREEN); PUT(" Narain Gehani living and breathing"); NEW_LINE; SIGNAL(SCREEN); end GIVE_BIRTH; for x in 1..NO_MEALS loop CHOPSTICK1.PICKUP; CHOPSTICK4.PICKUP; LENGTH_OF_MEAL := RANDOM(10); WAIT(SCREEN); PUT(" Narain Gehani eating meal"); PUT(x:2); PUT(" with chopsticks 1 and 4"); PUT(" for"); PUT(LENGTH_OF_MEAL:2); PUT(" seconds"); NEW_LINE; SIGNAL(SCREEN); delay LENGTH_OF_MEAL; WAIT(SCREEN); PUT(" Narain Gehani done"); NEW_LINE; SIGNAL(SCREEN); CHOPSTICK1.PUTDOWN; CHOPSTICK4.PUTDOWN; delay 5.0; end loop; WAIT(SCREEN); PUT(" Narain Gehani burp"); NEW_LINE; SIGNAL(SCREEN); end GEHANI; -- task body SCREEN is -- begin -- loop -- select -- accept WAIT; -- or -- terminate; -- end select; -- accept SIGNAL; -- end loop; -- end SCREEN; task body CHOPSTICK1 is begin loop select accept PICKUP; or terminate; end select; accept PUTDOWN; end loop; end CHOPSTICK1; task body CHOPSTICK2 is begin loop select accept PICKUP; or terminate; end select; accept PUTDOWN; end loop; end CHOPSTICK2; task body CHOPSTICK3 is begin loop select accept PICKUP; or terminate; end select; accept PUTDOWN; end loop; end CHOPSTICK3; task body CHOPSTICK4 is begin loop select accept PICKUP; or terminate; end select; accept PUTDOWN; end loop; end CHOPSTICK4; begin DIJKSTRA.GIVE_BIRTH; HOPPER.GIVE_BIRTH; SAMMET.GIVE_BIRTH; GEHANI.GIVE_BIRTH; end dinersmo; ================================================ FILE: exm/not_working/newrace.adb ================================================ with HAT; use HAT; -- CS159-10 Instructor: Arthur Vargas Lopes -- Fall 1990 procedure newrace is task SCREEN is entry WAITME; ENTRY SIGNALME; end SCREEN; task BUBBLE_SORT is end BUBBLE_SORT; task SELECT_S_SORT is end SELECT_S_SORT; task body SCREEN is n : integer; begin n := 0; loop select when n = 0 => accept WAITME do n := 1; end WAITME; or when n = 1 => accept SIGNALME do n := n - 1; end SIGNALME; or terminate; end select; end loop; end SCREEN; task body SELECT_S_SORT is B : STRING(0..25); I,J : INTEGER; procedure SWAP(X, Y : in INTEGER) is temp : character; begin SCREEN.WAITME; CURSORAT(2,X+14); PUT("X"); CURSORAT(2,Y+14); PUT("Y"); SCREEN.SIGNALME; temp := b(x); b(x) := b(y); b(y) := temp; SCREEN.WAITME; CURSORAT(3,X+14); PUT(b(x)); CURSORAT(3,Y+14); PUT(b(y)); CURSORAT(2,X+14); PUT(" "); CURSORAT(2,Y+14); PUT(" "); SCREEN.SIGNALME; end SWAP; begin SCREEN.WAITME;CURSORAT(3,1); PUT("Selection:");SCREEN.SIGNALME; B := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; for k in 0..25 loop CURSORAT(3,k+14); put(b(k)); end loop; for i in 0..24 loop SCREEN.WAITME; CURSORAT(2,50); PUT("I: "); PUT(I); SCREEN.SIGNALME; for j in (i+1)..25 loop SCREEN.WAITME; CURSORAT(3,50); PUT("J: "); PUT(J); SCREEN.SIGNALME; if B(I) > B(J) then SWAP(I,J); end if; end loop; end loop; end SELECT_S_SORT; task body BUBBLE_SORT is B : STRING(0..25); I,J : INTEGER; procedure SWAP(X, Y : in INTEGER) is temp : character; begin SCREEN.WAITME; CURSORAT(6,X+14); PUT("X"); CURSORAT(6,Y+14); PUT("Y"); SCREEN.SIGNALME; temp := b(x); b(x) := b(y); b(y) := temp; SCREEN.WAITME; CURSORAT(7,X+14); PUT(b(x)); CURSORAT(7,Y+14); PUT(b(y)); CURSORAT(6,X+14); PUT(" "); CURSORAT(6,Y+14); PUT(" "); SCREEN.SIGNALME; end SWAP; begin SCREEN.WAITME;CURSORAT(7,1); PUT("Bubble:"); SCREEN.SIGNALME; B := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; for k in 0..25 loop SCREEN.WAITME;CURSORAT(7,k+14); put(b(k)); SCREEN.SIGNALME; end loop; I:= 25; while (I > 0) loop CURSORAT(6,50); PUT("I: "); PUT(I); J:= 0; while (J < I) loop CURSORAT(7,50); PUT("J: "); PUT(J); if B(J) > B(J+1) then SWAP(J,J+1); end if; J:= J+1; end loop; I:= I-1; end loop; end BUBBLE_SORT; begin end newrace; ================================================ FILE: exm/not_working/overloading.adb ================================================ -- This example contains a feature that is missing in HAC (at least v.0.01) with HAT; use HAT; procedure Overloading is function A (i : Integer) return Integer is begin return i + 1; end A; function A (r : Real) return Integer is begin return Integer (r) + 2; end A; begin Put (A (0)); -- Should be 1 Put (A (0.0)); -- Should be 2 end Overloading; ================================================ FILE: exm/not_working/pgm0.adb ================================================ with HAT; use HAT; procedure PGM0 is TASK TELLER IS ENTRY MAKE_DEP(CUST_ID : INTEGER; AMOUNT : Real); END TELLER; TASK CUST_C; TASK CUST_B; TASK CUST_A; TYPE CUST_RECORD IS RECORD ID : INTEGER; BALANCE : Real; END RECORD; ACCOUNT : ARRAY (1 .. 5) OF CUST_RECORD; procedure Show is begin for i in account'Range loop Put_Line (+"#" & i & "; ID: " & account (i).ID & "; balance: " & account (i).balance); end loop; New_Line; end; TASK BODY CUST_C IS BEGIN TELLER.MAKE_DEP (435,75.50); END CUST_C; TASK BODY CUST_B IS BEGIN TELLER.MAKE_DEP (878,100.0); END CUST_B; TASK BODY CUST_A IS BEGIN TELLER.MAKE_DEP (354,50.00); END CUST_A; TASK BODY TELLER IS BEGIN ACCOUNT (1).ID := 125; ACCOUNT (1).BALANCE := 400.50; ACCOUNT (2).ID := 354; ACCOUNT (2).BALANCE := 75.33; ACCOUNT (3).ID := 435; ACCOUNT (3).BALANCE := 137.95; ACCOUNT (4).ID := 878; ACCOUNT (4).BALANCE := 557.00; ACCOUNT (5).ID := 589; ACCOUNT (5).BALANCE := 235.75; Show; LOOP SELECT ACCEPT MAKE_DEP (CUST_ID : INTEGER; AMOUNT : Real) DO for I in account'Range loop IF ACCOUNT(I).ID = CUST_ID THEN ACCOUNT(I).BALANCE := ACCOUNT(I).BALANCE + AMOUNT; Show; exit; END IF; END LOOP; END MAKE_DEP; OR TERMINATE; END SELECT; END LOOP; END TELLER; BEGIN NULL; END; ================================================ FILE: exm/not_working/pgm1.adb ================================================ with HAT; use HAT; PROCEDURE PGM1 IS TASK STD_1; TASK STD_2; TASK STD_3; TASK TEACHER IS ENTRY CHECK_GRADE (STDNT : INTEGER; GRADE : OUT INTEGER); END TEACHER; TASK BODY STD_1 IS MY_GRADE : INTEGER; BEGIN TEACHER.CHECK_GRADE (1, MY_GRADE); END STD_1; TASK BODY STD_2 IS MY_GRADE : INTEGER; BEGIN TEACHER.CHECK_GRADE (2, MY_GRADE); END STD_2; TASK BODY STD_3 IS MY_GRADE : INTEGER; BEGIN TEACHER.CHECK_GRADE (3, MY_GRADE); END STD_3; TASK BODY TEACHER IS CLASS_GRADES : ARRAY (1 .. 4) OF INTEGER; I : INTEGER; BEGIN CLASS_GRADES (1) := 35; CLASS_GRADES (2) := 97; CLASS_GRADES (3) := 85; CLASS_GRADES (4) := 77; ACCEPT CHECK_GRADE (STDNT : INTEGER; GRADE : OUT INTEGER) DO I := STDNT; GRADE := CLASS_GRADES(I); END CHECK_GRADE; END TEACHER; BEGIN NULL; END PGM1; ================================================ FILE: exm/not_working/pgm2.adb ================================================ with HAT; use HAT; PROCEDURE PGM2 IS POINT1 : INTEGER := 10; POINT2 : INTEGER := -10; POINT3 : INTEGER := -20; POINT4 : INTEGER := 0; POINT5 : INTEGER := 100; FINISHED : INTEGER; TASK CALCULATOR IS ENTRY GET_LENGTH(POINTA, POINTB : INTEGER; LENGTH : OUT INTEGER); ENTRY GET_MIDPOINT(POINTA, POINTB : INTEGER; POINTC : OUT INTEGER); ENTRY DONE; ENTRY ACK; END CALCULATOR; TASK GEOM_A; TASK GEOM_B; TASK GEOM_C; TASK BODY GEOM_A IS LENGTH : INTEGER; MIDPOINT : INTEGER; BEGIN CALCULATOR.GET_LENGTH(POINT2,POINT1,LENGTH); CALCULATOR.GET_MIDPOINT(POINT1,POINT5,MIDPOINT); CALCULATOR.ACK; END GEOM_A; TASK BODY GEOM_B IS LENGTH : INTEGER; MIDPOINT : INTEGER; BEGIN CALCULATOR.GET_MIDPOINT(POINT2,POINT3,MIDPOINT); CALCULATOR.GET_MIDPOINT(POINT3,POINT5,MIDPOINT); CALCULATOR.ACK; END GEOM_B; TASK BODY GEOM_C IS LENGTH : INTEGER; MIDPOINT : INTEGER; BEGIN CALCULATOR.GET_MIDPOINT(POINT1,POINT4,MIDPOINT); CALCULATOR.GET_LENGTH(POINT5,POINT2,LENGTH); CALCULATOR.GET_MIDPOINT(POINT4,POINT1,MIDPOINT); CALCULATOR.ACK; END GEOM_C; TASK BODY CALCULATOR IS BEGIN FINISHED := 0; LOOP SELECT ACCEPT GET_LENGTH(POINTA, POINTB : INTEGER; LENGTH : OUT INTEGER) DO LENGTH := POINTB - POINTA; END GET_LENGTH; OR ACCEPT GET_MIDPOINT(POINTA, POINTB : INTEGER; POINTC : OUT INTEGER) DO POINTC := (POINTA + POINTB) / 2; END GET_MIDPOINT; OR ACCEPT ACK DO FINISHED := FINISHED + 1; END ACK; OR WHEN FINISHED = 3 => ACCEPT DONE DO NULL; END DONE; OR TERMINATE; END SELECT; END LOOP; END CALCULATOR; BEGIN CALCULATOR.DONE; PUT("POINT1 = "); PUT_LINE(POINT1); PUT("POINT2 = "); PUT_LINE(POINT2); PUT("POINT3 = "); PUT_LINE(POINT3); PUT("POINT4 = "); PUT_LINE(POINT4); PUT("POINT5 = "); PUT_LINE(POINT5); END PGM2; ================================================ FILE: exm/not_working/race.adb ================================================ with HAT; use HAT; procedure RACE is ------------------------------------------------------------------------------ -- Sort race demonstration program for THE AVL PARALLEL MONITORING - -- WITH SmallAda Version 2.0. - ------------------------------------------------------------------------------ STIME : FLOAT; task BUBBLE_SORT is entry S(r : in INTEGER; t : in FLOAT); entry X; end BUBBLE_SORT; task INSERT_SORT is entry S(r : in INTEGER; t : in FLOAT); entry X; end INSERT_SORT; task SHELL_SORT is entry S(r : in INTEGER; t : in FLOAT); entry X; end SHELL_SORT; task SCREEN is entry P(X,Y : in INTEGER; C : in CHARACTER); entry place(who : integer); entry conclude; end SCREEN; task body SCREEN is position : integer := 0; begin loop select accept P(X,Y : in INTEGER; C : in CHARACTER) do CURSORAT(X,Y); PUT(C); end P; or accept place(who : integer) do CURSORAT(who,50); IF POSITION = 0 THEN PUT("FIRST"); ELSIF POSITION = 1 THEN PUT("SECOND"); ELSE PUT("LAST"); CURSORAT(18,1); END IF; POSITION := POSITION + 1; end place; or when position = 3 => accept conclude; or terminate ; end select ; end loop; end SCREEN; task body SHELL_SORT is B : STRING(0..25); TEMP : CHARACTER; I ,J ,STEP : INTEGER; STEPSIZE : array(1..4) OF INTEGER; STOP : BOOLEAN; ROW : INTEGER; STIME : FLOAT; begin B := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; -- Accept call from "main" accept S(r : in INTEGER; t : in FLOAT) do ROW := r; STIME := t; end S; for k in 0..25 loop SCREEN.P(ROW,14+k,B(k)); end loop; -- 'steps' contains decreasing increments for each -- pass. The last pass has increment 1. STEPSIZE(4) := 1; for PASS in reverse 1..3 loop STEPSIZE(PASS):= 2*STEPSIZE(PASS+1); end loop; delay STIME - CLOCK; for PASS in 1..4 loop STEP := STEPSIZE(PASS); -- Do a straight insertion sort with 'step' as -- an increment instead of 1. I := STEP; while (I <= 25) loop TEMP := B(I); J := I; STOP := FALSE; while (J > STEP-1) and (STOP /= TRUE) loop J := J - STEP; if B(J) > TEMP then B(J+STEP) := B(J); SCREEN.P(ROW, 14+J, TEMP); else B(J+STEP) := TEMP; STOP := TRUE; end if; SCREEN.P(ROW,14+(J+STEP),B(J+STEP)); end loop; if (not STOP) then B(0) := TEMP; SCREEN.P(ROW,14,B(0)); end if; I := I + STEP; end loop; end loop; -- for pass in 1..npass SCREEN.PLACE(ROW); end SHELL_SORT; task body BUBBLE_SORT is B : STRING(0..25); TEMP : CHARACTER; I, J : INTEGER; ROW : INTEGER; STIME : FLOAT; begin B := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; -- Accept call from "main" accept S(r : in INTEGER; t : in FLOAT) do ROW := r; STIME := t; end S; for k in 0..25 loop SCREEN.P(ROW,14+k,B(k)); end loop; delay STIME - CLOCK; I:= 25; while (I > 0) loop J:= 0; while (J < I) loop if B(J) > B(J+1) then TEMP:= B(J+1); B(J+1):= B(J); B(J):= TEMP; SCREEN.P(ROW,14+J ,B(J )); SCREEN.P(ROW,14+J+1,B(J+1)); end if; J:= J+1; end loop; I:= I-1; end loop; SCREEN.PLACE(ROW); end BUBBLE_SORT; task body INSERT_SORT is B : STRING(0..25); TEMP : CHARACTER; J : INTEGER; STOP : BOOLEAN; ROW : INTEGER; STIME : FLOAT; BEGIN B := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; -- Accept call from "main" accept S(r : in INTEGER; t : in FLOAT) do ROW := r; STIME := t; end S; for k in 0..25 loop SCREEN.P(ROW,14+k,B(k)); end loop; delay STIME - CLOCK; for I in 0..25 loop TEMP := B(I); J := I; STOP := FALSE; while (J > 0) and (not STOP) loop J := J - 1; if (B(J) > TEMP) then B(J+1):= B(J); else B(J+1):= TEMP; STOP := TRUE; end if; SCREEN.P(ROW, 14+(J+1) ,B(J+1)); end loop; if (not STOP) then B(0) := TEMP; SCREEN.P(ROW ,14 ,B(0)); end if; end loop; SCREEN.PLACE(ROW); end INSERT_SORT; begin CURSORAT(3,1); PUT("Bubble:"); CURSORAT(5,1); PUT("Insertion:"); CURSORAT(7,1); PUT("Shell:"); STIME := CLOCK + 10.0; -- Start Bubble BUBBLE_SORT.S(3,STIME); -- Start Insert INSERT_SORT.S(5,STIME); -- Start Shell SHELL_SORT.S(7,STIME); -- Wait until the "race" finish SCREEN.conclude; end RACE; ================================================ FILE: exm/not_working/racedead.adb ================================================ with HAT; use HAT; procedure RACEDead is ------------------------------------------------------------------------------ -- Sort race demonstration program for THE AVL PARALLEL MONITORING - -- WITH SmallAda Version 2.0. - ------------------------------------------------------------------------------ STIME : FLOAT; task BUBBLE_SORT is entry S(r : in INTEGER; t : in FLOAT); entry X; end BUBBLE_SORT; task INSERT_SORT is entry S(r : in INTEGER; t : in FLOAT); entry X; end INSERT_SORT; task SHELL_SORT is entry S(r : in INTEGER; t : in FLOAT); entry X; end SHELL_SORT; task SCREEN is entry P(X,Y : in INTEGER; C : in CHARACTER); end SCREEN; task body SCREEN is begin loop select accept P(X,Y : in INTEGER; C : in CHARACTER) do CURSORAT(X,Y); PUT(C); end P; end select ; end loop; end SCREEN; task body BUBBLE_SORT is B : STRING(0..5); TEMP : CHARACTER; I,J : INTEGER; ROW : INTEGER; STIME : FLOAT; begin B := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; accept S(r : in INTEGER; t : in FLOAT) do ROW := r; STIME := t; end S; for k in 0..5 loop SCREEN.P(ROW,14+k,B(k)); end loop; delay STIME - CLOCK; I:= 5; while (I > 0) loop J:= 0; while (J < I) loop if B(J) > B(J+1) then TEMP:= B(J+1); B(J+1):= B(J); B(J):= TEMP; SCREEN.P(ROW,14+J ,B(J )); SCREEN.P(ROW,14+J+1,B(J+1)); end if; J:= J+1; end loop; I:= I-1; end loop; accept X; end BUBBLE_SORT; task body INSERT_SORT is B : STRING(0..5); TEMP : CHARACTER; J : INTEGER; STOP : BOOLEAN; ROW : INTEGER; STIME : FLOAT; BEGIN B := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; accept S(r : in INTEGER; t : in FLOAT) do ROW := r; STIME := t; end S; for k in 0..5 loop SCREEN.P(ROW,14+k,B(k)); end loop; delay STIME - CLOCK; for I in 0..5 loop TEMP := B(I); J:= I; STOP := FALSE; while (J > 0) and (not STOP) loop J := J - 1; if (B(J) > TEMP) then B(J+1):= B(J); else B(J+1):= TEMP; STOP := TRUE; end if; SCREEN.P(ROW, 14+(J+1) ,B(J+1)); end loop; if (not STOP) then B(0):= TEMP; SCREEN.P(ROW ,14 ,B(0)); end if; end loop; accept X; end INSERT_SORT; task body SHELL_SORT is B : STRING(0..5); TEMP : CHARACTER; I,J,STEP : INTEGER; STEPSIZE : array(1..4) OF INTEGER; STOP : BOOLEAN; ROW : INTEGER; STIME : FLOAT; begin B := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; accept S(r : in INTEGER; t : in FLOAT) do ROW := r; STIME := t; end S; for k in 0..5 loop SCREEN.P(ROW,14+k,B(k)); end loop; -- 'steps' contains decreasing increments for each -- pass. The last pass has increment 1. STEPSIZE(4) := 1; for PASS in reverse 1..3 loop STEPSIZE(PASS):= 2*STEPSIZE(PASS+1); end loop; delay STIME - CLOCK; for PASS in 1..4 loop STEP := STEPSIZE(PASS); -- Do a straight insertion sort with 'step' as -- an increment instead of 1. I:= STEP; while (I <= 5) loop TEMP := B(I); J:= I; STOP:= FALSE; while (J > STEP-1) and (STOP /= TRUE) loop J := J - STEP; if B(J) > TEMP then B(J+STEP):= B(J); SCREEN.P(ROW, 14+J, TEMP); else B(J+STEP):= TEMP; STOP:= TRUE; end if; SCREEN.P(ROW, 14+(J+STEP) ,B(J+STEP)); end loop; if (not STOP) then B(0):= TEMP; SCREEN.P(ROW, 14 ,B(0)); end if; I := I + STEP; end loop; end loop; -- for pass in 1..npass accept X; end SHELL_SORT; begin CURSORAT(3,1); PUT("Bubble:"); CURSORAT(5,1); PUT("Insertion:"); CURSORAT(7,1); PUT("Shell:"); STIME := CLOCK + 10.0; BUBBLE_SORT.S(3,STIME); INSERT_SORT.S(5,STIME); SHELL_SORT.S(7,STIME); BUBBLE_SORT.X; INSERT_SORT.X; SHELL_SORT.X; end RACEDead; ================================================ FILE: exm/not_working/roland_01.adb ================================================ -- Submitted by Roland Coghetto - thanks -- -- ** HAC Bug as of 21-Mar-2019: the BEGIN .. END block -- below (even without DECLARE) seems to corrupt the stack. -- See comments @ procedure Block_statement in HAC.Parser. with HAT; use HAT; procedure Roland_01 is a:integer:= 1234; begin put("a = "); put(a); new_line; put("[p1]"); declare aa: integer; -- := 1; begin put("[p2]"); new_line; put_line("BEGIN BLOC 1"); put("aa = "); -- put(aa); -- BUG new_line; put_line("END BLOC 1"); end; new_line; put_line("OUT 1"); put("a = "); put(a); new_line; put_line("OUT 2"); end Roland_01; ================================================ FILE: exm/pack_list.adb ================================================ -- Turn a list of integers (one per row), like -- ... -- 791 -- 690 -- 960 -- 939 -- 549 -- ... -- into a packed format with 10 items per line, separated by commas, like: -- ... -- 791, 690, 960, 939, 549, 855, 911, 933, 911, 945, -- 40 .. 49 -- 974, 755, 846, 762, 761, 571, 677, 763, 760, 759, -- 50 .. 59 -- 754, 494, 552, 537, 577, 692, 786, 788, 788, 790, -- 60 .. 69 -- ... with HAT; procedure Pack_List is use HAT; s : VString; f, g : File_Type; i : Natural := 0; x : Natural; begin Open (f, "list.txt"); Create (g, "packed_list.txt"); while not End_Of_File (f) loop Get (f, x); Put (g, x, 4); Put (g, ", "); i := i + 1; if i mod 10 = 0 then Put (g, " -- "); Put (g, i - 10, 3); Put (g, " .. "); Put (g, i - 1, 3); New_Line (g); end if; end loop; Close (f); Close (g); end Pack_List; ================================================ FILE: exm/pdf/hac_pdf_out.adb ================================================ package body HAC_PDF_Out is use HAT; procedure Set_A4_Portrait (r : out Rectangle) is begin r.x_min := 0.0; r.y_min := 0.0; r.width := 21.0 * one_cm; r.height := 29.7 * one_cm; end Set_A4_Portrait; procedure Set_A4_Landscape (r : out Rectangle) is begin r.x_min := 0.0; r.y_min := 0.0; r.width := 29.7 * one_cm; r.height := 21.0 * one_cm; end Set_A4_Landscape; procedure Init (pdf : in out PDF_Out_File) is A4_portrait : Rectangle; cm_2_5_margins : Margins_Type; begin Set_A4_Portrait (A4_portrait); -- cm_2_5_margins.left := cm_2_5; cm_2_5_margins.right := cm_2_5; cm_2_5_margins.top := cm_2_5; cm_2_5_margins.bottom := cm_2_5; -- pdf.is_created := False; pdf.is_closed := False; pdf.file_index := 1; pdf.file_name := Null_VString; pdf.format := PDF_1_3; pdf.zone := nowhere; pdf.text_switch := graphics; pdf.last_page := 0; pdf.current_line := 1; -- Mostly for Ada.Text_IO compatibility pdf.current_col := 1; -- Mostly for Ada.Text_IO compatibility pdf.page_box := A4_portrait; pdf.maximum_box := A4_portrait; pdf.page_margins := cm_2_5_margins; pdf.objects := 1; pdf.current_font := Helvetica; pdf.font_size := 11.0; pdf.line_spacing := 1.2; pdf.stream_obj_buf := Null_VString; pdf.ext_font_name := Null_VString; pdf.doc_title := Null_VString; pdf.doc_author := Null_VString; pdf.doc_subject := Null_VString; pdf.doc_keywords := Null_VString; pdf.doc_creator := Null_VString; end Init; procedure W (pdf : in out PDF_Out_File; s : VString) is begin HAT.Put (pdf.pdf_file, s); pdf.file_index := pdf.file_index + Length (s); end W; function NL return Character is begin return Character'Val (10); end NL; procedure WL (pdf : in out PDF_Out_File; s : VString) is begin W (pdf, s & NL); end WL; procedure No_Nowhere (pdf : in out PDF_Out_File) is begin if pdf.zone = nowhere then New_Page (pdf); end if; end No_Nowhere; -- Delayed output, for internal PDF's "stream" object procedure Wd (pdf : in out PDF_Out_File; s : VString) is begin No_Nowhere (pdf); pdf.stream_obj_buf := pdf.stream_obj_buf & s; end Wd; procedure WLd (pdf : in out PDF_Out_File; s : VString) is begin Wd (pdf, s & NL); end WLd; -- External stream index function Buffer_index (pdf : PDF_Out_File) return Natural is begin return pdf.file_index - pdf.start_index; end Buffer_index; function Img_I (p : Integer) return VString is begin return HAT.Image (p); end Img_I; function Img_R (x : Real) return VString is im : VString := HAT.Image (x); begin if Slice (im, 1, 2) = "0." then im := Slice (im, 2, Length (im)); elsif Slice (im, 1, 3) = "-0." then im := '-' & Slice (im, 3, Length (im)); end if; if im = ".0" then return +"0"; end if; if Slice (im, Length (im) - 1, Length (im)) = ".0" then return Slice (im, 1, Length (im) - 2); -- Return as integer end if; return im; end Img_R; -- function "+"(P1, P2 : Point) return Point is -- begin -- return (P1.x + P2.x, P1.y + P2.y); -- end "+"; -- -- function "*"(f : Real; P : Point) return Point is -- begin -- return (f * P.x, f * P.y); -- end "*"; -- -- function "+"(P : Point; r : Rectangle) return Rectangle is -- begin -- return (P.x + r.x_min, P.y + r.y_min, r.width, r.height); -- end "+"; -- -- function "*"(f : Real; r : Rectangle) return Rectangle is -- begin -- return (r.x_min, r.y_min, f * r.width, f * r.height); -- end "*"; function X_Max (r : Rectangle) return Real is begin return r.x_min + r.width; end X_Max; function Y_Max (r : Rectangle) return Real is begin return r.y_min + r.height; end Y_Max; type Abs_Rel_Mode is (absolute, relative); function Img_P (p : Point) return VString is begin return Img_R (p.x) & ' ' & Img_R (p.y); end Img_P; function Img_Rect (box : Rectangle; mode : Abs_Rel_Mode) return VString is begin case mode is when absolute => return Img_R (box.x_min) & ' ' & Img_R (box.y_min) & ' ' & Img_R (X_Max (box)) & ' ' & Img_R (Y_Max (box)) & ' '; when relative => return Img_R (box.x_min) & ' ' & Img_R (box.y_min) & ' ' & Img_R (box.width) & ' ' & Img_R (box.height) & ' '; end case; end Img_Rect; procedure New_fixed_index_object (pdf : in out PDF_Out_File; idx : PDF_Index_Type) is begin pdf.object_offset (idx) := Buffer_index (pdf); WL (pdf, Img_I (Integer (idx)) & " 0 obj"); end New_fixed_index_object; procedure New_object (pdf : in out PDF_Out_File) is begin pdf.objects := pdf.objects + 1; New_fixed_index_object (pdf, pdf.objects); end New_object; function producer return VString is begin return +"HAC_PDF_Out, a version of Ada PDF Writer (http://apdf.sf.net/), " & "stripped down for the HAC Ada Compiler language subset."; end producer; procedure Write_PDF_header (pdf : in out PDF_Out_File) is sig : String (1 .. 8); begin pdf.is_created := True; pdf.start_index := pdf.file_index; case pdf.format is when PDF_1_3 => WL (pdf, +"%PDF-1.3"); sig (1) := Character'Val (16#25#); sig (2) := Character'Val (16#C2#); sig (3) := Character'Val (16#A5#); sig (4) := Character'Val (16#C2#); sig (5) := Character'Val (16#B1#); sig (6) := Character'Val (16#C3#); sig (7) := Character'Val (16#AB#); sig (8) := Character'Val (10); W (pdf, +sig); end case; WL (pdf, "% -- Produced by " & producer); end Write_PDF_header; procedure New_substream (pdf : in out PDF_Out_File) is begin pdf.stream_obj_buf := Null_VString; end New_substream; procedure Finish_substream (pdf : in out PDF_Out_File) is begin WL (pdf, +" << /Length" & Integer'Image (Length (pdf.stream_obj_buf)) & " >>"); -- Length could be alternatively stored in next object, -- so we wouldn't need to buffer the stream - see 7.3.10, Example 3. -- But we prefer the buffered version, which could be compressed in a future version -- of this package. WL (pdf, +"stream"); WL (pdf, pdf.stream_obj_buf); WL (pdf, +"endstream"); end Finish_substream; -- Internal - test page for experimenting PDF constructs (and how Adobe Reader reacts to them) -- procedure Test_Page (pdf : in out PDF_Out_File) is begin WLd (pdf, +"10 10 200 200 re S"); -- rectangle, stroke WLd (pdf, +" BT"); -- Begin Text object (9.4). Text matrix and text line matrix:= I WLd (pdf, +" /Ada_PDF_Std_Font_Helvetica 24 Tf"); -- F1 font, 24 pt size (9.3 Text State Parameters and Operators) WLd (pdf, +" 0.5 0 0 rg"); -- red, nonstroking colour (Table 74) WLd (pdf, +" 0.25 G"); -- 25% gray stroking colour (Table 74) WLd (pdf, +" 2 Tr"); -- Tr: Set rendering mode as "Fill, then stroke text" (Table 106) WLd (pdf, +" 20 539 Td"); WLd (pdf, +" (Hello World !) Tj"); -- Tj: Show a text string (9.4.3 Text-Showing Operators) WLd (pdf, +" 16 TL"); -- TL: set text leading (distance between lines, 9.3.5) WLd (pdf, +" T*"); -- T*: Move to the start of the next line (9.4.2) WLd (pdf, +" 20 20 200 200 re S"); -- rectangle, stroke (within text region) WLd (pdf, +" /Ada_PDF_Std_Font_Helvetica-Oblique 12 Tf"); WLd (pdf, +" 0 Tr"); -- Tr: Set rendering mode as default: "Fill text" (Table 106) WLd (pdf, +" 0 g"); -- black (default) WLd (pdf, +" (Subtitle here.) Tj T*"); WLd (pdf, +" ET"); -- End Text WLd (pdf, +"30 30 200 200 re S"); -- rectangle, stroke WLd (pdf, +" BT"); WLd (pdf, +" 5 5 Td (Second text chunk here.) Tj T*"); WLd (pdf, +" ET"); WLd (pdf, +"40 40 240 240 re S"); -- rectangle, stroke WLd (pdf, +"15 15 Td (Text chunk not within BT/ET.) Tj"); end Test_Page; function test_page_mode return Boolean is begin return False; end test_page_mode; package Fonts is function Standard_Font_Name (f : Standard_Font_Type) return VString; -- Font dictionary name within a page -- function Font_Dictionary_Name (font_name : VString) return VString; -- Font dictionary name within a page, for standard fonts -- Example: /Ada_PDF_Std_Font_Courier-Oblique -- function Standard_Font_Dictionary_Name (f : Standard_Font_Type) return VString; -- Output font dictionary (resource for last page) -- procedure Font_Dictionary (pdf : in out PDF_Out_File); -- function Current_Font_Name (pdf : PDF_Out_File) return VString; function Current_Font_Dictionary_Name (pdf : PDF_Out_File) return VString; end Fonts; procedure Insert_PDF_Font_Selection_Code (pdf : in out PDF_Out_File) is begin Insert_Text_PDF_Code (pdf, Fonts.Current_Font_Dictionary_Name (pdf) & ' ' & Img_R (pdf.font_size) & " Tf " & -- Tf: 9.3 Text State Parameters and Operators Img_R (pdf.font_size * pdf.line_spacing) & " TL" -- TL: set text leading (9.3.5) ); end Insert_PDF_Font_Selection_Code; procedure Font (pdf : in out PDF_Out_File; f : Standard_Font_Type) is begin pdf.current_font := f; Insert_PDF_Font_Selection_Code (pdf); end Font; procedure Font_Size (pdf : in out PDF_Out_File; size : Real) is begin pdf.font_size := size; Insert_PDF_Font_Selection_Code (pdf); end Font_Size; procedure Line_Spacing (pdf : in out PDF_Out_File; factor : Real) is begin pdf.line_spacing := factor; Insert_PDF_Font_Selection_Code (pdf); end Line_Spacing; procedure Line_Spacing_Pt (pdf : in out PDF_Out_File; pt : Real) is begin pdf.line_spacing := pt / pdf.font_size; -- !! This assumes that the font size is in Point (pt) units. Insert_PDF_Font_Selection_Code (pdf); end Line_Spacing_Pt; procedure Begin_text (pdf : in out PDF_Out_File) is begin WLd (pdf, +" BT"); -- Begin Text object (9.4.1, Table 107) end Begin_text; procedure End_text (pdf : in out PDF_Out_File) is begin WLd (pdf, +" ET"); end End_text; procedure Flip_to (pdf : in out PDF_Out_File; new_state : Text_or_graphics) is begin No_Nowhere (pdf); -- WLd(pdf, " % Text_or_graphics before: " & pdf.text_switch'Image); if pdf.text_switch /= new_state then pdf.text_switch := new_state; case new_state is when text => Begin_text (pdf); when graphics => End_text (pdf); end case; end if; -- WLd(pdf, " % Text_or_graphics after: " & pdf.text_switch'Image); end Flip_to; function pages_idx return Integer is begin return 1; end pages_idx; procedure New_Page (pdf : in out PDF_Out_File) is begin if pdf.zone /= nowhere then Finish_Page (pdf); end if; pdf.last_page := pdf.last_page + 1; pdf.current_line := 1; pdf.current_col := 1; -- PDF_Out.Images.Clear_local_resource_flags (pdf); -- -- Page descriptor object: -- New_object (pdf); pdf.page_idx (pdf.last_page) := pdf.objects; -- Table 30 (7.7.3.3 Page Objects) for options WL (pdf, +" <>"); WL (pdf, +"endobj"); -- Page contents object: -- New_object (pdf); New_substream (pdf); if test_page_mode then Test_Page (pdf); else pdf.zone := in_page; Insert_PDF_Font_Selection_Code (pdf); pdf.zone := in_header; -- No dispatching in the HAC version -> no custom header! Page_Header (pdf); end if; pdf.zone := in_page; Text_XY (pdf, pdf.page_margins.left, Y_Max (pdf.page_box) - pdf.page_margins.top); end New_Page; procedure Finish_Page (pdf : in out PDF_Out_File) is -- appended_object_idx : PDF_Index_Type; begin if pdf.zone = nowhere then return; -- We are already "between pages" end if; if test_page_mode then null; -- Nothing to do anymore with test page else pdf.zone := in_footer; -- No dispatching in the HAC version -> no custom footer! Page_Footer (pdf); Flip_to (pdf, graphics); end if; pdf.zone := nowhere; Finish_substream (pdf); WL (pdf, +"endobj"); -- end of page contents. -- Resources Dictionary (7.8.3) for the page just finished: New_object (pdf); WL (pdf, +"<<"); -- Font resources: Fonts.Font_Dictionary (pdf); -- appended_object_idx := pdf.objects + 1; -- Images contents to be appended after this object -- Image resources: WL (pdf, +" /XObject <<"); -- Image_List (pdf); WL (pdf, +" >>"); WL (pdf, +">>"); WL (pdf, +"endobj"); -- end of Resources -- PDF_Out.Images.Insert_unloaded_local_images (pdf); end Finish_Page; procedure Put_Real (pdf : in out PDF_Out_File; num : in Real ) is begin Put_Str (pdf, Image (num)); end Put_Real; procedure Put_Int (pdf : in out PDF_Out_File; num : in Integer ) is begin Put_Str (pdf, Image (num)); end Put_Int; procedure Put_Str (pdf : in out PDF_Out_File; str : VString) is begin if test_page_mode then null; -- Nothing to do (test page instead) else Insert_Text_PDF_Code (pdf, '(' & str & ") Tj"); end if; end Put_Str; procedure Put_Line (pdf : in out PDF_Out_File; str : VString) is begin Put_Str (pdf, str); New_Line (pdf); end Put_Line; procedure New_Line (pdf : in out PDF_Out_File) is Spacing : constant := 1; begin pdf.current_line := pdf.current_line + 1; pdf.current_col := 1; if test_page_mode then null; -- Nothing to do (test page instead) else for i in 1 .. Spacing loop Insert_Text_PDF_Code (pdf, +"T*"); end loop; end if; end New_Line; procedure Text_XY (pdf : in out PDF_Out_File; x, y : Real) is begin Flip_to (pdf, text); -- The following explicit End_text, Begin_text are just -- for resetting the text matrices (hence, position and orientation). End_text (pdf); Begin_text (pdf); Insert_PDF_Code (pdf, Img_R (x) & ' ' & Img_R (y) & " Td"); -- Td: 9.4.2 Text-Positioning Operators pdf.current_line := 1; pdf.current_col := 1; end Text_XY; procedure Put_XY (pdf : in out PDF_Out_File; x, y : Real; str : VString) is begin Text_XY (pdf, x, y); Put_Str (pdf, str); end Put_XY; function Col (pdf : in PDF_Out_File) return Positive is begin return pdf.current_col; end Col; function Line (pdf : in PDF_Out_File) return Positive is begin return pdf.current_line; end Line; function Page (pdf : in PDF_Out_File) return Natural is begin return Natural (pdf.last_page); -- Issue if Integer is 16-bit and last_page > 2**15-1 end Page; procedure Color (pdf : in out PDF_Out_File; c : Color_Type) is begin Insert_PDF_Code (pdf, Img_R (c.red) & ' ' & Img_R (c.green) & ' ' & Img_R (c.blue) & " rg"); -- rg = nonstroking colour (Table 74) end Color; procedure Stroking_Color (pdf : in out PDF_Out_File; c : Color_Type) is begin Insert_PDF_Code (pdf, Img_R (c.red) & ' ' & Img_R (c.green) & ' ' & Img_R (c.blue) & " RG"); -- RG = nonstroking colour (Table 74) end Stroking_Color; procedure Text_Rendering_Mode (pdf : in out PDF_Out_File; r : Rendering_Mode) is begin Insert_Text_PDF_Code (pdf, Img_I (Integer (Rendering_Mode'Pos (r))) & " Tr"); -- Tr = Set rendering mode (Table 106) end Text_Rendering_Mode; function Image_name (i : Positive) return VString is begin return "/Ada_PDF_Img" & Img_I (i); end Image_name; -- procedure Image (pdf : in out PDF_Out_File; file_name : String; target : Rectangle) is -- image_index : Positive; -- Index in the list of images -- begin -- No_Nowhere (pdf); -- PDF_Out.Images.Image_ref (pdf, file_name, image_index); -- Insert_Graphics_PDF_Code (pdf, "q " & -- Img (target.width) & " 0 0 " & Img (target.height) & -- ' ' & Img (target.x_min) & ' ' & Img (target.y_min) & " cm " & -- cm: Table 57 -- Image_name (image_index) & " Do Q" -- ); -- end Image; -- -- function Get_pixel_dimensions (image_file_name : String) return Rectangle is -- begin -- return PDF_Out.Images.Get_pixel_dimensions (image_file_name); -- end Get_pixel_dimensions; ----------------------- -- Vector graphics -- ----------------------- procedure Line_Width (pdf : in out PDF_Out_File; width : Real) is begin Insert_Graphics_PDF_Code (pdf, Img_R (width) & " w"); end Line_Width; procedure Single_Line (pdf : in out PDF_Out_File; from, to : Point) is begin Insert_Graphics_PDF_Code (pdf, Img_R (from.x) & ' ' & Img_R (from.y) & " m " & Img_R (to.x) & ' ' & Img_R (to.y) & " l s" ); end Single_Line; -- Table 59 - Path Construction Operators (8.5.2) -- Table 60 - Path-Painting Operators (8.5.3.1) function inside_path_rule_char (r : Inside_path_rule) return Character is begin case r is when nonzero_winding_number => return ' '; when even_odd => return '*'; end case; end inside_path_rule_char; function path_drawing_operator (m : Path_Rendering_Mode) return Character is begin case m is when fill => return 'F'; when stroke => return 'S'; when fill_then_stroke => return 'B'; end case; end path_drawing_operator; procedure Draw (pdf : in out PDF_Out_File; what : Rectangle; rendering : Path_Rendering_Mode) is begin Insert_Graphics_PDF_Code (pdf, Img_Rect (what, relative) & " re " & path_drawing_operator (rendering)); end Draw; procedure Move (pdf : in out PDF_Out_File; to : Point) is begin Insert_Graphics_PDF_Code (pdf, Img_P (to) & " m"); -- m operator (Table 59) end Move; procedure Line_To (pdf : in out PDF_Out_File; to : Point) is begin Insert_Graphics_PDF_Code (pdf, Img_P (to) & " l"); end Line_To; procedure Cubic_Bezier (pdf : in out PDF_Out_File; control_1, control_2 : Point; to : Point) is begin Insert_Graphics_PDF_Code ( pdf, Img_P (control_1) & ' ' & Img_P (control_2) & ' ' & Img_P (to) & " c" ); end Cubic_Bezier; procedure Finish_Path ( pdf : in out PDF_Out_File; close_path : Boolean; rendering : Path_Rendering_Mode; -- fill, stroke, or both rule : Inside_path_rule ) is cmd : VString; begin cmd := +path_drawing_operator (rendering) & inside_path_rule_char (rule); if close_path then cmd := To_Lower (cmd); end if; -- Insert the s, S, f, f*, b, b*, B, B* of Table 60 - Path-Painting Operators (8.5.3.1) if cmd = "s*" or cmd = "S*" or cmd = "F " or cmd = "F*" then Insert_Graphics_PDF_Code (pdf, +"n"); -- End the path object without filling or stroking it. else Insert_Graphics_PDF_Code (pdf, cmd); end if; end Finish_Path; ----------------------------- -- Direct code insertion -- ----------------------------- procedure Insert_PDF_Code (pdf : in out PDF_Out_File; code : VString) is begin WLd (pdf, " " & code); -- Indentation is just cosmetic... end Insert_PDF_Code; procedure Insert_Text_PDF_Code (pdf : in out PDF_Out_File; code : VString) is begin Flip_to (pdf, text); Insert_PDF_Code (pdf, code); end Insert_Text_PDF_Code; procedure Insert_Graphics_PDF_Code (pdf : in out PDF_Out_File; code : VString) is begin Flip_to (pdf, graphics); Insert_PDF_Code (pdf, code); end Insert_Graphics_PDF_Code; -- Table 317 - Entries in the document information dictionary (14.3.3) procedure Title (pdf : in out PDF_Out_File; s : VString) is begin pdf.doc_title := s; end Title; procedure Author (pdf : in out PDF_Out_File; s : VString) is begin pdf.doc_author := s; end Author; procedure Subject (pdf : in out PDF_Out_File; s : VString) is begin pdf.doc_subject := s; end Subject; procedure Keywords (pdf : in out PDF_Out_File; s : VString) is begin pdf.doc_keywords := s; end Keywords; procedure Creator_Application (pdf : in out PDF_Out_File; s : VString) is begin pdf.doc_creator := s; end Creator_Application; procedure Page_Header (pdf : in out PDF_Out_File) is begin null; -- Default header is empty. end Page_Header; procedure Page_Footer (pdf : in out PDF_Out_File) is begin null; -- Default footer is empty. end Page_Footer; procedure Set_Left_Margin (pdf : out PDF_Out_File; pts : Real) is begin pdf.page_margins.left := pts; end Set_Left_Margin; function Get_Left_Margin (pdf : PDF_Out_File) return Real is begin return pdf.page_margins.left; end Get_Left_Margin; procedure Set_Right_Margin (pdf : out PDF_Out_File; pts : Real) is begin pdf.page_margins.right := pts; end Set_Right_Margin; function Get_Right_Margin (pdf : PDF_Out_File) return Real is begin return pdf.page_margins.right; end Get_Right_Margin; procedure Set_Top_Margin (pdf : out PDF_Out_File; pts : Real) is begin pdf.page_margins.top := pts; end Set_Top_Margin; function Get_Top_Margin (pdf : PDF_Out_File) return Real is begin return pdf.page_margins.top; end Get_Top_Margin; procedure Set_Bottom_Margin (pdf : out PDF_Out_File; pts : Real) is begin pdf.page_margins.bottom := pts; end Set_Bottom_Margin; function Get_Bottom_Margin (pdf : PDF_Out_File) return Real is begin return pdf.page_margins.bottom; end Get_Bottom_Margin; procedure Set_Margins (pdf : out PDF_Out_File; new_margins : Margins_Type) is begin pdf.page_margins := new_margins; end Set_Margins; procedure Get_Margins (pdf : PDF_Out_File; result : out Margins_Type) is begin result := pdf.page_margins; end Get_Margins; procedure Page_Setup (pdf : in out PDF_Out_File; layout : Rectangle) is mb_x_min, mb_y_min, mb_x_max, mb_y_max : Real; begin pdf.page_box := layout; mb_x_min := Min (pdf.maximum_box.x_min, layout.x_min); mb_y_min := Min (pdf.maximum_box.y_min, layout.y_min); mb_x_max := Max (X_Max (pdf.maximum_box), X_Max (layout)); mb_y_max := Max (Y_Max (pdf.maximum_box), Y_Max (layout)); -- pdf.maximum_box.x_min := mb_x_min; pdf.maximum_box.y_min := mb_y_min; pdf.maximum_box.width := mb_x_max - mb_x_min; pdf.maximum_box.height := mb_y_max - mb_y_min; end Page_Setup; procedure Layout (pdf : PDF_Out_File; result : out Rectangle) is begin result := pdf.page_box; end Layout; procedure Reset ( pdf : in out PDF_Out_File; PDF_format : PDF_type ) is begin Init (pdf); -- Check if we are trying to re-use a half-finished object (ouch!): -- if pdf.is_created and not pdf.is_closed then -- null; -- !! raise PDF_stream_not_closed; -- end if; pdf.format := PDF_format; -- Set a default title (replaced when procedure Title is called). -- In Adobe Reader, this content can be copied to the clipboard. pdf.doc_title := +"Document created with: " & producer; end Reset; procedure Finish (pdf : in out PDF_Out_File) is info_idx, cat_idx : PDF_Index_Type; procedure Info is begin New_object (pdf); info_idx := pdf.objects; WL (pdf, +" << /Producer (" & producer & ')'); WL (pdf, +" /Title (" & To_String (pdf.doc_title) & ')'); WL (pdf, +" /Author (" & To_String (pdf.doc_author) & ')'); WL (pdf, +" /Subject (" & To_String (pdf.doc_subject) & ')'); WL (pdf, +" /Keywords (" & To_String (pdf.doc_keywords) & ')'); WL (pdf, +" /Creator (" & To_String (pdf.doc_creator) & ')'); WL (pdf, +" >>"); WL (pdf, +"endobj"); end Info; procedure Pages_dictionary is begin New_fixed_index_object (pdf, pages_idx); WL (pdf, +" << /Type /Pages"); W (pdf, +" /Kids ["); for p in 1 .. pdf.last_page loop W (pdf, Img_I (pdf.page_idx (p)) & " 0 R "); end loop; WL (pdf, +"]"); if pdf.last_page > 0 then WL (pdf, " /Count " & Img_I (pdf.last_page)); end if; WL (pdf, " /MediaBox [" & Img_Rect (pdf.maximum_box, absolute) & ']' ); -- 7.7.3.3 Page Objects - MediaBox -- Boundaries of the physical medium on which the page shall be displayed or printed -- 7.7.3.4 Inheritance of Page Attributes -- Global page size, lower-left to upper-right, measured in points -- Bounding box of all pages WL (pdf, +" >>"); WL (pdf, +"endobj"); end Pages_dictionary; procedure Catalog_dictionary is begin New_object (pdf); cat_idx := pdf.objects; WL (pdf, +" << /Type /Catalog"); WL (pdf, +" /Pages " & Img_I (pages_idx) & " 0 R"); if pdf.last_page > 0 then -- Open the document on page 1, fit the -- entire page within the window (Table 151): WL (pdf, +" /OpenAction [" & Img_I (pdf.page_idx (1)) & " 0 R /Fit]"); end if; WL (pdf, +" >>"); WL (pdf, +"endobj"); end Catalog_dictionary; procedure Trailer is begin WL (pdf, +"trailer"); WL (pdf, +" << /Root " & Img_I (cat_idx) & " 0 R"); WL (pdf, +" /Size " & Img_I (pdf.objects + 1)); WL (pdf, +" /Info " & Img_I (info_idx) & " 0 R"); WL (pdf, +" >>"); end Trailer; xref_offset : Natural; procedure XRef is s10 : VString; begin xref_offset := Buffer_index (pdf); WL (pdf, +"xref"); WL (pdf, +"0 " & Img_I (pdf.objects + 1)); WL (pdf, +"0000000000 65535 f "); for i in 1 .. pdf.objects loop s10 := Image (pdf.object_offset (i)); while Length (s10) < 10 loop s10 := '0' & s10; end loop; WL (pdf, s10 & " 00000 n "); -- <-- the trailing space is needed! end loop; end XRef; begin if pdf.last_page = 0 then -- No page ? Then make quickly a blank page. New_Page (pdf); end if; Finish_Page (pdf); Info; Pages_dictionary; Catalog_dictionary; XRef; Trailer; WL (pdf, +"startxref"); -- offset of xref WL (pdf, Img_I (Integer (xref_offset))); WL (pdf, +"%%EOF"); -- PDF_Out.Images.Clear_image_directory (pdf); pdf.is_closed := True; end Finish; ---------------------- -- Output to a file -- ---------------------- procedure Create ( pdf : in out PDF_Out_File; file_name : VString ) is begin Reset (pdf, PDF_1_3); HAT.Create (pdf.pdf_file, file_name); pdf.file_name := file_name; Write_PDF_header (pdf); end Create; procedure Close (pdf : in out PDF_Out_File) is begin Finish (pdf); if pdf.file_name /= "nul" then -- Test needed for OA 7.2.2 (Close raises Use_Error) HAT.Close (pdf.pdf_file); end if; end Close; function Is_Open (pdf : in PDF_Out_File) return Boolean is begin return HAT.Is_Open (pdf.pdf_file); end Is_Open; function one_cm return Real is begin return 28.346456692913385826771653543307; end one_cm; -- = 72.0 / 2.54; function cm_2_5 return Real is begin return 70.866141732283464566929133858268; end cm_2_5; -- = one_cm * 2.5; function one_inch return Real is begin return 72.0; end one_inch; -- !! HAC Bug: presence of subpackage body is not checked ! package body Fonts is -- 9.6.2.2 Standard Type 1 Fonts (Standard 14 Fonts) function Standard_Font_Name (f : Standard_Font_Type) return VString is begin -- Code generation: see pw_work.xls, Fonts (Std) case f is when Courier => return +"Courier"; when Courier_Bold => return +"Courier-Bold"; when Courier_Bold_Oblique => return +"Courier-BoldOblique"; when Courier_Oblique => return +"Courier-Oblique"; when Helvetica => return +"Helvetica"; when Helvetica_Bold => return +"Helvetica-Bold"; when Helvetica_Bold_Oblique => return +"Helvetica-BoldOblique"; when Helvetica_Oblique => return +"Helvetica-Oblique"; when Symbol => return +"Symbol"; when Times_Bold => return +"Times-Bold"; when Times_Bold_Italic => return +"Times-BoldItalic"; when Times_Italic => return +"Times-Italic"; when Times_Roman => return +"Times-Roman"; when Zapf_Dingbats => return +"ZapfDingbats"; end case; end Standard_Font_Name; function Font_Dictionary_Name (font_name : VString) return VString is begin return "/Ada_PDF_Font_" & font_name; end Font_Dictionary_Name; function Standard_Font_Dictionary_Name (f : Standard_Font_Type) return VString is begin return "/Ada_PDF_Std_Font_" & Standard_Font_Name (f); end Standard_Font_Dictionary_Name; -- 7.8.3 Resource Dictionaries (any resources required by a page). -- Table 33: Font: A dictionary that maps resource names to font dictionaries. -- procedure Font_Dictionary (pdf : in out PDF_Out_File) is begin WL (pdf, +" /Font <<"); -- font dictionary for f in Standard_Font_Type loop WL (pdf, +" " & Standard_Font_Dictionary_Name (f) & " << /Type /Font /Subtype /Type1 /BaseFont /" & Standard_Font_Name (f) & -- 7.9.2.2 Text String Type: "PDFDocEncoding can encode all of -- the ISO Latin 1 character set and is documented in Annex D." -- PDFDocEncoding is recognized by the Chrome PDF viewer on Windows but... -- *isn't* by Adobe Reader X, on Windows! So we resort to another ISO -- Latin 1 superset: WinAnsiEncoding = Windows Code Page 1252 (Table D.1). " /Encoding /WinAnsiEncoding " & " >>" ); end loop; WL (pdf, +" >>"); end Font_Dictionary; function Current_Font_Dictionary_Name (pdf : PDF_Out_File) return VString is begin if pdf.current_font in Standard_Font_Type then return Standard_Font_Dictionary_Name (pdf.current_font); else return Font_Dictionary_Name (pdf.ext_font_name); end if; end Current_Font_Dictionary_Name; end Fonts; end HAC_PDF_Out; ================================================ FILE: exm/pdf/hac_pdf_out.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC_PDF_OUT - A low level package for writing Adobe Acrobat PDF (*) files. -- -- HAC_PDF_OUT is a stripped-down version of PDF_OUT ( http://apdf.sf.net/ ) -- for successful compilation with HAC (HAC Ada Compiler) v.0.1. -- -- Elements of PDF_OUT removed in HAC_PDF_OUT are: -- -- - Object-oriented type extension (tagged type for PDF stream). -- PDF Files are the only supported PDF streams. -- - Object.method notation -- - Default values in records, replaced by explicit initialization. -- - Inclusion of raster images. -- - User-defined exceptions (PDF_stream_not_created, ...). -- - User-defined operators ("+", ...). -- - Indefinite page table and offset table. -- ------------------------------------------------------------------------------------- -- Legal licensing note: -- Copyright (c) 2014 .. 2022 Gautier de Montmollin -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- The above copyright notice and this permission notice shall be included in -- all copies or substantial portions of the Software. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- NB: this is the MIT License, as found 12-Sep-2007 on the site -- http://www.opensource.org/licenses/mit-license.php -- (*) All Trademarks mentioned are properties of their respective owners. ------------------------------------------------------------------------------------- -- -- Follow these steps to create a PDF document stream: -- -- 1. Create -- -- 2. | Put(pdf, data), -- | New_Line(pdf), ... : other "Text_IO"-like (full list below) -- | Image(pdf, ...) : raster images [disabled for the HAC version] -- | Move/Line/... : vector graphics -- | New_Page(pdf) -- -- 3. Close -- -- 4. (PDF_Out_String only) function Contents returns the full .pdf -- -- Header and footer are set up by overriding the corresponding methods. -- -- Note: the standard PDF measurement unit is a "point", set as 1/72 inch. -- -- All technical references are to PDF 1.7 format, ISO 32000-1:2008 standard -- http://www.adobe.com/devnet/pdf/pdf_reference.html -- -------------------------------------------------------------------------- with HAT; package HAC_PDF_Out is type PDF_type is ( PDF_1_3 -- PDF 1.3 ); subtype Real is HAT.Real; type Point is record x, y : Real; end record; -- procedure Add (P1, P2 : Point; result : out Point); -- -- procedure Scale_Point (f : Real; P : Point; result : out Point); type Rectangle is record x_min, y_min, width, height : Real; end record; -- procedure Translate (P : Point; r : Rectangle; result : out Rectangle); -- -- -- Scaling. r.x_min and r.y_min are preserved. -- procedure Scale_Rectangle (f : Real; r : Rectangle; result : out Rectangle); function X_Max (r : Rectangle) return Real; function Y_Max (r : Rectangle) return Real; subtype PDF_Index_Type is Integer; subtype Offset_Index_Type is PDF_Index_Type range 1 .. 1000; type Offset_table is array (Offset_Index_Type) of Natural; subtype Page_Index_Type is PDF_Index_Type range 1 .. 1000; type Page_table is array (Page_Index_Type) of PDF_Index_Type; -- object ID's of pages type Page_zone is (nowhere, in_page, in_header, in_footer); type Text_or_graphics is (text, graphics); type Margins_Type is record left, right, top, bottom : Real; end record; type Font_Type is ( -- The 14 standard fonts Courier, Courier_Bold, Courier_Bold_Oblique, Courier_Oblique, Helvetica, Helvetica_Bold, Helvetica_Bold_Oblique, Helvetica_Oblique, Symbol, Times_Bold, Times_Bold_Italic, Times_Italic, Times_Roman, Zapf_Dingbats, -- Fonts imported into the PDF document External_Font ); subtype Standard_Font_Type is Font_Type range Courier .. Zapf_Dingbats; -- !! Should be private (in a future version of HAC) type PDF_Out_File is record pdf_file : HAT.File_Type; file_index : Natural; file_name : HAT.VString; start_index : Natural; is_created : Boolean; is_closed : Boolean; format : PDF_type; zone : Page_zone; text_switch : Text_or_graphics; last_page : PDF_Index_Type; current_line : Positive; current_col : Positive; page_idx : Page_table; page_box : Rectangle; maximum_box : Rectangle; page_margins : Margins_Type; objects : PDF_Index_Type; object_offset : Offset_table; stream_obj_buf : HAT.VString; current_font : Font_Type; font_size : Real; line_spacing : Real; ext_font_name : HAT.VString; doc_title : HAT.VString; -- Document information (14.3.3) doc_author : HAT.VString; -- Document information (14.3.3) doc_subject : HAT.VString; -- Document information (14.3.3) doc_keywords : HAT.VString; -- Document information (14.3.3) doc_creator : HAT.VString; -- Document information (14.3.3) : creator application end record; procedure Init (pdf : in out PDF_Out_File); ---------------------------- -- (2) Document contents: -- ---------------------------- procedure Put_Real (pdf : in out PDF_Out_File; num : in Real ); procedure Put_Int (pdf : in out PDF_Out_File; num : in Integer ); procedure Put_Str (pdf : in out PDF_Out_File; str : HAT.VString); -- procedure Put_Line (pdf : in out PDF_Out_File; str : HAT.VString); -- procedure New_Line (pdf : in out PDF_Out_File); procedure New_Page (pdf : in out PDF_Out_File); -- Call to Finish_Page is optional, but can be necessary in some circumstances, -- for instance for displaying the footer correctly before changing page -- orientation or margins for the following pages. procedure Finish_Page (pdf : in out PDF_Out_File); -- procedure Text_XY (pdf : in out PDF_Out_File; x, y : Real); procedure Put_XY (pdf : in out PDF_Out_File; x, y : Real; str : HAT.VString); function Col (pdf : in PDF_Out_File) return Positive; function Line (pdf : in PDF_Out_File) return Positive; function Page (pdf : in PDF_Out_File) return Natural; -- Select one of the Adobe PDF standard fonts. -- The encoding is on 8 bits and follows the "Windows Code Page 1252" -- encoding (called WinAnsiEncoding in the PDF standard). -- See Annex D, especially "Table D.1 - Latin-text encodings" for details. procedure Font (pdf : in out PDF_Out_File; f : Standard_Font_Type); -- Set the font size. -- In general the size is a scale factor (see Table 105, Tf operator). -- For standard fonts the unit seems to be the Point (pt). procedure Font_Size (pdf : in out PDF_Out_File; size : Real); procedure Line_Spacing (pdf : in out PDF_Out_File; factor : Real); -- as multiple of font size procedure Line_Spacing_Pt (pdf : in out PDF_Out_File; pt : Real); -- in Point (pt) units -------------- -- Colors -- -------------- -- 0.0 = minimum intensity -- 1.0 = maximum intensity. subtype Color_Value is Real; -- range 0.0 .. 1.0; type Color_Type is record red, green, blue : Color_Value; end record; procedure Color (pdf : in out PDF_Out_File; c : Color_Type); procedure Stroking_Color (pdf : in out PDF_Out_File; c : Color_Type); type Rendering_Mode is ( fill, stroke, fill_then_stroke, invisible, -- Same, but also add text to path for clipping. fill_and_add_to_path, stroke_and_add_to_path, fill_then_stroke_and_add_to_path, add_to_path ); procedure Text_Rendering_Mode (pdf : in out PDF_Out_File; r : Rendering_Mode); ----------------------- -- Vector graphics -- ----------------------- procedure Line_Width (pdf : in out PDF_Out_File; width : Real); -- Draw a single line segment: procedure Single_Line (pdf : in out PDF_Out_File; from, to : Point); subtype Path_Rendering_Mode is Rendering_Mode range fill .. fill_then_stroke; -- Draw simple figures. -- Rectangle: procedure Draw (pdf : in out PDF_Out_File; what : Rectangle; rendering : Path_Rendering_Mode); -- Paths: type Inside_path_rule is (nonzero_winding_number, even_odd); -- Rule to determine how to fill areas within a (non-trivial) path. -- See 8.5.3.3.2 and 8.5.3.3.3 of PDF specification procedure Move (pdf : in out PDF_Out_File; to : Point); procedure Line_To (pdf : in out PDF_Out_File; to : Point); procedure Cubic_Bezier (pdf : in out PDF_Out_File; control_1, control_2 : Point; to : Point); -- All lines and curves and the eventual filling inside the path -- will be drawn when path is completed, with Finish_Path: procedure Finish_Path ( pdf : in out PDF_Out_File; close_path : Boolean; rendering : Path_Rendering_Mode; -- fill, stroke, or both rule : Inside_path_rule ); ------------ -- Misc -- ------------ -- In the likely case some PDF feature is not yet implemented in -- this package, you can insert direct PDF code - at your own risk ;-). -- -- NB: the state the PDF machine is either in text-writing -- mode, or graphics mode. To make outputs compliant with the PDF -- standard, if you want to insert graphics code, please -- use the Insert_Graphics_PDF_Code below. For text-related stuff, -- use Insert_Text_PDF_Code. -- procedure Insert_PDF_Code (pdf : in out PDF_Out_File; code : HAT.VString); -- This is for direct text PDF code insertion (text-writing mode -- will be switched on). In PDF language these are the T... commands. -- procedure Insert_Text_PDF_Code (pdf : in out PDF_Out_File; code : HAT.VString); -- This is for direct graphics PDF code insertion (text-writing mode -- will be switched off for the graphics output). -- procedure Insert_Graphics_PDF_Code (pdf : in out PDF_Out_File; code : HAT.VString); -- Document information procedure Title (pdf : in out PDF_Out_File; s : HAT.VString); procedure Author (pdf : in out PDF_Out_File; s : HAT.VString); procedure Subject (pdf : in out PDF_Out_File; s : HAT.VString); procedure Keywords (pdf : in out PDF_Out_File; s : HAT.VString); procedure Creator_Application (pdf : in out PDF_Out_File; s : HAT.VString); ------------------ -- Page layout -- ------------------ -- You need to override the Header and Footer methods -- for setting up your custom header and footer. By default they do nothing. procedure Page_Header (pdf : in out PDF_Out_File); procedure Page_Footer (pdf : in out PDF_Out_File); -- They have to be called before New_Page in order to influence the next page. -- For the first page, call them before any output (typically right after Create). -- procedure Set_Left_Margin (pdf : out PDF_Out_File; pts : Real); function Get_Left_Margin (pdf : PDF_Out_File) return Real; procedure Set_Right_Margin (pdf : out PDF_Out_File; pts : Real); function Get_Right_Margin (pdf : PDF_Out_File) return Real; procedure Set_Top_Margin (pdf : out PDF_Out_File; pts : Real); function Get_Top_Margin (pdf : PDF_Out_File) return Real; procedure Set_Bottom_Margin (pdf : out PDF_Out_File; pts : Real); function Get_Bottom_Margin (pdf : PDF_Out_File) return Real; -- Some distances in Points function one_cm return Real; function cm_2_5 return Real; function one_inch return Real; procedure Set_Margins (pdf : out PDF_Out_File; new_margins : Margins_Type); procedure Get_Margins (pdf : PDF_Out_File; result : out Margins_Type); procedure Set_A4_Portrait (r : out Rectangle); procedure Set_A4_Landscape (r : out Rectangle); procedure Page_Setup (pdf : in out PDF_Out_File; layout : Rectangle); procedure Layout (pdf : PDF_Out_File; result : out Rectangle); procedure Create ( pdf : in out PDF_Out_File; file_name : HAT.VString ); procedure Close (pdf : in out PDF_Out_File); function Is_Open (pdf : in PDF_Out_File) return Boolean; private function Image_name (i : Positive) return HAT.VString; procedure New_object (pdf : in out PDF_Out_File); procedure WL (pdf : in out PDF_Out_File; s : HAT.VString); end HAC_PDF_Out; ================================================ FILE: exm/pdf/hilbert_curve.adb ================================================ -- https://rosettacode.org/wiki/Hilbert_curve#Ada -- Author: Jesper Quorning -- -- This version is adapted to HAC's Ada subset. with HAT; with HAC_PDF_Out; procedure Hilbert_Curve is use HAT, HAC_PDF_Out; Page_Length : constant := 500.0; Corner_X : constant := 50.0; Corner_Y : constant := 300.0; type Rule_Type is (A, B, C, D); PDF : HAC_PDF_Out.PDF_Out_File; First : Boolean; procedure Hilbert (Order : in Natural; Rule : in Rule_Type; Length : in HAC_PDF_Out.Real; X, Y : in HAC_PDF_Out.Real) is L : constant HAC_PDF_Out.Real := Length / 4.0; P : Point; begin if Order = 0 then P.x := Corner_X + X; P.y := Corner_Y + Y; if First then First := False; Move (PDF, P); else Line_To (PDF, P); end if; else case Rule is when A => Hilbert (Order - 1, D, 2.0 * L, X - L, Y + L); Hilbert (Order - 1, A, 2.0 * L, X - L, Y - L); Hilbert (Order - 1, A, 2.0 * L, X + L, Y - L); Hilbert (Order - 1, B, 2.0 * L, X + L, Y + L); when B => Hilbert (Order - 1, C, 2.0 * L, X + L, Y - L); Hilbert (Order - 1, B, 2.0 * L, X - L, Y - L); Hilbert (Order - 1, B, 2.0 * L, X - L, Y + L); Hilbert (Order - 1, A, 2.0 * L, X + L, Y + L); when C => Hilbert (Order - 1, B, 2.0 * L, X + L, Y - L); Hilbert (Order - 1, C, 2.0 * L, X + L, Y + L); Hilbert (Order - 1, C, 2.0 * L, X - L, Y + L); Hilbert (Order - 1, D, 2.0 * L, X - L, Y - L); when D => Hilbert (Order - 1, A, 2.0 * L, X - L, Y + L); Hilbert (Order - 1, D, 2.0 * L, X + L, Y + L); Hilbert (Order - 1, D, 2.0 * L, X + L, Y - L); Hilbert (Order - 1, C, 2.0 * L, X - L, Y - L); end case; end if; end Hilbert; procedure Hilbert_Page (Order : Natural; Color : Color_Type) is begin First := True; Stroking_Color (PDF, Color); Hilbert (Order, A, Page_Length, Page_Length / 2.0, Page_Length / 2.0); Finish_Path (PDF, False, stroke, nonzero_winding_number); end Hilbert_Page; a4p, back : Rectangle; black, violet, green : Color_Type; begin HAC_PDF_Out.Create (PDF, +"hilbert-curve.pdf"); Set_A4_Portrait (a4p); Page_Setup (PDF, a4p); black.red := 0.0; black.green := 0.0; black.blue := 0.0; violet.red := 0.9; violet.green := 0.1; violet.blue := 0.8; green.red := 0.0; green.green := 0.9; green.blue := 0.0; for depth in reverse 1 .. 7 loop Color (PDF, black); back.x_min := Corner_X; back.y_min := Corner_Y; back.width := Page_Length; back.height := Page_Length; Draw (PDF, back, fill); if depth = 7 then Line_Width (PDF, 1.0); else Line_Width (PDF, 2.0); end if; Hilbert_Page (depth, violet); Hilbert_Page (depth - 1, green); if depth > 1 then New_Page (PDF); end if; end loop; HAC_PDF_Out.Close (PDF); end Hilbert_Curve; ================================================ FILE: exm/pdf/koch_curve.adb ================================================ -- http://www.rosettacode.org/wiki/Koch_curve#Ada -- Author: Jesper Quorning -- -- This version is adapted to HAC's Ada subset. with HAC_PDF_Out; with HAT; procedure Koch_Curve is use HAC_PDF_Out, HAT; subtype My_Real is HAC_PDF_Out.Real; subtype Angle_Deg is My_Real; subtype Level_Type is Integer range 0 .. 7; Vertex_Length : constant := 400.0; Purple : Color_Type; Corner : Point; procedure Draw_Image (Level : Level_Type) is Current : Point; Direction : Angle_Deg := 60.0; Doc : PDF_Out_File; My_Layout : Rectangle; My_Margins : Margins_Type; Deg_To_Rad : constant := 0.01745329251994329576923690768489; -- Pi / 180 procedure Koch (Level : Level_Type; Vertex_Length : My_Real) is Move, Abs_Point : Point; begin if Level = 0 then Move.x := Vertex_Length * Sin (Direction * Deg_To_Rad); Move.y := Vertex_Length * Cos (Direction * Deg_To_Rad); Current.x := Current.x + Move.x; Current.y := Current.y + Move.y; Abs_Point.x := Corner.x + Current.x; Abs_Point.y := Corner.y + Current.y; Line_To (Doc, Abs_Point); else Koch (Level - 1, Vertex_Length / 3.0); Direction := Direction - 60.0; Koch (Level - 1, Vertex_Length / 3.0); Direction := Direction + 120.0; Koch (Level - 1, Vertex_Length / 3.0); Direction := Direction - 60.0; Koch (Level - 1, Vertex_Length / 3.0); end if; end Koch; begin Current.x := 0.0; Current.y := 0.0; -- Create (Doc, +"koch_" & Character'Val (Character'Pos ('0') + Level) & ".pdf"); Creator_Application (Doc, +"Koch_Curve"); Title (Doc, +"Koch snowflake curve drawn with HAC_PDF_Out"); Author (Doc, +"Niels Fabian Helge von Koch"); Subject (Doc, +"Koch snowflake curve with recursion level" & Level_Type'Image (Level)); Keywords (Doc, +"Koch, snowflake, curve, fractal"); Set_A4_portrait (My_Layout); Page_Setup (Doc, My_Layout); My_Margins.left := cm_2_5; My_Margins.right := one_cm; My_Margins.top := one_cm; My_Margins.bottom := one_cm; Set_Margins (Doc, My_Margins); Color (Doc, Purple); Move (Doc, Corner); for Count in 1 .. 3 loop Koch (Level, Vertex_Length); Direction := Direction + 120.0; end loop; Finish_Path (Doc, True, fill, even_odd); Close (Doc); end Draw_Image; begin Purple.red := 0.35; Purple.green := 0.0; Purple.blue := 0.25; -- Corner.x := 90.0; Corner.y := 580.0; -- for Level in Level_Type loop Draw_Image (Level); end loop; end Koch_Curve; ================================================ FILE: exm/pdf/pdf_hello.adb ================================================ with HAC_PDF_Out; with HAT; procedure PDF_Hello is use HAC_PDF_Out, HAT; pdf : PDF_Out_File; c1, c2, black : Color_Type; begin Create (pdf, +"hello.pdf"); Creator_Application (pdf, +"PDF_Hello"); Keywords (pdf, +"Hello, World, HAC, PDF"); Put_Line (pdf, +"Hello world !"); New_Line (pdf); Put_Line (pdf, +"This PDF document was created by..."); Font (pdf, Helvetica); Text_Rendering_Mode (pdf, fill_then_stroke); -- The following can be done in a more compact way with -- a "full Ada" compiler: pdf.Stroking_Color ((0.0, 0.3, 0.1)); c1.red := 0.0; c1.green := 0.3; c1.blue := 0.1; Stroking_Color (pdf, c1); c2.red := 0.1; c2.green := 0.5; c2.blue := 0.2; Color (pdf, c2); Font_Size (pdf, 36.0); New_Line (pdf); Put_Line (pdf, +"HAC"); Font_Size (pdf, 18.0); Put_Line (pdf, +"HAC Ada Compiler"); Close (pdf); end PDF_Hello; ================================================ FILE: exm/pdf/peano_curve.adb ================================================ -- https://rosettacode.org/wiki/Peano_curve#Ada -- Author: Jesper Quorning -- -- This version is adapted to HAC's Ada subset. with HAT; with HAC_PDF_Out; procedure Peano_Curve is use HAT, HAC_PDF_Out; Filename : constant String (1 .. 15) := "peano-curve.pdf"; Scale : constant := 2.1; Line_W : constant := 2.5; Corner_X : constant := 150.0; Corner_Y : constant := 50.0; Background : Color_Type; Frame : Rectangle; PDF : PDF_Out_File; type Coord is record X, Y : Natural; end record; procedure Transform (left, right : Coord; scale_right : Natural; result : out Coord) is begin result.X := left.X + scale_right * right.X; result.Y := left.Y + scale_right * right.Y; end Transform; procedure Peano (Pos : Coord; Length : Positive; I1, I2 : Integer) is len : constant Integer := Length / 3; pt, new_pos : Coord; pdf_pt : Point; begin if Length = 1 then pdf_pt.x := Corner_X + Scale * (HAC_PDF_Out.Real (3 * Pos.X)); pdf_pt.y := Corner_Y + Scale * (HAC_PDF_Out.Real (3 * Pos.Y)); Line_To (PDF, pdf_pt); else pt.X := 2 * I1; pt.Y := 2 * I1; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, I1, I2); pt.X := I1 - I2 + 1; pt.Y := I1 + I2; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, I1, 1 - I2); pt.X := 1; pt.Y := 1; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, I1, 1 - I2); pt.X := I1 + I2; pt.Y := I1 - I2 + 1; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, 1 - I1, 1 - I2); pt.X := 2 * I2; pt.Y := 2 - 2 * I2; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, I1, I2); pt.X := 1 + I2 - I1; pt.Y := 2 - I1 - I2; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, I1, I2); pt.X := 2 - 2 * I1; pt.Y := 2 - 2 * I1; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, I1, I2); pt.X := 2 - I1 - I2; pt.Y := 1 + I2 - I1; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, 1 - I1, I2); pt.X := 2 - 2 * I2; pt.Y := 2 * I2; Transform (Pos, pt, len, new_pos); Peano (new_pos, len, 1 - I1, I2); end if; end Peano; procedure Draw_Peano (order : Natural) is black : Color_Type; pt : Coord; pdf_pt : Point; begin black.red := 0.0; black.green := 0.0; black.blue := 0.0; Stroking_Color (PDF, black); Line_Width (PDF, Line_W); pdf_pt.x := Corner_X; pdf_pt.y := Corner_Y; Move (PDF, pdf_pt); pt.X := 0; pt.Y := 0; Peano (pt, 3**order, 0, 0); Finish_Path (PDF, False, stroke, nonzero_winding_number); end Draw_Peano; a4p : Rectangle; begin Background.red := 0.827; Background.green := 0.816; Background.blue := 0.016; Frame.x_min := 10.0; Frame.y_min := 10.0; Frame.width := 820.0; Frame.height := 575.0; HAC_PDF_Out.Create (PDF, +Filename); Set_A4_Landscape (a4p); Page_Setup (PDF, a4p); for order in reverse 1 .. 4 loop Color (PDF, Background); Draw (PDF, Frame, fill); Draw_Peano (order); if order > 1 then New_Page (PDF); end if; end loop; HAC_PDF_Out.Close (PDF); end Peano_Curve; ================================================ FILE: exm/permutations.adb ================================================ -- Show all permutations of a certain range. with HAT; procedure Permutations is subtype Some_Range is Integer range 1 .. 4; x : array (Some_Range) of Some_Range; procedure Fill (from : Some_Range) is ok : Boolean; use HAT; begin for value in Some_Range loop ok := True; for i in 1 .. from - 1 loop ok := ok and then not (x (i) = value); end loop; if ok then x (from) := value; if from = Some_Range'Last then for i in Some_Range loop Put (Image (x (i))); end loop; New_Line; else Fill (from + 1); end if; end if; end loop; end; begin Fill (1); end Permutations; ================================================ FILE: exm/pkg_1.adb ================================================ package body Pkg_1 is ------------------------------------------------- -- Sub-packages defined only in Pkg_1's body -- ------------------------------------------------- package Sub_Pkg_3 is end Sub_Pkg_3; package Sub_Pkg_4 is function F return Integer; -- package Spec_which_doesnt_need_any_body is subtype Ha is Integer; end Spec_which_doesnt_need_any_body; -- -- package Spec_which_needs_a_body_1 is -- procedure Ho_1; -- end Spec_which_needs_a_body_1; -- -- !! HAC bug: doesn't check for missing body !! end Sub_Pkg_4; type Some_Useless_Type is record useless_1 : Integer; useless_2 : VS; -- Defined in the spec useless_3 : PA; -- Defined in the spec, private part end record; package body Sub_Pkg_4 is package Spec_which_needs_a_body_2 is procedure Ho2; end Spec_which_needs_a_body_2; package body Spec_which_needs_a_body_2 is procedure Ho2 is begin HAT.Put ("[Ho2] "); end Ho2; end Spec_which_needs_a_body_2; -- !! HAC bug: doesn't check for missing body !! function F return Integer is variable_local_to_F : Some_Useless_Type; begin Spec_which_needs_a_body_2.Ho2; variable_local_to_F.useless_3 := PA'Last; return 656 + variable_local_to_F.useless_3; -- Should be 666. end F; end Sub_Pkg_4; ------------------- -- Other stuff -- ------------------- procedure Proc_in_body; procedure Proc_in_body is begin null; end Proc_in_body; procedure Proc_1 (par_1 : Integer; par_2 : out HAT.Real) is x, y : PB; package Inner_pkg is use HAT; procedure Ho_ho_ho; public_message : constant VString := +"This is public"; private private_message : constant VString := +"Ho ho "; end Inner_pkg; some_garbage_1 : Integer; package body Inner_pkg is use HAT; body_message : constant VString := +"ho!"; procedure Ho_ho_ho is begin x.field_2 := private_message & body_message; end Ho_ho_ho; end Inner_pkg; some_garbage_2 : Integer; use Inner_pkg; use HAT; begin Inner_pkg.Ho_ho_ho; Ho_ho_ho; y := x; Put_Line (y.field_2); -- Put_Line (Inner_pkg.body_message); -- Compilation should fail if uncommented. -- Put_Line (Inner_pkg.private_message); -- Compilation should fail if uncommented. Put_Line (public_message); par_2 := Real (Sub_Pkg_4.F) + 0.123456; end Proc_1; ------------------------------------------------- -- Sub-packages defined only in Pkg_1's spec -- ------------------------------------------------- package body Sub_Pkg_2 is procedure Proc_2 (message : VString) is use HAT; -- !! Should not be necessary (clause already in spec) begin Put_Line ("Hello from Sub_Pkg_2.Proc_2: " & message); end Proc_2; end Sub_Pkg_2; end Pkg_1; ================================================ FILE: exm/pkg_1.ads ================================================ with HAT; package Pkg_1 is subtype A is Integer; subtype B0 is A; subtype B is Pkg_1.A; subtype C is B range 0 .. 1000; package Sub_Pkg_1 is subtype D is C range 1 .. 100; end Sub_Pkg_1; subtype E is Sub_Pkg_1.D range 2 .. 10; procedure Proc_1 (par_1 : Integer; par_2 : out HAT.Real); package Sub_Pkg_2 is use HAT; procedure Proc_2 (message : VString); end Sub_Pkg_2; subtype VS is HAT.VString; private subtype PA is E; type PB is record field_1 : PA; field_2 : HAT.VString; end record; end Pkg_1; ================================================ FILE: exm/pkg_2.ads ================================================ with Pkg_1; package Pkg_2 is subtype F is Pkg_1.E; use Pkg_1.Sub_Pkg_1; subtype G is D range 22 .. 99; end Pkg_2; ================================================ FILE: exm/pkg_demo.adb ================================================ -- Demo of many library-level packages. -- Minimum HAC version: HAC 0.0999 10-Apr-2022. -- -- HAC and GNAT figure out all the source files -- that are needed for the build. -- -- The X* packages are generated by Pkg_Demo_Gen (file pkg_demo_gen.adb). -- -- X_Pkg_Test_S depends on X_Pkg_Test_S1, X_Pkg_Test_S2, ... -- X_Pkg_Test_S1 depends on X_Pkg_Test_S11, X_Pkg_Test_S12, ... -- ... with HAT; with X_Pkg_Demo_S, -- Dependencies always declared in specs X_Pkg_Demo_M, -- Dependencies declared in specs or bodies (randomly) X_Pkg_Demo_B; -- Dependencies always declared in bodies procedure Pkg_Demo is use HAT; procedure Failure (Msg : VString) is begin Put_Line (+"Failure in test: [" & Msg & ']'); Set_Exit_Status (1); -- Compiler test failed. end Failure; procedure Assert (Msg : VString; Check : in Boolean) is -- Similar to RM 11.4.2 but without raising an exception. begin if not Check then Failure (Msg & ", assertion"); end if; end Assert; begin if Argument_Count = 0 then Put_Line (+"Specs: " & X_Pkg_Demo_S.Do_it); Put_Line (+"Mixed: " & X_Pkg_Demo_M.Do_it); Put_Line (+"Bodies: " & X_Pkg_Demo_B.Do_it); else Assert (+"Specs", X_Pkg_Demo_S.Do_it = "[S][S1][S11][S12][S13][S2][S21][S22][S23][S3][S31][S32][S33]"); Assert (+"Mixed", X_Pkg_Demo_M.Do_it = "[M][M1][M11][M12][M13][M2][M21][M22][M23][M3][M31][M32][M33]"); Assert (+"Bodies", X_Pkg_Demo_B.Do_it = "[B][B1][B11][B12][B13][B2][B21][B22][B23][B3][B31][B32][B33]"); end if; end Pkg_Demo; ================================================ FILE: exm/pkg_demo_gen.adb ================================================ -- Testing library-level packages. -- Pkg_Demo_Gen creates the packages for Pkg_Demo. -- -- The command `hac pkg_demo_gen.adb delete` will -- delete those packages. with HAT; procedure Pkg_Demo_Gen is -- This type controls the location of WITH's in -- packages further in the dependency tree. -- type Test_Mode is (all_in_spec, mixed, all_in_bodies); use HAT; max_depth : constant := 2; children : constant := 3; procedure Generate (prefix : VString; depth : Natural; mode : Test_Mode) is f : File_Type; name : constant VString := "X_Pkg_Demo_" & prefix; file_name : constant VString := To_Lower (name); subtype Child_Range is Integer range 1 .. children; with_in_spec : array (Child_Range) of Boolean; begin if Argument_Count > 0 and then Argument (1) = "delete" then Delete_File (file_name & ".adb"); Delete_File (file_name & ".ads"); else for child in Child_Range loop case mode is when all_in_spec => with_in_spec (child) := True; when mixed => with_in_spec (child) := Rnd > 0.5; when all_in_bodies => with_in_spec (child) := False; end case; end loop; -- for is_body in Boolean loop if is_body then Create (f, file_name & ".adb"); else Create (f, file_name & ".ads"); end if; Put_Line (f, "-- File generated by Pkg_Demo_Gen. This is needed for Pkg_Demo."); Put_Line (f, "--"); if depth < max_depth then New_Line (f); for child in Child_Range loop if is_body xor with_in_spec (child) then Put_Line (f, "with " & name & Image (child) & ';'); end if; end loop; end if; if not is_body then New_Line (f); Put_Line (f, "with HAT; use HAT;"); end if; New_Line (f); Put (f, "package "); if is_body then Put (f, "body "); end if; Put_Line (f, name & " is"); New_Line (f); Put (f, " function Do_it return VString"); if is_body then Put_Line (f, " is"); Put_Line (f, " begin"); Put_Line (f, " return +""[" & prefix & "]"""); if depth < max_depth then -- Now the funny part... for child in Child_Range loop Put_Line (f, " & " & name & Image (child) & ".Do_it"); end loop; end if; Put_Line (f, " ;"); Put_Line (f, " end Do_it;"); else Put_Line (f, ';'); end if; New_Line (f); Put_Line (f, "end " & name & ';'); Close (f); -- end loop; end if; if depth < max_depth then -- Now the funny part... for child in Child_Range loop Generate (prefix & Image (child), depth + 1, mode); end loop; end if; end Generate; abbr : array (Test_Mode) of Character; begin abbr (all_in_spec) := 'S'; abbr (mixed) := 'M'; abbr (all_in_bodies) := 'B'; for mode in Test_Mode loop Generate (+abbr (mode), 0, mode); end loop; end Pkg_Demo_Gen; ================================================ FILE: exm/prc.adb ================================================ -- Demo of modularity with packages. with HAT; with Pkg_1, Pkg_2; with Cross_A, Cross_B; procedure Prc is x : Pkg_1.A; use Pkg_1; y : B; z : Pkg_1.E; t : constant Pkg_2.G := Pkg_2.G'Last; r : HAT.Real; use HAT; package Local_Namespace is procedure Hi; -- package Loc_SubPkg_1 is abc : Integer; end Loc_SubPkg_1; -- package Loc_SubPkg_1b is abc : Integer; end Loc_SubPkg_1b; -- package Loc_SubPkg_2 is procedure Jedi_2; end Loc_SubPkg_2; -- end Local_Namespace; package body Local_Namespace is -- procedure Hi is begin Put_Line ("Hi!"); end Hi; -- package body Loc_SubPkg_1 is -- Superfluous, but admitted as local package. -- For library level it would be rejected: Ada RM 7.2 (4)) end Loc_SubPkg_1; -- -- Loc_SubPkg_3 (spec & body) is fully -- contained in Loc_SubPkg_1's body! -- package Loc_SubPkg_3 is procedure Jedi_3; end Loc_SubPkg_3; -- package body Loc_SubPkg_3 is -- !! HAC bug: doesn't check for missing body !! procedure Jedi_3 is begin Put ("[Jedi 3] "); end Jedi_3; end Loc_SubPkg_3; -- package body Loc_SubPkg_2 is procedure Jedi_2 is begin Loc_SubPkg_3.Jedi_3; Put ("[Jedi 2] "); end Jedi_2; end Loc_SubPkg_2; -- end Local_Namespace; procedure Hi_Hi is use Local_Namespace; begin Loc_SubPkg_2.Jedi_2; Hi; end Hi_Hi; procedure Hi_Hi_2 is use Local_Namespace; use Loc_SubPkg_2; begin Jedi_2; Hi; end Hi_Hi_2; begin x := 0; y := 0; z := 2; Put (t, 0); New_Line; Proc_1 (x, r); Put (r, 0, 7, 0); New_Line; Sub_Pkg_2.Proc_2 (+"Hey man"); Cross_A.A (5); Cross_B.B (5); -- Local_Namespace.Loc_SubPkg_2.Jedi_2; Local_Namespace.Hi; Hi_Hi; Hi_Hi_2; end Prc; ================================================ FILE: exm/random.adb ================================================ -- Pseudo-Random Generation: Rand (discrete) and Rnd (continuous) with HAT; procedure Random is use HAT; procedure Discrete (iterations : Integer) is faces : constant := 6; histogram : array (1 .. faces) of Integer; r, t : Integer; begin for f in 1 .. faces loop histogram (f) := 0; end loop; for it in 1 .. iterations loop r := 1 + Rand (5); histogram (r) := histogram (r) + 1; end loop; -- Any error should be detected by range checks. t := 0; for f in 1 .. faces loop t := t + histogram (f); end loop; if t /= iterations then Put_Line (+"*** ERROR: total = " & t); Skip_Line; end if; for f in 1 .. faces loop Put (+" Dice face " & f & ':'); Put (Real (histogram (f)) / Real (iterations), 2, 5, 0); Put_Line (+", #occurences: " & histogram (f)); end loop; end Discrete; procedure Continuous (iterations : Integer) is in_disc : Integer := 0; begin for it in 1 .. iterations loop if Rnd ** 2 + Rnd ** 2 <= 1.0 then in_disc := in_disc + 1; end if; end loop; Put (" Monte-Carlo estimation of pi: "); Put_Line (4.0 * Real (in_disc) / Real (iterations)); end Continuous; it : Integer; begin for dec in 3 .. 7 loop Put_Line (+"======= Iterations: 10 ** " & dec); it := 10 ** dec; Discrete (it); Continuous (it); end loop; end Random; ================================================ FILE: exm/record_code_gen.adb ================================================ -- Code generation example for Ada records with HAT; procedure Record_Code_Gen is use HAT; type Typ is (ints, floats); type Field is (a, b); -- function Typ_Of (f : Field) return Typ is begin case f is when a => return ints; when b => return floats; end case; end Typ_Of; -- f_ada : File_Type; t : Typ; begin -- Write a simple Ada record: Create (f_ada, "$_simple_ada_record_snippet.ads"); Put_Line (f_ada, " type T1 is record"); for f in Field loop t := Typ_Of (f); Put_Line (f_ada, To_Lower (+" " & f'Image & " : " & t'Image & ';')); end loop; Put_Line (f_ada, " end record;"); Close (f_ada); -- -- Here, other forms: C header, records in records vs. -- flat representation, record of arrays, conversion functions -- for the records, ... end Record_Code_Gen; ================================================ FILE: exm/remarks.adb ================================================ -- Remarks (warnings and notes) emitted by the HAC compiler. -- -- Command sample: -- -- for HAC: hac -c -rkruv remarks.adb -- for GNAT: gcc -c -gnatwkruv remarks.adb with Interfaces; procedure Remarks is use Interfaces; use Interfaces; -- Note: "use" clause already applied (...) [-rr] a : Integer; -- Note: variable "a" is not referenced [-ru] type B is (x, y); -- Note: type "B" is not referenced [-ru] procedure C is null; -- Note: procedure "C" is not referenced [-ru] d : Integer := 123; -- Note: variable "d" is not referenced [-ru] -- Note: variable "d" is not modified, could be declared constant [-rk] e : Integer; -- Note: variable "e" is never read [-ru] f : Integer := 123; -- Note: variable "f" is never read [-ru] g : Integer := 123; -- Note: variable "g" is not modified, could be declared constant [-rk] h : Integer; -- Warning: variable "h" is read but never written [-rv] type A0 is (x0, y0); -- Note: item "y0" is not referenced [-ru] b0 : A0 := x0; -- Note: variable "b0" is not referenced [-ru] -- Note: variable "b0" is not modified, could be declared constant [-rk] procedure Missing_Read_Writes -- Note: procedure "Missing_Read_Writes" is not referenced [-ru] (a1 : in Integer; -- Note: parameter "a1" is not referenced [-ru] b1 : in out Integer; -- Note: parameter "b1" is not referenced [-ru] c1 : out Integer; -- Warning: parameter "c1" is never written [-rv] -- Note: parameter "c1" is not referenced [-ru] d1 : out Integer; -- Warning: parameter "d1" is read but never written [-rv] e1 : out Integer) -- `e1` is written -> compiler is happy. is begin if d1 = 5 then null; end if; -- Warning: parameter "d1" is read but not written at this point [-rv] if e1 = 5 then null; end if; -- Warning: parameter "e1" is read but not written at this point [-rv] e1 := 2; end Missing_Read_Writes; procedure OK_Read_Writes -- Note: procedure "OK_Read_Writes" is not referenced [-ru] (a2 : in Integer; b2 : in out Integer; -- Note: parameter "b2" is not referenced [-ru] c2 : out Integer) is begin c2 := a2; -- `c2` is written, `a2` is read, so the compiler is happy about `a2` and `c2`. end OK_Read_Writes; function Useless return Integer is -- Note: function "Useless" is not referenced [-ru] begin return 5; end Useless; -- Example appeared @ -- https://www.reddit.com/r/ada/comments/1ezm9d6/the_variable_may_not_be_initialized/ type Array_Of_Naturals is array (1 .. 5) of Natural; function Max_Array (A : Array_Of_Naturals) return Natural is Max : Natural; begin for I in A'Range loop if A (I) > Max then -- Warning: variable "Max" is read before it is ever written [-rv] Max := A (I); end if; end loop; return Max; end Max_Array; function Max_Array_2 (A : Array_Of_Naturals) return Natural is Max_2 : Natural; Further_Iteration : Boolean := False; begin for I in A'Range loop if Further_Iteration then if A (I) > Max_2 then -- Warning: variable "Max_2" may be read before it is ever written [-rv] -- -- ^ The warning is softer than for Max: when there is a condition -- within a loop, we are not sure this is the first iteration. -- Then, we cannot be sure that Max_2 is not initialized. -- In this example, Max_2 is actually initialized on the first iteration. Max_2 := A (I); end if; else Max_2 := 0; Further_Iteration := True; end if; end loop; return Max_2; end Max_Array_2; procedure Tom (Condition : Boolean; J : out Integer) is I : Integer; begin if Condition then J := I; -- Warning: variable "I" is read but not written at this point [-rv] end if; end Tom; procedure Cases is type ABC is (a, b, c); x : constant ABC := a; begin case x is when a => null; when b => null; when c => null; when others => null; -- Note: "when others" is redundant here: all values are already explicitly covered [-rr] end case; end; begin e := 0; f := g + h; -- Warning: variable "h" is read but not written at this point [-rv] Cases; end Remarks; ================================================ FILE: exm/series.adb ================================================ with HAT; procedure Series is use HAT; max_x : constant := 30; sum : Real := 0.0; x : constant Real := 0.8; begin Put_Line (+"x = " & x); Put_Line (+"sum: 1 + x + x^2 + ... + x^n:"); for n in 0 .. max_x loop sum := sum + x ** n; Put_Line (+"n = " & n & "; sum = " & sum); end loop; Put_Line (+"n -> infinity; sum = " & 1.0 / (1.0 - x)); end Series; ================================================ FILE: exm/shell.adb ================================================ with HAT; use HAT; procedure Shell is type OS_Kind is (Nixux, Windoze); k : OS_Kind; r : Integer; f : File_Type; -- procedure Pipe_Test (with_result, with_output : Boolean) is line, contents : VString; out_name : constant VString := +"output.lst"; secret_command : constant VString := +"echo This is the ultra-secret message for testing I/O pipe"; piped_secret_command : constant VString := secret_command & '>' & out_name; begin Put ("Testing outward pipe (command>something). With result parameter: "); Put (with_result); Put (". With output parameter: "); Put (with_output); Put_Line ("."); if with_output then if with_result then Shell_Execute (secret_command, r, contents); else Shell_Execute (secret_command, contents); end if; Put_Line (+" --> Contents output VString are: [" & contents & ']'); else if with_result then Shell_Execute (piped_secret_command, r); else Shell_Execute (piped_secret_command); end if; Put (+" --> Contents of file " & out_name & " are: ["); Open (f, out_name); while not End_Of_File (f) loop Get_Line (f, line); Put_Line (line); end loop; Close (f); Put_Line (']'); end if; if with_result and r /= 0 then Put_Line (+"Result of echo command is not 0: " & r); end if; New_Line; end Pipe_Test; -- procedure Produce_Errors (command : VString) is begin Shell_Execute (command, r); Put_Line ( +"Result of command """ & command & """ should be not 0. Returned value is: " & r ); if k = Nixux then -- WEXITSTATUS Put_Line (+" POSIX: filtered exit code is: " & r / 256 mod 256); end if; New_Line; end Produce_Errors; begin if Index (Get_Env ("OS"), "Windows") > 0 then k := Windoze; else k := Nixux; end if; -- Set_Env ("HAC_Rules", "Good Day, Ladies and Gentlemen!"); -- case k is when Nixux => Shell_Execute ("echo The env. var. is set... [$HAC_Rules]", r); when Windoze => Shell_Execute ("echo The env. var. is set... [%HAC_Rules%]", r); end case; if r /= 0 then Put_Line (+"Result of echo command is not 0: " & r); end if; -- for w_res in Boolean loop for w_out in Boolean loop Pipe_Test (w_res, w_out); end loop; end loop; Produce_Errors (+"Command_Impossible"); Produce_Errors (+"exit 123"); end Shell; ================================================ FILE: exm/shell_sort.adb ================================================ with HAT; -- SmallAda: CS159-10 - FAll/1990 - Arthur Vargas Lopes procedure Shell_Sort is use HAT; procedure Shell is b : String (1 .. 26); i, j, step : Integer; step_size : array (1 .. 4) of Integer; stop : Boolean; temp : Character; begin b := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; Put_Line ("Shell Sort"); New_Line; Put_Line ("String at start:"); Put_Line ("----------------"); Put_Line (b); New_Line; -- Put_Line(B); -- 'steps' contains decreasing increments for each -- pass. The last pass has increment 1. step_size (4) := 1; for pass in reverse 1 .. 3 loop step_size (pass) := 2 * step_size (pass + 1); end loop; for pass in 1 .. 4 loop -- cursorat(14,45); Put ("Pass: "); Put (pass); New_Line; step := step_size (pass); Put ("Step: "); Put (step); New_Line; -- Do a straight insertion sort with 'step' as -- an increment instead of 1. i := step + 1; while i <= 26 loop -- cursorat(15,45); New_Line; Put ("I: "); Put (i); New_Line; temp := b (i); j := i; stop := False; while j > step and not stop loop j := j - step; -- cursorat(16,45); put("J: "); put(J); if b (j) > temp then b (j + step) := b (j); -- cursorat(15,14+j); Put (temp); else b (j + step) := temp; stop := True; end if; -- CursorAt(15,14+(j+step)); Put(b(j+step)); end loop; if not stop then b (1) := temp; -- CursorAt(15,14+0); Put (temp); end if; i := i + step; end loop; New_Line; end loop; -- for pass in 1..npass New_Line; Put_Line ("Result of Shell Sort:"); Put_Line ("---------------------"); Put_Line (b); end Shell; begin Shell; -- New_Line; -- PUT("Press enter to proceed..."); -- GET(ch); end Shell_Sort; ================================================ FILE: exm/strings_demo.adb ================================================ with HAT; use HAT; procedure Strings_demo is s1, s2, s4, s4_s4 : VString; -- n : constant := 10; type Str_Vector is array (1 .. n) of VString; type Bi_Vector is record A, B : Str_Vector; end record; -- procedure A_to_B (BV : in out Bi_Vector) is begin BV.B := BV.A; end A_to_B; -- procedure Reverso (SV : in out Str_Vector) is SV2 : Str_Vector; begin for i in 1 .. n loop SV2 (n - i + 1) := SV (i); end loop; SV := SV2; end Reverso; -- procedure Show (SV : in Str_Vector) is begin for i in 1 .. n loop Put_Line (SV (i)); end loop; end Show; -- procedure Slice_Show (v : VString) is l : constant Integer := Length (v); c : Character; row : VString; begin for i in reverse 1 .. l loop Put_Line (Slice (v, 1, i)); end loop; -- for i in 1 .. l loop Put ((i - 1) * ' '); Put_Line (Slice (v, i, l)); end loop; -- for i in 1 .. l loop row := +""; for j in 1 .. l loop if i = j then c := Element (v, i); elsif abs (i - j) = 1 then c := ' '; else c := '_'; end if; row := row & c; end loop; Put_Line (row); end loop; end Slice_Show; -- procedure Up_Low (v : VString) is row : VString; c : Character; begin Put_Line (v); New_Line; Put_Line (To_Upper (v)); Put_Line (To_Lower (v)); New_Line; for i in 1 .. Length (v) loop row := +""; for j in 1 .. Length (v) loop c := Element (v, j); if i = j then row := row & To_Upper (c); else row := row & To_Lower (c); end if; end loop; Put_Line (row); end loop; end Up_Low; s3 : constant VString := +" world"; ZZ : Bi_Vector; padded : VString; Str3 : constant String (6 .. 8) := "But"; v_char : VString; begin s2 := +"Hello"; -- Convert from literal string, copy to s2. v_char := +'.'; -- Convert from Character s1 := s2; -- Copy VString to VString s4 := s1 & s3; -- Concatenation VString & VString Put_Line (5 * (s1 & ' ')); -- Multiplication, and Concatenation with Character for i in 1 .. 4 loop Put (v_char & s1); end loop; New_Line; padded := +" " & '"' & s1 & """ "; New_Line; Put_Line ("->" & padded & "<- original"); Put_Line ("->" & Trim_Left (padded) & "<- Trim_Left"); Put_Line ("->" & Trim_Right (padded) & "<- Trim_Right"); Put_Line ("->" & Trim_Both (padded) & "<- Trim_Both"); s4 := "---> """ & s4 & '"'; Put_Line (s4); Put_Line (">> " & s4 & ' ' & '!' & " <<"); s4 := +"abc" & 'd' & "ef"; -- for i in 1 .. n loop ZZ.A (i) := +""; for j in 1 .. n loop if j = i then ZZ.A (i) := ZZ.A (i) & '*'; else ZZ.A (i) := ZZ.A (i) & '.'; end if; end loop; end loop; -- A_to_B (ZZ); -- Show (ZZ.B); Reverso (ZZ.B); Show (ZZ.B); -- Slice_Show (+"What's happening to this string?!"); Up_Low (+"Upside Down"); -- Put_Line (+" [" & (-123) & "] [" & 123 & "] [" & Real (Pi) & ']'); Put_Line (123 & (+" & Right VString")); Put_Line (Real (-456.0) & (+" & Right VString")); Put_Line (Real (-456.0e9) & (+" & Right VString")); Put_Line (Real (456.0e11) & (+" & Right VString")); Put_Line (Real (456.0e66) & (+" & Right VString")); Put_Line (Real (456.789e13) & (+" & Right VString")); Put_Line (Real (4.56789e13) & (+" & Right VString")); Put_Line (Real (4.56789e14) & (+" & Right VString")); Put_Line (Real (4.56789e15) & (+" & Right VString")); Put_Line (Real (1.79769313486232E+307) & (+" & Right VString")); Put_Line ("Integer: Image... " & Image (456789)); Put_Line ("Real: Image... " & Image (Real (456789.0))); Put_Line ("Real: Image... " & Image (Real (4.56789e10))); Put_Line ("Real: Image attribute..." & Real'Image (4.56789e10)); Put_Line (Float_Value (+"456.789e13")); -- Ada.Text_IO display of the Real number Put_Line (Integer_Value (+"456")); -- Ada.Text_IO display of the Integer number Put (Str3); Put ("! "); s1 := +Str3; Put_Line (s1 & "!!"); Put ("Heads: "); for i in 1 .. 10 loop Put (Head (+"Head...", i)); end loop; New_Line; Put ("Tails: "); for i in 1 .. 10 loop Put (Tail (+"...Tail", i)); end loop; New_Line (2); Put_Line ("----------- Strings_demo: That's all folks, the show is over! -----------"); New_Line (3); Put_Line ('.'); -- -- Quick tests. More systematic tests can be found in: test/strings.adb -- if s2 /= To_VString ("Hello") then -- `To_VString ("Hello")` and `+"Hello"` are identical function calls. Put ("Ooops?"); end if; if +Str3 /= To_VString (Str3) then -- `To_VString (s3)` and `+s3` are identical function calls. Put ("Ooops?"); end if; if +'x' /= To_VString ('x') then -- `To_VString ('x')` and `+'x'` are identical function calls. Put ("Ooops?"); end if; if s4 /= +"abcdef" then -- Comparison VString to VString Put ("Ooops?"); end if; if s4 /= "abcdef" then -- Comparison VString to String_Literal Put ("Ooops?"); end if; if Length (s4) /= 6 then Put ("Ooops?"); end if; s4_s4 := s4 & s4; -- abcdefabcdef -- 123456789012 if Index (s4_s4, +"cd") /= 3 or Index (s4_s4, "cd") /= 3 or Index (s4_s4, 'c') /= 3 then Put ("[Index] Ooops?"); end if; if Index (s4_s4, +"cd", 4) /= 9 or Index (s4_s4, "cd", 4) /= 9 or Index (s4_s4, 'c', 4) /= 9 then Put ("[Index, From] Ooops?"); end if; if Index_Backward (s4_s4, +"cd") /= 9 or Index_Backward (s4_s4, "cd") /= 9 or Index_Backward (s4_s4, 'c') /= 9 then Put ("[Index_Backward] Ooops?"); end if; if Index_Backward (s4_s4, +"cd", 8) /= 3 or Index_Backward (s4_s4, "cd", 8) /= 3 or Index_Backward (s4_s4, 'c', 8) /= 3 then Put ("[Index_Backward, From] Ooops?"); end if; -- if Starts_With (+"package", 'q') then Put ("Ooops?"); end if; if Starts_With (+"package", "proc") then Put ("Ooops?"); end if; if Starts_With (+"package", +"proc") then Put ("Ooops?"); end if; if not Starts_With (+"package", "pack") then Put ("Ooops?"); end if; if not Starts_With (+"package", +"pack") then Put ("Ooops?"); end if; -- if Ends_With (+"package", 'f') then Put ("Ooops?"); end if; if Ends_With (+"package", "proc") then Put ("Ooops?"); end if; if Ends_With (+"package", +"proc") then Put ("Ooops?"); end if; if not Ends_With (+"package", "age") then Put ("Ooops?"); end if; if not Ends_With (+"package", +"age") then Put ("Ooops?"); end if; end Strings_demo; ================================================ FILE: exm/sudoku_sample.adb ================================================ with Sudokus; with HAT; procedure Sudoku_Sample is use Sudokus; grand_total : Technique_Count; procedure Solve_from_Strings (s : Sudo_Strings; name : HAT.VString; verbosity_level : Natural) is p : Sudo_Pack; h : Sudo_Help; begin Convert_Data (s, p, h); Solve (p, h, name, verbosity_level); Cumulate (grand_total, p.total); end Solve_from_Strings; easy, less_easy, hard, very_hard, hidden_double_1, hidden_triple_1 : Sudo_Strings; use HAT; begin Put_Line ("Increase parameter `verbosity_level` for getting more details about " & "the Sudoku resolution."); New_Line; Zero (grand_total); -- Spotting only naked singles is sufficient on this one. easy (1) := +"1 83 57"; easy (2) := +"9 27 "; easy (3) := +" 5 34 "; easy (4) := +"5 7 8 "; easy (5) := +"4 9 1 5"; easy (6) := +" 1 5 6"; easy (7) := +" 57 8 "; easy (8) := +" 87 4"; easy (9) := +"24 16 9"; Solve_from_Strings (easy, +"Easy 1 ", 1); -- One round needs to spot only hidden singles; -- the rest is solved by handling naked singles. easy (1) := +"1459 2 8"; easy (2) := +" 3 5 91"; easy (3) := +"2 3 7"; easy (4) := +" 2 1 6"; easy (5) := +" 6 "; easy (6) := +"4 1 8 "; easy (7) := +"3 4 2"; easy (8) := +"65 1 7 "; easy (9) := +"9 4 7513"; Solve_from_Strings (easy, +"Easy 2 ", 1); -- One round needs to spot doubles on rows. less_easy (1) := +"7 8 4 3"; less_easy (2) := +" 8 9 "; less_easy (3) := +" 7 8 2"; less_easy (4) := +" 7941"; less_easy (5) := +" "; less_easy (6) := +"1745 "; less_easy (7) := +"9 6 3 "; less_easy (8) := +" 4 6 "; less_easy (9) := +"8 4 5 9"; Solve_from_Strings (less_easy, +"Less easy 1a ", 1); -- Same puzzle, but first row is filled a bit more... -- No multiple spotting is needed for solving it. less_easy (1) := +"7 8 4 53"; Solve_from_Strings (less_easy, +"Less easy 1b ", 1); less_easy (1) := +" 8 2 "; less_easy (2) := +"4 7 536 "; less_easy (3) := +" 6 4 "; less_easy (4) := +" 49 2"; less_easy (5) := +"2 7"; less_easy (6) := +"7 59 "; less_easy (7) := +" 6 9 "; less_easy (8) := +" 547 3 1"; less_easy (9) := +" 1 4 "; Solve_from_Strings (less_easy, +"Less easy 2 ", 1); less_easy (1) := +"8 9 "; less_easy (2) := +" 5 18 "; less_easy (3) := +" 236"; less_easy (4) := +" 7 31 "; less_easy (5) := +" 1 4 "; less_easy (6) := +" 74 9 "; less_easy (7) := +"729 "; less_easy (8) := +" 64 8 "; less_easy (9) := +" 6 7"; Solve_from_Strings (less_easy, +"Less easy 3 ", 1); -- This one has a {13} {13} hidden -- double on first row at round 6. less_easy (1) := +" 7 2 6"; less_easy (2) := +" 9 16 4"; less_easy (3) := +"5 3 7"; less_easy (4) := +" 4 "; less_easy (5) := +"9 6 1 8"; less_easy (6) := +" 3 "; less_easy (7) := +"6 7 1"; less_easy (8) := +"7 58 4 "; less_easy (9) := +"2 9 7 "; Solve_from_Strings (less_easy, +"Less easy 4 ", 1); less_easy (1) := +"6 1 "; less_easy (2) := +" 869 2 "; less_easy (3) := +" 23 5 "; less_easy (4) := +"3 9 "; less_easy (5) := +"8 7 3"; less_easy (6) := +" 1 8"; less_easy (7) := +" 7 18 "; less_easy (8) := +" 4 862 "; less_easy (9) := +" 5 6"; Solve_from_Strings (less_easy, +"Less easy 5 ", 1); less_easy (1) := +"1 4 7 9 "; less_easy (2) := +"3 8 51 "; less_easy (3) := +" 6 "; less_easy (4) := +"4 6 3 "; less_easy (5) := +"7 1"; less_easy (6) := +" 3 4 7"; less_easy (7) := +" 1 "; less_easy (8) := +" 38 5 4"; less_easy (9) := +" 7 5 9 8"; Solve_from_Strings (less_easy, +"Less easy 6 ", 1); -- This one is tricky near the end. less_easy (1) := +"81 5 4 72"; less_easy (2) := +" 1 7 48"; less_easy (3) := +" 8 3195"; less_easy (4) := +"298741563"; less_easy (5) := +" 239481"; less_easy (6) := +"1 685927"; less_easy (7) := +"981376254"; less_easy (8) := +" 2 958716"; less_easy (9) := +"576412839"; Solve_from_Strings (less_easy, +"Less easy 7 ", 1); -- https://www.youtube.com/watch?v=8dNHOyzH-gc hard (1) := +" 2 5"; hard (2) := +" 4 7 1"; hard (3) := +" 3 "; hard (4) := +" 7 2 9 "; hard (5) := +"4 3 "; hard (6) := +" 6 8"; hard (7) := +" 56 1 "; hard (8) := +" 3 7 2"; hard (9) := +"9 8 "; Solve_from_Strings (hard, +"Hard 1 ", 1); -- https://www.youtube.com/watch?v=9LiOg4BnmVU hard (1) := +"56 1 3 "; hard (2) := +"9 2 6 "; hard (3) := +" 1 2"; hard (4) := +" 36 7 9"; hard (5) := +" 8 4"; hard (6) := +" 5 "; hard (7) := +" 3 "; hard (8) := +" 4 "; hard (9) := +" 27 6 13"; Solve_from_Strings (hard, +"Hard 2 ", 1); -- https://www.youtube.com/watch?v=4GVyBiFUNws hard (1) := +" 8 2 56 "; hard (2) := +" 1 7"; hard (3) := +" "; hard (4) := +" 5 9 4 8"; hard (5) := +" 78 3"; hard (6) := +" 9 1 5 "; hard (7) := +"2 4 8 "; hard (8) := +" 6 85 "; hard (9) := +" 2 1 "; Solve_from_Strings (hard, +"Hard 3 ", 1); -- This one is tricky due to locked cells that -- are well hidden to the human. In that case, -- it is about the digit 4 on last row, that -- can be only within the bottom, center box. -- Then 4 can't be in any cell of that box that -- isn't on the last row. hard (1) := +"1 76 2 "; hard (2) := +"2 5 3 4 "; hard (3) := +"3 9 2"; hard (4) := +" 4 2 5 "; hard (5) := +"87 264"; hard (6) := +"52 8 7 "; hard (7) := +" 2 7"; hard (8) := +" 2 7 1 "; hard (9) := +"7 8325"; Solve_from_Strings (hard, +"Hard 4 ", 1); hidden_double_1 (1) := +" 6 "; -- {47} {47}: hidden double hidden_double_1 (2) := +" 42736"; -- in the first two cells hidden_double_1 (3) := +" 673 4 "; hidden_double_1 (4) := +" 94 68"; hidden_double_1 (5) := +" 964 7"; hidden_double_1 (6) := +"6 7 5 923"; hidden_double_1 (7) := +"1 85"; hidden_double_1 (8) := +" 6 8 271"; hidden_double_1 (9) := +" 5 1 94"; Solve_from_Strings (hidden_double_1, +"Hidden double 1", 1); hidden_triple_1 (1) := +"9 7 "; hidden_triple_1 (2) := +" 34 5 "; hidden_triple_1 (3) := +" 7 3 1 "; hidden_triple_1 (4) := +"3 94 "; hidden_triple_1 (5) := +"2 8 6 3"; hidden_triple_1 (6) := +" 83 9"; hidden_triple_1 (7) := +" 1 8 2 "; hidden_triple_1 (8) := +" 4 36 "; hidden_triple_1 (9) := +" 7 5"; Solve_from_Strings (hidden_triple_1, +"Hidden triple 1", 1); -- https://www.youtube.com/watch?v=T4OdkQMmyu8 -- Stalls at round 7, equivalent to t = 7:37 -- From comment at t= 8:30: "a computer has -- to go on a brute force way". very_hard (1) := +" 8 1 7"; very_hard (2) := +" 5 26"; very_hard (3) := +" 27 4 3"; very_hard (4) := +" 1 4"; very_hard (5) := +"1 "; very_hard (6) := +" 42 "; very_hard (7) := +" 6 8"; very_hard (8) := +"7 1 3 "; very_hard (9) := +" 54 9 "; Solve_from_Strings (very_hard, +"Very hard 1 ", 1); Show_Total (grand_total, +"Techniques used for all puzzles:"); end Sudoku_Sample; ================================================ FILE: exm/sudokus.adb ================================================ package body Sudokus is function Count (s : Sudoset) return Natural is res : Natural := 0; begin for i in Sudigit loop if s (i) then res := res + 1; end if; end loop; return res; end Count; function Count_Solved (u : Grid) return Natural is total : Natural := 0; begin for i in Sudigit loop for j in Sudigit loop if u (i, j).solved then total := total + 1; end if; end loop; end loop; return total; end Count_Solved; function Is_Solved (u : Grid) return Boolean is begin return Count_Solved (u) = 81; end Is_Solved; procedure Find_Box_Base (i, j : Sudigit; base_i, base_j : out Sudigit) is zone_i, zone_j : Natural; begin zone_i := (i - 1) / 3; zone_j := (j - 1) / 3; base_i := zone_i * 3 + 1; base_j := zone_j * 3 + 1; end Find_Box_Base; function Is_Valid (u : Grid) return Boolean is set, empty : Sudoset; v : Sudigit; base_i, base_j : Sudigit; use HAT; begin for num in Sudigit loop empty (num) := False; end loop; for i in Sudigit loop set := empty; -- Check row: for j in Sudigit loop if u (i, j).solved then v := u (i, j).value; if set (v) then Put_Line (+"Invalid row " & i & "; duplicate value " & v); return False; end if; set (v) := True; end if; end loop; end loop; -- for j in Sudigit loop set := empty; -- Check column: for i in Sudigit loop if u (i, j).solved then v := u (i, j).value; if set (v) then Put_Line (+"Invalid column " & j & "; duplicate value " & v); return False; end if; set (v) := True; end if; end loop; end loop; -- for bi in 0 .. 2 loop for bj in 0 .. 2 loop set := empty; base_i := bi * 3 + 1; base_j := bj * 3 + 1; -- Check box: for i in base_i .. base_i + 2 loop for j in base_j .. base_j + 2 loop if u (i, j).solved then v := u (i, j).value; if set (v) then Put_Line (+"Invalid box " & (1 + bi * 3 + bj) & "; duplicate value " & v); return False; end if; set (v) := True; end if; end loop; end loop; end loop; end loop; return True; end Is_Valid; procedure Adapt_Sets (u : in out Grid; i, j : Sudigit) is num : Sudigit; base_i, base_j : Sudigit; begin if u (i, j).solved then num := u (i, j).value; for k in Sudigit loop -- Disable row: u (i, k).set (num) := False; -- Disable column: u (k, j).set (num) := False; Find_Box_Base (i, j, base_i, base_j); -- Disable square: for ii in base_i .. base_i + 2 loop for jj in base_j .. base_j + 2 loop u (ii, jj).set (num) := False; end loop; end loop; end loop; else HAT.Put_Line ("Cell i, j is not solved!"); -- !! Full Ada: raise some exception end if; end Adapt_Sets; procedure Adapt_All_Sets (u : in out Grid) is begin for i in Sudigit loop for j in Sudigit loop if u (i, j).solved then Adapt_Sets (u, i, j); end if; end loop; end loop; end Adapt_All_Sets; procedure Mark_Solution (u : in out Grid; i, j, num : Sudigit) is begin u (i, j).value := num; u (i, j).solved := True; Adapt_Sets (u, i, j); for n in Sudigit loop u (i, j).set (n) := False; end loop; end Mark_Solution; ------------------------------------ -- === Solving techniques === -- ------------------------------------ --------------------------------------------------------------- -- Singles. Some cells have only one possibility. -- -- This case is called "single". It can be either "naked", -- -- when the only possibility is alone, or "hidden" when -- -- the possibility in question is not alone in its cell -- -- but is nowhere else in a house (row, column or box). -- -- When a single is found, the cell is solved. -- --------------------------------------------------------------- -- The "naked single" case is the most simple case to solve when -- the possibilities for each cell are counted: the cell (i, j) -- has only one possible digit. Note that for humans, this case -- is not easily identifiable visually. -- procedure Handle_Naked_Singles (u : in out Grid; verbose : in Boolean; found : out Natural) is procedure Handle_Naked_Single (i, j : Sudigit) is the_number : Sudigit; use HAT; begin if Count (u (i, j).set) = 1 then found := found + 1; for num in Sudigit loop if u (i, j).set (num) then Mark_Solution (u, i, j, num); the_number := num; exit; end if; end loop; if verbose then Put_Line (+"Found naked single at pos " & i & ',' & j & ": digit: " & the_number); end if; end if; end Handle_Naked_Single; begin found := 0; for i in Sudigit loop for j in Sudigit loop if not u (i, j).solved then Handle_Naked_Single (i, j); end if; end loop; end loop; end Handle_Naked_Singles; procedure Handle_Hidden_Singles (u : in out Grid; verbose : in Boolean; found : out Natural) is procedure Handle_Hidden_Single (i, j : Sudigit) is base_i, base_j : Sudigit; ok : Boolean; use HAT; begin Find_Box_Base (i, j, base_i, base_j); for num in Sudigit loop if u (i, j).set (num) then -- Check row: ok := True; for jj in Sudigit loop if jj /= j then -- Check that the digit is NOT possible elsewhere on the row. ok := ok and not u (i, jj).set (num); exit when not ok; end if; end loop; if ok then if verbose then Put_Line (+"Found hidden single (row) at pos " & i & ',' & j & ": digit: " & num); end if; else -- Check column: ok := True; for ii in Sudigit loop if ii /= i then -- Check that the digit is NOT possible elsewhere on the column. ok := ok and not u (ii, j).set (num); exit when not ok; end if; end loop; if ok then if verbose then Put_Line (+"Found hidden single (column) at pos " & i & ',' & j & ": digit: " & num); end if; end if; end if; if not ok then -- Check box: ok := True; Box_Row : for ii in base_i .. base_i + 2 loop for jj in base_j .. base_j + 2 loop if ii /= i or else j /= jj then -- Check that the digit is NOT possible elsewhere in the box. ok := ok and not u (ii, jj).set (num); exit Box_Row when not ok; end if; end loop; end loop Box_Row; if ok then if verbose then Put_Line (+"Found hidden single (box) at pos " & i & ',' & j & ": digit: " & num); end if; end if; end if; if ok then found := found + 1; Mark_Solution (u, i, j, num); exit; end if; end if; end loop; end Handle_Hidden_Single; begin found := 0; for i in Sudigit loop for j in Sudigit loop if not u (i, j).solved then Handle_Hidden_Single (i, j); end if; end loop; end loop; end Handle_Hidden_Singles; -------------------- -- Locked cells -- -------------------- procedure Handle_Locked_Cells_Outside_Boxes (u : in out Grid; verbose : in Boolean; found : out Natural) is procedure Handle_Locked_Cells_Outside_A_Box (i, j : Sudigit) is base_i, base_j : Sudigit; ok_row, ok_col, any_cell : Boolean; use HAT; begin Find_Box_Base (i, j, base_i, base_j); for num in Sudigit loop if u (i, j).set (num) then -- Check if `num` is only on a row / column within its box: ok_row := True; ok_col := True; for ii in base_i .. base_i + 2 loop for jj in base_j .. base_j + 2 loop if u (ii, jj).set (num) then ok_col := ok_col and jj = j; ok_row := ok_row and ii = i; end if; end loop; end loop; -- We have found that `num` is possible only on a row within the box. -- Then, it cannot be on that row outside the box. any_cell := False; if ok_row then for jj in Sudigit loop if jj not in base_j .. base_j + 2 and then u (i, jj).set (num) then found := found + 1; u (i, jj).set (num) := False; any_cell := True; end if; end loop; if verbose and then any_cell then Put_Line (+"Found locked cells on row " & i & " *outside* of box with edge " & base_i & ',' & base_j & "; digit: " & num); end if; end if; -- We have found that `num` is possible only on a column within the box. -- Then, it cannot be on that column outside the box. any_cell := False; if ok_col then for ii in Sudigit loop if ii not in base_i .. base_i + 2 and then u (ii, j).set (num) then found := found + 1; u (ii, j).set (num) := False; any_cell := True; end if; end loop; if verbose and then any_cell then Put_Line (+"Found locked cells on column " & j & " *outside* of box with edge " & base_i & ',' & base_j & "; digit: " & num); end if; end if; end if; end loop; end Handle_Locked_Cells_Outside_A_Box; begin found := 0; for i in Sudigit loop for j in Sudigit loop if not u (i, j).solved then Handle_Locked_Cells_Outside_A_Box (i, j); end if; end loop; end loop; end Handle_Locked_Cells_Outside_Boxes; procedure Handle_Locked_Cells_Inside_Boxes (u : in out Grid; verbose : in Boolean; found : out Natural) is procedure Handle_Locked_Cells_Inside_A_Box (i, j : Sudigit) is base_i, base_j : Sudigit; ok_row, ok_col, any_cell_row, any_cell_col : Boolean; use HAT; begin Find_Box_Base (i, j, base_i, base_j); for num in Sudigit loop if u (i, j).set (num) then -- Check if `num` is only on a row / column within its box: ok_row := True; for jj in Sudigit loop if jj not in base_j .. base_j + 2 then -- Row i, but outside the box if u (i, jj).set (num) then ok_row := False; exit; end if; end if; end loop; -- ok_col := True; for ii in Sudigit loop if ii not in base_i .. base_i + 2 then -- Column j, but outside the box if u (ii, j).set (num) then ok_col := False; exit; end if; end if; end loop; -- any_cell_row := False; any_cell_col := False; for ii in base_i .. base_i + 2 loop for jj in base_j .. base_j + 2 loop -- We have found that on the whole row, `num` is possible only within the box. -- Then, it cannot be on another row inside the box. if ok_row and then i /= ii and then u (ii, jj).set (num) then found := found + 1; u (ii, jj).set (num) := False; any_cell_row := True; end if; -- We have found that on the whole column, `num` is possible only within the box. -- Then, it cannot be on another column inside the box. if ok_col and then j /= jj and then u (ii, jj).set (num) then found := found + 1; u (ii, jj).set (num) := False; any_cell_col := True; end if; end loop; end loop; -- if verbose then if any_cell_row then Put_Line (+"Found locked cells on row " & i & " *inside* of box with edge " & base_i & ',' & base_j & "; digit: " & num); end if; if any_cell_col then Put_Line (+"Found locked cells on column " & j & " *inside* of box with edge " & base_i & ',' & base_j & "; digit: " & num); end if; end if; end if; end loop; end Handle_Locked_Cells_Inside_A_Box; begin found := 0; for i in Sudigit loop for j in Sudigit loop if not u (i, j).solved then Handle_Locked_Cells_Inside_A_Box (i, j); end if; end loop; end loop; end Handle_Locked_Cells_Inside_Boxes; ------------------------------ -- Multiple possibilities -- ------------------------------ -- TBD: Handle_Naked_Multiples procedure Handle_Hidden_Multiples (u : in out Grid; multi : in Sudigit; h : in out Sudo_Help; verbose : in Boolean; found : out Natural) is procedure Single_Row (i : Sudigit) is procedure Check_Sequence (s : Sequence_Type) is -- Example: we check if the *triple* {2, 5, 6} -- appears, partially or fully, only in *three* -- cells in a house, possibly with other digits. -- In that case, the said other digits can be -- removed as possibilities in those three cells. match_count : Natural; ok : Boolean; has_multiple : Sudoset; mask, appears : Sudoset := h.empty; is_set, is_set_new : Boolean; something_removed : Boolean; selected_digit : Sudigit; use HAT; begin for seq in 1 .. multi loop -- ex.: (2, 5, 6 => True, others => False) mask (s (seq)) := True; end loop; match_count := 0; has_multiple := h.empty; for jj in Sudigit loop ok := False; for seq in 1 .. multi loop selected_digit := s (seq); if u (i, jj).set (selected_digit) then appears (selected_digit) := True; ok := True; end if; end loop; if ok then match_count := match_count + 1; has_multiple (jj) := True; end if; end loop; if match_count <= multi and then Count (appears) = multi -- Ensure all considered digits appear at least once then for j in Sudigit loop if has_multiple (j) then something_removed := False; -- In the cells containing the hidden multiple, -- we keep only the digits of the multiple -- and remove the other digits. for d in Sudigit loop is_set := u (i, j).set (d); is_set_new := is_set and mask (d); u (i, j).set (d) := is_set_new; if is_set_new /= is_set then something_removed := True; end if; end loop; if something_removed then found := found + 1; if verbose then Put (+"Found hidden multiple on a row at pos " & i & ',' & j & ": digits:"); for seq in 1 .. multi loop if u (i, j).set (s (seq)) then Put (s (seq), 2); else Put (+" (" & s (seq) & ')'); end if; end loop; New_Line; end if; end if; end if; end loop; end if; end Check_Sequence; begin -- Check all sequences. E.g., for multi = 2: -- {1, 2}, {1, 3}, {2, 3}, {1, 4}, {2, 4}, {3, 4}, ... for combi in 1 .. h.max_combi (multi) loop Check_Sequence (h.table (multi, combi)); end loop; end Single_Row; procedure Single_Column (j : Sudigit) is procedure Check_Sequence (s : Sequence_Type) is match_count : Natural; ok : Boolean; has_multiple : Sudoset; mask, appears : Sudoset := h.empty; is_set, is_set_new : Boolean; something_removed : Boolean; selected_digit : Sudigit; use HAT; begin for seq in 1 .. multi loop mask (s (seq)) := True; end loop; match_count := 0; has_multiple := h.empty; for i in Sudigit loop ok := False; for seq in 1 .. multi loop selected_digit := s (seq); if u (i, j).set (selected_digit) then appears (selected_digit) := True; ok := True; end if; end loop; if ok then match_count := match_count + 1; has_multiple (i) := True; end if; end loop; if match_count <= multi and then Count (appears) = multi then for i in Sudigit loop if has_multiple (i) then something_removed := False; for d in Sudigit loop is_set := u (i, j).set (d); is_set_new := is_set and mask (d); u (i, j).set (d) := is_set_new; if is_set_new /= is_set then something_removed := True; end if; end loop; if something_removed then found := found + 1; if verbose then Put (+"Found hidden multiple on a column at pos " & i & ',' & j & ": digits:"); for seq in 1 .. multi loop if u (i, j).set (s (seq)) then Put (s (seq), 2); else Put (+" (" & s (seq) & ')'); end if; end loop; New_Line; end if; end if; end if; end loop; end if; end Check_Sequence; begin for combi in 1 .. h.max_combi (multi) loop Check_Sequence (h.table (multi, combi)); end loop; end Single_Column; procedure Single_Box (base_i, base_j : Sudigit) is procedure Check_Sequence (s : Sequence_Type) is match_count : Natural; ok : Boolean; has_multiple : array (0 .. 2, 0 .. 2) of Boolean; mask, appears : Sudoset := h.empty; is_set, is_set_new : Boolean; something_removed : Boolean; selected_digit : Sudigit; use HAT; begin for seq in 1 .. multi loop mask (s (seq)) := True; end loop; match_count := 0; for i in has_multiple'Range (1) loop for j in has_multiple'Range (2) loop has_multiple (i, j) := False; end loop; end loop; for i in base_i .. base_i + 2 loop for j in base_j .. base_j + 2 loop ok := False; for seq in 1 .. multi loop selected_digit := s (seq); if u (i, j).set (selected_digit) then appears (selected_digit) := True; ok := True; end if; end loop; if ok then match_count := match_count + 1; has_multiple (i - base_i, j - base_j) := True; end if; end loop; end loop; if match_count <= multi and then Count (appears) = multi then for i in base_i .. base_i + 2 loop for j in base_j .. base_j + 2 loop if has_multiple (i - base_i, j - base_j) then something_removed := False; for d in Sudigit loop is_set := u (i, j).set (d); is_set_new := is_set and mask (d); u (i, j).set (d) := is_set_new; if is_set_new /= is_set then something_removed := True; end if; end loop; if something_removed then found := found + 1; if verbose then Put (+"Found hidden multiple in a box at pos " & i & ',' & j & ": digits:"); for seq in 1 .. multi loop if u (i, j).set (s (seq)) then Put (s (seq), 2); else Put (+" (" & s (seq) & ')'); end if; end loop; New_Line; end if; end if; end if; end loop; end loop; end if; end Check_Sequence; begin for combi in 1 .. h.max_combi (multi) loop Check_Sequence (h.table (multi, combi)); end loop; end Single_Box; begin found := 0; for ij in Sudigit loop Single_Row (ij); Single_Column (ij); end loop; for box_i in 0 .. 2 loop for box_j in 0 .. 2 loop Single_Box (box_i * 3 + 1, box_j * 3 + 1); end loop; end loop; end Handle_Hidden_Multiples; function Technique_Image (t : Resolution_Technique) return HAT.VString is use HAT; begin case t is when naked_single => return +"naked single(s)"; when hidden_single => return +"hidden single(s)"; when locked_cell_outside_box => return +"locked cell(s), outside boxe(s)"; when locked_cell_inside_box => return +"locked cell(s), inside boxe(s)"; when hidden_double => return +"hidden double(s)"; when hidden_triple => return +"hidden triple(s)"; when hidden_quadruple => return +"hidden quadruple(s)"; when hidden_quintuple => return +"hidden quintuple(s)"; when hidden_sextuple => return +"hidden sextuple(s)"; when hidden_septuple => return +"hidden septuple(s)"; when hidden_octuple => return +"hidden octuple(s)"; end case; end Technique_Image; procedure Zero (count : out Technique_Count) is begin for t in Resolution_Technique loop count (t) := 0; end loop; end Zero; function Sum (count : Technique_Count) return Natural is s : Natural := 0; begin for t in Resolution_Technique loop s := s + count (t); end loop; return s; end Sum; procedure Cumulate (total : in out Technique_Count; additional : Technique_Count) is begin for t in Resolution_Technique loop total (t) := total (t) + additional (t); end loop; end Cumulate; procedure Show_Total (total : Technique_Count; title : HAT.VString) is use HAT; begin Put_Line (title); for t in Resolution_Technique loop if total (t) > 0 then Put_Line (+" found: " & total (t) & ' ' & Technique_Image (t)); end if; end loop; New_Line; end Show_Total; procedure Show (u : Grid; title : HAT.VString) is min_poss : Natural := Natural'Last; poss : Natural; use HAT; begin Put_Line (title); Put_Line (Length (title) * '='); New_Line; Put_Line (+"Grid, " & Count_Solved (u) & " digits set Possibilities"); New_Line; for i in Sudigit loop for j in Sudigit loop if j mod 3 = 1 then Put ('|'); else Put (' '); end if; if u (i, j).solved then Put (u (i, j).value, 0); else Put ('_'); end if; end loop; Put ("| "); for j in Sudigit loop if j mod 3 = 1 then Put ('|'); else Put (' '); end if; if u (i, j).solved then Put ('_'); else poss := Count (u (i, j).set); Put (poss, 0); min_poss := Min (min_poss, poss); end if; end loop; Put_Line ('|'); if i = 3 or else i = 6 then Put_Line (":-----+-----+-----: :-----+-----+-----:"); end if; end loop; New_Line; if min_poss in Sudigit then Put_Line (+" Minimum: " & min_poss); end if; end Show; procedure Show_Detailed_Possibilities (u : Grid) is use HAT; begin for i in Sudigit loop for j in Sudigit loop for num in Sudigit loop if u (i, j).set (num) then Put (num, 0); else Put ('.'); end if; end loop; if j mod 3 = 0 then Put ('|'); else Put (' '); end if; end loop; New_Line; if i mod 3 = 0 then Put_Line (90 * '-'); end if; end loop; end Show_Detailed_Possibilities; procedure Resolution_Round (pack : in out Sudo_Pack; help : in out Sudo_Help; title : in HAT.VString; verbosity_level : in Natural) is found : Technique_Count; procedure Handle_Techniques is single_hit_verbosity : constant Boolean := verbosity_level > 4; begin Handle_Naked_Singles (pack.u, single_hit_verbosity, found (naked_single)); if found (naked_single) > 0 then return; end if; -- We search more complicated possibilities, -- only when none for the less complicated was found. Handle_Hidden_Singles (pack.u, single_hit_verbosity, found (hidden_single)); if found (hidden_single) > 0 then return; end if; Handle_Locked_Cells_Outside_Boxes (pack.u, single_hit_verbosity, found (locked_cell_outside_box)); if found (locked_cell_outside_box) > 0 then return; end if; Handle_Locked_Cells_Inside_Boxes (pack.u, single_hit_verbosity, found (locked_cell_inside_box)); if found (locked_cell_inside_box) > 0 then return; end if; for t in hidden_double .. hidden_octuple loop Handle_Hidden_Multiples (pack.u, 2 + Resolution_Technique'Pos (t) - Resolution_Technique'Pos (hidden_double), help, single_hit_verbosity, found (t)); if found (t) > 0 then return; end if; end loop; end Handle_Techniques; use HAT; begin Zero (found); Handle_Techniques; pack.stalling := Sum (found) = 0; if verbosity_level > 1 then if pack.stalling then Put_Line ("Stalling. Search abandoned."); if verbosity_level > 2 then Show_Detailed_Possibilities (pack.u); end if; end if; if verbosity_level > 2 or else Is_Solved (pack.u) then Show (pack.u, title); if verbosity_level > 3 then Show_Detailed_Possibilities (pack.u); end if; end if; if verbosity_level > 2 then Show_Total (found, +"Techniques used in this round:"); end if; end if; Cumulate (pack.total, found); end Resolution_Round; procedure Solve (pack : in out Sudo_Pack; help : in out Sudo_Help; name : in HAT.VString; verbosity_level : in Natural) is use HAT; begin Adapt_All_Sets (pack.u); case verbosity_level is when 0 => null; -- Completely silent, except for errors. when 1 => Put ("Puzzle: " & name & " - "); when others => New_Line; Show (pack.u, "> > > > Initial board for: " & name); if verbosity_level > 3 then Show_Detailed_Possibilities (pack.u); end if; end case; if not Is_Valid (pack.u) then Put_Line ("Initial board is invalid!"); return; end if; -- for round in 1 .. Sudigit'Last * Sudigit'Last loop Resolution_Round (pack, help, +"After round " & round & " for " & name, verbosity_level); exit when pack.stalling or else Is_Solved (pack.u); end loop; -- if verbosity_level > 1 then Show_Total (pack.total, +"Totals of techniques used:"); end if; if not Is_Valid (pack.u) then Put_Line ("Solution or current state is invalid!"); return; end if; if verbosity_level = 1 then if pack.stalling then Put_Line ("** stalling **, algorithm not smart enough," & " or too few digits set in puzzle!"); elsif Is_Solved (pack.u) then Put_Line ("solved and checked."); else Put_Line ("Neither solved nor unsolved ?!"); end if; end if; end Solve; procedure Initialize (pack : out Sudo_Pack) is begin Zero (pack.total); pack.stalling := False; end Initialize; procedure Initialize_Helper (help : out Sudo_Help) is i_shifted, bits_1 : Natural; comb_index : Positive; begin for num in Sudigit loop help.full (num) := True; help.empty (num) := False; help.max_combi (num) := 0; end loop; -- for i in 1 .. (2 ** Sudigit'Last) - 1 loop i_shifted := i; bits_1 := 0; for d in Sudigit loop if i_shifted mod 2 = 1 then bits_1 := bits_1 + 1; end if; i_shifted := i_shifted / 2; end loop; -- For bits_1 = 3 (say), we have found a new -- combination with 3 digits which correspond to -- the position of the bit in the binary -- representation of i. help.max_combi (bits_1) := help.max_combi (bits_1) + 1; i_shifted := i; comb_index := 1; for d in Sudigit loop if i_shifted mod 2 = 1 then help.table (bits_1, help.max_combi (bits_1))(comb_index) := d; comb_index := comb_index + 1; end if; i_shifted := i_shifted / 2; end loop; end loop; -- Some table outputs: -- -- HAT.Put_Line ("Combinations:"); -- for d in 1 .. Sudigit'Last - 1 loop -- HAT.Put ("For"); -- HAT.Put (d, 2); -- HAT.Put_Line (help.max_combi (d)); -- = Binomial (9, d) -- end loop; -- -- HAT.Put_Line ("All doubles:"); -- for i in 1 .. help.max_combi (2) loop -- for j in 1 .. 2 loop -- HAT.Put (help.table (2, i)(j), 2); -- end loop; -- HAT.New_Line; -- end loop; -- -- HAT.Put_Line ("All triples:"); -- for i in 1 .. help.max_combi (3) loop -- for j in 1 .. 3 loop -- HAT.Put (help.table (3, i)(j), 2); -- end loop; -- HAT.New_Line; -- end loop; end Initialize_Helper; procedure Convert_Data (s : in Sudo_Strings; pack : in out Sudo_Pack; help : in out Sudo_Help) is procedure Convert_String (i : Sudigit; s : HAT.VString) is c : Character; use HAT; begin for j in Sudigit loop c := Element (s, j); case c is when ' ' => pack.u (i, j).solved := False; pack.u (i, j).set := help.full; when '1' .. '9' => pack.u (i, j).solved := True; pack.u (i, j).set := help.empty; pack.u (i, j).value := Ord (c) - Ord ('0'); when others => Put_Line ("Data Error!"); -- !! Full Ada: raise some exception end case; end loop; end Convert_String; begin Initialize (pack); Initialize_Helper (help); for i in Sudigit loop Convert_String (i, s (i)); end loop; end Convert_Data; end Sudokus; ================================================ FILE: exm/sudokus.ads ================================================ -- This package explores ways to solve a Sudoku -- in a human-friendly way, that is *without* resorting -- to brute force by using recursion. with HAT; package Sudokus is subtype Sudigit is Integer range 1 .. 9; type Sudoset is array (Sudigit) of Boolean; function Count (s : Sudoset) return Natural; type Cell is record solved : Boolean; value : Sudigit; set : Sudoset; end record; type Grid is array (Sudigit, Sudigit) of Cell; function Count_Solved (u : Grid) return Natural; function Is_Solved (u : Grid) return Boolean; function Is_Valid (u : Grid) return Boolean; -- Once a cell (i, j) is solved, we need to remove -- the digit in the possibility sets of the row i, -- the column j and the 3x3 box containing (i, j). -- procedure Adapt_Sets (u : in out Grid; i, j : Sudigit); procedure Adapt_All_Sets (u : in out Grid); -- We associate combinations of possible Sudigits -- with the binary representation of numbers. -- Example: if we want to consider digits 2 and 4, -- the number associated is 2 ** 1 + 2 ** 3 = 10. -- -- ----- Binary ----- |#Sudigits = count -- Decimal: Bit : >987654321< |of binary '1's |Sequence: ------------------------------------------------------------ -- 1 > 1< 1 | 1 -- 2 > 10< 1 | 2 -- 3 > 11< 2 | 1, 2 -- 4 > 100< 1 | 3 -- 5 > 101< 2 | 1, 3 -- 6 > 110< 2 | 2, 3 -- 7 > 111< 3 | 1, 2, 3 -- 8 > 1000< 1 | 4 -- 9 > 1001< 2 | 1, 4 -- >>>> 10 > 1010< 2 | 2, 4 -- 11 > 1011< 3 | 1, 2, 4 type Sequence_Type is array (Sudigit) of Sudigit; type Combination_Table is array (Sudigit, 1 .. 126) of Sequence_Type; -- Say c is of type Combination_Table. Then, in the example above, -- we see that the pair {2, 4} is the 5th combination with two Sudigits. -- Then c (2, 5)(1) = 2 and c (2, 5)(2) = 4. type Max_Combinations_Type is array (Sudigit) of Natural; -- The data in the following record is invariant and independent of puzzles. type Sudo_Help is record full : Sudoset; empty : Sudoset; table : Combination_Table; max_combi : Max_Combinations_Type; end record; ------------------------------------------------------- -- Organization of different resolution techniques -- ------------------------------------------------------- type Resolution_Technique is (naked_single, hidden_single, locked_cell_outside_box, locked_cell_inside_box, hidden_double, hidden_triple, hidden_quadruple, hidden_quintuple, hidden_sextuple, hidden_septuple, hidden_octuple); function Technique_Image (t : Resolution_Technique) return HAT.VString; type Technique_Count is array (Resolution_Technique) of Natural; procedure Zero (count : out Technique_Count); procedure Cumulate (total : in out Technique_Count; additional : Technique_Count); procedure Show_Total (total : Technique_Count; title : HAT.VString); -- Output of a grid on console. procedure Show_Detailed_Possibilities (u : Grid); type Sudo_Pack is record u : Grid; total : Technique_Count; stalling : Boolean; end record; procedure Resolution_Round (pack : in out Sudo_Pack; help : in out Sudo_Help; title : in HAT.VString; verbosity_level : in Natural); procedure Solve (pack : in out Sudo_Pack; help : in out Sudo_Help; name : in HAT.VString; verbosity_level : in Natural); -- Input of puzzles as strings. type Sudo_Strings is array (Sudigit) of HAT.VString; procedure Convert_Data (s : in Sudo_Strings; pack : in out Sudo_Pack; help : in out Sudo_Help); end Sudokus; ================================================ FILE: exm/tasking/tasks_01.adb ================================================ -- Here is the simplest case of tasking you can imagine: just -- a bunch of tasks running in parallel, without communication -- between them. with HAT; procedure Tasks_01 is task T1; task T2; task body T1 is begin for i in 1 .. 4 loop HAT.Put_Line (" [1] I am T1"); delay 0.01; end loop; end T1; task body T2 is begin for i in 1 .. 6 loop HAT.Put_Line (" [2] I am T2"); delay 0.01; end loop; end T2; begin for i in 1 .. 3 loop HAT.Put_Line ("I am the main procedure"); delay 0.01; end loop; end Tasks_01; ================================================ FILE: exm/tasking/tasks_02.adb ================================================ -- Was originally Test2 in SmallAda with HAT; procedure Tasks_02 is compiler_regression_test_mode : constant Boolean := HAT.Argument_Count > 0; verbose : constant Boolean := not compiler_regression_test_mode; procedure Selective_Put_Line (M : HAT.VString) is begin if verbose then HAT.Put_Line (M); end if; end Selective_Put_Line; task T1; task T2 is entry Hereza_Num (V1 : Integer); entry Gimmea_Num (V2 : out Integer); end T2; the_answer : constant := 42; use HAT; task body T1 is iii : Integer; begin Selective_Put_Line (5 * "Task T1 starting... "); iii := the_answer; Selective_Put_Line (+"iii = " & iii); T2.Hereza_Num (iii); end T1; task body T2 is jjj : Integer; begin Selective_Put_Line (5 * "Task T2 starting... "); jjj := 0; Selective_Put_Line (+"jjj = " & jjj); accept Hereza_Num (V1 : Integer) do jjj := V1; end Hereza_Num; Selective_Put_Line (+"jjj = " & jjj); accept Gimmea_Num (V2 : out Integer) do V2 := jjj; end Gimmea_Num; end T2; Mmm : Integer := 99; begin Selective_Put_Line (+"[Main] ---------- Test with Tasks."); Selective_Put_Line (+"[Main] [point 1] mmm = " & Mmm); T2.Gimmea_Num (Mmm); Selective_Put_Line (+"[Main] ---------- At this point, tasks are done."); Selective_Put_Line (+"[Main] [point 2] mmm = " & Mmm); Selective_Put_Line (+"[Main] Done."); if compiler_regression_test_mode and then Mmm /= the_answer then Put_Line (" ----> Compiler test failed."); Set_Exit_Status (1); end if; end Tasks_02; ================================================ FILE: exm/three_lakes_s.adb ================================================ -- *** This HAC demo is a version of the Three_Lakes -- *** program in MathPaqs. The program is scaled down for -- *** meeting HAC v.0.072 syntax subset. -- *** We mark the downscaling with "!" in comments. -- *** -- *** For the original verion in full Ada, see "three_lakes.adb" @ -- *** https://mathpaqs.sourceforge.io/ or -- *** https://github.com/zertovitch/mathpaqs . ---------------------------------------------------------------------------- -- This program solves a vectorial ordinary differential equation -- (or a system of ordinary differential equations). -- -- * The unknown is a vector containing the levels of three lakes. -- * The lakes are connected by two channels. -- * There is an initial condition: the levels at t = 0. -- * Boundary conditions take the form of natural inflows into the lakes, -- and a single, controlled outflow out of one of the lakes. -- -- Related publication: -- Evolution simulee des niveaux dans le systeme des Trois-Lacs, -- F. & G. de Montmollin, -- Bulletin de la Societe vaudoise des sciences naturelles. -- 88.2: 121-129, ISSN 0037-9603, 2002 -- -- Related post: -- https://gautiersblog.blogspot.com/2020/05/the-three-lakes-problem.html -- with HAT; -- ! with Ada.Text_IO, -- ! Ada.Integer_Text_IO, -- ! Ada.Numerics.Generic_Elementary_Functions; procedure Three_Lakes_S is -- ! type Real is digits 15; -- ! package PFIO is new Ada.Text_IO.Float_IO (Real); -- ! package PFEF is new Ada.Numerics.Generic_Elementary_functions (Real); use HAT; type Lake is (Morat, Neuchatel, Bienne); type Lake_Vector is array (Lake) of Real; -- ! Full Ada: programmable operators (*, +, ...). -- ! function "*" (l : Real; v : Lake_Vector) return Lake_Vector is -- ! r : Lake_Vector; -- ! begin -- ! for i in v'Range loop r(i) := v(i) * l; end loop; -- ! return r; -- ! end "*"; -- ! function "+" (a, b : Lake_Vector) return Lake_Vector is -- ! r : Lake_Vector; -- ! begin -- ! for i in a'Range loop r(i) := a(i) + b(i); end loop; -- ! return r; -- ! end "+"; procedure Times (l : Real; v : Lake_Vector; r : out Lake_Vector) is begin for i in Lake loop r (i) := v (i) * l; end loop; end Times; procedure Plus (a, b : Lake_Vector; r : out Lake_Vector) is begin for i in Lake loop r (i) := a (i) + b (i); end loop; end Plus; function Sign (i : Real) return Real is begin if i < 0.0 then return -1.0; elsif i = 0.0 then return 0.0; else return 1.0; end if; end Sign; -- ! ivs: constant Lake_Vector:= -- ! (Morat => 1.0 / 2.2820e7, -- ! Neuchatel => 1.0 / 2.1581e8, -- ! Bienne => 1.0 / 4.0870e7); -- -- ! Full Ada: aggregates ivs : Lake_Vector; procedure Init_Sensitivity is begin ivs (Morat) := 1.0 / 2.2820e7; ivs (Neuchatel) := 1.0 / 2.1581e8; ivs (Bienne) := 1.0 / 4.0870e7; end Init_Sensitivity; -- We solve numerically x' (t) = f (x (t), t) over the time step h. -- procedure Evolution (x : in out Lake_Vector; q_e : Lake_Vector; q_sb, h : Real) is -- -- ! function f (x : Lake_Vector) return Lake_Vector is -- ! Full Ada: functions with non-atomic results. procedure f (x : Lake_Vector; res_f : out Lake_Vector) is q_tr_mn, q_tr_nb : Real; -- procedure Flux_tansfert is -- ! use PFEF; begin q_tr_mn := -- Canal de la Broye: Morat -> Neuchatel. Sign (x (Morat) - x (Neuchatel)) * -- sens d'ecoulement 15.223 * -- facteur de debit (((x (Morat) + x (Neuchatel)) * 0.5 - 426.0)**1.868) * -- effet du niveau moyen ((abs (x (Morat) - x (Neuchatel)))**0.483); -- effet de la diff. de niveaux -- q_tr_nb := -- Canal de la Thielle: Neuchatel -> Bienne. Sign (x (Neuchatel) - x (Bienne)) * -- sens d'ecoulement 18.582 * -- facteur de debit (((x (Neuchatel) + x (Bienne)) * 0.5 - 426.0)**2.511) * -- effet du niveau moyen ((abs (x (Neuchatel) - x (Bienne)))**0.482); -- effet de la diff. de niveaux end Flux_tansfert; begin Flux_tansfert; res_f (Morat) := (q_e (Morat) - q_tr_mn) * ivs (Morat); res_f (Neuchatel) := (q_e (Neuchatel) + q_tr_mn - q_tr_nb) * ivs (Neuchatel); res_f (Bienne) := (q_e (Bienne) + q_tr_nb - q_sb) * ivs (Bienne); end f; k1, k2, k3, k4, tmp_a, tmp_b, dbk2, dbk3 : Lake_Vector; begin -- Runge-Kutta, Order 4 -- -- ! Full Ada: sooooo much simpler with operators! -- -- ! k1 := f (x ); -- ! k2 := f (x + h * 0.5 * k1); -- ! k3 := f (x + h * 0.5 * k2); -- ! k4 := f (x + h * k3); -- ! x := x + h * (1.0/6.0) * (k1 + 2.0 * k2 + 2.0 * k3 + k4); -- f (x, k1); -- Times (h * 0.5, k1, tmp_a); Plus (x, tmp_a, tmp_b); -- tmp_b = x + h * 0.5 * k1 f (tmp_b, k2); -- Times (h * 0.5, k2, tmp_a); Plus (x, tmp_a, tmp_b); -- tmp_b = x + h * 0.5 * k2 f (tmp_b, k3); -- Times (h, k3, tmp_a); Plus (x, tmp_a, tmp_b); -- tmp_b = x + h * k3 f (tmp_b, k4); -- Times (2.0, k2, dbk2); Times (2.0, k3, dbk3); Plus (k1, dbk2, tmp_a); Plus (tmp_a, dbk3, tmp_b); Plus (tmp_b, k4, tmp_a); -- tmp_a = (k1 + 2.0 * k2 + 2.0 * k3 + k4) Times (h * (1.0 / 6.0), tmp_a, tmp_b); Plus (x, tmp_b, tmp_a); x := tmp_a; end Evolution; procedure Simulation (sim_output : VString) is -- ! use Ada.Text_IO, Ada.Integer_Text_IO, PFIO; x, q_e : Lake_Vector; q_sb, h : Real; n_iter : Integer; out_step : Integer; rf : File_Type; sep : constant Character := ';'; begin h := 3600.0; n_iter := 24 * 20; out_step := 3; -- ! x := (Morat => 428.2, Neuchatel => 429.0, Bienne => 429.4); -- Lake levels at time t = 0. -- ! q_e := (Morat => 40.0, Neuchatel => 70.0, Bienne => 100.0); -- Inflows (could be dynamic). x (Morat) := 428.2; x (Neuchatel) := 429.0; x (Bienne) := 429.4; q_e (Morat) := 40.0; q_e (Neuchatel) := 70.0; q_e (Bienne) := 100.0; q_sb := 200.0; -- Outflow (could be dynamic). Create (rf, sim_output); Put (rf, "t"); for l in Lake loop Put (rf, sep); Put (rf, Lake'Image (l)); end loop; New_Line (rf); for i in 0 .. n_iter loop if i mod out_step = 0 then Put (rf, i); for l in Lake loop Put (rf, sep); Put (rf, x (l), 4, 5, 0); end loop; New_Line (rf); end if; Evolution (x, q_e, q_sb, h); end loop; Close (rf); end Simulation; sim_output : constant VString := +"3_lakes_s.csv"; begin Put_Line ("Three_Lakes_S Simulation"); Put_Line (" - predicting the levels of 3 interconnected lakes."); Put_Line ("Output in : " & sim_output); Init_Sensitivity; Simulation (sim_output); Put_Line ("Done"); end Three_Lakes_S; ================================================ FILE: exm/timing.adb ================================================ with HAT; procedure Timing is use HAT; procedure Simple is T1 : constant Time := Clock; T2 : Time; D : Duration; Day_Secs, Day_Mins : Integer; begin Put_Line (Image (T1)); Day_Secs := Integer (Seconds (T1)); Day_Mins := Day_Secs / 60; Put_Line ( +"More in detail... : Year = " & Year (T1) & ", Month = " & Month (T1) & ", Day = " & Day (T1) & ", Hour = " & Day_Mins / 60 & ", Minutes = " & Day_Mins mod 60 & ", Seconds = " & Day_Secs mod 60 ); Put_Line ("Waiting 3 seconds..."); delay 1.0 + 4.0 * 0.5; -- HAC interpreter can be interrupted during the "delay" statement. T2 := Clock; Put_Line (Image (T2)); D := T2 - T1 + 0.0 * 1.234; Put_Line (Image (D)); D := D + 1.0; D := D - 2.0 * 0.5; Put_Line (Image (D)); end Simple; begin Simple; end Timing; ================================================ FILE: exm/triangles_overlap.adb ================================================ -- https://rosettacode.org/wiki/Determine_if_two_triangles_overlap -- This version is adapted to HAC's Ada subset. with HAT; procedure Triangles_Overlap is use HAT; subtype Vertex is Natural range 0 .. 2; -- ^ Full Ada: type Vertex is mod 3; (we simulate that with a range and explicit "mod 3"s) type Point is array (1 .. 2) of Real; type Triangle is array (Vertex) of Point; function Same_Side (A, B, M, N : Point) return Boolean is function Z_of_Cross_Product_AB_AU (U : Point) return Real is begin return (B (2) - A (2)) * (U (1) - A (1)) - (B (1) - A (1)) * (U (2) - A (2)); end Z_of_Cross_Product_AB_AU; begin -- If the Z-value of AB^AM and AB^AN have the same sign, or one or both is 0, -- then the segment MN doesn't intersect the line containing segment AB. return Z_of_Cross_Product_AB_AU (M) * Z_of_Cross_Product_AB_AU (N) >= 0.0; end Same_Side; function In_Side (t1, t2 : Triangle) return Boolean is cond_1, cond_2 : Boolean; begin -- Simulate Ada 2012's "for all v in Vertex =>": cond_1 := True; for v1 in Vertex loop -- Simulate Ada 2012's "for some v2 in Vertex =>": cond_2 := False; for v2 in Vertex loop cond_2 := cond_2 or Same_Side (t1 ((v1 + 1) mod 3), t1 ((v1 + 2) mod 3), t1 (v1), t2 (v2)); end loop; cond_1 := cond_1 and cond_2; end loop; return cond_1; end In_Side; function Overlap (t1, t2 : Triangle) return Boolean is begin return In_Side (t1, t2) and then In_Side (t2, t1); end Overlap; procedure To_Triangle (r1, r2, r3, r4, r5, r6 : Real; t : out Triangle) is begin t (0)(1) := r1; t (0)(2) := r2; t (1)(1) := r3; t (1)(2) := r4; t (2)(1) := r5; t (2)(2) := r6; end To_Triangle; procedure Show (T1, T2 : Triangle) is begin Put_Line (Boolean'Image (Overlap (T1, T2))); -- !! Overlap (T1, T2)'Image not accepted by HAC ?? end Show; t1, t2 : Triangle; begin To_Triangle (0.0, 0.0, 5.0, 0.0, 0.0, 5.0, t1); To_Triangle (0.0, 0.0, 5.0, 0.0, 0.0, 6.0, t2); Show (t1, t2); To_Triangle (0.0, 0.0, 0.0, 5.0, 5.0, 0.0, t1); To_Triangle (0.0, 0.0, 0.0, 5.0, 5.0, 0.0, t2); Show (t1, t2); To_Triangle (0.0, 0.0, 5.0, 0.0, 0.0, 5.0, t1); To_Triangle (-10.0, 0.0, -5.0, 0.0, -1.0, 6.0, t2); Show (t1, t2); To_Triangle (0.0, 0.0, 5.0, 0.0, 2.5, 5.0, t1); To_Triangle (0.0, 4.0, 2.5, -1.0, 5.0, 4.0, t2); Show (t1, t2); To_Triangle (0.0, 0.0, 1.0, 1.0, 0.0, 2.0, t1); To_Triangle (2.0, 1.0, 3.0, 0.0, 3.0, 2.0, t2); Show (t1, t2); To_Triangle (0.0, 0.0, 1.0, 1.0, 0.0, 2.0, t1); To_Triangle (2.0, 1.0, 3.0, -2.0, 3.0, 4.0, t2); Show (t1, t2); To_Triangle (0.0, 0.0, 1.0, 0.0, 0.0, 1.0, t1); To_Triangle (1.0, 0.0, 2.0, 0.0, 1.0, 1.0, t2); Show (t1, t2); end Triangles_Overlap; ================================================ FILE: exm/unit_a.adb ================================================ with Unit_B, Unit_C, HAT; -- GNAT compilation: gnatmake unit_a -I..\src -- "src" is for getting the HAT package. procedure Unit_A is v : Integer; a_msg : HAT.VString; use HAT; procedure X is begin Put ("(x>"); a_msg := +"A"; Unit_B (v, +"b", +"B"); v := v * 3; Put (""); for i in 1 .. 2 loop Put (Image (Unit_C (+"u", +"U", v))); end loop; X; Unit_B (v, +"b", +"B"); X; HAT.Put (v, 0); HAT.Put (""); Put (Image (Unit_C (+"c", +"C", n))); HAT.Put (""); Put (Image (Unit_C (+"s", +"S", n))); Y2; HAT.Put (+"<" & title_2 & b_msg & ")"); Unit_E; if n /= 777 then Unit_F; end if; n := n * 2; end Unit_B; ================================================ FILE: exm/unit_b.ads ================================================ with HAT; procedure Unit_B (n : in out Integer; title_1, title_2 : HAT.VString); ================================================ FILE: exm/unit_c.adb ================================================ with HAT; use HAT; function Unit_C (title_1, title_2 : VString; n : Integer) return Real is c_msg : VString; procedure Z is begin c_msg := +".C"; Put (+"z[" & n & "]"); end Z; begin c_msg := +".c"; Put (+"(" & title_1 & c_msg & ">"); Z; Put (+"<" & title_2 & c_msg & ")"); return Real (n); end Unit_C; ================================================ FILE: exm/unit_e.adb ================================================ with Unit_C; with HAT; procedure Unit_E is use HAT; begin Put (Unit_C (+"Unit_C called from Unit_E", +"Said otherwise: Unit_E calls Unit_C", 123)); end Unit_E; ================================================ FILE: exm/unit_f.adb ================================================ with Unit_B; procedure Unit_F is x : Integer := 777; use HAT; -- WITH'ed in unit_f.ads. begin Unit_B (x, +" {Unit_B called from Unit_F} ", +" {Value: 777} "); Unit_G; -- WITH'ed in unit_f.ads. end Unit_F; ================================================ FILE: exm/unit_f.ads ================================================ with Unit_G, HAT; procedure Unit_F; ================================================ FILE: exm/unit_g.adb ================================================ with HAT; procedure Unit_G is begin HAT.Put ("__(G)__"); end Unit_G; ================================================ FILE: exm/unit_g.ads ================================================ procedure Unit_G; ================================================ FILE: fast.cmd ================================================ gprbuild %1 -P hac -XHAC_Build_Mode=Fast -XHAC_OS=Win64 ================================================ FILE: hac.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the HAC project: -- -- Home page: http://hacadacompiler.sf.net/ -- Project page: http://sf.net/projects/hacadacompiler/ -- Mirror: https://github.com/zertovitch/hac -- Alire crate: https://alire.ada.dev/crates/hac -- -- Build me with "gprbuild -P hac", or "gnatmake -P hac", -- or open me with GNAT Studio. -- project HAC is type HAC_Build_Mode_Type is ("Debug", "Fast", "Small", "Small_Unchecked", -- Smallest size, at the price of less safety. Not for the release binary! "Profiling"); HAC_Build_Mode : HAC_Build_Mode_Type := external ("HAC_Build_Mode", "Debug"); type HAC_OS_Kind is ("Any", "Linux", "MacOSX", "Win32", "Win64"); HAC_OS : HAC_OS_Kind := external ("HAC_OS", "Any"); for Main use ("hac.adb", -- Principal command-line tool "hac_mini.adb", -- Minimal version of hac.adb "hac_multi.adb"); -- Parallel demo with many compilations case HAC_Build_Mode is when "Debug" => for Object_Dir use "obj/debug"; when "Fast" => for Object_Dir use "obj/fast"; when "Small" => for Object_Dir use "obj/small"; when "Small_Unchecked" => for Object_Dir use "obj/small_unchecked"; when "Profiling" => for Object_Dir use "obj/profiling"; end case; for Source_Dirs use ("src", "src/apps", "src/compile", "src/compile/emit", "src/execute", "src/manage"); for Exec_Dir use "."; for Create_Missing_Dirs use "True"; -- Flips by default the "-p" switch package Pretty_Printer is for Default_Switches ("ada") use ("-i2"); end Pretty_Printer; type HAC_Styles_Checks_Type is ("Off", "On"); HAC_Styles_Checks : HAC_Styles_Checks_Type := external ("HAC_Styles_Checks", "On"); Compiler_Common_Options := ("-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatwcijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ", -- Don't quit, write ali/tree file even if compile errors "-g"); -- Generate debugging information Style_Checks := ("-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens "-gnatye", -- Style: check e:end/exit labels present "-gnatytc"); -- Style: check t:token separation rules, c:comment format (two spaces) case HAC_Styles_Checks is when "Off" => null; when "On" => Compiler_Common_Options := Compiler_Common_Options & Style_Checks; end case; Compiler_Debug_Options := ("-gnata", -- Assertions enabled "-gnato", -- Enable overflow checking in STRICT mode "-gnatVa", -- Enable all validity checking options "-fstack-check", "-fno-inline") & Compiler_Common_Options; Compiler_Fast_Options := ("-O2", "-gnatpn", "-fipa-cp-clone", "-fgcse-after-reload", "-funroll-loops", "-fpeel-loops", "-funswitch-loops", "-ftracer", "-fweb", "-ftree-vectorize", "-frename-registers", "-ffunction-sections", "-fdata-sections") & Compiler_Common_Options; Compiler_Small_Options := ("-Os" -- Commented out: see remark in Check_No_Extra_Symbol. -- "-ffunction-sections" -- "-fdata-sections" ) & Compiler_Common_Options; Compiler_Profiling_Options := ("-O2", "-gnatp", "-fno-inline", "-pg") & Compiler_Common_Options; package Compiler is case HAC_Build_Mode is when "Fast" => for Default_Switches ("ada") use Compiler_Fast_Options; when "Small" => for Default_Switches ("ada") use Compiler_Small_Options; when "Small_Unchecked" => for Default_Switches ("ada") use Compiler_Small_Options & ("-gnatp"); when "Profiling" => for Default_Switches ("ada") use Compiler_Profiling_Options; when "Debug" => for Default_Switches ("ada") use Compiler_Debug_Options; for Local_Configuration_Pragmas use project'Project_Dir & "debug.pra"; end case; end Compiler; Binder_Common_Options := (); case HAC_OS is when "Linux" => Binder_Common_Options := Binder_Common_Options & "-static"; -- Ensures a consistent run-time library when others => end case; package Binder is -- -Es: Store tracebacks in exception occurrences, and enable symbolic tracebacks for Default_Switches ("ada") use Binder_Common_Options & ("-Es"); end Binder; Linker_Common_Options := ("-g"); case HAC_OS is when "Linux" => Linker_Common_Options := Linker_Common_Options & "-static"; -- Ensures a consistent run-time library when "Win64" => Linker_Common_Options := Linker_Common_Options & ("obj/hac_icon.rbj"); when "MacOSX" => Linker_Common_Options := Linker_Common_Options & ("-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib"); -- To overcome "ld: library not found for -lSystem" when others => end case; Linker_Small_Options := Linker_Common_Options & ("-Wl,--gc-sections"); package Linker is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Linker_Common_Options; when "Profiling" => for Default_Switches ("ada") use Linker_Small_Options & ("-pg"); when "Fast" | "Small" | "Small_Unchecked" => for Default_Switches ("ada") use Linker_Small_Options; end case; end Linker; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-j0"); end Builder; package Ide is for Default_Switches ("adacontrol") use ("-f", "test/verif_hac.aru", "-r"); end Ide; end HAC; ================================================ FILE: profiling.cmd ================================================ call go17 gprbuild -P hac -XHAC_Build_Mode=Profiling -XHAC_OS=Win32 cd exm\aoc\2022 ..\..\..\hac -c -v2 aoc_2022_21.adb copy gmon.out ..\..\.. del gmon.out cd ..\..\.. gprof hac.exe >hac_profile.txt ================================================ FILE: readme.md ================================================ # HAC - HAC Ada Compiler HAC is perhaps the first open-source (albeit very partial) Ada compiler fully programmed in Ada itself. **Complete description in: `doc/hac.txt`** ### Command-line flavor: If you are impatient: in Alire (https://alire.ada.dev/), do "alr get hac", then "alr run" from the hac* directory. Alternatively: have GNAT installed (https://www.adacore.com/download), then, on your preferred command-line interpreter: ``` gnatmake -P hac cd exm ../hac gallery.adb ``` (if `gnatmake` doesn't work, try `gprbuild`; for Windows, '\\' is meant in place of '/' ) ### Editor / pre-built flavor: Or, if you don't want to touch the command-line at all for playing with HAC, you can download and use LEA (http://l-e-a.sf.net/). ### Examples You'll find hundreds of examples in the `exm` directory and its subdirectories. Here is the famous Hello World! File `hello.adb`: ```Ada with HAT; procedure Hello is begin HAT.Put ("Hello world!"); end Hello; ``` Another classic example (file `fibo.adb`): ```Ada with HAT; procedure Fibo is function Fibonacci (P : Natural) return Positive is begin if P <= 2 then return 1; else return Fibonacci (P - 1) + Fibonacci (P - 2); end if; end Fibonacci; use HAT; begin for i in 1 .. 22 loop Put_Line (Fibonacci (i)); end loop; end Fibo; ``` Enjoy! ### License HAC is free, open-source and released under the MIT license. ================================================ FILE: save.hac ================================================ --#!/usr/bin/env hac -- Local backup Ada shell script for the HAC project. -- -- This script works both with HAC (command: hac save.adb) -- and a full Ada compiler like GNAT, and that on different -- Operating Systems: Linux and Windows at least. -- -- A "shebang" for Unix/Linux, such as "#!/usr/bin/env hac" can be -- added on the top line of this file. -- HAC will ignore it, but GNAT won't like it (that's normal). -- -- The extension for the main procedure is a free choice. -- We choose ".hac" so we can associate the ".hac" files by -- default with hac.exe on Windows, for Explorer *and* command-line! -- Explorer: double-click / hit Return on "save.hac". -- Cmd / PowerShell: type "save.hac" and hit Return. with HAT; procedure Save is use HAT; function Nice_Date (with_intraday : Boolean) return VString is t1 : constant Time := Clock; day_secs, day_mins : Integer; just_day : VString; -- function Two_Digits (x : Integer) return VString is begin if x < 10 then return "0" & Image (x); else return Image (x); end if; end Two_Digits; -- begin day_secs := Integer (Seconds (t1)); day_mins := day_secs / 60; just_day := +"" & -- VString concatenation Year (t1) & '-' & Two_Digits (Month (t1)) & '-' & Two_Digits (Day (t1)); if with_intraday then return just_day & "--" & Two_Digits (day_mins / 60) & '-' & Two_Digits (day_mins mod 60) & '-' & Two_Digits (day_secs mod 60); else return just_day; end if; end Nice_Date; root, demos, examples, files, tests : VString; zip_res : Integer; sep : constant Character := Directory_Separator; begin Put_Line ("Save date: " & Nice_Date (True)); Put_Line ("Current directory: " & Current_Directory); Put_Line ("-----"); root := Tail_After_Match (Current_Directory, sep); Set_Directory (".."); demos := root & "/demo/data_exchange/*.ad* " & root & "/demo/data_exchange_simple/*.ad* " & root & "/demo/*.gpr " & root & "/demo/*.prj "; examples := root & "/exm/*.ad* " & root & "/exm/*.gpr " & root & "/exm/*.prj " & root & "/exm/e.cmd " & root & "/exm/not_working/*.ad* " & root & "/exm/pdf/*.ad* " & root & "/exm/tasking/*.ad* " & -- root & "/exm/aoc/2020/aoc*.ad* " & root & "/exm/aoc/2020/aoc*.txt " & root & "/exm/aoc/2020/aoc*.gpr " & root & "/exm/aoc/2020/aoc*.prj " & -- root & "/exm/aoc/2021/aoc*.ad* " & root & "/exm/aoc/2021/aoc*.txt " & root & "/exm/aoc/2021/aoc*.gpr " & -- root & "/exm/aoc/2022/aoc*.ad* " & root & "/exm/aoc/2022/aoc*.txt " & root & "/exm/aoc/2022/aoc*.gpr " & -- root & "/exm/aoc/2023/aoc*.ad* " & root & "/exm/aoc/2023/aoc*.txt " & root & "/exm/aoc/2023/aoc*.gpr " & root & "/exm/mathe_kal/2022/m*.ad* " & root & "/exm/mathe_kal/2022/m*.gpr "; tests := root & "/test/*.ad* " & root & "/test/*.gpr " & root & "/test/*.prj " & root & "/test/t.cmd " & root & "/test/tf.cmd " & root & "/test/*.aru " & root & "/test/future/*.ad* "; files := root & "/src/*.ad* " & root & "/src/apps/*.ad* " & root & "/src/compile/*.ad* " & root & "/src/compile/emit/*.ad* " & root & "/src/execute/*.ad* " & root & "/src/manage/*.ad* " & root & "/*.gpr " & root & "/*.prj " & root & "/*.hac " & root & "/build.cmd " & root & "/fast.cmd " & root & "/small.cmd " & root & "/*.txt " & root & "/doc/hac*.txt " & root & "/doc/hac*.xls " & root & "/doc/hac*.pdf " & root & "/debug.pra " & root & "/obj/hac_icon* " & root & "/obj/debug/create_dir.txt " & root & "/obj/fast/create_dir.txt "; files := files & ' ' & demos & ' ' & examples & ' ' & tests; -- The ZipAda command-line tool can be built or downloaded -- from the project Zip-Ada @ -- https://unzip-ada.sourceforge.io/ , -- https://github.com/zertovitch/zip-ada -- or from ALIRE (Ada LIbrary REpository) @ https://alire.ada.dev/ -- Shell_Execute ("zipada -ep2 " & root & sep & root & '-' & Nice_Date (True) & "- " & files, zip_res); if zip_res = 0 then Put_Line ("Zip archive creation successful"); else Put_Line ("Zip archive creation failed"); end if; Set_Directory (root); Put ("Press Return "); Skip_Line; end Save; ================================================ FILE: save_modif.hac ================================================ -- #!/usr/bin/env hac -- -- Local backup Ada shell script for a version-controlled repository. -- -- This HAC script detects changes between two commits and -- saves the repository's modified files into a Zip-ball. -- -- Version Control Systems supported: -- git, hg (mercurial), svn (subversion) -- -- This is a HAC script *and* an Ada program. -- How to run it is your choice. -- -- Usage with the HAC command-line tool : -- -- hac save_modif.hac -- -- The HAC (HAC Ada Compiler) command-line tool can be found @ -- https://hacadacompiler.sourceforge.io/ , -- https://github.com/zertovitch/hac -- -- This program works both with HAC (command: hac save.hac) -- and a full Ada compiler like GNAT, and that on different -- Operating Systems: Linux and Windows at least. -- -- The extension for the main procedure is a free choice. -- We choose ".hac" so we can associate the ".hac" files by -- default with hac.exe on Windows, for Explorer *and* command-line! -- Explorer: double-click / hit Return on "save_modif.hac". -- Cmd / PowerShell: type "save_modif.hac" and hit Return. with HAT; procedure Save_Modif is use HAT; function Nice_Date (with_intraday : Boolean) return VString is t1 : constant Time := Clock; day_secs, day_mins : Integer; just_day : VString; -- function Two_Digits (x : Integer) return VString is begin if x < 10 then return "0" & Image (x); else return Image (x); end if; end Two_Digits; -- begin day_secs := Integer (Seconds (t1)); day_mins := day_secs / 60; just_day := +"" & -- VString concatenation Year (t1) & '-' & Two_Digits (Month (t1)) & '-' & Two_Digits (Day (t1)); if with_intraday then return just_day & "--" & Two_Digits (day_mins / 60) & '-' & Two_Digits (day_mins mod 60) & '-' & Two_Digits (day_secs mod 60); else return just_day; end if; end Nice_Date; line, nd, root, mod_zip, files : VString; f : File_Type; log_name : constant VString := +"modif.log"; sep : constant Character := Directory_Separator; type VCS_Type is (None, Git, Mercurial, Subversion); function Detect_VCS return VCS_Type is begin if Directory_Exists (".git") then return Git; elsif Directory_Exists (".hg") then return Mercurial; elsif Directory_Exists (".svn") then return Subversion; end if; return None; end Detect_VCS; function Abbreviation (vcs : VCS_Type) return VString is begin case vcs is when Git => return +"git"; when Mercurial => return +"hg"; when Subversion => return +"svn"; when None => return +""; end case; end Abbreviation; vcs : constant VCS_Type := Detect_VCS; col_name : Integer; add_line : Boolean; begin Put_Line ("Save date: " & Nice_Date (True)); Put_Line ("Version Control System: " & VCS_Type'Image (vcs)); Put_Line ("-----"); root := Tail_After_Match (Current_Directory, sep); files := root & sep & log_name; case vcs is when Git => Shell_Execute (+"git status -s -uno >" & log_name); col_name := 4; when Mercurial => Shell_Execute (+"hg status -q >" & log_name); col_name := 3; when Subversion => Shell_Execute (+"svn status -q >" & log_name); col_name := 9; when None => Put ("Nothing to do! Press Return"); Skip_Line; return; end case; Open (f, log_name); while not End_Of_File (f) loop Get_Line (f, line); if Length (line) > 3 and then not Ends_With (line, ".out") then add_line := False; for col_tag in 1 .. 2 loop -- Git tags are on two columns case Element (line, col_tag) is when ' ' | 'D' | 'R' | '!' => -- Ignore extra lines, or missing items, or items to be Deleted / Removed null; when others => add_line := True; end case; end loop; if add_line then line := root & sep & Slice (line, col_name, Length (line)); Put_Line (line); files := files & ' ' & line; end if; end if; end loop; Close (f); Put_Line ("-----"); New_Line; -- Shell_Execute ("echo . >>" & log_name); -- Shell_Execute ("echo --- SVN Info --- >>" & log_name); -- Shell_Execute ("svn info >>" & log_name); nd := Nice_Date (True); mod_zip := root & sep & root & "-modif-" & Abbreviation (vcs) & '-' & nd & ".zip"; Set_Directory (".."); Shell_Execute ("zipada -ep2 " & mod_zip & ' ' & files); Set_Directory (root); -- Delete_File (log_name); Put ("Press Return "); Skip_Line; end Save_Modif; ================================================ FILE: save_modif_and_untracked.hac ================================================ -- #!/usr/bin/env hac -- This HAC script detects changes between two commits and -- saves the repository's modified and untracked files into a Zip-ball. -- -- Version Control Systems supported: -- git, hg (mercurial), svn (subversion) with HAT; procedure Save_Modif_and_Untracked is use HAT; function Nice_Date (with_intraday : Boolean) return VString is t1 : constant Time := Clock; day_secs, day_mins : Integer; just_day : VString; -- function Two_Digits (x : Integer) return VString is begin if x < 10 then return "0" & Image (x); else return Image (x); end if; end Two_Digits; -- begin day_secs := Integer (Seconds (t1)); day_mins := day_secs / 60; just_day := +"" & -- VString concatenation Year (t1) & '-' & Two_Digits (Month (t1)) & '-' & Two_Digits (Day (t1)); if with_intraday then return just_day & "--" & Two_Digits (day_mins / 60) & '-' & Two_Digits (day_mins mod 60) & '-' & Two_Digits (day_secs mod 60); else return just_day; end if; end Nice_Date; line, nd, root, mod_zip, files : VString; f : File_Type; log_name : constant VString := +"modif.log"; sep : constant Character := Directory_Separator; type VCS_Type is (None, Git, Mercurial, Subversion); function Detect_VCS return VCS_Type is begin if Directory_Exists (".git") then return Git; elsif Directory_Exists (".hg") then return Mercurial; elsif Directory_Exists (".svn") then return Subversion; end if; return None; end Detect_VCS; function Abbreviation (vcs : VCS_Type) return VString is begin case vcs is when Git => return +"git"; when Mercurial => return +"hg"; when Subversion => return +"svn"; when None => return +""; end case; end Abbreviation; vcs : constant VCS_Type := Detect_VCS; col_name : Integer; add_line : Boolean; begin Put_Line ("Save date: " & Nice_Date (True)); Put_Line ("Version Control System: " & VCS_Type'Image (vcs)); Put_Line ("-----"); root := Tail_After_Match (Current_Directory, sep); -- files := root & sep & log_name; case vcs is when Git => Shell_Execute (+"git status -s -uno >" & log_name); col_name := 4; when Mercurial => Shell_Execute (+"hg status >" & log_name); col_name := 3; when Subversion => Shell_Execute (+"svn status >" & log_name); col_name := 9; when None => Put ("Nothing to do! Press Return"); Skip_Line; return; end case; Open (f, log_name); while not End_Of_File (f) loop Get_Line (f, line); if Length (line) > 3 then add_line := False; for col_tag in 1 .. 2 loop -- Git tags are on two columns case Element (line, col_tag) is when ' ' | 'D' | 'R' | '!' => -- Ignore extra lines, or missing items, or items to be Deleted / Removed null; when others => add_line := True; end case; end loop; if add_line then line := root & sep & Slice (line, col_name, Length (line)); Put_Line (line); files := files & ' ' & line; end if; end if; end loop; Close (f); Put_Line ("-----"); New_Line; -- Shell_Execute ("echo . >>" & log_name); -- Shell_Execute ("echo --- SVN Info --- >>" & log_name); -- Shell_Execute ("svn info >>" & log_name); nd := Nice_Date (True); mod_zip := root & sep & root & "-modif-untracked-" & Abbreviation (vcs) & '-' & nd & ".zip"; Set_Directory (".."); Shell_Execute ("zipada -ep2 " & mod_zip & ' ' & files); -- Shell_Execute ("7z t " & mod_zip); Set_Directory (root); Delete_File (log_name); Put ("Press Return "); Skip_Line; end Save_Modif_and_Untracked; ================================================ FILE: small.cmd ================================================ @echo off echo Build... del hac*.exe gprbuild -P hac hac -XHAC_Build_Mode=Small_Unchecked -XHAC_OS=Win64 copy /B hac.exe hac_unchecked.exe del hac.exe gprbuild -P hac -XHAC_Build_Mode=Small -XHAC_OS=Win64 del demo\*.exe gprbuild -P demo/hac_demo -XHAC_Build_Mode=Small -XHAC_OS=Win64 echo. for %%I in (hac*.exe) do echo %%~zI ... %%I for %%I in (demo\*.exe) do echo %%~zI ... %%I echo. echo Stripping... strip -s hac*.exe strip -s demo/*.exe echo Done. echo. for %%I in (hac*.exe) do echo %%~zI ... %%I for %%I in (demo\*.exe) do echo %%~zI ... %%I ================================================ FILE: src/apps/hac.adb ================================================ -- HAC: command-line build and execution tool for HAC (HAC Ada Compiler) -- Usage, license etc. : see `Help` below and the HAC_Sys package (hac_sys.ads). -- For a small version, see HAC_Mini (hac_mini.adb). -- with HAC_Pkg; with HAC_Sys.Builder, HAC_Sys.Co_Defs, HAC_Sys.Defs, HAC_Sys.PCode.Interpreter.In_Defs; with HAT; with Ada.Calendar, Ada.Command_Line, Ada.Text_IO; procedure HAC is cmp_dump_file_name : HAT.VString; asm_dump : Boolean := False; remarks : HAC_Sys.Defs.Remark_Set := HAC_Sys.Defs.default_remarks; use HAC_Pkg; procedure Compile_and_interpret_file (Ada_file_name : String; arg_pos : Positive) is use Ada.Calendar, Ada.Text_IO; source_stream : HAC_Sys.Co_Defs.Source_Stream_Access; t1, t2 : Ada.Calendar.Time; BD : HAC_Sys.Builder.Build_Data; shebang_offset : Natural := 0; trace : constant HAC_Sys.Co_Defs.Compilation_Trace_Parameters := (pipe => null, progress => Compilation_Feedback'Access, detail_level => verbosity); cat : aliased Path_Management.File_Catalogue; begin main_Ada_file_name := HAT.To_VString (Ada_file_name); if verbosity > 1 then New_Line; Put_Line (HAC_margin_1 & "HAC is free and open-source. Type ""hac"" for license."); end if; cat.Source_Open (Ada_file_name, source_stream); cat.Skip_Shebang (Ada_file_name, shebang_offset); BD.Set_Diagnostic_Parameters (asm_dump, HAT.To_String (cmp_dump_file_name)); BD.Set_Remark_Set (remarks); BD.Set_Main_Source_Stream (source_stream, Ada_file_name, shebang_offset); BD.Set_Message_Feedbacks (trace); BD.Set_Target (target); BD.Set_File_Catalogue (cat'Unchecked_Access); t1 := Clock; BD.Build_Main; t2 := Clock; cat.Close (Ada_file_name); if verbosity >= 2 then Put_Line ( HAC_margin_2 & "Build finished in" & Duration'Image (t2 - t1) & " seconds." & Integer'Image (BD.Total_Compiled_Lines) & " lines compiled in total." ); end if; -- if not BD.Build_Successful then PLCE ("Errors found, build failed."); HAC_Pkg.Failure; return; end if; if verbosity >= 2 then Put_Line (HAC_margin_2 & "Target . : " & BD.CD.target.Name); Put_Line (HAC_margin_2 & "CPU . . : " & BD.CD.target.CPU); Put_Line (HAC_margin_2 & "OS . . . : " & BD.CD.target.OS); -- if BD.CD.Is_HAC_VM then Put_Line (HAC_margin_2 & "Object code size:" & Natural'Image (BD.Object_Code_Size) & " of" & Natural'Image (HAC_Sys.Builder.Maximum_Object_Code_Size) & " Virtual Machine instructions."); if BD.Folded_Instructions + BD.Specialized_Instructions > 0 then Put_Line (HAC_margin_2 & "Code optimization:"); Put_Line (HAC_margin_2 & " " & Natural'Image (BD.Folded_Instructions) & " instructions folded"); Put_Line (HAC_margin_2 & " " & Natural'Image (BD.Specialized_Instructions) & " instructions specialized"); end if; end if; end if; Post_Build (BD); if compile_only then null; elsif BD.CD.Is_Executable then Run (BD, arg_pos); else PLCE ("Can only execute a parameterless procedure"); end if; exception when Name_Error => PLCE (HAC_margin_3 & "Error: file """ & Ada_file_name & """ not found (perhaps in exm or test subdirectory ?)"); HAC_Pkg.Failure; end Compile_and_interpret_file; hac_ing : Boolean := False; quit : Boolean := False; help_level : Positive := 1; procedure Argument_Error (msg : String) is begin PLCE (msg); NLCE; quit := True; delay 1.0; end Argument_Error; procedure Process_Argument (arg : String; arg_pos : Positive) is opt : constant String := arg (arg'First + 1 .. arg'Last); unknown_remark : Boolean; use HAC_Sys.Defs, HAT; begin if arg (arg'First) = '-' then if opt'Length = 0 then Argument_Error ("Missing option code after '-'"); return; end if; case opt (opt'First) is when 'a' => asm_dump := True; when 'c' => compile_only := True; when 'd' => cmp_dump_file_name := To_VString (compiler_dump_name); when 'h' => if opt'Length > 1 and then opt (opt'First + 1) = '2' then help_level := 2; end if; quit := True; when 't' => if opt'Length = 1 then Argument_Error ("Missing target"); else declare new_target_name : constant String := opt (opt'First + 1 .. opt'Last); begin Set_Target (new_target_name); exception when Constraint_Error => Argument_Error ("Unknown target " & new_target_name); end; end if; when 'r' => if opt'Length = 1 then Argument_Error ("Missing remark switch"); else for letter in opt'First + 1 .. opt'Last loop if opt (letter) in '0' .. '3' then remarks := preset_remarks (Remark_Level'Value (opt (letter .. letter))); else unknown_remark := True; for r in HAC_Sys.Defs.Compile_Remark loop if HAC_Sys.Defs.remark_letter (r) = opt (letter) then remarks (r) := True; unknown_remark := False; elsif To_Upper (HAC_Sys.Defs.remark_letter (r)) = opt (letter) then remarks (r) := False; unknown_remark := False; end if; end loop; if unknown_remark then Argument_Error ("Unknown remark switch '" & opt (letter) & '''); exit; end if; end if; end loop; end if; when 'I' => if command_line_source_path /= "" then command_line_source_path := command_line_source_path & ';'; end if; command_line_source_path := command_line_source_path & To_VString (opt (opt'First + 1 .. opt'Last)); when 'v' => verbosity := 1; if opt'Length > 1 and then opt (opt'First + 1) in '0' .. '9' then verbosity := Character'Pos (opt (opt'First + 1)) - Character'Pos ('0'); end if; when others => Argument_Error ("Unknown option: """ & arg & '"'); end case; else Compile_and_interpret_file (arg, arg_pos); hac_ing := True; quit := True; -- The other arguments are for the HAC program. end if; end Process_Argument; use Ada.Command_Line; begin for i in 1 .. Argument_Count loop Process_Argument (Argument (i), i); exit when quit; end loop; if not hac_ing then Help (help_level); if verbosity > 1 then Ada.Text_IO.Put_Line ("Size of a HAC VM memory unit:" & Integer'Image (HAC_Sys.PCode.Interpreter.In_Defs.Data_Type'Size / 8) & " bytes" ); end if; end if; end HAC; ================================================ FILE: src/apps/hac_mini.adb ================================================ -- This is a minimalistic version of HAC, for showing the minimum code required -- to run HAC on a given Ada source file and display outputs on Standard_Output. -- -- See HAC (hac.adb) for the full version of the command-line tool. with Ada.Command_Line, Ada.Text_IO; with HAC_Sys.Builder, HAC_Sys.PCode.Interpreter; procedure HAC_Mini is use Ada.Command_Line, Ada.Text_IO; use HAC_Sys.PCode.Interpreter; -- BD : HAC_Sys.Builder.Build_Data; post_mortem : Post_Mortem_Data; begin if Argument_Count = 0 then Put_Line (Current_Error, "Usage: hac_mini main.adb"); else BD.Build_Main_from_File (Argument (1)); if BD.Build_Successful then Interpret_on_Current_IO (BD, 1, "", post_mortem); if Is_Exception_Raised (post_mortem.Unhandled) then Put_Line (Current_Error, "HAC VM: raised " & Image (post_mortem.Unhandled)); Put_Line (Current_Error, Message (post_mortem.Unhandled)); end if; end if; end if; end HAC_Mini; ================================================ FILE: src/apps/hac_multi.adb ================================================ -- This is a demo of multiple instances of HAC running in parallel. -- Run as: hac_multi >res_multi.csv -- and open the CSV file in your preferred spreadsheet software. -- -- See HAC for the full version of the command-line tool. with HAC_Sys.Builder, HAC_Sys.Defs, HAC_Sys.PCode.Interpreter; with HAT; with Ada.Calendar, Ada.Command_Line, Ada.Numerics.Float_Random, Ada.Streams.Stream_IO, Ada.Text_IO; procedure HAC_Multi is procedure Launch_Tasks is use Ada.Text_IO; sep : constant Character := ';'; task type HAC_Instance is entry Start (id : Positive); end HAC_Instance; task body HAC_Instance is use HAC_Sys.Builder, HAC_Sys.PCode.Interpreter; procedure No_Put (Item : Character) is null; procedure No_New_Line (Spacing : Positive_Count := 1) is null; package Current_IO_Console is new Console_Traits (Ada.Text_IO.End_Of_File, Ada.Text_IO.End_Of_Line, Current_IO_Get_Needs_Skip_Line, HAC_Sys.Defs.IIO.Get, HAC_Sys.Defs.RIO.Get, Ada.Text_IO.Get, Ada.Text_IO.Get_Immediate, Ada.Text_IO.Get_Line, Ada.Text_IO.Skip_Line, HAC_Sys.Defs.IIO.Put, HAC_Sys.Defs.RIO.Put, HAC_Sys.Defs.BIO.Put, No_Put, -- Ada.Text_IO.Put Ada.Text_IO.Put, No_New_Line -- Ada.Text_IO.New_Line ); package Custom_System_Calls is new System_Calls_Traits (Ada.Command_Line.Argument_Count, Ada.Command_Line.Argument, Ada.Command_Line.Command_Name, -- Wrong but not used anyway in this demo. HAT.Shell_Execute, HAT.Shell_Execute, -- This profile has an Output parameter. HAT.Directory_Separator ); use Ada.Calendar, Ada.Numerics.Float_Random, Ada.Streams.Stream_IO; task_id : Positive; tick : Time; gen : Generator; procedure Multi_Feedback ( Stack_Current, Stack_Total : in Natural; Wall_Clock : in Ada.Calendar.Time; User_Abort : out Boolean ) is pragma Unreferenced (Stack_Current, Stack_Total); begin User_Abort := False; if Wall_Clock - tick >= 0.005 then if Random (gen) > 0.999 then User_Abort := True; Put_Line ("A1" & sep & " Task" & sep & Integer'Image (task_id) & sep & " wants to abort the HAC VM."); end if; tick := Wall_Clock; end if; end Multi_Feedback; procedure Interpret_for_Multi is new Interpret (Multi_Feedback, Current_IO_Console, Custom_System_Calls ); Ada_file_name : constant String := "exm/mandelbrot.adb"; -- f : Ada.Streams.Stream_IO.File_Type; BD : Build_Data; post_mortem : Post_Mortem_Data; begin accept Start (id : Positive) do task_id := id; end Start; tick := Clock; Reset (gen); -- Open (f, In_File, Ada_file_name); Set_Main_Source_Stream (BD, Stream (f), Ada_file_name); Build_Main (BD); Close (f); -- if Build_Successful (BD) then Put_Line ("S" & sep & " Task" & sep & Integer'Image (task_id) & sep & " successful compilation. Running the VM."); Interpret_for_Multi (BD, post_mortem); if Image (post_mortem.Unhandled) = "User_Abort" then Put_Line ("A2" & sep & " Task" & sep & Integer'Image (task_id) & sep & " got ""User_Abort"" exception from HAC VM."); else Put_Line ("D" & sep & " Task" & sep & Integer'Image (task_id) & sep & " is done."); end if; end if; end HAC_Instance; hacs : array (1 .. 20) of HAC_Instance; begin Put_Line ("Event" & sep & " Task #" & sep & " Message"); for T in hacs'Range loop hacs (T).Start (T); delay 0.01; end loop; end Launch_Tasks; begin Launch_Tasks; end HAC_Multi; ================================================ FILE: src/apps/hac_pkg.adb ================================================ with HAC_Sys.Defs, HAC_Sys.PCode.Interpreter, HAC_Sys.Targets.AMD64_Windows_Console_FASM; with Show_MIT_License; with Ada.Command_Line, Ada.Containers, Ada.Directories, Ada.Exceptions, Ada.Text_IO; package body HAC_Pkg is procedure Compilation_Feedback (message : String) is begin case verbosity is when 0 => null; when 1 => HAT.Put_Line (message); when others => HAT.Put_Line (HAC_margin_2 & message); end case; end Compilation_Feedback; package body Path_Management is overriding function Exists (cat : File_Catalogue; name : String) return Boolean is begin return cat.Full_Source_Name (name) /= ""; end Exists; overriding function Full_Source_Name (cat : File_Catalogue; name : String) return String is -- Search order: same as GNAT's, -- cf. 4.2.2 Search Paths and the Run-Time Library (RTL). use Ada.Directories; begin -- 0) The file name as such exists. if HAC_Sys.Files.Default.File_Catalogue (cat).Exists (name) then return name; end if; -- 1) The directory containing the source file of the main unit -- being compiled (the file name on the command line). declare fn : constant String := Ada.Directories.Containing_Directory (HAT.To_String (main_Ada_file_name)) & HAT.Directory_Separator & name; begin if Exists (fn) and then Kind (fn) = Ordinary_File then return fn; end if; exception when others => null; -- Continue searching elsewhere. end; -- 2) Each directory named by an -I switch given on the -- hac command line, in the order given. declare fn : constant String := HAT.Search_File (name, HAT.To_String (command_line_source_path)); begin if fn /= "" then return fn; end if; end; -- 3) Omitted (directories listed in the text file whose name is given by ADA_PRJ_INCLUDE_FILE). -- 4) Each of the directories listed in the value of the ADA_INCLUDE_PATH environment variable. declare fn : constant String := HAT.Search_File (name, HAT.To_String (HAT.Get_Env ("ADA_INCLUDE_PATH"))); begin if fn /= "" then return fn; end if; end; -- 5) Omitted (content of the ada_source_path file). -- Now, extra search capabilities specific to HAC: declare fn : constant String := HAT.Search_File (name, HAT.To_String (cat.extra_path)); begin if fn /= "" then return fn; end if; end; return ""; end Full_Source_Name; overriding function Is_Open (cat : File_Catalogue; name : String) return Boolean is begin return HAC_Sys.Files.Default.File_Catalogue (cat).Is_Open (cat.Full_Source_Name (name)); end Is_Open; overriding procedure Source_Open (cat : in out File_Catalogue; name : in String; stream : out HAC_Sys.Files.Root_Stream_Class_Access) is ffn : constant String := cat.Full_Source_Name (name); begin if ffn = "" then raise Ada.Directories.Name_Error; else HAC_Sys.Files.Default.File_Catalogue (cat).Source_Open (ffn, stream); end if; end Source_Open; overriding procedure Skip_Shebang (cat : in out File_Catalogue; name : in String; shebang_offset : out Natural) is begin HAC_Sys.Files.Default.File_Catalogue (cat).Skip_Shebang (cat.Full_Source_Name (name), shebang_offset); end Skip_Shebang; overriding procedure Close (cat : in out File_Catalogue; name : String) is begin HAC_Sys.Files.Default.File_Catalogue (cat).Close (cat.Full_Source_Name (name)); end Close; overriding procedure Add_to_Source_Path (cat : in out File_Catalogue; new_dir : String) is use HAT; begin cat.extra_path := cat.extra_path & ';' & new_dir; end Add_to_Source_Path; end Path_Management; procedure PLCE (s : String) is use Ada.Text_IO; begin Put_Line (Current_Error, s); end PLCE; procedure Option_Head (s : String) is begin NLCE; PLCE ("______"); PLCE ("Option " & s); end Option_Head; procedure NLCE is use Ada.Text_IO; begin New_Line (Current_Error); end NLCE; procedure Help (level : Positive) is use HAC_Sys.Defs, Ada.Text_IO; function Show_Level (r : Compile_Remark) return String is (" (from level" & Minimum_Level (r)'Image & ')'); begin PLCE ("HAC: command-line build and execution tool for HAC (HAC Ada Compiler)"); PLCE (version_info); PLCE ("Main URL: " & HAC_Sys.web); PLCE (" Sources, site #1: " & HAC_Sys.web2); PLCE (" Sources, site #2: " & HAC_Sys.web3); PLCE (" Alire Crate: " & HAC_Sys.web4); NLCE; PLCE ("Usage: hac [options] main.adb [command-line parameters for main]"); NLCE; PLCE ("Options: -h, h1 : this help"); PLCE (" -h2 : show more help & details about options"); NLCE; PLCE (" -a : assembler output"); PLCE (" -c : compile only"); PLCE (" -d : dump compiler information in " & compiler_dump_name); PLCE (" -I : specify source files search path"); PLCE (" -rx : enable / disable remarks"); PLCE (" -tx : target machine (default: HAC VM)"); PLCE (" -v, v1 : verbose"); PLCE (" -v2 : very verbose"); NLCE; PLCE ("Note: HAC (this command-line tool) accepts source files with shebang's,"); PLCE (" for instance: #!/usr/bin/env hac or #!/usr/bin/hac"); Show_MIT_License (Current_Error, "hac_sys.ads"); if level > 1 then NLCE; PLCE ("/------------------------------------------\"); PLCE ("| Extended help for HAC (command: hac -h2) |"); PLCE ("\------------------------------------------/"); Option_Head ("-I : specify source files search path"); NLCE; PLCE (" The search path is a list of directories separated by commas (,) or semicolons (;)."); PLCE (" HAC searches Ada source files in the following order:"); PLCE (" 1) The directory containing the source file of the main unit"); PLCE (" being compiled (the file name on the command line)."); PLCE (" 2) Each directory named by an -I switch given on the"); PLCE (" hac command line, in the order given."); PLCE (" 3) Each of the directories listed in the value of the ADA_INCLUDE_PATH"); PLCE (" environment variable."); Option_Head ("-rx : enable remarks (warnings or notes) of kind x"); PLCE (" -rX : disable remarks for letter x"); PLCE (" x ="); PLCE (" 0 .. 3 : enable remarks of level x; default is" & default_remark_level'Image); PLCE (" k : notes for constant variables" & Show_Level (note_constant_variable)); PLCE (" r : notes for redundant constructs" & Show_Level (note_redundant_construct)); PLCE (" u : notes for unused items" & Show_Level (note_unused_item)); PLCE (" v : warnings for uninitialized variables or parameters" & Show_Level (warn_read_but_not_written)); Option_Head ("-tx : set target machine to x"); PLCE (" x ="); PLCE (" amd64_windows_console_fasm"); NLCE; end if; Ada.Text_IO.Put ("Press Return"); Ada.Text_IO.Skip_Line; end Help; type Target_List is (hac_vm, amd64_windows_console_fasm); target_choice : Target_List := hac_vm; procedure Set_Target (name : String) is begin target_choice := Target_List'Value (name); case target_choice is when hac_vm => null; -- Actual target in BD.CD is already initialized. when amd64_windows_console_fasm => target := new HAC_Sys.Targets.AMD64_Windows_Console_FASM.Machine; end case; end Set_Target; procedure Failure is use HAT; begin if Ends_With (main_Ada_file_name, ".hac") then -- Main has the "HAC script extension", possibly run -- from Explorer, Nautilus, etc. Put ("Failure in " & main_Ada_file_name & ", press Return"); Skip_Line; end if; Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Failure); end Failure; procedure Run_HAC_VM (BD : in out HAC_Sys.Builder.Build_Data; arg_pos : Positive) is use HAC_Sys.PCode.Interpreter, HAT; use Ada.Containers; -- procedure Show_Line_Information ( File_Name : String; -- Example: hac-pcode-interpreter.adb Block_Name : String; -- Example: HAC.PCode.Interpreter.Do_Write_Formatted Line_Number : Positive ) is begin PLCE (File_Name & ": " & Block_Name & " at line" & Integer'Image (Line_Number)); end Show_Line_Information; -- procedure CIO_Trace_Back is new Show_Trace_Back (Show_Line_Information); -- post_mortem : Post_Mortem_Data; unhandled_found : Boolean; t1, t2 : Time; begin if verbosity >= 1 then New_Line; end if; t1 := Clock; Interpret_on_Current_IO (BD, arg_pos, Ada.Directories.Full_Name (To_String (main_Ada_file_name)), post_mortem); t2 := Clock; unhandled_found := Is_Exception_Raised (post_mortem.Unhandled); if verbosity >= 2 then -- The "if expression" commented out here confuses ObjectAda 10.4. -- -- Put_Line -- (HAC_margin_3 & -- (if unhandled_found then -- "VM interpreter stopped execution of " & -- Ada_file_name & " due to an unhandled exception." -- else -- "VM interpreter done after" & Duration'Image (t2 - t1) & " seconds.")); -- if unhandled_found then Put_Line ( HAC_margin_3 & "VM interpreter stopped execution of " & main_Ada_file_name & " due to an unhandled exception."); else Put_Line ( HAC_margin_3 & "VM interpreter done after" & Duration'Image (t2 - t1) & " seconds." ); end if; end if; if unhandled_found then PLCE ("HAC VM: raised " & Image (post_mortem.Unhandled)); PLCE (Message (post_mortem.Unhandled)); PLCE ("Trace-back: approximate location"); CIO_Trace_Back (post_mortem.Unhandled); Failure; elsif verbosity >= 1 then Put_Line ("Execution of " & main_Ada_file_name & " completed."); end if; if verbosity >= 2 then Put_Line ( "Maximum stack usage:" & Integer'Image (post_mortem.Max_Stack_Usage) & " of" & Integer'Image (post_mortem.Stack_Size) & " memory units, around" & Integer'Image (100 * post_mortem.Max_Stack_Usage / post_mortem.Stack_Size) & "%." ); end if; if verbosity >= 1 then if post_mortem.Open_Files.Length > 0 then Put_Line ("List of files that were left open during execution:"); for ofd of post_mortem.Open_Files loop Put_Line (" Name: " & HAT.To_String (ofd.Name) & ", mode: " & Ada.Text_IO.File_Mode'Image (ofd.Mode)); end loop; end if; end if; exception when E : Abnormal_Termination => PLCE ("Abnormal Termination (VM): " & Ada.Exceptions.Exception_Message (E)); Failure; when Ada.Text_IO.Name_Error => PLCE (HAC_margin_3 & "Error: file """ & To_String (main_Ada_file_name) & """ not found (perhaps in exm or test subdirectory ?)"); Failure; end Run_HAC_VM; function Remaining_Arguments (arg_pos : Positive) return String is (if arg_pos <= Ada.Command_Line.Argument_Count then Ada.Command_Line.Argument (arg_pos) & Remaining_Arguments (arg_pos + 1) else ""); procedure Post_Build_amd64_windows_console_fasm (BD : HAC_Sys.Builder.Build_Data) is use HAT; use Ada.Directories; main_base_name : constant String := Base_Name (To_String (main_Ada_file_name)); begin Shell_Execute ("fasm " & BD.target.Assembler_File_Name & ' ' & main_base_name & ".exe"); end Post_Build_amd64_windows_console_fasm; procedure Run_amd64_windows_console_fasm (arg_pos : Positive) is use HAT; use Ada.Directories; main_base_name : constant String := Base_Name (To_String (main_Ada_file_name)); begin if Get_Env ("OS") = "Windows_NT" then Shell_Execute (main_base_name & ' ' & Remaining_Arguments (arg_pos)); else Put_Line ("No run: build target (AMD64/Windows) is different than this system"); end if; end Run_amd64_windows_console_fasm; procedure Post_Build (BD : in out HAC_Sys.Builder.Build_Data) is begin case target_choice is when hac_vm => null; when amd64_windows_console_fasm => Post_Build_amd64_windows_console_fasm (BD); end case; end Post_Build; procedure Run (BD : in out HAC_Sys.Builder.Build_Data; arg_pos : Positive) is use HAT; begin if verbosity >= 2 then if BD.CD.Is_HAC_VM then Put_Line (HAC_margin_2 & "Starting p-code VM interpreter..."); else Put_Line (HAC_margin_2 & "Running native (if target = native)"); end if; end if; if target_choice /= hac_vm then Put_Line ("*** Caution *** Native code generation is experimental and incomplete !"); end if; case target_choice is when hac_vm => Run_HAC_VM (BD, arg_pos); when amd64_windows_console_fasm => Run_amd64_windows_console_fasm (arg_pos); end case; end Run; end HAC_Pkg; ================================================ FILE: src/apps/hac_pkg.ads ================================================ -- This package contains call-backs for the -- HAC command-line application, as well as various helpers. with HAC_Sys.Builder, HAC_Sys.Files.Default, HAC_Sys.Targets; with HAT; package HAC_Pkg is verbosity : Natural := 0; version_info : constant String := "Compiler version: " & HAC_Sys.version & " dated " & HAC_Sys.reference & '.'; HAC_margin_1 : constant String := "*******[ HAC ]******* "; HAC_margin_2 : constant String := " [ HAC ] "; HAC_margin_3 : constant String := "-------[ HAC ]------- "; command_line_source_path, main_Ada_file_name : HAT.VString; target : HAC_Sys.Targets.Abstract_Machine_Reference := null; procedure Compilation_Feedback (message : String); package Path_Management is -- Specific search path management type File_Catalogue is limited new HAC_Sys.Files.Default.File_Catalogue with record extra_path : HAT.VString; end record; -- We enrich the default file system with searching of -- files through pathes. overriding function Exists (cat : File_Catalogue; name : String) return Boolean; overriding function Full_Source_Name (cat : File_Catalogue; name : String) return String; overriding function Is_Open (cat : File_Catalogue; name : String) return Boolean; overriding procedure Source_Open (cat : in out File_Catalogue; name : in String; stream : out HAC_Sys.Files.Root_Stream_Class_Access); overriding procedure Skip_Shebang (cat : in out File_Catalogue; name : in String; shebang_offset : out Natural); overriding procedure Close (cat : in out File_Catalogue; name : String); overriding procedure Add_to_Source_Path (cat : in out File_Catalogue; new_dir : String); end Path_Management; compiler_dump_name : constant String := "compiler_dump.lst"; compile_only : Boolean := False; procedure PLCE (s : String); -- Put_Line on Current Error procedure NLCE; -- New_Line on Current Error procedure Help (level : Positive); procedure Set_Target (name : String); procedure Failure; procedure Post_Build (BD : in out HAC_Sys.Builder.Build_Data); procedure Run (BD : in out HAC_Sys.Builder.Build_Data; arg_pos : Positive); end HAC_Pkg; ================================================ FILE: src/apps/show_mit_license.adb ================================================ with Ada.Text_IO; procedure Show_MIT_License (file : Ada.Text_IO.File_Type; source_with_license : String) is use Ada.Text_IO; begin New_Line (file); Put_Line (file, "| This software is free and open-source."); Put_Line (file, "| It is provided ""as is"", WITHOUT WARRANTY OF ANY KIND."); Put_Line (file, "| For the full license wording, see the header" & " (copyright & MIT license)"); Put_Line (file, "| appearing on top of this software's source files."); Put_Line (file, "| In doubt, check the file: " & source_with_license); New_Line (file); end Show_MIT_License; ================================================ FILE: src/compile/emit/hac_sys-targets-amd64_windows_console_fasm.adb ================================================ package body HAC_Sys.Targets.AMD64_Windows_Console_FASM is -- Technical quotations are from: -- AMD64 Architecture Programmer's Manual -- 24594 - Rev. 3.35 - June 2023 use Defs, HAT; asm_name : constant String := "hac_generated.asm"; overriding procedure Initialize_Code_Emission (m : in out Machine) is begin Create (m.asm_file, asm_name); Put_Line (m.asm_file, "; Assembler file for the Flat Assembler - https://flatassembler.net/"); New_Line (m.asm_file); Put_Line (m.asm_file, "format PE64 console"); Put_Line (m.asm_file, "entry _start"); Put_Line (m.asm_file, "include 'include\win64a.inc'"); New_Line (m.asm_file); Put_Line (m.asm_file, "section '.code' code readable executable"); New_Line (m.asm_file); Put_Line (m.asm_file, "_start:"); end Initialize_Code_Emission; overriding procedure Finalize_Code_Emission (m : in out Machine; strings : String) is procedure Dump_Strings is printable : Boolean := True; col : Integer; function Needs_New_Line return Boolean is (col mod 60 = 10); procedure Separate_with_Comma is begin if col > strings'First then Put (m.asm_file, ", "); end if; if Needs_New_Line then Put_Line (m.asm_file, "\ "); Put (m.asm_file, " "); end if; end Separate_with_Comma; begin Put_Line (m.asm_file, "_hac_end_of_line db 10, 0"); Put_Line (m.asm_file, "_hac_decimal_format db ""%d"", 0"); Put (m.asm_file, "_hac_strings_pool db ""X"); for i in strings'Range loop col := i; if Character'Pos (strings (i)) in 32 .. 127 then if printable then if Needs_New_Line then Put_Line (m.asm_file, """, \"); Put (m.asm_file, " """); end if; else Separate_with_Comma; Put (m.asm_file, '"'); printable := True; end if; Put (m.asm_file, strings (i)); else if printable then Put (m.asm_file, '"'); printable := False; end if; Separate_with_Comma; Put (m.asm_file, Character'Pos (strings (i)), 0); end if; end loop; if printable then Put (m.asm_file, '"'); end if; New_Line (m.asm_file); end Dump_Strings; begin if strings'Length > 0 then Put_Line (m.asm_file, "section '.data' data readable writeable"); Dump_Strings; New_Line (m.asm_file); end if; Put_Line (m.asm_file, "section '.idata' import data readable"); Put_Line (m.asm_file, "library kernel,'kernel32.dll',\"); Put_Line (m.asm_file, " msvcrt,'msvcrt.dll'"); Put_Line (m.asm_file, "import kernel,\"); Put_Line (m.asm_file, " ExitProcess,'ExitProcess'"); Put_Line (m.asm_file, "import msvcrt,\"); Put_Line (m.asm_file, " printf,'printf'"); Close (m.asm_file); end Finalize_Code_Emission; procedure Output (m : Machine; asm : Assembler_Line) is instr_img : constant String := (case asm.instr is when push_immediate => "push", when xor_i => "xor", when others => asm.instr'Image); begin Put_Line (m.asm_file, asm.label & Integer'Max (0, 9 - Length (asm.label)) * ' ' & To_Lower (+instr_img) & (20 - instr_img'Length) * ' ' & asm.operand_1 & (if asm.operand_2 = "" then +"" else ", " & asm.operand_2)); end Output; procedure Peephole_Optimization (m : in out Machine) is aux_line : Assembler_Line; -- procedure Pass is lines : Natural := Integer (m.asm_buf.Length); current : Positive := 1; cur_instr : Instruction; -- procedure Replace_Pair is begin m.asm_buf.Delete (current); m.asm_buf (current) := aux_line; lines := lines - 1; end Replace_Pair; -- procedure Swap_Pair is begin aux_line := m.asm_buf (current); m.asm_buf (current) := m.asm_buf (current + 1); m.asm_buf (current + 1) := aux_line; end Swap_Pair; -- begin while current <= lines loop cur_instr := m.asm_buf (current).instr; if current < lines and then m.asm_buf (current + 1).label = "" then -- Optimization involving this line and the next one. case cur_instr is when push | push_immediate => -- Displace or simplify PUSH instruction. if cur_instr = push_immediate or else m.asm_buf (current).operand_1 = "rax" then case m.asm_buf (current + 1).instr is when pop => -- Fold "push x; pop y;" into "mov y, x" aux_line := (label => m.asm_buf (current).label, instr => mov, operand_1 => m.asm_buf (current + 1).operand_1, operand_2 => m.asm_buf (current).operand_1); Replace_Pair; when mov | add | sub | imul | idiv | xor_i => -- !! check it is not an operation involving the stack pointer !! -- Move the "push" one line further. Perhaps it meets a "pop"... if m.asm_buf (current).operand_1 = "rax" and then (m.asm_buf (current + 1).operand_1 = "rax" or else m.asm_buf (current + 1).instr = idiv) then -- The pushed register *** is modified on next instruction, -- so we can't displace the current "push *** " instrction after it. null; else Swap_Pair; end if; when others => null; end case; end if; when others => null; end case; end if; current := current + 1; end loop; end Pass; begin for pass_count in 1 .. 10 loop Pass; end loop; end Peephole_Optimization; procedure Flush_Assembler (m : in out Machine) is begin Peephole_Optimization (m); for l of m.asm_buf loop Output (m, l); end loop; m.asm_buf.Clear; end Flush_Assembler; procedure Emit (m : in out Machine; instr : Instruction; operand_1 : String := ""; operand_2 : String := ""; label : String := "") is begin m.asm_buf.Append ((label => +label, instr => instr, operand_1 => +operand_1, operand_2 => +operand_2)); end Emit; overriding procedure Emit_Arithmetic_Binary_Instruction (m : in out Machine; operator : Defs.Arithmetic_Binary_Operator; base_typ : Defs.Numeric_Typ) is begin case base_typ is when Floats => -- case operator is -- when Plus => raise combination_not_supported; -- when Minus => raise combination_not_supported; -- when Times => raise combination_not_supported; -- when Divide => raise combination_not_supported; -- when Power => raise combination_not_supported; -- end case; raise combination_not_supported with base_typ'Image & ' ' & operator'Image; when Ints => Emit (m, pop, "r11"); -- Right Emit (m, pop, "rax"); -- Left case operator is when Plus => Emit (m, add, "rax", "r11"); when Minus => Emit (m, sub, "rax", "r11"); when Times => Emit (m, imul, "rax", "r11"); when Divide => Emit (m, xor_i, "rdx, rdx"); Emit (m, idiv, "r11"); when Power => raise combination_not_supported with base_typ'Image & ' ' & operator'Image; end case; Emit (m, push, "rax"); end case; end Emit_Arithmetic_Binary_Instruction; overriding procedure Emit_Halt (m : in out Machine) is begin Emit (m, stdcall, "[ExitProcess], 0"); Flush_Assembler (m); New_Line (m.asm_file); end Emit_Halt; overriding procedure Emit_Push_Discrete_Literal (m : in out Machine; x : Defs.HAC_Integer) is begin -- P.327: "In 64-bit mode, the operand size of all -- PUSH instructions defaults to 64 bits" Emit (m, push_immediate, HAC_Image (x)); end Emit_Push_Discrete_Literal; overriding procedure Emit_Push_Discrete_Literals (m : in out Machine; x, y : Defs.HAC_Integer) is begin Emit (m, push_immediate, HAC_Image (x)); Emit (m, push_immediate, HAC_Image (y)); end Emit_Push_Discrete_Literals; overriding procedure Emit_HAT_Builtin_Procedure (m : in out Machine; builtin_proc : Defs.SP_Code; parameter : Defs.HAC_Integer) is begin case builtin_proc is when SP_Put .. SP_Put_Line => case Defs.Typen'Val (parameter) is -- Register numbering is parameter position, plus 10. when String_Literals => Emit (m, pop, "r12"); -- String Position in the strings pool Emit (m, add, "r12, _hac_strings_pool"); Emit (m, pop, "r11"); -- String Length, discarded Emit (m, ccall, "[printf], r12"); when Ints => Emit (m, pop, "r13"); -- Base - support it !! Emit (m, pop, "r12"); -- Width - support it !! Emit (m, pop, "r11"); -- Integer value Emit (m, ccall, "[printf], _hac_decimal_format, r11"); when others => raise combination_not_supported; end case; if builtin_proc = SP_Put_Line then m.Emit_HAT_Builtin_Procedure (SP_New_Line, 0); end if; when SP_New_Line => Emit (m, ccall, "[printf], _hac_end_of_line"); when others => raise combination_not_supported with builtin_proc'Image; end case; end Emit_HAT_Builtin_Procedure; overriding function Assembler_File_Name (m : Machine) return String is (asm_name); end HAC_Sys.Targets.AMD64_Windows_Console_FASM; ================================================ FILE: src/compile/emit/hac_sys-targets-amd64_windows_console_fasm.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- This target is AMD64, Windows, using the Flat Assembler (FASM). -- https://flatassembler.net/ with Ada.Containers.Vectors; with HAT; package HAC_Sys.Targets.AMD64_Windows_Console_FASM is type Machine is limited new Targets.Machine with private; -------------------- -- Informations -- -------------------- overriding function Name (m : Machine) return String is ("Windows 64 Console via FASM"); overriding function CPU (m : Machine) return String is ("AMD64"); overriding function OS (m : Machine) return String is ("Windows"); overriding function Null_Terminated_String_Literals (m : Machine) return Boolean is (True); ------------------------------------------- -- Initialize & Finalize Code Emission -- ------------------------------------------- overriding procedure Initialize_Code_Emission (m : in out Machine); overriding procedure Finalize_Code_Emission (m : in out Machine; strings : String); ---------------------------- -- Machine Instructions -- ---------------------------- overriding procedure Emit_Arithmetic_Binary_Instruction (m : in out Machine; operator : Defs.Arithmetic_Binary_Operator; base_typ : Defs.Numeric_Typ); overriding procedure Emit_Halt (m : in out Machine); overriding procedure Emit_Push_Discrete_Literal (m : in out Machine; x : Defs.HAC_Integer); overriding procedure Emit_Push_Discrete_Literals (m : in out Machine; x, y : Defs.HAC_Integer); ---------------------------- -- Built-In Subprograms -- ---------------------------- overriding procedure Emit_HAT_Builtin_Procedure (m : in out Machine; builtin_proc : Defs.SP_Code; parameter : Defs.HAC_Integer); ------------- -- Misc. -- ------------- overriding function Assembler_File_Name (m : Machine) return String; private type Instruction is (add, ccall, idiv, imul, mov, pop, push, push_immediate, stdcall, sub, xor_i); type Assembler_Line is record label : HAT.VString := HAT.Null_VString; instr : Instruction; operand_1 : HAT.VString := HAT.Null_VString; operand_2 : HAT.VString := HAT.Null_VString; end record; package Assembler_Buffers is new Ada.Containers.Vectors (Positive, Assembler_Line); type Machine is limited new Targets.Machine with record asm_file : HAT.File_Type; asm_buf : Assembler_Buffers.Vector; end record; end HAC_Sys.Targets.AMD64_Windows_Console_FASM; ================================================ FILE: src/compile/emit/hac_sys-targets-hac_virtual_machine.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Defs, HAC_Sys.Errors, HAC_Sys.PCode; package body HAC_Sys.Targets.HAC_Virtual_Machine is overriding procedure Finalize_Code_Emission (m : in out Machine; strings : String) is use Defs; begin if m.CD.Blocks_Table (1).VSize > StMax - (STKINCR * m.CD.Tasks_Definitions_Count) then Errors.Error (m.CD.all, err_stack_size); end if; end Finalize_Code_Emission; use Compiler.PCode_Emit, PCode; overriding procedure Emit_Arithmetic_Binary_Instruction (m : in out Machine; operator : Defs.Arithmetic_Binary_Operator; base_typ : Defs.Numeric_Typ) is use Defs; begin case base_typ is when Floats => case operator is when Plus => Emit (m.CD.all, k_ADD_Float); when Minus => Emit (m.CD.all, k_SUBTRACT_Float); when Times => Emit (m.CD.all, k_MULT_Float); when Divide => Emit (m.CD.all, k_DIV_Float); when Power => Emit (m.CD.all, k_Power_Float); end case; when Ints => case operator is when Plus => Emit (m.CD.all, k_ADD_Integer); when Minus => Emit (m.CD.all, k_SUBTRACT_Integer); when Times => Emit (m.CD.all, k_MULT_Integer); when Divide => Emit (m.CD.all, k_DIV_Integer); when Power => Emit (m.CD.all, k_Power_Integer); end case; end case; end Emit_Arithmetic_Binary_Instruction; overriding procedure Emit_Halt (m : in out Machine) is begin Emit (m.CD.all, k_Halt_Interpreter); end Emit_Halt; overriding procedure Emit_Push_Discrete_Literal (m : in out Machine; x : Defs.HAC_Integer) is begin Emit_1 (m.CD.all, k_Push_Discrete_Literal, x); end Emit_Push_Discrete_Literal; overriding procedure Emit_Push_Discrete_Literals (m : in out Machine; x, y : Defs.HAC_Integer) is begin Emit_2 (m.CD.all, k_Push_Two_Discrete_Literals, x, y); end Emit_Push_Discrete_Literals; overriding procedure Emit_HAT_Builtin_Procedure (m : in out Machine; builtin_proc : Defs.SP_Code; parameter : Defs.HAC_Integer) is begin Emit_2 (m.CD.all, k_HAT_Procedure, Defs.SP_Code'Pos (builtin_proc), parameter); end Emit_HAT_Builtin_Procedure; end HAC_Sys.Targets.HAC_Virtual_Machine; ================================================ FILE: src/compile/emit/hac_sys-targets-hac_virtual_machine.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- Here is the code emission for the original HAC target, the -- HAC Virtual Machine ("p-code"). with HAC_Sys.Co_Defs; package HAC_Sys.Targets.HAC_Virtual_Machine is type Machine is limited new Targets.Machine with record CD : Co_Defs.Compiler_Data_Access; -- ^ In the future, the instruction table and other items -- will be stored here and we can remove CD. -- As long as this field exists, we keep it public for -- convenience (it is needed in method Set_Target in Co_Defs). end record; -------------------- -- Informations -- -------------------- overriding function Name (m : Machine) return String is ("HAC Virtual Machine"); overriding function CPU (m : Machine) return String is ("HAC VM"); overriding function OS (m : Machine) return String is ("Any"); overriding function Null_Terminated_String_Literals (m : Machine) return Boolean is (False); ------------------------------------------- -- Initialize & Finalize Code Emission -- ------------------------------------------- overriding procedure Finalize_Code_Emission (m : in out Machine; strings : String); ---------------------------- -- Machine Instructions -- ---------------------------- overriding procedure Emit_Arithmetic_Binary_Instruction (m : in out Machine; operator : Defs.Arithmetic_Binary_Operator; base_typ : Defs.Numeric_Typ); overriding procedure Emit_Halt (m : in out Machine); overriding procedure Emit_Push_Discrete_Literal (m : in out Machine; x : Defs.HAC_Integer); overriding procedure Emit_Push_Discrete_Literals (m : in out Machine; x, y : Defs.HAC_Integer); ---------------------------- -- Built-In Subprograms -- ---------------------------- overriding procedure Emit_HAT_Builtin_Procedure (m : in out Machine; builtin_proc : Defs.SP_Code; parameter : Defs.HAC_Integer); ------------- -- Misc. -- ------------- overriding function Assembler_File_Name (m : Machine) return String is ("asm_dump.pca"); -- PCA = PCode Assembler end HAC_Sys.Targets.HAC_Virtual_Machine; ================================================ FILE: src/compile/emit/hac_sys-targets-semantics.adb ================================================ with HAC_Sys.Defs; with Ada.Unchecked_Deallocation; package body HAC_Sys.Targets.Semantics is overriding procedure Finalize (m : in out Machine) is procedure Unchecked_Free is new Ada.Unchecked_Deallocation (Declaration_Line_Maps.Map, Declaration_Line_Map_Access); begin for line_map_a of m.loc_map loop Unchecked_Free (line_map_a); end loop; end Finalize; overriding procedure Initialize_Code_Emission (m : in out Machine) is use HAT; begin m.busy := True; m.started := Clock; m.ref_map.Clear; end Initialize_Code_Emission; overriding procedure Finalize_Code_Emission (m : in out Machine; strings : String) is use HAT; begin m.finished := Clock; m.total_time := m.finished - m.started; m.busy := False; end Finalize_Code_Emission; trace : constant Boolean := False; overriding procedure Mark_Declaration (m : in out Machine; is_built_in : Boolean := False) is use File_Names_to_Line_Maps_Maps; curs : Cursor; line_map_a : Declaration_Line_Map_Access; begin -- Feed the declaration array used for getting a declaration's coordinates -- from an index in the identifier table, possibly obtained -- via Find_Referenced_Declaration. -- m.decl_array (m.CD.Id_Count) := (file_name => (if is_built_in then HAT.Null_VString else m.CD.CUD.source_file_name), line => (if is_built_in then -1 else m.CD.CUD.location.line), column => (if is_built_in then -1 else m.CD.CUD.location.column_start), is_built_in => is_built_in, id_index => m.CD.Id_Count, others => <>); -- Feed the structures for searching possible declarations -- at any given point of any source file. -- if not is_built_in then -- 1) Find or create the line map associated to the file name. curs := m.loc_map.Find (m.CD.CUD.source_file_name); if curs = No_Element then line_map_a := new Declaration_Line_Maps.Map; m.loc_map.Insert (m.CD.CUD.source_file_name, line_map_a); else line_map_a := Element (curs); end if; -- 2) Insert the infos for the declaration into the line map, -- possibly replacing a value for the same line number. line_map_a.Include (m.CD.CUD.location.line, m.CD.Id_Count); end if; end Mark_Declaration; procedure Add_Reference (m : in out Machine; ref : in Reference_Point'Class; located_id : in Natural) is use HAT; admit_duplicates : constant Boolean := True; key : constant VString := ref.file_name & ref.line'Image & ref.column'Image; -- ^ Example: "c:\files\source.adb 130 12" begin if trace then HAT.Put_Line ("Mark_Reference, key = [" & key & "] for Id" & located_id'Image & ", " & Defs.A2S (m.CD.id_table (located_id).name_with_case)); end if; if admit_duplicates then m.ref_map.Include (key, located_id); else m.ref_map.Insert (key, located_id); end if; exception when Constraint_Error => raise Constraint_Error with "Duplicate reference key: " & To_String (key); end Add_Reference; overriding procedure Mark_Spec_Body_Cross_References (m : in out Machine; spec_id, body_id : in Positive) is begin m.decl_array (spec_id).body_id := body_id; m.decl_array (body_id).spec_id := spec_id; -- -- Add references to own declarations so a user can go from -- spec to body, and vice-versa, directly from the declarations. Add_Reference (m, m.decl_array (spec_id), spec_id); Add_Reference (m, m.decl_array (body_id), body_id); end Mark_Spec_Body_Cross_References; overriding procedure Mark_Reference (m : in out Machine; located_id : Natural) is begin Add_Reference (m, Reference_Point' (m.CD.CUD.source_file_name, m.CD.CUD.location.line, m.CD.CUD.location.column_start), located_id); end Mark_Reference; procedure Find_Referenced_Declarations (m : in Machine; ref : in Reference_Point'Class; decl_1, decl_2 : out Declaration_Point'Class; found : out Natural) is use Co_Defs, HAT, Reference_Mapping; key : constant VString := ref.file_name & ref.line'Image & ref.column'Image; curs : constant Reference_Mapping.Cursor := m.ref_map.Find (key); index_1, index_2 : Positive; begin if curs = No_Element then decl_1.id_index := -1; decl_2.id_index := -1; found := 0; else index_1 := Element (curs); decl_1 := Declaration_Point'Class (m.decl_array (index_1)); if decl_1.spec_id = No_Id and then decl_1.body_id = No_Id then found := 1; else found := 2; -- There is a cross-reference. -- In any case, decl_1 will be the spec and decl_2 will be the body. if decl_1.spec_id /= No_Id then -- We have a body referencing a spec. index_2 := index_1; index_1 := decl_1.spec_id; decl_1 := Declaration_Point'Class (m.decl_array (index_1)); else -- We have a spec referencing a body. index_2 := decl_1.body_id; end if; decl_2 := Declaration_Point'Class (m.decl_array (index_2)); if Reference_Point (decl_2) = Reference_Point (ref) then -- Mark cases where ref point = decl. point decl_2.self_reference := True; end if; end if; if found >= 1 and then Reference_Point (decl_1) = Reference_Point (ref) then -- Mark cases where ref point = decl. point decl_1.self_reference := True; end if; end if; end Find_Referenced_Declarations; function Find_Possible_Declarations (m : Machine; point : Reference_Point'Class; prefix : String; max_list : Positive; max_scan : Positive) return String is use Co_Defs, HAT; line_map_a : Declaration_Line_Map_Access; idx, l : Natural; package Declaration_Lists is new Ada.Containers.Ordered_Maps (VString, VString); list : Declaration_Lists.Map; up_prefix : constant VString := To_Upper (+prefix); result : VString; -- procedure Include_Special (word : String) is up_word : constant VString := To_Upper (+word); begin if Starts_With (up_word, up_prefix) then list.Include (up_word, +word); end if; end Include_Special; -- begin -- 1) Find the line map associated to the given file name. declare use File_Names_to_Line_Maps_Maps; curs : constant Cursor := m.loc_map.Find (point.file_name); begin if curs = No_Element then return ""; else line_map_a := Element (curs); end if; end; -- 2) Find the last declaration before given line. declare use Declaration_Line_Maps; curs : Cursor; begin curs := line_map_a.Floor (point.line - 1); if curs = No_Element then return ""; else idx := Element (curs); end if; end; -- 3) Build an identifier list matching the prefix. if trace then Put_Line (+"Find_Possible_Declarations, identifiers matching """ & prefix & """:"); end if; for scan in 1 .. max_scan loop exit when idx = No_Id; exit when Integer (list.Length) = max_list; declare item : Identifier_Table_Entry renames m.CD.id_table (idx); use type Defs.Nesting_Level; begin if Starts_With (item.name, up_prefix) then -- Enter the identifier in a case-insensitive way: list.Include (item.name, item.name_with_case); if trace then Put_Line (+" " & item.name_with_case); end if; end if; if item.link = No_Id and then idx - 1 > No_Id and then m.CD.id_table (idx - 1).entity in prozedure | funktion and then item.lev > 0 and then m.CD.id_table (idx - 1).lev = item.lev - 1 then -- Jump to last declaration of level - 1, that -- is the subprogram declaration (if any) preceding -- the exhausted local identifier list. idx := idx - 1; else -- Jump to previous identifier index, or to No_Id. idx := item.link; end if; end; end loop; -- 4) Add some keywords Include_Special ("record"); Include_Special ("begin"); Include_Special ("end"); Include_Special ("case"); Include_Special ("when"); Include_Special ("others"); Include_Special ("loop"); Include_Special ("while"); Include_Special ("exit"); Include_Special ("return"); Include_Special ("procedure"); Include_Special ("function"); Include_Special ("package"); Include_Special ("body"); -- 5) Output the list as a single string seperated by spaces: for s of list loop -- Like `result := result & s & ' ';`, possibly more efficient: VStr_Pkg.Append (result, s); VStr_Pkg.Append (result, ' '); end loop; l := Length (result); if l > 0 then Delete (result, l, l); -- Remove trailing ' ' end if; if trace then Put_Line (+" [" & result & "]"); end if; return To_String (result); end Find_Possible_Declarations; end HAC_Sys.Targets.Semantics; ================================================ FILE: src/compile/emit/hac_sys-targets-semantics.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- The target Semantics produces no machine code but -- serves semantics analysis purposes, like cross-references -- for an editor with auto-complete, contextual menus and tool tips. with Ada.Containers.Hashed_Maps, Ada.Containers.Ordered_Maps, Ada.Strings.Unbounded.Hash; with HAC_Sys.Co_Defs; with HAT; package HAC_Sys.Targets.Semantics is type Reference_Point is tagged record file_name : HAT.VString; line, column : Integer; end record; type Declaration_Point is new Reference_Point with record is_built_in : Boolean; id_index : Integer; spec_id : Natural := Co_Defs.No_Id; -- For a body item: link to its spec. body_id : Natural := Co_Defs.No_Id; -- For a spec item: link to its body. self_reference : Boolean := False; end record; -- Reference map -- ============= -- -- This container holds all references to variables, functions, -- types, etc. The search key is the exact position of the first -- letter of the identifier. -- -- Key Value -- === ===== -- [file_name i j] index in the Id Table package Reference_Mapping is new Ada.Containers.Hashed_Maps (Key_Type => HAT.VString, -- [file_name i j] Element_Type => Positive, -- Index in the Id Table Hash => Ada.Strings.Unbounded.Hash, Equivalent_Keys => Ada.Strings.Unbounded."="); -- Declaration array -- ================= -- -- This container holds the exact position of the declarations. -- It is a simple array; the element #i corresponds to -- the identifer #i in the compiler's identifier table. -- -- Key Value -- === ===== -- index in Id Table file_name, i, j of declaration type Declaration_Point_Array is array (Co_Defs.Identifier_Table_Type'Range) of Declaration_Point; -- Possible sanity checks for an usage within an editor: -- - compare identifiers between the one at [file_name i j] and -- the one in the identifier table (weak check) -- - ensure the analysis was completed after the latest -- modification in the editor (keystroke, cut, paste, ...) -- -- Declaration localization -- ======================== -- -- This container provides the reverse operation of a -- Declaration_Point_Array. It enables the localization of the index -- of the last identifier on any given line in a source code file. -- From the index, it is then possible to gather all the identifiers -- visible at the next line (we don't go down to a column-wise -- localization for simplicity purposes). -- Due to nesting, that overall identifier list is not simply growing -- along the text, so the list of visible identifiers it is a part of -- a declaration tree. You build it by going from a leaf (index of -- the last identifier) to the root. package Declaration_Line_Maps is new Ada.Containers.Ordered_Maps (Key_Type => Integer, -- Line number Element_Type => Natural); -- Index in the Id Table type Declaration_Line_Map_Access is access Declaration_Line_Maps.Map; package File_Names_to_Line_Maps_Maps is new Ada.Containers.Hashed_Maps (Key_Type => HAT.VString, -- File_name Element_Type => Declaration_Line_Map_Access, Hash => Ada.Strings.Unbounded.Hash, Equivalent_Keys => Ada.Strings.Unbounded."="); type Machine is limited new Targets.Machine with record CD : Co_Defs.Compiler_Data_Access; ref_map : Reference_Mapping.Map; decl_array : Declaration_Point_Array; loc_map : File_Names_to_Line_Maps_Maps.Map; started : HAT.Time; finished : HAT.Time; total_time : Duration := 0.0; busy : Boolean := False with Volatile; end record; type Semantics_Machine_Reference is access all Machine'Class; overriding procedure Finalize (m : in out Machine); -------------------- -- Informations -- -------------------- overriding function Name (m : Machine) return String is ("HAC Semantics"); overriding function CPU (m : Machine) return String is ("No CPU"); overriding function OS (m : Machine) return String is ("Any"); overriding function Null_Terminated_String_Literals (m : Machine) return Boolean is (False); --------------------------------------- -- Initialize & Finalize Semantics -- --------------------------------------- overriding procedure Initialize_Code_Emission (m : in out Machine); overriding procedure Finalize_Code_Emission (m : in out Machine; strings : String); ---------------------------- -- Machine Instructions -- ---------------------------- overriding procedure Emit_Arithmetic_Binary_Instruction (m : in out Machine; operator : Defs.Arithmetic_Binary_Operator; base_typ : Defs.Numeric_Typ) is null; overriding procedure Emit_Halt (m : in out Machine) is null; overriding procedure Emit_Push_Discrete_Literal (m : in out Machine; x : Defs.HAC_Integer) is null; overriding procedure Emit_Push_Discrete_Literals (m : in out Machine; x, y : Defs.HAC_Integer) is null; ---------------------------- -- Built-In Subprograms -- ---------------------------- overriding procedure Emit_HAT_Builtin_Procedure (m : in out Machine; builtin_proc : Defs.SP_Code; parameter : Defs.HAC_Integer) is null; ------------- -- Misc. -- ------------- overriding function Assembler_File_Name (m : Machine) return String is (""); overriding procedure Mark_Reference (m : in out Machine; located_id : Natural); overriding procedure Mark_Declaration (m : in out Machine; is_built_in : Boolean := False); overriding procedure Mark_Spec_Body_Cross_References (m : in out Machine; spec_id, body_id : in Positive); -- From given valid reference point, get the corresponding declaration. procedure Find_Referenced_Declarations (m : in Machine; ref : in Reference_Point'Class; decl_1, decl_2 : out Declaration_Point'Class; found : out Natural); -- This is for "auto-complete" purposes. -- The list of identifiers is sorted, separated by spaces. function Find_Possible_Declarations (m : Machine; point : Reference_Point'Class; prefix : String; max_list : Positive; max_scan : Positive) return String; end HAC_Sys.Targets.Semantics; ================================================ FILE: src/compile/emit/hac_sys-targets.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- This package defines an interface for emitting machine -- code in an abstract way. This allows to emit code for -- various targets: -- -- - the HAC virtual machine ("p-code") -- - __ -- -- ! Goal: replace all "Emit" in the compiler with -- ! method calls from this interface. -- ! There will be likely hundreds of such methods in the end. -- ! This will be done progressively. Be patient (or contribute)! with HAC_Sys.Defs; with Ada.Finalization; package HAC_Sys.Targets is type Machine is abstract new Ada.Finalization.Limited_Controlled with null record; type Abstract_Machine_Reference is access all Machine'Class; -------------------- -- Informations -- -------------------- function Name (m : Machine) return String is abstract; function CPU (m : Machine) return String is abstract; function OS (m : Machine) return String is abstract; function Null_Terminated_String_Literals (m : Machine) return Boolean is abstract; ------------------------------------------- -- Initialize & Finalize Code Emission -- ------------------------------------------- procedure Initialize_Code_Emission (m : in out Machine) is null; procedure Finalize_Code_Emission (m : in out Machine; strings : in String) is null; ---------------------------- -- Machine Instructions -- ---------------------------- procedure Emit_Arithmetic_Binary_Instruction (m : in out Machine; operator : in Defs.Arithmetic_Binary_Operator; base_typ : in Defs.Numeric_Typ) is abstract; procedure Emit_Halt (m : in out Machine) is abstract; procedure Emit_Push_Discrete_Literal (m : in out Machine; x : Defs.HAC_Integer) is abstract; procedure Emit_Push_Discrete_Literals (m : in out Machine; x, y : Defs.HAC_Integer) is abstract; ---------------------------- -- Built-In Subprograms -- ---------------------------- procedure Emit_HAT_Builtin_Procedure (m : in out Machine; builtin_proc : in Defs.SP_Code; parameter : in Defs.HAC_Integer) is abstract; ------------- -- Misc. -- ------------- function Assembler_File_Name (m : Machine) return String is abstract; procedure Mark_Reference (m : in out Machine; located_id : Natural) is null; procedure Mark_Declaration (m : in out Machine; is_built_in : Boolean := False) is null; procedure Mark_Spec_Body_Cross_References (m : in out Machine; spec_id, body_id : in Positive) is null; combination_not_supported : exception; end HAC_Sys.Targets; ================================================ FILE: src/compile/hac_sys-builder.adb ================================================ with HAC_Sys.Compiler, HAC_Sys.Errors, HAC_Sys.Parser.Helpers, HAC_Sys.Targets.HAC_Virtual_Machine; with Ada.Characters.Handling, Ada.Exceptions, Ada.Integer_Text_IO, Ada.Text_IO, Ada.Unchecked_Deallocation; package body HAC_Sys.Builder is overriding procedure Finalize (BD : in out Build_Data) is procedure Unchecked_Free is new Ada.Unchecked_Deallocation (Co_Defs.Compiler_Data, Co_Defs.Compiler_Data_Access); begin Unchecked_Free (BD.CD); end Finalize; procedure Compile_Pending_Bodies_Single_Round (BD : in out Build_Data; num_pending : out Natural) is use HAT, Librarian, Targets; pending : Library_Unit_Vectors.Vector; previous_context : Co_Defs.Id_Maps.Map; needs_body_dummy : Boolean; begin for lu of BD.LD.library loop if lu.status in Spec_Done then pending.Append (lu); end if; end loop; -- -- Here: the list of pending bodies is now established -- for this round. Of course the library may expand -- further due to dependencies, via Register_Unit, -- adding pending bodies for the next round. -- num_pending := 0; if BD.CD.error_count > 0 then return; end if; for lu of pending loop declare upper_vname : constant VString := To_Upper (lu.full_name); upper_name : constant String := To_String (upper_vname); fn_spec : constant String := Find_Unit_File_Name (BD.LD, upper_name); fn_body : constant String := BD.LD.cat.Full_Body_Source_Name (fn_spec); begin case Spec_Done (lu.status) is when Body_Postponed => previous_context := BD.LD.library.Element (BD.LD.map.Element (upper_vname)).spec_context; BD.CD.remarks := BD.global_remarks; if BD.target /= null then BD.CD.target := BD.target; end if; Compiler.Compile_Unit (CD => BD.CD.all, LD => BD.LD, upper_name => upper_name, file_name => fn_body, as_specification => False, as_main_unit => upper_name = Defs.A2S (BD.CD.Id), needs_opening_a_stream => True, first_compilation => False, specification_id_index => lu.id_index, new_id_index => lu.id_body_index, unit_context => previous_context, kind => lu.kind, needs_body => needs_body_dummy); exit when BD.CD.error_count > 0; num_pending := num_pending + 1; when Spec_Only => if BD.LD.cat.Exists (fn_body) then Errors.Error (BD.CD.all, Defs.err_library_error, "library package declaration shall not have a body unless it " & "requires a body (Ada RM 7.2 (4)); found the file: " & fn_body); end if; end case; lu.status := Done; Change_Unit_Details (BD.LD, lu); end; end loop; end Compile_Pending_Bodies_Single_Round; procedure Build_Main (BD : in out Build_Data; body_compilation_rounds_limit : Rounds_Range := full_build) is use Co_Defs, Defs, HAT.VStr_Pkg, Librarian, Targets; use Ada.Exceptions, Ada.Text_IO; main_unit : Library_Unit := (full_name => BD.main_name_hint, kind => Procedure_Unit, status => In_Progress, -- Temporary value. id_index => No_Id, -- Temporary value. id_body_index => No_Id, -- Temporary value. spec_context => Id_Maps.Empty_Map); procedure Finalize_Target is begin BD.CD.target.Finalize_Code_Emission (BD.CD.Strings_Constants_Table (1 .. BD.CD.Strings_Table_Top)); end Finalize_Target; procedure Progress (s : String; min_level : Positive) is begin if BD.CD.trace.detail_level >= min_level then Compiler.Progress_Message (BD.CD.all, s); end if; end Progress; procedure Complete_Graph_Build is num_pending : Natural; begin if body_compilation_rounds_limit > 0 then Progress ("------ Compilation of possibly uncompiled unit bodies ------", 2); end if; for round in 1 .. body_compilation_rounds_limit loop Compile_Pending_Bodies_Single_Round (BD, num_pending); -- Now, other bodies may have appeared that have -- not been yet compiled. if num_pending > 0 then Progress ("------ End of Round" & round'Image & ", compiled bodies:" & num_pending'Image & " ------", 2); end if; exit when num_pending = 0; end loop; end Complete_Graph_Build; procedure Dump_Object_Map (var_map_file_name : String) is map_file : File_Type; use type HAC_Integer; begin Create (map_file, Out_File, var_map_file_name); Put_Line (map_file, " -* Object Table *-"); New_Line (map_file); Put_Line (map_file, " LOC Name scope"); Put_Line (map_file, "------------------------"); New_Line (map_file); for Blk of BD.CD.id_table (BD.CD.Blocks_Table (0).Last_Id_Idx + 1 .. BD.CD.Id_Count) loop if Blk.entity in Object_Kind then if Blk.xtyp.TYP /= NOTYP then Ada.Integer_Text_IO.Put (map_file, Integer (Blk.adr_or_sz), 4); Put (map_file, A2S (Blk.name) & " "); end if; Put_Line (map_file, (if Blk.lev = 1 then -- TBD: check this, should be 0. " Global (" else " Local (") & Blk.lev'Image & ')'); end if; end loop; New_Line (map_file); Close (map_file); end Dump_Object_Map; procedure Restart_with_Spec is fn_body : constant String := HAT.To_String (BD.CD.CUD.source_file_name); begin if BD.LD.cat.Is_Open (fn_body) then BD.LD.cat.Close (fn_body); end if; Progress ("\---> Cannot start build with a package's body.", 1); Progress (" We restart from a possible spec.", 1); BD.Build_Main_from_File (file_name => (if fn_body'Length = 0 then -- The body hasn't a file name (like just typed in an editor bound to HAC). -- Let's try to invent a name for the spec. Librarian.GNAT_File_Naming (A2S (BD.CD.main_unit_ident_with_case)) & ".ads" else BD.LD.cat.Full_Spec_Source_Name (fn_body)), -- body_compilation_rounds_limit => (if body_compilation_rounds_limit = Rounds_Range'Last then Rounds_Range'Last else body_compilation_rounds_limit + 1)); end Restart_with_Spec; procedure Build_Main_Inner is main_file_name : constant String := To_String (BD.CD.CUD.source_file_name); new_id_index : Natural; needs_body : Boolean; as_specification : Boolean; begin BD.LD.library.Clear; BD.LD.map.Clear; -- The main unit is from the beginning registered with the In_Progress -- status, so we can catch a possible circular dependency of the main -- unit on itself - directly or indirectly. -- -- Examples: -- with A; procedure A is begin null; end; -- -- with Y; procedure X is begin null; end; -- with X; procedure Y is begin null; end; -- Librarian.Register_Unit (BD.LD, main_unit); BD.CD.remarks := BD.global_remarks; if BD.target /= null then BD.CD.target := BD.target; end if; BD.CD.listing_requested := BD.listing_file_name /= ""; if BD.CD.listing_requested then Create (BD.CD.listing, Name => To_String (BD.listing_file_name)); Put_Line (BD.CD.listing, Defs.Header); end if; BD.CD.comp_dump_requested := BD.cmp_dump_file_name /= ""; if BD.CD.comp_dump_requested then Create (BD.CD.comp_dump, Name => To_String (BD.cmp_dump_file_name)); Put_Line (BD.CD.comp_dump, "Compiler: main unit file name is " & main_file_name); end if; Progress ("HAC Ada Compiler version " & version & ", " & reference, 1); Progress ("Compiling main: " & main_file_name, 1); begin Compiler.Init_for_new_Build (BD.CD.all); exception when End_Error => -- Happens if the text stream is empty. Errors.Error (BD.CD.all, err_unexpected_end_of_text, severity => Errors.major); end; as_specification := main_file_name (main_file_name'Last) = 's'; Compiler.Compile_Unit (CD => BD.CD.all, LD => BD.LD, upper_name => To_String (BD.main_name_hint), file_name => main_file_name, as_specification => as_specification, as_main_unit => True, needs_opening_a_stream => False, first_compilation => True, specification_id_index => No_Id, new_id_index => new_id_index, unit_context => main_unit.spec_context, kind => main_unit.kind, needs_body => needs_body); if as_specification then case main_unit.kind is when Subprogram_Unit => main_unit.status := Body_Postponed; when Package_Declaration => main_unit.status := (if needs_body then Body_Postponed else Spec_Only); when Package_Body => null; -- Not relevant (spec.) end case; else case main_unit.kind is when Procedure_Unit => -- !! The following should be performed by Statements_Part_Closing -- in Parser... But it doesn't happen for the main block. BD.CD.Blocks_Table (1).SrcTo := BD.CD.CUD.location.line; when Function_Unit => null; when Package_Body => null; when Package_Declaration => null; -- not relevant end case; main_unit.status := Done; end if; Progress ("Compilation of " & main_file_name & " (main) completed", 2); main_unit.id_index := new_id_index; Librarian.Change_Unit_Details (BD.LD, main_unit); -- -- Here: compilation of Main unit is finished (with or without -- minor or medium errors). -- Complete_Graph_Build; -- -- Here: build of the whole unit graph is finished (with or without -- minor or medium errors). -- Finalize_Target; -- if BD.CD.LC > BD.CD.ObjCode'First and then BD.CD.target.all not in Targets.HAC_Virtual_Machine.Machine'Class then -- Some machine code was emitted for the HAC VM instead of the alternative target. Errors.Error (BD.CD.all, err_general_error, "Code generation for alternative target (non-HAC-VM) is incomplete"); end if; -- if BD.CD.error_count = 0 then Parser.Helpers.Check_Incomplete_Definitions (BD.CD.all, 0); end if; if BD.CD.diags /= no_diagnostic then Errors.Compilation_Diagnostics_Summary (BD.CD.all); end if; if BD.CD.comp_dump_requested then Compiler.Print_Tables (BD.CD.all); Close (BD.CD.comp_dump); end if; if BD.asm_dump then Compiler.Dump_HAC_VM_Asm (BD.CD.all, BD.CD.target.Assembler_File_Name); end if; if BD.CD.listing_requested then Close (BD.CD.listing); end if; if Length (BD.obj_map_file_name) > 0 then Dump_Object_Map (To_String (BD.obj_map_file_name)); end if; exception when Errors.Compilation_of_package_body_before_spec => Restart_with_Spec; when E : HAC_Sys.Librarian.Circular_Unit_Dependency => Finalize_Target; -- Needed even on incomplete compilation. Errors.Error (BD.CD.all, Defs.err_library_error, "circular unit dependency (""->"" means ""depends on""): " & To_String (BD.main_name_hint) & " -> " & Exception_Message (E)); end Build_Main_Inner; begin Build_Main_Inner; exception when Errors.Compilation_abandoned => -- Hit a severe error... Finalize_Target; -- Needed even on incomplete compilation. Errors.Compilation_Diagnostics_Summary (BD.CD.all); if BD.CD.comp_dump_requested then Compiler.Print_Tables (BD.CD.all); Close (BD.CD.comp_dump); end if; if BD.asm_dump then Compiler.Dump_HAC_VM_Asm (BD.CD.all, BD.CD.target.Assembler_File_Name); end if; end Build_Main; procedure Build_Main_from_File (BD : in out Build_Data; file_name : String; body_compilation_rounds_limit : Rounds_Range := full_build) is source_stream : Co_Defs.Source_Stream_Access; begin BD.CD.error_count := 0; if BD.LD.cat.Exists (file_name) then BD.LD.cat.Source_Open (file_name, source_stream); else BD.CD.CUD.location := (0, 1, 1); Errors.Error (BD.CD.all, Defs.err_library_error, "file " & file_name & " not found", severity => Errors.medium); end if; if BD.CD.error_count = 0 then BD.Set_Main_Source_Stream (source_stream, file_name); BD.Build_Main (body_compilation_rounds_limit); BD.LD.cat.Close (file_name); end if; end Build_Main_from_File; procedure Set_Diagnostic_Parameters (BD : in out Build_Data; asm_dump : Boolean := False; -- Assembler output of compiled object code cmp_dump_file_name : String := ""; -- Compiler dump listing_file_name : String := ""; -- Listing of source code with details obj_map_file_name : String := "") -- Output of objects (map) is use HAT; begin BD.asm_dump := asm_dump; BD.cmp_dump_file_name := To_VString (cmp_dump_file_name); BD.listing_file_name := To_VString (listing_file_name); BD.obj_map_file_name := To_VString (obj_map_file_name); end Set_Diagnostic_Parameters; procedure Set_Remark_Set (BD : in out Build_Data; set : in Defs.Remark_Set) is begin BD.global_remarks := set; end Set_Remark_Set; -- Set current main source stream (file, editor data, zipped file,...) procedure Set_Main_Source_Stream (BD : in out Build_Data; s : in Co_Defs.Source_Stream_Access; file_name : in String; -- Can be a virtual name (editor title, zip entry) start_line : in Natural := 0) -- We could have a shebang or other Ada sources before is main_name_guess : String := Ada.Characters.Handling.To_Upper (file_name); last_slash, last_dot : Natural := 0; begin Co_Defs.Set_Source_Stream (BD.CD.CUD, s, file_name, start_line); -- Guess unit name from file name (operation is the reverse of GNAT_Naming in Librarian). for i in main_name_guess'Range loop case main_name_guess (i) is when '.' => last_dot := i; when '/' | '\' => last_slash := i; when '-' => main_name_guess (i) := '.'; -- Child unit (GNAT naming convention) when others => null; end case; end loop; if last_dot = 0 -- no dot at all or else last_dot < last_slash -- dot only in a path then last_dot := main_name_guess'Last + 1; end if; BD.main_name_hint := HAT.To_VString (main_name_guess (last_slash + 1 .. last_dot - 1)); end Set_Main_Source_Stream; procedure Set_File_Catalogue (BD : in out Build_Data; cat : in Files.Abstract_File_Catalogue_Reference) is begin BD.CD.Set_File_Catalogue (cat); BD.LD.Set_File_Catalogue (cat); end Set_File_Catalogue; procedure Set_Message_Feedbacks (BD : in out Build_Data; trace_params : in Co_Defs.Compilation_Trace_Parameters) is begin Compiler.Set_Message_Feedbacks (BD.CD.all, trace_params); end Set_Message_Feedbacks; procedure Set_Target (BD : in out Build_Data; new_target : Targets.Abstract_Machine_Reference) is use Targets; begin if new_target /= null then BD.target := new_target; end if; end Set_Target; function Build_Successful (BD : Build_Data) return Boolean is begin return Compiler.Unit_Compilation_Successful (BD.CD.all); -- NB: currently, only full builds are supported. end Build_Successful; function Total_Compiled_Lines (BD : Build_Data) return Natural is begin return BD.CD.total_lines; end Total_Compiled_Lines; function Object_Code_Size (BD : Build_Data) return Natural is begin return Compiler.Unit_Object_Code_Size (BD.CD.all); -- Whatever the build mode, the entire object code lands into BD.CD's object code. end Object_Code_Size; function Folded_Instructions (BD : Build_Data) return Natural is begin return BD.CD.folded_instructions; end Folded_Instructions; function Specialized_Instructions (BD : Build_Data) return Natural is begin return BD.CD.specialized_instructions; end Specialized_Instructions; function Maximum_Object_Code_Size return Natural is begin return Defs.CDMax; end Maximum_Object_Code_Size; end HAC_Sys.Builder; ================================================ FILE: src/compile/hac_sys-builder.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- Builder: *the* entry point for building an executable (possibly for the p-code -- virtual machine) from Ada sources (a main procedure and possible depending units). with HAC_Sys.Co_Defs, HAC_Sys.Defs, HAC_Sys.Files, HAC_Sys.Librarian, HAC_Sys.Targets; with HAT; with Ada.Containers.Hashed_Maps, Ada.Finalization, Ada.Strings.Unbounded.Hash; package HAC_Sys.Builder is package String_Maps is new Ada.Containers.Hashed_Maps (Key_Type => HAT.VString, Element_Type => HAT.VString, Hash => Ada.Strings.Unbounded.Hash, Equivalent_Keys => HAT."=", "=" => HAT."="); type Build_Data is new Ada.Finalization.Limited_Controlled with record CD : Co_Defs.Compiler_Data_Access := new Co_Defs.Compiler_Data; LD : Librarian.Library_Data; global_VM_variables : String_Maps.Map; global_remarks : Defs.Remark_Set := Defs.default_remarks; -- Main name hint is the upper-case Ada name of the main unit -- as guessed from a file name. -- This is used for circular unit dependency detection. -- The name has to be known before the parsing of main unit's -- context clause, and so, before the parsing of the name itself. main_name_hint : HAT.VString; asm_dump : Boolean := False; -- Assembler output of compiled object code cmp_dump_file_name : HAT.VString; -- Compiler dump listing_file_name : HAT.VString; -- Listing of source code with details obj_map_file_name : HAT.VString; -- Output of variables (map) target : Targets.Abstract_Machine_Reference := null; -- Always heap-allocated! end record; overriding procedure Finalize (BD : in out Build_Data); type Rounds_Range is range 0 .. 1e9; compile_only : constant Rounds_Range := Rounds_Range'First; full_build : constant Rounds_Range := Rounds_Range'Last; -- Build a main unit (possibly, the main procedure). -- The main unit's source code stream is already -- available via Set_Main_Source_Stream. -- If the stream stems from a file, the file must be already open and won't be closed. -- -- Build_Main takes care of all other needed compilations around main as well, -- depending on the value of body_compilation_rounds_limit. -- body_compilation_rounds_limit = 0 -> compile the given unit only, plus the WITH-ed specs. -- body_compilation_rounds_limit = full_build (default) -> main procedure will be executable. -- procedure Build_Main (BD : in out Build_Data; body_compilation_rounds_limit : Rounds_Range := full_build); procedure Build_Main_from_File (BD : in out Build_Data; file_name : String; body_compilation_rounds_limit : Rounds_Range := full_build); procedure Set_Diagnostic_Parameters (BD : in out Build_Data; asm_dump : Boolean := False; -- Assembler output of compiled object code cmp_dump_file_name : String := ""; -- Compiler dump listing_file_name : String := ""; -- Listing of source code with details obj_map_file_name : String := ""); -- Output of objects (map) procedure Set_Remark_Set (BD : in out Build_Data; set : in Defs.Remark_Set); -- Set current main source stream (file, editor data, zipped file,...) procedure Set_Main_Source_Stream (BD : in out Build_Data; s : in Co_Defs.Source_Stream_Access; file_name : in String; -- Can be a virtual name (editor title, zip entry) start_line : in Natural := 0); -- We could have a shebang or other Ada sources before procedure Set_File_Catalogue (BD : in out Build_Data; cat : in Files.Abstract_File_Catalogue_Reference); procedure Set_Message_Feedbacks ( BD : in out Build_Data; trace_params : in Co_Defs.Compilation_Trace_Parameters ); procedure Set_Target (BD : in out Build_Data; new_target : Targets.Abstract_Machine_Reference); function Build_Successful (BD : Build_Data) return Boolean; function Total_Compiled_Lines (BD : Build_Data) return Natural; function Object_Code_Size (BD : Build_Data) return Natural; function Folded_Instructions (BD : Build_Data) return Natural; function Specialized_Instructions (BD : Build_Data) return Natural; function Maximum_Object_Code_Size return Natural; end HAC_Sys.Builder; ================================================ FILE: src/compile/hac_sys-co_defs.adb ================================================ with HAC_Sys.Targets.HAC_Virtual_Machine; with Ada.Unchecked_Deallocation; package body HAC_Sys.Co_Defs is procedure Construct_Root (Root : out Exact_Typ; Typ : Typen) is begin Root.TYP := Typ; Root.Ref := 0; Root.Is_Range := False; end Construct_Root; overriding procedure Construct_Root (Root : out Exact_Subtyp; Typ : Typen) is begin Construct_Root (Exact_Typ (Root), Typ); -- Call parent method. Root.Discrete_First := HAC_Integer'First; Root.Discrete_Last := HAC_Integer'Last; end Construct_Root; function Construct_Root (Typ : Typen) return Exact_Subtyp is result : Exact_Subtyp; begin Construct_Root (result, Typ); return result; end Construct_Root; procedure Elevate_to_Maybe (item : in out No_Maybe_Yes) is begin -- no -> maybe -- maybe -> maybe -- yes -> yes item := No_Maybe_Yes'Max (item, maybe); end Elevate_to_Maybe; procedure Elevate_to_Maybe_or_Yes (item : in out No_Maybe_Yes; context : Flow_Context) is begin if context.is_within_condition or context.is_within_loop then -- The condition might not be fullfilled, the loop might be skipped. Elevate_to_Maybe (item); else item := yes; end if; end Elevate_to_Maybe_or_Yes; procedure Set_Source_Stream (CUD : in out Current_Unit_Data; s : in Source_Stream_Access; file_name : in String; -- Can be a virtual name (editor title, zip entry) start_line : in Natural := 0) is begin CUD.compiler_stream := s; CUD.source_file_name := HAT.To_VString (file_name); CUD.location.line := start_line; end Set_Source_Stream; function Get_Source_Name (CUD : Current_Unit_Data) return String is begin return HAT.VStr_Pkg.To_String (CUD.source_file_name); end Get_Source_Name; function Source_Buffer_has_Data (CUD : Current_Unit_Data) return Boolean is (CUD.buffer_length > 0); procedure Unchecked_Free is new Ada.Unchecked_Deallocation (Targets.Machine'Class, Targets.Abstract_Machine_Reference); function Is_Executable (CD : Compiler_Data) return Boolean is begin return CD.main_proc_id_index /= HAC_Sys.Co_Defs.No_Id; end Is_Executable; function Is_HAC_VM (CD : Compiler_Data) return Boolean is use Targets; begin return CD.target /= null and then CD.target.all in HAC_Virtual_Machine.Machine'Class; end Is_HAC_VM; procedure Set_Target (CD : in out Compiler_Data; new_target : Targets.Abstract_Machine_Reference) is use Targets; begin if new_target /= null then if CD.target /= null then Unchecked_Free (CD.target); end if; CD.target := new_target; -- Special case for a special target: the HAC VM. if new_target.all in HAC_Virtual_Machine.Machine'Class then HAC_Virtual_Machine.Machine (new_target.all).CD := CD'Unchecked_Access; end if; end if; end Set_Target; procedure Set_File_Catalogue (CD : in out Compiler_Data; cat : in Files.Abstract_File_Catalogue_Reference) is begin CD.cat := cat; end Set_File_Catalogue; overriding procedure Initialize (CD : in out Compiler_Data) is begin -- Ensure the CD has a valid target from the beginning: CD.Set_Target (new Targets.HAC_Virtual_Machine.Machine); end Initialize; overriding procedure Finalize (CD : in out Compiler_Data) is begin Unchecked_Free (CD.target); end Finalize; function Discrete_Image (CD : Compiler_Data; value : HAC_Integer; Typ : Typen; Ref : Index) return String is begin case Typ is when Ints => return HAC_Image (value); when Bools => return Boolean'Image (Boolean'Val (value)); when Chars => return Character'Image (Character'Val (value)); when Enums => if value in 0 .. CD.id_table (Ref).xtyp.Discrete_Last then return A2S (CD.id_table (Ref + 1 + Integer (value)).name_with_case); else return "[invalid position: " & HAC_Image (value) & ']'; end if; when others => raise Program_Error with "Non-discrete type"; end case; exception when Constraint_Error => return "[invalid position: " & HAC_Image (value) & ']'; end Discrete_Image; function Discrete_Range_Image (CD : Compiler_Data; value_1, value_2 : HAC_Integer; Typ : Typen; Ref : Index) return String is begin return Discrete_Image (CD, value_1, Typ, Ref) & " .. " & Discrete_Image (CD, value_2, Typ, Ref); end Discrete_Range_Image; function Size_of (CD : Compiler_Data; Id_Index : Natural) return Positive is X : constant Exact_Subtyp := CD.id_table (Id_Index).xtyp; begin case X.TYP is when Arrays => return CD.Arrays_Table (X.Ref).Array_Size; when Records => return CD.Blocks_Table (X.Ref).VSize; when others => return 1; end case; end Size_of; procedure Increment_Nesting_or_Descending_Level (CD : in out Compiler_Data) is begin CD.CUD.use_hat_stack_top := CD.CUD.use_hat_stack_top + 1; if CD.CUD.use_hat_stack_top > 0 then -- "Inherit" the possible presence of a USE clause for HAT. CD.CUD.Use_HAT_Stack (CD.CUD.use_hat_stack_top) := CD.CUD.Use_HAT_Stack (CD.CUD.use_hat_stack_top - 1); end if; end Increment_Nesting_or_Descending_Level; procedure Decrement_Nesting_or_Descending_Level (CD : in out Compiler_Data) is begin CD.CUD.use_hat_stack_top := CD.CUD.use_hat_stack_top - 1; end Decrement_Nesting_or_Descending_Level; begin undefined_subtyp.Construct_Root (NOTYP); end HAC_Sys.Co_Defs; ================================================ FILE: src/compile/hac_sys-co_defs.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- Co_Defs: Compiler Definitions with HAC_Sys.Defs, HAC_Sys.Files.Default, HAC_Sys.PCode, HAC_Sys.Targets; with HAT; with Ada.Containers.Hashed_Maps, Ada.Containers.Indefinite_Hashed_Maps, Ada.Finalization, Ada.Strings.Hash, Ada.Strings.Unbounded.Hash, Ada.Text_IO; package HAC_Sys.Co_Defs is -- NB: cannot be a child package of Compiler because of Parser, Scanner, ... use Defs; ------------------ -- Exact type -- ------------------ type Exact_Typ is tagged record -- NB: was called "Item" in SmallAda. TYP : Typen; Ref : Index; -- If TYP is not a standard type, then (TYP, Ref) does identify the base type. -- E.g. it can be (Enums, [index of the enumerated type definition]). -- -- Ref is an index into different tables, depending on TYP: -- If TYP = Records, Block_Table; -- if TYP = Arrays, Arrays_Table; -- if TYP = Enums, Idtab (the enumeration type's declaration). -- Is_Range : Boolean; -- ^ For X'Range expressions, indicates a pair of values waiting on the stack. end record; procedure Construct_Root (Root : out Exact_Typ; Typ : Typen) with Inline; --------------------- -- Exact subtype -- --------------------- type Exact_Subtyp is new Exact_Typ with record Discrete_First : HAC_Integer; -- If subtype S is discrete, S'First Discrete_Last : HAC_Integer; -- If subtype S is discrete, S'Last end record; overriding procedure Construct_Root (Root : out Exact_Subtyp; Typ : Typen) with Inline; function Construct_Root (Typ : Typen) return Exact_Subtyp with Inline; undefined_subtyp : Exact_Subtyp; -- This global variable is initialized. ------------------------------------------------------------------------- ------------------------------------------------------------ATabEntry---- ------------------------------------------------------------------------- -- An Array Table Entry represents an array. Each entry contains -- the following fields (fields marked with a C are used only by -- the compiler and ignored by the interpreter): -- type Array_Table_Entry is record Index_xTyp : Exact_Subtyp; -- C Subtype of the index (with bounds). Element_Size : Index; -- Size of an element. Element_xTyp : Exact_Subtyp; -- C Subtype of the elements of the array. -- If the elements of the array are themselves -- arrays, Element_xTYP.Ref is an index to an -- entry in Arrays_Table (it's not a special case). Array_Size : Index; -- C Total size of the array. dimensions : Positive; -- C Total dimensions of the array. end record; ------------------------------------------------------------------------- ------------------------------------------------------------BTabEntry---- ------------------------------------------------------------------------- -- Block Table Entry : Each entry represents a subprogram or a record type. -- -- A subprogram activation record consists of: -- -- (1) the five word fixed area; (see definition of S in Interpreter) -- (2) an area for the actual parameters (whether values or -- addresses), and -- (3) an area for the local variables of the subprogram -- -- Once again, fields marked with C are used only by the compiler -- type Block_Table_Entry is record Id : Alfa; -- Name of the block Last_Id_Idx : Index; -- C index of the last identifier in this block First_Param_Id_Idx : Index; -- C index of the first parameter in this block Last_Param_Id_Idx : Index; -- C index of the last parameter in this block -- (if first > last, it's parameterless) PSize : Index; -- sum of the lengths of areas (1) & (2) above VSize : Index := 0; -- sum of PSize and length of area (3) -- (i.e. size of the activation record for -- this block if it is a subprogram) SrcFrom : Positive; -- Source code line count. Source starts here SrcTo : Positive; -- and goes until here (* Manuel *) end record; fixed_area_size : constant := 5; -- Size of area (1) described above. type Package_Table_Entry is record first_public_declaration : Positive; last_public_declaration : Natural; -- = 0 if none. last_private_declaration : Natural; -- = 0 if none. end record; type Entity_Kind is -- RM 3.1 (declared_number_or_enum_item, -- Declared number: untyped constant, like -- "pi : constant := 3.1415927" (RM 3.3.2) -- variable_object, -- RM 3.3.1(5) constant_object, -- RM 3.3.1(6) -- type_mark, -- paquetage, paquetage_body, -- prozedure, prozedure_intrinsic, funktion, funktion_intrinsic, -- tache, entree, -- loop_identifier, alias); -- Short name of another entity ("use" clause). subtype Object_Kind is Entity_Kind range variable_object .. constant_object; -- RM 3.3 type Declaration_Kind is (spec_unresolved, spec_resolved, complete, param_in, param_in_out, param_out); subtype Split_Declaration_Kind is Declaration_Kind range spec_unresolved .. complete; subtype Parameter_Kind is Declaration_Kind range param_in .. param_out; type Initialized_Kind is (none, explicit, implicit); type No_Maybe_Yes is (no, maybe, yes); -- Unless we are in the main execution path (not within "if", "loop", etc.) -- we can only note that a variable or field is *maybe* read or written. -- procedure Elevate_to_Maybe (item : in out No_Maybe_Yes) with Inline; -- Elevate certainty level to "maybe" or "yes", depending on the context. -- procedure Elevate_to_Maybe_or_Yes (item : in out No_Maybe_Yes; context : Flow_Context) with Inline; ------------------------------ -- Identifier Table Entry -- ------------------------------ type Identifier_Table_Entry is record name : Alfa; -- Identifier name in ALL CAPS name_with_case : Alfa; -- Identifier name with original casing link : Index; -- Previous declaration on same nesting level, or No_Id entity : Entity_Kind; decl_kind : Declaration_Kind; -- Declaration kind: forward or complete. -- Matters for a type, a constant, a subprogram; -- Values param_in .. param_out are -- for subprogram parameters. xtyp : Exact_Subtyp; -- Subtype identification block_or_pkg_ref : Index; -- Reference in the block or package tables. normal : Boolean; -- value param? lev : Nesting_Level; adr_or_sz : HAC_Integer; -- Address, Size; index of aliased entity (USE) !! rather use block_or_pkg_ref ?! is_referenced : Boolean; -- For any item: is it referenced at all? is_read : No_Maybe_Yes; -- For variable or constant: is it read? is_written_after_init : No_Maybe_Yes; -- Is variable written via ":=" or "out" mode? is_initialized : Initialized_Kind; -- For variable or constant: is it initialized? location : Symbol_Location; end record; -- Entity Meaning of Adr_or_Sz -- ------------------------------------------------------------------------------- -- declared_number_or_enum_item Value (number), position (enumerated type) -- variable_object Relative position in the stack. -- constant_object Relative position in the stack. -- type_mark Size (in PCode stack items) of an object -- of the declared type. -- prozedure Index into the Object Code table. -- prozedure_intrinsic Standard Procedure code (SP_Code). -- funktion Index into the Object Code table. -- funktion_intrinsic Standard Function code (SF_Code). -- tache ? -- entree ? -- loop_identifier ? -- alias Index into the Identifier table of the aliased entity. type Loop_Info is record loop_Id : Natural; -- No_Id : no identifier is_FOR_loop : Boolean; -- Emit k_FOR_Release_Stack for each exited FOR loop start_line : Natural; end record; subtype Source_Buffer_String is String (1 .. 65_536); subtype Source_Line_String is String (1 .. 1000); -- Must be at least 200 (RM 2.2 (15)) ----------------------- -- Compiler tables -- ----------------------- type Arrays_Table_Type is array (1 .. AMax) of Array_Table_Entry; type Blocks_Table_Type is array (0 .. BMax) of Block_Table_Entry; type Display_Type is array (Nesting_Level) of Integer; type Entries_Table_Type is array (0 .. entry_table_max) of Index; type Identifier_Table_Type is array (0 .. Id_Table_Max) of Identifier_Table_Entry; type Nested_Loop_Table_Type is array (1 .. loop_nesting_max) of Loop_Info; type Packages_Table_Type is array (0 .. package_table_max) of Package_Table_Entry; type Tasks_Definitions_Table_Type is array (0 .. TaskMax) of Index; -- ^ Task #0 is main task. type Use_HAT_Stack_Type is array (0 .. nesting_and_descending_max) of Boolean; -- Display: keeps track of addressing by nesting level. See Ben-Ari Appendix A. No_Id : constant := 0; No_Id_Cache : constant := -1; subtype Source_Stream_Access is Files.Root_Stream_Class_Access; package Id_Maps is new Ada.Containers.Hashed_Maps (Key_Type => Alfa, Element_Type => Positive, Hash => Ada.Strings.Unbounded.Hash, Equivalent_Keys => HAT."="); type Current_Unit_Data is record -- Current source code information and scanner data compiler_stream : Source_Stream_Access; source_file_name : HAT.VString; -- Indicative, for error messages buffer : Source_Buffer_String; buffer_length : Natural; -- = 0 only on init or when exhausted. buffer_position : Positive; -- Points to the next character to be read. -- Parsing location : Symbol_Location; input_line : Source_Line_String; c, prev_c : Character; -- Character read from source program CC : Integer; -- Character counter (=column in current line) LL : Natural; -- Length of current line -- Level 0 definitions visible to currently compiled unit: level_0_def : Id_Maps.Map; Use_HAT_Stack : Use_HAT_Stack_Type; use_hat_stack_top : Natural; end record; -- Set current source stream (file, editor data, zipped file,...) procedure Set_Source_Stream (CUD : in out Current_Unit_Data; s : in Source_Stream_Access; file_name : in String; -- Can be a virtual name (editor title, zip entry) start_line : in Natural := 0); -- We could have a shebang or other Ada sources before function Get_Source_Name (CUD : Current_Unit_Data) return String; function Source_Buffer_has_Data (CUD : Current_Unit_Data) return Boolean; type Compilation_Feedback is access procedure (message : String); type Compilation_Trace_Parameters is record pipe : Defs.Smart_Error_Pipe := null; -- Default: messages to Current_Error. progress : Compilation_Feedback := null; -- Default: messages to Current_Output. detail_level : Natural := 0; end record; default_trace : constant Compilation_Trace_Parameters := (others => <>); procedure Silent_Diagnostics (kit : Diagnostic_Kit) is null; procedure Silent_Feedback (message : String) is null; silent_trace : constant Compilation_Trace_Parameters := (Silent_Diagnostics'Access, Silent_Feedback'Access, 0); type Dummy_Procedure_Access is access procedure; package Exported_Procedure_Mapping is new Ada.Containers.Indefinite_Hashed_Maps (Key_Type => String, Element_Type => Dummy_Procedure_Access, -- Actually: HAC_Sys.Interfacing.Exported_Procedure, but we -- end up in a circular unit dependency mess. Hash => Ada.Strings.Hash, Equivalent_Keys => "="); -- Global object used as a default for library file management: default_file_catalogue : aliased Files.Default.File_Catalogue; --------------------- -- Compiler_Data -- --------------------- type Compiler_Data is new Ada.Finalization.Limited_Controlled with record CUD : Current_Unit_Data; -- Scanning & Parsing Sy, prev_sy : Symbol; -- sy: last Symbol read by In_Symbol prev_sy_loc : Symbol_Location; Id : Alfa; -- Identifier from In_Symbol Id_with_case : Alfa; -- Same as Id, but with casing. Id_location : Integer; -- Cache for Locate_CD_Id INum : HAC_Integer; -- Integer from In_Symbol RNum : HAC_Float; -- Float number from In_Symbol SLeng : Integer; -- String Length pkg_prefix : HAT.VString; -- Prefix of package being currently parsed. -- Compiler tables. Floats and Strings are used by interpreter at run-time. Arrays_Table : Arrays_Table_Type; -- NB: only static-sized arrays so far. Blocks_Table : Blocks_Table_Type; Display : Display_Type; Entries_Table : Entries_Table_Type; Float_Constants_Table : Float_Constants_Table_Type; id_table : Identifier_Table_Type; Nested_Loop_Table : Nested_Loop_Table_Type; Packages_Table : Packages_Table_Type; Strings_Constants_Table : Strings_Constants_Table_Type; Tasks_Definitions_Table : Tasks_Definitions_Table_Type; -- Indices to compiler tables Arrays_Count : Natural; Blocks_Count : Natural; Entries_Count : Natural; Float_Constants_Count : Natural; Id_Count : Natural; loop_nesting_level : Natural; main_proc_id_index : Natural := No_Id; -- No_Id <=> the main unit is not executable. Packages_Count : Natural; String_Id_Index : Natural; Strings_Table_Top : Natural; Tasks_Definitions_Count : Natural; -- Object code -- Mostly for HAC VM / p-code -> will be moved to HAC_Sys.Targets.HAC_Virtual_Machine) target : Targets.Abstract_Machine_Reference := null; ObjCode : PCode.Object_Code_Table (0 .. CDMax); LC : Integer; -- Location counter in the Object_Code_Table CMax : Integer; -- Top of available ObjCode table; -- CMax + 1 .. CDMax: variable initialization code folded_instructions : Natural; specialized_instructions : Natural; -- Information about source code Full_Block_Id : HAT.VString; -- Full block's Id (P1.P2.F3.P4) main_unit_ident : Alfa := Empty_Alfa; main_unit_ident_with_case : Alfa := Empty_Alfa; Exported_Procedures : Exported_Procedure_Mapping.Map; -- listing_requested : Boolean := False; comp_dump_requested : Boolean := False; listing : Ada.Text_IO.File_Type; comp_dump : Ada.Text_IO.File_Type; -- error_count, minor_error_count : Natural; remarks : Remark_Set := default_remarks; diags : Diagnostic_Set; total_lines : Natural; cat : Files.Abstract_File_Catalogue_Reference := default_file_catalogue'Access; trace : Compilation_Trace_Parameters; -- On `WITH X`, we start the recursive compilation of X, -- if X is not yet compiled or built-in. We monitor the -- recursion level for the fun of it. recursion : Natural := 0; end record; overriding procedure Initialize (CD : in out Compiler_Data); overriding procedure Finalize (CD : in out Compiler_Data); function Is_Executable (CD : Compiler_Data) return Boolean; function Is_HAC_VM (CD : Compiler_Data) return Boolean; procedure Set_Target (CD : in out Compiler_Data; new_target : Targets.Abstract_Machine_Reference); -- Method used internally by HAC. -- Prefer using Build_Data's Set_File_Catalogue method. -- procedure Set_File_Catalogue (CD : in out Compiler_Data; cat : in Files.Abstract_File_Catalogue_Reference); type Compiler_Data_Access is access all Co_Defs.Compiler_Data; -- Image function for compilation errors or out-of-range exception messages. -- function Discrete_Image (CD : Compiler_Data; value : HAC_Integer; Typ : Typen; Ref : Index) return String; function Discrete_Range_Image (CD : Compiler_Data; value_1, value_2 : HAC_Integer; Typ : Typen; Ref : Index) return String; -- Size of a variable or subprogram parameter -- function Size_of (CD : Compiler_Data; Id_Index : Natural) return Positive; procedure Increment_Nesting_or_Descending_Level (CD : in out Compiler_Data); procedure Decrement_Nesting_or_Descending_Level (CD : in out Compiler_Data); Universe : constant HAT.VString := HAT.To_VString ("[-- The Universe --]"); type Constant_Rec is record TP : Exact_Subtyp; I : HAC_Integer; -- Includes Character and enumeration types (including Boolean) R : HAC_Float; end record; end HAC_Sys.Co_Defs; ================================================ FILE: src/compile/hac_sys-compiler-pcode_emit.adb ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Errors; package body HAC_Sys.Compiler.PCode_Emit is function Compiler_Data_to_Debug_Info (CD : Compiler_Data) return Debug_Info is begin return (Line_Number => CD.CUD.location.line, Full_Block_Id => CD.Full_Block_Id, File_Name => CD.CUD.source_file_name); end Compiler_Data_to_Debug_Info; procedure Emit ( CD : in out Compiler_Data; FCT : Opcode ) is begin Emit_3 (CD, FCT, 0, 0, 0); end Emit; procedure Emit_1 ( CD : in out Compiler_Data; FCT : Opcode; B : Operand_2_Type ) is begin Emit_3 (CD, FCT, 0, B, 0); end Emit_1; procedure Emit_2 ( CD : in out Compiler_Data; FCT : Opcode; a : Operand_1_Type; B : Operand_2_Type ) is begin Emit_3 (CD, FCT, a, B, 0); end Emit_2; procedure Emit_3 ( CD : in out Compiler_Data; FCT : Opcode; a : Operand_1_Type; B : Operand_2_Type; c : Operand_3_Type ) is folded, specialized : Boolean; begin PCode.Emit_Instruction ( CD.ObjCode (CD.ObjCode'First .. CD.CMax), -- ^ We don't pass the full object code table (CD.ObjCode) -- but the part before variable initialization code, -- for preventing overwriting existing initialization code. CD.LC, Compiler_Data_to_Debug_Info (CD), FCT, a, B, c, folded, specialized ); if folded then CD.folded_instructions := CD.folded_instructions + 1; end if; if specialized then CD.specialized_instructions := CD.specialized_instructions + 1; end if; end Emit_3; procedure Emit_Std_Funct ( CD : in out Compiler_Data; Code : SF_Code; Extra : Operand_1_Type := 0 ) is begin Emit_2 (CD, k_HAT_Function, Extra, SF_Code'Pos (Code)); end Emit_Std_Funct; procedure Emit_Comparison_Instruction ( CD : in out Compiler_Data; Operator : Comparison_Operator; Base_Typ : Typen ) is begin if Base_Typ = Floats then case Operator is when EQL => Emit (CD, k_EQL_Float); when NEQ => Emit (CD, k_NEQ_Float); when LSS => Emit (CD, k_LSS_Float); when LEQ => Emit (CD, k_LEQ_Float); when GTR => Emit (CD, k_GTR_Float); when GEQ => Emit (CD, k_GEQ_Float); end case; elsif Discrete_Typ (Base_Typ) then case Operator is when EQL => Emit (CD, k_EQL_Integer); when NEQ => Emit (CD, k_NEQ_Integer); when LSS => Emit (CD, k_LSS_Integer); when LEQ => Emit (CD, k_LEQ_Integer); when GTR => Emit (CD, k_GTR_Integer); when GEQ => Emit (CD, k_GEQ_Integer); end case; elsif Base_Typ = VStrings then case Operator is when EQL => Emit (CD, k_EQL_VString); when NEQ => Emit (CD, k_NEQ_VString); when LSS => Emit (CD, k_LSS_VString); when LEQ => Emit (CD, k_LEQ_VString); when GTR => Emit (CD, k_GTR_VString); when GEQ => Emit (CD, k_GEQ_VString); end case; else raise Errors.Internal_error with "Emit_Comparison_Instruction: comparison instruction for not supported type"; end if; end Emit_Comparison_Instruction; procedure Emit_Unary_Minus ( CD : in out Compiler_Data; Base_Typ : Numeric_Typ ) is begin case Base_Typ is when Floats => Emit (CD, k_Unary_MINUS_Float); when Ints => Emit (CD, k_Unary_MINUS_Integer); end case; end Emit_Unary_Minus; procedure Emit_Push_Float_Literal ( CD : in out Compiler_Data; X : HAC_Float ) is RNum_Index : Natural; begin Enter_or_find_Float (CD, X, RNum_Index); Emit_1 (CD, k_Push_Float_Literal, Operand_2_Type (RNum_Index)); end Emit_Push_Float_Literal; procedure Enter_or_find_Float ( CD : in out Compiler_Data; X : HAC_Float; RNum_Index : out Natural ) is use Errors; use type HAC_Float; begin if CD.Float_Constants_Count = float_const_table_max - 1 then Fatal (FLOAT_CONSTANTS); -- Exception is raised there. end if; -- We add X's value as an extra item: potential new item *and* sentinel value. CD.Float_Constants_Table (CD.Float_Constants_Count + 1) := X; RNum_Index := 1; while CD.Float_Constants_Table (RNum_Index) /= X loop -- Binary equality. RNum_Index := RNum_Index + 1; end loop; if RNum_Index > CD.Float_Constants_Count then -- X's value was not previously in the table. CD.Float_Constants_Count := RNum_Index; end if; end Enter_or_find_Float; procedure Emit_Lower_Bound_Check (CD : in out Compiler_Data; S : Exact_Subtyp) is use type HAC_Integer; begin if S.Discrete_First > HAC_Integer'First then Emit_3 (CD, k_Check_Lower_Bound, S.Discrete_First, Typen'Pos (S.TYP), Operand_3_Type (S.Ref)); end if; end Emit_Lower_Bound_Check; procedure Emit_Upper_Bound_Check (CD : in out Compiler_Data; S : Exact_Subtyp) is use type HAC_Integer; begin if S.Discrete_Last < HAC_Integer'Last then Emit_3 (CD, k_Check_Upper_Bound, S.Discrete_Last, Typen'Pos (S.TYP), Operand_3_Type (S.Ref)); end if; end Emit_Upper_Bound_Check; end HAC_Sys.Compiler.PCode_Emit; ================================================ FILE: src/compile/hac_sys-compiler-pcode_emit.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- This package facilitates the code emission for the HAC VM, but will -- shrink in the future in favour of HAC_Sys.Targets.HAC_Virtual_Machine. with HAC_Sys.Defs, HAC_Sys.PCode; package HAC_Sys.Compiler.PCode_Emit is -- This layer could be developed to abstract the virtual machine -- code emission, for instance for producing real machine code. use Defs, PCode; procedure Emit (CD : in out Compiler_Data; FCT : Opcode); procedure Emit_1 (CD : in out Compiler_Data; FCT : Opcode; B : Operand_2_Type); procedure Emit_2 (CD : in out Compiler_Data; FCT : Opcode; a : Operand_1_Type; B : Operand_2_Type); procedure Emit_3 (CD : in out Compiler_Data; FCT : Opcode; a : Operand_1_Type; B : Operand_2_Type; c : Operand_3_Type); procedure Emit_Std_Funct (CD : in out Compiler_Data; Code : SF_Code; Extra : Operand_1_Type := 0); procedure Emit_Comparison_Instruction (CD : in out Compiler_Data; Operator : Comparison_Operator; Base_Typ : Typen); procedure Emit_Unary_Minus (CD : in out Compiler_Data; Base_Typ : Numeric_Typ); procedure Emit_Push_Float_Literal (CD : in out Compiler_Data; X : HAC_Float); procedure Enter_or_find_Float (CD : in out Compiler_Data; X : HAC_Float; RNum_Index : out Natural); procedure Emit_Lower_Bound_Check (CD : in out Compiler_Data; S : Exact_Subtyp); procedure Emit_Upper_Bound_Check (CD : in out Compiler_Data; S : Exact_Subtyp); end HAC_Sys.Compiler.PCode_Emit; ================================================ FILE: src/compile/hac_sys-compiler.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Defs, HAC_Sys.Errors, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Modularity, HAC_Sys.Parser.Packages, HAC_Sys.PCode, HAC_Sys.Scanner; with HAT; with Ada.Integer_Text_IO, Ada.Strings.Fixed, Ada.Text_IO; package body HAC_Sys.Compiler is use Defs; procedure Set_Message_Feedbacks (CD : in out Compiler_Data; trace_params : in Compilation_Trace_Parameters) is begin CD.trace := trace_params; end Set_Message_Feedbacks; -- Initialize the compiler for a new unit. procedure Init (CUD : in out Current_Unit_Data) is begin CUD.buffer_length := 0; CUD.buffer_position := 1; CUD.c := ' '; CUD.CC := 0; CUD.LL := 0; CUD.location := (0, 1, 1); CUD.level_0_def.Clear; CUD.use_hat_stack_top := 0; CUD.Use_HAT_Stack (CUD.use_hat_stack_top) := False; end Init; -- Initialize the compiler for an entire build. procedure Init_for_new_Build (CD : out Compiler_Data) is begin CD.Arrays_Count := 0; CD.Blocks_Count := 0; CD.Float_Constants_Count := 0; CD.loop_nesting_level := 0; CD.Packages_Count := 0; -- Identifiers CD.Id_Count := 0; CD.id_table (CD.Id_Count).name := Empty_Alfa; -- Strings literals CD.Strings_Table_Top := Strings_Constants_Table_Type'First - 1; -- Tasks, Entries CD.Tasks_Definitions_Count := 0; CD.Entries_Count := 0; -- Location Counter (in output code) CD.LC := 0; CD.CMax := CDMax; -- Code optimization: CD.folded_instructions := 0; CD.specialized_instructions := 0; -- Current block name for debugging of HAC programs. CD.Full_Block_Id := Universe; -- CD.main_unit_ident := Empty_Alfa; CD.main_unit_ident_with_case := Empty_Alfa; CD.main_proc_id_index := No_Id; -- -- Current unit data -- Init (CD.CUD); -- Scanner data CD.Sy := Dummy_Symbol; CD.prev_sy_loc := (0, 1, 1); CD.error_count := 0; CD.minor_error_count := 0; CD.diags := no_diagnostic; CD.total_lines := 0; Scanner.In_Symbol (CD); -- CD.Display (0) := 0; -- Added 7-Dec-2009 CD.pkg_prefix := HAT.Null_VString; -- CD.target.Initialize_Code_Emission; -- -- Block Table Entry 0 is not a real block but serves only for -- its index in the identifier table, which lists global, -- level 0 stuff, outside any subprogram including Main. -- This entry is accessed by Locate_Identifier_Internal (implicitly), -- Dump_Object_Map, Enter_Library_Level_Def (explicitly). CD.Blocks_Table (0) := (Id => S2A ("-- Definitions at level 0"), Last_Id_Idx => 0, -- Updated by Enter_Library_Level_Def. First_Param_Id_Idx => 1, Last_Param_Id_Idx => 0, PSize => 0, VSize => 0, SrcFrom => 1, SrcTo => 1); end Init_for_new_Build; -- Print_Tables is for debugging purposes. -- procedure Print_Tables (CD : in Compiler_Data) is use Ada.Text_IO, Ada.Integer_Text_IO, Ada.Strings.Fixed; package HIIO is new Integer_IO (HAC_Integer); use HIIO; -- function Cut_name (n : String; l : Natural) return String is dots : constant String := "..."; begin if n'Length > l then return dots & n (n'Last - (l - 1) + dots'Length .. n'Last); else return n; end if; end Cut_name; -- procedure Show_Padded (n : String; t : Positive) is trunc : constant String := Cut_name (n, t); begin Put (CD.comp_dump, " " & trunc & Integer'Max (0, t - trunc'Length) * ' '); end Show_Padded; use type Alfa; Alng : constant := 50; -- Max characters displayed on this dump. begin New_Line (CD.comp_dump); Put_Line (CD.comp_dump, " Identifiers" & (Alng - 6) * ' ' & "Link Object " & "TYP Ref Norm Lvl Adr Blck" ); Put_Line (CD.comp_dump, (Alng + Entity_Kind'Width + Typen'Width + Boolean'Width + 34) * '-' ); -- We list all definitions, starting -- from Main (last Id of the "zero block" / standard). -- for I in 1 .. CD.Id_Count loop declare r : Identifier_Table_Entry renames CD.id_table (I); begin Put (CD.comp_dump, I, 4); Show_Padded (A2S (r.name_with_case), Alng); Put (CD.comp_dump, r.link, 4); Show_Padded (Entity_Kind'Image (r.entity), Entity_Kind'Width); Show_Padded (Typen'Image (r.xtyp.TYP), Typen'Width); Put (CD.comp_dump, r.xtyp.Ref, 5); Show_Padded (Boolean'Image (r.normal), Boolean'Width); Put (CD.comp_dump, Integer (r.lev), 3); Put (CD.comp_dump, r.adr_or_sz, 5); if r.block_or_pkg_ref > 0 then Put (CD.comp_dump, r.block_or_pkg_ref, 5); else Put (CD.comp_dump, " "); end if; Put (CD.comp_dump, " " & Declaration_Kind'Image (r.decl_kind)); New_Line (CD.comp_dump); end; end loop; New_Line (CD.comp_dump); Put_Line (CD.comp_dump, " Tasks Block#"); for I in 1 .. CD.Tasks_Definitions_Count loop Put (CD.comp_dump, I, 4); Put (CD.comp_dump, ' '); Put (CD.comp_dump, A2S (CD.id_table (CD.Tasks_Definitions_Table (I)).name) & " "); Put (CD.comp_dump, CD.id_table (CD.Tasks_Definitions_Table (I)).block_or_pkg_ref); New_Line (CD.comp_dump); end loop; New_Line (CD.comp_dump); if CD.Entries_Count > 0 then Put (CD.comp_dump, " Entries "); New_Line (CD.comp_dump); for I in 1 .. CD.Entries_Count loop Put (CD.comp_dump, I, 4); Put (CD.comp_dump, ' ' & A2S (CD.id_table (CD.Entries_Table (I)).name) & " in Task " & A2S (CD.id_table ( CD.Tasks_Definitions_Table (Integer (CD.id_table (CD.Entries_Table (I)).adr_or_sz)) ).name) ); New_Line (CD.comp_dump); end loop; New_Line (CD.comp_dump); end if; Put_Line (CD.comp_dump, " Blocks" & Alng * ' ' & " Last_ID FPar LPar PSze Vsze"); for I in 1 .. CD.Blocks_Count loop declare r : Block_Table_Entry renames CD.Blocks_Table (I); begin Put (CD.comp_dump, I, 4); Show_Padded (A2S (r.Id), Alng); Put (CD.comp_dump, r.Last_Id_Idx, 10); Put (CD.comp_dump, r.First_Param_Id_Idx, 5); Put (CD.comp_dump, r.Last_Param_Id_Idx, 5); Put (CD.comp_dump, r.PSize, 5); Put (CD.comp_dump, r.VSize, 5); New_Line (CD.comp_dump); end; end loop; New_Line (CD.comp_dump); if CD.Arrays_Count = 0 then Put_Line (CD.comp_dump, " Arrays: none"); else Put_Line (CD.comp_dump, " Array | Index: typ_________ " & " Element: typ_______ref " & " Low___High El. Size Ar. Size Dims"); -- for i in 1 .. CD.Arrays_Count loop declare r : Array_Table_Entry renames CD.Arrays_Table (i); package TIO is new Enumeration_IO (Typen); use TIO; typ_img : String (1 .. Typen'Width); begin Put (CD.comp_dump, i, 7); Put (typ_img, r.Index_xTyp.TYP); -- Padded Put (CD.comp_dump, " | " & typ_img); Put (typ_img, r.Element_xTyp.TYP); -- Padded Put (CD.comp_dump, " " & typ_img); Put (CD.comp_dump, r.Element_xTyp.Ref, 3); Put (CD.comp_dump, r.Index_xTyp.Discrete_First, 7); Put (CD.comp_dump, r.Index_xTyp.Discrete_Last, 7); Put (CD.comp_dump, r.Element_Size, 11); Put (CD.comp_dump, r.Array_Size, 9); Put (CD.comp_dump, r.dimensions, 5); end; New_Line (CD.comp_dump); end loop; end if; New_Line (CD.comp_dump); if CD.Packages_Count = 0 then Put_Line (CD.comp_dump, " Packages: none"); else Put_Line (CD.comp_dump, " Package | First decl. | Last public | Last private"); for i in 1 .. CD.Packages_Count loop declare p : Package_Table_Entry renames CD.Packages_Table (i); begin Put (CD.comp_dump, i, 8); Put (CD.comp_dump, p.first_public_declaration, 15); Put (CD.comp_dump, p.last_public_declaration, 14); Put (CD.comp_dump, p.last_private_declaration, 15); end; New_Line (CD.comp_dump); end loop; end if; New_Line (CD.comp_dump); Put_Line (CD.comp_dump, " Library Level visible identifiers (unordered list):"); for l0 of CD.CUD.level_0_def loop Put_Line (CD.comp_dump, " " & A2S (CD.id_table (l0).name)); end loop; New_Line (CD.comp_dump); if CD.main_unit_ident /= Empty_Alfa then Put_Line (CD.comp_dump, " Information about Main procedure:"); Put_Line (CD.comp_dump, " Name : " & A2S (CD.main_unit_ident_with_case)); Put_Line (CD.comp_dump, " Block # : " & Defs.Index'Image (CD.id_table (CD.main_proc_id_index).block_or_pkg_ref)); end if; New_Line (CD.comp_dump); Put_Line (CD.comp_dump, "String table. Length:" & CD.Strings_Table_Top'Image); Put_Line (CD.comp_dump, "----"); for i in Strings_Constants_Table_Type'First .. CD.Strings_Table_Top loop Put (CD.comp_dump, CD.Strings_Constants_Table (i)); if i mod 70 = 0 or else i = CD.Strings_Table_Top then New_Line (CD.comp_dump); end if; end loop; Put_Line (CD.comp_dump, "----"); end Print_Tables; --------------------------------------------------------------------------- procedure Progress_Message (CD : Co_Defs.Compiler_Data; msg : String) is begin if CD.trace.progress = null then Ada.Text_IO.Put_Line (msg); else CD.trace.progress (msg); end if; end Progress_Message; procedure Dump_HAC_VM_Asm (CD : Co_Defs.Compiler_Data; file_name : String) is use Ada.Text_IO; asm_dump : File_Type; begin if CD.Is_HAC_VM then Create (asm_dump, Out_File, file_name); PCode.Dump (CD.ObjCode (CD.ObjCode'First .. CD.LC - 1), -- Dump only compiled part. CD.Strings_Constants_Table, CD.Float_Constants_Table, asm_dump); Close (asm_dump); end if; end Dump_HAC_VM_Asm; procedure Compile_Unit (CD : in out Co_Defs.Compiler_Data; LD : in out Librarian.Library_Data; upper_name : String; file_name : String; as_specification : Boolean; as_main_unit : Boolean; needs_opening_a_stream : Boolean; first_compilation : Boolean; -- First compilation of whole build specification_id_index : Natural; new_id_index : out Natural; unit_context : in out Co_Defs.Id_Maps.Map; -- in : empty for spec, spec's context for body -- out: spec's context or body's full context. kind : out Librarian.Unit_Kind; -- The unit kind is discovered during parsing. needs_body : out Boolean) is use Ada.Strings.Fixed, Ada.Text_IO, Errors, Librarian, Parser.Helpers, PCode; -- -- Save state of unit currently being parsed (within a WITH clause). -- That compilation is frozen until the point where `mem` is copied -- back to CD.CUD. mem : constant Current_Unit_Data := CD.CUD; -- Unit_Id_with_case : Alfa; unit_block : Parser.Block_Data_Type; indent : Natural := 0; src_stream : Co_Defs.Source_Stream_Access; function Spec_or_Body return String is (" (" & (if as_specification then "specification)" else "body)")); procedure Reactivate_USE_HAT is -- Detect a directly visible item of the HAT package. -- It that case, it proves that a "USE HAT" was in the context -- clause of the specification. some_stuff_in_HAT_str : constant String := "VSTRING"; some_stuff_in_HAT : constant Alfa := S2A (some_stuff_in_HAT_str); stuff_index : Integer; begin if unit_context.Contains (some_stuff_in_HAT) then stuff_index := unit_context (some_stuff_in_HAT); if CD.id_table (stuff_index).entity = alias then -- Item named VSTRING from a USE clause was detected. -- Get the real item behind the alias (VSTRING -> ?.VSTRING): stuff_index := Integer (CD.id_table (stuff_index).adr_or_sz); if A2S (CD.id_table (stuff_index).name) = HAT_Name & '.' & some_stuff_in_HAT_str then -- Now we are sure the item stems from the HAT package. -- Normally, the full name is "HAT.VSTRING", unless HAT_Name has been customized. CD.CUD.Use_HAT_Stack (CD.CUD.use_hat_stack_top) := True; end if; end if; end if; end Reactivate_USE_HAT; function Indent_String (starting : Boolean) return String is (case indent is when 0 => "", when 1 => "| ", when others => (indent - 1) * ' ' & (if starting then '\' else '/') & ' '); full_file_name : constant String := LD.cat.Full_Source_Name (file_name); procedure Check_No_Extra_Symbol is begin Scanner.In_Symbol (CD); Error (CD, err_general_error, "end of file is expected here, found extra symbol"); exception -- Compiler bug: when compiled with -Os -ffunction-sections -fdata-sections, -- GNAT 21 and 23 (possibly more versions) ignore this handler! when End_Error => null; -- It's the expected case. end Check_No_Extra_Symbol; begin CD.recursion := CD.recursion + 1; if CD.trace.detail_level >= 1 then if CD.trace.detail_level >= 2 then indent := CD.recursion; end if; Progress_Message (CD, Indent_String (True) & "Compiling " & file_name & Spec_or_Body); end if; if needs_opening_a_stream then begin LD.cat.Source_Open (full_file_name, src_stream); Set_Source_Stream (CD.CUD, src_stream, full_file_name, 0); exception when Name_Error => Error (CD, err_library_error, "file " & file_name & Spec_or_Body & " not found", severity => major); end; end if; if not first_compilation then -- Reset scanner data (line counter etc.) and -- library-level visible declarations (processed WITH of caller's compilation) Init (CD.CUD); -- If we are compiling the body of a unit, unit_context already contains, automatically: -- - the WITH and USE context clauses of the spec, -- - the package's declarations, incuding the private part. -- Basically the body is a continuation of the spec, possibly in another file. CD.CUD.level_0_def := unit_context; Reactivate_USE_HAT; Scanner.In_Symbol (CD); end if; -- -- We define Standard, or activate if this is not the first unit compiled. -- Librarian.Apply_WITH_USE_Standard (CD, LD); -- The invisible "with Standard; use Standard;" -- HAT.PUT_LINE("Unit " & upper_name & " sees and uses Standard"); Parser.Modularity.Context_Clause (CD, LD); -- Parse the "with"'s and "use"'s, compile units. case CD.Sy is when PACKAGE_Symbol => Scanner.In_Symbol (CD); if CD.Sy = BODY_Symbol then Scanner.In_Symbol (CD); -- Absorb the BODY symbol. kind := Package_Body; if as_specification then Error (CD, err_library_error, "specification expected in this file; found body", severity => major); end if; else kind := Package_Declaration; if not as_specification then Error (CD, err_library_error, "body expected in this file; found specification", severity => major); end if; end if; when FUNCTION_Symbol => kind := Function_Unit; Scanner.In_Symbol (CD); when PROCEDURE_Symbol => kind := Procedure_Unit; Scanner.In_Symbol (CD); when others => kind := Package_Declaration; -- Useless, but this removes an ObjectAda warning. Error (CD, err_general_error, "`package`, `procedure` or `function` expected here", severity => major); end case; if CD.Sy /= IDent then Error (CD, err_identifier_missing, severity => major); end if; if as_main_unit then CD.main_unit_ident := CD.Id; CD.main_unit_ident_with_case := CD.Id_with_case; end if; if A2S (CD.Id) /= upper_name then Error (CD, err_wrong_unit_name, upper_name, A2S (CD.Id), major); end if; if first_compilation and then kind = Package_Body then raise Compilation_of_package_body_before_spec; end if; -- -- Enter the identifier: -- Unit_Id_with_case := CD.Id_with_case; case kind is when Procedure_Unit => Librarian.Enter_Library_Level_Def (CD, A2S (Unit_Id_with_case), prozedure, NOTYP, 0); when Function_Unit => Librarian.Enter_Library_Level_Def (CD, A2S (Unit_Id_with_case), funktion, NOTYP, 0); -- ^ The type of the return value is adjusted by Block.Function_Result_Profile. when Package_Declaration => Librarian.Enter_Library_Level_Def (CD, A2S (Unit_Id_with_case), paquetage, NOTYP, 0); when Package_Body => Librarian.Enter_Library_Level_Def (CD, A2S (Unit_Id_with_case), paquetage_body, NOTYP, 0); -- ^ The identifier is used only by the Semantics target. end case; new_id_index := CD.Id_Count; if specification_id_index /= No_Id then CD.target.Mark_Spec_Body_Cross_References (spec_id => specification_id_index, body_id => new_id_index); end if; case kind is when Subprogram_Unit => -- Absorb the identifier symbol: Scanner.In_Symbol (CD); -- -- At this point, the current symbol should be: ";", "IS", "(", -- or, for a parameterless function, "RETURN". -- unit_block.context.level := 1; unit_block.block_id_index := new_id_index; unit_block.entity := (if kind = Function_Unit then funktion else prozedure); unit_block.is_main := as_main_unit; unit_block.previous_declaration_id_index := specification_id_index; Parser.Block (CD, Block_Begin_Symbol + Statement_Begin_Symbol, False, unit_block, CD.id_table (CD.Id_Count).name, Unit_Id_with_case); if as_main_unit then if kind = Procedure_Unit and then Number_of_Parameters (CD, unit_block.block_id_index) = 0 then -- This main unit can be executed. CD.main_proc_id_index := unit_block.block_id_index; CD.Tasks_Definitions_Table (0) := unit_block.block_id_index; -- Task Table Entry for main task. else CD.main_proc_id_index := No_Id; end if; Check_No_Extra_Symbol; end if; case Split_Declaration_Kind (CD.id_table (unit_block.block_id_index).decl_kind) is when complete => if as_specification then Error (CD, err_library_error, "specification expected in this file; found body", severity => major); end if; if kind = Function_Unit then -- When this part of the machine code is reached, it means -- that the end of a function was reached without -- a "RETURN" statement. This will raise Program_Error. PCode_Emit.Emit_1 (CD, k_Return_Function, End_Function_without_Return); elsif as_main_unit then CD.target.Emit_Halt; else PCode_Emit.Emit_1 (CD, k_Return_Call, Normal_Procedure_Call); end if; when spec_unresolved => if not as_specification then Error (CD, err_library_error, "body expected in this file; found specification", severity => major); end if; when spec_resolved => raise Program_Error with "Unexpected case: spec_resolved"; end case; needs_body := as_specification; when Package_Declaration => unit_block.context.level := 0; -- Actually, not a block. CD.id_table (new_id_index).decl_kind := spec_resolved; -- Why spec_resolved ? missing bodies for possible suprograms -- in that package are checked anyway. Parser.Packages.Package_Declaration (CD, empty_symset, unit_block, needs_body); when Package_Body => unit_block.context.level := 0; -- Actually, not a block. Parser.Packages.Package_Body (CD, empty_symset, unit_block); needs_body := False; end case; if needs_opening_a_stream then LD.cat.Close (full_file_name); end if; if CD.trace.detail_level >= 2 then Progress_Message (CD, Indent_String (False) & " " & file_name & ": done."); end if; -- Export library-level context, possibly needed later by a body: unit_context := CD.CUD.level_0_def; CD.total_lines := CD.total_lines + CD.CUD.location.line; -- Forget about the compilation just completed, and go back to the -- ongoing compilation that triggered a call to Compile_Unit via a WITH: CD.CUD := mem; CD.recursion := CD.recursion - 1; exception when End_Error => kind := Function_Unit; -- Fake but valid value. Error (CD, err_unexpected_end_of_text); when others => if needs_opening_a_stream then LD.cat.Close (full_file_name); end if; raise; end Compile_Unit; function Unit_Compilation_Successful (CD : Compiler_Data) return Boolean is begin return CD.error_count = 0; end Unit_Compilation_Successful; function Unit_Object_Code_Size (CD : Compiler_Data) return Natural is begin return CD.LC; end Unit_Object_Code_Size; end HAC_Sys.Compiler; ================================================ FILE: src/compile/hac_sys-compiler.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Co_Defs, HAC_Sys.Librarian; package HAC_Sys.Compiler is -- Compile unit not yet in the library. -- Registration into the library is done elsewhere, by the Librarian. -- procedure Compile_Unit (CD : in out Co_Defs.Compiler_Data; LD : in out Librarian.Library_Data; upper_name : String; file_name : String; as_specification : Boolean; as_main_unit : Boolean; needs_opening_a_stream : Boolean; first_compilation : Boolean; -- First compilation of whole build specification_id_index : Natural; new_id_index : out Natural; unit_context : in out Co_Defs.Id_Maps.Map; -- in : empty for spec, spec's context for body -- out: spec's context or body's full context. kind : out Librarian.Unit_Kind; -- The unit kind is discovered during parsing. needs_body : out Boolean); use Co_Defs; -- Initialize the compiler for an entire build. procedure Init_for_new_Build (CD : out Compiler_Data); procedure Set_Message_Feedbacks (CD : in out Compiler_Data; trace_params : in Compilation_Trace_Parameters); procedure Print_Tables (CD : in Compiler_Data); procedure Progress_Message (CD : Co_Defs.Compiler_Data; msg : String); procedure Dump_HAC_VM_Asm (CD : Co_Defs.Compiler_Data; file_name : String); function Unit_Compilation_Successful (CD : Compiler_Data) return Boolean; function Unit_Object_Code_Size (CD : Compiler_Data) return Natural; end HAC_Sys.Compiler; ================================================ FILE: src/compile/hac_sys-defs.adb ================================================ package body HAC_Sys.Defs is function "+" (a, b : Symset) return Symset is begin return a or b; end "+"; function "+" (a : Symset; b : Symbol) return Symset is c : Symset := a; begin c (b) := True; return c; end "+"; function "-" (a, b : Symset) return Symset is begin return a and not b; end "-"; function "-" (a : Symset; b : Symbol) return Symset is c : Symset := a; begin c (b) := False; return c; end "-"; function Minimum_Level (r : Compile_Remark) return Remark_Level is begin for lev in Remark_Level loop if preset_remarks (lev)(r) then return lev; end if; end loop; return Remark_Level'Last; end Minimum_Level; end HAC_Sys.Defs; ================================================ FILE: src/compile/hac_sys-defs.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- This package contains constants and types for the -- compiler and the p-code interpreter. with HAT; with Ada.Characters.Handling, Ada.Text_IO; with Interfaces; package HAC_Sys.Defs is HAT_Name : constant String := "HAT"; -- Stands for: HAC Ada Toolbox (was: Library). subtype HAC_Integer is Interfaces.Integer_64; HAC_Integer_Name : constant String := "Integer"; HAC_Integer_Name_Upper : constant String := Ada.Characters.Handling.To_Upper (HAC_Integer_Name); function HAC_Image is new HAT.HAC_Generic_Image (Abstract_Integer => HAC_Integer); -- HAC's default floating-point type is double-precision -- and is called "Real" in HAC's HAT package. -- There is *no* Float in HAC's Standard package. -- Float is commonly assumed to be single-precision -> no practical use and would -- complicate the parsing in HAC by having multiple possible -- floating-point type expressions. -- On top of that a universal float would be probably needed. -- subtype HAC_Float is HAT.Real; HAC_Float_Name : constant String := "Real"; HAC_Float_Name_Upper : constant String := Ada.Characters.Handling.To_Upper (HAC_Float_Name); -- Max & Min Exponents. IEEE Double Precision. -- TBD: !! find the attribute, applied on HAC_Float, that matches this value. EMax : constant := 308; EMin : constant := -308; ------------------------ -- Global constants -- ------------------------ StMax : constant := 5_000_000; -- Maximum Stack Size STKINCR : constant := 2_000; -- Stack Increment allocated per Task Header : constant String := "HAC - HAC Ada Compiler"; -- Alternative name: Hackers' Ada Compiler -- Was: "Small-Ada Macintosh Ver 1.1 Nov 1989 George Washington University" MaxINT : constant Integer := Integer'Last - 1; AMax : constant := 1_000; -- Size OF ARRAY-TABLE BMax : constant := 10_000; -- Size OF Block-TABLE float_const_table_max : constant := 200; Cases_Max : constant := 2000; -- Max number of cases in a CASE statement CDMax : constant := 100_000; -- Size OF ObjCode entry_table_max : constant := 30; -- Maximum Number of Entries integer_digits_max : constant := 18; -- Maximum digits for an integer literal, was KMAX: -- decimal representation of 2**63, minus 1 digit. package_table_max : constant := 10_000; -- Size of Package table loop_nesting_max : constant := 100; nesting_level_max : constant := 20; -- Maximum subprogram nesting level, was LMAX. nesting_and_descending_max : constant := 40; -- subprograms, subpackages and child packages End_Function_without_Return : constant := -1; Normal_Procedure_Call : constant := 0; Normal_Entry_Call : constant := 1; Timed_Entry_Call : constant := 2; Conditional_Entry_Call : constant := 3; OrdMinChar : constant := 0; -- Ord of First Char OrdMaxChar : constant := 255; -- Ord of last Char PriMax : constant := 100; -- Maximum Task priority SMax : constant := 100_000; -- Size of String table TaskMax : constant := 12; -- Max # of concurrent tasks string_folding_scan_limit : constant := 1000; Wind_Size : constant := TaskMax + 2; -- SnapShot window size Id_Table_Max : constant := 10_000; -- Size of identifier table XMax : constant Integer := MaxINT; Patch_Max : constant := 100; identifier_length_max : constant := 200; -------------------- -- Global types -- -------------------- ----------------------------------------------------------------------- ------------------------ Symbol - All symbols used by the compiler ---- ----------------------------------------------------------------------- type Symbol is (integer_literal, real_literal, character_literal, string_literal, -- Plus, -- + Minus, -- - Times, -- * Divide, -- / Power, -- ** -- EQL, -- = NEQ, -- /= GTR, -- > GEQ, -- >= LSS, -- < LEQ, -- <= -- LParent, RParent, LBrack, RBrack, Apostrophe, Comma, Semicolon, Period, Range_Double_Dot_Symbol, -- ".." compound delimiter (RM 2.2) Colon, Alt, Finger, Becomes, IDent, Dummy_Symbol, -- Symbol that is never scanned. Ampersand_Symbol, -------------------- -- -- -- Ada keywords -- -- -- -------------------- ABORT_Symbol, ABS_Symbol, ABSTRACT_Symbol, ACCEPT_Symbol, ACCESS_Symbol, ALIASED_Symbol, ALL_Symbol, AND_Symbol, AND_THEN_Symbol, -- This symbol is never scanned as such. ARRAY_Symbol, AT_Symbol, BEGIN_Symbol, BODY_Symbol, CASE_Symbol, CONSTANT_Symbol, DECLARE_Symbol, DELAY_Symbol, DELTA_Symbol, DIGITS_Symbol, DO_Symbol, ELSE_Symbol, ELSIF_Symbol, END_Symbol, ENTRY_Symbol, EXCEPTION_Symbol, EXIT_Symbol, FOR_Symbol, FUNCTION_Symbol, GENERIC_Symbol, GOTO_Symbol, IF_Symbol, IN_Symbol, INTERFACE_Symbol, IS_Symbol, LIMITED_Symbol, LOOP_Symbol, MOD_Symbol, NEW_Symbol, NOT_Symbol, NULL_Symbol, OF_Symbol, OR_Symbol, OR_ELSE_Symbol, -- This symbol is never scanned as such. OTHERS_Symbol, OUT_Symbol, OVERRIDING_Symbol, PACKAGE_Symbol, PARALLEL_Symbol, PRAGMA_Symbol, PRIVATE_Symbol, PROCEDURE_Symbol, PROTECTED_Symbol, RAISE_Symbol, RANGE_Keyword_Symbol, -- "range" reserved word (RM 2.9) RECORD_Symbol, REM_Symbol, RENAMES_Symbol, REQUEUE_Symbol, RETURN_Symbol, REVERSE_Symbol, SELECT_Symbol, SEPARATE_Symbol, SOME_Symbol, SUBTYPE_Symbol, SYNCHRONIZED_Symbol, TAGGED_Symbol, TASK_Symbol, TERMINATE_Symbol, THEN_Symbol, TYPE_Symbol, UNTIL_Symbol, USE_Symbol, WHEN_Symbol, WHILE_Symbol, WITH_Symbol, XOR_Symbol); subtype Plus_Minus is Symbol range Plus .. Minus; subtype Comparison_Operator is Symbol range EQL .. LEQ; subtype Arithmetic_Binary_Operator is Symbol range Plus .. Power; --------------------- -- Sets of symbols -- --------------------- type Symset is array (Symbol) of Boolean; -- The "+" and "-" reproduce the Pascal set operators. function "+" (a, b : Symset) return Symset; function "+" (a : Symset; b : Symbol) return Symset; function "-" (a, b : Symset) return Symset; function "-" (a : Symset; b : Symbol) return Symset; empty_symset : constant Symset := (others => False); ----------------- -- Identifiers -- ----------------- subtype Alfa is HAT.VString; -- Originally, Alfa was a space-padded fixed string. Empty_Alfa : Alfa renames HAT.Null_VString; function A2S (a : Alfa) return String renames HAT.To_String; function S2A (s : String) return Alfa renames HAT.To_VString; -- Data types in HAC. We call them "Typ" (with an Akzent ;-) ) to avoid -- confusion with the types of the HAC code itself. -- -- The order of these is significant. -- type Typen is ( ---------------------- -- Built-in types -- ---------------------- NOTYP, -- Appears when the parsing of an expression fails at some point. Ints, Floats, Bools, Chars, VStrings, Times, Durations, -- Text_Files, -- This one is limited (like Ada's File_Type). ------------------------------------ -- Types defined by programmers -- ------------------------------------ Arrays, Records, Enums, ------------------------------------------------------- -- Special types appearing only during the parsing -- -- and unavailable to the programmer. -- ------------------------------------------------------- String_Literals, -- Strings in the "abcd" form. Takes 2 items on the stack. Strings_as_VStrings -- VString value, but semantically a String. E.g. returned by S'Image ); for Typen'Size use 8; type Typ_Set is array (Typen) of Boolean; empty_typ_set : constant Typ_Set := (others => False); subtype Standard_Typ is Typen range NOTYP .. Text_Files; subtype Special_Strings is Typen range String_Literals .. Strings_as_VStrings; subtype Composite_Typ is Typen range Arrays .. Records; Standard_or_Enum_Typ : constant Typ_Set := (Standard_Typ | Enums => True, others => False); Discrete_Typ : constant Typ_Set := -- RM 3.2 (12) (Ints | Bools | Chars | Enums => True, others => False); subtype Numeric_Typ is Typen range Ints .. Floats; -- RM 3.2 (1) Auto_Init_Typ : constant Typ_Set := (VStrings | Text_Files => True, others => False); Typ_with_Variant_Part : constant Typ_Set := (Floats | VStrings | Times | Durations | Text_Files => True, others => False); subtype Index is Integer range -XMax .. +XMax; type Float_Constants_Table_Type is array (1 .. float_const_table_max) of HAC_Float; subtype Nesting_Level is HAC_Integer range 0 .. nesting_level_max; type Flow_Context is record level : Nesting_Level; -- This is for rudimentary flow analysis -- and the issuance of clever warnings and notes. is_within_loop : Boolean := False; -- Reversed on leaving top loop is_within_condition : Boolean := False; -- Reversed on leaving top condition is_in_cond_within_loop : Boolean := False; -- Reversed on leaving this case end record; ------------------------------ -- Compilation error type -- ------------------------------ type Compile_Diagnostic is -- Errors that may occur during the scanning of symbols (tokens): (err_scanner_character_zero_chars, err_scanner_control_character, err_scanner_digit_expected, err_scanner_double_underline_not_permitted, err_scanner_identifier_cannot_end_with_underline, err_scanner_identifier_too_long, err_scanner_illegal_character, err_scanner_illegal_character_in_number, err_scanner_negative_exponent_for_integer_literal, err_scanner_exponent_too_large, err_scanner_integer_literal_too_large, err_scanner_space_missing_after_number, -- Errors that may occur during parsing: err_undefined_identifier, err_duplicate_identifier, err_identifier_missing, err_missing_a_procedure_declaration, err_closing_parenthesis_missing, err_colon_missing, err_colon_missing_for_named_statement, err_incorrectly_used_symbol, err_missing_OF, err_missing_an_opening_parenthesis, err_left_bracket_instead_of_parenthesis, err_right_bracket_instead_of_parenthesis, err_missing_type_begin_symbol, err_expecting_double_dot, err_semicolon_missing, err_duplicate_semicolon, err_extra_right_parenthesis, -- 2021-12-29 err_bad_result_type_for_a_function, err_type_of_return_statement_doesnt_match, err_illegal_statement_start_symbol, err_expecting_a_boolean_expression, err_control_variable_of_the_wrong_type, err_bounds_type_mismatch, err_IS_missing, err_incorrect_name_after_END, err_bad_type_for_a_case_statement, err_illegal_constant_or_constant_identifier, err_wrong_type_for_array_index, err_too_few_array_indices, err_too_many_array_indices, err_illegal_array_bounds, err_indexed_variable_must_be_an_array, err_missing_a_type_identifier, err_undefined_type, err_var_with_field_selector_must_be_record, err_resulting_type_should_be_Boolean, err_illegal_type_for_arithmetic_expression, err_mod_requires_integer_arguments, err_incompatible_types_for_comparison, err_parameter_types_do_not_match, err_variable_missing, err_number_of_parameters_do_not_match, err_illegal_parameters_to_Get, err_illegal_parameters_to_Put, err_parameter_must_be_of_type_Float, err_parameter_must_be_Integer, err_expected_constant_function_variable_or_subtype, err_types_of_assignment_must_match, err_case_label_not_same_type_as_case_clause, err_duplicate_case_choice_value, err_argument_to_std_function_of_wrong_type, err_stack_size, err_illegal_symbol_for_a_number_declaration, err_BECOMES_missing, err_THEN_missing, err_IN_missing, err_missing_closing_LOOP, err_missing_closing_LOOP_2, err_BEGIN_missing, err_END_missing, err_primary_unexpected_symbol, err_RETURN_missing, err_RECORD_missing, err_missing_closing_IF, err_missing_closing_IF_2, err_WHEN_missing, err_FINGER_missing, err_missing_closing_CASE, err_missing_closing_CASE_2, err_functions_must_return_a_value, err_procedures_cannot_return_a_value, err_missing_an_entry, err_missing_expression_for_delay, err_wrong_type_in_DELAY, err_COMMA_missing, err_expecting_accept_when_or_entry_id, err_expecting_task_entry, err_expecting_OR_or_ELSE_in_SELECT, err_expecting_DELAY, err_SELECT_missing, err_program_incomplete, -- These errors messages are new in HAC and weren't in SmallAda err_OF_instead_of_IS, err_THEN_instead_of_Arrow, err_EQUALS_instead_of_BECOMES, err_numeric_constant_expected, err_statement_expected, err_duplicate_loop_identifier, err_unexpected_end_of_text, -- 2018-04-01 err_not_yet_implemented, -- 2019-03-24 err_type_conversion_not_supported, -- 2020-03-31 err_numeric_type_coercion, -- 2020-04-06 err_numeric_type_coercion_operator, err_operator_not_defined_for_types, -- 2020-04-06 err_no_null_functions, -- 2020-04-10 err_cannot_modify_constant_or_in_parameter, err_case_others_alone_last, err_no_X_for_END_X, err_END_LOOP_ident_missing, err_END_LOOP_ident_wrong, err_general_error, -- Default (without hint): the classic "syntax error" err_string_to_vstring_assignment, err_range_constraint_error, err_discrete_type_expected, err_membership_test_type_mismatch, err_string_not_supported_as_parameter, err_string_lengths_do_not_match, err_object_used_before_end_own_declaration, -- 2021-12-11 err_attribute_prefix_invalid, -- 2021-12-26 err_attribute_prefix_must_be_discrete_type, -- 2021-12-26 err_invalid_dimension_number, -- 2022-01-09 err_spec_body_mismatch, -- 2022-01-22 err_incomplete_declaration, -- 2022-01-22 err_non_public_entity, -- 2022-04-02 err_choices_not_covered, err_choice_out_of_range, err_mixed_logical_operators, err_library_error, err_wrong_unit_name, err_obsolete_hat_name, err_assignment_not_allowed_declarative, -- note_redundant_construct, note_unused_item, note_constant_variable, -- warn_read_but_not_written); subtype Compile_Note is Compile_Diagnostic range note_redundant_construct .. note_constant_variable; subtype Compile_Warning is Compile_Diagnostic range warn_read_but_not_written .. warn_read_but_not_written; -- A Remark is either a Warning (about something potentially dangerous) -- or a Note (about something harmless but typically superfluous). subtype Compile_Remark is Compile_Diagnostic range Compile_Note'First .. Compile_Warning'Last; -- Summary of Compile_Diagnostic: -- -- +------------------------+ -- | Diagnostic | -- +---v-----------v--------+ -- | | Remark | -- | Error |--v--------v----+ -- | | Note | Warning | -- +-------+------+---------+ type Remark_Set is array (Compile_Remark) of Boolean; type Remark_Level is range 0 .. 3; default_remark_level : constant Remark_Level := 1; -- Level 0 means: no remarks are issued. -- Level 1 corresponds roughly to the GNAT defaults (when you type "gnatmake" -- on a command-line interpreter, it's the warnings marked -- with a '*', plus others that are always enabled. -- Level 2 corresponds roughly to the GNAT's "-gnatwa" option, that is, -- warnings marked with a '+' in the help. -- Level 3 means: all remarkes are enabled. This level corresponds roughly to -- the "-gnatw.e" switch. preset_remarks : constant array (Remark_Level) of Remark_Set := (0 => (others => False), 1 => (warn_read_but_not_written => True, others => False), 2 => (note_redundant_construct | note_unused_item | note_constant_variable | warn_read_but_not_written => True), 3 => (others => True)); function Minimum_Level (r : Compile_Remark) return Remark_Level; default_remarks : constant Remark_Set := preset_remarks (default_remark_level); remark_letter : constant array (Compile_Remark) of Character := (note_redundant_construct => 'r', note_unused_item => 'u', note_constant_variable => 'k', -- warn_read_but_not_written => 'v'); subtype Compile_Error is Compile_Diagnostic range Compile_Diagnostic'First .. Compile_Diagnostic'Pred (Compile_Remark'First); type Diagnostic_Set is array (Compile_Diagnostic) of Boolean; no_diagnostic : constant Diagnostic_Set := (others => False); type Repair_Kind_Type is (none, insert, replace_token); type Repair_Kit is tagged record repair_kind : Repair_Kind_Type := none; alternative : HAT.VString := HAT.Null_VString; end record; -- The Symbol_Location record unifies the location of symbols -- within a source stream, basically for errors & warnings. type Symbol_Location is record line : Integer; column_start : Integer; column_stop : Integer; end record; type Diagnostic_Kind_Type is (error, warning, note, style); subtype Remark_Type is Diagnostic_Kind_Type range warning .. note; type Diagnostic_Kit is new Repair_Kit with record diagnostic_kind : Diagnostic_Kind_Type := error; message : HAT.VString := HAT.Null_VString; file_name : HAT.VString := HAT.Null_VString; location : Symbol_Location := (0, 0, 0); end record; type Smart_Error_Pipe is access procedure (kit : Diagnostic_Kit); package IIO is new Ada.Text_IO.Integer_IO (HAC_Integer); package RIO is new Ada.Text_IO.Float_IO (HAC_Float); package BIO is new Ada.Text_IO.Enumeration_IO (Boolean); -- package REF is new Ada.Numerics.Generic_Elementary_Functions (HAC_Float); subtype Strings_Constants_Table_Type is String (1 .. SMax); ------------------------------------ -- Standard function operations -- ------------------------------------ type SF_Code is ( SF_Abs_Int, SF_Abs_Float, SF_T_Val, -- S'Val : RM 3.5.5 (5) SF_T_Pos, -- S'Pos : RM 3.5.5 (2) SF_T_Succ, -- S'Succ : RM 3.5 (22) SF_T_Pred, -- S'Pred : RM 3.5 (25) SF_in_discrete_Interval, SF_not_in_discrete_Interval, -- Numerical functions SF_Round_Float_to_Int, SF_Trunc_Float_to_Int, SF_Float_to_Duration, SF_Duration_to_Float, SF_Int_to_Duration, SF_Duration_to_Int, SF_Sin, SF_Cos, SF_Exp, SF_Log, SF_Sqrt, SF_Arctan, SF_Sgn_Int, SF_Sgn_Float, SF_EOF, SF_EOLN, SF_Is_Open, SF_Random_Int, SF_Min_Int, SF_Max_Int, SF_Min_Float, SF_Max_Float, -- -- VString functions (Ada.Strings.Unbounded-like) -- SF_String_to_VString, -- +s (s is a fixed-size string) SF_String_Literal_to_VString, -- +"Hello" SF_VString_to_String, -- -v SF_Char_to_VString, -- +'x' SF_Two_VStrings_Concat, -- v1 & v2 SF_VString_Char_Concat, -- v & 'x' SF_Char_VString_Concat, -- 'x' & v SF_LStr_VString_Concat, -- "Hello " & v -- SF_VString_Int_Concat, -- v & 123 SF_Int_VString_Concat, -- 123 & v SF_VString_Float_Concat, -- v & 3.14159 SF_Float_VString_Concat, -- 3.14159 & v SF_VString_Duration_Concat, -- v & (Time_1 - Time_0) SF_Duration_VString_Concat, -- (Time_1 - Time_0) & v SF_VString_Boolean_Concat, -- v & is_found SF_Boolean_VString_Concat, -- is_found & v -- SF_Element, SF_Length, SF_Slice, -- SF_To_Lower_Char, SF_To_Upper_Char, SF_To_Lower_VStr, SF_To_Upper_VStr, SF_Index, SF_Index_Backward, SF_Int_Times_Char, SF_Int_Times_VStr, -- SF_Trim_Left, SF_Trim_Right, SF_Trim_Both, -- SF_Head, SF_Head_Before_Match, SF_Tail, SF_Tail_After_Match, SF_Starts_With, SF_Ends_With, -- -- Ada.Calendar-like functions -- SF_Time_Subtract, -- T2 - T1 -> Duration SF_Duration_Add, SF_Duration_Subtract, SF_Year, SF_Month, SF_Day, SF_Seconds, -- SF_Image_Ints, -- HAT.Image without the nasty ' ' before non-negative values SF_Image_Floats, -- HAT.Image with a human-readable formatting whenever possible SF_Image_Times, -- HAT.Image SF_Image_Durations, -- HAT.Image -- SF_Integer_Value, SF_Float_Value, -- 'Image attribute "as is" from Ada: SF_Image_Attribute_Ints, SF_Image_Attribute_Floats, SF_Image_Attribute_Bools, SF_Image_Attribute_Chars, SF_Image_Attribute_Durs, SF_Image_Attribute_Enums, -- 'Value attribute "as is" from Ada: SF_Value_Attribute_Ints, SF_Value_Attribute_Floats, SF_Value_Attribute_Bools, SF_Value_Attribute_Chars, SF_Value_Attribute_Durs, SF_Value_Attribute_Enums, -- SF_Argument, -- Ada.Directories-like SF_Directory_Exists, SF_Exists, SF_File_Exists, -- Ada.Environment_Variables-like SF_Get_Env, SF_Get_VM_Variable, -- -- Niladic functions (they have no arguments). -- SF_Clock, SF_Random_Float, SF_Null_VString, SF_Argument_Count, SF_Command_Name, SF_Directory_Separator, SF_Current_Directory, -- Ada.Directories-like -- SF_Get_Needs_Skip_Line -- Informs whether Get from console needs Skip_Line ); subtype SF_Niladic is SF_Code range SF_Clock .. SF_Get_Needs_Skip_Line; subtype SF_Min_Max_Int is SF_Code range SF_Min_Int .. SF_Max_Int; subtype SF_File_or_Console_Information is SF_Code range SF_EOF .. SF_EOLN; subtype SF_Index_Any_Direction is SF_Code range SF_Index .. SF_Index_Backward; ------------------------------------- -- Standard procedure operations -- ------------------------------------- type SP_Code is ( SP_Create, SP_Open, SP_Append, SP_Close, -- SP_Push_Abstract_Console, -- SP_Get, SP_Get_Immediate, SP_Get_Line, SP_Get_File, SP_Get_Line_File, SP_Skip_Line, -- SP_Put, SP_Put_Line, SP_Put_File, SP_Put_Line_File, SP_New_Line, -- SP_Randomize, SP_Random_Seed, -- SP_Wait, SP_Signal, -- SP_Quantum, SP_Priority, SP_InheritP, -- -- Ada.Environment_Variables-like procedures -- SP_Set_Env, SP_Set_VM_Variable, -- -- Ada.Directories-like procedures -- SP_Copy_File, SP_Create_Directory, SP_Create_Path, SP_Delete_Directory, SP_Delete_File, SP_Rename, SP_Set_Directory, SP_Set_Exit_Status, -- -- VString procedures (Ada.Strings.Unbounded-like) -- SP_Delete, -- -- Other system procedures -- SP_Shell_Execute_without_Result, -- Result: no, Output no SP_Shell_Execute_with_Result, -- Result: yes, Output no SP_Shell_Execute_Output, -- Result: no, Output yes SP_Shell_Execute_Result_Output -- Result: yes, Output yes ); subtype SP_Shell_Execute is SP_Code range SP_Shell_Execute_without_Result .. SP_Shell_Execute_Result_Output; end HAC_Sys.Defs; ================================================ FILE: src/compile/hac_sys-errors.adb ================================================ with HAC_Sys.Librarian; with Ada.Strings.Fixed, Ada.Text_IO; package body HAC_Sys.Errors is use Defs; function Diagnostic_String (code : Defs.Compile_Diagnostic; hint_1 : String := ""; hint_2 : String := "") return String is begin case code is when err_undefined_identifier => return "undefined identifier" & (if hint_1 = "" then "" else ": " & hint_1); when err_duplicate_identifier => return "duplicate identifier: " & hint_1; when err_identifier_missing => return "missing an identifier"; when err_missing_a_procedure_declaration => return "missing a procedure declaration" & hint_1; when err_closing_parenthesis_missing => return "missing closing parenthesis "")"""; when err_colon_missing => return "missing a colon "":"""; when err_colon_missing_for_named_statement => return "undefined identifier (" & hint_1 & ");" & " if a named statement is meant, a colon "":"" would be expected here"; when err_incorrectly_used_symbol => return "incorrectly used symbol [" & hint_1 & ']'; when err_missing_OF => return "missing ""of"""; when err_missing_an_opening_parenthesis => return "missing an opening parenthesis ""("""; when err_left_bracket_instead_of_parenthesis => return "found '[' instead of '('"; when err_right_bracket_instead_of_parenthesis => return "found ']' instead of ')'"; when err_missing_type_begin_symbol => -- We only show the supported symbols for starting a type definition. return "missing ""("", ""array"" or ""record"""; when err_expecting_double_dot => return "expecting double dot symbol: "".."""; when err_semicolon_missing => return "missing a semicolon: "";"""; when err_duplicate_semicolon => return "duplicate semicolon: "";"""; when err_extra_right_parenthesis => return "extra ')' ignored"; when err_bad_result_type_for_a_function => return "this type is not supported for a function's result; " & "try a procedure with an ""out"" parameter"; when err_type_of_return_statement_doesnt_match => return "type of expression in return statement doesn't match: " & hint_1; when err_illegal_statement_start_symbol => return "statement cannot start with a " & hint_1; when err_expecting_a_boolean_expression => return "expecting a Boolean expression"; when err_control_variable_of_the_wrong_type => return "control variable must be discrete; found: " & hint_1; when err_bounds_type_mismatch => return "bounds in range must be of the same type"; when err_IS_missing => return "missing ""is"""; when err_scanner_exponent_too_large => return "total actual exponent is too large:" & hint_1; when err_scanner_integer_literal_too_large => return "integer part of number literal is too large; max =" & integer_digits_max'Image & " digits"; when err_scanner_illegal_character_in_number => return "illegal character in number" & hint_1; when err_scanner_negative_exponent_for_integer_literal => return "integer literal with negative exponent; possible: a float with "".0"" such as" & hint_1; when err_incorrect_name_after_END => return """end " & hint_1 & ";"" expected here"; when err_bad_type_for_a_case_statement => return "bad type for a case statement"; when err_scanner_illegal_character => return "illegal character"; when err_illegal_constant_or_constant_identifier => return "illegal constant or constant identifier"; when err_wrong_type_for_array_index => return "type mismatch in array index: " & hint_1; when err_too_few_array_indices => return "too few indices in array reference: found" & hint_1 & ", needed" & hint_2; when err_too_many_array_indices => return "too many indices in array reference: found" & hint_1 & ", needed" & hint_2; when err_illegal_array_bounds => return "illegal bounds for an array index: " & hint_1; when err_indexed_variable_must_be_an_array => return "indexed variable must be an array"; when err_missing_a_type_identifier => return "identifier is not a type"; when err_undefined_type => return "undefined type"; when err_var_with_field_selector_must_be_record => return "var with field selector must be record"; when err_resulting_type_should_be_Boolean => return "resulting type should be Boolean"; when err_illegal_type_for_arithmetic_expression => return "illegal type for arithmetic expression"; when err_mod_requires_integer_arguments => return """mod"" requires integer arguments"; when err_incompatible_types_for_comparison => return "incompatible types for comparison: " & hint_1; when err_parameter_types_do_not_match => return "parameter types do not match: " & hint_1; when err_variable_missing => if hint_1 = "" then return "variable expected here"; else return "variable expected as actual for """ & hint_1 & '"'; end if; when err_scanner_character_zero_chars => return "a character literal is of the form 'x'; " & "strings are delimited by double quote character"; when err_number_of_parameters_do_not_match => return "number of parameters do not match" & hint_1; when err_illegal_parameters_to_Get => return "illegal parameters to ""Get"""; when err_illegal_parameters_to_Put => return "illegal parameters to ""Put"""; when err_parameter_must_be_of_type_Float => return "parameter must be of type Float"; when err_parameter_must_be_Integer => return "parameter must be of type Integer"; when err_expected_constant_function_variable_or_subtype => return "expected a constant, function, variable or subtype name"; when err_types_of_assignment_must_match => return "types must match in an assignment: " & hint_1; when err_case_label_not_same_type_as_case_clause => return "case label not of same type as case clause: " & hint_1; when err_duplicate_case_choice_value => return "duplicate choice value in ""case"" statement"; when err_argument_to_std_function_of_wrong_type => return "wrong type of argument to operator or standard function: " & hint_1; when err_stack_size => return "the program requires too much storage"; when err_illegal_symbol_for_a_number_declaration => return "illegal symbol for a number declaration or a literal"; when err_BECOMES_missing => return "missing "":="""; when err_THEN_missing => return "missing ""then"""; when err_IN_missing => return "missing ""in"""; when err_missing_closing_LOOP | err_missing_closing_LOOP_2 => return "missing closing ""loop"""; when err_BEGIN_missing => return "missing ""begin"""; when err_END_missing => return "missing ""end"""; when err_primary_unexpected_symbol => return "expected ""("", or: name, number, string, ... (RM 4.4 (7), 4.5(8))"; when err_RETURN_missing => return "missing ""return"""; when err_scanner_control_character => return "control character present in source "; when err_RECORD_missing => return "missing ""record"""; when err_missing_closing_IF | err_missing_closing_IF_2 => return "missing closing ""if"""; when err_WHEN_missing => return "missing ""when"" (must have at least one alternative)"; when err_FINGER_missing => return "missing the finger ""=>"""; when err_missing_closing_CASE | err_missing_closing_CASE_2 => return "missing closing ""case"""; when err_functions_must_return_a_value => return "functions must return a value"; when err_procedures_cannot_return_a_value => return "procedures cannot return a value (use functions instead)"; when err_missing_an_entry => return "expecting an entry"; when err_missing_expression_for_delay => return "missing expression for ""delay"""; when err_wrong_type_in_DELAY => return "delay time must be type Float"; when err_COMMA_missing => return "comma expected"; when err_expecting_accept_when_or_entry_id => return "expecting ""accept"", ""when"", or entry id"; when err_expecting_task_entry => return "expecting Task.Entry"; when err_expecting_OR_or_ELSE_in_SELECT => return "expecting ""or"" or ""else"" in select"; when err_expecting_DELAY => return "expecting ""delay"""; when err_SELECT_missing => return "missing ""select"""; when err_program_incomplete => return "program incomplete"; when err_OF_instead_of_IS => return "found ""of"", should be ""is"""; when err_THEN_instead_of_Arrow => return "found ""then"", should be ""=>"""; when err_EQUALS_instead_of_BECOMES => return "found ""="", should be "":="""; when err_numeric_constant_expected => return "numeric constant expected"; when err_scanner_identifier_too_long => return "identifier is too long; max =" & Integer'Image (identifier_length_max) & " characters"; when err_scanner_identifier_cannot_end_with_underline => return "identifier cannot end with underline"; when err_scanner_double_underline_not_permitted => return "double underline not permitted"; when err_statement_expected => return "statement expected, can be ""null"""; when err_duplicate_loop_identifier => return "loop identifier already defined above: " & hint_1; when err_unexpected_end_of_text => return "unexpected end of text"; when err_not_yet_implemented => return "construct not yet implemented or supported by HAC: " & hint_1; when err_type_conversion_not_supported => return "this type conversion is not supported: " & hint_1; when err_numeric_type_coercion => return "numeric types don't match: " & hint_1 & " - please use explicit conversion"; when err_numeric_type_coercion_operator => return "numeric types don't match (" & hint_1 & "): " & hint_2 & " - please use explicit conversion"; when err_operator_not_defined_for_types => return "operator (" & hint_1 & ") is not defined for that type(s) of operand(s): " & hint_2; when err_no_null_functions => return "a function cannot be null; only a procedure can"; when err_scanner_digit_expected => return "digit expected"; when err_cannot_modify_constant_or_in_parameter => return "cannot modify a constant or a ""in"" parameter" & hint_1; when err_case_others_alone_last => return "the ""others"" choice must appear alone and in the last choice list (RM 5.4 (5))"; when err_no_X_for_END_X => return "no """ & hint_1 & """ for this ""end " & hint_1 & """"; when err_END_LOOP_ident_missing => return """end loop " & hint_1 & ";"" expected (RM 5.5 (5))"; when err_END_LOOP_ident_wrong => return "wrong loop identifier: ""end loop " & hint_1 & ";"" expected"; when err_general_error => if hint_1 = "" then return "syntax error"; else return hint_1; -- The message is the hint. end if; when err_string_to_vstring_assignment => return "fixed string assigned to a variable string;" & " put a ""+"" in front of the fixed string"; when err_range_constraint_error => return "error in range constraint: " & hint_1; when err_discrete_type_expected => return "discrete type expected"; when err_membership_test_type_mismatch => return "incompatible types in membership test: " & hint_1; when err_string_not_supported_as_parameter => return "string not supported as parameter" & " - define a constrained ""subtype S2 is String (1..2)"" or use a VString"; when err_string_lengths_do_not_match => return "fixed-size string lengths do not match: " & hint_1; when err_library_error => return "library error: " & hint_1; when err_wrong_unit_name => return "unit name """ & hint_1 & """ expected in this file, found: """ & hint_2 & '"'; when err_obsolete_hat_name => return "the new name of """ & hint_2 & """ is """ & hint_1 & '"'; when err_object_used_before_end_own_declaration => return "attempt to use object " & hint_1 & "before end of its own declaration"; when err_attribute_prefix_invalid => return "invalid prefix for """ & hint_1 & """ attribute"; when err_attribute_prefix_must_be_discrete_type => return "prefix of """ & hint_1 & """ attribute must be discrete type"; when err_invalid_dimension_number => return "invalid dimension number for array type, " & hint_1; when err_spec_body_mismatch => return "specification vs. body mismatch: " & hint_1; when err_incomplete_declaration => return "missing body or full declaration for " & hint_1; when err_non_public_entity => return '"' & hint_1 & """ is not a public entity of the package in prefix"; when err_choices_not_covered => return "all case values shall be covered, either explicitly " & "or by ""others"" (RM 5.4 (6))" & hint_1; when err_choice_out_of_range => return "choice(s) out of range of case expression"; when err_mixed_logical_operators => return "mixed logical operators in expression (RM 4.4 (2)) - " & "clarify by using parentheses"; when err_scanner_space_missing_after_number => return "space missing here; " & "if an identifier was meant, it cannot start with a number"; when err_assignment_not_allowed_declarative => return "assignment (variable := ...) not allowed in declarative part"; when others => return hint_1; end case; end Diagnostic_String; ---------------------------------------------------------------------------- function "+" (S : String) return HAT.VString renames HAT."+"; -- The "[...]" are replaced by the correct identifier. repair_table : constant array (Compile_Diagnostic) of Repair_Kit := ( err_missing_a_procedure_declaration => (insert, +"procedure "), err_colon_missing => (insert, +": "), err_semicolon_missing => (insert, +"; "), err_RETURN_missing => (insert, +"return "), err_statement_expected => (insert, +"null;"), err_IN_missing => (insert, +"in "), err_IS_missing => (insert, +"is "), err_OF_instead_of_IS => (replace_token, +"is"), err_THEN_instead_of_Arrow => (replace_token, +"=>"), err_FINGER_missing => (insert, +" => "), err_missing_closing_LOOP => (insert, +" loop"), err_missing_closing_LOOP_2 => (replace_token, +"loop"), err_missing_closing_CASE => (insert, +" case"), err_missing_closing_CASE_2 => (replace_token, +"case"), err_missing_closing_IF => (insert, +" if"), err_missing_closing_IF_2 => (replace_token, +"if"), err_RECORD_missing => (insert, +" record"), err_closing_parenthesis_missing => (insert, +")"), err_END_LOOP_ident_missing => (insert, +"[ something... ]"), err_scanner_space_missing_after_number => (insert, +" "), err_choices_not_covered => (insert, +"\twhen others => null; -- Use with caution...\n"), err_incorrect_name_after_END | err_END_LOOP_ident_wrong | err_wrong_unit_name | err_obsolete_hat_name => (replace_token, +"[ something... ]"), err_EQUALS_instead_of_BECOMES => (replace_token, +":="), err_duplicate_semicolon => (replace_token, +""), err_extra_right_parenthesis => (replace_token, +""), others => nothing_to_repair ); procedure Diagnostic (CD : in out Co_Defs.Compiler_Data; code : Defs.Compile_Diagnostic; hint_1 : String := ""; hint_2 : String := ""; severity : Error_Severity := medium; location_method : Symbol_Location_Method := current_symbol; explicit_location : Defs.Symbol_Location := (0, 0, 0)) is use Ada.Strings, Ada.Strings.Fixed, Ada.Text_IO; to_be_marked : Symbol_Location; -- procedure Show_to_comp_dump (objNumber : Integer) is begin if CD.comp_dump_requested then Put_Line (CD.comp_dump, " Error code = " & Defs.Compile_Diagnostic'Image (code) & " (" & Diagnostic_String (code, hint_1, hint_2) & ") " & " srcNumber=" & to_be_marked.line'Image & " charStart=" & to_be_marked.column_start'Image & " charEnd=" & to_be_marked.column_stop'Image & " objNumber=" & objNumber'Image); end if; end Show_to_comp_dump; -- updated_repair_kit : Repair_Kit := repair_table (code); ub_hint : constant HAT.VString := HAT.To_VString (hint_1); use HAT.VStr_Pkg; kit : Diagnostic_Kit; -- function Diagnostic_Suffix return String is (case kit.diagnostic_kind is when warning | note => " [-r" & remark_letter (code) & ']', when others => ""); begin kit.diagnostic_kind := (case code is when Compile_Error => error, when Compile_Warning => warning, when Compile_Note => note); to_be_marked := (case location_method is when current_symbol => CD.CUD.location, when previous_symbol => CD.prev_sy_loc, when explicit => explicit_location); Show_to_comp_dump (-1); CD.diags (code) := True; if code in Compile_Error then if severity = minor then CD.minor_error_count := CD.minor_error_count + 1; else CD.error_count := CD.error_count + 1; end if; end if; if CD.trace.pipe = null then Put_Line (Current_Error, (if CD.CUD.source_file_name = "" then "" else To_String (CD.CUD.source_file_name) & ": " & Trim (to_be_marked.line'Image, Left) & ':' & Trim (to_be_marked.column_start'Image, Left) & '-' & Trim (to_be_marked.column_stop'Image, Left) & ": ") & Diagnostic_Prefix (kit.diagnostic_kind) & Diagnostic_String (code, hint_1, hint_2) & Diagnostic_Suffix); else case code is when err_incorrect_name_after_END => if hint_1 = "" then updated_repair_kit.repair_kind := none; else updated_repair_kit.alternative := ub_hint; end if; when err_END_LOOP_ident_missing => updated_repair_kit.alternative := ' ' & ub_hint; when err_END_LOOP_ident_wrong | err_obsolete_hat_name => updated_repair_kit.alternative := ub_hint; when err_wrong_unit_name => updated_repair_kit.alternative := HAT.To_VString (Librarian.Ada_RM_Casing (HAT.To_String (ub_hint))); when others => null; end case; Repair_Kit (kit) := updated_repair_kit; kit.message := To_Unbounded_String (Diagnostic_String (code, hint_1, hint_2)); kit.file_name := To_Unbounded_String (Co_Defs.Get_Source_Name (CD.CUD)); kit.location := to_be_marked; CD.trace.pipe (kit); end if; -- Uncomment the next line for getting a nice trace-back of 1st error. -- raise Constraint_Error; -- if code in Compile_Error and then severity = major then -- Useless to continue compiling, the source is FUBAR -- and the compiler close to total confusion! raise Compilation_abandoned; end if; end Diagnostic; procedure Error (CD : in out Co_Defs.Compiler_Data; code : Defs.Compile_Error; hint_1 : String := ""; hint_2 : String := ""; severity : Error_Severity := medium; location_method : Symbol_Location_Method := current_symbol; explicit_location : Defs.Symbol_Location := (0, 0, 0)) is begin Diagnostic (CD, code, hint_1, hint_2, severity, location_method, explicit_location); end Error; procedure Remark (CD : in out Co_Defs.Compiler_Data; code : Defs.Compile_Remark; hint_1 : String := ""; hint_2 : String := ""; location_method : Symbol_Location_Method := current_symbol; explicit_location : Defs.Symbol_Location := (0, 0, 0); remark_made : out Boolean) is begin remark_made := False; if CD.remarks (code) then -- Remark (Note or Warning) is optional. -- Severity (minor passed here) does nothing for remarks. Diagnostic (CD, code, hint_1, hint_2, minor, location_method, explicit_location); remark_made := True; end if; end Remark; procedure Remark (CD : in out Co_Defs.Compiler_Data; code : Defs.Compile_Remark; hint_1 : String := ""; hint_2 : String := ""; location_method : Symbol_Location_Method := current_symbol; explicit_location : Defs.Symbol_Location := (0, 0, 0)) is dummy : Boolean; begin Remark (CD, code, hint_1, hint_2, location_method, explicit_location, dummy); end Remark; ---------------------------------------------------------------------------- procedure Fatal (N : Table_OverFlow_Error; Current_Error_Output : Boolean := False) is use Ada.Text_IO; begin if Current_Error_Output then Put (Current_Error, "The Compiler TABLE for: *"); case N is when FLOAT_CONSTANTS => Put (Current_Error, "Float Constants"); when STRING_CONSTANTS => Put (Current_Error, "Strings Constants"); when Object_Code => Put (Current_Error, "Object Code"); when PATCHING => Put (Current_Error, "ObjCode PATCHING"); when others => Put (Current_Error, Table_OverFlow_Error'Image (N)); end case; Put_Line (Current_Error, "* is too SMALL"); New_Line (Current_Error); Put_Line (Current_Error, " Please take this output to the maintainers of "); Put_Line (Current_Error, " HAC for your installation "); New_Line (Current_Error); Put_Line (Current_Error, " Fatal termination of HAC"); end if; -- raise Failure_1_0 with "HAC.UErrors.Fatal:" & " internal HAC compiler error." & " The table for " & Table_OverFlow_Error'Image (N) & " is too small. More details with qDebug=True"; end Fatal; ---------------------------------------------------------------------------- procedure Compilation_Diagnostics_Summary (CD : Co_Defs.Compiler_Data) is use Ada.Text_IO; procedure Summary_Line (s : String) is begin if CD.comp_dump_requested then Put_Line (CD.comp_dump, s); end if; if CD.listing_requested then Put_Line (CD.listing, s); end if; end Summary_Line; begin Summary_Line (""); for K in CD.diags'Range loop if K = Compile_Error'First then Summary_Line ("==== Error Message(s) ===="); elsif K = Compile_Warning'First then Summary_Line ("==== Warning(s) =========="); end if; if CD.diags (K) then Summary_Line (K'Image & ": " & Diagnostic_String (K)); end if; end loop; end Compilation_Diagnostics_Summary; end HAC_Sys.Errors; ================================================ FILE: src/compile/hac_sys-errors.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- with HAC_Sys.Co_Defs, HAC_Sys.Defs; with HAT; package HAC_Sys.Errors is nothing_to_repair : constant Defs.Repair_Kit := (Defs.none, HAT.Null_VString); type Error_Severity is (minor, -- Extra ';', ')', value out of range, etc.: we can continue the -- compilation normally for catching other possible errors. medium, -- Compilation is shortened at some points in order to avoid -- infinite loops in the parser. Tricky! major); -- In this case, the best choice is to STOP the compilation immediately. type Symbol_Location_Method is (current_symbol, previous_symbol, explicit); procedure Error (CD : in out Co_Defs.Compiler_Data; code : Defs.Compile_Error; hint_1 : String := ""; hint_2 : String := ""; severity : Error_Severity := medium; location_method : Symbol_Location_Method := current_symbol; explicit_location : Defs.Symbol_Location := (0, 0, 0)); procedure Remark (CD : in out Co_Defs.Compiler_Data; code : Defs.Compile_Remark; hint_1 : String := ""; hint_2 : String := ""; location_method : Symbol_Location_Method := current_symbol; explicit_location : Defs.Symbol_Location := (0, 0, 0); remark_made : out Boolean); procedure Remark (CD : in out Co_Defs.Compiler_Data; code : Defs.Compile_Remark; hint_1 : String := ""; hint_2 : String := ""; location_method : Symbol_Location_Method := current_symbol; explicit_location : Defs.Symbol_Location := (0, 0, 0)); function Diagnostic_Prefix (kind : Defs.Diagnostic_Kind_Type) return String is (case kind is when Defs.error => "", when Defs.warning => "warning: ", when Defs.note => "note: ", when Defs.style => "style: "); procedure Compilation_Diagnostics_Summary (CD : Co_Defs.Compiler_Data); type Table_OverFlow_Error is (IDENTIFIERS, PROCEDURES, FLOAT_CONSTANTS, ARRAYS, LEVELS, Loop_Nesting_Levels, Object_Code, Case_Labels, STRING_CONSTANTS, TASKS, ENTRIES, PATCHING); procedure Fatal (N : Table_OverFlow_Error; Current_Error_Output : Boolean := False); Internal_error : exception; Failure_1_0 : exception; Compilation_abandoned : exception; Compilation_of_package_body_before_spec : exception; end HAC_Sys.Errors; ================================================ FILE: src/compile/hac_sys-multi_precision_integers.adb ================================================ ----------------------------------------------------------------------------- -- File: hac_sys-multi_precision_integers.ads ----------------------------------------------------------------------------- -- Aug-2007: - No more generics (Long_Block_type, -- Block_type,... always the largest possible idea: J.C.) -- - Fixed Basic(...) (based on J.C.'s remarks) -- Nov-2006: - Multiply_internal with/without copy of result (automatic -- detection of when it is needed) -- - Explicit Multiply_internal for Multi_int * Basic_int -- - Multiply(multi,basic,multi) available as procedure -- - useless zeroing of quotient removed -- - useless zeroing of blocks removed for indices -- above last possible used in * -- 24-Feb-2002: Div_Rem(u, v, v, r) also possible -- 23-Feb-2002: DEBUG: +: multiplications are verified by dividing the result -- +: divisions are verified by comparing i2*q+r and i1 -- 15-Feb-2002: "zero" and 1st index in Divide_absolute_normalized -- bugs fixed by Duncan Sands (D.S.) pragma Warnings (".P"); pragma Warnings (".I"); pragma Warnings ("C"); with Ada.Unchecked_Deallocation; package body HAC_Sys.Multi_Precision_Integers is use type Basic_Int; function Shift_Left (Value : Block_type; Amount : Natural) return Block_type is begin return Value * (2 ** Amount); end Shift_Left; function Shift_Right (Value : Block_type; Amount : Natural) return Block_type is begin return Value / (2 ** Amount); end Shift_Right; function Shift_Left (Value : Long_Block_type; Amount : Natural) return Long_Block_type is begin return Value * (2 ** Amount); end Shift_Left; function Shift_Right (Value : Long_Block_type; Amount : Natural) return Long_Block_type is begin return Value / (2 ** Amount); end Shift_Right; -- Internal_error: exception; -- Not_done: exception; type compar is (smaller, equal, greater); function Min (a, b : Index_Int) return Index_Int is begin return (if a < b then a else b); end Min; function Max (a, b : Index_Int) return Index_Int is begin return (if a > b then a else b); end Max; procedure Reduce_last_nonzero (n : in out Multi_int) is old_last : constant Index_Int := n.last_used; begin if n.zero then -- We avoid de-zeroing accidentally return; -- and returning a false non-zero with rubbish :-) end if; n.zero := True; for i in 0 .. old_last loop -- after old_last it *is* rubbish anyway. if n.blk (i) /= 0 then n.zero := False; n.last_used := i; end if; end loop; end Reduce_last_nonzero; function Compare_absolute (i1, i2 : Multi_int) return compar is l1, l2 : Index_Int; begin -- On ne compare que ABS(i1) et ABS(i2) l1 := i1.last_used; l2 := i2.last_used; if l1 > l2 then -- i1 a plus de blocs non nuls return greater; elsif l1 < l2 then -- i1 a moins de blocs non nuls return smaller; else -- i1 et i2 ont le meme nb de blocs for i in reverse 0 .. l1 loop -- on parcourt du + signifiant au - if i1.blk (i) > i2.blk (i) then -- <> de i1 plus grand return greater; elsif i1.blk (i) < i2.blk (i) then -- <> de i1 plus petit return smaller; end if; -- M\^emes chiffres -> au suivant! end loop; -- Bon, les 2 nombres sont egaux! return equal; end if; end Compare_absolute; ----- Informations, conversions function Multi (small : Basic_Int) return Multi_int is long : Long_Block_type_signed; abs_long, heading : Long_Block_type; small_enough, case_first_value : Boolean; negs : constant Boolean := small < 0; Conversion_overflow : exception; begin abs_long := 0; long := Long_Block_type_signed (small); case_first_value := long = Long_Block_type_signed'First; if case_first_value then -- `long` is equal to the lowest value for Long_Block_type_signed. -- Then, (abs long) will automatically overflow. -- For example, for a 64-bit integer, -2**63 is ok, but 2**63 is -- larger than the maximum 64-bit integer, 2**63 - 1. -- So we have to have a special case for that value. small_enough := False; else abs_long := Long_Block_type (abs long); small_enough := abs_long <= Long_Block_type (maxblock); end if; -- if small_enough then return Multi_int' (n => 0, -- One block is enough. blk => (0 => Block_type (abs_long)), -- The block contains the number. neg => negs, zero => small = 0, last_used => 0 ); elsif case_first_value then heading := Shift_Right (Long_Block_type (-(Long_Block_type_signed'First / 2)), -- E.g. for 64-bit: 2**62. Block_type_bits - 1); -- First shift is done by the / 2. return Multi_int' (n => 1, -- Two blocks are needed. blk => (0 => 0, -- Block #0 1 => Block_type (heading)), -- Block #1 neg => True, zero => False, last_used => 1 ); else heading := Shift_Right (abs_long, Block_type_bits); if heading <= Long_Block_type (maxblock) then return (n => 1, -- Two blocks are needed. blk => (0 => Block_type (abs_long and maxblock), -- Block #0 1 => Block_type (heading)), -- Block #1 neg => negs, zero => False, last_used => 1 ); else if Shift_Right (heading, Block_type_bits) > Long_Block_type (maxblock) then raise Conversion_overflow; end if; return (n => 2, -- Three blocks are needed. (e.g. 31 bits: 15+15+1) blk => (0 => Block_type (abs_long and maxblock), -- Block #0 1 => Block_type (heading and maxblock), -- Block #1 2 => Block_type (Shift_Right (heading, Block_type_bits)) -- Block #2 ), neg => negs, zero => False, last_used => 2 ); end if; end if; end Multi; zero : constant Multi_int := Multi (0); one : constant Multi_int := Multi (1); Blocks_Per_Basic : constant Positive := (Basic_Int'Size + Block_type'Size - 1) / Block_type'Size; -- Convert Multi_int to Basic_int (when possible, else: Cannot_fit raised) -- 2007: -- - correct code for block sizes smaller than Basic_int -- - fixed usage of negative flag function Basic (large : Multi_int) return Basic_Int is type Same_as_Basic_natural is mod 2 ** Basic_Int'Size; function Shift_Left (Value : Same_as_Basic_natural; Amount : Natural) return Same_as_Basic_natural is begin return Value * (2 ** Amount); end Shift_Left; result : Same_as_Basic_natural; block_value : Block_type; type Huge_int is mod System.Max_Binary_Modulus; last_bit : Natural; begin if large.zero then -- <- 17-Feb-2002 return 0; end if; -- Case: too many blocks (whatever sizes) if 1 + large.last_used > Blocks_Per_Basic then raise Cannot_fit; end if; -- Case: block size and contents larger than basic block_value := large.blk (large.last_used); if Huge_int (block_value) > Huge_int (Basic_Int'Last) then raise Cannot_fit; end if; declare tmp : Block_type := block_value; begin last_bit := 0; while tmp /= 0 loop tmp := tmp / 2; last_bit := last_bit + 1; end loop; end; result := Same_as_Basic_natural (block_value); -- If the following loop was on all blocks, -- the shift by Block_type_bits in the loop could do meaningless -- things the case Basic_int'Size <= Block_Type'Size for b in reverse 0 .. large.last_used - 1 loop result := Shift_Left (result, Block_type_bits); -- An overflow is not detected by shifting (it's the way we want it!) -- so we need to detect the overall overflow by locating the -- last bit. last_bit := last_bit + Block_type_bits; if last_bit > Basic_Int'Size - 1 then -- ^ "- 1" because of sign bit in Basic_int raise Cannot_fit; end if; result := result + Same_as_Basic_natural (large.blk (b)); end loop; if large.neg then return -Basic_Int (result); else return Basic_Int (result); end if; end Basic; -- 14-Feb-2002: "zero" bug fixed by Duncan Sands procedure Fill (what : out Multi_int; with_smaller : Multi_int) is l : constant Index_Int := with_smaller.last_used; begin what.zero := with_smaller.zero; if with_smaller.zero then return; end if; if what.n < l then raise Array_too_small; -- contenant trop petit end if; what.blk (0 .. l) := with_smaller.blk (0 .. l); -- copy contents what.neg := with_smaller.neg; what.last_used := l; end Fill; procedure Fill (what : out Multi_int; with_basic : Basic_Int) is begin Fill (what, Multi (with_basic)); end Fill; function Bits_per_block return Positive is begin return Block_type_bits; end Bits_per_block; --------------------------- ----- Unary operators ----- --------------------------- function "+" (i : Multi_int) return Multi_int is begin return i; end "+"; procedure Opp (i : in out Multi_int) is begin i.neg := not i.neg; -- -0 possible, anyway i.zero = True in such a case end Opp; function "-" (i : Multi_int) return Multi_int is res : Multi_int (i.n) := i; -- copy + stack :-( begin Opp (res); return res; end "-"; procedure Abso (i : in out Multi_int) is begin i.neg := False; end Abso; function "Abs" (i : Multi_int) return Multi_int is abs_i : Multi_int (i.n) := i; -- copy + stack :-( begin abs_i.neg := False; return abs_i; end "Abs"; function Sign (i : Multi_int) return Basic_Int is begin if i.zero then return 0; elsif i.neg then return -1; else return +1; end if; end Sign; function Even (i : Multi_int) return Boolean is begin return i.zero or else i.blk (0) mod 2 = 0; end Even; function Odd (i : Multi_int) return Boolean is begin return (not i.zero) and then i.blk (0) mod 2 = 1; end Odd; ---------------------------- ----- Binary operators ----- ---------------------------- -- Internal algorithm to add two numbers AS POSITIVE ( > 0 ) ! procedure Add_absolute (i1, i2 : in Multi_int; i3 : out Multi_int) is l1 : constant Index_Int := i1.last_used; l2 : constant Index_Int := i2.last_used; min_ind : constant Index_Int := Min (l1, l2); max_ind : constant Index_Int := Max (l1, l2); s : Long_Block_type := 0; retenue_finale : Block_type; begin if max_ind > i3.n then raise Result_undersized; end if; -- 17-Feb-2002 -- (1) On additionne sur le <> for ind in 0 .. min_ind loop s := Long_Block_type (i1.blk (ind)) + Long_Block_type (i2.blk (ind)) + Shift_Right (s, Block_type_bits); -- (retenue) i3.blk (ind) := Block_type (s and maxblock); -- NB: dans un cas de Add(a,b,a) ou Add(a,b,b), -- i1.blk(ind) ou i2.blk(ind) est modifie en meme temps! end loop; -- (2) On poursuit au besoin si i1 a plus de blocs... if l1 > min_ind then for ind in min_ind + 1 .. max_ind loop s := Long_Block_type (i1.blk (ind)) + Shift_Right (s, Block_type_bits); -- (retenue) i3.blk (ind) := Block_type (s and maxblock); end loop; -- ... ou bien si i2 en a plus. elsif l2 > min_ind then for ind in min_ind + 1 .. max_ind loop s := Long_Block_type (i2.blk (ind)) + Shift_Right (s, Block_type_bits); -- (retenue) i3.blk (ind) := Block_type (s and maxblock); end loop; end if; -- (3) Il peut rester une retenue retenue_finale := Block_type (Shift_Right (s, Block_type_bits)); if retenue_finale /= 0 then if max_ind + 1 > i3.n then raise Result_undersized; end if; -- 17-Feb-2002 i3.blk (max_ind + 1) := retenue_finale; i3.last_used := max_ind + 1; else i3.last_used := max_ind; end if; -- (4) i3 = i1+i2 > 0 i3.neg := False; i3.zero := False; end Add_absolute; -- Internal algorithm to subtract two numbers AS POSITIVE ( > 0 ) ! procedure Sub_absolute (i1, i2 : in Multi_int; i3 : in out Multi_int; sgn : out Boolean) is l1 : constant Index_Int := i1.last_used; l2 : constant Index_Int := i2.last_used; max_ind : constant Index_Int := Max (l1, l2); ai, bi : Long_Block_type; s : Block_type; retenue_finale : Long_Block_type; begin if max_ind > i3.n then raise Result_undersized; end if; -- 17-Feb-2002 i3.last_used := 0; i3.zero := True; s := 0; -- (1) Soustraction avec retenue for ind in 0 .. max_ind loop if ind <= l1 then ai := Long_Block_type (i1.blk (ind)); else ai := 0; end if; if ind <= l2 then bi := Long_Block_type (i2.blk (ind)) + Long_Block_type (s); else bi := Long_Block_type (s); end if; if ai < bi then ai := ai + cardblock; s := 1; else s := 0; end if; i3.blk (ind) := Block_type (ai - bi); -- NB: dans un cas de Sub(a,b,a) ou Sub(a,b,b), -- i1.blk(ind) ou i2.blk(ind) est modifie en meme temps! if i3.blk (ind) /= 0 then -- au passage, on corrige .last_used et .zero i3.last_used := ind; i3.zero := False; end if; end loop; -- (2) Traitement de la derni\`ere retenue if s = 0 then i3.neg := False; sgn := False; else i3.neg := True; sgn := True; i3.last_used := 0; retenue_finale := 1; -- on fait "9-chaque chiffre" et on ajoute 1 au tout for i in 0 .. max_ind loop retenue_finale := Long_Block_type (maxblock) - Long_Block_type (i3.blk (i)) + retenue_finale; i3.blk (i) := Block_type (retenue_finale and maxblock); if i3.blk (i) /= 0 then i3.last_used := i; end if; retenue_finale := Shift_Right (retenue_finale, Block_type_bits); end loop; end if; end Sub_absolute; procedure Add (i1, i2 : in Multi_int; i3 : in out Multi_int) is sgn : Boolean; begin -- (1) Les cas o\`u i1 ou i2 = 0 if i1.zero and i2.zero then i3.zero := True; elsif i1.zero then Fill (i3, i2); elsif i2.zero then Fill (i3, i1); -- (2) Maintenant: i1 /= 0 et i2 /= 0; on regarde les signes -- (2.1) Facile: i1 et i2 de m\^eme signe elsif i1.neg = i2.neg then Add_absolute (i1, i2, i3); -- On fait comme si i1>0 et i2>0 i3.neg := i1.neg; -- et on met le bon signe -- (2.2) i1 < 0, i2 > 0, donc i3 = i2 - abs(i1) elsif i1.neg and not i2.neg then Sub_absolute (i2, i1, i3, sgn); -- (2.3) i1 > 0, i2 < 0, donc i3 = i1 - abs(i2) elsif i2.neg and not i1.neg then Sub_absolute (i1, i2, i3, sgn); end if; end Add; function "+" (i1, i2 : Multi_int) return Multi_int is somme : Multi_int (Max (i1.n, i2.n) + 1); begin Add (i1, i2, somme); return somme; end "+"; procedure Sub (i1, i2 : in Multi_int; i3 : in out Multi_int) is sgn : Boolean; begin -- (1) Les cas o\`u i1 ou i2 = 0 if i1.zero and i2.zero then i3.zero := True; elsif i1.zero then Fill (i3, i2); i3.neg := not i2.neg; elsif i2.zero then Fill (i3, i1); -- (2) Maintenant: i1 /= 0 et i2 /= 0; on regarde les signes -- (2.1) Facile: i1 et i2 de m\^eme signe elsif i1.neg = i2.neg then Sub_absolute (i1, i2, i3, sgn); -- On fait comme si i1>0 et i2>0 -- et on met le bon signe i3.neg := i1.neg xor sgn; -- 26-Mar-2002: equivalent a: -- if i1.neg then -- i3.neg:= NOT sgn; -- else -- i3.neg:= sgn; -- end if; -- (2.2) i1 < 0, i2 > 0, donc i3 = i1-i2 = - (abs(i1) + abs(i2)) elsif i1.neg and not i2.neg then Add_absolute (i1, i2, i3); i3.neg := True; -- (2.3) i1 > 0, i2 < 0, donc i3 = i1-i2 = i1 + (-i2) = i1 + abs(i2) elsif i2.neg and not i1.neg then Add_absolute (i1, i2, i3); end if; end Sub; function "-" (i1, i2 : Multi_int) return Multi_int is diff : Multi_int (Max (i1.n, i2.n) + 1); -- +1: retenue possible (add_abs.) begin Sub (i1, i2, diff); return diff; end "-"; function "+" (i1 : Multi_int; i2 : Basic_Int) return Multi_int is begin return i1 + Multi (i2); end "+"; function "+" (i1 : Basic_Int; i2 : Multi_int) return Multi_int is begin return Multi (i1) + i2; end "+"; function "-" (i1 : Multi_int; i2 : Basic_Int) return Multi_int is begin return i1 - Multi (i2); end "-"; function "-" (i1 : Basic_Int; i2 : Multi_int) return Multi_int is begin return Multi (i1) - i2; end "-"; ----- Begin of MULTIPLICATION part ----- -- Added 2006: choice to copy result into i3 or write directly into i3 generic copy : Boolean; procedure Multiply_internal_m_m (i1, i2 : in Multi_int; i3 : in out Multi_int); type p_Block_array is access Block_array; procedure Dispose is new Ada.Unchecked_Deallocation (Block_array, p_Block_array); ------------------- -- Multi * Multi -- ------------------- -- To do: implement a faster algorithm. -- 1) Karatsuba's algorithm -- Ada code for string arithm exists -- http://www.csc.liv.ac.uk/~ped/teachadmin/algor/karatsuba.ada -- 2) Better: Schnhage-Strassen algorithm (no Ada code) procedure Multiply_internal_m_m (i1, i2 : in Multi_int; i3 : in out Multi_int) is l1 : constant Index_Int := i1.last_used; l2 : constant Index_Int := i2.last_used; last_max : constant Index_Int := l1 + l2 + 2; prod, sum_carry, rk, i1j : Long_Block_type; i, k : Index_Int; res : p_Block_array; -- res: buffer used in the "copy" variant to avoid -- problems with Multiply(i,j,i) or Multiply(j,i,i) begin if i1.zero or i2.zero then i3.zero := True; return; end if; if last_max > i3.n then raise Result_undersized; end if; if copy then res := new Block_array (0 .. last_max); for k in res'Range loop res (k) := 0; end loop; -- Seems slower :-( : res:= new Block_array'( 0..last_max => 0); else for k in 0 .. last_max loop i3.blk (k) := 0; end loop; -- Slower :-( : i3.blk(0..last_max):= (others => 0); end if; i3.zero := False; i3.last_used := last_max; -- NB: va changer i1.last_used ou i2.last_used si -- i1 ou i2 et i3 sont les memes for j in 0 .. l1 loop i1j := Long_Block_type (i1.blk (j)); sum_carry := 0; i := 0; k := j; loop if i <= l2 then prod := i1j * Long_Block_type (i2.blk (i)); else exit when sum_carry = 0; -- nothing more to add prod := 0; end if; if copy then rk := Long_Block_type (res (k)); else rk := Long_Block_type (i3.blk (k)); end if; sum_carry := rk + prod + sum_carry; if copy then res (k) := Block_type (sum_carry and maxblock); -- somme else i3.blk (k) := Block_type (sum_carry and maxblock); -- somme end if; sum_carry := Shift_Right (sum_carry, Block_type_bits); -- retenue i := i + 1; k := k + 1; end loop; end loop; if copy then i3.blk (res'Range) := res.all; Dispose (res); end if; Reduce_last_nonzero (i3); i3.neg := i1.neg /= i2.neg; end Multiply_internal_m_m; procedure Multiply_internal_copy is new Multiply_internal_m_m (copy => True); procedure Multiply_internal_copy_export (i1, i2 : in Multi_int; i3 : in out Multi_int) renames Multiply_internal_copy; -- ^ At least GNAT <= GPL 2006 requires the trick with renames... -- ObjectAda 7.2.2 too -> there must be a good reason... procedure Multiply_internal_no_copy is new Multiply_internal_m_m (copy => False); ------------------- -- Multi * Basic -- -- added 2006 -- ------------------- generic copy : Boolean; procedure Multiply_internal_m_b (i1 : in Multi_int; i2 : Basic_Int; i3 : in out Multi_int); procedure Multiply_internal_m_b (i1 : in Multi_int; i2 : Basic_Int; i3 : in out Multi_int) is l1 : constant Index_Int := i1.last_used; last_max : constant Index_Int := l1 + 2; prod, sum_carry, rk, i2a : Long_Block_type; k : Index_Int; res : p_Block_array; -- res: buffer used in the "copy" variant to avoid -- problems with Multiply(i,j,i) or Multiply(j,i,i) begin if i1.zero or i2 = 0 then i3.zero := True; return; end if; if last_max > i3.n then raise Result_undersized; end if; if copy then res := new Block_array (0 .. last_max); for k in res'Range loop res (k) := 0; end loop; -- Seems slower :-( : res:= new Block_array'( 0..last_max => 0); else for k in 0 .. last_max loop i3.blk (k) := 0; end loop; -- Slower :-( : i3.blk(0..last_max):= (others => 0); end if; i3.zero := False; i3.last_used := last_max; -- NB: va changer i1.last_used ou i2.last_used si i1 ou i2 et i3 sont les memes i2a := Long_Block_type (abs i2); for j in 0 .. l1 loop k := j; sum_carry := 0; prod := Long_Block_type (i1.blk (j)) * i2a; loop if copy then rk := Long_Block_type (res (k)); else rk := Long_Block_type (i3.blk (k)); end if; sum_carry := rk + prod + sum_carry; if copy then res (k) := Block_type (sum_carry and maxblock); -- somme else i3.blk (k) := Block_type (sum_carry and maxblock); -- somme end if; sum_carry := Shift_Right (sum_carry, Block_type_bits); -- retenue exit when sum_carry = 0; -- nothing more to add prod := 0; k := k + 1; end loop; end loop; if copy then i3.blk (res'Range) := res.all; Dispose (res); end if; Reduce_last_nonzero (i3); i3.neg := i1.neg /= (i2 < 0); end Multiply_internal_m_b; procedure Multiply_internal_copy is new Multiply_internal_m_b (copy => True); procedure Multiply_internal_no_copy is new Multiply_internal_m_b (copy => False); procedure Multiply (i1, i2 : in Multi_int; i3 : in out Multi_int) is use System; begin if Debug then declare m1 : constant Multi_int := i1; m2 : constant Multi_int := i2; begin Multiply_internal_no_copy (m1, m2, i3); end; else if i1'Address = i3'Address or i2'Address = i3'Address then -- Ada.Text_IO.Put_Line("* with copy"); Multiply_internal_copy (i1, i2, i3); else -- Ada.Text_IO.Put_Line("* without copy"); Multiply_internal_no_copy (i1, i2, i3); end if; end if; end Multiply; procedure Multiply (i1 : in Multi_int; i2 : Basic_Int; i3 : in out Multi_int) is use System; begin if Debug then declare m1 : constant Multi_int := i1; m2 : constant Basic_Int := i2; begin Multiply_internal_no_copy (m1, m2, i3); end; else if i1'Address = i3'Address or i2'Address = i3'Address then -- Ada.Text_IO.Put_Line("* with copy"); Multiply_internal_copy (i1, i2, i3); else -- Ada.Text_IO.Put_Line("* without copy"); Multiply_internal_no_copy (i1, i2, i3); end if; end if; end Multiply; function "*" (i1, i2 : Multi_int) return Multi_int is begin if i1.zero or i2.zero then return zero; else declare prod : Multi_int (i1.last_used + i2.last_used + 2); begin Multiply (i1, i2, prod); return prod; end; end if; end "*"; function "*" (i1 : Multi_int; i2 : Basic_Int) return Multi_int is begin if i1.zero or i2 = 0 then return zero; else declare prod : Multi_int (i1.last_used + 4); begin Multiply (i1, i2, prod); return prod; end; end if; end "*"; function "*" (i1 : Basic_Int; i2 : Multi_int) return Multi_int is begin if i2.zero or i1 = 0 then return zero; else declare prod : Multi_int (i2.last_used + 4); begin Multiply (i2, i1, prod); return prod; end; end if; end "*"; ----- Begin of DIVISION part ----- -- Interne: Division et reste en 1 coup procedure Div_Rem (a, b : Long_Block_type; q, r : out Long_Block_type) is Conflict_with_REM : exception; begin q := a / b; r := a - b * q; if Debug and then r /= (a rem b) then raise Conflict_with_REM; end if; end Div_Rem; procedure Divide_absolute_normalized (u : in out Multi_int; -- output: u = r v : in Multi_int; q : in out Multi_int) is qi : Index_Int := u.last_used - v.last_used - 1; -- was: q.n; D.S. Feb-2002 v1 : constant Long_Block_type := Long_Block_type (v.blk (v.last_used)); v2 : constant Long_Block_type := Long_Block_type (v.blk (v.last_used - 1)); vlast : constant Index_Int := v.last_used; v1L : constant Long_Block_type := v1; guess, comparand : Long_Block_type; function Divide_subtract (ustart : Index_Int) return Block_type is ui : Index_Int; carry : Long_Block_type; begin if guess = 0 then return 0; end if; ui := ustart; carry := 0; -- On soustrait (le chiffre du quotient) * diviseur au dividende for vi in 0 .. vlast loop declare prod : constant Long_Block_type := Long_Block_type (v.blk (vi)) * guess + carry; bpro : constant Block_type := Block_type (prod and maxblock); diff : constant Long_Block_type_signed := Long_Block_type_signed (u.blk (ui)) - Long_Block_type_signed (bpro); begin if diff < 0 then u.blk (ui) := Block_type (diff + cardblock); carry := Shift_Right (prod, Block_type_bits) + 1; else u.blk (ui) := Block_type (diff); carry := Shift_Right (prod, Block_type_bits); end if; ui := ui + 1; end; end loop; if carry = 0 then return Block_type (guess and maxblock); end if; declare diff : constant Long_Block_type_signed := Long_Block_type_signed (u.blk (ui)) - Long_Block_type_signed (carry and maxblock); begin if diff < 0 then u.blk (ui) := Block_type (diff + cardblock); -- carry generated else u.blk (ui) := Block_type (diff); return Block_type (guess and maxblock); end if; end; -- Carry was generated declare icarry : Block_type := 0; begin ui := ustart; for vi in 0 .. vlast loop declare sum : constant Long_Block_type := Long_Block_type (v.blk (vi)) + Long_Block_type (u.blk (ui)) + Long_Block_type (icarry); begin u.blk (ui) := Block_type (sum and maxblock); ui := ui + 1; icarry := Block_type (Shift_Right (sum, Block_type_bits)); end; end loop; if icarry = 1 then u.blk (ui) := Block_type ((Long_Block_type (u.blk (ui)) + 1) and maxblock); end if; end; return Block_type ((guess - 1) and maxblock); end Divide_subtract; is_q_zero : Boolean := True; begin -- Divide_absolute_normalized -- for i in q.blk'Range loop q.blk(i):= 0; end loop; -- -- ^ zeroing useless: q.last_used = u.last_used-v.last_used-1 -- and q.blk(0..q.last_used) is written below q.blk(qi) := ... -- GM 4-nov-2006 q.last_used := qi; -- was: q.n; D.S. Feb-2002 for j in reverse vlast + 1 .. u.last_used loop declare uj : constant Long_Block_type := Long_Block_type (u.blk (j)); uj1 : constant Long_Block_type := Long_Block_type (u.blk (j - 1)); uj2 : constant Long_Block_type := Long_Block_type (u.blk (j - 2)); ujL, rmL : Long_Block_type; begin ujL := Shift_Left (uj, Block_type_bits) + uj1; Div_Rem (ujL, v1L, guess, rmL); comparand := Shift_Left (rmL, Block_type_bits) + uj2; while comparand < v2 * guess loop guess := guess - 1; comparand := comparand + Shift_Left (v1L, Block_type_bits); exit when comparand > cardblock * cardblock; end loop; q.blk (qi) := Divide_subtract (j - vlast - 1); if q.blk (qi) /= 0 and then is_q_zero then -- n'arrive que 0 ou 1 fois is_q_zero := False; q.last_used := qi; end if; qi := qi - 1; end; end loop; -- j q.zero := is_q_zero; end Divide_absolute_normalized; procedure Divide_absolute_big_small (u : in Multi_int; v : in Long_Block_type; q : out Multi_int; r : out Long_Block_type) is n : Long_Block_type; Quotient_constraint_error : exception; last_u_nz : constant Index_Int := u.last_used; u_zero : constant Boolean := u.zero; -- in case u and q are the same variables is_q_zero : Boolean := True; begin if q.n < last_u_nz then raise Quotient_constraint_error; end if; q.last_used := 0; q.neg := False; r := 0; if not u_zero then for i in reverse 0 .. last_u_nz loop n := Long_Block_type (u.blk (i)) + Shift_Left (r, Block_type_bits); r := n mod v; q.blk (i) := Block_type (n / v); if q.blk (i) /= 0 and then is_q_zero then is_q_zero := False; q.last_used := i; end if; end loop; q.zero := is_q_zero; end if; end Divide_absolute_big_small; procedure Solve_signs_for_Div_Rem (i1n, i2n : in Boolean; qn, rn : out Boolean) is begin -- Invariant: i1= i2*q+r on cherche (pos) = (pos)*(pos)+(pos) if i1n and i2n then -- i1<0; i2<0 (-i1) = (-i2) * q + (-r) qn := False; -- Quotient > 0 -- rn:= True; -- Reste < 0 elsif i1n then -- i1<0; i2>0 (-i1) = i2 *(-q) + (-r) qn := True; -- Quotient < 0 -- rn:= True; -- Reste < 0 elsif i2n then -- i1>0; i2<0 i1 = (-i2) *(-q) + r qn := True; -- Quotient < 0 -- rn:= False; -- Reste > 0 else -- i1>0; i2>0 i1 = i2 * q + r qn := False; -- Quotient > 0 -- rn:= False; -- Reste > 0 end if; -- on observe que... "(A rem B) has the sign of A " ARM 4.5.5 -- en effet on peut mettre: rn := i1n; end Solve_signs_for_Div_Rem; procedure Div_Rem (i1 : in Multi_int; i2 : in Basic_Int; q : out Multi_int; r : out Basic_Int) is i1_neg : constant Boolean := i1.neg; -- in case i1 and q are the same variables rneg : Boolean; lai2, lr : Long_Block_type; begin if i2 = 0 then raise Division_by_zero; end if; if i1.zero then -- 15-Feb-2002: 0/i2 q.zero := True; r := 0; return; end if; lai2 := Long_Block_type (abs i2); Divide_absolute_big_small (i1, lai2, q, lr); r := Basic_Int (lr); Solve_signs_for_Div_Rem (i1_neg, i2 < 0, q.neg, rneg); if rneg then r := -r; end if; end Div_Rem; type Div_Rem_mode is (div_only, both); generic div_rem_output : Div_Rem_mode; procedure Div_Rem_internal (i1, i2 : in Multi_int; q, r : in out Multi_int); procedure Div_Rem_internal (i1, i2 : in Multi_int; q, r : in out Multi_int) is -- Calculate u/v procedure Divide_absolute (u, v : in Multi_int; q, r : in out Multi_int) is shift : Integer := 0; v1 : Block_type := v.blk (v.last_used); v_zero, v1_zero : exception; u_work : Multi_int (u.last_used + 2); use System; procedure Normalization (source : in Multi_int; target : in out Multi_int) is carry : Block_type := 0; tl : constant Index_Int := target.last_used; blk : Block_type; begin for i in 0 .. source.last_used loop blk := source.blk (i); target.blk (i) := Shift_Left (blk, shift) + carry; carry := Shift_Right (blk, Block_type_bits - shift); end loop; if source.last_used < tl then target.blk (source.last_used + 1) := carry; end if; for i in source.last_used + 2 .. tl loop target.blk (i) := 0; end loop; end Normalization; procedure Unnormalization (m : in out Multi_int) is carry : Block_type := 0; blk : Block_type; begin for i in reverse 0 .. m.last_used loop blk := m.blk (i); m.blk (i) := Shift_Right (blk, shift) + carry; carry := Shift_Left (blk, Block_type_bits - shift); end loop; end Unnormalization; begin -- Divide_absolute (multi u / multi v) if Debug then if v.zero then raise v_zero; end if; if v1 = 0 then raise v1_zero; end if; end if; -- Calculate shift needed to normalize u_work.last_used := u_work.n; u_work.zero := False; while v1 < 2**(Block_type_bits - 1) loop shift := shift + 1; v1 := v1 * 2; end loop; if shift = 0 then -- no shift needed u_work.blk (0 .. u.last_used) := u.blk (0 .. u.last_used); u_work.blk (u.last_used + 1 .. u_work.last_used) := (0, 0); -- Now, u is copied, so a Div_Rem(u, v, u, r) won't crash if v'Address = q'Address then declare v_work : Multi_int (v.last_used); begin -- 23-Feb-2002: also copy v, in case of a Div_Rem(u, v, v, r) v_work.blk (0 .. v.last_used) := v.blk (0 .. v.last_used); v_work.neg := v.neg; v_work.zero := v.zero; v_work.last_used := v.last_used; -- Now, u is copied, so a Div_Rem(u, v, v, r) won't crash -- Ada.Text_IO.Put_Line("* divisor with copy"); Divide_absolute_normalized (u_work, v_work, q); end; else -- Ada.Text_IO.Put_Line("* divisor without copy"); Divide_absolute_normalized (u_work, v, q); end if; else -- shift needed declare v_work : Multi_int (v.last_used); begin v_work.last_used := v_work.n; Normalization (u, u_work); Normalization (v, v_work); Reduce_last_nonzero (v_work); Divide_absolute_normalized (u_work, v_work, q); end; if div_rem_output /= div_only then Unnormalization (u_work); end if; end if; q.neg := False; -- check friendly if div_rem_output /= div_only then u_work.neg := False; -- check friendly Reduce_last_nonzero (u_work); Fill (r, u_work); end if; end Divide_absolute; l1 : constant Index_Int := i1.last_used; l2 : constant Index_Int := i2.last_used; rl : Long_Block_type; begin -- Div_Rem_internal if i2.zero then raise Division_by_zero; end if; if i1.zero then -- 15-Feb-2002: 0/i2 q.zero := True; r.zero := True; return; end if; if q.n < l1 - l2 then -- 17-Feb-2002 raise Quotient_undersized; end if; if div_rem_output /= div_only and then r.n < Max (l1, l2) then -- 17-Feb-2002 raise Remainder_undersized; end if; if l2 = 0 then if l1 = 0 then -- On a affaire a une ridicule division d'entiers q.blk (0) := i1.blk (0) / i2.blk (0); if div_rem_output /= div_only then r.blk (0) := Block_type ( abs ( Long_Block_type_signed (i1.blk (0)) - Long_Block_type_signed (i2.blk (0)) * Long_Block_type_signed (q.blk (0)) ) ); end if; q.zero := q.blk (0) = 0; q.last_used := 0; else -- multi / entier Divide_absolute_big_small (i1, Long_Block_type (i2.blk (0)), q, rl); if div_rem_output /= div_only then r.blk (0) := Block_type (rl); end if; end if; if div_rem_output /= div_only then r.zero := r.blk (0) = 0; r.last_used := 0; end if; else -- multi / multi case Compare_absolute (i2, i1) is when greater => q.zero := True; -- q:= 0; q.last_used := 0; q.neg := False; if div_rem_output /= div_only then Fill (r, i1); -- r:= i1, q:=0 car i1 = 0 * i2 (>i1 en v.abs) + r end if; return; when equal => Fill (q, one); -- Fill( q, Multi(1) ); r.zero := True; -- Fill( r, Multi(0) ); when smaller => -- cas <>: diviseur < dividende Divide_absolute (i1, i2, q, r); end case; end if; Solve_signs_for_Div_Rem (i1.neg, i2.neg, q.neg, r.neg); end Div_Rem_internal; procedure Div_Rem_internal_div_only is new Div_Rem_internal (div_rem_output => div_only); procedure Div_Rem_internal_both is new Div_Rem_internal (div_rem_output => both); procedure Div_Rem_internal_both_export (i1, i2 : in Multi_int; q, r : in out Multi_int) renames Div_Rem_internal_both; procedure Div_Rem (i1, i2 : in Multi_int; q, r : out Multi_int) is begin if Debug then declare m1 : constant Multi_int := i1; m2 : constant Multi_int := i2; begin Div_Rem_internal_both (m1, m2, q, r); end; else Div_Rem_internal_both (i1, i2, q, r); end if; end Div_Rem; procedure Divide (i1, i2 : in Multi_int; q : out Multi_int) is begin if Debug then declare m1 : constant Multi_int := i1; m2 : constant Multi_int := i2; r : Multi_int (Max (i1.last_used, i2.last_used) + 2); begin Div_Rem_internal_both (m1, m2, q, r); end; else declare r : Multi_int (0); -- Fake begin Div_Rem_internal_div_only (i1, i2, q, r); end; end if; end Divide; function "/" (i1, i2 : Multi_int) return Multi_int is q : Multi_int (Max (0, i1.last_used - i2.last_used + 1)); r : Multi_int (Max (i1.last_used, i2.last_used) + 2); begin Div_Rem (i1, i2, q, r); return q; end "/"; function "/" (i1 : Multi_int; i2 : Basic_Int) return Multi_int is q : Multi_int (i1.last_used + 1); r : Basic_Int; begin Div_Rem (i1, i2, q, r); return q; end "/"; function "rem" (i1, i2 : Multi_int) return Multi_int is q : Multi_int (Max (0, i1.last_used - i2.last_used + 1)); r : Multi_int (Max (i1.last_used, i2.last_used) + 2); begin Div_Rem (i1, i2, q, r); return r; end "rem"; function "rem" (i1 : Multi_int; i2 : Basic_Int) return Multi_int is begin return i1 rem Multi (i2); end "rem"; function "rem" (i1 : Multi_int; i2 : Basic_Int) return Basic_Int is q : Multi_int (i1.last_used + 1); r : Basic_Int; begin Div_Rem (i1, i2, q, r); return r; end "rem"; function "mod" (i1, i2 : Multi_int) return Multi_int is q : Multi_int (Max (0, i1.last_used - i2.last_used + 1)); r : Multi_int (Max (i1.last_used, i2.last_used) + 2); begin -- Ada RM, 4.5.5 Multiplying Operators -- (8) -- The signed integer modulus operator is defined such that -- the result of A mod B has the sign of B and an absolute value -- less than the absolute value of B; in addition, for some signed -- integer value N, this result satisfies the relation: -- (9) A = B*N + (A mod B) Div_Rem (i1, i2, q, r); if r.zero or else i2.neg = r.neg then -- (A rem B) est nul ou return r; -- a le meme signe que B, donc (A mod B) = (A rem B) else -- signe opposes return i2 + r; -- alors (B + (A rem B)) est le bon candidat end if; end "mod"; function "mod" (i1 : Multi_int; i2 : Basic_Int) return Multi_int is begin return i1 mod Multi (i2); end "mod"; function "mod" (i1 : Multi_int; i2 : Basic_Int) return Basic_Int is r : constant Basic_Int := i1 rem i2; begin if r = 0 or else (i2 < 0) = (r < 0) then -- (A rem B) est nul ou return r; -- a le meme signe que B, donc (A mod B) = (A rem B) else -- signe opposes return i2 + r; -- alors (B + (A rem B)) est le bon candidat end if; end "mod"; ----- End of DIVISION part ------ ----- Begin of POWER part ------- procedure Power (i : Multi_int; n : Natural; ipn : out Multi_int) is max_ipn_last : Index_Int; -- 17-Feb-2002 begin if i.zero then if n = 0 then raise Zero_power_zero; else -- The 0**n = 0 case (17-Feb-2002). ipn.zero := True; -- 4-Nov-2006, was: Fill( ipn, Multi(0) ); return; end if; end if; max_ipn_last := ((1 + i.last_used) * Index_Int (n) - 1) + 2; if ipn.n < max_ipn_last then raise Result_undersized; end if; case n is when 0 => Fill (ipn, one); -- the i**0 = 1 case when 1 => Fill (ipn, i); -- the i**1 = i case when others => declare nn : Natural := n - 1; i0, ii : Multi_int (max_ipn_last); begin Fill (i0, i); Fill (ii, i0); while nn > 0 loop if nn mod 2 = 0 then -- x^(2 c) = (x^2) ^c Mult (i0, i0, i0); nn := nn / 2; else Mult (i0, ii, ii); nn := nn - 1; end if; end loop; Fill (ipn, ii); end; end case; end Power; function "**" (i : Multi_int; n : Natural) return Multi_int is ipn : Multi_int ((1 + i.last_used) * Index_Int (n) + 2); begin Power (i, n, ipn); return ipn; end "**"; procedure Power (i : Multi_int; n : Multi_int; ipn : out Multi_int; modulo : Multi_int) is max_ipn_last : Index_Int; begin if i.zero then if n.zero then raise Zero_power_zero; else -- The 0**n = 0 case (17-Feb-2002). ipn.zero := True; -- 4-Nov-2006, was: Fill( ipn, Multi(0) ); return; end if; end if; if n.neg then raise Power_negative; end if; if modulo.zero or else (i.neg or modulo.neg) then raise Power_modulo_non_positive; end if; max_ipn_last := 2 * modulo.last_used + 2; if ipn.n < max_ipn_last then raise Result_undersized; end if; if n.zero then Fill (ipn, one); -- the i**0 = 1 case elsif Equal (n, one) then Fill (ipn, i); -- the i**1 = i case else declare nn : Multi_int (n.n) := n; i0, ii, dummy : Multi_int (max_ipn_last); dummy_b : Basic_Int; begin Subtract (nn, one, nn); -- nn:= nn - 1; Fill (i0, i); Fill (ii, i0); while nn > 0 loop if Even (nn) then -- x^(2 c) = (x^2) ^c Mult (i0, i0, i0); Div_Rem (nn, 2, nn, dummy_b); -- nn:= nn/2 Div_Rem (i0, modulo, dummy, i0); -- i0:= i0 mod modulo else Mult (i0, ii, ii); Subtract (nn, one, nn); -- nn:= nn - 1; Div_Rem (ii, modulo, dummy, ii); -- ii:= ii mod modulo end if; end loop; Fill (ipn, ii); end; end if; end Power; ----- End of POWER part --------- ----- Comparisons function Equal (i1, i2 : Multi_int) return Boolean is begin return (i1.zero and then i2.zero) or else (i1.zero = i2.zero and then i1.neg = i2.neg and then i1.last_used = i2.last_used and then i1.blk (0 .. i1.last_used) = i2.blk (0 .. i2.last_used)); end Equal; function Equal (i1 : Multi_int; i2 : Basic_Int) return Boolean is begin return Equal (i1, Multi (i2)); end Equal; function ">" (i1, i2 : Multi_int) return Boolean is begin -- (1) Cas \'evident o\`u: i1 <= i2 if (i1.zero or i1.neg) and then -- i1 <= 0 et (i2.zero or not i2.neg) -- i2 >= 0 then return False; end if; -- (2.1) Cas \'evident o\`u: i1 > i2 if ((not i1.zero) and not i1.neg) and then -- i1 > 0 et (i2.zero or i2.neg) -- i2 <= 0 then return True; end if; -- (2.2) Cas \'evident o\`u: i1 > i2 if (i1.zero or not i1.neg) and then -- i1 >= 0 et ((not i2.zero) and i2.neg) -- i2 < 0 then return True; end if; -- Cas faciles resolus: -- i1 > i2 - 0 + ------------------- -- - # F F -- 0 T F F -- + T T # -- On a les cas avec "#", o\`u i1 et i2 ont le meme signe if i1.neg then return not (Compare_absolute (i1, i2) = greater); else return (Compare_absolute (i1, i2) = greater); end if; end ">"; function ">" (i1 : Multi_int; i2 : Basic_Int) return Boolean is begin return i1 > Multi (i2); end ">"; function "<" (i1, i2 : Multi_int) return Boolean is begin return i2 > i1; end "<"; function "<" (i1 : Multi_int; i2 : Basic_Int) return Boolean is begin return i1 < Multi (i2); end "<"; function ">=" (i1, i2 : Multi_int) return Boolean is begin return not (i2 > i1); end ">="; function ">=" (i1 : Multi_int; i2 : Basic_Int) return Boolean is begin return i1 >= Multi (i2); end ">="; function "<=" (i1, i2 : Multi_int) return Boolean is begin return not (i1 > i2); end "<="; function "<=" (i1 : Multi_int; i2 : Basic_Int) return Boolean is begin return i1 <= Multi (i2); end "<="; end HAC_Sys.Multi_Precision_Integers; ================================================ FILE: src/compile/hac_sys-multi_precision_integers.ads ================================================ ------------------------------------------------------------------------------ -- File: hac_sys-multi_precision_integers.ads -- -- Description: Multiple precision integers package, copy -- for HAC internals. Stems from Mathpaqs project: -- http://mathpaqs.sf.net/ -- https://github.com/zertovitch/mathpaqs -- Alire ( https://alire.ada.dev/ ): alr get mathpaqs -- -- Date/version: Aug-2007: - No more generics (Long_Block_type, -- Block_type,... always the largest possible -- idea: J.C.) -- - Fixed Basic(...) (based on J.C.'s remarks) -- Nov-2006: - unsigned types for blocks -- - a block uses 2 bits more -- - Ada95+ only -- Mar-2002: Bugs fixed related to zero field, division -- Nov-1999: - procedures (no stack, less copies !) -- - new data structure -- Dec-1996: First version (operators only) -- -- Author: G. de Montmollin, Univ. Neuchatel -- -- Thanks to: Duncan Sands, Univ. Paris-Sud, CNRS -- Jeffrey R. Carter -- -- Tested on: Intel 586 (32 bit) - Windows 98, NT4+ - GNAT 3.13p+ -- Intel 586 (32 bit) - Windows 98, NT4+ - ObjectAda 7.2.1+ -- Alpha-AXP (64 bit) - OpenVMS 7.1 - Compaq Ada -- -- Division algorithm adaptated from BigInt 1.0 library, -- by Stephen Adams, that refers to -- D. E. Knuth, the Art of computer programming -- volume 2, "Seminumerical Algorithms" -- section 4.3.1, "Multiple-Precision Arithmetic" -- ------------------------------------------------------------------------------ with HAC_Sys.Defs; with System; package HAC_Sys.Multi_Precision_Integers is -- Integers for array indexing -- subtype Index_Int is Integer; -- THE multi-precision integer type -- type Multi_Int (n : Index_Int) is private; -- Integer type for small values -- subtype Basic_Int is Defs.HAC_Integer; -- the "normal" signed integer ---------------------------------------------------------------- -- Debug mode: checks results of arithmetic operations and -- -- Multi_int variables' integrity. -- -- CAUTION: Debug = True reduces monstruously the performance -- ---------------------------------------------------------------- Debug : constant Boolean := False; --------------------------------------------- ----- Informations, conversions, filling ---- --------------------------------------------- -- Convert Basic_int to Multi_int function Multi (small : Basic_Int) return Multi_Int; -- Convert Multi_int to Basic_int (when possible, else: Cannot_fit raised) function Basic (large : Multi_Int) return Basic_Int; -- Fill an Multi_int of greater array dimension with a smaller one procedure Fill (what : out Multi_Int; with_smaller : Multi_Int); procedure Fill (what : out Multi_Int; with_basic : Basic_Int); -- Comparisons function Equal (i1, i2 : Multi_Int) return Boolean; function Equal (i1 : Multi_Int; i2 : Basic_Int) return Boolean; function ">" (i1, i2 : Multi_Int) return Boolean; function ">" (i1 : Multi_Int; i2 : Basic_Int) return Boolean; function "<" (i1, i2 : Multi_Int) return Boolean; function "<" (i1 : Multi_Int; i2 : Basic_Int) return Boolean; function ">=" (i1, i2 : Multi_Int) return Boolean; function ">=" (i1 : Multi_Int; i2 : Basic_Int) return Boolean; function "<=" (i1, i2 : Multi_Int) return Boolean; function "<=" (i1 : Multi_Int; i2 : Basic_Int) return Boolean; -- Other informations function Bits_per_block return Positive; --------------------------------------------------------------------------- -------- Arithmetic operators. ---------- -------- For speed, the "procedure" variants should be preferred ---------- --------------------------------------------------------------------------- --------------------------- ----- Unary operators ----- --------------------------- procedure Opp (i : in out Multi_Int); function "+" (i : Multi_Int) return Multi_Int; function "-" (i : Multi_Int) return Multi_Int; procedure Abso (i : in out Multi_Int); function "ABS" (i : Multi_Int) return Multi_Int; function Sign (i : Multi_Int) return Basic_Int; function Even (i : Multi_Int) return Boolean; function Odd (i : Multi_Int) return Boolean; ---------------------------- ----- Binary operators ----- ---------------------------- --------------------------- -- Addition, subtraction -- --------------------------- procedure Add (i1, i2 : in Multi_Int; i3 : in out Multi_Int); function "+" (i1, i2 : Multi_Int) return Multi_Int; function "+" (i1 : Multi_Int; i2 : Basic_Int) return Multi_Int; function "+" (i1 : Basic_Int; i2 : Multi_Int) return Multi_Int; procedure Sub (i1, i2 : in Multi_Int; i3 : in out Multi_Int); procedure Subtract (i1, i2 : in Multi_Int; i3 : in out Multi_Int) renames Sub; function "-" (i1, i2 : Multi_Int) return Multi_Int; function "-" (i1 : Multi_Int; i2 : Basic_Int) return Multi_Int; function "-" (i1 : Basic_Int; i2 : Multi_Int) return Multi_Int; -------------------- -- Multiplication -- -------------------- procedure Multiply (i1, i2 : in Multi_Int; i3 : in out Multi_Int); procedure Mult (i1, i2 : in Multi_Int; i3 : in out Multi_Int) renames Multiply; procedure Multiply (i1 : in Multi_Int; i2 : Basic_Int; i3 : in out Multi_Int); procedure Mult (i1 : in Multi_Int; i2 : Basic_Int; i3 : in out Multi_Int) renames Multiply; function "*" (i1, i2 : Multi_Int) return Multi_Int; function "*" (i1 : Multi_Int; i2 : Basic_Int) return Multi_Int; function "*" (i1 : Basic_Int; i2 : Multi_Int) return Multi_Int; ------------------------- -- Division, Remainder -- ------------------------- procedure Div_Rem (i1 : in Multi_Int; i2 : in Basic_Int; q : out Multi_Int; r : out Basic_Int); procedure Div_Rem (i1, i2 : in Multi_Int; q, r : out Multi_Int); procedure Divide (i1, i2 : in Multi_Int; q : out Multi_Int); function "/" (i1, i2 : Multi_Int) return Multi_Int; function "/" (i1 : Multi_Int; i2 : Basic_Int) return Multi_Int; function "Rem" (i1, i2 : Multi_Int) return Multi_Int; function "Rem" (i1 : Multi_Int; i2 : Basic_Int) return Multi_Int; function "Rem" (i1 : Multi_Int; i2 : Basic_Int) return Basic_Int; function "Mod" (i1, i2 : Multi_Int) return Multi_Int; function "Mod" (i1 : Multi_Int; i2 : Basic_Int) return Multi_Int; function "Mod" (i1 : Multi_Int; i2 : Basic_Int) return Basic_Int; ----------- -- Power -- ----------- procedure Power (i : Multi_Int; n : Natural; ipn : out Multi_Int); function "**" (i : Multi_Int; n : Natural) return Multi_Int; -- + 26-Mar-2002 : procedure Power (i : Multi_Int; n : Multi_Int; ipn : out Multi_Int; modulo : Multi_Int); Cannot_fit, Empty_multi_int : exception; Array_too_small : exception; Result_undersized, Quotient_undersized, Remainder_undersized : exception; Division_by_zero : exception; Zero_power_zero, Power_negative : exception; Power_modulo_non_positive : exception; private --> Long_Block_type is used for + and * of blocks. -- It is by design -- a/ the largest possible modular integer, and -- b/ twice the size of Block_type defined below. -- With the double of bits (2n) one can store m**2 + 2m without overflow -- where m = 2**n - 1 is the largest value possible on n bits. type Long_Block_type is mod System.Max_Binary_Modulus; --> Same size as Long_Block_type, but signed: type Long_Block_type_signed is range -2**(Long_Block_type'Size - 1) .. 2**(Long_Block_type'Size - 1) - 1; --> Block_type: unsigned integer used to store a chunk of a Multi_int. type Block_type is mod 2 ** (Long_Block_type'Size / 2); Block_type_bits : constant := Block_type'Size; cardblock : constant := 2 ** Block_type_bits; -- Number of possible values maxblock : constant := Block_type'Last; -- NB: GNAT (2006) optimizes out correctly the Block_type(l and maxblock_long) -- to Block_type(l), the latter form being caught when range checks are on. type Block_array is array (Index_Int range <>) of Block_type; -- 2006: was "of Basic_int" for obscure reasons... type Multi_int (n : Index_Int) is record blk : Block_array (0 .. n); -- the n blocks with ABSOLUTE value neg : Boolean := False; -- negative flag zero : Boolean := True; -- zero flag (supercedes the other fields) last_used : Index_Int; -- the others blocks are supposed 0 end record; -- NB the `zero' field supercedes EVERY other information (last_used, neg) ---------------------------------------------------------------------------- -- Format of type Multi_int.blk: ( i_0, i_1, ..., i_k, *, ..., * ) -- -- i_0..i_k are >=0 ; others (*) are treated as 0 -- ---------------------------------------------------------------------------- -- Some internal procedures use by check: procedure Multiply_internal_copy_export (i1, i2 : in Multi_int; i3 : in out Multi_int); procedure Div_Rem_internal_both_export (i1, i2 : in Multi_int; q, r : in out Multi_int); end HAC_Sys.Multi_Precision_Integers; ================================================ FILE: src/compile/hac_sys-parser-attributes.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Ranges, HAC_Sys.PCode, HAC_Sys.Scanner, HAC_Sys.Errors; package body HAC_Sys.Parser.Attributes is type Attribute is (First, Image, Last, Length, Pos, Pred, Range_Attr, Succ, Val, Value); procedure Which_Attribute (CD : in out Co_Defs.Compiler_Data; attr : out Attribute) is use Co_Defs, Defs, Errors; attr_ID : constant String := A2S (CD.Id); begin attr := (if attr_ID = "RANGE" then Range_Attr else Attribute'Value (attr_ID)); Scanner.In_Symbol (CD); -- Consume the attribute name (First, Last, ...) exception when Constraint_Error => Error (CD, err_general_error, "unknown attribute: " & attr_ID, severity => major); end Which_Attribute; procedure Array_Subtype_Attribute (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys : in Defs.Symset; Array_Index : in Natural; attr : in Attribute; xSubtyp_of_Result : out Co_Defs.Exact_Subtyp) is use Co_Defs, Defs, Helpers, Errors; A : Array_Table_Entry := CD.Arrays_Table (Array_Index); Low, High : Index; N : Constant_Rec; use Compiler.PCode_Emit, Expressions, PCode, Scanner; use type HAC_Integer; begin N.I := 1; if CD.Sy = LParent then In_Symbol (CD); Static_Scalar_Expression (CD, Level, FSys + RParent, N); if N.TP.TYP /= Ints then Error (CD, err_parameter_must_be_Integer, severity => major); end if; Need (CD, RParent, err_closing_parenthesis_missing); end if; if N.I < 1 then Error (CD, err_invalid_dimension_number, "minimum is 1", severity => major); end if; -- Jump_to_next_Dimension : for Skip_Dim in 2 .. N.I loop if A.Element_xTyp.TYP = Arrays then A := CD.Arrays_Table (A.Element_xTyp.Ref); else Error (CD, err_invalid_dimension_number, "maximum is" & HAC_Integer'Image (Skip_Dim - 1), severity => major); end if; end loop Jump_to_next_Dimension; -- Low := Index (A.Index_xTyp.Discrete_First); High := Index (A.Index_xTyp.Discrete_Last); case attr is when First => -- RM 3.6.2 (3, 4) Emit_1 (CD, k_Push_Discrete_Literal, Operand_2_Type (Low)); xSubtyp_of_Result := A.Index_xTyp; when Last => -- RM 3.6.2 (5, 6) Emit_1 (CD, k_Push_Discrete_Literal, Operand_2_Type (High)); xSubtyp_of_Result := A.Index_xTyp; when Range_Attr => -- RM 3.6.2 (7, 8) Emit_1 (CD, k_Push_Discrete_Literal, Operand_2_Type (Low)); Emit_1 (CD, k_Push_Discrete_Literal, Operand_2_Type (High)); xSubtyp_of_Result := A.Index_xTyp; xSubtyp_of_Result.Is_Range := True; when Length => -- RM 3.6.2 (9, 10) Emit_1 (CD, k_Push_Discrete_Literal, Operand_2_Type (High - Low + 1)); Construct_Root (xSubtyp_of_Result, Ints); when others => Error (CD, err_general_error, "attribute not defined for this type", severity => major); end case; end Array_Subtype_Attribute; procedure Image_Attribute -- S'Image (...) or X'Image (CD : in out Co_Defs.Compiler_Data; S : in Co_Defs.Exact_Subtyp; xSubtyp_of_Result : out Co_Defs.Exact_Subtyp) is use Co_Defs, Compiler.PCode_Emit, Defs, Errors, PCode; begin -- The value to get an image from is assumed to be on top -- of the stack. The appropriate built-in function will replace -- it by its image as a string (internal type: Strings_as_VStrings). case S.TYP is when NOTYP => null; -- Already in error when Ints => Emit_Std_Funct (CD, SF_Image_Attribute_Ints); when Floats => Emit_Std_Funct (CD, SF_Image_Attribute_Floats); when Bools => Emit_Std_Funct (CD, SF_Image_Attribute_Bools); when Chars => Emit_Std_Funct (CD, SF_Image_Attribute_Chars); when Durations => Emit_Std_Funct (CD, SF_Image_Attribute_Durs); when Enums => -- The enumeration items' declarations follow the type name -- For example: `type Enum is (a, b, c)`, we send the index -- of the first item, `a`, in the identifier table. Emit_Std_Funct (CD, SF_Image_Attribute_Enums, Operand_1_Type (S.Ref + 1)); when others => Error (CD, err_attribute_prefix_invalid, "Image", severity => major); end case; -- The result subtype is a VString disguised as a String. Construct_Root (xSubtyp_of_Result, Strings_as_VStrings); end Image_Attribute; procedure Object_Attribute ( CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys : in Defs.Symset; Object_xSubtyp : in Co_Defs.Exact_Subtyp; LC_before_Object : in Integer; xSubtyp_of_Result : out Co_Defs.Exact_Subtyp ) is use Defs, Helpers, Errors; attr : Attribute; begin Which_Attribute (CD, attr); case attr is when Image => -- X'Image (Ada 2022) Image_Attribute (CD, Object_xSubtyp, xSubtyp_of_Result); when others => if Arrays_Set (Object_xSubtyp.TYP) then -- Forget all the code emitted for selecting the array variable. -- It can be a complex thing like `a (i * 2).loc_x (3)` ! CD.LC := LC_before_Object; Array_Subtype_Attribute (CD, Level, FSys + RParent, Object_xSubtyp.Ref, attr, xSubtyp_of_Result); else Error (CD, err_general_error, "attribute not defined for this object", severity => major); end if; end case; end Object_Attribute; procedure Subtype_Attribute (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Typ_ID_Index : in Natural; xSubtyp_of_Result : out Co_Defs.Exact_Subtyp) is use Co_Defs, Defs, Helpers, Errors; Typ_ID : Identifier_Table_Entry renames CD.id_table (Typ_ID_Index); S : Exact_Subtyp renames Typ_ID.xtyp; attr_ID : constant String := A2S (CD.Id); attr : Attribute; -- procedure Scalar_Subtype_Attribute is use Compiler.PCode_Emit, PCode; -- procedure First_Last is -- S'First, S'Last: RM 3.5 (12, 13) begin case S.TYP is when NOTYP => null; -- Already in error when Floats => -- !! To do: floating point strict subtypes if attr = First then Emit (CD, k_Push_Float_First); else Emit (CD, k_Push_Float_Last); end if; when others => if Discrete_Typ (S.TYP) then Emit_1 (CD, k_Push_Discrete_Literal, (if attr = First then S.Discrete_First else S.Discrete_Last) ); else Error (CD, err_attribute_prefix_invalid, attr_ID, severity => major); end if; end case; xSubtyp_of_Result := S; if Discrete_Typ (S.TYP) then Ranges.Set_Singleton_Range (xSubtyp_of_Result, (if attr = First then S.Discrete_First else S.Discrete_Last)); end if; end First_Last; -- procedure Range_Attribute is -- S'Range: RM 3.5 (14) begin case S.TYP is when NOTYP => null; -- Already in error when Floats => -- !! To do: floating point strict subtypes Emit_Push_Float_Literal (CD, HAC_Float'First); Emit_Push_Float_Literal (CD, HAC_Float'Last); when others => if Discrete_Typ (S.TYP) then Emit_1 (CD, k_Push_Discrete_Literal, S.Discrete_First); Emit_1 (CD, k_Push_Discrete_Literal, S.Discrete_Last); else Error (CD, err_attribute_prefix_invalid, attr_ID, severity => major); end if; end case; xSubtyp_of_Result := S; xSubtyp_of_Result.Is_Range := True; end Range_Attribute; -- procedure Pred_Succ_Discrete is use type HAC_Integer; begin Emit_1 (CD, k_Push_Discrete_Literal, 1); if attr = Pred then -- !! overflow check here if arg = hac_integer'first. Emit (CD, k_SUBTRACT_Integer); Emit_Lower_Bound_Check (CD, S); else -- !! overflow check here if arg = hac_integer'first. Emit (CD, k_ADD_Integer); Emit_Upper_Bound_Check (CD, S); end if; end Pred_Succ_Discrete; -- procedure Pred_Succ is -- S'Pred (...), S'Succ (...): RM 3.5 (22, 25) s_base : Exact_Typ; type_of_argument : Exact_Subtyp; begin Need (CD, LParent, err_missing_an_opening_parenthesis); Expressions.Expression (CD, context, FSys + RParent, type_of_argument); -- Argument is of the base type (S'Base). s_base := Exact_Typ (S); if s_base = Exact_Typ (type_of_argument) then case S.TYP is when NOTYP => null; -- Already in error when Floats => -- !! To do Error (CD, err_not_yet_implemented, "attribute " & attr_ID & " for this subtype", severity => major); when others => if Discrete_Typ (S.TYP) then Pred_Succ_Discrete; else Error (CD, err_attribute_prefix_invalid, attr_ID, severity => major); end if; end case; else Type_Mismatch (CD, err_parameter_types_do_not_match, type_of_argument, s_base); end if; Need (CD, RParent, err_closing_parenthesis_missing); xSubtyp_of_Result := S; end Pred_Succ; -- procedure Pos is -- S'Pos (...): RM 3.5.5 (2) s_base : Exact_Typ; type_of_argument : Exact_Subtyp; begin if Discrete_Typ (S.TYP) then Need (CD, LParent, err_missing_an_opening_parenthesis); Expressions.Expression (CD, context, FSys + RParent, type_of_argument); -- Argument is of the base type (S'Base). s_base := Exact_Typ (S); if s_base = Exact_Typ (type_of_argument) then -- Just set the desired type, and that's it - no VM instruction! xSubtyp_of_Result := Standard_Integer; else Type_Mismatch (CD, err_parameter_types_do_not_match, type_of_argument, s_base); end if; Need (CD, RParent, err_closing_parenthesis_missing); else Error (CD, err_attribute_prefix_must_be_discrete_type, attr_ID, severity => major); end if; end Pos; -- procedure Val is -- S'Val (...): RM 3.5.5 (5) type_of_argument : Exact_Subtyp; begin if Discrete_Typ (S.TYP) then Helpers.Need (CD, LParent, err_missing_an_opening_parenthesis); Expressions.Expression (CD, context, FSys + RParent, type_of_argument); if type_of_argument.TYP = Ints then -- Just set the desired subtype, and that's it - no VM instruction for -- the conversion itself! xSubtyp_of_Result := S; -- ...but we need to add a range check. Emit_Lower_Bound_Check (CD, S); Emit_Upper_Bound_Check (CD, S); else Helpers.Type_Mismatch (CD, err_parameter_types_do_not_match, type_of_argument, Helpers.Standard_Integer); end if; Helpers.Need (CD, RParent, err_closing_parenthesis_missing); else Error (CD, err_attribute_prefix_must_be_discrete_type, attr_ID, severity => major); end if; end Val; -- procedure Image is -- S'Image (...) type_of_argument : Exact_Subtyp; -- Argument of the function is of the base type, that is: S'Base. -- Translation: we forget the subtype constraints here. s_base : constant Exact_Typ := Exact_Typ (S); begin Need (CD, LParent, err_missing_an_opening_parenthesis); Expressions.Expression (CD, context, FSys + RParent, type_of_argument); if s_base = Exact_Typ (type_of_argument) then Image_Attribute (CD, S, xSubtyp_of_Result); else Type_Mismatch (CD, err_parameter_types_do_not_match, type_of_argument, s_base); end if; Need (CD, RParent, err_closing_parenthesis_missing); end Image; -- procedure Value is type_of_argument : Exact_Subtyp; begin Need (CD, LParent, err_missing_an_opening_parenthesis); Expressions.Expression (CD, context, FSys + RParent, type_of_argument); -- Argument is of the base type (S'Base). if type_of_argument.TYP = String_Literals then Emit_Std_Funct (CD, SF_String_Literal_to_VString); elsif type_of_argument.TYP = Strings_as_VStrings then null; elsif Is_Char_Array (CD, type_of_argument) then Emit_Std_Funct (CD, SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (type_of_argument.Ref).Array_Size) ); else Type_Mismatch (CD, err_parameter_types_do_not_match, Found => type_of_argument, Expected => Str_Lit_Set or Str_as_VStr_Set or Arrays_Set); end if; case S.TYP is when NOTYP => null; -- Already in error when Ints => Emit_Std_Funct (CD, SF_Value_Attribute_Ints); Construct_Root (xSubtyp_of_Result, Ints); when Floats => Emit_Std_Funct (CD, SF_Value_Attribute_Floats); Construct_Root (xSubtyp_of_Result, Floats); when Bools => Emit_Std_Funct (CD, SF_Value_Attribute_Bools); Construct_Root (xSubtyp_of_Result, Bools); when Chars => Emit_Std_Funct (CD, SF_Value_Attribute_Chars); Construct_Root (xSubtyp_of_Result, Chars); when Durations => Emit_Std_Funct (CD, SF_Value_Attribute_Durs); Construct_Root (xSubtyp_of_Result, Durations); when Enums => Emit_Std_Funct (CD, SF_Value_Attribute_Enums, Operand_1_Type (S.Ref)); xSubtyp_of_Result := S; when others => Error (CD, err_attribute_prefix_invalid, attr_ID, severity => major); end case; Need (CD, RParent, err_closing_parenthesis_missing); end Value; -- begin case attr is when First | Last => First_Last; -- RM 3.5 (12, 13) when Range_Attr => Range_Attribute; -- RM 3.5 (14) when Pred | Succ => Pred_Succ; when Pos => Pos; when Val => Val; when Image => Image; when Value => Value; when others => Error (CD, err_general_error, "attribute not defined for this type", severity => major); end case; end Scalar_Subtype_Attribute; -- begin pragma Assert (Typ_ID.entity = type_mark); -- Which_Attribute (CD, attr); if Scalar_Set (S.TYP) then Scalar_Subtype_Attribute; elsif Arrays_Set (S.TYP) then Array_Subtype_Attribute (CD, context.level, FSys + RParent, S.Ref, attr, xSubtyp_of_Result); else Error (CD, err_general_error, "no attribute defined for this type: " & A2S (Typ_ID.name_with_case), severity => major); end if; end Subtype_Attribute; end HAC_Sys.Parser.Attributes; ================================================ FILE: src/compile/hac_sys-parser-attributes.ads ================================================ private package HAC_Sys.Parser.Attributes is procedure Object_Attribute ( CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys : in Defs.Symset; Object_xSubtyp : in Co_Defs.Exact_Subtyp; LC_before_Object : in Integer; xSubtyp_of_Result : out Co_Defs.Exact_Subtyp ); -- Subtype attributes. Ada RM ref: scalar 3.5 (10), arrays 3.6 (2) -- -- The subtype name has just been parsed and determined to -- be corresponding to subtype S. The symbol "'" has been parsed too. -- In output, the type of the returned value is set in X. -- Example: -- S is Boolean, we have the expression ` Boolean'Image (Flag) ` -- From here we parse the attribute (` Image `), then, its -- parameter ` (Flag) `, if any. -- The return type is X = (Strings_as_VStrings, 0), an internal type in this case. procedure Subtype_Attribute (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Typ_ID_Index : in Natural; xSubtyp_of_Result : out Co_Defs.Exact_Subtyp); end HAC_Sys.Parser.Attributes; ================================================ FILE: src/compile/hac_sys-parser-calls.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.Scanner, HAC_Sys.Errors; package body HAC_Sys.Parser.Calls is use Compiler.PCode_Emit, Co_Defs, Defs, Expressions, Helpers, PCode, Scanner, Errors; use type HAC_Integer; procedure Push_Parameter_by_Value (CD : in out Co_Defs.Compiler_Data; context : Defs.Flow_Context; fsys : Defs.Symset; expected : Co_Defs.Exact_Subtyp) is X : Exact_Subtyp; expected_array_len : Natural; begin -- Expression does all the job of parsing and, for -- atomic types, emitting the correct "push" instructions. Expression (CD, context, fsys + Colon_Comma_RParent, X); -- What is remaining is: -- - checking types -- - for composite types, emit an instruction for pushing -- the contents on the stack. if X.TYP = expected.TYP then if X.Ref /= expected.Ref then Type_Mismatch (CD, err_parameter_types_do_not_match, X, expected); elsif X.TYP = Arrays then Emit_1 (CD, k_Load_Block, Operand_2_Type (CD.Arrays_Table (X.Ref).Array_Size)); elsif X.TYP = Records then Emit_1 (CD, k_Load_Block, Operand_2_Type (CD.Blocks_Table (X.Ref).VSize)); end if; elsif X.TYP = Ints and expected.TYP = Floats then Forbid_Type_Coercion (CD, X, expected); Emit_1 (CD, k_Integer_to_Float, 0); -- Left as a "souvenir" of SmallAda... elsif X.TYP = String_Literals and then Is_Char_Array (CD, expected) then expected_array_len := CD.Arrays_Table (expected.Ref).Array_Size; if expected_array_len = CD.SLeng then Emit_1 (CD, k_Load_String_Literal, Operand_2_Type (expected_array_len)); else Error (CD, err_string_lengths_do_not_match, "subprogram parameter has length" & expected_array_len'Image & ", literal has length" & CD.SLeng'Image, severity => minor); end if; elsif X.TYP /= NOTYP then Type_Mismatch (CD, err_parameter_types_do_not_match, X, expected); end if; end Push_Parameter_by_Value; procedure Push_Parameter_by_Reference (CD : in out Co_Defs.Compiler_Data; context : Defs.Flow_Context; fsys : Defs.Symset; name : String; mode : Co_Defs.Parameter_Kind; found : out Co_Defs.Exact_Subtyp) is K : Integer; begin found := undefined_subtyp; if CD.Sy = IDent then K := Locate_CD_Id (CD, context.level); In_Symbol (CD); if K = No_Id then null; -- Error already issued due to undefined identifier elsif CD.id_table (K).entity not in Object_Kind then Error (CD, err_variable_missing, name, severity => major); elsif CD.id_table (K).entity = constant_object then Error (CD, err_cannot_modify_constant_or_in_parameter, ": passed to OUT or IN OUT parameter"); else found := CD.id_table (K).xtyp; -- Update the reference analysis for the variable. -- The concerned flags (.is_read, .is_written) are -- raised from `no` to `maybe`. -- The usage of the subprogram's parameters is -- checked at the end of the subprogram's compilation -- (see Formal_Parameter_List for startup values). -- case mode is when param_in => Elevate_to_Maybe (CD.id_table (K).is_read); when param_in_out => Elevate_to_Maybe (CD.id_table (K).is_read); Elevate_to_Maybe (CD.id_table (K).is_written_after_init); when param_out => Elevate_to_Maybe (CD.id_table (K).is_written_after_init); end case; Emit_2 (CD, (if CD.id_table (K).normal then k_Push_Address -- Push "v'Access". else k_Push_Discrete_Value), -- Push "(a.all)'Access", that is, a (a is an access type). Operand_1_Type (CD.id_table (K).lev), Operand_2_Type (CD.id_table (K).adr_or_sz)); if Selector_Symbol_Loose (CD.Sy) then -- '.' or '(' or (wrongly) '[' Selector (CD, context, fsys + Colon_Comma_RParent, found); end if; end if; else Error (CD, err_variable_missing, name, severity => major); end if; end Push_Parameter_by_Reference; ------------------------------------------------------------------ -----------------------------------------Subprogram_or_Entry_Call- procedure Subprogram_or_Entry_Call (CD : in out Co_Defs.Compiler_Data; context : Defs.Flow_Context; fsys : Defs.Symset; ident_index : Integer; call_type : PCode.Operand_1_Type) is --**************************************************************** -- Generate ObjCode for subprogram or Task Entry Call -- CallType specifies type of Call -- = 0 then standard subprogram Call, CallSTDP -- = 1 then standard Task Entry Call, CallSTDE -- = 2 then timed Task Entry Call, CallTMDE -- = 3 then conditional Task Entry Call, CallCNDE --**************************************************************** last_param, current_param : Index; found, expected : Exact_Subtyp; block_idx : Index; begin Emit_1 (CD, k_Mark_Stack, Operand_2_Type (ident_index)); block_idx := CD.id_table (ident_index).block_or_pkg_ref; current_param := CD.Blocks_Table (block_idx).First_Param_Id_Idx - 1; last_param := CD.Blocks_Table (block_idx).Last_Param_Id_Idx; if CD.Sy = LParent then -- Actual parameter list loop In_Symbol (CD); if current_param >= last_param then Error (CD, err_number_of_parameters_do_not_match, ": too many actual parameters", severity => major); else current_param := current_param + 1; expected := CD.id_table (current_param).xtyp; if CD.id_table (current_param).normal then ------------------------------------------------------ -- Value parameter -- -- Only IN mode; value is passed by value (copy). -- ------------------------------------------------------ Push_Parameter_by_Value (CD, context, fsys, expected); else ------------------------------------ -- Variable (Name) parameter -- -- This is passed by reference. -- ------------------------------------ Push_Parameter_by_Reference (CD, context, fsys, A2S (CD.id_table (current_param).name_with_case), CD.id_table (current_param).decl_kind, found); if Exact_Typ (found) /= Exact_Typ (expected) then Type_Mismatch (CD, err_parameter_types_do_not_match, found, expected); end if; end if; if CD.Sy = Finger then Error (CD, err_not_yet_implemented, "positional association", severity => major); end if; end if; Test (CD, Comma_RParent, fsys, err_incorrectly_used_symbol); exit when CD.Sy /= Comma; end loop; Need (CD, RParent, err_closing_parenthesis_missing); end if; if current_param < last_param then Error (CD, err_number_of_parameters_do_not_match, ": too few actual parameters", severity => major); end if; -- Emit_2 (CD, k_Call, call_type, Operand_2_Type (CD.Blocks_Table (CD.id_table (ident_index).block_or_pkg_ref).PSize - 1)); if call_type /= Normal_Procedure_Call then -- Some for of entry call Emit_1 (CD, k_Return_Call, Operand_2_Type (call_type)); -- Return from Entry Call end if; -- if CD.id_table (ident_index).lev < context.level then Emit_2 (CD, k_Update_Display_Vector, Operand_1_Type (CD.id_table (ident_index).lev), Operand_2_Type (context.level)); end if; end Subprogram_or_Entry_Call; ------------------------------------------------------------------ -------------------------------------------------------Entry_Call- procedure Entry_Call (CD : in out Co_Defs.Compiler_Data; context : Defs.Flow_Context; fsys : Defs.Symset; i : Integer; call_type : PCode.Operand_1_Type) is -- Hathorn Addr, J : Integer; use type Alfa; begin if CD.Sy = Period then In_Symbol (CD); -- Task Entry Selector if CD.Sy = IDent then J := CD.Blocks_Table (CD.id_table (i).block_or_pkg_ref).Last_Id_Idx; CD.id_table (0).name := CD.Id; while CD.id_table (J).name /= CD.Id loop J := CD.id_table (J).link; end loop; -- if J = 0 then Error (CD, err_undefined_identifier, A2S (CD.Id_with_case)); end if; -- Addr := J; In_Symbol (CD); Subprogram_or_Entry_Call (CD, context, fsys, Addr, call_type); else Error_then_Skip (CD, Semicolon, err_identifier_missing); end if; else Error_then_Skip (CD, Semicolon, err_incorrectly_used_symbol); end if; end Entry_Call; end HAC_Sys.Parser.Calls; ================================================ FILE: src/compile/hac_sys-parser-calls.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.PCode; private package HAC_Sys.Parser.Calls is procedure Push_Parameter_by_Value (CD : in out Co_Defs.Compiler_Data; context : Defs.Flow_Context; fsys : Defs.Symset; expected : Co_Defs.Exact_Subtyp); procedure Push_Parameter_by_Reference (CD : in out Co_Defs.Compiler_Data; context : Defs.Flow_Context; fsys : Defs.Symset; name : String; mode : Co_Defs.Parameter_Kind; found : out Co_Defs.Exact_Subtyp); procedure Entry_Call (CD : in out Co_Defs.Compiler_Data; context : Defs.Flow_Context; fsys : Defs.Symset; i : Integer; call_type : PCode.Operand_1_Type); procedure Subprogram_or_Entry_Call (CD : in out Co_Defs.Compiler_Data; context : Defs.Flow_Context; fsys : Defs.Symset; ident_index : Integer; call_type : PCode.Operand_1_Type); end HAC_Sys.Parser.Calls; ================================================ FILE: src/compile/hac_sys-parser-const_var.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Co_Defs, HAC_Sys.Defs, HAC_Sys.Parser.Enter_Def, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Statements, HAC_Sys.Parser.Type_Def, HAC_Sys.PCode, HAC_Sys.Scanner, HAC_Sys.Errors; package body HAC_Sys.Parser.Const_Var is procedure Var_Declaration (CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; Block_Data : in out Block_Data_Type) is use Compiler.PCode_Emit, Co_Defs, Defs, Enter_Def, Helpers, PCode, Errors; procedure In_Symbol is begin Scanner.In_Symbol (CD); end In_Symbol; -- This procedure processes both Variable and Constant declarations. procedure Possibly_Initialized_Constant_or_Variable (explicity : Boolean; id_first, id_last : Integer; var_typ : Exact_Subtyp) is LC0 : Integer := CD.LC; LC1 : Integer; begin -- Create constant or variable initialization ObjCode -- The new variables Id's are in the range id_first .. id_last. if explicity then -- We do an assignment to the last one. -- Example: -- for: "a, b, c : Real := F (x);" -- we do first: "c := F (x)". Statements.Assignment (CD, FSys, Block_Data.context, id_last, check_is_variable => False); CD.id_table (id_last).is_initialized := explicit; -- Id_Last has been assigned. -- Now, we emit the code for copying the value -- of id_last to id_first .. id_last - 1. -- In the above example: "a := c" and "b := c". for var of CD.id_table (id_first .. id_last - 1) loop -- Push destination address: Emit_2 (CD, k_Push_Address, var.lev, Operand_2_Type (var.adr_or_sz)); if var_typ.TYP in Composite_Typ then -- Push source address: Emit_2 (CD, k_Push_Address, CD.id_table (id_last).lev, Operand_2_Type (CD.id_table (id_last).adr_or_sz) ); case Composite_Typ (var_typ.TYP) is when Arrays => Emit_1 (CD, k_Copy_Block, Operand_2_Type (CD.Arrays_Table (var_typ.Ref).Array_Size) ); when Records => Emit_1 (CD, k_Copy_Block, Operand_2_Type (CD.Blocks_Table (var_typ.Ref).VSize) ); end case; else -- Non-composite type. We copy the value. Emit_2 (CD, k_Push_Value, CD.id_table (id_last).lev, Operand_2_Type (CD.id_table (id_last).adr_or_sz) ); Emit_1 (CD, k_Store, Typen'Pos (var_typ.TYP)); end if; var.is_initialized := explicit; end loop; else -- Implicit initialization (for instance, VString's and File_Type's). for var of CD.id_table (id_first .. id_last) loop if Auto_Init_Typ (var.xtyp.TYP) then Emit_2 (CD, k_Push_Address, var.lev, Operand_2_Type (var.adr_or_sz)); Emit_1 (CD, k_Variable_Initialization, Typen'Pos (var.xtyp.TYP)); var.is_initialized := implicit; end if; -- !! TBD: Must handle composite types (arrays or records) containing -- initialized types, too... Bug #2 end loop; end if; -- LC1 := CD.LC; -- Reset ObjCode pointer as if ObjCode had not been generated CD.LC := LC0; -- Copy ObjCode to end of ObjCode table in reverse order. -- -- This buffering is needed for having the initialization code placed -- right after the "BEGIN" of current block (see Statements_Part_Setup). -- Nested subprograms have their own code and their possible own -- initialization code coming before in the object code table. Block_Data.initialization_object_code_size := Block_Data.initialization_object_code_size + (LC1 - LC0); -- Size of initialization ObjCode if LC0 + Block_Data.initialization_object_code_size >= CD.CMax - Block_Data.initialization_object_code_size then Fatal (Object_Code); -- Collision during the copy (loop below). Garbage guaranteed. end if; while LC0 < LC1 loop CD.ObjCode (CD.CMax) := CD.ObjCode (LC0); CD.CMax := CD.CMax - 1; LC0 := LC0 + 1; end loop; end Possibly_Initialized_Constant_or_Variable; -- procedure Single_Var_Declaration is T0, T1, Sz, T0i : Integer; xTyp : Exact_Subtyp; is_constant, is_typed, is_untyped_constant : Boolean; C : Constant_Rec; Dummy_First, Dummy_Last : HAC_Integer; begin C.TP.TYP := NOTYP; T0 := CD.Id_Count; Enter_Variables (CD, Block_Data.context.level, True); if CD.Sy = Becomes then Error (CD, err_assignment_not_allowed_declarative, severity => major); else Need (CD, Colon, err_colon_missing); -- ':' in "x, y : Integer;" end if; T1 := CD.Id_Count; -- Test (CD, Type_Begin_Symbol + Subtype_Begin_Symbol + CONSTANT_Symbol, Semicolon_Set, err_incorrectly_used_symbol); -- is_constant := False; if CD.Sy = CONSTANT_Symbol then -- Consume "constant" in "x : constant ...;" is_constant := True; In_Symbol; end if; -- is_typed := False; if Type_Begin_Symbol (CD.Sy) or CD.Sy = IDent then -- Here, a type name or an anonymous type definition (array or access) -- See Object Declaration. is_typed := True; case CD.Sy is when IDent => Type_Def.Subtype_Indication (CD, Block_Data.context.level, Becomes_Comma_IDent_Semicolon + FSys, xTyp, Sz); when ARRAY_Symbol => -- Anonymous array type in "v : array (1 .. 5) of Integer;" Type_Def.Type_Definition (CD, Block_Data.context.level, Becomes_Comma_IDent_Semicolon + FSys, xTyp, Sz); when ACCESS_Symbol => Error (CD, err_not_yet_implemented, "access types", severity => major); when others => Error (CD, err_general_error, "this kind of anonymous type definition is not allowed here"); -- Recovery: Type_Def.Type_Definition (CD, Block_Data.context.level, Becomes_Comma_IDent_Semicolon + FSys, xTyp, Sz); end case; end if; Test (CD, Becomes_EQL_Semicolon, empty_symset, err_incorrectly_used_symbol); -- if CD.Sy = EQL then -- Common mistake by BASIC or C programmers. Error (CD, err_EQUALS_instead_of_BECOMES); CD.Sy := Becomes; end if; -- is_untyped_constant := is_constant and not is_typed; -- if is_untyped_constant then -- Numeric constant: we parse the number here ("k : constant := 123.0"). if CD.Sy = Becomes then In_Symbol; Expressions.Static_Scalar_Expression (CD, Block_Data.context.level, Comma_IDent_Semicolon + FSys, C); else Error (CD, err_BECOMES_missing); end if; end if; -- T0i := T0; if is_constant or is_typed then -- This path covers all correct cases, since untyped -- variable errors ("a : := 5;", "a : ;", "a;") were -- caught earlier. -- -- Update identifier table for all entered names: while T0 < T1 loop T0 := T0 + 1; declare r : Identifier_Table_Entry renames CD.id_table (T0); begin r.entity := (if is_constant then constant_object else variable_object); r.is_referenced := False; r.is_read := no; r.is_written_after_init := no; r.is_initialized := (if is_untyped_constant then explicit else none); -- ^ This value may be changed below. if is_untyped_constant then r.entity := declared_number_or_enum_item; -- r was initially a Variable. r.xtyp := C.TP; case C.TP.TYP is when Floats => Enter_or_find_Float (CD, C.R, Integer (r.adr_or_sz)); when Ints => r.adr_or_sz := C.I; when others => Error (CD, err_numeric_constant_expected); -- "boo : constant := True;" or "x: constant := 'a';" are wrong in Ada. r.adr_or_sz := C.I; end case; else -- A variable or a typed constant r.xtyp := xTyp; r.adr_or_sz := HAC_Integer (Block_Data.data_allocation_index); Block_Data.data_allocation_index := Block_Data.data_allocation_index + Sz; end if; end; end loop; -- While T0 < T1 end if; -- if CD.Sy = EQL and not is_untyped_constant then Error (CD, err_EQUALS_instead_of_BECOMES); CD.Sy := Becomes; end if; if is_constant and is_typed then -- For typed constants, the ":=" is required and consumed with the Assignment below. Test (CD, Becomes_Set, empty_symset, err_BECOMES_missing); end if; -- if not is_untyped_constant then Possibly_Initialized_Constant_or_Variable (explicity => CD.Sy = Becomes, id_first => T0i + 1, id_last => T1, var_typ => xTyp); end if; Need_Semicolon_after_Declaration (CD, FSys); end Single_Var_Declaration; begin while CD.Sy = IDent loop Single_Var_Declaration; end loop; end Var_Declaration; end HAC_Sys.Parser.Const_Var; ================================================ FILE: src/compile/hac_sys-parser-const_var.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- Package around constants and variables declarations. private package HAC_Sys.Parser.Const_Var is procedure Var_Declaration (CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; Block_Data : in out Block_Data_Type); end HAC_Sys.Parser.Const_Var; ================================================ FILE: src/compile/hac_sys-parser-enter_def.adb ================================================ with HAC_Sys.Scanner, HAC_Sys.Errors; with HAT; package body HAC_Sys.Parser.Enter_Def is use Co_Defs, Defs, Errors; use type HAC_Integer; ------------------------------------------------------------------ ------------------------------------------------------Enter_Block- procedure Enter_Block (CD : in out Co_Defs.Compiler_Data; Tptr : Integer) is begin if CD.Blocks_Count = BMax then Fatal (PROCEDURES); -- Exception is raised there. end if; CD.Blocks_Count := CD.Blocks_Count + 1; declare New_B : Block_Table_Entry renames CD.Blocks_Table (CD.Blocks_Count); begin New_B.Id := CD.id_table (Tptr).name; New_B.Last_Id_Idx := 0; New_B.First_Param_Id_Idx := 0; New_B.Last_Param_Id_Idx := 0; New_B.SrcFrom := CD.CUD.location.line; end; end Enter_Block; ------------------------------------------------------------------ ------------------------------------------------------------Enter- procedure Enter_Simple (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; Id, Id_with_case : Defs.Alfa; K : Co_Defs.Entity_Kind; Forward_Decl_Id : out Natural) is last_id : constant Index := CD.Blocks_Table (CD.Display (Level)).Last_Id_Idx; J : Integer := last_id; use HAT; begin Forward_Decl_Id := No_Id; if CD.Id_Count = Id_Table_Max then Fatal (IDENTIFIERS); -- Exception is raised there. end if; CD.id_table (No_Id).name := Id; -- Sentinel -- Follow the chain of identifiers for current Level: while CD.id_table (J).name /= Id loop J := CD.id_table (J).link; end loop; if J = No_Id then -- All good: the identifier is new at this nesting level, -- and we don't care about lower levels: name hiding is allowed. null; elsif ((K = prozedure or K = funktion) and then K = CD.id_table (J).entity and then CD.id_table (J).decl_kind = spec_unresolved) or else (K = paquetage_body and then CD.id_table (J).entity = paquetage) then -- No duplicate name in those cases: J is a specification, -- new declaration is the corresponding body. Forward_Decl_Id := J; else Error (CD, err_duplicate_identifier, A2S (Id) -- & ", previous is a " & CD.IdTab (J).entity'Image , severity => major); end if; -- Enter identifier in table IdTab CD.Id_Count := CD.Id_Count + 1; CD.id_table (CD.Id_Count) := (name => Id, name_with_case => Id_with_case, link => last_id, entity => K, decl_kind => complete, xtyp => undefined_subtyp, block_or_pkg_ref => 0, normal => True, lev => Level, adr_or_sz => 0, is_referenced => False, is_read => no, is_written_after_init => no, is_initialized => none, location => CD.CUD.location); -- CD.target.Mark_Declaration; -- Update start of identifier chain: CD.Blocks_Table (CD.Display (Level)).Last_Id_Idx := CD.Id_Count; if Level = 0 then CD.CUD.level_0_def.Include (Id, CD.Id_Count); end if; end Enter_Simple; procedure Enter_Prefixed (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; Id, Id_with_case : Defs.Alfa; K : Co_Defs.Entity_Kind; Forward_Decl_Id : out Natural) is use HAT; prefixed_Id : constant Alfa := CD.pkg_prefix & Id; prefixed_Id_with_case : constant Alfa := CD.pkg_prefix & Id_with_case; begin Enter_Simple (CD, Level, prefixed_Id, prefixed_Id_with_case, K, Forward_Decl_Id); end Enter_Prefixed; procedure Enter (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; prefixed : Boolean; Id, Id_with_case : Defs.Alfa; K : Co_Defs.Entity_Kind; Forward_Decl_Id : out Natural) is begin if prefixed then Enter_Prefixed (CD, Level, Id, Id_with_case, K, Forward_Decl_Id); else Enter_Simple (CD, Level, Id, Id_with_case, K, Forward_Decl_Id); end if; end Enter; ------------------------------------------------------------------ -------------------------------------------------------EnterArray- procedure Enter_Array (CD : in out Co_Defs.Compiler_Data; Index_STP : Co_Defs.Exact_Subtyp) is begin if Index_STP.Discrete_First > Index_STP.Discrete_Last then Error (CD, err_illegal_array_bounds, "Low > High. NB: legal in Ada (empty array)", -- !! severity => major); end if; if Index_STP.Discrete_First < -HAC_Integer (XMax) or else Index_STP.Discrete_Last > HAC_Integer (XMax) then Error (CD, err_illegal_array_bounds, "absolute value of a bound exceeds maximum possible value", severity => major); end if; if CD.Arrays_Count = AMax then Fatal (ARRAYS); -- Exception is raised there. end if; CD.Arrays_Count := CD.Arrays_Count + 1; CD.Arrays_Table (CD.Arrays_Count).Index_xTyp := Index_STP; end Enter_Array; ------------------------------------------------------------------ --------------------------------------------------Enter_Variables- procedure Enter_Variables (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; prefixed : Boolean) is procedure Enter_Variable is dummy_id_idx : Natural; begin if CD.Sy = IDent then Enter (CD, Level, prefixed, CD.Id, CD.Id_with_case, variable_object, dummy_id_idx); Scanner.In_Symbol (CD); else Error (CD, err_identifier_missing); end if; end Enter_Variable; -- begin Enter_Variable; while CD.Sy = Comma loop -- ',' in "a, b, c : Integer;" Scanner.In_Symbol (CD); Enter_Variable; end loop; end Enter_Variables; end HAC_Sys.Parser.Enter_Def; ================================================ FILE: src/compile/hac_sys-parser-enter_def.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- Package around entering definitions, from the parser or "by hand", -- for built-in packages. package HAC_Sys.Parser.Enter_Def is procedure Enter_Block (CD : in out Co_Defs.Compiler_Data; Tptr : Integer); procedure Enter_Simple (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; Id, Id_with_case : Defs.Alfa; K : Co_Defs.Entity_Kind; Forward_Decl_Id : out Natural); -- Enter a definition with package prefix. procedure Enter_Prefixed (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; Id, Id_with_case : Defs.Alfa; K : Co_Defs.Entity_Kind; Forward_Decl_Id : out Natural); procedure Enter (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; prefixed : Boolean; Id, Id_with_case : Defs.Alfa; K : Co_Defs.Entity_Kind; Forward_Decl_Id : out Natural); procedure Enter_Array (CD : in out Co_Defs.Compiler_Data; Index_STP : Co_Defs.Exact_Subtyp); procedure Enter_Variables (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; prefixed : Boolean); -- For instance, fields in a record must be non-prefixed. end HAC_Sys.Parser.Enter_Def; ================================================ FILE: src/compile/hac_sys-parser-expressions.adb ================================================ with HAC_Sys.Compiler.PCode_Emit; with HAC_Sys.Parser.Attributes; with HAC_Sys.Parser.Calls; with HAC_Sys.Parser.Helpers; with HAC_Sys.Parser.Ranges; with HAC_Sys.Parser.Standard_Functions; with HAC_Sys.Parser.Type_Conversion; with HAC_Sys.PCode; with HAC_Sys.Scanner; with HAC_Sys.Errors; package body HAC_Sys.Parser.Expressions is use Compiler.PCode_Emit, Co_Defs, Defs, Helpers, PCode, Scanner, Errors; procedure Static_Scalar_Expression (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys_ND : in Defs.Symset; C : out Co_Defs.Constant_Rec) is -- This covers number declarations (RM 3.3.2) and enumeration items (RM 3.5.1). -- Additionally this compiler does on-the-fly declarations for static values: -- bounds in ranges (FOR, ARRAY), and values in CASE statements. -- Was: Constant in the Pascal compiler. X : Integer; Sign : HAC_Integer; use type HAC_Float, HAC_Integer; signed : Boolean := False; procedure In_Symbol is begin Scanner.In_Symbol (CD); end In_Symbol; begin C.TP := undefined_subtyp; C.I := 0; Test (CD, Constant_Definition_Begin_Symbol, FSys_ND, err_illegal_symbol_for_a_number_declaration); if not Constant_Definition_Begin_Symbol (CD.Sy) then return; end if; if CD.Sy = character_literal then -- Untyped character constant, occurs only in ranges. Construct_Root (C.TP, Chars); C.I := CD.INum; In_Symbol; else Sign := 1; if CD.Sy in Plus_Minus then signed := True; if CD.Sy = Minus then Sign := -1; end if; In_Symbol; end if; case CD.Sy is when IDent => -- Number defined using another one: "minus_pi : constant := -pi;" -- ... or, we have an enumeration item. X := Locate_CD_Id (CD, Level); if X /= 0 then if CD.id_table (X).entity = declared_number_or_enum_item then C.TP := CD.id_table (X).xtyp; if C.TP.TYP = Floats then C.R := HAC_Float (Sign) * CD.Float_Constants_Table (Integer (CD.id_table (X).adr_or_sz)); else C.I := Sign * CD.id_table (X).adr_or_sz; if signed and then C.TP.TYP not in Numeric_Typ then Error (CD, err_numeric_constant_expected); end if; end if; else Error (CD, err_illegal_constant_or_constant_identifier, severity => major); end if; end if; -- X /= 0 In_Symbol; when integer_literal => C.TP.Construct_Root (Ints); C.I := Sign * CD.INum; In_Symbol; when real_literal => C.TP.Construct_Root (Floats); C.R := HAC_Float (Sign) * CD.RNum; In_Symbol; when others => Error_then_Skip (CD, FSys_ND, err_illegal_symbol_for_a_number_declaration); end case; end if; Test (CD, FSys_ND, empty_symset, err_incorrectly_used_symbol); end Static_Scalar_Expression; ------------------------------------------------------------------ ---------------------------------------------------------Selector- procedure Selector (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; V : in out Co_Defs.Exact_Subtyp) is procedure Record_Field_Selector is Field_Offset, Field_Id : Integer; use type Alfa; begin if V.TYP = Records then Field_Id := CD.Blocks_Table (V.Ref).Last_Id_Idx; CD.id_table (0).name := CD.Id; while CD.id_table (Field_Id).name /= CD.Id loop -- Search field identifier Field_Id := CD.id_table (Field_Id).link; end loop; if Field_Id = No_Id then Error (CD, err_undefined_identifier, A2S (CD.Id_with_case), severity => major); else CD.target.Mark_Reference (Field_Id); CD.id_table (Field_Id).is_referenced := True; Elevate_to_Maybe (CD.id_table (Field_Id).is_read); V := CD.id_table (Field_Id).xtyp; Field_Offset := Integer (CD.id_table (Field_Id).adr_or_sz); if Field_Offset /= 0 then Emit_1 (CD, k_Record_Field_Offset, Operand_2_Type (Field_Offset)); end if; end if; else Error (CD, err_var_with_field_selector_must_be_record); end if; In_Symbol (CD); end Record_Field_Selector; procedure Array_Coordinates_Selector is Array_Index_Typ : Exact_Subtyp; -- Evaluation of "i", "j+7", "k*2" in "a (i, j+7, k*2)". use type HAC_Integer; procedure Emit_Index_Instructions (ATI : Integer; ATE : Array_Table_Entry) is range_check_needed : constant Boolean := Array_Index_Typ.Discrete_First < ATE.Index_xTyp.Discrete_First or else Array_Index_Typ.Discrete_Last > ATE.Index_xTyp.Discrete_Last; begin if ATE.Element_Size = 1 then if range_check_needed then Emit_1 (CD, k_Array_Index_Element_Size_1, Operand_2_Type (ATI)); else Emit_1 (CD, k_Array_Index_No_Check_Element_Size_1, Operand_2_Type (ATI)); end if; else if range_check_needed then Emit_1 (CD, k_Array_Index, Operand_2_Type (ATI)); else Emit_1 (CD, k_Array_Index_No_Check, Operand_2_Type (ATI)); end if; end if; end Emit_Index_Instructions; procedure Show_Range_Error (ATE : Array_Table_Entry) is begin Error (CD, err_range_constraint_error, "value of index (" & (if Ranges.Is_Singleton_Range (Array_Index_Typ) then -- More understandable message part for a single value Discrete_Image (CD, Array_Index_Typ.Discrete_First, ATE.Index_xTyp.TYP, ATE.Index_xTyp.Ref) else "range: " & Discrete_Range_Image (CD, Array_Index_Typ.Discrete_First, Array_Index_Typ.Discrete_Last, ATE.Index_xTyp.TYP, ATE.Index_xTyp.Ref)) & ") is out of the array's range, " & Discrete_Range_Image (CD, ATE.Index_xTyp.Discrete_First, ATE.Index_xTyp.Discrete_Last, ATE.Index_xTyp.TYP, ATE.Index_xTyp.Ref), severity => minor); end Show_Range_Error; procedure Show_Type_Mismatch_Error (ATE : Array_Table_Entry) is begin Type_Mismatch (CD, err_wrong_type_for_array_index, Found => Array_Index_Typ, Expected => ATE.Index_xTyp); end Show_Type_Mismatch_Error; indices : Natural := 0; first_dimension : Boolean := True; dims : Integer; begin Array_Indices : loop In_Symbol (CD); -- Consume '(', (wrongly) '[', or ',' symbol. Expression (CD, context, FSys + Comma_RParent + RBrack, Array_Index_Typ); indices := indices + 1; if V.TYP = Arrays then declare ATI : constant Integer := V.Ref; ATE : Array_Table_Entry renames CD.Arrays_Table (ATI); begin if first_dimension then dims := ATE.dimensions; first_dimension := False; end if; if Exact_Typ (ATE.Index_xTyp) /= Exact_Typ (Array_Index_Typ) then Show_Type_Mismatch_Error (ATE); elsif Ranges.Do_Ranges_Overlap (Array_Index_Typ, ATE.Index_xTyp) then Emit_Index_Instructions (ATI, ATE); else Show_Range_Error (ATE); end if; V := ATE.Element_xTyp; end; else Error (CD, err_indexed_variable_must_be_an_array); end if; exit Array_Indices when CD.Sy /= Comma; end loop Array_Indices; if indices < dims then Error (CD, err_too_few_array_indices, indices'Image, dims'Image); elsif indices > dims then Error (CD, err_too_many_array_indices, indices'Image, dims'Image); end if; end Array_Coordinates_Selector; begin pragma Assert (Selector_Symbol_Loose (CD.Sy)); -- '.' or '(' or (wrongly) '[' loop if CD.Sy = Period then -- Record field selector. In_Symbol (CD); -- Consume '.' symbol. if CD.Sy = IDent then Record_Field_Selector; else Error (CD, err_identifier_missing); end if; else -- Array element selector. if CD.Sy = LBrack then -- '[' -- Common mistake by Pascal, Python or R programmers. Error (CD, err_left_bracket_instead_of_parenthesis); end if; Array_Coordinates_Selector; if CD.Sy = RBrack then -- ']' : same kind of mistake as for '[' ... Error (CD, err_right_bracket_instead_of_parenthesis); In_Symbol (CD); else Need (CD, RParent, err_closing_parenthesis_missing); end if; end if; exit when not Selector_Symbol_Loose (CD.Sy); end loop; -- Test (CD, FSys, empty_symset, (if FSys = Semicolon_Set then err_semicolon_missing else err_incorrectly_used_symbol)); end Selector; is_logical_operator : constant Symset := -- RM 4.5 (2) (AND_Symbol | OR_Symbol | XOR_Symbol => True, others => False); relational_operator : constant Symset := -- RM 4.5 (3) (Comparison_Operator => True, others => False); binary_adding_operator : constant Symset := -- RM 4.5 (4) (Plus | Minus | Ampersand_Symbol => True, others => False); multiplying_operator : constant Symset := -- RM 4.5 (6) (Times | Divide | MOD_Symbol | REM_Symbol => True, others => False); highest_precedence_operator : constant Symset := -- RM 4.5 (7) (ABS_Symbol | NOT_Symbol | Power => True, others => False); ------------------------------------------------------------------ -------------------------------------------------------Expression- procedure Expression (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; X : out Co_Defs.Exact_Subtyp) is procedure Relation (FSys_Rel : Symset; X : out Exact_Subtyp) is -- RM 4.4 (3) Y : Exact_Subtyp; procedure Issue_Comparison_Type_Mismatch_Error is begin Type_Mismatch (CD, err_incompatible_types_for_comparison, Found => Y, Expected => X); end Issue_Comparison_Type_Mismatch_Error; Rel_OP : Symbol; Not_In : Boolean; begin -- Relation -- -- Single simple_expression, or: simple_expression OPERATOR simple_expression -- Simple_Expression (CD, context, FSys_Rel + relational_operator + IN_Symbol + NOT_Symbol, X); -- case CD.Sy is when Comparison_Operator => -- -- We collect here a comparison (relational) operator, e.g.: x < y -- Rel_OP := CD.Sy; In_Symbol (CD); Simple_Expression (CD, context, FSys_Rel, Y); if Internally_VString_Set (X.TYP) and then Internally_VString_Set (Y.TYP) then -- The internal type is actually a VString on both sides. Emit_Comparison_Instruction (CD, Rel_OP, VStrings); elsif Is_Char_Array (CD, X) and Is_Char_Array (CD, Y) then -- String object comparison, e.g. sx = sy Emit (CD, k_Swap); Emit_Std_Funct (CD, SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (X.Ref).Array_Size)); Emit (CD, k_Swap); Emit_Std_Funct (CD, SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (Y.Ref).Array_Size)); Emit_Comparison_Instruction (CD, Rel_OP, VStrings); elsif X.TYP = Y.TYP then if X.TYP = Enums and then X.Ref /= Y.Ref then Issue_Comparison_Type_Mismatch_Error; elsif PCode_Atomic_Comparable_Typ (X.TYP) then Emit_Comparison_Instruction (CD, Rel_OP, X.TYP); else Issue_Undefined_Operator_Error (CD, Rel_OP, X, Y); end if; elsif Is_Char_Array (CD, X) and Y.TYP = String_Literals then -- s = "abc" -- We needs convert the literal before anything else, -- since it takes two elements on the stack. Emit_Std_Funct (CD, SF_String_Literal_to_VString); Emit (CD, k_Swap); Emit_Std_Funct (CD, SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (X.Ref).Array_Size)); Emit (CD, k_Swap); Emit_Comparison_Instruction (CD, Rel_OP, VStrings); elsif Internally_VString_Set (X.TYP) and then Y.TYP = String_Literals then -- E.g., X < "World". -- Y is on top of the stack, we turn it into a VString. -- If this becomes a perfomance issue we could consider -- a new Standard Function (SF_Code) for (VStr op Lit_Str). Emit_Std_Funct (CD, SF_String_Literal_to_VString); -- Now we have X < +"World". Emit_Comparison_Instruction (CD, Rel_OP, VStrings); -- Emit "<" (X, +Y). elsif X.TYP = Ints and Y.TYP = Floats then Forbid_Type_Coercion (CD, Rel_OP, X, Y); X.TYP := Floats; Emit_1 (CD, k_Integer_to_Float, 1); elsif X.TYP = Floats and Y.TYP = Ints then Forbid_Type_Coercion (CD, Rel_OP, X, Y); Y.TYP := Floats; Emit_1 (CD, k_Integer_to_Float, 0); else Issue_Comparison_Type_Mismatch_Error; end if; Construct_Root (X, Bools); -- The result of the comparison is always Boolean. when IN_Symbol | NOT_Symbol => -- -- We collect here a membership test, e.g.: x [not] in a .. b -- Not_In := CD.Sy = NOT_Symbol; In_Symbol (CD); if Not_In then Need (CD, IN_Symbol, err_IN_missing); end if; if CD.error_count = 0 then Ranges.Dynamic_Range (CD, context, FSys_Rel, err_discrete_type_expected, Y); if Exact_Typ (X) /= Exact_Typ (Y) then Type_Mismatch (CD, err_membership_test_type_mismatch, Found => Y, Expected => X); -- The RM 4.5.2 (2) seems to accept any types for X and Y. The test would be False -- if types were incompatible. However, in that situation, GNAT says -- "incompatible types", ObjectAda says "LRM:8.6(28), Inappropriate operands -- for "IN" operation". end if; if Not_In then Emit_Std_Funct (CD, SF_not_in_discrete_Interval); else Emit_Std_Funct (CD, SF_in_discrete_Interval); end if; Construct_Root (X, Bools); -- The result of the membership test is always Boolean. end if; when others => null; end case; end Relation; logical_operator : Symbol; previous_operator : Symbol; Y : Exact_Subtyp; short_circuit : Boolean; LC_Cond_Jump : Integer; procedure Process_Short_Circuit (Cond_Jump : Opcode) is begin In_Symbol (CD); short_circuit := True; LC_Cond_Jump := CD.LC; Emit (CD, Cond_Jump); Emit (CD, k_Pop); -- Discard X value from stack. Top item will be Y. end Process_Short_Circuit; begin -- Expression Relation (FSys + is_logical_operator, X); -- -- RM 4.4 (2): we collect here possible relations, connected by -- logical operators: X {and Y}. -- previous_operator := Dummy_Symbol; while is_logical_operator (CD.Sy) loop logical_operator := CD.Sy; In_Symbol (CD); -- -- Short-circuit forms of AND, OR. -- short_circuit := False; if logical_operator = AND_Symbol and CD.Sy = THEN_Symbol then Process_Short_Circuit (k_Jump_If_Zero_No_Pop); -- -- Jump on X = False (i.e. 0). If X = True, then X and Y = Y. -- -- X : 0 0 1 1 -- \ \ -- Y : 0 | 1 | 0 1 -- / / | | -- X and Y : 0 0 0 1 -- logical_operator := AND_THEN_Symbol; elsif logical_operator = OR_Symbol and CD.Sy = ELSE_Symbol then Process_Short_Circuit (k_Jump_If_Non_Zero_No_Pop); -- -- Jump on X = True (i.e. 1). If X = False, then X or Y = Y. -- -- X : 0 0 1 1 -- \ \ -- Y : 0 1 0 | 1 | -- | | / / -- X or Y : 0 1 1 1 -- logical_operator := OR_ELSE_Symbol; end if; if previous_operator /= Dummy_Symbol and then logical_operator /= previous_operator then Error (CD, err_mixed_logical_operators, severity => minor); end if; -- -- Right side of the logical operator. -- Relation (FSys + is_logical_operator, Y); -- if X.TYP = Bools and Y.TYP = Bools then if short_circuit then -- Patch the address for the conditional jump, with the place -- right after the evaluation of relation Y: CD.ObjCode (LC_Cond_Jump).Y := Operand_2_Type (CD.LC); else case logical_operator is when AND_Symbol => Emit (CD, k_AND_Boolean); when OR_Symbol => Emit (CD, k_OR_Boolean); when XOR_Symbol => Emit (CD, k_XOR_Boolean); when others => null; end case; end if; else Error (CD, err_resulting_type_should_be_Boolean); X.TYP := NOTYP; end if; previous_operator := logical_operator; end loop; if X.TYP = NOTYP and then CD.error_count = 0 then Error (CD, err_object_used_before_end_own_declaration, severity => major); end if; end Expression; procedure Simple_Expression -- RM 4.4 (4) (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; X : out Co_Defs.Exact_Subtyp) is procedure Term (FSys_Term : Symset; X : out Exact_Subtyp) is -- RM 4.4 (5) procedure Factor (FSys_Fact : Symset; X : out Exact_Subtyp) is -- RM 4.4 (6) procedure Primary (FSys_Prim : Symset; X : out Exact_Subtyp) is -- RM 4.4 (7) procedure Process_Identifier is ident_index : constant Integer := Locate_CD_Id (CD, context.level); r : Identifier_Table_Entry renames CD.id_table (ident_index); procedure Process_Object_Identifier is LC_Mem : constant Integer := CD.LC; begin if Selector_Symbol_Loose (CD.Sy) then -- '.' or '(' or (wrongly) '[' Emit_2 (CD, (if r.normal then k_Push_Address -- Composite: push "v'Access". else k_Push_Discrete_Value), -- Composite: push "(a.all)'Access", that is, a. Operand_1_Type (r.lev), Operand_2_Type (r.adr_or_sz)); Selector (CD, context, FSys_Prim + Apostrophe, X); if Standard_or_Enum_Typ (X.TYP) then -- We are at a leaf point of composite type selection, -- so the stack top is expected to contain a value, not -- an address (for an expression). Emit (CD, k_Dereference); end if; else -- No selector. Emit_2 (CD, (if Standard_or_Enum_Typ (X.TYP) then (if r.normal then (if Discrete_Typ (r.xtyp.TYP) then k_Push_Discrete_Value -- Push variable v's discrete value. else k_Push_Value) -- Push variable v's value. else k_Push_Indirect_Value) -- Push "a.all" (a is an access). elsif r.normal then k_Push_Address -- Composite: push "v'Access". else k_Push_Discrete_Value), -- Composite: push "(a.all)'Access, that is, a. Operand_1_Type (r.lev), Operand_2_Type (r.adr_or_sz)); end if; if CD.Sy = Apostrophe then -- Attribute on an object. In_Symbol (CD); Attributes.Object_Attribute (CD, context.level, FSys_Prim, X, LC_Mem, X); else -- The variable or parameter itself, not an attribute on it, has been read. -- We check that it has been even written on the way to this expression. Mark_Read_and_Check_Read_before_Written (CD, context, r); end if; end Process_Object_Identifier; begin In_Symbol (CD); X := r.xtyp; case r.entity is when Object_Kind => Process_Object_Identifier; when declared_number_or_enum_item => if X.TYP = Floats then -- Address is an index in the float constants table. Emit_1 (CD, k_Push_Float_Literal, Operand_2_Type (r.adr_or_sz)); else -- Here the address is actually the immediate (discrete) value. Emit_1 (CD, k_Push_Discrete_Literal, Operand_2_Type (r.adr_or_sz)); -- The local subtype for the value V is the range V .. V. Ranges.Set_Singleton_Range (X, r.adr_or_sz); end if; when prozedure | prozedure_intrinsic => Error (CD, err_expected_constant_function_variable_or_subtype); when funktion => Calls.Subprogram_or_Entry_Call (CD, context, FSys_Prim, ident_index, Normal_Procedure_Call); when funktion_intrinsic => Standard_Functions.Standard_Function (CD, context, FSys_Prim, ident_index, SF_Code'Val (r.adr_or_sz), X); when type_mark => Subtype_Prefixed_Expression (CD, context, FSys_Prim, ident_index, X); when others => null; end case; if X.TYP = NOTYP and then CD.error_count = 0 then Error (CD, err_object_used_before_end_own_declaration, '"' & A2S (r.name_with_case) & """ ", severity => major); end if; end Process_Identifier; begin X := undefined_subtyp; Test (CD, Primary_Begin_Symbol, FSys_Prim, err_primary_unexpected_symbol); case CD.Sy is when IDent => Process_Identifier; when character_literal | integer_literal => -- Here we have a discrete literal. X.Construct_Root (if CD.Sy = character_literal then Chars else Ints); CD.target.Emit_Push_Discrete_Literal (CD.INum); -- The local subtype for the value V is the range V .. V. Ranges.Set_Singleton_Range (X, CD.INum); In_Symbol (CD); when real_literal => X.Construct_Root (Floats); Emit_Push_Float_Literal (CD, CD.RNum); In_Symbol (CD); when string_literal => Construct_Root (X, String_Literals); CD.target.Emit_Push_Discrete_Literals (Operand_1_Type (CD.SLeng), -- String Literal Length Operand_2_Type (CD.INum)); -- Index To String IdTab In_Symbol (CD); when LParent => -- '(' : what is inside the parentheses is an -- expression of the lowest level. In_Symbol (CD); Expression (CD, context, FSys_Prim + RParent, X); if CD.Sy = Comma then Error (CD, err_not_yet_implemented, "aggregates (RM 4.3)", severity => major); end if; Need (CD, RParent, err_closing_parenthesis_missing); when others => null; end case; if X.TYP = NOTYP and then CD.error_count = 0 then Error (CD, err_object_used_before_end_own_declaration, severity => major); end if; end Primary; Y : Exact_Subtyp; begin -- Factor case CD.Sy is when ABS_Symbol => In_Symbol (CD); Primary (FSys_Fact, X); case X.TYP is when Ints => Emit_Std_Funct (CD, SF_Abs_Int); when Floats => Emit_Std_Funct (CD, SF_Abs_Float); when NOTYP => null; -- Another error before. when others => Error (CD, err_argument_to_std_function_of_wrong_type); end case; X.Construct_Root (X.TYP); -- Forget subtype bounds when NOT_Symbol => In_Symbol (CD); Primary (FSys_Fact, X); case X.TYP is when Bools => Emit (CD, k_NOT_Boolean); when NOTYP => null; -- Another error before. when others => Error (CD, err_resulting_type_should_be_Boolean); end case; when others => Primary (FSys_Fact + highest_precedence_operator, X); if CD.Sy = Power then In_Symbol (CD); Primary (FSys_Fact, Y); if X.TYP in Numeric_Typ and then X.TYP = Y.TYP then CD.target.Emit_Arithmetic_Binary_Instruction (Power, X.TYP); elsif X.TYP = Floats and Y.TYP = Ints then Emit (CD, k_Power_Float_Integer); else Issue_Undefined_Operator_Error (CD, Power, X, Y); end if; X.Construct_Root (X.TYP); -- Forget subtype bounds end if; end case; end Factor; use type HAC_Integer; Mult_OP : Symbol; Y : Exact_Subtyp; begin -- Term Factor (FSys_Term + multiplying_operator, X); -- -- We collect here possible factors: a {* b} -- while multiplying_operator (CD.Sy) loop Mult_OP := CD.Sy; In_Symbol (CD); Factor (FSys_Term + multiplying_operator, Y); if X.TYP = NOTYP or Y.TYP = NOTYP then null; -- Something is already wrong at this point; nothing to check or emit. else case Mult_OP is when Times => -- * if X.TYP in Numeric_Typ and then Y.TYP in Numeric_Typ then if X.TYP = Y.TYP then CD.target.Emit_Arithmetic_Binary_Instruction (Times, X.TYP); else Forbid_Type_Coercion (CD, Mult_OP, X, Y); end if; -- Figure out the subtype range after the -- multiplication, if possible. NB: beyond trivial cases, -- compile-time overflow checks would be needed. if X.TYP = Ints then -- Find some possible static values. if Ranges.Is_Singleton_Range (X, 0) then -- 0 * Y = 0. null; -- Keep X's range, which is [0; 0]. elsif Ranges.Is_Singleton_Range (Y, 0) then -- X * 0 = 0. Ranges.Set_Singleton_Range (X, 0); elsif Ranges.Is_Singleton_Range (X, 1) then -- 1 * Y = Y. X.Discrete_First := Y.Discrete_First; X.Discrete_Last := Y.Discrete_Last; elsif Ranges.Is_Singleton_Range (Y, 1) then -- X * 1 = X. null; -- Keep X's range. else X.Construct_Root (X.TYP); -- Forget subtype bounds end if; end if; elsif X.TYP = Ints then -- N * (something non-numeric) case Y.TYP is when Chars => Emit_Std_Funct (CD, SF_Int_Times_Char); -- N * Some_Char Construct_Root (X, VStrings); when String_Literals => -- Y is on top of the stack, we turn it into a VString. Emit_Std_Funct (CD, SF_String_Literal_to_VString); Emit_Std_Funct (CD, SF_Int_Times_VStr); -- N * Some_String_Literal Construct_Root (X, VStrings); when VStrings | Strings_as_VStrings => Emit_Std_Funct (CD, SF_Int_Times_VStr); -- N * Some_VString Construct_Root (X, VStrings); when others => Issue_Undefined_Operator_Error (CD, Mult_OP, X, Y); end case; else Issue_Undefined_Operator_Error (CD, Mult_OP, X, Y); end if; when Divide => -- / if X.TYP in Numeric_Typ and then X.TYP = Y.TYP then CD.target.Emit_Arithmetic_Binary_Instruction (Divide, X.TYP); X.Construct_Root (X.TYP); -- Forget subtype bounds else if X.TYP = Ints then Forbid_Type_Coercion (CD, Mult_OP, X, Y); Emit_1 (CD, k_Integer_to_Float, 1); -- NB: this assumed Y.TYP was Floats! X.TYP := Floats; end if; if Y.TYP = Ints then Forbid_Type_Coercion (CD, Mult_OP, X, Y); Emit_1 (CD, k_Integer_to_Float, 0); -- NB: this assumed Y.TYP was Floats! Y.TYP := Floats; end if; Error (CD, err_illegal_type_for_arithmetic_expression); X.TYP := NOTYP; end if; when MOD_Symbol | REM_Symbol => if X.TYP = Ints and Y.TYP = Ints then if Mult_OP = MOD_Symbol then Emit (CD, k_MOD_Integer); else Emit (CD, k_REM_Integer); end if; else Error (CD, err_mod_requires_integer_arguments); X.TYP := NOTYP; end if; when others => raise Internal_error with "Unknown operator in Term"; end case; end if; end loop; end Term; procedure Check_HAT_Operator_Visibility (op : Symbol) is begin if not CD.CUD.Use_HAT_Stack (CD.CUD.use_hat_stack_top) then -- HAT is not USE-visible Error (CD, err_general_error, "operator (" & Op_Hint (op) & ") not visible (missing a ""use " & HAT_Name & """ clause)", severity => major); end if; end Check_HAT_Operator_Visibility; additive_operator : Symbol; y : Exact_Subtyp; function Do_VString_Concatenation return Boolean is begin if X.TYP /= VStrings and y.TYP /= VStrings then return False; end if; -- Below this line, at least X or Y is a VString, defined in the HAT package. Check_HAT_Operator_Visibility (Ampersand_Symbol); -- RM References are about Unbounded_String (A.4.5). if Internally_VString_Set (X.TYP) and then Internally_VString_Set (y.TYP) then -- v1 & v2 A.4.5 (15) -- v & Enum'Image (x) A.4.5 (16), -- Enum'Image (x) & v A.4.5 (17) Emit_Std_Funct (CD, SF_Two_VStrings_Concat); elsif y.TYP = String_Literals then -- v & "x" A.4.5 (16) -- Y is on top of the stack, we turn it into a VString. -- If this becomes a perfomance issue we could consider -- adding a Standard Function (SF_Code) for (VStr op Lit_Str). Emit_Std_Funct (CD, SF_String_Literal_to_VString); -- Now we concatenate both VStrings. Emit_Std_Funct (CD, SF_Two_VStrings_Concat); elsif X.TYP = String_Literals then -- "x" & v A.4.5 (17) Emit_Std_Funct (CD, SF_LStr_VString_Concat); elsif Is_Char_Array (CD, y) then -- v & s A.4.5 (16) Emit_Std_Funct (CD, SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (y.Ref).Array_Size) ); Emit_Std_Funct (CD, SF_Two_VStrings_Concat); elsif Is_Char_Array (CD, X) then -- s & v A.4.5 (17) Emit (CD, k_Swap); -- v, then s on the stack Emit_Std_Funct (CD, -- s -> +s SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (X.Ref).Array_Size) ); Emit (CD, k_Swap); -- +s, then v on the stack Emit_Std_Funct (CD, SF_Two_VStrings_Concat); elsif y.TYP = Chars then -- v & 'x' A.4.5 (18) Emit_Std_Funct (CD, SF_VString_Char_Concat); elsif X.TYP = Chars then -- 'x' & v A.4.5 (19) Emit_Std_Funct (CD, SF_Char_VString_Concat); -- -- Hereafter, we have "&" operators on VString provided only by HAT -- and not by Ada.Unbounded_Strings -- elsif y.TYP = Ints then Emit_Std_Funct (CD, SF_VString_Int_Concat); -- v & 123 elsif X.TYP = Ints then Emit_Std_Funct (CD, SF_Int_VString_Concat); -- 123 & v elsif y.TYP = Floats then Emit_Std_Funct (CD, SF_VString_Float_Concat); -- v & 3.14159 elsif X.TYP = Floats then Emit_Std_Funct (CD, SF_Float_VString_Concat); -- 3.14159 & v elsif y.TYP = Durations then Emit_Std_Funct (CD, SF_VString_Duration_Concat); -- v & dur elsif X.TYP = Durations then Emit_Std_Funct (CD, SF_Duration_VString_Concat); -- dur & v elsif y.TYP = Bools then Emit_Std_Funct (CD, SF_VString_Boolean_Concat); -- v & is_found elsif X.TYP = Bools then Emit_Std_Funct (CD, SF_Boolean_VString_Concat); -- is_found & v else return False; end if; Construct_Root (X, VStrings); return True; end Do_VString_Concatenation; function Do_String_Concatenation return Boolean is -- Arguments can be one of the three internal representations of String: -- 1) sv : VString (the parser sees the TYP Strings_as_VStrings) -- 2) sc : constrained array of character -- 3) "xy" : literal string -- Additionally, we can have a character: -- 4) 'x' : character (value or literal) -- -- So, it makes 16 argument combinations. We note them [ab]. -- For example, a concatenation of a Strings_as_VStrings and a Literal -- is noted [13]. -- -- Result is always Strings_as_VStrings. -- RM Reference: the predefined "&" operator 4.5.3(3), applied to String. procedure Emit_sc1_amp_sv2 is -- Emit code for: sc1 & sv2 begin Emit (CD, k_Swap); -- sv2, then sc1 on the stack Emit_Std_Funct (CD, -- sv1 := To_VString (sc1) SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (X.Ref).Array_Size)); Emit (CD, k_Swap); -- sv1, then sv2 on the stack Emit_Std_Funct (CD, SF_Two_VStrings_Concat); -- sv1 & sv2 end Emit_sc1_amp_sv2; procedure Emit_sc2_to_sv2 is begin Emit_Std_Funct (CD, -- sv2 := To_VString (sc2) SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (y.Ref).Array_Size)); end Emit_sc2_to_sv2; begin if X.TYP = Strings_as_VStrings then if y.TYP = Strings_as_VStrings then -- [11] sv1 & sv2 Emit_Std_Funct (CD, SF_Two_VStrings_Concat); elsif Is_Char_Array (CD, y) then -- [12] sv1 & sc2 Emit_sc2_to_sv2; -- Back to case [11]: Emit_Std_Funct (CD, SF_Two_VStrings_Concat); elsif y.TYP = String_Literals then -- [13] sv1 & "xy" Emit_Std_Funct (CD, SF_String_Literal_to_VString); -- Back to case [11]: Emit_Std_Funct (CD, SF_Two_VStrings_Concat); elsif y.TYP = Chars then -- [14] sv1 & 'x' Emit_Std_Funct (CD, SF_VString_Char_Concat); else return False; end if; elsif Is_Char_Array (CD, X) then if y.TYP = Strings_as_VStrings then -- [21] sc1 & sv2 Emit_sc1_amp_sv2; elsif Is_Char_Array (CD, y) then -- [22] sc1 & sc2 Emit_sc2_to_sv2; Emit_sc1_amp_sv2; elsif y.TYP = String_Literals then -- [23] sc1 & "xy" Emit_Std_Funct (CD, SF_String_Literal_to_VString); Emit_sc1_amp_sv2; elsif y.TYP = Chars then -- [24] sc1 & 'x' Emit_Std_Funct (CD, SF_Char_to_VString); Emit_sc1_amp_sv2; else return False; end if; elsif X.TYP = String_Literals then if y.TYP = Strings_as_VStrings then -- [31] "xy" & sv2 Emit_Std_Funct (CD, SF_LStr_VString_Concat); elsif Is_Char_Array (CD, y) then -- [32] "xy" & sc2 Emit_sc2_to_sv2; Emit_Std_Funct (CD, SF_LStr_VString_Concat); elsif y.TYP = String_Literals then -- [33] "ab" & "cd" Emit_Std_Funct (CD, SF_String_Literal_to_VString); Emit_Std_Funct (CD, SF_LStr_VString_Concat); elsif y.TYP = Chars then -- [34] "ab" & 'c' Emit_Std_Funct (CD, SF_Char_to_VString); Emit_Std_Funct (CD, SF_LStr_VString_Concat); else return False; end if; elsif X.TYP = Chars then if y.TYP = Strings_as_VStrings then -- [41] 'x' & sv2 Emit_Std_Funct (CD, SF_Char_VString_Concat); elsif Is_Char_Array (CD, y) then -- [42] 'x' & sc2 Emit_sc2_to_sv2; Emit_Std_Funct (CD, SF_Char_VString_Concat); elsif y.TYP = String_Literals then -- [43] 'a' & "bc" Emit_Std_Funct (CD, SF_String_Literal_to_VString); Emit_Std_Funct (CD, SF_Char_VString_Concat); elsif y.TYP = Chars then -- [34] 'a' & 'b' Emit_Std_Funct (CD, SF_Char_to_VString); Emit_Std_Funct (CD, SF_Char_VString_Concat); else return False; end if; else return False; end if; Construct_Root (X, Strings_as_VStrings); return True; end Do_String_Concatenation; begin -- Simple_Expression if CD.Sy in Plus_Minus then -- -- Unary + , - RM 4.5 (5), 4.4 (4) -- additive_operator := CD.Sy; In_Symbol (CD); Term (FSys + Plus_Minus_Set, X); -- At this point we have consumed "+X" or "-X". if X.TYP in String_Literals | Strings_as_VStrings | Chars | VStrings or else Is_Char_Array (CD, X) then Check_HAT_Operator_Visibility (additive_operator); case Plus_Minus (additive_operator) is when Plus => case X.TYP is when String_Literals => -- +"Hello" Emit_Std_Funct (CD, SF_String_Literal_to_VString); when Strings_as_VStrings => -- +Enum'Image (x) -- Nothing to do, except setting X's -- subtype as an "official" VString. null; when Chars => -- +'H' Emit_Std_Funct (CD, SF_Char_to_VString); when Arrays => if Is_Char_Array (CD, X) then -- +S Emit_Std_Funct (CD, SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (X.Ref).Array_Size)); else Issue_Undefined_Operator_Error (CD, additive_operator, X); end if; when others => Issue_Undefined_Operator_Error (CD, additive_operator, X); end case; Construct_Root (X, VStrings); when Minus => if X.TYP = VStrings then -- -v Construct_Root (X, Strings_as_VStrings); else Issue_Undefined_Operator_Error (CD, additive_operator, X); end if; end case; elsif X.TYP not in Numeric_Typ then Error (CD, err_illegal_type_for_arithmetic_expression); elsif additive_operator = Minus then Emit_Unary_Minus (CD, X.TYP); if X.TYP = Ints then Ranges.Negate_Range (CD, X); end if; end if; else Term (FSys + binary_adding_operator, X); end if; -- -- Binary operators: we collect here possible terms: a {+ b} RM 4.4 (4) -- while binary_adding_operator (CD.Sy) loop additive_operator := CD.Sy; In_Symbol (CD); Term (FSys + binary_adding_operator, y); if X.TYP = NOTYP or y.TYP = NOTYP then null; -- Something is already wrong at this point; nothing to check or emit. else case additive_operator is when OR_Symbol => if X.TYP = Bools and y.TYP = Bools then Emit (CD, k_OR_Boolean); else Error (CD, err_resulting_type_should_be_Boolean); X.TYP := NOTYP; end if; when XOR_Symbol => if X.TYP = Bools and y.TYP = Bools then Emit (CD, k_XOR_Boolean); else Error (CD, err_resulting_type_should_be_Boolean); X.TYP := NOTYP; end if; when Plus | Minus => if X.TYP in Numeric_Typ and then y.TYP in Numeric_Typ then if X.TYP = y.TYP then CD.target.Emit_Arithmetic_Binary_Instruction (additive_operator, X.TYP); else Forbid_Type_Coercion (CD, additive_operator, X, y); end if; if X.TYP = Ints then if Ranges.Is_Singleton_Range (y, 0) then -- X +/- 0 = X. null; -- Keep X's range. else X.Construct_Root (X.TYP); -- Forget subtype bounds end if; end if; elsif X.TYP = Times and y.TYP = Times and additive_operator = Minus then Emit_Std_Funct (CD, SF_Time_Subtract); -- T2 - T1 Construct_Root (X, Durations); elsif X.TYP = Durations then if y.TYP = Floats then -- Duration hack for "X + 1.234" (see Delay_Statement -- for full explanation). Emit_Std_Funct (CD, SF_Float_to_Duration); Construct_Root (y, Durations); -- Now X and Y have the type Duration. end if; if y.TYP = Durations then if additive_operator = Plus then Emit_Std_Funct (CD, SF_Duration_Add); else Emit_Std_Funct (CD, SF_Duration_Subtract); end if; else Issue_Undefined_Operator_Error (CD, additive_operator, X, y); end if; else Issue_Undefined_Operator_Error (CD, additive_operator, X, y); end if; when Ampersand_Symbol => if not (Do_VString_Concatenation or else Do_String_Concatenation) then Issue_Undefined_Operator_Error (CD, additive_operator, X, y); end if; when others => -- Doesn't happen: Binary_Adding_Operators(OP) is True. null; end case; end if; end loop; end Simple_Expression; procedure Boolean_Expression (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; X : out Co_Defs.Exact_Subtyp) is begin Expression (CD, context, FSys, X); Check_Boolean (CD, X.TYP); end Boolean_Expression; procedure Subtype_Prefixed_Expression (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Typ_ID_Index : in Natural; X : in out Co_Defs.Exact_Subtyp) is Mem_Sy : constant Symbol := CD.Sy; begin pragma Assert (CD.id_table (Typ_ID_Index).entity = type_mark); In_Symbol (CD); case Mem_Sy is when LParent => -- S (...) Type_Conversion (CD, context, FSys, CD.id_table (Typ_ID_Index), X); when Apostrophe => -- S'First, S'Image, ... Attributes.Subtype_Attribute (CD, context, FSys, Typ_ID_Index, X); when others => Error (CD, err_general_error, "expected ""'"" or ""("" here", severity => major); end case; end Subtype_Prefixed_Expression; end HAC_Sys.Parser.Expressions; ================================================ FILE: src/compile/hac_sys-parser-expressions.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- private package HAC_Sys.Parser.Expressions is procedure Static_Scalar_Expression (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys_ND : in Defs.Symset; C : out Co_Defs.Constant_Rec); -- For all dynamic expressions: -- - the appropriate machine code is emitted; -- - in the machine code, the expression is pushed on the stack -- - for parsing: the type of the expression is set in X. procedure Boolean_Expression (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; X : out Co_Defs.Exact_Subtyp); procedure Expression -- RM 4.4 (2) (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; X : out Co_Defs.Exact_Subtyp); procedure Simple_Expression -- RM 4.4 (4) (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; X : out Co_Defs.Exact_Subtyp); procedure Selector (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; V : in out Co_Defs.Exact_Subtyp); -- Conversion, like ` Integer (123.456) ` -- or attribute, like ` Integer'Image (123) `. -- procedure Subtype_Prefixed_Expression (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Typ_ID_Index : in Natural; X : in out Co_Defs.Exact_Subtyp); end HAC_Sys.Parser.Expressions; ================================================ FILE: src/compile/hac_sys-parser-helpers.adb ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.PCode, HAC_Sys.Scanner, HAC_Sys.Errors; with HAT; package body HAC_Sys.Parser.Helpers is use Scanner, Errors; use type HAC_Integer; procedure Need (CD : in out Compiler_Data; S : Symbol; E : Compile_Diagnostic; Forgive : Symbol := Dummy_Symbol) is severity : Error_Severity := medium; begin if CD.Sy = S then In_Symbol (CD); else if Forgive = Dummy_Symbol then severity := major; end if; Error (CD, E, ": " & Symbol'Image (S) & " expected", severity => severity); if CD.Sy = Forgive then In_Symbol (CD); end if; end if; end Need; procedure Error_then_Skip (CD : in out Compiler_Data; FSys : Symset; N : Compile_Diagnostic; hint : String := "") is function StopMe return Boolean is begin return False; end StopMe; begin Error (CD, N, hint); -- while not FSys (CD.Sy) loop In_Symbol (CD); if StopMe then raise Failure_1_0; end if; end loop; In_Symbol (CD); -- Manuel: If this In_Symbol call is -- omitted, the system will get in an -- infinite loop on the statement: -- put_lin("Typo is on purpose"); if StopMe then raise Failure_1_0; end if; end Error_then_Skip; procedure Error_then_Skip (CD : in out Compiler_Data; S : Symbol; N : Compile_Diagnostic; hint : String := "") is begin Error_then_Skip (CD, Singleton (S), N, hint); end Error_then_Skip; procedure Test (CD : in out Compiler_Data; S1, S2 : Symset; N : Compile_Diagnostic; stop_on_error : Boolean := False) is use HAT; begin if not S1 (CD.Sy) then declare hint : VString; first : Boolean := True; begin for s in S1'Range loop if S1 (s) then if not first then hint := hint & ", "; end if; first := False; hint := hint & Symbol'Image (s); end if; end loop; hint := "Found: " & Symbol'Image (CD.Sy) & "; expected: " & hint; if stop_on_error then Error (CD, N, HAT.VStr_Pkg.To_String (hint), severity => major); end if; Error_then_Skip (CD, S1 + S2, N, HAT.VStr_Pkg.To_String (hint)); end; end if; end Test; After_Semicolon_after_Declaration : constant Symset := Declaration_X_Subprogram_Symbol + Block_Begin_Symbol + END_Symbol + PRIVATE_Symbol; Comma_or_colon : constant Symset := Symset'(Comma | Colon => True, others => False); procedure Need_Semicolon_after_Declaration (CD : in out Compiler_Data; FSys : Symset) is begin if CD.Sy = Semicolon then In_Symbol (CD); Ignore_Extra_Semicolons (CD); else Error (CD, err_semicolon_missing); if Comma_or_colon (CD.Sy) then In_Symbol (CD); end if; end if; Test (CD, After_Semicolon_after_Declaration, FSys, err_incorrectly_used_symbol); end Need_Semicolon_after_Declaration; procedure Need_END_Symbol (CD : in out Compiler_Data) is begin if CD.Sy = END_Symbol then In_Symbol (CD); else Error_then_Skip (CD, Semicolon, err_END_missing); end if; end Need_END_Symbol; procedure Check_Boolean (CD : in out Compiler_Data; T : Typen) is begin if T /= Bools then Error (CD, err_expecting_a_boolean_expression); end if; end Check_Boolean; procedure Check_Integer (CD : in out Compiler_Data; T : Typen) is begin if T /= Ints then Error (CD, err_parameter_must_be_Integer); end if; end Check_Integer; procedure Ignore_Extra_Semicolons (CD : in out Compiler_Data) is begin if CD.Sy = Semicolon then Error (CD, err_duplicate_semicolon, severity => minor); while CD.Sy = Semicolon loop In_Symbol (CD); end loop; end if; end Ignore_Extra_Semicolons; procedure Need_Semicolon (CD : in out Compiler_Data) is begin if CD.Sy = RParent and then CD.prev_sy = RParent then Error (CD, err_extra_right_parenthesis, severity => minor); while CD.Sy = RParent loop In_Symbol (CD); end loop; end if; Need (CD, Semicolon, err_semicolon_missing, Forgive => Comma); Ignore_Extra_Semicolons (CD); end Need_Semicolon; procedure Argument_Type_Not_Supported (CD : in out Compiler_Data) is begin Error (CD, err_type_conversion_not_supported, "argument type not supported"); end Argument_Type_Not_Supported; function Nice_Image (T : Typen) return String is begin case T is when NOTYP => return "(undefined type)"; when Ints => return "an integer type"; when Chars => return "Character"; -- "the" Character type when Bools => return "Boolean"; -- "the" Boolean type when Floats => return "a floating-point type"; when Arrays => return "an array type"; when Records => return "a record type"; when Enums => return "an enumeration type"; when String_Literals => return "String [literal]"; when Strings_as_VStrings => return "String [pseudo-unconstrained]"; when VStrings => return "VString"; when Times => return "Time"; -- "the" Time type when Durations => return "Duration"; -- "the" Duration type when Text_Files => return "File_Type"; end case; end Nice_Image; function Enum_Name (CD : Compiler_Data; E_Ref : Index) return String is (A2S (CD.id_table (E_Ref).name_with_case)); function Nice_Exact_Image (CD : Compiler_Data; xT : Exact_Typ'Class) return String is (Nice_Image (xT.TYP) & (if xT.TYP = Enums then " (" & Enum_Name (CD, xT.Ref) & ')' else "")); procedure Type_Mismatch (CD : in out Compiler_Data; Err : Compile_Diagnostic; Found, Expected : Exact_Typ'Class) is begin if Found.TYP /= Expected.TYP then Error (CD, Err, "found " & Nice_Exact_Image (CD, Found) & ", expected " & Nice_Exact_Image (CD, Expected), severity => major); elsif Found.TYP = Enums then Error (CD, Err, "found """ & Enum_Name (CD, Found.Ref) & """, expected """ & Enum_Name (CD, Expected.Ref) & '"', severity => major); else Error (CD, Err, "not exactly the same " & Nice_Image (Found.TYP), severity => major); -- Possible improvement: find the possible array or record -- names using X.Ref, Y.Ref ... if they have names! -- (same for Issue_Undefined_Operator_Error) end if; end Type_Mismatch; procedure Type_Mismatch (CD : in out Compiler_Data; Err : Compile_Diagnostic; Found : Exact_Subtyp; Expected : Typ_Set) is function Types_List (TS : Typ_Set) return String is use HAT; hint : VString; first : Boolean := True; begin for s in TS'Range loop if TS (s) then if not first then hint := hint & ", "; end if; first := False; hint := hint & Nice_Image (s); end if; end loop; return HAT.VStr_Pkg.To_String (hint); end Types_List; begin Error (CD, Err, "found: " & Nice_Exact_Image (CD, Found) & ", expected: " & Types_List (Expected), severity => major); end Type_Mismatch; function Op_Hint (OP : Symbol) return String is -- Displayed as "operator (+) is not defined..." begin case OP is when Plus => return "+"; when Minus => return "-"; when Times => return "*"; when Divide => return "/"; when Power => return "**"; when Ampersand_Symbol => return "&"; when EQL => return "="; when NEQ => return "/="; when GTR => return ">"; when GEQ => return ">="; when LSS => return "<"; when LEQ => return "<="; when others => return "?"; end case; end Op_Hint; procedure Issue_Undefined_Operator_Error (CD : in out Compiler_Data; Operator : Symbol; Right : Exact_Subtyp) is begin if Right.TYP = Enums then Error (CD, err_operator_not_defined_for_types, Op_Hint (Operator), Enum_Name (CD, Right.Ref)); else Error (CD, err_operator_not_defined_for_types, Op_Hint (Operator), Nice_Image (Right.TYP)); end if; end Issue_Undefined_Operator_Error; procedure Issue_Undefined_Operator_Error (CD : in out Compiler_Data; Operator : Symbol; Left, Right : Exact_Subtyp) is begin if Left.TYP /= Right.TYP then Error (CD, err_operator_not_defined_for_types, Op_Hint (Operator), "left is " & Nice_Exact_Image (CD, Left) & ", right is " & Nice_Exact_Image (CD, Right)); elsif Left.TYP = Enums then if Left.Ref = Right.Ref then Error (CD, err_operator_not_defined_for_types, Op_Hint (Operator), Enum_Name (CD, Left.Ref)); else Error (CD, err_operator_not_defined_for_types, Op_Hint (Operator), "left is " & Enum_Name (CD, Left.Ref) & ", right is " & Enum_Name (CD, Right.Ref)); end if; else Error (CD, err_operator_not_defined_for_types, Op_Hint (Operator), Nice_Image (Left.TYP)); -- Possible improvement: find the possible array or record -- names using X.Ref, Y.Ref ... if they have names! -- (same for Type_Mismatch) end if; end Issue_Undefined_Operator_Error; procedure Forbid_Type_Coercion (CD : in out Compiler_Data; Operator : Symbol; Left, Right : Exact_Subtyp) is begin Error (CD, err_numeric_type_coercion_operator, Op_Hint (Operator), "left is " & Nice_Exact_Image (CD, Left) & ", right is " & Nice_Exact_Image (CD, Right), major); end Forbid_Type_Coercion; procedure Forbid_Type_Coercion (CD : in out Compiler_Data; Found, Expected : Exact_Subtyp) is begin Error (CD, err_numeric_type_coercion, "found " & Nice_Exact_Image (CD, Found) & ", expected " & Nice_Exact_Image (CD, Expected), severity => major); end Forbid_Type_Coercion; function Singleton (s : Symbol) return Symset is res : Symset := empty_symset; begin res (s) := True; return res; end Singleton; function Singleton (t : Typen) return Typ_Set is res : Typ_Set := empty_typ_set; begin res (t) := True; return res; end Singleton; function Is_Char_Array (CD : Compiler_Data; T : Exact_Subtyp) return Boolean is begin return T.TYP = Arrays and then T.Ref in Arrays_Table_Type'Range -- ^ Filter out invalid reference due to an error -- that has occurred previously in the parsing. and then CD.Arrays_Table (T.Ref).Element_xTyp.TYP = Chars; end Is_Char_Array; procedure Check_any_String_and_promote_to_VString (CD : in out Compiler_Data; X : in out Exact_Subtyp; include_characters : Boolean) is use Compiler.PCode_Emit, PCode; expected_set : Typ_Set := VStrings_Set or Str_Lit_Set or Str_as_VStr_Set or Arrays_Set; begin if include_characters then expected_set := expected_set or Chars_Set; end if; if X.TYP = String_Literals then Emit_Std_Funct (CD, SF_String_Literal_to_VString); elsif Is_Char_Array (CD, X) then Emit_Std_Funct (CD, SF_String_to_VString, Operand_1_Type (CD.Arrays_Table (X.Ref).Array_Size) ); elsif Internally_VString_Set (X.TYP) then null; -- Already a VString. elsif include_characters and then X.TYP = Chars then Emit_Std_Funct (CD, SF_Char_to_VString); else Type_Mismatch (CD, err_parameter_types_do_not_match, Found => X, Expected => expected_set); end if; X.Construct_Root (VStrings); end Check_any_String_and_promote_to_VString; ------------------------------------------------------------------ ------------------------------------------------Locate_Identifier- function Locate_Identifier_Internal (CD : in out Compiler_Data; Id : in Alfa; using_parsed_Id : in Boolean; Prefix_Id : in Alfa; Level : in Defs.Nesting_Level; Fail_when_No_Id : in Boolean; Alias_Resolution : in Boolean; Level_0_Filter : in Boolean; Public_Filter : in Index) return Natural is L : Defs.Nesting_Level'Base; J : Integer := No_Id; ID_Copy : Alfa; is_name_matched : Boolean; dot_pos : Integer; l0_def : Id_Maps.Cursor; use HAT, Id_Maps; trace_search : constant Boolean := False; begin L := Level; if trace_search then Put_Line (+" Start Id search, at level" & L'Image & " for Id = """ & Id & '"'); end if; -- Scan all Id's from level L down to level 0: Scan : loop if L = 0 and then Level_0_Filter then l0_def := CD.CUD.level_0_def.Find (Id); if l0_def /= No_Element then -- Global definition found, within a library package, or in the -- WITH context clauses. -- In this case there is no point doing a tedious linear search :-) . J := Element (l0_def); if trace_search then Put_Line (+" Shortcut! Found global (level 0) definition with value # " & J); end if; exit Scan; end if; end if; J := CD.Blocks_Table (CD.Display (L)).Last_Id_Idx; if trace_search then Put_Line (+" Reset index for level" & L'Image & " with value # " & J); end if; Scan_level_L : loop exit Scan_level_L when J = No_Id; -- Beginning of ID table reached. if CD.id_table (J).entity /= paquetage_body then -- ^ A package body is invisible as a declaration. if CD.id_table (J).entity = paquetage and then Length (Prefix_Id) > 0 and then Prefix_Id = CD.id_table (J).name then -- We have reached the defining package. -- Example: we are looking for HAT.PUT, but we just hit a -- local HAT package's specification. Logically that local HAT -- doesn't contain a PUT item, otherwise we would have found -- it already. -- Other packages with the same name at upper levels are hidden. J := No_Id; exit Scan; end if; dot_pos := Length (CD.pkg_prefix); if dot_pos = 0 then is_name_matched := CD.id_table (J).name = Id; else -- We are within a package declaration. -- Things are a bit more complicated: the package's items -- are visible to the package itself. So we simulate a hidden USE. -- -- Say we are within `Pkg.Child_1.Subpackage_2` declaration. -- For entry `Pkg.Child_1.Subpackage_2.Item` in the identifier -- table, `Item` is visible, as well as `Subpackage_2[.Item]` -- `Child_1[.Subpackage_2[.Item]]`. -- NB : the stuff with [] is resolved at the end of Locate_Identifier_Internal. loop is_name_matched := CD.id_table (J).name = Slice (CD.pkg_prefix, 1, dot_pos) & Id; exit when is_name_matched; exit when dot_pos = 0; loop dot_pos := dot_pos - 1; exit when dot_pos = 0; exit when Element (CD.pkg_prefix, dot_pos) = '.'; end loop; end loop; end if; if trace_search then Put_Line (+" Id search level" & L'Image & "; candidate # " & J & " named " & CD.id_table (J).name & "; matched : " & is_name_matched'Image); end if; if is_name_matched then -- Reasons to consider the matched identifier: -- * Not library-level: we have a local subprogram -- identifier (possibly wrapped in a local package): exit Scan_level_L when L > 0; -- * Filter for library-level definition is disabled: exit Scan_level_L when not Level_0_Filter; -- * Activated library-level definition: exit Scan_level_L when CD.CUD.level_0_def.Contains (CD.id_table (J).name); end if; end if; if trace_search then Put (+" Chained list: identifier index goes from J = " & J); end if; J := CD.id_table (J).link; -- Skip this identifier. if trace_search then Put_Line (+" to J = " & J); end if; end loop Scan_level_L; L := L - 1; -- Decrease nesting level. if trace_search then Put_Line (+" Level decreases to L =" & L'Image); end if; exit Scan when L < 0 or J /= No_Id; end loop Scan; if J = No_Id then if not Fail_when_No_Id then return No_Id; end if; -- Issue an error, severity: major (an exception is raised). ID_Copy := CD.Id_with_case; In_Symbol (CD); if CD.Sy = Finger then Error (CD, err_not_yet_implemented, "positional association", severity => major); else Error (CD, err_undefined_identifier, A2S (ID_Copy), severity => major); end if; end if; -- -- From this point, the identifier ID is matched with -- element J in the identifier table. -- -- Name aliasing resolution (brought by a use clause -- or a simple renames clause): while Alias_Resolution and then CD.id_table (J).entity = alias loop J := Integer (CD.id_table (J).adr_or_sz); -- E.g. True -> Standard.True end loop; if J > Public_Filter then Error (CD, err_non_public_entity, A2S (Id), severity => major); end if; -- Prefixed package resolution: `Pkg.Item`, `Pkg.Child_1.Item`, ... if using_parsed_Id and then CD.id_table (J).entity = paquetage then Skip_Blanks (CD); if CD.CUD.c = '.' then -- We sneak a look at the next symbol. ID_Copy := Id; CD.target.Mark_Reference (J); CD.id_table (J).is_referenced := True; -- Here some parsing: entity is a package and there is a dot waiting. In_Symbol (CD); -- Consume prefix package identifier. Need (CD, Period, err_general_error); -- Accept "Pkg.", reject "Pkg.." if CD.Sy = IDent then return Locate_Identifier_Internal (CD, ID_Copy & '.' & CD.Id, True, ID_Copy, Level, Fail_when_No_Id, Alias_Resolution, Level_0_Filter, CD.Packages_Table (CD.id_table (J).block_or_pkg_ref).last_public_declaration); end if; Error (CD, err_identifier_missing, severity => major); end if; end if; if J /= No_Id then CD.target.Mark_Reference (J); CD.id_table (J).is_referenced := True; end if; if trace_search then Put_Line (+" Found identifier # " & J); end if; return J; end Locate_Identifier_Internal; function Locate_Identifier (CD : in out Compiler_Data; Id : in Alfa; Level : in Defs.Nesting_Level; Fail_when_No_Id : in Boolean := True; Alias_Resolution : in Boolean := True; Level_0_Filter : in Boolean := True; Public_Filter : in Index := Index'Last) return Natural is begin return Locate_Identifier_Internal (CD => CD, Id => Id, using_parsed_Id => False, -- Extra parameter Prefix_Id => Empty_Alfa, -- Extra parameter Level => Level, Fail_when_No_Id => Fail_when_No_Id, Alias_Resolution => Alias_Resolution, Level_0_Filter => Level_0_Filter, Public_Filter => Public_Filter); end Locate_Identifier; function Locate_CD_Id (CD : in out Compiler_Data; Level : in Defs.Nesting_Level; Fail_when_No_Id : in Boolean := True; Alias_Resolution : in Boolean := True; Level_0_Filter : in Boolean := True; Public_Filter : in Index := Index'Last) return Natural is begin if CD.Id_location = No_Id_Cache then CD.Id_location := -- Note that the following call might consume several -- identifiers in the case of, e.g., Pkg_1.Sub_Pkg_2.Item. Locate_Identifier_Internal (CD => CD, Id => CD.Id, -- Here we use the Id just parsed. using_parsed_Id => True, -- Extra parameter Prefix_Id => Empty_Alfa, -- Extra parameter Level => Level, Fail_when_No_Id => Fail_when_No_Id, Alias_Resolution => Alias_Resolution, Level_0_Filter => Level_0_Filter, Public_Filter => Public_Filter); else -- In some cases, the same identifier token, at the same location in -- source text, is parsed twice or more times. -- Example: -- "for i in some_array'Range loop": some_array is checked for -- begin a subtype (in Static_Subtype_Indication) then for being -- a variable (in Simple_Expression). Finally, a pair of values -- are detected via the 'Range attribute. null; end if; return CD.Id_location; end Locate_CD_Id; procedure Check_Duplicate_Specification (CD : in out Compiler_Data; old_id_idx : Natural; id_current : Alfa) is begin if old_id_idx = No_Id then return; -- First occurrence of the specification. end if; Error (CD, err_duplicate_identifier, "specification of " & A2S (id_current), severity => major); end Check_Duplicate_Specification; procedure Check_Subprogram_Spec_Body_Consistency (CD : in out Compiler_Data; old_id_idx : Natural; new_id_idx : Natural; id_current : Alfa) is sub_sub_last_param_idx, forward_last_param_idx, sub_sub_params, forward_params : Natural; use type Alfa; procedure Check_Formal_Parameter_List is procedure Check_One_to_One (prefix : String; is_identical : Boolean; topic : String) is begin if not is_identical then Error (CD, err_spec_body_mismatch, prefix & " has a different " & topic, severity => major); -- This raises an exception. end if; end Check_One_to_One; procedure Check_Parameter_One_to_One (count : Positive; is_identical : Boolean; topic : String) is begin Check_One_to_One ("parameter #" & count'Image, is_identical, topic); end Check_Parameter_One_to_One; version_1, version_2 : Natural; begin version_1 := old_id_idx + 1; version_2 := new_id_idx + 1; for count in 1 .. sub_sub_params loop Check_Parameter_One_to_One (count, CD.id_table (version_1).name = CD.id_table (version_2).name, "name"); Check_Parameter_One_to_One (count, CD.id_table (version_1).xtyp = CD.id_table (version_2).xtyp, "type"); Check_Parameter_One_to_One (count, CD.id_table (version_1).decl_kind = CD.id_table (version_2).decl_kind, "mode"); version_1 := version_1 + 1; version_2 := version_2 + 1; end loop; if CD.id_table (new_id_idx).entity = funktion then Check_One_to_One ("result of function", CD.id_table (new_id_idx).xtyp = CD.id_table (old_id_idx).xtyp, "type"); end if; end Check_Formal_Parameter_List; begin if old_id_idx = No_Id then return; end if; CD.id_table (old_id_idx).decl_kind := spec_resolved; -- The following is only for making the compiler dump -- easier to understand: CD.Blocks_Table (CD.id_table (old_id_idx).block_or_pkg_ref).Id := S2A ("Unused (was from a subprogram spec)"); -- Check that the formal parameter list is identical: sub_sub_last_param_idx := CD.Blocks_Table (CD.id_table (new_id_idx).block_or_pkg_ref).Last_Param_Id_Idx; forward_last_param_idx := CD.Blocks_Table (CD.id_table (old_id_idx).block_or_pkg_ref).Last_Param_Id_Idx; sub_sub_params := sub_sub_last_param_idx - new_id_idx; forward_params := forward_last_param_idx - old_id_idx; if sub_sub_params > forward_params then Error (CD, err_number_of_parameters_do_not_match, ": specification of " & A2S (id_current) & " has less parameters", severity => major); elsif sub_sub_params < forward_params then Error (CD, err_number_of_parameters_do_not_match, ": specification of " & A2S (id_current) & " has more parameters", severity => major); else Check_Formal_Parameter_List; end if; end Check_Subprogram_Spec_Body_Consistency; procedure Link_Forward_Declaration (CD : in out Compiler_Data; old_id_idx : Positive; new_id_idx : Positive) is begin -- Clone key information at the new id's index (the body) -- onto the data at old id's index (the specification): -- * Subprogram's machine code address -- * The block_ref (hence, the correct VSize -- is used for reserving the stack) -- CD.id_table (old_id_idx).adr_or_sz := CD.id_table (new_id_idx).adr_or_sz; CD.id_table (old_id_idx).block_or_pkg_ref := CD.id_table (new_id_idx).block_or_pkg_ref; -- -- The linking is done! -- CD.target.Mark_Spec_Body_Cross_References (spec_id => old_id_idx, body_id => new_id_idx); end Link_Forward_Declaration; procedure Check_Incomplete_Definitions (CD : in out Co_Defs.Compiler_Data; level : Defs.Nesting_Level) is id_index : Integer := CD.Blocks_Table (CD.Display (level)).Last_Id_Idx; begin -- Follow the chain of identifiers for given Level: while id_index /= No_Id loop if CD.id_table (id_index).decl_kind = spec_unresolved and then CD.id_table (id_index).entity /= entree then Error (CD, err_incomplete_declaration, A2S (CD.id_table (id_index).name_with_case)); end if; id_index := CD.id_table (id_index).link; end loop; end Check_Incomplete_Definitions; function Nice_Image (item : Identifier_Table_Entry) return String is ((if item.decl_kind in Parameter_Kind then "parameter" else (case item.entity is when variable_object => "variable", when constant_object => "constant", when type_mark => "type", when prozedure => "procedure", when funktion => "function", when paquetage => "package", when tache => "task", when others => "item")) & " """ & A2S (item.name_with_case) & '"'); procedure Mark_Read_and_Check_Read_before_Written (CD : in out Compiler_Data; context : in Flow_Context; item : in out Identifier_Table_Entry) is begin -- This is for the variable's overall lifetime analysis: -- Elevate_to_Maybe_or_Yes (item.is_read, context); if item.is_written_after_init = no -- Not overwritten in a subprogram, nor in the above statements. and then item.is_initialized = none -- Not initialized, even implicitly. and then context.level = item.lev -- Not a within subprogram (uncertainty since call sequence is unknown). then -- By following the top-down flow, we notice that the variable or parameter -- was never written until this point, including in any nested subprogram. -- Remark (CD, warn_read_but_not_written, Nice_Image (item) & (if context.is_in_cond_within_loop then -- We are within a condition, itself within a loop. -- Then, we cannot be not sure that the expression is -- evaluated in the first iteration of all loops. " may be" else -- We are sure that the expression is evaluated -- at the first iteration of all loops (if any). " is") & " read before it is ever written"); end if; end Mark_Read_and_Check_Read_before_Written; function Has_Dummy_Name (name : Alfa) return Boolean is (HAT.Starts_With (name, "DUMMY") or else HAT.Starts_With (name, "UNUSED") or else HAT.Starts_With (name, "JUNK") or else HAT.Starts_With (name, "IGNORE")); procedure Check_Unused_or_Uninitialized_Items (CD : in out Compiler_Data; level : in Defs.Nesting_Level) is procedure Check_Item (item : Identifier_Table_Entry) is already_insulted : Natural := 0; procedure Remark_for_Declared_Item (diag : Compile_Diagnostic; text : String) is remark_made : Boolean; begin if already_insulted < 2 then Remark (CD, diag, text, location_method => explicit, explicit_location => item.location, remark_made => remark_made); -- if remark_made then already_insulted := already_insulted + 1; end if; end if; end Remark_for_Declared_Item; procedure Handle_Variables_and_Parameters is begin case item.is_written_after_init is when no => -- Not written. case item.is_initialized is when none => if item.is_read = no and then item.decl_kind /= param_out then -- Neither read, not written, nor initialized, and not an "out" parameter. -- Issue no warning. The note "-ru" will catch the item as unused. null; else -- Neither written, nor initialized, but is maybe or surely read, -- or is an "out" parameter. Remark_for_Declared_Item (warn_read_but_not_written, Nice_Image (item) & (case item.is_read is when no => " is never written", -- Case reached for an "out" parameter. when maybe => " is never written, but is possibly read", when yes => " is read but never written") & ""); end if; when explicit => Remark_for_Declared_Item (note_constant_variable, Nice_Image (item) & " is not modified, could be declared constant"); when implicit => -- Implicitly initialized -> we don't care. null; end case; when maybe .. yes => if item.is_read = no -- Maybe written after init., but not read. and then item.decl_kind /= param_out -- Don't care about "out" param no being read. and then not Has_Dummy_Name (item.name) then Remark_for_Declared_Item (note_unused_item, Nice_Image (item) & " is never read"); end if; end case; end Handle_Variables_and_Parameters; procedure Handle_Unused is begin -- Here we can have any explicit declaration -- (object, type, subprogram, ...) Remark_for_Declared_Item (note_unused_item, Nice_Image (item) & " is not referenced"); end Handle_Unused; use type Alfa; begin if item.name = Empty_Alfa then -- Zombie item, for instance a loop parameter. return; end if; -- See table in "hac_work.xls", sheet "Remarks". if item.entity = variable_object then Handle_Variables_and_Parameters; end if; if item.is_referenced or else item.entity in loop_identifier | alias then -- Item is used somewhere, or is a loop identifier or an alias. -- In this case, don't make a note for it. null; else Handle_Unused; end if; end Check_Item; id_index : Integer := CD.Blocks_Table (CD.Display (level)).Last_Id_Idx; begin -- Follow the chain of identifiers for given Level: while id_index /= No_Id loop Check_Item (CD.id_table (id_index)); id_index := CD.id_table (id_index).link; end loop; end Check_Unused_or_Uninitialized_Items; function Number_of_Parameters (CD : in out Compiler_Data; id_idx : in Natural) return Natural is id_table_entry : Identifier_Table_Entry renames CD.id_table (id_idx); block_idx : constant Integer := id_table_entry.block_or_pkg_ref; begin pragma Assert (id_table_entry.entity in prozedure | funktion); declare block : Block_Table_Entry renames CD.Blocks_Table (block_idx); begin return (if block.First_Param_Id_Idx > block.Last_Param_Id_Idx then 0 else block.Last_Param_Id_Idx - block.First_Param_Id_Idx + 1); end; end Number_of_Parameters; end HAC_Sys.Parser.Helpers; ================================================ FILE: src/compile/hac_sys-parser-helpers.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- package HAC_Sys.Parser.Helpers is use Co_Defs, Defs; ---------------------- -- Symbol testing -- ---------------------- -- If needed symbol S is correct, consume it; -- otherwise output error code E. -- -- Optionally, we consume a symbol Forgive that -- the programmer may have written instead of S. -- For instance '[' instead of '('. -- procedure Need (CD : in out Compiler_Data; S : Symbol; E : Compile_Diagnostic; Forgive : Symbol := Dummy_Symbol); -- Issue error N, then skip all subsequent symbols -- that are not in the FSys set. -- procedure Error_then_Skip (CD : in out Compiler_Data; FSys : Symset; N : Compile_Diagnostic; hint : String := ""); -- Issue error N, then skip all subsequent symbols -- that are not equal to S. -- procedure Error_then_Skip (CD : in out Compiler_Data; S : Symbol; N : Compile_Diagnostic; hint : String := ""); -- Test if current symbol is in the S1 set, otherwise -- issue error N. If stop_on_error = False, we skip -- subsequent symbols that are not in the union (S1 + S2). -- procedure Test (CD : in out Compiler_Data; S1, S2 : Symset; N : Compile_Diagnostic; stop_on_error : Boolean := False); procedure Need_Semicolon_after_Declaration (CD : in out Compiler_Data; FSys : Symset); procedure Need_END_Symbol (CD : in out Compiler_Data); procedure Ignore_Extra_Semicolons (CD : in out Compiler_Data); procedure Need_Semicolon (CD : in out Compiler_Data); ----------------------------------- -- Data type checks and errors -- ----------------------------------- procedure Check_Boolean (CD : in out Compiler_Data; T : Typen); procedure Check_Integer (CD : in out Compiler_Data; T : Typen); procedure Argument_Type_Not_Supported (CD : in out Compiler_Data); function Nice_Exact_Image (CD : Compiler_Data; xT : Exact_Typ'Class) return String; procedure Type_Mismatch (CD : in out Compiler_Data; Err : Compile_Diagnostic; Found, Expected : Exact_Typ'Class); procedure Type_Mismatch (CD : in out Compiler_Data; Err : Compile_Diagnostic; Found : Exact_Subtyp; Expected : Typ_Set); function Op_Hint (OP : Symbol) return String; procedure Issue_Undefined_Operator_Error -- Unary (CD : in out Compiler_Data; Operator : Symbol; Right : Exact_Subtyp); procedure Issue_Undefined_Operator_Error -- Binary (CD : in out Compiler_Data; Operator : Symbol; Left, Right : Exact_Subtyp); -- https://en.wikipedia.org/wiki/Type_conversion#Implicit_type_conversion -- One of the most useful feature of Ada is the absence of type coercion. -- Note from the Python 2.5 doc: -- "In Python 3.0, coercion will not be supported." -- procedure Forbid_Type_Coercion (CD : in out Compiler_Data; Operator : Symbol; Left, Right : Exact_Subtyp); procedure Forbid_Type_Coercion (CD : in out Compiler_Data; Found, Expected : Exact_Subtyp); ------------------------------------ -- Symbol sets used for parsing -- ------------------------------------ -- Singletons: function Singleton (s : Symbol) return Symset; -- Specific singletons: Becomes_Set : constant Symset := (Becomes => True, others => False); Colon_Set : constant Symset := (Colon => True, others => False); END_Set : constant Symset := (END_Symbol => True, others => False); IDent_Set : constant Symset := (IDent => True, others => False); RParent_Set : constant Symset := (RParent => True, others => False); Semicolon_Set : constant Symset := (Semicolon => True, others => False); -- Specific sets: Alt_Finger_THEN : constant Symset := -- For "WHEN" in CASE statements ("THEN" is wrong, -- but that error is processed specifically). (Alt | Finger | THEN_Symbol => True, others => False); Becomes_Comma_IDent_Semicolon : constant Symset := (Semicolon | Comma | IDent | Becomes => True, others => False); Becomes_EQL_Semicolon : constant Symset := (Becomes | EQL | Semicolon => True, others => False); Becomes_EQL : constant Symset := (Becomes | EQL => True, others => False); Colon_Comma_LParent_RParent_Semicolon : constant Symset := (Colon | Comma | LParent | RParent | Semicolon => True, others => False); Colon_Comma_RParent : constant Symset := (Colon | Comma | RParent => True, others => False); Colon_Comma_IS_OF : constant Symset := (Colon | Comma | IS_Symbol | OF_Symbol => True, others => False); Comma_END_IDent_Semicolon : constant Symset := (Comma | END_Symbol | IDent | Semicolon => True, others => False); Comma_IDent_Semicolon : constant Symset := (Comma | IDent | Semicolon => True, others => False); Comma_IDent_RParent_Semicolon : constant Symset := (Comma | IDent | RParent | Semicolon => True, others => False); Comma_OF_RParent : constant Symset := (Comma | RParent | OF_Symbol => True, others => False); Comma_RParent : constant Symset := (Comma | RParent => True, others => False); DO_LOOP : constant Symset := (DO_Symbol | LOOP_Symbol => True, others => False); DO_THEN : constant Symset := (DO_Symbol | THEN_Symbol => True, others => False); ELSE_ELSIF_END : constant Symset := (ELSE_Symbol | ELSIF_Symbol | END_Symbol => True, others => False); ELSE_END_OR : constant Symset := (ELSE_Symbol | END_Symbol | OR_Symbol => True, others => False); ELSE_OR : constant Symset := (ELSE_Symbol | OR_Symbol => True, others => False); END_IDent_Semicolon : constant Symset := (END_Symbol | IDent | Semicolon => True, others => False); END_LOOP_RANGE_Double_Dot : constant Symset := (END_Symbol | LOOP_Symbol | Range_Double_Dot_Symbol => True, others => False); END_LOOP_Semicolon : constant Symset := (END_Symbol | LOOP_Symbol | Semicolon => True, others => False); END_WHEN : constant Symset := (END_Symbol | WHEN_Symbol => True, others => False); OF_RANGE_Double_Dot_RParent : constant Symset := (OF_Symbol | Range_Double_Dot_Symbol | RParent => True, others => False); -- Other sets, named by their context: After_Subprogram_Parameters : constant Symset := (IS_Symbol | RETURN_Symbol | Semicolon | WITH_Symbol => True, others => False); Block_Begin_Symbol : constant Symset := (PROCEDURE_Symbol | FUNCTION_Symbol | TASK_Symbol | ENTRY_Symbol | BEGIN_Symbol | DECLARE_Symbol => True, others => False); Constant_Definition_Begin_Symbol : constant Symset := (Plus | Minus | integer_literal | real_literal | character_literal | IDent => True, others => False); Declaration_X_Subprogram_Symbol : constant Symset := (IDent | PACKAGE_Symbol | SUBTYPE_Symbol | TYPE_Symbol | TASK_Symbol | USE_Symbol => True, others => False); Declaration_Symbol : constant Symset := Declaration_X_Subprogram_Symbol + (PROCEDURE_Symbol | FUNCTION_Symbol => True, others => False); Primary_Begin_Symbol : constant Symset := (integer_literal | real_literal | character_literal | string_literal | IDent | LParent => True, others => False); Fail_after_FOR : constant Symset := (IN_Symbol | Range_Double_Dot_Symbol | LOOP_Symbol | END_Symbol => True, others => False); Plus_Minus_Set : constant Symset := (Plus_Minus => True, others => False); Selector_Symbol : constant Symset := (LParent | Period => True, others => False); Selector_Symbol_Loose : constant Symset := (LBrack | LParent | Period => True, others => False); Statement_Begin_Symbol : constant Symset := (IDent | BEGIN_Symbol | DECLARE_Symbol | IF_Symbol | WHILE_Symbol | LOOP_Symbol | FOR_Symbol | CASE_Symbol | EXIT_Symbol | NULL_Symbol | RETURN_Symbol | SELECT_Symbol | ACCEPT_Symbol | DELAY_Symbol => True, others => False); Symbols_after_Subprogram_Identifier : constant Symset := (LParent | RETURN_Symbol | IS_Symbol | Semicolon | WITH_Symbol -- Aspect => True, others => False); Type_Begin_Symbol : constant Symset := (ABSTRACT_Symbol | ACCESS_Symbol | ARRAY_Symbol | DIGITS_Symbol | DELTA_Symbol | INTERFACE_Symbol | LIMITED_Symbol | NOT_Symbol | -- For "not null" (null_exclusion) NEW_Symbol | PRIVATE_Symbol | PROTECTED_Symbol | RANGE_Keyword_Symbol | RECORD_Symbol | SYNCHRONIZED_Symbol | TASK_Symbol | TAGGED_Symbol | LParent => True, others => False); Subtype_Begin_Symbol : constant Symset := (IDent | NOT_Symbol => True, -- For "not null" (null_exclusion) others => False); ------------------ -- Types sets -- ------------------ function Singleton (t : Typen) return Typ_Set with Inline; Numeric_Typ_Set : constant Typ_Set := (Numeric_Typ => True, others => False); Bools_Set : constant Typ_Set := (Bools => True, others => False); Chars_Set : constant Typ_Set := (Chars => True, others => False); Ints_Set : constant Typ_Set := (Ints => True, others => False); Floats_Set : constant Typ_Set := (Floats => True, others => False); Arrays_Set : constant Typ_Set := (Arrays => True, others => False); VStrings_Set : constant Typ_Set := (VStrings => True, others => False); Times_Set : constant Typ_Set := (Times => True, others => False); Durations_Set : constant Typ_Set := (Durations => True, others => False); Text_Files_Set : constant Typ_Set := (Text_Files => True, others => False); Str_Lit_Set : constant Typ_Set := (String_Literals => True, others => False); Str_as_VStr_Set : constant Typ_Set := (Strings_as_VStrings => True, others => False); Standard_Set : constant Typ_Set := (Standard_Typ => True, others => False); PCode_Atomic_Comparable_Typ : constant Typ_Set := Discrete_Typ or Numeric_Typ_Set or VStrings_Set; PCode_Atomic_Nonlimited_Typ : constant Typ_Set := (Standard_Set or Discrete_Typ) and not Text_Files_Set; Text_IO_Get_Item_Set : constant Typ_Set := (Standard_Set and not Bools_Set) or Arrays_Set; -- RM 3.2 (3): Scalar_Set : constant Typ_Set := (Ints | Floats | Durations | Chars | Bools | Enums => True, others => False); Internally_VString_Set : constant Typ_Set := VStrings_Set or Str_as_VStr_Set; ------------------ -- Base types -- ------------------ Standard_Integer : constant Exact_Subtyp := (Ints, 0, False, HAC_Integer'First, HAC_Integer'Last); ------------- -- Misc. -- ------------- -- Check if we have an "array of Character", for instance a String. -- function Is_Char_Array (CD : Compiler_Data; T : Exact_Subtyp) return Boolean; -- Convert a string of any kind sitting on stack top to VString. procedure Check_any_String_and_promote_to_VString (CD : in out Compiler_Data; X : in out Exact_Subtyp; include_characters : Boolean); ------------------------------------------------------------------ ------------------------------------------------Locate_Identifier- -- -- - Aliases are resolved (True -> Standard.True). -- - Parsing continues on each "package_name.": e.g. on "Pkg.", -- parser will parse "Pkg.Child_Pkg.Sub_pkg.Var.X" until the -- non-package entity: "Var". -- function Locate_Identifier (CD : in out Compiler_Data; Id : in Alfa; Level : in Defs.Nesting_Level; Fail_when_No_Id : in Boolean := True; Alias_Resolution : in Boolean := True; Level_0_Filter : in Boolean := True; Public_Filter : in Index := Index'Last) return Natural; function Locate_CD_Id (CD : in out Compiler_Data; Level : in Defs.Nesting_Level; Fail_when_No_Id : in Boolean := True; Alias_Resolution : in Boolean := True; Level_0_Filter : in Boolean := True; Public_Filter : in Index := Index'Last) return Natural; procedure Check_Duplicate_Specification (CD : in out Compiler_Data; old_id_idx : Natural; id_current : Alfa); procedure Check_Subprogram_Spec_Body_Consistency (CD : in out Compiler_Data; old_id_idx : Natural; new_id_idx : Natural; id_current : Alfa); procedure Link_Forward_Declaration (CD : in out Compiler_Data; old_id_idx : Positive; new_id_idx : Positive); procedure Check_Incomplete_Definitions (CD : in out Co_Defs.Compiler_Data; level : Defs.Nesting_Level); -- Check initialization of a variable or parameter -- when read in an expression. -- procedure Mark_Read_and_Check_Read_before_Written (CD : in out Compiler_Data; context : in Flow_Context; item : in out Identifier_Table_Entry); -- Check usage of variables and parameters -- after the last statement. -- procedure Check_Unused_or_Uninitialized_Items (CD : in out Compiler_Data; level : in Defs.Nesting_Level); function Number_of_Parameters (CD : in out Compiler_Data; id_idx : in Natural) return Natural; end HAC_Sys.Parser.Helpers; ================================================ FILE: src/compile/hac_sys-parser-modularity.adb ================================================ with HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Packages, HAC_Sys.Scanner, HAC_Sys.Errors; package body HAC_Sys.Parser.Modularity is procedure With_Clause -- 10.1.2 (4) (CD : in out Co_Defs.Compiler_Data; LD : in out Librarian.Library_Data) is use Defs, Scanner, Errors; begin In_Symbol (CD); -- Consume "with". loop if CD.Sy /= IDent then Error (CD, err_identifier_missing, severity => major); end if; -- -- TBD: parse '.' for child units, like Locate_Identifier_Internal -- with `using_parsed_Id` = True -- Librarian.Apply_WITH (CD, LD, A2S (CD.Id)); In_Symbol (CD); -- Consume the identifier. exit when CD.Sy = Semicolon; Helpers.Need (CD, Comma, err_general_error); end loop; In_Symbol (CD); -- Consume the ';'. end With_Clause; procedure Context_Clause (CD : in out Co_Defs.Compiler_Data; LD : in out Librarian.Library_Data) is use Defs, Librarian; begin loop case CD.Sy is when WITH_Symbol => With_Clause (CD, LD); when USE_Symbol => Packages.Use_Clause (CD, Library_Level, False); when others => exit; end case; end loop; end Context_Clause; end HAC_Sys.Parser.Modularity; ================================================ FILE: src/compile/hac_sys-parser-modularity.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Librarian; package HAC_Sys.Parser.Modularity is -- Context clause, 10.1.2. -- -- Parse the bunch of "with" and "use" before a library level -- unit (which can be a subprogram or a package). -- Referenced units (specifications or body-only) are compiled if -- necessary, or reactivated as library level definitions. -- procedure Context_Clause (CD : in out Co_Defs.Compiler_Data; LD : in out Librarian.Library_Data); end HAC_Sys.Parser.Modularity; ================================================ FILE: src/compile/hac_sys-parser-packages.adb ================================================ with HAC_Sys.Errors, HAC_Sys.Parser.Const_Var, HAC_Sys.Parser.Enter_Def, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Tasking, HAC_Sys.Parser.Type_Def, HAC_Sys.Scanner; with HAT; package body HAC_Sys.Parser.Packages is --------------------------- -- Package_Declaration -- --------------------------- procedure Package_Declaration ( CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; block_data : in out Block_Data_Type; needs_body : out Boolean ) is use Co_Defs, Defs, Errors, HAT, Helpers; use type HAC_Integer; package_name : constant Alfa := CD.Id; package_name_with_case : constant Alfa := CD.Id_with_case; package_id_index : constant Natural := CD.Id_Count; previous_pkg_prefix : constant VString := CD.pkg_prefix; subpkg_needs_body : Boolean; in_private : Boolean := False; dummy_forward : Natural; current_pkg_table_index : Positive; subprogram_kind : Declaration_Kind; -- procedure Mark_Last_Declaration is begin if CD.Id_Count > package_id_index then if in_private then CD.Packages_Table (current_pkg_table_index).last_private_declaration := CD.Id_Count; else CD.Packages_Table (current_pkg_table_index).last_public_declaration := CD.Id_Count; end if; end if; end Mark_Last_Declaration; -- begin Feed_Packages_Table (CD); -- CD.Packages_Count can be incremented further during -- this procedure due to subpackages, so we need to memorize it. current_pkg_table_index := CD.Packages_Count; -- Scanner.In_Symbol (CD); -- Absorb the identifier symbol. !! We need more for child packages. Need (CD, IS_Symbol, err_IS_missing); -- Set new prefix, support also possible subpackages: CD.pkg_prefix := CD.pkg_prefix & A2S (package_name) & '.'; Increment_Nesting_or_Descending_Level (CD); needs_body := False; loop Test ( CD, Declaration_Symbol + END_Symbol + PRIVATE_Symbol, empty_symset, err_incorrectly_used_symbol, stop_on_error => True -- Exception is raised there if there is an error. ); case CD.Sy is when IDent => if block_data.context.level = 0 then Error (CD, err_not_yet_implemented, "variables and constants in packages at library level", severity => major); end if; Const_Var.Var_Declaration (CD, FSys, block_data); Mark_Last_Declaration; when TYPE_Symbol | SUBTYPE_Symbol => Type_Def.Type_or_Subtype_Declaration (CD, block_data.context.level, FSys + END_Symbol); Mark_Last_Declaration; when TASK_Symbol => Tasking.Task_Declaration (CD, FSys, block_data.context.level); Mark_Last_Declaration; when USE_Symbol => Use_Clause (CD, block_data.context.level, True); when PROCEDURE_Symbol | FUNCTION_Symbol => Subprogram_Declaration_or_Body (CD, FSys, block_data.context.level, subprogram_kind); if subprogram_kind = complete then Error (CD, err_general_error, "subprogram body not allowed in package specification", severity => major); end if; if block_data.context.level = 0 then Scanner.In_Symbol (CD); -- Consume ';' symbol after END [Subprogram_Id]. end if; needs_body := True; Mark_Last_Declaration; when PACKAGE_Symbol => -- Subpackage: Scanner.In_Symbol (CD); case CD.Sy is when BODY_Symbol => Error (CD, err_general_error, "subpackage body not allowed in package specification", severity => major); when IDent => null; -- Good! when others => Error (CD, err_identifier_missing, severity => major); end case; Enter_Def.Enter_Prefixed (CD, block_data.context.level, CD.Id, CD.Id_with_case, paquetage, dummy_forward); CD.id_table (CD.Id_Count).decl_kind := spec_resolved; -- Why spec_resolved ? missing bodies for possible suprograms -- in that package are checked anyway. Package_Declaration (CD, FSys, block_data, subpkg_needs_body); Need_Semicolon_after_Declaration (CD, FSys); needs_body := needs_body or subpkg_needs_body; Mark_Last_Declaration; when PRIVATE_Symbol => Scanner.In_Symbol (CD); if in_private then Error (CD, err_general_error, "only one private part allowed per package"); end if; in_private := True; when others => null; end case; exit when CD.Sy = END_Symbol; end loop; Scanner.In_Symbol (CD); -- Absorb END symbol if CD.Sy = IDent then -- !! For supporting child package names ("x.y.z"), reuse/share Check_ident_after_END if CD.Id /= package_name then Error (CD, err_incorrect_name_after_END, hint_1 => A2S (package_name_with_case), severity => minor ); end if; Scanner.In_Symbol (CD); -- Absorb identifier symbol end if; -- Test semicolon but don't absorb it (we might be at the end of the stream). Test (CD, Semicolon_Set, empty_symset, err_incorrectly_used_symbol, stop_on_error => True); -- Exception is raised there if there is an error. CD.pkg_prefix := previous_pkg_prefix; Decrement_Nesting_or_Descending_Level (CD); end Package_Declaration; -------------------- -- Package_Body -- -------------------- procedure Package_Body ( CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; block_data : in out Block_Data_Type ) is use Co_Defs, Defs, Errors, HAT, Helpers; use type HAC_Integer; package_name : constant Alfa := CD.Id; package_name_with_case : constant Alfa := CD.Id_with_case; previous_pkg_prefix : constant VString := CD.pkg_prefix; -- last_id : constant Defs.Index := CD.Blocks_Table (CD.Display (block_data.context.level)).Last_Id_Idx; -- subprogram_kind : Declaration_Kind; pkg_spec_index : Natural; subpkg_needs_body, subpackage_body : Boolean; subpkg_kind : Entity_Kind; begin Scanner.In_Symbol (CD); -- Absorb the identifier symbol. !! We need more for child packages. Need (CD, IS_Symbol, err_IS_missing); CD.pkg_prefix := CD.pkg_prefix & A2S (package_name) & '.'; Increment_Nesting_or_Descending_Level (CD); loop Test ( CD, Declaration_Symbol + BEGIN_Symbol + END_Symbol + PRIVATE_Symbol, empty_symset, err_incorrectly_used_symbol, stop_on_error => True -- Exception is raised there if there is an error. ); case CD.Sy is when IDent => if block_data.context.level = 0 then Error (CD, err_not_yet_implemented, "variables and constants in packages at library level", severity => major); end if; Const_Var.Var_Declaration (CD, FSys, block_data); when TYPE_Symbol | SUBTYPE_Symbol => Type_Def.Type_or_Subtype_Declaration (CD, block_data.context.level, FSys + END_Symbol); when TASK_Symbol => Tasking.Task_Declaration (CD, FSys, block_data.context.level); when USE_Symbol => Use_Clause (CD, block_data.context.level, False); when PROCEDURE_Symbol | FUNCTION_Symbol => Subprogram_Declaration_or_Body (CD, FSys, block_data.context.level, subprogram_kind); if block_data.context.level = 0 then Scanner.In_Symbol (CD); -- Consume ';' symbol after END [Subprogram_Id]. end if; when PACKAGE_Symbol => -- Subpackage inside a package body. -- Subpackage can be spec & body, or just a spec, or the body of -- a spec defined in the parent package... Scanner.In_Symbol (CD); subpackage_body := False; subpkg_kind := paquetage; if CD.Sy = BODY_Symbol then Scanner.In_Symbol (CD); subpackage_body := True; subpkg_kind := paquetage_body; end if; if CD.Sy /= IDent then Error (CD, err_identifier_missing, severity => major); end if; Enter_Def.Enter_Prefixed (CD, block_data.context.level, CD.Id, CD.Id_with_case, subpkg_kind, pkg_spec_index); if subpackage_body then if pkg_spec_index = No_Id then Error (CD, err_general_error, "missing specification for package body", severity => major); end if; CD.id_table (CD.Id_Count).block_or_pkg_ref := CD.id_table (pkg_spec_index).block_or_pkg_ref; Package_Body (CD, FSys, block_data); else CD.id_table (CD.Id_Count).decl_kind := spec_resolved; -- Why spec_resolved ? missing bodies for possible suprograms -- in that package are checked anyway. Package_Declaration (CD, FSys, block_data, subpkg_needs_body); end if; -- !! Do something with subpkg_needs_body ... Need_Semicolon_after_Declaration (CD, FSys); when PRIVATE_Symbol => Error (CD, err_general_error, """private"" belongs to specification"); Scanner.In_Symbol (CD); when others => null; end case; exit when CD.Sy = BEGIN_Symbol or CD.Sy = END_Symbol; end loop; if CD.Sy = BEGIN_Symbol then Error (CD, err_not_yet_implemented, "initialisation part in packages", severity => major); end if; Scanner.In_Symbol (CD); -- Absorb END symbol if CD.Sy = IDent then -- !! For supporting child package names ("x.y.z"), reuse/share Check_ident_after_END if CD.Id /= package_name then Error (CD, err_incorrect_name_after_END, hint_1 => A2S (package_name_with_case), severity => minor ); end if; Scanner.In_Symbol (CD); -- Absorb identifier symbol end if; -- Test semicolon but don't absorb it (we might be at the end of the stream). Test (CD, Semicolon_Set, empty_symset, err_incorrectly_used_symbol, stop_on_error => True); -- Exception is raised there if there is an error. CD.pkg_prefix := previous_pkg_prefix; -- Make body's declarations unreachable in identifier chain. CD.Blocks_Table (CD.Display (block_data.context.level)).Last_Id_Idx := last_id; Decrement_Nesting_or_Descending_Level (CD); end Package_Body; procedure Use_Clause (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; prefixed : Boolean) is -- 8.4 (2) use Defs, Scanner, Errors; begin In_Symbol (CD); -- Consume "use". loop if CD.Sy /= IDent then Error (CD, err_identifier_missing, severity => major); end if; Apply_USE_Clause (CD, Level, prefixed, Helpers.Locate_CD_Id (CD, Level)); In_Symbol (CD); -- Consume the identifier. exit when CD.Sy = Semicolon; Helpers.Need (CD, Comma, err_general_error); end loop; In_Symbol (CD); -- Consume the ';'. end Use_Clause; procedure Apply_USE_Clause (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; prefixed : Boolean; Pkg_Idx : in Natural) -- Index in the identifier table for USEd package. is use Co_Defs, Defs, Parser.Enter_Def, Errors; use type Nesting_Level; Pkg_UName : constant String := A2S (CD.id_table (Pkg_Idx).name); Id_Alias, dummy_id_idx : Natural; pkg_table_index : Positive; pkg_level : Nesting_Level; -- procedure Issue_Duplicate_Use_Note is begin if Pkg_UName = "STANDARD" then -- For a unit's body, a "USE Standard" is applied while it -- was already applied for its spec (so it is superfluous). -- We still choose to do the USE because some unit bodies -- may not have a spec. null; else Remark (CD, note_redundant_construct, """use"" clause already applied, in same declarative part, for" & " package """ & A2S (CD.id_table (Pkg_Idx).name_with_case) & '"'); end if; end Issue_Duplicate_Use_Note; begin pragma Assert (Pkg_Idx > No_Id); if CD.id_table (Pkg_Idx).entity /= paquetage then Error (CD, err_general_error, "package name expected", severity => major); end if; if CD.id_table (Pkg_Idx).lev = 0 and then Pkg_UName = HAT_Name then -- We are USE-ing the HAT package, thus opening the visibility of operators. CD.CUD.Use_HAT_Stack (CD.CUD.use_hat_stack_top) := True; end if; pkg_level := CD.id_table (Pkg_Idx).lev; -- The package specification's definitions begins immediately after the -- package's identifier. -- E.g. HAT: PAQUETAGE; HAT.File_Type: TYPEMARK; ... -- pkg_table_index := CD.id_table (Pkg_Idx).block_or_pkg_ref; -- for i in CD.Packages_Table (pkg_table_index).first_public_declaration .. CD.Packages_Table (pkg_table_index).last_public_declaration loop if CD.id_table (i).lev = pkg_level then -- Subprogram parameters are not declarations of -- the package and have a higher nesting level. declare Full_UName : constant String := A2S (CD.id_table (i).name); Full_Name : String (Full_UName'Range); Start : Positive; begin -- We have spotted an item with the correct prefix. -- E.g. "STANDARD.FALSE" has the matching prefix "STANDARD.", -- or we have the item "ADA.STRINGS.FIXED.INDEX" and -- the prefix "ADA.STRINGS.FIXED.". Start := Full_UName'First + Pkg_UName'Length + 1; Full_Name := A2S (CD.id_table (i).name_with_case); declare Short_Id_str : constant String := Full_UName (Start .. Full_UName'Last); Short_Id : constant Alfa := S2A (Short_Id_str); -- Id as visible after USE. begin -- Check if there is already this identifier, even as -- a library level invisible definition. -- If not, we do a "FROM Pkg IMPORT Short_Id" as you -- would do in Modula-2 or Python. Id_Alias := Parser.Helpers.Locate_Identifier (CD => CD, Id => Short_Id, Level => Level, Fail_when_No_Id => False, Alias_Resolution => False, Level_0_Filter => False); -- ^ We search any matching name, including an inactive -- name at library level. if Id_Alias = No_Id or else CD.id_table (Id_Alias).lev < Level then -- Name was not found, or was defined at a lower nesting level. -- We enter, e.g. the "FALSE", "False" pair. Enter (CD, Level, prefixed, Short_Id, S2A (Full_Name (Start .. Full_Name'Last)), alias, dummy_id_idx); CD.id_table (CD.Id_Count).adr_or_sz := HAC_Integer (i); -- ^ i = Aliased entity's index. else -- Here we have found an identical and -- visible short identifier at the same level. if CD.id_table (Id_Alias).entity = alias and then CD.id_table (Id_Alias).adr_or_sz = HAC_Integer (i) then -- Here we have an identical alias (same name, and points -- to the same definition). if Level > 0 then Issue_Duplicate_Use_Note; exit; else -- Level 0 here. if CD.CUD.level_0_def.Contains (Short_Id) then Issue_Duplicate_Use_Note; exit; else -- Re-activate definition at zero level (context clause). CD.CUD.level_0_def.Include (Short_Id, Id_Alias); -- HAT.PUT_LINE ("Activate USEd item: " & Short_Id_str); end if; end if; end if; end if; end; end; end if; end loop; end Apply_USE_Clause; procedure Feed_Packages_Table (CD : in out Co_Defs.Compiler_Data) is begin CD.Packages_Count := CD.Packages_Count + 1; CD.id_table (CD.Id_Count).block_or_pkg_ref := CD.Packages_Count; declare p : Co_Defs.Package_Table_Entry renames CD.Packages_Table (CD.Packages_Count); begin p.first_public_declaration := CD.Id_Count + 1; p.last_public_declaration := 0; p.last_private_declaration := 0; end; end Feed_Packages_Table; end HAC_Sys.Parser.Packages; ================================================ FILE: src/compile/hac_sys-parser-packages.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Co_Defs, HAC_Sys.Defs; package HAC_Sys.Parser.Packages is -------------------------------------------------------------------------- -- Parse a package right after the "PACKAGE name" symbol sequence. -- -- `name` has been entered in the identifier table as "Paquetage" -- -- kind, either as a library-level declaration and library item, -- -- or a declaration which is local to a subprogram. -- -------------------------------------------------------------------------- procedure Package_Declaration ( CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; block_data : in out Block_Data_Type; needs_body : out Boolean ); ------------------------------------------------------------------ -- Parse a package's body right after the "PACKAGE BODY name" -- -- symbol sequence. -- ------------------------------------------------------------------ procedure Package_Body ( CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; block_data : in out Block_Data_Type ); ---------------------------------------------------------------------- -- Parse Use clause. -- -- It is either part of a context clause, or a local declaration. -- -- RM 8.4 (2) -- ---------------------------------------------------------------------- procedure Use_Clause (CD : in out Co_Defs.Compiler_Data; Level : Defs.Nesting_Level; prefixed : Boolean); ------------------------------------------------- -- Apply the USE clause at any nesting level -- ------------------------------------------------- procedure Apply_USE_Clause (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; prefixed : Boolean; Pkg_Idx : in Natural); -- Index in the identifier table for USEd package. ------------------------------------------ -- Feed the compiler's packages table -- ------------------------------------------ procedure Feed_Packages_Table (CD : in out Co_Defs.Compiler_Data); end HAC_Sys.Parser.Packages; ================================================ FILE: src/compile/hac_sys-parser-ranges.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.PCode, HAC_Sys.Scanner, HAC_Sys.Errors; package body HAC_Sys.Parser.Ranges is -- Are we sitting on the identifier of a discrete subtype -- like "Color" in "Color [range red .. blue]" ? -- In that case, we return the range red .. blue. -- procedure Static_Subtype_Indication -- RM 3.2.2 (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; Low, High : out Co_Defs.Constant_Rec; Found : out Boolean) is Idx : Integer; use Co_Defs, Defs, Helpers, Scanner; begin Found := False; if CD.Sy /= IDent then return; -- Perhaps we have a number like "1" in "1 .. 3", or something wrong. end if; Idx := Locate_CD_Id (CD, Level); if Idx /= No_Id then declare Id_T : Identifier_Table_Entry renames CD.id_table (Idx); begin if Id_T.entity = type_mark and then Discrete_Typ (Id_T.xtyp.TYP) then -- Subtype S, but need to exclude the attribute case: S'First, S'Image, ... Skip_Blanks (CD); -- We sneak a look at the next symbol: if CD.CUD.c /= ''' then -- Not a S'... attribute here. In_Symbol (CD); -- Consume the identifier. -- Do we have a subtype of a subtype? if CD.Sy = RANGE_Keyword_Symbol then -- Here comes the optional ` range 'a' .. 'z' ` constraint. In_Symbol (CD); Explicit_Static_Range (CD, Level, empty_symset + LOOP_Symbol, err_range_constraint_error, Low, High); Check_Explicit_Static_Range_Against_Parent_Type (CD, Low, High, Id_T.xtyp, False); else -- We can use the subtype identifier as a range. Low.TP := Id_T.xtyp; Low.I := Id_T.xtyp.Discrete_First; -- High.TP := Id_T.xtyp; High.I := Id_T.xtyp.Discrete_Last; end if; -- Found := True; end if; end if; end; end if; end Static_Subtype_Indication; ------------------------------------------------------- -- Check_Explicit_Static_Range_Against_Parent_Type -- ------------------------------------------------------- procedure Check_Explicit_Static_Range_Against_Parent_Type (CD : in out Co_Defs.Compiler_Data; low, high : in Co_Defs.Constant_Rec; parent : in out Co_Defs.Exact_Subtyp; narrow_the_parent : in Boolean) is use Co_Defs, Defs, Errors; begin if high.TP /= low.TP then Error (CD, err_bounds_type_mismatch, "types in range bounds do not match", severity => major); elsif Exact_Typ (low.TP) /= Exact_Typ (parent) then Error (CD, err_bounds_type_mismatch, "type of bounds don't match with the parent type", severity => major); elsif low.I not in parent.Discrete_First .. parent.Discrete_Last then Error (CD, err_range_constraint_error, "lower bound, " & Discrete_Image (CD, low.I, parent.TYP, parent.Ref) & ", is out of parent type's range, " & Discrete_Range_Image (CD, parent.Discrete_First, parent.Discrete_Last, parent.TYP, parent.Ref), severity => major); elsif high.I not in parent.Discrete_First .. parent.Discrete_Last then Error (CD, err_range_constraint_error, "higher bound, " & Discrete_Image (CD, high.I, parent.TYP, parent.Ref) & ", is out of parent type's range, " & Discrete_Range_Image (CD, parent.Discrete_First, parent.Discrete_Last, parent.TYP, parent.Ref), severity => major); elsif narrow_the_parent then parent.Discrete_First := low.I; parent.Discrete_Last := high.I; end if; end Check_Explicit_Static_Range_Against_Parent_Type; --------------------------- -- Explicit_Static_Range -- --------------------------- procedure Explicit_Static_Range (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys : in Defs.Symset; Specific_Error : in Defs.Compile_Diagnostic; Lower_Bound : out Co_Defs.Constant_Rec; Higher_Bound : out Co_Defs.Constant_Rec) is use Co_Defs, Defs, Expressions, Helpers, Errors; begin Static_Scalar_Expression (CD, Level, OF_RANGE_Double_Dot_RParent + FSys, Lower_Bound); -- if Lower_Bound.TP.TYP = Floats then Error (CD, Specific_Error, "a float type is not expected here"); Construct_Root (Lower_Bound.TP, Ints); Lower_Bound.I := 0; end if; -- Need (CD, Range_Double_Dot_Symbol, err_expecting_double_dot); -- " .. " -- Static_Scalar_Expression (CD, Level, Comma_OF_RParent + FSys, Higher_Bound); -- if Higher_Bound.TP /= Lower_Bound.TP then Error (CD, Specific_Error, "types in range bounds do not match"); Higher_Bound.I := Lower_Bound.I; end if; end Explicit_Static_Range; ------------------ -- Static_Range -- ------------------ procedure Static_Range (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys : in Defs.Symset; Specific_Error : in Defs.Compile_Diagnostic; Lower_Bound : out Co_Defs.Constant_Rec; Higher_Bound : out Co_Defs.Constant_Rec) is -- The variant "Low .. High" was initially -- in HAC.Parser <= 0.07 for array bounds. Is_SI_Found : Boolean; begin Static_Subtype_Indication (CD, Level, Lower_Bound, Higher_Bound, Is_SI_Found); if Is_SI_Found then return; -- All right, we have parsed, e.g., "Boolean" and -- pass further "False .. True". end if; -- -- We try an explicit static range, like: `1 .. N` (N declared number), -- `red .. blue` or `Base_Colour'First .. Colour'Last`. -- Explicit_Static_Range (CD, Level, FSys, Specific_Error, Lower_Bound, Higher_Bound); end Static_Range; ------------------- -- Dynamic_Range -- ------------------- procedure Dynamic_Range (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Non_Discrete_Error : in Defs.Compile_Diagnostic; Range_Typ : out Co_Defs.Exact_Subtyp) is use Compiler.PCode_Emit, Co_Defs, Defs, Expressions, Helpers, PCode, Scanner, Errors; -- The explicit range "Low_Expr .. High_Expr" was initially -- the only possibility in HAC.Parser version<= 0.07 for FOR statements. Lower_Bound_Typ, Upper_Bound_Typ : Exact_Subtyp; Lower_Bound_Static, Higher_Bound_Static : Constant_Rec; Is_SI_Found : Boolean; begin -- -- !! To do: replace by a dynamic subtype indication parser. -- Static_Subtype_Indication (CD, context.level, Lower_Bound_Static, Higher_Bound_Static, Is_SI_Found); -- if Is_SI_Found then -- All right, we have parsed a subtype indication, e.g., "Boolean". -- Since we are in a dynamic context, we need to push -- the bounds on the stack (E.g., "False .. True"). Emit_1 (CD, k_Push_Discrete_Literal, Lower_Bound_Static.I); Emit_1 (CD, k_Push_Discrete_Literal, Higher_Bound_Static.I); Range_Typ := Lower_Bound_Static.TP; return; end if; -- -- We try an explicit dynamic range, like: "f (z) + j .. n * 2" or "1 .. 6". -- See RM 3.5 (3). -- Simple_Expression (CD, context, END_LOOP_RANGE_Double_Dot + FSys, Lower_Bound_Typ); -- You may ask: why did the Ada standard authors take Simple_Expression -- instead of Expression for the range bounds ? -- It's for stopping the parsing on relational and logical operators. -- Consider the following example (in exm/aoc/2021/aoc_2021_11.adb ). -- With Expression for bounds, you need brackets for the membership tests: -- -- if (xx in 1 .. sx) and then (yy in 1 .. sy) and then map (xx, yy) <= 9 then -- -- With Simple_Expression, you can write, instead, the more intuitive: -- -- if xx in 1 .. sx and then yy in 1 .. sy and then map (xx, yy) <= 9 then -- Range_Typ := Lower_Bound_Typ; Range_Typ.Is_Range := False; -- if not Discrete_Typ (Range_Typ.TYP) then Error (CD, Non_Discrete_Error, Nice_Exact_Image (CD, Range_Typ)); end if; -- if Lower_Bound_Typ.Is_Range then -- We got a ` X'Range ` expression which is a shortcut for ` X'First .. X'Last `. -- The ` .. X'Last ` part has been implicitly parsed with ` X'Range ` . null; elsif CD.Sy = Range_Double_Dot_Symbol then -- ".." In_Symbol (CD); -- Simple_Expression (CD, context, FSys + LOOP_Symbol, Upper_Bound_Typ); -- if Exact_Typ (Upper_Bound_Typ) /= Exact_Typ (Lower_Bound_Typ) then Type_Mismatch (CD, err_bounds_type_mismatch, Found => Upper_Bound_Typ, Expected => Lower_Bound_Typ); end if; Range_Typ.Discrete_Last := Upper_Bound_Typ.Discrete_Last; else Error_then_Skip (CD, END_LOOP_Semicolon + FSys, err_expecting_double_dot); end if; end Dynamic_Range; procedure Set_Singleton_Range (X : in out Co_Defs.Exact_Subtyp; Value : Defs.HAC_Integer) is begin X.Discrete_First := Value; X.Discrete_Last := Value; end Set_Singleton_Range; function Is_Singleton_Range (X : Co_Defs.Exact_Subtyp) return Boolean is use type Defs.HAC_Integer; begin return X.Discrete_First = X.Discrete_Last; end Is_Singleton_Range; function Is_Singleton_Range (X : Co_Defs.Exact_Subtyp; Value : Defs.HAC_Integer) return Boolean is use type Defs.HAC_Integer; begin return Is_Singleton_Range (X) and then X.Discrete_First = Value; end Is_Singleton_Range; procedure Negate_Range (CD : in out Co_Defs.Compiler_Data; X : in out Co_Defs.Exact_Subtyp) is use Defs; use type HAC_Integer; temp : HAC_Integer; begin pragma Assert (X.TYP = Ints); if X.Discrete_Last = HAC_Integer'First then -- *Upper* bound is -2**(bits-1) -> overflow guaranteed on negating. Errors.Error (CD, err_range_constraint_error, ": overflow on applying ""-"""); end if; temp := X.Discrete_Last; if X.Discrete_First = HAC_Integer'First then -- Compile-time overflow if we negate that! X.Discrete_Last := HAC_Integer'Last; -- one off else X.Discrete_Last := -X.Discrete_First; end if; X.Discrete_First := -temp; end Negate_Range; function Do_Ranges_Overlap (X_min, X_max, Y_min, Y_max : Defs.HAC_Integer) return Boolean is use type Defs.HAC_Integer; begin pragma Assert (X_min <= X_max and then Y_min <= Y_max); -- -- The following is logically identical to: "not (Y_max < X_min or X_max < Y_min)", -- which means we don't have this situation: -- [X_min .. X_max] ... a gap ... [Y_min .. Y_max]. -- or [Y_min .. Y_max] ... a gap ... [X_min .. X_max]. -- return Y_max >= X_min and then X_max >= Y_min; end Do_Ranges_Overlap; function Do_Ranges_Overlap (X, Y : Co_Defs.Exact_Subtyp) return Boolean is begin return Do_Ranges_Overlap (X.Discrete_First, X.Discrete_Last, Y.Discrete_First, Y.Discrete_Last); end Do_Ranges_Overlap; end HAC_Sys.Parser.Ranges; ================================================ FILE: src/compile/hac_sys-parser-ranges.ads ================================================ with HAC_Sys.Defs; private package HAC_Sys.Parser.Ranges is -- This package has two families (Static_Range, Dynamic_Range) of -- discrete_subtype_definition RM 3.6 (6). In a distant future we could -- have a variant of Dynamic_Range which detects that the bounds are -- actually static and optimizes the code accordingly. -- which is either: -- a subtype_indication 3.2.2 (3) : name [constraint] -- like "Color [range red .. blue]" -- or -- a range 3.5 (3) -- which is either: -- simple_expression .. simple_expression : "low .. high" -- or -- range_attribute_reference 4.1.4 (4): A'Range[(2)] --------------------- -- Static ranges -- --------------------- -- A range with static bounds is parsed. -- The bounds are known at compile-time. -- At least, HAC is expecting the bounds to be static... -- -- Examples of static bounds: -- type T is range 1 .. 10; -- Must be static -- type T is new Integer range 1 .. 10; -- Could be dynamic as well -- subtype S is T range 2 .. 9; -- Could be dynamic as well -- -- As long as HAC has static-only arrays, this is also used for: -- type A is array (1 .. 5); -- -- Purely static discrete_subtype_definition in "full" Ada seem -- to be restricted to: -- - range types -- - case statements -- - record type declarations with variant parts. -- CF answer by Niklas Holsti to -- "Q: discrete_subtype_definition: static only cases?" -- on comp.lang.ada, 2020-06-07. --------------------------- -- Explicit_Static_Range -- --------------------------- -- -- `1 .. 3` -- procedure Explicit_Static_Range (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys : in Defs.Symset; Specific_Error : in Defs.Compile_Diagnostic; Lower_Bound : out Co_Defs.Constant_Rec; Higher_Bound : out Co_Defs.Constant_Rec); ------------------------------------------------------- -- Check_Explicit_Static_Range_Against_Parent_Type -- ------------------------------------------------------- procedure Check_Explicit_Static_Range_Against_Parent_Type (CD : in out Co_Defs.Compiler_Data; low, high : in Co_Defs.Constant_Rec; parent : in out Co_Defs.Exact_Subtyp; narrow_the_parent : in Boolean); ------------------ -- Static_Range -- ------------------ -- -- So far: either `1 .. 3` (that is, Explicit_Static_Range) or `Character`. -- procedure Static_Range (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys : in Defs.Symset; Specific_Error : in Defs.Compile_Diagnostic; Lower_Bound : out Co_Defs.Constant_Rec; Higher_Bound : out Co_Defs.Constant_Rec); ------------------- -- Dynamic_Range -- ------------------- -- -- A range with dynamic bounds is parsed. -- The bounds are pushed on the stack. -- Example: -- -- FOR statement (RM 5.5 (4)). -- for I in J .. N loop -- procedure Dynamic_Range (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Non_Discrete_Error : in Defs.Compile_Diagnostic; Range_Typ : out Co_Defs.Exact_Subtyp); procedure Set_Singleton_Range (X : in out Co_Defs.Exact_Subtyp; Value : Defs.HAC_Integer); function Is_Singleton_Range (X : Co_Defs.Exact_Subtyp) return Boolean; pragma Inline (Is_Singleton_Range); function Is_Singleton_Range (X : Co_Defs.Exact_Subtyp; Value : Defs.HAC_Integer) return Boolean; pragma Inline (Is_Singleton_Range); procedure Negate_Range (CD : in out Co_Defs.Compiler_Data; X : in out Co_Defs.Exact_Subtyp); -- Check whether ranges [X_min .. X_max] and [Y_min .. Y_max] overlap. -- function Do_Ranges_Overlap (X_min, X_max, Y_min, Y_max : Defs.HAC_Integer) return Boolean; pragma Inline (Do_Ranges_Overlap); function Do_Ranges_Overlap (X, Y : Co_Defs.Exact_Subtyp) return Boolean; pragma Inline (Do_Ranges_Overlap); end HAC_Sys.Parser.Ranges; ================================================ FILE: src/compile/hac_sys-parser-standard_functions.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.PCode, HAC_Sys.Scanner; package body HAC_Sys.Parser.Standard_Functions is use Compiler.PCode_Emit, Defs, Expressions, Helpers, PCode, Scanner; SF_Args : constant array (SF_Code) of Natural := (SF_Niladic => 0, SF_Min_Max_Int | SF_Element | SF_Head | SF_Tail | SF_Head_Before_Match | SF_Tail_After_Match | SF_Starts_With | SF_Ends_With | SF_Int_Times_Char | SF_Int_Times_VStr => 2, SF_Index | SF_Index_Backward | SF_Slice => 3, others => 1 ); procedure Standard_Function (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : Defs.Symset; Ident_Index : Integer; Code : Defs.SF_Code; Return_Typ : out Co_Defs.Exact_Subtyp) is use Co_Defs; Max_Args : constant := 3; Args : Natural := SF_Args (Code); Expected : array (1 .. Max_Args) of Typ_Set; -- Expected type of the function's arguments Actual : array (1 .. Max_Args) of Exact_Subtyp; -- Actual type from argument expression Code_Adjusted : SF_Code := Code; do_SF_emit : Boolean := True; X : Exact_Subtyp; -- procedure Prepare_Accepted_Parameter_Types is VString_or_Chars_Set : constant Typ_Set := VStrings_Set or Chars_Set; Strings_Set : constant Typ_Set := Arrays_Set or Str_Lit_Set or Str_as_VStr_Set; Any_String_Set : constant Typ_Set := VStrings_Set or Strings_Set; Any_String_or_Chars_Set : constant Typ_Set := Any_String_Set or Chars_Set; Chars_or_Strings_Set : constant Typ_Set := Chars_Set or Strings_Set; begin case Code is when SF_Abs_Int => Expected (1) := Numeric_Typ_Set; when SF_T_Val => -- S'Val : RM 3.5.5 (5) Expected (1) := Ints_Set; when SF_T_Pos => -- S'Pos : RM 3.5.5 (2) Expected (1) := Discrete_Typ; when SF_T_Succ | SF_T_Pred => -- S'Succ, S'Pred : RM 3.5 (22, 25) Expected (1) := Discrete_Typ; when SF_Round_Float_to_Int | SF_Trunc_Float_to_Int | SF_Sin | SF_Cos | SF_Exp | SF_Log | SF_Sqrt | SF_Arctan | SF_Sgn_Int => Expected (1) := Numeric_Typ_Set; when SF_Image_Ints => Expected (1) := Numeric_Typ_Set or Times_Set or Durations_Set; when SF_Image_Attribute_Floats => Expected (1) := Floats_Set; when SF_Random_Int | SF_Argument => Expected (1) := Ints_Set; when SF_Min_Max_Int => Expected (1 .. 2) := (Numeric_Typ_Set, Numeric_Typ_Set); when SF_Element | SF_Head | SF_Tail => Expected (1 .. 2) := (VStrings_Set, Ints_Set); when SF_Length | SF_Trim_Left .. SF_Trim_Both | SF_Float_Value | SF_Integer_Value => Expected (1) := VStrings_Set; when SF_Slice => Expected (1 .. 3) := (VStrings_Set, Ints_Set, Ints_Set); when SF_To_Lower_Char | SF_To_Upper_Char => Expected (1) := VString_or_Chars_Set; when SF_String_Literal_to_VString => Expected (1) := Chars_or_Strings_Set; when SF_VString_to_String => Expected (1) := VStrings_Set; when SF_Index | SF_Index_Backward => -- Index (OS, +"Windows"[, 3]), Index (OS, "Windows"[, 3]) or Index (OS, 'W'[, 3]) Expected (1 .. 3) := (VStrings_Set, Any_String_or_Chars_Set, Ints_Set); when SF_Starts_With | SF_Ends_With | SF_Head_Before_Match | SF_Tail_After_Match => Expected (1 .. 2) := (VStrings_Set, Any_String_or_Chars_Set); when SF_Year .. SF_Seconds => Expected (1) := Times_Set; when SF_Directory_Exists | SF_Exists | SF_File_Exists | SF_Get_Env | SF_Get_VM_Variable => -- Get_Env (+"PATH") _or_ Get_Env ("PATH") Expected (1) := Any_String_Set; when SF_Niladic => null; -- Zero argument -> no argument type to check. when SF_File_or_Console_Information => null; -- Arguments are parsed separately. when SF_Is_Open => Expected (1) := Text_Files_Set; when others => null; -- Here we have functions that are never parsed -- E.g. SF_Abs_Float, parsed as SF_Abs_Int, or "&" operators. end case; end Prepare_Accepted_Parameter_Types; -- procedure Parse_Arguments is TYP_of_arg : Typen; begin for a in 1 .. Args loop Expression (CD, context, FSys + RParent + Comma, Actual (a)); TYP_of_arg := Actual (a).TYP; if Expected (a) (TYP_of_arg) then null; -- All right so far: argument type is in the admitted set of types. elsif Actual (a).TYP /= NOTYP then Type_Mismatch ( CD, err_argument_to_std_function_of_wrong_type, Found => Actual (a), Expected => Expected (a) ); end if; if (Code = SF_Index or Code = SF_Index_Backward) and then a = 2 and then CD.Sy = RParent then Args := 2; -- Alright: Index, Index_Backard without From. exit; elsif a < Args then Need (CD, Comma, err_COMMA_missing); end if; end loop; end Parse_Arguments; -- procedure Parse_File_Information_Function (FIF_Code : SF_Code) is file_parameter : Boolean; begin if CD.Sy = LParent then -- End_Of_File (...), End_Of_Line (...). In_Symbol (CD); Expression (CD, context, FSys + RParent + Comma, X); if X.TYP /= Text_Files then Type_Mismatch (CD, err_general_error, Found => X, Expected => Text_Files_Set); end if; file_parameter := True; Need (CD, RParent, err_closing_parenthesis_missing); else -- Niladic End_Of_File, End_Of_Line without parameter. file_parameter := False; end if; Emit_2 (CD, k_HAT_Function, Boolean'Pos (file_parameter), SF_Code'Pos (FIF_Code)); end Parse_File_Information_Function; -- procedure Adjustments_to_Parameter_Types is -- Here is the actual overloading implemented. begin case Code is when SF_Abs_Int => -- Abs (NB: in Ada it's an operator, not a function) Return_Typ := Actual (1); if Actual (1).TYP = Floats then Code_Adjusted := SF_Abs_Float; end if; when SF_T_Succ | SF_T_Pred => -- S'Succ, S'Pred : RM 3.5 (22, 25) Return_Typ := Actual (1); when SF_Round_Float_to_Int | SF_Trunc_Float_to_Int | SF_Sin | SF_Cos | SF_Exp | SF_Log | SF_Sqrt | SF_Arctan => if Ints_Set (Actual (1).TYP) then Forbid_Type_Coercion (CD, Found => Actual (1), Expected => Construct_Root (Floats)); Emit_1 (CD, k_Integer_to_Float, 0); -- Ghost of SmallAda end if; when SF_Min_Max_Int => Return_Typ := Actual (1); if Actual (1).TYP = Floats then Code_Adjusted := (if Code = SF_Min_Int then SF_Min_Float else SF_Max_Float); end if; if Actual (2).TYP /= Actual (1).TYP then Type_Mismatch (CD, err_parameter_types_do_not_match, Actual (2), Actual (1)); end if; when SF_Sgn_Int => Return_Typ := Actual (1); if Actual (1).TYP = Floats then Code_Adjusted := SF_Sgn_Float; end if; when SF_Image_Ints => case Actual (1).TYP is when Floats => Code_Adjusted := SF_Image_Floats; when Times => Code_Adjusted := SF_Image_Times; when Durations => Code_Adjusted := SF_Image_Durations; when others => null; end case; when SF_To_Lower_Char => -- To_Lower (Item : Character) return Character; Return_Typ := Actual (1); if Actual (1).TYP = VStrings then -- To_Lower (Item : VString) return VString; Code_Adjusted := SF_To_Lower_VStr; end if; when SF_To_Upper_Char => -- To_Upper (Item : Character) return Character; Return_Typ := Actual (1); if Actual (1).TYP = VStrings then -- To_Upper (Item : VString) return VString; Code_Adjusted := SF_To_Upper_VStr; end if; when SF_Index | SF_Index_Backward | SF_Starts_With | SF_Ends_With | SF_Head_Before_Match | SF_Tail_After_Match => if Code in SF_Index_Any_Direction then if Args = 2 then Emit_1 (CD, k_Push_Discrete_Literal, 0); -- We push a non-positive value for `From`. end if; Emit (CD, k_Pop_to_Temp); -- `From` is now temporarily removed from the stack. `Pattern` is at the top. end if; -- Second parameter can be a Character, a String, or a VString. Check_any_String_and_promote_to_VString (CD, Actual (2), True); if Code in SF_Index_Any_Direction then Emit (CD, k_Push_Temp); -- `From` is now back at the stack top. end if; when SF_Directory_Exists | SF_Exists | SF_File_Exists | SF_Get_Env | SF_Get_VM_Variable => -- Get_Env ("PATH") becomes Get_Env (+"PATH") Check_any_String_and_promote_to_VString (CD, Actual (1), False); when SF_String_Literal_to_VString => -- Explicit call to the `To_VString` function, identical to the unary "+". -- See Simple_Expression in Parser.Expressions Check_any_String_and_promote_to_VString (CD, Actual (1), True); do_SF_emit := False; -- Conversion code is already emitted. when SF_Niladic => null; -- No arguments, nothing to adjust when others => null; -- Nothing to adjust regarding parameter types. end case; end Adjustments_to_Parameter_Types; -- begin Return_Typ := CD.id_table (Ident_Index).xtyp; -- Prepare_Accepted_Parameter_Types; -- if Code in SF_File_or_Console_Information then Parse_File_Information_Function (Code); else if Args > 0 then Need (CD, LParent, err_missing_an_opening_parenthesis); Parse_Arguments; end if; Adjustments_to_Parameter_Types; if do_SF_emit then Emit_Std_Funct (CD, Code_Adjusted); end if; if Args > 0 then Need (CD, RParent, err_closing_parenthesis_missing); end if; end if; end Standard_Function; end HAC_Sys.Parser.Standard_Functions; ================================================ FILE: src/compile/hac_sys-parser-standard_functions.ads ================================================ private package HAC_Sys.Parser.Standard_Functions is -- NB: Some of the supplied subprograms may disappear when modularity, -- Ada.Text_IO etc. will be implemented, as well as overloading. procedure Standard_Function (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : Defs.Symset; Ident_Index : Integer; Code : Defs.SF_Code; Return_Typ : out Co_Defs.Exact_Subtyp); end HAC_Sys.Parser.Standard_Functions; ================================================ FILE: src/compile/hac_sys-parser-standard_procedures.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Calls, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.PCode, HAC_Sys.Scanner, HAC_Sys.Errors; package body HAC_Sys.Parser.Standard_Procedures is use Calls, Compiler.PCode_Emit, Co_Defs, Defs, Expressions, Helpers, PCode, Scanner, Errors; type Default_Extra_Put_Parameter_Type is array (Typen, 1 .. 3) of Integer; invalid : constant := -1; default_extra_put_param : constant Default_Extra_Put_Parameter_Type := (Ints => (IIO.Default_Width, IIO.Default_Base, invalid), Floats => (RIO.Default_Fore, RIO.Default_Aft, RIO.Default_Exp), Bools => (BIO.Default_Width, invalid, invalid), others => (others => invalid)); -- NB: for String_Literals on the target HAC VM, two values are pushed on the stack. procedure Standard_Procedure (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Code : in Defs.SP_Code) is procedure HAT_Procedure_Call (FIO_Code : SP_Code; Param : Operand_2_Type := 0) is begin CD.target.Emit_HAT_Builtin_Procedure (FIO_Code, Param); end HAT_Procedure_Call; -- procedure Set_Abstract_Console is begin HAT_Procedure_Call (SP_Push_Abstract_Console); end Set_Abstract_Console; -- procedure Parse_Gets (Code : SP_Code) is -- Parse Get & Co including an possible File parameter Found : Exact_Subtyp; with_file : Boolean; String_Length_Encoding : Operand_2_Type := 0; use type Operand_2_Type; begin Need (CD, LParent, err_missing_an_opening_parenthesis); Push_Parameter_by_Reference (CD, context, FSys, "File", param_in_out, Found); with_file := Found.TYP = Text_Files; if with_file then -- We place the file handle's value on the stack: Emit (CD, k_Dereference); Need (CD, Comma, err_COMMA_missing); -- Now the variable for "Get (file, variable);": Push_Parameter_by_Reference (CD, context, FSys, "", param_out, Found); end if; -- The "out" variable for Get, Get_Immediate, Get_Line -- has been pushed by reference now. if Found.TYP = NOTYP then null; -- Error(s) already appeared in the parsing. elsif Text_IO_Get_Item_Set (Found.TYP) then if Found.TYP = Arrays then -- Array: it must be a fixed-sized String here. if Is_Char_Array (CD, Found) then String_Length_Encoding := (2 ** Typen'Size) * Operand_2_Type (CD.Arrays_Table (Found.Ref).Array_Size); else Error (CD, err_illegal_parameters_to_Get); end if; end if; HAT_Procedure_Call ((if with_file then (if Code = SP_Get_Line then SP_Get_Line_File else SP_Get_File) else Code), Typen'Pos (Found.TYP) + String_Length_Encoding); else Error (CD, err_illegal_parameters_to_Get); end if; Need (CD, RParent, err_closing_parenthesis_missing); end Parse_Gets; -- procedure Parse_Puts (Code : SP_Code) is -- Parse Put & Co including an possible File parameter Item_Typ, Format_Param_Typ : Exact_Subtyp; Format_Params : Natural := 0; with_file : Boolean; begin Need (CD, LParent, err_missing_an_opening_parenthesis); Expression (CD, context, FSys + Colon_Comma_RParent, Item_Typ); with_file := Item_Typ.TYP = Text_Files; if with_file then Need (CD, Comma, err_COMMA_missing); Expression (CD, context, FSys + Colon_Comma_RParent, Item_Typ); end if; -- -- Here we have tha actual thing to "Put": a character, (v)string, a number. -- if Item_Typ.TYP in Standard_Typ | Special_Strings then null; -- Good, Put[_Line] can do it all "as is"! elsif Is_Char_Array (CD, Item_Typ) then -- Address is already pushed; we need to push the string's length. Emit_1 (CD, k_Push_Discrete_Literal, Operand_2_Type (CD.Arrays_Table (Item_Typ.Ref).Array_Size)); else Error (CD, err_illegal_parameters_to_Put); end if; for Param in 1 .. 3 loop exit when CD.Sy /= Comma; In_Symbol (CD); Format_Params := Format_Params + 1; -- Here we parse: -- Width, Base for Put ([F,] I [, Width [, Base]]); -- Fore, Aft, Exp for Put ([F,] R [, Fore[, Aft[, Exp]]]); -- Width for Put ([F,] B [, Width]); Expression (CD, context, FSys + Colon_Comma_RParent, Format_Param_Typ); Check_Integer (CD, Format_Param_Typ.TYP); end loop; -- Check given / default parameters (nice short common solution, isn't it ?) for Param in 1 .. Format_Params loop -- First we check if the programmer didn't put too many -- (then, undefined) parameters. if default_extra_put_param (Item_Typ.TYP, Param) = invalid then Error (CD, err_illegal_parameters_to_Put); end if; end loop; if Item_Typ.TYP = String_Literals or else Is_Char_Array (CD, Item_Typ) then -- With String_Literals and String's, we have *two* values pushed on the stack. Format_Params := Format_Params + 1; end if; for Param in Format_Params + 1 .. 3 loop -- Send default parameters to the stack. exit when default_extra_put_param (Item_Typ.TYP, Param) = invalid; -- See Do_Write_Formatted on HAC VM or the code associated with SP_Put on -- other targets via Emit_HAT_Builtin_Procedure to have an idea on how -- everybody is retrieved from the stack. CD.target.Emit_Push_Discrete_Literal (Operand_2_Type (default_extra_put_param (Item_Typ.TYP, Param))); end loop; HAT_Procedure_Call ((if with_file then (if Code = SP_Put_Line then SP_Put_Line_File else SP_Put_File) else Code), Typen'Pos (Item_Typ.TYP)); Need (CD, RParent, err_closing_parenthesis_missing); end Parse_Puts; type Param_Passing_Mode is (by_value, by_reference); type Param is record mode : Param_Passing_Mode; typ : Typen; end record; type Param_List is array (Positive range <>) of Param; procedure Parse_Call_to_Single_Profile_Procedure (pl : Param_List) is -- This fits non-overloaded procedures. X : Exact_Subtyp; begin if pl'Length = 0 then return; -- No parameter else Need (CD, LParent, err_missing_an_opening_parenthesis); for i in pl'Range loop -- Parse the passed parameter's variable (when by reference) -- or expression (when by value) and emit corresponding VM code -- that will have in fine an address or a value pushed on the stack. case pl (i).mode is when by_reference => Push_Parameter_by_Reference (CD, context, FSys, "", param_in_out, X); when by_value => Expression (CD, context, Comma_RParent, X); end case; -- Check the base type. if X.TYP /= pl (i).typ then Type_Mismatch (CD, err_parameter_types_do_not_match, Found => X, Expected => Singleton (pl (i).typ)); end if; -- Parse the comma separating current parameter from next one. if i < pl'Last then Need (CD, Comma, err_COMMA_missing); end if; end loop; Need (CD, RParent, err_closing_parenthesis_missing); end if; end Parse_Call_to_Single_Profile_Procedure; procedure Parse_Call_to_Single_Profile_HAT_Procedure (pl : Param_List) is begin Parse_Call_to_Single_Profile_Procedure (pl); HAT_Procedure_Call (Code); end Parse_Call_to_Single_Profile_HAT_Procedure; X, Y, Z : Exact_Subtyp; begin case Code is when SP_Get | SP_Get_Immediate | SP_Get_Line => Parse_Gets (Code); when SP_Put | SP_Put_Line => Parse_Puts (Code); when SP_New_Line | SP_Skip_Line => if CD.Sy = LParent then In_Symbol (CD); Expression (CD, context, FSys + Colon_Comma_RParent, X); case X.TYP is when Text_Files => if CD.Sy = Comma then -- "New_Line (File, Spacing);" In_Symbol (CD); Expression (CD, context, FSys + RParent, Y); Check_Integer (CD, Y.TYP); else -- "New_Line (File);" Emit_1 (CD, k_Push_Discrete_Literal, 1); -- Push default value, Spacing := 1 end if; when Ints => -- "New_Line (Spacing);" Set_Abstract_Console; Emit (CD, k_Swap); -- File (the console) has to be before Spacing on the stack. when others => Type_Mismatch (CD, err_general_error, Found => X, Expected => Text_Files_Set or Ints_Set); end case; Need (CD, RParent, err_closing_parenthesis_missing); else -- "New_Line;" Set_Abstract_Console; Emit_1 (CD, k_Push_Discrete_Literal, 1); -- Push default value, Spacing := 1 end if; HAT_Procedure_Call (Code); when SP_Randomize => HAT_Procedure_Call (Code); when SP_Random_Seed => Parse_Call_to_Single_Profile_HAT_Procedure ((1 => (by_value, Ints))); when SP_Wait | SP_Signal => Parse_Call_to_Single_Profile_Procedure ((1 => (by_value, Ints))); if Code = SP_Wait then Emit (CD, k_Wait_Semaphore); else Emit (CD, k_Signal_Semaphore); end if; when SP_Open | SP_Create | SP_Append | SP_Close => Need (CD, LParent, err_missing_an_opening_parenthesis); Push_Parameter_by_Reference (CD, context, FSys + Colon_Comma_RParent, "File", param_in_out, X); if X.TYP /= Text_Files then Type_Mismatch (CD, err_general_error, Found => X, Expected => Text_Files_Set); end if; if Code in SP_Open | SP_Create | SP_Append then -- Parse file name. Need (CD, Comma, err_COMMA_missing); Expression (CD, context, FSys + Colon_Comma_RParent, X); Check_any_String_and_promote_to_VString (CD, X, False); end if; HAT_Procedure_Call (Code); Need (CD, RParent, err_closing_parenthesis_missing); when SP_Quantum => -- Cramer Parse_Call_to_Single_Profile_Procedure ((1 => (by_value, Floats))); Emit (CD, k_Set_Quantum_Task); when SP_Priority => -- Cramer Parse_Call_to_Single_Profile_Procedure ((1 => (by_value, Ints))); Emit (CD, k_Set_Task_Priority); when SP_InheritP => -- Cramer Parse_Call_to_Single_Profile_Procedure ((1 => (by_value, Bools))); Emit (CD, k_Set_Task_Priority_Inheritance); -- when SP_Set_Env | SP_Set_VM_Variable | SP_Copy_File | SP_Rename => Need (CD, LParent, err_missing_an_opening_parenthesis); for arg in 1 .. 2 loop Expression (CD, context, Colon_Comma_RParent, X); -- We push the arguments in the stack. -- Set_Env ( "HAC_Var", "Hello"); <- 2 String's -- Set_Env (+"HAC_Var", +"Hello"); <- 2 VString's -- Set_Env (+"HAC_Var", "Hello"); -- Set_Env ( "HAC_Var", +"Hello"); Check_any_String_and_promote_to_VString (CD, X, False); if arg < 2 then Need (CD, Comma, err_COMMA_missing); end if; end loop; HAT_Procedure_Call (Code); Need (CD, RParent, err_closing_parenthesis_missing); when SP_Create_Directory | SP_Create_Path | SP_Delete_Directory | SP_Delete_File | SP_Set_Directory => Need (CD, LParent, err_missing_an_opening_parenthesis); Expression (CD, context, RParent_Set, X); -- We push the argument in the stack. Check_any_String_and_promote_to_VString (CD, X, False); HAT_Procedure_Call (Code); Need (CD, RParent, err_closing_parenthesis_missing); when SP_Shell_Execute => Need (CD, LParent, err_missing_an_opening_parenthesis); Expression (CD, context, Comma_RParent, X); -- We push the argument in the stack. Check_any_String_and_promote_to_VString (CD, X, False); -- ` Shell_Execute (cmd ` has been parsed at this point. if CD.Sy = Comma then In_Symbol (CD); Push_Parameter_by_Reference (CD, context, RParent_Set, "Command", param_in_out, Y); case Y.TYP is when VStrings => -- Shell_Execute (cmd, output); HAT_Procedure_Call (SP_Shell_Execute_Output); when Ints => if CD.Sy = Comma then In_Symbol (CD); Push_Parameter_by_Reference (CD, context, RParent_Set, "Result", param_out, Z); -- Shell_Execute (cmd, result, output); HAT_Procedure_Call (SP_Shell_Execute_Result_Output); if Z.TYP /= VStrings then Type_Mismatch (CD, err_parameter_types_do_not_match, Found => Z, Expected => VStrings_Set); end if; else -- Shell_Execute (cmd, result); HAT_Procedure_Call (SP_Shell_Execute_with_Result); end if; when others => Type_Mismatch (CD, err_parameter_types_do_not_match, Found => Y, Expected => VStrings_Set or Ints_Set); end case; else -- Shell_Execute (cmd); HAT_Procedure_Call (SP_Shell_Execute_without_Result); end if; Need (CD, RParent, err_closing_parenthesis_missing); when SP_Set_Exit_Status => Parse_Call_to_Single_Profile_HAT_Procedure ((1 => (by_value, Ints))); -- Exit code when SP_Delete => Parse_Call_to_Single_Profile_HAT_Procedure (((by_reference, VStrings), -- Source (by_value, Ints), -- From (by_value, Ints))); -- Through when SP_Push_Abstract_Console => null; -- Internal: used by Get, Put, etc. without file parameter. when SP_Get_File | SP_Get_Line_File | SP_Put_File | SP_Put_Line_File => -- Theses cases are "fronted" by SP_Get, SP_Get_Line,... -- They are used by the VM. null; end case; end Standard_Procedure; end HAC_Sys.Parser.Standard_Procedures; ================================================ FILE: src/compile/hac_sys-parser-standard_procedures.ads ================================================ private package HAC_Sys.Parser.Standard_Procedures is -- NB: Some of the supplied subprograms may disappear when modularity, -- Ada.Text_IO etc. will be implemented, as well as overloading. procedure Standard_Procedure (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Code : in Defs.SP_Code); end HAC_Sys.Parser.Standard_Procedures; ================================================ FILE: src/compile/hac_sys-parser-statements-case_statement.adb ================================================ with HAC_Sys.Co_Defs, HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Defs, HAC_Sys.Multi_Precision_Integers, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Ranges, HAC_Sys.PCode, HAC_Sys.Scanner, HAC_Sys.Errors; procedure HAC_Sys.Parser.Statements.CASE_Statement -- Ada RM 5.4 (CD : in out Co_Defs.Compiler_Data; fsys : in Defs.Symset; block_data : in out Block_Data_Type) is use Defs, Co_Defs, Compiler.PCode_Emit, Errors, Expressions, Helpers, PCode; use type HAC_Integer; type CASE_Label_Value is record value_1, value_2 : HAC_Integer; -- value of a choice in a CASE statement LC : Index; -- instruction address Is_others : Boolean; end record; case_table : array (1 .. Cases_Max) of CASE_Label_Value; exit_table : array (1 .. Cases_Max) of Integer; X : Exact_Subtyp; choice_counter : Integer := 0; -- This counts the various choices separated by '|'. exit_counter : Integer := 0; -- This will correspond to the number of "=>". LC1 : Integer; WHEN_OTHERS_flag : Boolean := False; use Multi_Precision_Integers; subtype Choice_Count_Type is Multi_Int (4); parsed_choices : Choice_Count_Type; procedure In_Symbol is begin Scanner.In_Symbol (CD); end In_Symbol; function Count_Choice_Values (Low, High : HAC_Integer) return Choice_Count_Type is result : Choice_Count_Type; begin pragma Assert (Low <= High); Fill (result, Multi (High) - Multi (Low) + 1); return result; end Count_Choice_Values; procedure Discrete_Choice is -- Ada RM 3.8.1 (5) label_1, label_2 : Constant_Rec; K : Integer; choice_symbol_set : constant Symset := fsys + Alt_Finger_THEN + Range_Double_Dot_Symbol; begin Static_Scalar_Expression (CD, block_data.context.level, choice_symbol_set, label_1); if CD.Sy = Range_Double_Dot_Symbol then -- !! To do: non-explicit ranges, like a subtype name, a 'Range, ... . -- Ranges.Static_Range. In_Symbol; Static_Scalar_Expression (CD, block_data.context.level, choice_symbol_set, label_2); if label_2.TP /= label_1.TP then Type_Mismatch ( CD, err_case_label_not_same_type_as_case_clause, Found => label_2.TP, Expected => label_1.TP ); end if; else label_2 := label_1; end if; if Exact_Typ (label_1.TP) /= Exact_Typ (X) then Type_Mismatch ( CD, err_case_label_not_same_type_as_case_clause, Found => label_1.TP, Expected => X ); elsif choice_counter = Cases_Max then Fatal (Case_Labels); -- Exception is raised there. else if (label_1.I not in X.Discrete_First .. X.Discrete_Last) or else (label_2.I not in X.Discrete_First .. X.Discrete_Last) then Error (CD, err_choice_out_of_range, severity => minor); end if; choice_counter := choice_counter + 1; case_table (choice_counter) := (value_1 => label_1.I, value_2 => label_2.I, LC => CD.LC, Is_others => False); K := 0; loop K := K + 1; -- Detect any range overlap: exit when Ranges.Do_Ranges_Overlap (label_1.I, label_2.I, case_table (K).value_1, case_table (K).value_2); end loop; if K < choice_counter then Error (CD, err_duplicate_case_choice_value, severity => major); end if; -- Since single choices or ranges do not overlap, -- we can simply add the number of covered values in order to check -- at the end that everything is covered. Fill (parsed_choices, parsed_choices + Count_Choice_Values (label_1.I, label_2.I)); end if; end Discrete_Choice; procedure WHEN_Discrete_Choice_List is begin pragma Assert (CD.Sy = WHEN_Symbol); -- This subprogram is called only on WHEN_Symbol. In_Symbol; -- Consume `WHEN` -- Here, a discrete_choice_list (Ada RM 3.8.1 (4)) following WHEN. if Constant_Definition_Begin_Symbol (CD.Sy) then if WHEN_OTHERS_flag then -- Normal choice list *atfer* the "others" choice. Error (CD, err_case_others_alone_last); end if; Discrete_Choice; while CD.Sy = Alt loop In_Symbol; -- Consume '|' symbol. if CD.Sy = OTHERS_Symbol then -- "others" mixed with normal choices. Error (CD, err_case_others_alone_last); else Discrete_Choice; end if; end loop; elsif CD.Sy = OTHERS_Symbol then -- Hathorn if WHEN_OTHERS_flag then -- Duplicate "others". Error (CD, err_case_others_alone_last); end if; WHEN_OTHERS_flag := True; if choice_counter = Cases_Max then Fatal (Case_Labels); -- Exception is raised there. end if; choice_counter := choice_counter + 1; case_table (choice_counter) := (value_1 | value_2 => 0, LC => CD.LC, Is_others => True); In_Symbol; end if; if CD.Sy = THEN_Symbol then -- Mistake happens when converting IF statements to CASE. Error (CD, err_THEN_instead_of_Arrow, severity => major); In_Symbol; else Need (CD, Finger, err_FINGER_missing); end if; Sequence_of_Statements_in_a_Conditional_Statement (CD, END_WHEN, block_data); exit_counter := exit_counter + 1; exit_table (exit_counter) := CD.LC; Emit (CD, k_Jump); end WHEN_Discrete_Choice_List; procedure Check_Coverage is expected_choices, difference : Choice_Count_Type; begin pragma Assert (Choice_Count_Type'Size >= HAC_Integer'Size); Fill (expected_choices, Count_Choice_Values (X.Discrete_First, X.Discrete_Last)); Fill (difference, expected_choices - parsed_choices); if Equal (difference, 0) then if WHEN_OTHERS_flag then if CD.remarks (note_redundant_construct) then Remark (CD, note_redundant_construct, """when others"" is redundant here: all values" & " are already explicitly covered"); end if; end if; else pragma Assert (difference > 0); -- ^ NB: if the difference was negative, there would be more parsed -- choices than possible choices. Thus at least one choice -- would be out of range. But that error would have been detected -- on parsing and this procedure would not have been called. if not WHEN_OTHERS_flag then Error (CD, err_choices_not_covered, (if difference > 99 then "" -- Too many omissions for display... elsif Equal (difference, 1) then ": one case is missing" else ":" & Basic_Int'Image (Basic (difference)) & " cases are missing"), severity => minor); end if; end if; end Check_Coverage; begin -- CASE_Statement pragma Assert (CD.Sy = CASE_Symbol); block_data.context.is_within_condition := True; block_data.context.is_in_cond_within_loop := block_data.context.is_within_loop; Fill (parsed_choices, 0); In_Symbol; Expression (CD, block_data.context, fsys + Colon_Comma_IS_OF, X); if not Discrete_Typ (X.TYP) then Error (CD, err_bad_type_for_a_case_statement); end if; LC1 := CD.LC; Emit (CD, k_CASE_Switch); case CD.Sy is when IS_Symbol => In_Symbol; when OF_Symbol => Error (CD, err_OF_instead_of_IS); -- ^ Common mistake by Pascal programmers. -- Historical note: "OF" and not "IS" was expected by SmallAda! -- For instance, "case x OF when 1 => ..." In_Symbol; when others => Error (CD, err_IS_missing); end case; if CD.Sy /= WHEN_Symbol then Error (CD, err_WHEN_missing, severity => major); end if; loop -- All cases are parsed in this loop. WHEN_Discrete_Choice_List; exit when CD.Sy /= WHEN_Symbol; end loop; if CD.error_count + CD.minor_error_count = 0 then Check_Coverage; end if; CD.ObjCode (LC1).Y := Operand_2_Type (CD.LC); -- ^ Set correct address for k_CASE_Switch above. -- This is the address of the following bunch of -- instructions. -- Output the case table as (CASE_Any_Choice, k_CASE_Match_Jump) -- instruction pairs: for K in 1 .. choice_counter loop if case_table (K).Is_others then Emit (CD, k_CASE_Choice_Others); elsif case_table (K).value_1 = case_table (K).value_2 then Emit_1 (CD, k_CASE_Choice_Value, case_table (K).value_1); else Emit_2 (CD, k_CASE_Choice_Range, case_table (K).value_1, case_table (K).value_2); end if; Emit_1 (CD, k_CASE_Match_Jump, Operand_2_Type (case_table (K).LC)); end loop; -- The following is for having the interpreter exiting the k_CASE_Choice_Data loop. -- Note: the k_CASE_No_Choice_Found allowed to check a missing "when others" -- at run-time. Now this check is done at compile-time by Check_Coverage. Emit (CD, k_CASE_No_Choice_Found); -- for K in 1 .. exit_counter loop -- Patch k_Jump addresses to the instruction coming after "END CASE;" : CD.ObjCode (exit_table (K)).Y := Operand_2_Type (CD.LC); end loop; Need (CD, END_Symbol, err_END_missing); -- END (case) if CD.Sy in LOOP_Symbol | IF_Symbol | IDent then Error (CD, err_missing_closing_CASE_2, severity => minor); In_Symbol; else Need (CD, CASE_Symbol, err_missing_closing_CASE); -- (end) CASE end if; end HAC_Sys.Parser.Statements.CASE_Statement; ================================================ FILE: src/compile/hac_sys-parser-statements.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Calls, HAC_Sys.Parser.Enter_Def, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Ranges, HAC_Sys.PCode, HAC_Sys.Parser.Standard_Procedures, HAC_Sys.Parser.Statements.CASE_Statement, HAC_Sys.Scanner, HAC_Sys.Errors; package body HAC_Sys.Parser.Statements is use type Defs.HAC_Integer; procedure Assignment (CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; context : Defs.Flow_Context; var_id_index : Integer; check_is_variable : Boolean) is use Compiler.PCode_Emit, Co_Defs, Defs, Expressions, Helpers, PCode, Scanner, Errors; var : Identifier_Table_Entry renames CD.id_table (var_id_index); X, Y : Exact_Subtyp; X_Len : Natural; -- procedure Issue_Type_Mismatch_Error is begin Type_Mismatch (CD, err_types_of_assignment_must_match, Found => Y, Expected => X); end Issue_Type_Mismatch_Error; -- begin pragma Assert (var.entity in Object_Kind); X := var.xtyp; Emit_2 (CD, (if var.normal then k_Push_Address -- Normal variable, we push its address else k_Push_Discrete_Value), -- The value is a reference, we want that address. Operand_1_Type (var.lev), Operand_2_Type (var.adr_or_sz)); if Selector_Symbol_Loose (CD.Sy) then -- '.' or '(' or (wrongly) '[' -- Resolve composite types' selectors (arrays and records). Selector (CD, context, Becomes_EQL + FSys, X); -- Now, X denotes the leaf type (which can be composite as well). end if; -- Parse the ":=" of "X := Y;" case CD.Sy is when Becomes => In_Symbol (CD); when EQL => -- Common mistake by BASIC or C programmers. Error (CD, err_EQUALS_instead_of_BECOMES); In_Symbol (CD); when others => Error (CD, err_BECOMES_missing); end case; if check_is_variable and then var.entity = constant_object then Error (CD, err_cannot_modify_constant_or_in_parameter); end if; Expression (CD, context, Semicolon_Set, Y); -- if X.TYP = Y.TYP and X.TYP /= NOTYP then if Discrete_Typ (X.TYP) then if Ranges.Do_Ranges_Overlap (X, Y) then if X.Discrete_First > Y.Discrete_First then Compiler.PCode_Emit.Emit_3 (CD, k_Check_Lower_Bound, X.Discrete_First, Typen'Pos (X.TYP), Operand_3_Type (X.Ref)); end if; if X.Discrete_Last < Y.Discrete_Last then Compiler.PCode_Emit.Emit_3 (CD, k_Check_Upper_Bound, X.Discrete_Last, Typen'Pos (X.TYP), Operand_3_Type (X.Ref)); end if; else Error (CD, err_range_constraint_error, "value of expression (" & (if Ranges.Is_Singleton_Range (Y) then -- More understandable message part for a single value Discrete_Image (CD, Y.Discrete_First, X.TYP, X.Ref) else "range: " & Discrete_Range_Image (CD, Y.Discrete_First, Y.Discrete_Last, X.TYP, X.Ref)) & ") is out of destination's range, " & Discrete_Range_Image (CD, X.Discrete_First, X.Discrete_Last, X.TYP, X.Ref), severity => minor); end if; end if; if X.TYP in Standard_Typ then Emit_1 (CD, k_Store, Typen'Pos (X.TYP)); elsif X.Ref /= Y.Ref then Issue_Type_Mismatch_Error; -- E.g. different arrays, enums, ... else case X.TYP is when Arrays => Emit_1 (CD, k_Copy_Block, Operand_2_Type (CD.Arrays_Table (X.Ref).Array_Size)); when Records => Emit_1 (CD, k_Copy_Block, Operand_2_Type (CD.Blocks_Table (X.Ref).VSize)); when Enums => -- Behaves like a "Standard_Typ". -- We have checked that X.Ref = Y.Ref (same actual type). Emit_1 (CD, k_Store, Typen'Pos (X.TYP)); when others => raise Internal_error with "Assignment: X := Y on unsupported Typ ?"; end case; end if; else -- -- Here, X.TYP and Y.TYP are different. -- if X.TYP = Floats and Y.TYP = Ints then Forbid_Type_Coercion (CD, Found => Y, Expected => X); elsif X.TYP = Durations and Y.TYP = Floats then -- Duration hack (see Delay_Statement for full explanation). Emit_Std_Funct (CD, SF_Float_to_Duration); Emit_1 (CD, k_Store, Typen'Pos (X.TYP)); elsif Is_Char_Array (CD, X) and Y.TYP = String_Literals then X_Len := CD.Arrays_Table (X.Ref).Array_Size; if X_Len = CD.SLeng then Emit_1 (CD, k_String_Literal_Assignment, Operand_2_Type (X_Len)); else Error (CD, err_string_lengths_do_not_match, "variable has length" & Integer'Image (X_Len) & ", literal has length" & Integer'Image (CD.SLeng), severity => minor); end if; elsif X.TYP = VStrings and then (Y.TYP in String_Literals | Strings_as_VStrings or else Is_Char_Array (CD, Y)) then Error (CD, err_string_to_vstring_assignment); elsif X.TYP = NOTYP then if CD.error_count = 0 then raise Internal_error with "Assignment: assigned variable (X) is typeless"; end if; -- All right, there were already enough compilation error messages... elsif Y.TYP = NOTYP then if CD.error_count = 0 then raise Internal_error with "Assignment: assigned value (Y) is typeless"; end if; -- All right, there were already enough compilation error messages... else Issue_Type_Mismatch_Error; -- NB: We are in the X.TYP /= Y.TYP case. end if; end if; end Assignment; procedure Statement -- Ada RM 5.1 (3) (CD : in out Co_Defs.Compiler_Data; FSys_St : Defs.Symset; block_data : in out Block_Data_Type); procedure Sequence_of_Statements -- Ada RM 5.1 (2) (CD : in out Co_Defs.Compiler_Data; sentinel : Defs.Symset; block_data : in out Block_Data_Type; optional : Boolean := False) is use Defs, Helpers, Errors; statement_or_sentinel : constant Symset := Statement_Begin_Symbol or sentinel; begin if sentinel (CD.Sy) and then not optional then -- GdM 15-Aug-2014: there should be at least one statement. -- -- But in some places in the grammar the sequence is optional: -- in an accept_alternative and in a delay_alternative. -- In both cases the sequence follow a first statement (accept or delay). Error (CD, err_statement_expected, severity => minor); else loop Statement (CD, statement_or_sentinel, block_data); exit when sentinel (CD.Sy) or else CD.error_count > 0; end loop; end if; end Sequence_of_Statements; procedure Sequence_of_Statements_in_a_Conditional_Statement (CD : in out Co_Defs.Compiler_Data; sentinel : Defs.Symset; block_data : in out Block_Data_Type; optional : Boolean := False) is old_context : constant Defs.Flow_Context := block_data.context; begin block_data.context.is_within_condition := True; block_data.context.is_in_cond_within_loop := block_data.context.is_within_loop; -- Sequence_of_Statements (CD, sentinel, block_data, optional); -- block_data.context := old_context; end Sequence_of_Statements_in_a_Conditional_Statement; ------------------------------------------------------------------ --------------------------------------Statement - Ada RM 5.1 (3)-- procedure Statement (CD : in out Co_Defs.Compiler_Data; FSys_St : Defs.Symset; block_data : in out Block_Data_Type) is use Compiler.PCode_Emit, Calls, Co_Defs, Defs, Enter_Def, Expressions, Helpers, PCode, Errors; use type Alfa; procedure In_Symbol is begin Scanner.In_Symbol (CD); end In_Symbol; procedure Accept_Statement is -- Hathorn procedure Accept_Call is begin -- !! Check to make sure parameters match with Entry Statement if CD.Sy = Semicolon then return; end if; if CD.Sy = LParent then -- <--- temporary while not (CD.Sy = DO_Symbol or CD.Sy = RParent) loop In_Symbol; end loop; -- !! should check no. and end if; -- Types of parms. if CD.Sy = RParent then In_Symbol; end if; end Accept_Call; I_Entry : Integer; begin -- Accept_Statement In_Symbol; I_Entry := Locate_CD_Id (CD, block_data.context.level); if CD.id_table (I_Entry).entity /= entree then Error (CD, err_general_error, "an entry name is expected here"); else CD.target.Mark_Reference (I_Entry); end if; In_Symbol; Accept_Call; Emit_1 (CD, k_Accept_Rendezvous, Operand_2_Type (I_Entry)); if CD.Sy = DO_Symbol then if block_data.context.level = nesting_level_max then Fatal (LEVELS); -- Exception is raised there. end if; block_data.context.level := block_data.context.level + 1; CD.Display (block_data.context.level) := CD.id_table (I_Entry).block_or_pkg_ref; In_Symbol; Sequence_of_Statements (CD, END_Set, block_data); Need_END_Symbol (CD); if CD.Sy = IDent then if CD.Id /= CD.id_table (I_Entry).name then Error (CD, err_incorrect_name_after_END); else CD.target.Mark_Reference (I_Entry); end if; In_Symbol; end if; block_data.context.level := block_data.context.level - 1; end if; Emit_1 (CD, k_End_Rendezvous, Operand_2_Type (I_Entry)); end Accept_Statement; procedure Exit_Statement is -- RM 5.7 -- Generate an absolute branch statement with a dummy end loop address X : Exact_Subtyp; exit_level : Natural := CD.loop_nesting_level; id_found : Boolean; count_FOR_loops : Natural := 0; landing_after_jump : Integer; conditional : Boolean := False; begin pragma Assert (CD.Sy = EXIT_Symbol); In_Symbol; -- Consume EXIT symbol. if CD.loop_nesting_level = 0 then Error (CD, err_general_error, """exit"" without a ""loop"" - was ""return"" intended?", severity => major); -- Exception raised, compilation stopped. end if; -- Possible name: if CD.Sy = IDent then id_found := False; for level in reverse 1 .. CD.loop_nesting_level loop if CD.Nested_Loop_Table (level).is_FOR_loop then count_FOR_loops := count_FOR_loops + 1; end if; if CD.Nested_Loop_Table (level).loop_Id /= No_Id and then CD.Id = CD.id_table (CD.Nested_Loop_Table (level).loop_Id).name then id_found := True; exit_level := level; exit; end if; end loop; if not id_found then Error (CD, err_general_error, "loop name not matched: " & A2S (CD.Id_with_case)); end if; In_Symbol; -- Consume the identifier. else -- EXIT without a name. if CD.Nested_Loop_Table (CD.loop_nesting_level).is_FOR_loop then count_FOR_loops := 1; end if; end if; if CD.Sy = WHEN_Symbol then -- Conditional Exit In_Symbol; -- Consume WHEN symbol. Boolean_Expression (CD, block_data.context, Semicolon_Set, X); -- On False, conditional jump around Exit: if count_FOR_loops = 0 then landing_after_jump := CD.LC + 2; else landing_after_jump := CD.LC + 3; end if; Emit_1 (CD, k_Jump_If_Zero_With_Pop, Operand_2_Type (landing_after_jump)); conditional := True; end if; -- De-stacking for all FOR loops. if count_FOR_loops > 0 then Emit_1 (CD, k_FOR_Release_Stack, Operand_2_Type (count_FOR_loops)); end if; -- Unconditional jump with dummy address to be patched: Emit_1 (CD, k_Jump, dummy_address_loop - Operand_2_Type (exit_level)); pragma Assert ((not conditional) or else CD.LC = landing_after_jump); end Exit_Statement; procedure IF_Statement is X : Exact_Subtyp; LC0, LC1 : Integer; begin In_Symbol; Boolean_Expression (CD, block_data.context, FSys_St + DO_THEN, X); LC1 := CD.LC; Emit (CD, k_Jump_If_Zero_With_Pop); Need (CD, THEN_Symbol, err_THEN_missing, Forgive => DO_Symbol); -- Statements after "THEN": Sequence_of_Statements_in_a_Conditional_Statement (CD, ELSE_ELSIF_END, block_data); LC0 := CD.LC; -- while CD.Sy = ELSIF_Symbol loop In_Symbol; Emit_1 (CD, k_Jump, dummy_address_if); -- Unconditional jump with dummy address to be patched CD.ObjCode (LC1).Y := Operand_2_Type (CD.LC); -- Patch the previous conditional jump Boolean_Expression (CD, block_data.context, FSys_St + DO_THEN, X); LC1 := CD.LC; Emit (CD, k_Jump_If_Zero_With_Pop); Need (CD, THEN_Symbol, err_THEN_missing, Forgive => DO_Symbol); -- Statements after "ELSIF .. THEN": Sequence_of_Statements_in_a_Conditional_Statement (CD, ELSE_ELSIF_END, block_data); end loop; -- if CD.Sy = ELSE_Symbol then In_Symbol; Emit_1 (CD, k_Jump, dummy_address_if); -- Jump to "END IF" - dummy address to be patched. CD.ObjCode (LC1).Y := Operand_2_Type (CD.LC); -- Statements after "ELSE": Sequence_of_Statements_in_a_Conditional_Statement (CD, END_Set, block_data); else CD.ObjCode (LC1).Y := Operand_2_Type (CD.LC); end if; Need (CD, END_Symbol, err_END_missing); -- END (if) if CD.Sy in CASE_Symbol | LOOP_Symbol | IDent then Error (CD, err_missing_closing_IF_2, severity => minor); In_Symbol; else Need (CD, IF_Symbol, err_missing_closing_IF); -- (end) IF end if; -- Go back and patch the dummy addresses in unconditional jumps Patch_Addresses (CD.ObjCode (LC0 .. CD.LC), dummy_address_if); end IF_Statement; procedure LOOP_Statement (FCT_Loop_End : Opcode; -- Instruction for jumping back to loop begin. LC_At_Begin : Integer; info : Loop_Info) is LC0 : constant Integer := CD.LC; old_is_within_loop : constant Boolean := block_data.context.is_within_loop; begin CD.loop_nesting_level := CD.loop_nesting_level + 1; if CD.loop_nesting_level > loop_nesting_max then Fatal (Loop_Nesting_Levels); -- Exception is raised there. end if; CD.Nested_Loop_Table (CD.loop_nesting_level) := info; if CD.Sy = LOOP_Symbol then In_Symbol; else Error_then_Skip (CD, Statement_Begin_Symbol, err_missing_closing_IF); end if; block_data.context.is_within_loop := True; Sequence_of_Statements (CD, END_Set, block_data); block_data.context.is_within_loop := old_is_within_loop; Emit_1 (CD, FCT_Loop_End, Operand_2_Type (LC_At_Begin)); Need (CD, END_Symbol, err_END_missing); -- END (loop) if CD.Sy in CASE_Symbol | IF_Symbol | IDent then Error (CD, err_missing_closing_LOOP_2, severity => minor); In_Symbol; else Need (CD, LOOP_Symbol, err_missing_closing_LOOP); -- (end) LOOP end if; -- Go back and patch the dummy addresses generated by Exit statements. Patch_Addresses (CD.ObjCode (LC0 .. CD.LC), dummy_address_loop - Operand_2_Type (CD.loop_nesting_level)); CD.loop_nesting_level := CD.loop_nesting_level - 1; end LOOP_Statement; procedure RETURN_Statement is -- Hathorn -- Generate a procedure or function return Statement, calculate return value if req'D. X, Y : Exact_Subtyp; procedure Issue_Type_Mismatch_Error is begin Type_Mismatch (CD, err_type_of_return_statement_doesnt_match, Found => Y, Expected => X); end Issue_Type_Mismatch_Error; begin In_Symbol; if CD.Sy = Semicolon then -- RETURN; if block_data.entity = funktion then Error (CD, err_functions_must_return_a_value); end if; else -- RETURN x; if block_data.entity = prozedure then Error (CD, err_procedures_cannot_return_a_value, severity => major); end if; block_data.return_statement_seen := True; -- Calculate return value (destination: X; expression: Y). if CD.id_table (block_data.block_id_index).block_or_pkg_ref /= CD.Display (block_data.context.level) then raise Program_Error with "Is it `return x` from main? Issue should have been caught earlier: " & "err_procedures_cannot_return_a_value."; end if; X := CD.id_table (block_data.block_id_index).xtyp; Emit_2 (CD, (if CD.id_table (block_data.block_id_index).normal then k_Push_Address else k_Push_Value), Operand_1_Type (CD.id_table (block_data.block_id_index).lev + 1), 0); -- Expression (CD, block_data.context, Semicolon_Set, Y); if X.TYP = Y.TYP then if (X.TYP in Standard_Typ) or else (X.TYP = Enums and then Exact_Typ (X) = Exact_Typ (Y)) then Emit_1 (CD, k_Store, Typen'Pos (X.TYP)); elsif X.Ref /= Y.Ref then Issue_Type_Mismatch_Error; end if; elsif X.TYP = Floats and Y.TYP = Ints then Forbid_Type_Coercion (CD, Found => Y, Expected => X); elsif X.TYP /= NOTYP and Y.TYP /= NOTYP then Issue_Type_Mismatch_Error; end if; end if; if block_data.entity = funktion then Emit_1 (CD, k_Return_Function, Normal_Procedure_Call); elsif block_data.is_main then CD.target.Emit_Halt; else Emit_1 (CD, k_Return_Call, Normal_Procedure_Call); end if; end RETURN_Statement; procedure Delay_Statement is -- Cramer. Generate a Task delay. Y : Exact_Subtyp; begin In_Symbol; if CD.Sy = Semicolon then Error_then_Skip (CD, Semicolon, err_missing_expression_for_delay); else Expression (CD, block_data.context, Semicolon_Set, Y); if Y.TYP /= Floats and Y.TYP /= Durations then Error (CD, err_wrong_type_in_DELAY); end if; if Y.TYP = Floats then -- Duration hack: for expressions like 2.0 * 3600.0, we don't -- know in advance it's not a Duration. Check with a "full -- Ada" compiler the type conformity of the expression. Emit_Std_Funct (CD, SF_Float_to_Duration); end if; end if; Emit (CD, k_Delay); end Delay_Statement; procedure WHILE_Statement (loop_Id : Natural) is -- RM 5.5 (8) X : Exact_Subtyp; LC_Cond_Eval, LC_Cond_Jump : Integer; line_number : constant Natural := CD.CUD.location.line; begin In_Symbol; -- Consume WHILE symbol. LC_Cond_Eval := CD.LC; Boolean_Expression (CD, block_data.context, FSys_St + DO_LOOP, X); LC_Cond_Jump := CD.LC; Emit (CD, k_Jump_If_Zero_With_Pop); LOOP_Statement (k_Jump, LC_Cond_Eval, (loop_Id, False, line_number)); CD.ObjCode (LC_Cond_Jump).Y := Operand_2_Type (CD.LC); end WHILE_Statement; procedure FOR_Statement (label_Id : Natural) is -- RM 5.5 (9) FOR_Begin_Instruction : Opcode; -- Forward or Reverse LC_FOR_Begin, loop_param_id_index, previous_last : Index; loop_param_id, loop_param_id_with_case : Alfa; line_number : constant Natural := CD.CUD.location.line; begin -- -- Pushed on the stack: -- - address of the loop parameter (a temporary iterator variable) -- - lower bound value -- - upper bound value -- In_Symbol; -- Consume FOR symbol. if CD.Sy = IDent then if CD.Id_Count = Id_Table_Max then Fatal (IDENTIFIERS); -- Exception is raised there. end if; -- Declare local loop control Variable -- added Hathorn previous_last := CD.Blocks_Table (CD.Display (block_data.context.level)).Last_Id_Idx; CD.Id_Count := CD.Id_Count + 1; loop_param_id_index := CD.Id_Count; loop_param_id := CD.Id; loop_param_id_with_case := CD.Id_with_case; CD.id_table (loop_param_id_index) := -- Loop parameter: the "i" in "for i in 1..10 loop" (name => Empty_Alfa, -- Hide name because of "for i in 1 .. i loop" name_with_case => Empty_Alfa, link => previous_last, entity => constant_object, decl_kind => complete, xtyp => undefined_subtyp, -- Subtype is determined by the range. block_or_pkg_ref => 0, normal => True, lev => block_data.context.level, adr_or_sz => HAC_Integer (block_data.data_allocation_index), is_referenced => False, is_read => no, is_written_after_init => yes, is_initialized => explicit, location => (0, 0, 0)); CD.target.Mark_Declaration; CD.Blocks_Table (CD.Display (block_data.context.level)).Last_Id_Idx := loop_param_id_index; block_data.data_allocation_index := block_data.data_allocation_index + 1; block_data.max_data_allocation_index := Integer'Max (block_data.max_data_allocation_index, block_data.data_allocation_index); CD.Blocks_Table (CD.Display (block_data.context.level)).VSize := block_data.max_data_allocation_index; else Error (CD, err_identifier_missing, severity => major); end if; Emit_2 (CD, k_Push_Address, Operand_1_Type (CD.id_table (loop_param_id_index).lev), Operand_2_Type (CD.id_table (loop_param_id_index).adr_or_sz)); In_Symbol; FOR_Begin_Instruction := k_FOR_Forward_Begin; Need (CD, IN_Symbol, err_IN_missing); -- "IN" in "for i in reverse 1 .. 10 loop" if CD.Sy = REVERSE_Symbol then -- "REVERSE" in "for i in reverse 1 .. 10 loop" FOR_Begin_Instruction := k_FOR_Reverse_Begin; In_Symbol; end if; Ranges.Dynamic_Range (CD, block_data.context, FSys_St, err_control_variable_of_the_wrong_type, CD.id_table (loop_param_id_index).xtyp); -- ^ Last parameter: set the subtype of "c" in "for c in Red .. Blue loop" LC_FOR_Begin := CD.LC; Emit (CD, FOR_Begin_Instruction); CD.id_table (loop_param_id_index).name := loop_param_id; -- Unhide name CD.id_table (loop_param_id_index).name_with_case := loop_param_id_with_case; -- Unhide name LOOP_Statement (For_END_Instruction (FOR_Begin_Instruction), CD.LC, (label_Id, True, line_number)); -- Patch the loop control exit address; points to the code -- just after the loop's end: CD.ObjCode (LC_FOR_Begin).Y := Operand_2_Type (CD.LC); block_data.data_allocation_index := block_data.data_allocation_index - 1; -- -- Make the loop parameter unusable. The .name_with_case is still -- visible for the compiler dump. Previously, the identifier counter -- was decreased, but that method conflicted with the necessity of -- keeping all loop names within a block. CD.id_table (loop_param_id_index).name := Empty_Alfa; end FOR_Statement; procedure Select_Statement is procedure Select_Error (N : Compile_Diagnostic) is begin Error_then_Skip (CD, Semicolon, N); end Select_Error; -- Either a Timed or Conditional Entry Call. procedure Qualified_Entry_Call is I, J, IStart, IEnd : Integer; patch : array (0 .. 4) of Integer; O : Order; Y : Exact_Subtyp; begin I := Locate_CD_Id (CD, block_data.context.level); if CD.id_table (I).entity = tache then In_Symbol; Entry_Call (CD, block_data.context, FSys_St, I, -1); if CD.ObjCode (CD.LC - 2).F = k_Call then -- Need to patch CallType later patch (0) := CD.LC - 2; else patch (0) := CD.LC - 3; end if; -- LC-1 must be OP=3, update Display patch (1) := CD.LC; -- Need to patch in JMPC address later Emit_1 (CD, k_Jump_If_Zero_With_Pop, dummy_address_if); -- JMPC, address patched in after ELSE -- or OR if CD.Sy = Semicolon then In_Symbol; else Error_then_Skip (CD, Semicolon, err_semicolon_missing); end if; if CD.Sy not in OR_Symbol | ELSE_Symbol then Sequence_of_Statements (CD, ELSE_OR, block_data); end if; if CD.Sy = OR_Symbol then -- =====================> Timed Entry Call CD.ObjCode (patch (0)).X := Timed_Entry_Call; CD.ObjCode (patch (0) + 1).Y := Timed_Entry_Call; -- Exit type matches Entry type In_Symbol; if CD.Sy = DELAY_Symbol then In_Symbol; if CD.Sy = Semicolon then Select_Error (err_missing_expression_for_delay); else -- Calculate delay value patch (2) := CD.LC; Expression (CD, block_data.context, Semicolon_Set, Y); patch (3) := CD.LC - 1; if Y.TYP /= Floats then Select_Error (err_wrong_type_in_DELAY); else -- End of timed Entry select ObjCode, do patching CD.ObjCode (patch (1)).Y := Operand_2_Type (CD.LC); -- if Entry not made, skip rest J := patch (3) - patch (2) + 1; IStart := patch (0); IEnd := CD.LC - 1; while J > 0 loop -- Move delay time ObjCode To before O := CD.ObjCode (IEnd); -- opcodes k_Call, k_Return_Call. for I in reverse IEnd - 1 .. IStart loop CD.ObjCode (I + 1) := CD.ObjCode (I); end loop; CD.ObjCode (IStart) := O; J := J - 1; end loop; In_Symbol; end if; end if; else Select_Error (err_expecting_DELAY); end if; -- end Sy = OrSy else -- Sy = ELSE_Symbol, ===============> Conditional Entry Call CD.ObjCode (patch (0)).X := Conditional_Entry_Call; CD.ObjCode (patch (0) + 1).Y := Conditional_Entry_Call; patch (2) := CD.LC; Emit_1 (CD, k_Jump, dummy_address_if); -- JMP, address patched in after END SELECT patch (3) := CD.LC; In_Symbol; Sequence_of_Statements (CD, END_Set, block_data); CD.ObjCode (patch (1)).Y := Operand_2_Type (patch (3)); CD.ObjCode (patch (2)).Y := Operand_2_Type (CD.LC); end if; if CD.Sy /= END_Symbol then Select_Error (err_END_missing); end if; In_Symbol; if CD.Sy /= SELECT_Symbol then Select_Error (err_SELECT_missing); end if; else Select_Error (err_expecting_task_entry); end if; -- Task.Entry Call expected end Qualified_Entry_Call; procedure Selective_Wait is -- Kurtz <=================== -- Jay, this Buds for you !! JSD, Alt_Patch : Fixed_Size_Patch_Table; ISD, IAlt, StartSel : Integer; SelectDone : Boolean; X, Y : Exact_Subtyp; do_terminate : Boolean; procedure Accept_Statement_2 is -- Kurtz procedure Accept_Call_2 is begin -- Check to make sure parameters match with Entry Statement if CD.Sy = Semicolon then return; end if; if CD.Sy = LParent then -- should be modified -- To check no. and while not (CD.Sy = DO_Symbol or CD.Sy = RParent) loop In_Symbol; end loop; end if; -- of parameters. if CD.Sy = RParent then In_Symbol; end if; end Accept_Call_2; I : Integer; begin -- Accept_Statment_2 In_Symbol; I := Locate_CD_Id (CD, block_data.context.level); if CD.id_table (I).entity /= entree then Select_Error (err_general_error); else CD.target.Mark_Reference (I); end if; In_Symbol; Accept_Call_2; Emit_2 (CD, k_Selective_Wait, 2, Operand_2_Type (I)); -- Retain Entry Index Feed_Patch_Table (Alt_Patch, IAlt, CD.LC); Emit_2 (CD, k_Selective_Wait, 3, Operand_2_Type (CD.LC)); -- ACCEPT IF Ready ELSE Skip To LC -- CONDITIONAL ACCEPT MUST BE ATOMIC if CD.Sy = DO_Symbol then if block_data.context.level = nesting_level_max then Fatal (LEVELS); -- Exception is raised there. end if; block_data.context.level := block_data.context.level + 1; CD.Display (block_data.context.level) := CD.id_table (I).block_or_pkg_ref; In_Symbol; Sequence_of_Statements (CD, END_Set, block_data); Need_END_Symbol (CD); if CD.Sy = IDent then if CD.Id /= CD.id_table (I).name then Select_Error (err_incorrect_name_after_END); else CD.target.Mark_Reference (I); end if; end if; block_data.context.level := block_data.context.level - 1; In_Symbol; end if; Emit_1 (CD, k_End_Rendezvous, Operand_2_Type (I)); end Accept_Statement_2; begin -- Selective_Wait ===============================> Kurtz ISD := 0; IAlt := 0; SelectDone := False; do_terminate := False; StartSel := CD.LC; Emit_2 (CD, k_Selective_Wait, 1, 0); -- START OF SELECT SELECTIVE Wait SEQUENCE loop case CD.Sy is when WHEN_Symbol => Patch_Addresses (CD.ObjCode (CD.ObjCode'First .. CD.LC), Alt_Patch, IAlt); In_Symbol; -- Consume WHEN symbol. Boolean_Expression (CD, block_data.context, FSys_St + Finger, X); In_Symbol; case CD.Sy is when ACCEPT_Symbol => Feed_Patch_Table (Alt_Patch, IAlt, CD.LC); Emit (CD, k_Jump_If_Zero_With_Pop); Accept_Statement_2; when DELAY_Symbol => Feed_Patch_Table (Alt_Patch, IAlt, CD.LC); Emit (CD, k_Jump_If_Zero_With_Pop); In_Symbol; Expression (CD, block_data.context, FSys_St + Semicolon, Y); Emit_2 (CD, k_Selective_Wait, 4, Operand_2_Type (CD.LC + 2)); -- Update delay time if Y.TYP /= Floats then Select_Error (err_wrong_type_in_DELAY); end if; Feed_Patch_Table (Alt_Patch, IAlt, CD.LC); Emit (CD, k_Jump); when others => Select_Error (err_missing_a_procedure_declaration); -- ?? end case; In_Symbol; Sequence_of_Statements (CD, ELSE_END_OR, block_data, True); Feed_Patch_Table (JSD, ISD, CD.LC); Emit (CD, k_Jump); -- patch JMP ADDRESS AT EndSy -- end WHEN_Symbol when ACCEPT_Symbol => Patch_Addresses (CD.ObjCode (CD.ObjCode'First .. CD.LC), Alt_Patch, IAlt); Accept_Statement_2; In_Symbol; Sequence_of_Statements (CD, ELSE_END_OR, block_data, True); Feed_Patch_Table (JSD, ISD, CD.LC); Emit (CD, k_Jump); when OR_Symbol => In_Symbol; -- Consume OR symbol. when ELSE_Symbol => Patch_Addresses (CD.ObjCode (CD.ObjCode'First .. CD.LC), Alt_Patch, IAlt); In_Symbol; Sequence_of_Statements (CD, END_Set, block_data); Feed_Patch_Table (JSD, ISD, CD.LC); Emit (CD, k_Jump); when DELAY_Symbol => Patch_Addresses (CD.ObjCode (CD.ObjCode'First .. CD.LC), Alt_Patch, IAlt); -- Generate a Task delay, calculate return value if req'D In_Symbol; if CD.Sy = Semicolon then Error_then_Skip (CD, Semicolon, err_missing_expression_for_delay); else -- calculate return value Expression (CD, block_data.context, Semicolon_Set, Y); Emit_2 (CD, k_Selective_Wait, 4, Operand_2_Type (CD.LC + 2)); -- Update delay time if Y.TYP /= Floats then Select_Error (err_wrong_type_in_DELAY); end if; Feed_Patch_Table (Alt_Patch, IAlt, CD.LC); Emit (CD, k_Jump); end if; In_Symbol; Sequence_of_Statements (CD, ELSE_END_OR, block_data, True); Feed_Patch_Table (JSD, ISD, CD.LC); Emit (CD, k_Jump); when TERMINATE_Symbol => In_Symbol; if CD.Sy /= Semicolon then Select_Error (err_semicolon_missing); end if; do_terminate := True; -- Oguz In_Symbol; when END_Symbol => In_Symbol; if CD.Sy /= SELECT_Symbol then Select_Error (err_END_missing); end if; SelectDone := True; Patch_Addresses (CD.ObjCode (CD.ObjCode'First .. CD.LC), Alt_Patch, IAlt); if do_terminate then Emit_2 (CD, k_Selective_Wait, 5, Operand_2_Type (StartSel)); else Emit_2 (CD, k_Selective_Wait, 6, Operand_2_Type (StartSel)); end if; -- Suspend Patch_Addresses (CD.ObjCode (CD.ObjCode'First .. CD.LC), JSD, ISD); when others => SelectDone := True; end case; exit when SelectDone; end loop; end Selective_Wait; begin In_Symbol; -- Consume SELECT symbol. case CD.Sy is when ACCEPT_Symbol | WHEN_Symbol => Selective_Wait; In_Symbol; when IDent => -- Task Entry objectName. Qualified_Entry_Call; In_Symbol; -- Timed or Conditional Entry Call (?) when others => Select_Error (err_expecting_accept_when_or_entry_id); end case; end Select_Statement; procedure Block_Statement (block_name : Alfa) is -- RM: 5.6 block_statement_data : Block_Data_Type; begin Error ( CD, err_not_yet_implemented, hint_1 => "Block statements don't work yet", severity => major ); -- block_statement_data.context.level := block_data.context.level + 1; block_statement_data.block_id_index := CD.Id_Count; block_statement_data.entity := block_data.entity; block_statement_data.is_main := False; block_statement_data.previous_declaration_id_index := No_Id; Block (CD, FSys_St, True, block_statement_data, block_name, block_name); -- !! up/low case -- -- !! to check: -- !! * stack management of variables when entering / quitting the block -- !! * object code and nesting... works on some cases at least (test.adb) !... -- !! Perhaps keep same level but have local declarations as for the -- variable in a FOR_Statement. -- !! Either both FOR and Block statements forget their definitions, or there -- is perhaps a problem with the stack (DX). -- !! Local bodies of subprograms surely mess the object code. end Block_Statement; procedure Named_Statement is -- Block_Statement or loop, named by a label, like this: -- "name : loop". -- We remember the identifier for checking purposes. new_ident_for_statement : constant Alfa := CD.Id; new_ident_for_statement_with_case : constant Alfa := CD.Id_with_case; -- procedure Check_ID_after_END_LOOP is -- RM 5.5 (5) procedure Boom (err : Compile_Diagnostic) is begin Error (CD, err, A2S (new_ident_for_statement_with_case)); end Boom; begin if CD.Sy = IDent then if CD.Id /= new_ident_for_statement then Boom (err_END_LOOP_ident_wrong); end if; In_Symbol; -- Consume identifier. else Boom (err_END_LOOP_ident_missing); end if; end Check_ID_after_END_LOOP; -- dummy_idx : Natural; begin Enter_Simple (CD, block_data.context.level, new_ident_for_statement, new_ident_for_statement_with_case, loop_identifier, dummy_idx); if CD.Sy /= Colon then Error (CD, err_colon_missing_for_named_statement, A2S (new_ident_for_statement_with_case), severity => major); end if; In_Symbol; -- Consume ':' symbol. case CD.Sy is when BEGIN_Symbol | DECLARE_Symbol => -- Named Block_Statement Block_Statement (new_ident_for_statement); when FOR_Symbol => FOR_Statement (CD.Id_Count); Check_ID_after_END_LOOP; when LOOP_Symbol => LOOP_Statement (k_Jump, CD.LC, (CD.Id_Count, False, CD.CUD.location.line)); Check_ID_after_END_LOOP; when WHILE_Symbol => WHILE_Statement (CD.Id_Count); Check_ID_after_END_LOOP; when others => Error (CD, err_general_error); end case; end Named_Statement; procedure Statement_starting_with_an_Identifier is I_Statement : constant Integer := Locate_CD_Id (CD, block_data.context.level, Fail_when_No_Id => False); begin In_Symbol; if I_Statement = No_Id then -- Unknown identifier: must be an identifier for a named Block_Statement or loop. Named_Statement; else case CD.id_table (I_Statement).entity is when Object_Kind => Assignment (CD, FSys_St, block_data.context, I_Statement, check_is_variable => True); Elevate_to_Maybe_or_Yes (CD.id_table (I_Statement).is_written_after_init, block_data.context); when declared_number_or_enum_item => Error (CD, err_illegal_statement_start_symbol, "constant or an enumeration item", severity => major); when type_mark => Error (CD, err_illegal_statement_start_symbol, "type name", severity => major); when funktion | funktion_intrinsic => Error (CD, err_illegal_statement_start_symbol, "function name", severity => major); when tache => Entry_Call (CD, block_data.context, FSys_St, I_Statement, Normal_Entry_Call); when prozedure => Subprogram_or_Entry_Call (CD, block_data.context, FSys_St, I_Statement, Normal_Procedure_Call); when prozedure_intrinsic => Standard_Procedures.Standard_Procedure (CD, block_data.context, FSys_St, SP_Code'Val (CD.id_table (I_Statement).adr_or_sz)); when loop_identifier => Error (CD, err_duplicate_loop_identifier, A2S (CD.Id), severity => major); when paquetage => Error (CD, err_illegal_statement_start_symbol, "package name", severity => major); when others => Error (CD, err_illegal_statement_start_symbol, ". Entity found: " & Entity_Kind'Image (CD.id_table (I_Statement).entity), severity => major); end case; end if; end Statement_starting_with_an_Identifier; procedure Process_Name_for_Unnamed_Loop is begin if CD.Sy = IDent then Error (CD, err_general_error, "loop starting at line" & CD.Nested_Loop_Table (CD.loop_nesting_level + 1).start_line'Image & " has no name"); In_Symbol; -- Recovery. end if; end Process_Name_for_Unnamed_Loop; begin -- Statement if CD.error_count > 0 then return; end if; if Statement_Begin_Symbol (CD.Sy) then case CD.Sy is when IDent => Statement_starting_with_an_Identifier; when ACCEPT_Symbol => Accept_Statement; when BEGIN_Symbol | DECLARE_Symbol => -- Anonymous Block Statement Block_Statement (Empty_Alfa); when CASE_Symbol => CASE_Statement (CD, FSys_St, block_data); when DELAY_Symbol => Delay_Statement; when EXIT_Symbol => Exit_Statement; when FOR_Symbol => FOR_Statement (No_Id); Process_Name_for_Unnamed_Loop; when IF_Symbol => IF_Statement; when LOOP_Symbol => LOOP_Statement (k_Jump, CD.LC, (No_Id, False, CD.CUD.location.line)); Process_Name_for_Unnamed_Loop; when NULL_Symbol => In_Symbol; -- Just consume the NULL symbol. when RETURN_Symbol => RETURN_Statement; when SELECT_Symbol => Select_Statement; when WHILE_Symbol => WHILE_Statement (No_Id); Process_Name_for_Unnamed_Loop; when others => null; end case; -- Need_Semicolon (CD); end if; -- CD.Sy in Statement_Begin_Symbol -- Test (CD, FSys_St - Semicolon, Semicolon_Set, err_incorrectly_used_symbol); end Statement; end HAC_Sys.Parser.Statements; ================================================ FILE: src/compile/hac_sys-parser-statements.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- private package HAC_Sys.Parser.Statements is procedure Assignment (CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; context : Defs.Flow_Context; var_id_index : Integer; check_is_variable : Boolean); procedure Sequence_of_Statements -- Ada RM 5.1 (2) (CD : in out Co_Defs.Compiler_Data; sentinel : Defs.Symset; block_data : in out Block_Data_Type; optional : Boolean := False); procedure Sequence_of_Statements_in_a_Conditional_Statement (CD : in out Co_Defs.Compiler_Data; sentinel : Defs.Symset; block_data : in out Block_Data_Type; optional : Boolean := False); end HAC_Sys.Parser.Statements; ================================================ FILE: src/compile/hac_sys-parser-tasking.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Enter_Def, HAC_Sys.Parser.Helpers, HAC_Sys.PCode, HAC_Sys.Scanner, HAC_Sys.Errors; package body HAC_Sys.Parser.Tasking is use Compiler, Compiler.PCode_Emit, Co_Defs, Defs, Enter_Def, Helpers, PCode, Errors; use type HAC_Integer; ------------------------------------------------------------------ -------------------------------------------------Task_Declaration- -- Hathorn procedure Task_Declaration ( CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; Initial_Level : Defs.Nesting_Level ) is Level : Nesting_Level := Initial_Level; saveLineCount : constant Integer := CD.CUD.location.line; -- Source line where Task appeared procedure In_Symbol is begin Scanner.In_Symbol (CD); end In_Symbol; I, T0 : Integer; TaskID, TaskID_with_case : Alfa; task_block : Block_Data_Type; forward_id_idx : Natural; use type Alfa; begin In_Symbol; if CD.Sy = BODY_Symbol then -- Task Body In_Symbol; I := Locate_CD_Id (CD, Level); TaskID := CD.id_table (I).name; TaskID_with_case := CD.id_table (I).name_with_case; CD.Blocks_Table (CD.id_table (I).block_or_pkg_ref).SrcFrom := saveLineCount; -- (* Manuel *) In_Symbol; task_block.context.level := Level + 1; task_block.block_id_index := I; task_block.entity := entree; task_block.is_main := False; task_block.previous_declaration_id_index := No_Id; Block (CD, FSys, False, task_block, TaskID, TaskID_with_case); Emit_1 (CD, k_Return_Call, Normal_Procedure_Call); else -- Task Specification if CD.Sy = IDent then TaskID := CD.Id; TaskID_with_case := CD.Id_with_case; else Error (CD, err_identifier_missing); CD.Id := Empty_Alfa; TaskID := Empty_Alfa; TaskID_with_case := Empty_Alfa; end if; CD.Tasks_Definitions_Count := CD.Tasks_Definitions_Count + 1; if CD.Tasks_Definitions_Count > TaskMax then Fatal (TASKS); -- Exception is raised there. end if; Enter_Prefixed (CD, Level, TaskID, TaskID_with_case, tache, forward_id_idx); CD.Tasks_Definitions_Table (CD.Tasks_Definitions_Count) := CD.Id_Count; Enter_Block (CD, CD.Id_Count); CD.id_table (CD.Id_Count).block_or_pkg_ref := CD.Blocks_Count; In_Symbol; if CD.Sy = Semicolon then In_Symbol; -- Task with no entries else -- Parsing the Entry specs Need (CD, IS_Symbol, err_IS_missing); if Level = nesting_level_max then Fatal (LEVELS); -- Exception is raised there. end if; Level := Level + 1; CD.Display (Level) := CD.Blocks_Count; while CD.Sy = ENTRY_Symbol loop In_Symbol; if CD.Sy /= IDent then Error (CD, err_identifier_missing); CD.Id := Empty_Alfa; end if; CD.Entries_Count := CD.Entries_Count + 1; if CD.Entries_Count > entry_table_max then Fatal (ENTRIES); -- Exception is raised there. end if; Enter_Prefixed (CD, Level, CD.Id, CD.Id_with_case, entree, forward_id_idx); CD.Entries_Table (CD.Entries_Count) := CD.Id_Count; -- point to identifier table location T0 := CD.Id_Count; -- of TaskID In_Symbol; task_block.context.level := Level + 1; task_block.block_id_index := CD.Id_Count; task_block.entity := entree; task_block.is_main := False; task_block.previous_declaration_id_index := No_Id; Block (CD, FSys, False, task_block, CD.id_table (CD.Id_Count).name, CD.id_table (CD.Id_Count).name_with_case); CD.id_table (T0).adr_or_sz := HAC_Integer (CD.Tasks_Definitions_Count); if CD.Sy = Semicolon then In_Symbol; else Error (CD, err_semicolon_missing); end if; end loop; -- while CD.Sy = ENTRY_Symbol Level := Level - 1; Need_END_Symbol (CD); if CD.Sy = IDent and then CD.Id = TaskID then In_Symbol; else Error_then_Skip (CD, Semicolon, err_incorrect_name_after_END); end if; Need_Semicolon_after_Declaration (CD, FSys); end if; end if; pragma Assert (Level = Initial_Level); end Task_Declaration; end HAC_Sys.Parser.Tasking; ================================================ FILE: src/compile/hac_sys-parser-tasking.ads ================================================ private package HAC_Sys.Parser.Tasking is ------------------------------------------------------------------ -------------------------------------------------Task_Declaration- -- Hathorn procedure Task_Declaration ( CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; Initial_Level : Defs.Nesting_Level ); end HAC_Sys.Parser.Tasking; ================================================ FILE: src/compile/hac_sys-parser-type_conversion.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Expressions, HAC_Sys.Parser.Helpers, HAC_Sys.PCode, HAC_Sys.Errors; procedure HAC_Sys.Parser.Type_Conversion -- Ada RM 4.6 (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Typ_ID : in Co_Defs.Identifier_Table_Entry; X : in Co_Defs.Exact_Subtyp) is use Defs, Helpers, PCode, Errors; type Type_Conversion_Kind is (To_Float, To_Integer, To_Duration, To_Bools, Unknown); kind : Type_Conversion_Kind; T_Expr : Co_Defs.Exact_Subtyp; begin -- X is the type of the name just parsed, as in the identifier table. -- E.g.: "Natural (12.34)" -> X is from Standard.Natural as entered by the librarian. case X.TYP is when Floats => kind := To_Float; when Ints => kind := To_Integer; when Durations => kind := To_Duration; when Bools => kind := To_Bools; when others => kind := Unknown; end case; -- Expressions.Expression (CD, context, FSys + RParent, T_Expr); -- T_Expr is the type of the expression between the parentheses. -- E.g.: "Natural (12.34)" -> X.TYP is Floats because of 12.34. -- case kind is when To_Float => case T_Expr.TYP is when Floats => null; -- Useless conversion if we have the same named subtype when Ints => Compiler.PCode_Emit.Emit_1 (CD, k_Integer_to_Float, 0); when Durations => Compiler.PCode_Emit.Emit_Std_Funct (CD, SF_Duration_to_Float); when others => Argument_Type_Not_Supported (CD); end case; -- when To_Integer => case T_Expr.TYP is when Floats => -- Rounding to closest integer (Ada RM 4.6 (33)). Compiler.PCode_Emit.Emit_Std_Funct (CD, SF_Round_Float_to_Int); when Durations => Compiler.PCode_Emit.Emit_Std_Funct (CD, SF_Duration_to_Int); when Ints => null; -- Useless conversion if we have the same named subtype when others => Argument_Type_Not_Supported (CD); end case; Compiler.PCode_Emit.Emit_Lower_Bound_Check (CD, X); Compiler.PCode_Emit.Emit_Upper_Bound_Check (CD, X); -- when To_Duration => case T_Expr.TYP is when Floats => Compiler.PCode_Emit.Emit_Std_Funct (CD, SF_Float_to_Duration); when Ints => Compiler.PCode_Emit.Emit_Std_Funct (CD, SF_Int_to_Duration); when Durations => null; -- Useless conversion if we have the same named subtype when others => Argument_Type_Not_Supported (CD); end case; when To_Bools => if T_Expr.TYP = Bools then Remark (CD, note_redundant_construct, "redundant conversion to type ""Boolean"""); else Argument_Type_Not_Supported (CD); end if; when Unknown => Error ( CD, err_type_conversion_not_supported, "no support for target type " & A2S (Typ_ID.name_with_case) ); end case; Need (CD, RParent, err_closing_parenthesis_missing); end HAC_Sys.Parser.Type_Conversion; ================================================ FILE: src/compile/hac_sys-parser-type_conversion.ads ================================================ -- The subtype name has just been parsed, its identifier is in Type_ID. -- This identification method works only for standard types, -- which is currently the only option. -- The symbol "(" has been parsed too. private procedure HAC_Sys.Parser.Type_Conversion -- Ada RM 4.6 (CD : in out Co_Defs.Compiler_Data; context : in Defs.Flow_Context; FSys : in Defs.Symset; Typ_ID : in Co_Defs.Identifier_Table_Entry; X : in Co_Defs.Exact_Subtyp); ================================================ FILE: src/compile/hac_sys-parser-type_def.adb ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Parser.Enter_Def, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Ranges, HAC_Sys.Scanner, HAC_Sys.Errors; with HAT; with Ada.Characters.Handling; package body HAC_Sys.Parser.Type_Def is use Co_Defs, Defs, Enter_Def, Helpers, Errors; use type HAC_Integer; procedure Type_or_Subtype_Declaration (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys_NTD : in Defs.Symset) is T1 : Integer; forward_id_idx : Natural; is_subtype : constant Boolean := CD.Sy = SUBTYPE_Symbol; begin Scanner.In_Symbol (CD); -- Consume TYPE or SUBTYPE symbol. Test (CD, IDent_Set, Semicolon_Set, err_identifier_missing); Enter_Prefixed (CD, Level, CD.Id, CD.Id_with_case, type_mark, forward_id_idx); T1 := CD.Id_Count; Scanner.In_Symbol (CD); if CD.Sy = LParent then Error (CD, err_not_yet_implemented, "discriminants (type parameters), Ada RM 3.7", severity => major); end if; Need (CD, IS_Symbol, err_IS_missing); declare New_T : Identifier_Table_Entry renames CD.id_table (T1); begin if is_subtype then Subtype_Indication (CD, Level, FSys_TD => Comma_IDent_Semicolon + FSys_NTD, xTP => New_T.xtyp, Size => Integer (New_T.adr_or_sz)); else Type_Definition (CD, Level, FSys_TD => Comma_IDent_Semicolon + FSys_NTD, xTP => New_T.xtyp, Size => Integer (New_T.adr_or_sz)); end if; end; -- Need_Semicolon_after_Declaration (CD, FSys_NTD); end Type_or_Subtype_Declaration; log_max_index : constant HAT.Real := HAT.Log (HAT.Real (Index'Last)); -- constrained_array_definition 3.6 (5) : "array (1 .. 2, 3 .. 4) of Integer;" -- index_constraint 3.6.1 (2) : "Matrix (1 .. 2, 3 .. 4);" -- procedure Array_Typ (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys_TD : in Defs.Symset; arr_tab_ref, arr_size, arr_dimensions : out Integer; string_constrained_subtype : Boolean) is Element_Exact_Subtyp, Index_Exact_Subtyp : Exact_Subtyp; Element_Size : Integer; recursive_dimensions : Natural := 0; Lower_Bound, Higher_Bound : Constant_Rec; new_dim_size : HAC_Integer; use HAT, Ranges; begin Static_Range (CD, Level, FSys_TD, err_illegal_array_bounds, Lower_Bound, Higher_Bound); Index_Exact_Subtyp := Lower_Bound.TP; Index_Exact_Subtyp.Discrete_First := Lower_Bound.I; Index_Exact_Subtyp.Discrete_Last := Higher_Bound.I; Enter_Array (CD, Index_Exact_Subtyp); arr_tab_ref := CD.Arrays_Count; if string_constrained_subtype then -- We define String (L .. H) exactly as an "array (L .. H) of Character". Construct_Root (Element_Exact_Subtyp, Chars); Element_Exact_Subtyp.Discrete_First := 0; Element_Exact_Subtyp.Discrete_Last := 255; Element_Size := 1; Need (CD, RParent, err_closing_parenthesis_missing, Forgive => RBrack); elsif CD.Sy = Comma then -- Multidimensional array is equivalant to: array (range_1) of array (range_2,...). Scanner.In_Symbol (CD); -- Consume ',' symbol. Construct_Root (Element_Exact_Subtyp, Arrays); -- Recursion for next array dimension. Array_Typ (CD, Level, FSys_TD, Element_Exact_Subtyp.Ref, Element_Size, recursive_dimensions, False); else Need (CD, RParent, err_closing_parenthesis_missing, Forgive => RBrack); Need (CD, OF_Symbol, err_missing_OF); -- "of" in "array (...) of Some_Type" if Type_Begin_Symbol (CD.Sy) then Error (CD, err_general_error, "anonymous definition not permitted here"); -- Recovery: Type_Definition (CD, Level, FSys_TD, Element_Exact_Subtyp, Element_Size); else -- RM 3.6 (2) -- Here is a component_definition, which is a -- subtype indication (possibly aliased). Subtype_Indication (CD, Level, FSys_TD, Element_Exact_Subtyp, Element_Size); end if; end if; if Element_Size = 0 then -- Happens when the element type is undefined (source is already in error) or -- if the element type is an empty array type. arr_size := 0; else new_dim_size := Higher_Bound.I - Lower_Bound.I + 1; if new_dim_size <= 0 then -- This dimension is empty. arr_size := 0; elsif Log (Real (new_dim_size)) + Log (Real (Element_Size)) < log_max_index then arr_size := Integer (new_dim_size) * Element_Size; else Error (CD, err_illegal_array_bounds, "array is too large (more than" & Defs.Index'Last'Image & " elements)"); arr_size := 0; end if; end if; arr_dimensions := 1 + recursive_dimensions; declare New_A : Array_Table_Entry renames CD.Arrays_Table (arr_tab_ref); begin -- New_A.Index_xTyp already set by Enter_Array. New_A.Array_Size := arr_size; New_A.Element_xTyp := Element_Exact_Subtyp; New_A.Element_Size := Element_Size; New_A.dimensions := arr_dimensions; end; end Array_Typ; procedure Type_Definition (CD : in out Co_Defs.Compiler_Data; Initial_Level : in Defs.Nesting_Level; FSys_TD : in Defs.Symset; xTP : out Co_Defs.Exact_Subtyp; Size : out Integer) is Level : Nesting_Level := Initial_Level; procedure In_Symbol is begin Scanner.In_Symbol (CD); end In_Symbol; procedure Enumeration_Typ is -- RM 3.5.1 Enumeration Types enum_count : Natural := 0; forward_id_idx : Natural; begin xTP.Construct_Root (Enums); xTP.Ref := CD.Id_Count; loop In_Symbol; -- Consume '(' symbol. if CD.Sy = IDent then enum_count := enum_count + 1; Enter_Prefixed (CD, Level, CD.Id, CD.Id_with_case, declared_number_or_enum_item, forward_id_idx); declare new_enum_item : Identifier_Table_Entry renames CD.id_table (CD.Id_Count); begin new_enum_item.xtyp := xTP; new_enum_item.adr_or_sz := HAC_Integer (enum_count - 1); -- RM 3.5.1 (7): position begins with 0. new_enum_item.is_referenced := False; end; else Error (CD, err_identifier_missing); end if; In_Symbol; exit when CD.Sy /= Comma; end loop; Size := 1; xTP.Discrete_First := 0; xTP.Discrete_Last := HAC_Integer (enum_count - 1); Need (CD, RParent, err_closing_parenthesis_missing); end Enumeration_Typ; procedure Record_Typ is -- RM 3.8 Field_Exact_Subtyp : Exact_Subtyp; Field_Size, Offset, T0, T1 : Integer; begin In_Symbol; -- Consume RECORD symbol. Enter_Block (CD, CD.Id_Count); Construct_Root (xTP, Records); xTP.Ref := CD.Blocks_Count; if Level = nesting_level_max then Fatal (LEVELS); -- Exception is raised there. end if; Level := Level + 1; CD.Display (Level) := CD.Blocks_Count; Offset := 0; -- loop if CD.Sy = IDent then -- RM 3.8: Record component declaration T0 := CD.Id_Count; Enter_Variables (CD, Level, False); Need (CD, Colon, err_colon_missing); -- ':' in "a, b, c : Integer;" T1 := CD.Id_Count; if Type_Begin_Symbol (CD.Sy) then Error (CD, err_general_error, "anonymous definition not permitted here"); -- Recovery: Type_Definition (CD, Level, FSys_TD + Comma_END_IDent_Semicolon, Field_Exact_Subtyp, Field_Size); else -- RM 3.6 (2) -- Here is a component_definition, which is a -- subtype indication (possibly aliased). Subtype_Indication (CD, Level, FSys_TD + Comma_END_IDent_Semicolon, Field_Exact_Subtyp, Field_Size); end if; while T0 < T1 loop T0 := T0 + 1; CD.id_table (T0).xtyp := Field_Exact_Subtyp; CD.id_table (T0).adr_or_sz := HAC_Integer (Offset); Offset := Offset + Field_Size; end loop; else Error (CD, err_identifier_missing, severity => major); end if; Need_Semicolon (CD); exit when CD.Sy = END_Symbol; end loop; -- CD.Blocks_Table (xTP.Ref).VSize := Offset; Size := Offset; CD.Blocks_Table (xTP.Ref).PSize := 0; In_Symbol; Need (CD, RECORD_Symbol, err_RECORD_missing); -- (END) RECORD Level := Level - 1; end Record_Typ; dummy_dims : Natural; begin xTP := undefined_subtyp; Size := 0; if CD.Sy in ABSTRACT_Symbol | ACCESS_Symbol | DIGITS_Symbol | DELTA_Symbol | INTERFACE_Symbol | LIMITED_Symbol | NOT_Symbol | NEW_Symbol | PRIVATE_Symbol | PROTECTED_Symbol | RANGE_Keyword_Symbol | SYNCHRONIZED_Symbol | TASK_Symbol | TAGGED_Symbol then Error (CD, err_not_yet_implemented, ": type definitions starting with """ & Ada.Characters.Handling.To_Lower (A2S (CD.Id)) & '"', severity => major); end if; Test (CD, Type_Begin_Symbol, FSys_TD, err_missing_type_begin_symbol); if Type_Begin_Symbol (CD.Sy) then case CD.Sy is when ARRAY_Symbol => In_Symbol; Need (CD, LParent, err_missing_an_opening_parenthesis, Forgive => LBrack); Construct_Root (xTP, Arrays); Array_Typ (CD, Level, FSys_TD, xTP.Ref, Size, dummy_dims, string_constrained_subtype => False); when RECORD_Symbol => Record_Typ; when LParent => Enumeration_Typ; when others => null; end case; Test (CD, FSys_TD, empty_symset, err_incorrectly_used_symbol); end if; if CD.error_count = 0 then pragma Assert (Level = Initial_Level); end if; end Type_Definition; procedure Subtype_Indication (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys_TD : in Defs.Symset; xTP : out Co_Defs.Exact_Subtyp; Size : out Integer) is procedure In_Symbol is begin Scanner.In_Symbol (CD); end In_Symbol; dummy_dims : Natural; procedure String_Sub_Typ is -- Prototype of constraining an array type: String -> String (1 .. 26) -- We need to implement general constraints one day... begin In_Symbol; Need (CD, LParent, err_missing_an_opening_parenthesis, Forgive => LBrack); Construct_Root (xTP, Arrays); Array_Typ (CD, Level, FSys_TD, xTP.Ref, Size, dummy_dims, string_constrained_subtype => True); end String_Sub_Typ; Ident_Index : Integer; -- Here we are sitting, say, on `Character` in `subtype My_Chars is Character` [range 'a' .. 'z'] -- procedure Sub_Typ is Low, High : Constant_Rec; begin if Ident_Index = No_Id then return; -- Error already issued due to undefined identifier end if; declare Id_T : Identifier_Table_Entry renames CD.id_table (Ident_Index); begin if Id_T.entity = type_mark then xTP := Id_T.xtyp; Size := Integer (Id_T.adr_or_sz); if xTP.TYP = NOTYP then Error (CD, err_undefined_type); end if; else Error (CD, err_missing_a_type_identifier); end if; end; In_Symbol; if CD.Sy = RANGE_Keyword_Symbol then -- Here comes the optional ` range 'a' .. 'z' ` constraint. In_Symbol; Ranges.Explicit_Static_Range (CD, Level, FSys_TD, err_range_constraint_error, Low, High); Ranges.Check_Explicit_Static_Range_Against_Parent_Type (CD, Low, High, xTP, True); end if; end Sub_Typ; begin xTP := undefined_subtyp; Size := 0; if CD.Sy = NOT_Symbol then Error (CD, err_not_yet_implemented, ": subtype indications starting with """ & Ada.Characters.Handling.To_Lower (A2S (CD.Id)) & '"', severity => major); end if; Test (CD, Subtype_Begin_Symbol, FSys_TD, err_identifier_missing); if CD.Sy /= IDent then -- Normally this case should have been filtered out before. Error (CD, err_general_error, severity => major); end if; Ident_Index := Locate_CD_Id (CD, Level); if Ident_Index = CD.String_Id_Index then String_Sub_Typ; else Sub_Typ; end if; Test (CD, FSys_TD, empty_symset, err_incorrectly_used_symbol); end Subtype_Indication; end HAC_Sys.Parser.Type_Def; ================================================ FILE: src/compile/hac_sys-parser-type_def.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- private package HAC_Sys.Parser.Type_Def is -- Package around type definitions. ------------------------------------------------------------------ --------------------------------------Type_or_Subtype_Declaration- -- Type Declarations : RM 3.2.1 -- Subtype Declarations: RM 3.2.2 -- -- Parses "[sub]type T is ..." right after the "[sub]type" symbol. -- Depending on the symbol (SUBTYPE or TYPE), the parser will -- look for either a Subtype_Indication or a Type_Definition. -- procedure Type_or_Subtype_Declaration (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys_NTD : in Defs.Symset); ------------------------------------------------------------------ -----------------------------------Type_Definition - RM 3.2.1 (4)- -- procedure Type_Definition (CD : in out Co_Defs.Compiler_Data; Initial_Level : in Defs.Nesting_Level; FSys_TD : in Defs.Symset; xTP : out Co_Defs.Exact_Subtyp; Size : out Integer); ------------------------------------------------------------------ --------------------------------Subtype_Indication - RM 3.2.2 (2)- -- procedure Subtype_Indication (CD : in out Co_Defs.Compiler_Data; Level : in Defs.Nesting_Level; FSys_TD : in Defs.Symset; xTP : out Co_Defs.Exact_Subtyp; Size : out Integer); end HAC_Sys.Parser.Type_Def; ================================================ FILE: src/compile/hac_sys-parser.adb ================================================ with HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Enter_Def, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Packages, HAC_Sys.Parser.Statements, HAC_Sys.Parser.Tasking, HAC_Sys.Parser.Const_Var, HAC_Sys.Parser.Type_Def, HAC_Sys.PCode, HAC_Sys.Scanner, HAC_Sys.Errors; with HAT; package body HAC_Sys.Parser is ------------------------------------------------------------------ ------------------------------------------------------------Block- procedure Block (CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; Is_a_block_statement : Boolean; -- 5.6 Block Statements Initial_Block_Data : Block_Data_Type; Block_Id : Defs.Alfa; -- Name of this block (if any) Block_Id_with_case : Defs.Alfa) is use Co_Defs, Defs, Enter_Def, Errors, Helpers; use type HAC_Integer; -- block_data : Block_Data_Type := Initial_Block_Data; subprogram_block_index : Integer; -- Was: PRB procedure In_Symbol is begin Scanner.In_Symbol (CD); end In_Symbol; ------------------------------------------------------------------ --------------------------------------------Formal_Parameter_List- procedure Formal_Parameter_List is Sz, X, T0 : Integer; ValParam : Boolean; xTP : Exact_Subtyp := undefined_subtyp; param_kind : Parameter_Kind; in_keyword : Boolean; begin In_Symbol; -- Consume '(' symbol. Sz := 0; Test (CD, IDent_Set, FSys + RParent, err_identifier_missing, stop_on_error => True); -- while CD.Sy = IDent loop T0 := CD.Id_Count; Enter_Variables (CD, block_data.context.level, False); -- if CD.Sy = Colon then -- The ':' in "function F (x, y : in Real) return Real;" In_Symbol; param_kind := param_in; in_keyword := False; if CD.Sy = IN_Symbol then In_Symbol; in_keyword := True; end if; if block_data.entity = funktion then -- If I am a function, no In Out params allowed ValParam := True; elsif CD.Sy = OUT_Symbol then In_Symbol; ValParam := False; param_kind := (if in_keyword then param_in_out else param_out); else ValParam := True; end if; if CD.Sy = IDent then X := Locate_CD_Id (CD, block_data.context.level); In_Symbol; if X = CD.String_Id_Index then -- We could pass string literals as "in" parameter -- if we replaced String_Literals by a record wrapping -- the string length and the index into the string table. Error (CD, err_string_not_supported_as_parameter, severity => major); elsif X /= No_Id then if CD.id_table (X).entity = type_mark then xTP := CD.id_table (X).xtyp; Sz := Integer (if ValParam then CD.id_table (X).adr_or_sz else 1); else Error (CD, err_missing_a_type_identifier, severity => major); end if; end if; -- X /= No_Id else Error (CD, err_identifier_missing); end if; Test (CD, Comma_IDent_RParent_Semicolon, FSys, err_semicolon_missing, stop_on_error => True); -- Update information while T0 < CD.Id_Count loop T0 := T0 + 1; declare r : Identifier_Table_Entry renames CD.id_table (T0); begin r.xtyp := xTP; r.normal := ValParam; r.entity := (if param_kind = param_in then constant_object else variable_object); r.decl_kind := param_kind; r.adr_or_sz := HAC_Integer (block_data.data_allocation_index); r.lev := block_data.context.level; r.is_referenced := False; r.is_read := no; r.is_written_after_init := no; r.is_initialized := (if param_kind = param_out then none else implicit); end; block_data.data_allocation_index := block_data.data_allocation_index + Sz; end loop; -- while T0 < CD.Id_Count else Error (CD, err_colon_missing, severity => major); end if; if CD.Sy /= RParent then Need_Semicolon (CD); Test (CD, IDent_Set, FSys + RParent, err_incorrectly_used_symbol); end if; end loop; -- while Sy = IDent -- if CD.Sy = RParent then In_Symbol; Test (CD, After_Subprogram_Parameters, FSys, err_incorrectly_used_symbol); else Error (CD, err_closing_parenthesis_missing); end if; end Formal_Parameter_List; procedure Declarative_Part is ignored_kind : Declaration_Kind; ignored_needs_body, is_body : Boolean; pkg_spec_index : Index; pkg_kind : Entity_Kind; begin loop Test ( -- Added 17-Apr-2018 to avoid infinite loop on erroneous code CD, Declaration_Symbol + BEGIN_Symbol, empty_symset, err_incorrectly_used_symbol, stop_on_error => True -- Exception is raised there if there is an error. ); case CD.Sy is when IDent => Const_Var.Var_Declaration (CD, FSys, block_data); when TYPE_Symbol | SUBTYPE_Symbol => Type_Def.Type_or_Subtype_Declaration (CD, block_data.context.level, FSys); when TASK_Symbol => Tasking.Task_Declaration (CD, FSys, block_data.context.level); when USE_Symbol => Packages.Use_Clause (CD, block_data.context.level, False); when PROCEDURE_Symbol | FUNCTION_Symbol => Subprogram_Declaration_or_Body (CD, FSys, block_data.context.level, ignored_kind); when PACKAGE_Symbol => -- Local package (local to a block or subprogram). In_Symbol; is_body := CD.Sy = BODY_Symbol; pkg_kind := paquetage; if is_body then In_Symbol; pkg_kind := paquetage_body; end if; if CD.Sy /= IDent then Error (CD, err_identifier_missing, severity => major); end if; Enter_Prefixed (CD, block_data.context.level, CD.Id, CD.Id_with_case, pkg_kind, pkg_spec_index); if is_body then if pkg_spec_index = No_Id then Error (CD, err_general_error, "missing specification for package body", severity => major); end if; CD.id_table (CD.Id_Count).block_or_pkg_ref := CD.id_table (pkg_spec_index).block_or_pkg_ref; Parser.Packages.Package_Body (CD, empty_symset, block_data); else CD.id_table (CD.Id_Count).decl_kind := spec_resolved; -- Why spec_resolved ? missing bodies for possible suprograms -- in that package are checked anyway. Parser.Packages.Package_Declaration (CD, empty_symset, block_data, ignored_needs_body); end if; In_Symbol; -- Absorb ';' when others => null; end case; CD.Blocks_Table (subprogram_block_index).VSize := block_data.data_allocation_index; exit when CD.Sy = BEGIN_Symbol; end loop; Check_Incomplete_Definitions (CD, block_data.context.level); end Declarative_Part; procedure Statements_Part_Setup is begin block_data.max_data_allocation_index := block_data.data_allocation_index; CD.id_table (block_data.block_id_index).adr_or_sz := HAC_Integer (CD.LC); if block_data.previous_declaration_id_index > No_Id then Link_Forward_Declaration (CD, block_data.previous_declaration_id_index, block_data.block_id_index); end if; -- Copy initialization (elaboration) ObjCode from end of ObjCode table for Init_Code_Idx in reverse CD.CMax + 1 .. CD.CMax + block_data.initialization_object_code_size loop CD.ObjCode (CD.LC) := CD.ObjCode (Init_Code_Idx); CD.LC := CD.LC + 1; end loop; -- Restore CMax to the initial max. -- At lowest nesting level, it will be CDMax. -- For higher levels, it will be CDMax minus the sum of -- current values of ICode for all lower levels. CD.CMax := CD.CMax + block_data.initialization_object_code_size; end Statements_Part_Setup; procedure Statements_Part_Closing is begin CD.Blocks_Table (subprogram_block_index).SrcTo := CD.CUD.location.line; end Statements_Part_Closing; procedure Function_Result_Profile is I_Res_Type : Integer; begin if CD.Sy = RETURN_Symbol then In_Symbol; -- FUNCTION TYPE if CD.Sy = IDent then I_Res_Type := Locate_CD_Id (CD, block_data.context.level); In_Symbol; if I_Res_Type /= 0 then if CD.id_table (I_Res_Type).entity /= type_mark then Error (CD, err_missing_a_type_identifier, severity => major); elsif PCode_Atomic_Nonlimited_Typ (CD.id_table (I_Res_Type).xtyp.TYP) then CD.id_table (block_data.block_id_index).xtyp := CD.id_table (I_Res_Type).xtyp; else Error (CD, err_bad_result_type_for_a_function, severity => major); end if; end if; else Error (CD, err_identifier_missing, severity => major); end if; block_data.return_statement_seen := False; else Error (CD, err_RETURN_missing, severity => major); end if; end Function_Result_Profile; Restore_Block_ID : constant HAT.VString := CD.Full_Block_Id; use HAT; procedure Check_ident_after_END is full_name : VString; -- ^ It can be a library unit name, like: "Parent_1.Child_3.Grandchild_5". begin pragma Assert (CD.Sy = IDent); CD.target.Mark_Reference (Initial_Block_Data.block_id_index); loop full_name := full_name & CD.Id; In_Symbol; exit when CD.Sy /= Period; full_name := full_name & '.'; In_Symbol; if CD.Sy /= IDent then Error (CD, err_identifier_missing); end if; end loop; if full_name /= Block_Id then Error (CD, err_incorrect_name_after_END, hint_1 => A2S (Block_Id_with_case), severity => minor, location_method => previous_symbol); -- ^ Ideally we would enclose the whole wrong full name (x.y.z), -- possibly spanning on several lines. -- But the method is correct on a single wrong identifier, -- the most frequent case. end if; end Check_ident_after_END; procedure Subprogram_Aspect is use Compiler.PCode_Emit, PCode; begin In_Symbol; -- Consume WITH if CD.Sy = IDent then if CD.Id = "IMPORT" then In_Symbol; -- Consume Import Need (CD, Finger, err_general_error); if CD.Id = "TRUE" then In_Symbol; -- Consume True CD.id_table (block_data.block_id_index).adr_or_sz := HAC_Integer (CD.LC); CD.id_table (block_data.block_id_index).decl_kind := spec_resolved; Emit_1 (CD, k_Exchange_with_External, Operand_2_Type (block_data.block_id_index)); Emit_1 (CD, k_Return_Call, Normal_Procedure_Call); else Error (CD, err_general_error, "value True expected here"); end if; end if; else Error (CD, err_general_error); end if; end Subprogram_Aspect; procedure Process_Spec is begin CD.id_table (block_data.block_id_index).decl_kind := spec_unresolved; CD.id_table (block_data.block_id_index).adr_or_sz := -1; -- ^ This invalid address will raise VM_Subprogram_Spec. Check_Duplicate_Specification (CD, block_data.previous_declaration_id_index, Block_Id_with_case); CD.Blocks_Table (subprogram_block_index).VSize := block_data.data_allocation_index; -- if CD.Sy = WITH_Symbol then Subprogram_Aspect; end if; if block_data.context.level > 1 and then block_data.entity /= entree then In_Symbol; -- Consume ';' end if; -- End of subprogram specification part (forward declaration). -- Body is declared later in the containing block or elsewhere in the library. end Process_Spec; procedure Process_Body is begin CD.id_table (block_data.block_id_index).decl_kind := complete; Check_Subprogram_Spec_Body_Consistency (CD, block_data.previous_declaration_id_index, block_data.block_id_index, Block_Id_with_case); -- if Is_a_block_statement then case CD.Sy is when DECLARE_Symbol => In_Symbol; when BEGIN_Symbol => null; when others => raise Internal_error with "Unexpected " & Symbol'Image (CD.Sy); end case; elsif CD.Sy = IS_Symbol then -- The "IS" in "procedure ABC (param : T_Type) IS" In_Symbol; else Error (CD, err_IS_missing); return; end if; -- if CD.Sy = NULL_Symbol and not Is_a_block_statement then -- RM 6.7 Null Procedures (Ada 2005) -- E.g.: "procedure Not_Yet_Done (a : Integer) is null;" In_Symbol; -- Consume NULL symbol. Statements_Part_Setup; if block_data.entity = funktion then -- There are no null functions: what would be the result? Error (CD, err_no_null_functions); else null; -- No statement -> no instruction, like for the NULL statement. end if; Statements_Part_Closing; else Declarative_Part; In_Symbol; -- Consume BEGIN symbol. Statements_Part_Setup; Statements.Sequence_of_Statements (CD, END_Set, block_data); Statements_Part_Closing; -- if CD.remarks (note_unused_item) or CD.remarks (note_constant_variable) or CD.remarks (warn_read_but_not_written) then Check_Unused_or_Uninitialized_Items (CD, block_data.context.level); end if; -- if CD.Sy = END_Symbol then In_Symbol; elsif CD.error_count > 0 then return; -- At this point the program is already FUBAR. else Error (CD, err_END_missing); return; end if; if block_data.entity = funktion and not Is_a_block_statement then if not block_data.return_statement_seen then Error (CD, err_general_error, "missing ""return"" statement in function body", severity => major); end if; end if; -- case CD.Sy is when IDent => -- Found an identifier after "END". Verify that the name matches the unit name. Check_ident_after_END; when CASE_Symbol | IF_Symbol | LOOP_Symbol => -- An extra END CASE, END IF, or END LOOP was found. Error (CD, err_no_X_for_END_X, (case CD.Sy is when CASE_Symbol => "case", when IF_Symbol => "if", when LOOP_Symbol => "loop", when others => ""), severity => major); when others => if Is_a_block_statement and Block_Id /= Empty_Alfa then -- No identifier after "end", but "end [label]" is required in this case. Error (CD, err_incorrect_name_after_END, hint_1 => A2S (Block_Id_with_case)); end if; end case; end if; -- if CD.Sy /= Semicolon then Error (CD, err_semicolon_missing); return; end if; -- if block_data.context.level <= 1 or Is_a_block_statement then -- Time to count the minor errors as errors. CD.error_count := CD.error_count + CD.minor_error_count; CD.minor_error_count := 0; else In_Symbol; -- Consume ';' symbol after END [Subprogram_Id]. Ignore_Extra_Semicolons (CD); -- -- Now we have either another declaration, -- or BEGIN or, if it's a package body, the END symbol. Test (CD, FSys + Declaration_Symbol + BEGIN_Symbol + END_Symbol, empty_symset, err_incorrectly_used_symbol); end if; end Process_Body; begin -- Block if CD.error_count > 0 then return; end if; Increment_Nesting_or_Descending_Level (CD); if CD.Full_Block_Id = Universe then CD.Full_Block_Id := Block_Id_with_case; else CD.Full_Block_Id := CD.Full_Block_Id & '.' & Block_Id_with_case; end if; block_data.data_allocation_index := fixed_area_size; -- Fixed area of the subprogram activation record. block_data.initialization_object_code_size := 0; if Is_a_block_statement then null; -- We should be here with Sy = BEGIN_Symbol or Sy = DECLARE_Symbol. else Test (CD, Symbols_after_Subprogram_Identifier, FSys, err_incorrectly_used_symbol); end if; if CD.id_table (block_data.block_id_index).block_or_pkg_ref > 0 then subprogram_block_index := CD.id_table (block_data.block_id_index).block_or_pkg_ref; else Enter_Block (CD, block_data.block_id_index); subprogram_block_index := CD.Blocks_Count; CD.id_table (block_data.block_id_index).block_or_pkg_ref := subprogram_block_index; end if; CD.Display (block_data.context.level) := subprogram_block_index; CD.id_table (block_data.block_id_index).xtyp := undefined_subtyp; CD.Blocks_Table (subprogram_block_index).First_Param_Id_Idx := CD.Id_Count + 1; if CD.Sy = LParent then Formal_Parameter_List; end if; -- if CD.error_count > 0 then return; end if; -- CD.Blocks_Table (subprogram_block_index).Last_Param_Id_Idx := CD.Id_Count; CD.Blocks_Table (subprogram_block_index).PSize := block_data.data_allocation_index; -- if block_data.entity = funktion and not Is_a_block_statement then Function_Result_Profile; end if; -- if CD.Sy = Semicolon or CD.Sy = WITH_Symbol -- Aspect then Process_Spec; else Process_Body; end if; CD.Full_Block_Id := Restore_Block_ID; Decrement_Nesting_or_Descending_Level (CD); if CD.error_count = 0 then pragma Assert (block_data.context.level = Initial_Block_Data.context.level); end if; end Block; procedure Subprogram_Declaration_or_Body (CD : in out Co_Defs.Compiler_Data; FSys : in Defs.Symset; current_level : in Defs.Nesting_Level; kind : out Co_Defs.Declaration_Kind) is use Co_Defs, Compiler.PCode_Emit, Defs, Enter_Def, Errors, PCode; use type HAC_Integer; -- new_id_idx, old_id_idx : Natural; IsFun : constant Boolean := CD.Sy = FUNCTION_Symbol; sub_sub_prog_block_data : Block_Data_Type; begin Scanner.In_Symbol (CD); if CD.Sy /= IDent then Error (CD, err_identifier_missing); CD.Id := Empty_Alfa; end if; declare id_subprog : constant Alfa := CD.Id; id_subprog_with_case : constant Alfa := CD.Id_with_case; begin Enter_Prefixed (CD, current_level, CD.Id, id_subprog_with_case, (if IsFun then funktion else prozedure), old_id_idx); -- NB: now old_id_idx, if different than No_Id, points to the -- possible previous declaration of the subprogram with that name. Scanner.In_Symbol (CD); sub_sub_prog_block_data.context.level := current_level + 1; sub_sub_prog_block_data.block_id_index := CD.Id_Count; sub_sub_prog_block_data.entity := (if IsFun then funktion else prozedure); sub_sub_prog_block_data.is_main := False; sub_sub_prog_block_data.previous_declaration_id_index := old_id_idx; new_id_idx := CD.Id_Count; Block (CD, FSys, False, sub_sub_prog_block_data, id_subprog, id_subprog_with_case); kind := CD.id_table (new_id_idx).decl_kind; if kind = complete then if IsFun then Emit_1 (CD, k_Return_Function, End_Function_without_Return); else Emit_1 (CD, k_Return_Call, Normal_Procedure_Call); end if; end if; end; end Subprogram_Declaration_or_Body; end HAC_Sys.Parser; ================================================ FILE: src/compile/hac_sys-parser.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Co_Defs, HAC_Sys.Defs; package HAC_Sys.Parser is type Block_Data_Type is record context : Defs.Flow_Context; -- When context.level = 0, the rest -- of this record is garbage. entity : Co_Defs.Entity_Kind; -- Procedure, function or entry. return_statement_seen : Boolean; is_main : Boolean; block_id_index : Natural; previous_declaration_id_index : Natural; -- Subprogram "forward" declaration initialization_object_code_size : Integer; -- Was: ICode data_allocation_index : Integer; -- Was: DX max_data_allocation_index : Integer; -- Was: MaxDX -- ^ includes the maximum space needed -- for parameters of FOR loops. end record; -------------------------------------------- -- Block: subprogram or block statement -- -------------------------------------------- procedure Block (CD : in out Co_Defs.Compiler_Data; FSys : Defs.Symset; Is_a_block_statement : Boolean; -- RM: 5.6 Block Statements Initial_Block_Data : Block_Data_Type; Block_Id : Defs.Alfa; -- Name of this block (if any) Block_Id_with_case : Defs.Alfa); -- E.g. : in the case of a block statement within a function, the value -- True will be passed for both Is_a_function and Is_a_block_statement. -- When Is_a_block_statement = True, the current symbol Sy must be either -- DECLARE_symbol or BEGIN_symbol -------------------------------------------------------- -- Subprogram declaration or body (Ada RM 6.1, 6.3) -- -------------------------------------------------------- procedure Subprogram_Declaration_or_Body (CD : in out Co_Defs.Compiler_Data; FSys : in Defs.Symset; current_level : in Defs.Nesting_Level; kind : out Co_Defs.Declaration_Kind); end HAC_Sys.Parser; ================================================ FILE: src/compile/hac_sys-scanner.adb ================================================ with HAC_Sys.Defs, HAC_Sys.Errors; with HAT; with Ada.Directories, Ada.IO_Exceptions, Ada.Streams, Ada.Strings.Fixed; package body HAC_Sys.Scanner is use Co_Defs, Defs, Errors, HAT; type Special_Symbol_Mapping is array (Character'(' ') .. ']') of Symbol; Special_Symbols : constant Special_Symbol_Mapping := ('+' => Plus, '-' => Minus, '*' => Times, '/' => Divide, '(' => LParent, ')' => RParent, '[' => LBrack, ']' => RBrack, ',' => Comma, ';' => Semicolon, '&' => Ampersand_Symbol, others => NULL_Symbol); type Character_Category is (Letter, Number, Special, Illegal); type Set_of_Character_Category is array (Character_Category) of Boolean; special_or_illegal : constant Set_of_Character_Category := (Letter | Number => False, Special | Illegal => True); c128 : constant Character := Character'Val (128); Character_Types : constant array (Character) of Character_Category := ('A' .. 'Z' | 'a' .. 'z' => Letter, '0' .. '9' => Number, '#' | '+' | '-' | '*' | '/' | '(' | ')' | '[' | ']' | '&' | '=' | ' ' | ',' | '.' | ''' | ':' | '_' | ';' | '|' | '<' | '>' | '"' => Special, c128 => Special, others => Illegal); type Ada_Keyword_Mapping_Pair is record st : VString; sy : Symbol; end record; type Ada_Keyword_Mapping_List is array (Positive range <>) of Ada_Keyword_Mapping_Pair; ada_keyword : constant Ada_Keyword_Mapping_List := ((+"ABORT", ABORT_Symbol), (+"ABS", ABS_Symbol), (+"ABSTRACT", ABSTRACT_Symbol), -- [added in] Ada 95 (+"ACCEPT", ACCEPT_Symbol), (+"ACCESS", ACCESS_Symbol), (+"ALIASED", ALIASED_Symbol), -- Ada 95 (+"ALL", ALL_Symbol), -- Ada 95 (+"AND", AND_Symbol), (+"ARRAY", ARRAY_Symbol), (+"AT", AT_Symbol), (+"BEGIN", BEGIN_Symbol), (+"BODY", BODY_Symbol), (+"CASE", CASE_Symbol), (+"CONSTANT", CONSTANT_Symbol), (+"DECLARE", DECLARE_Symbol), (+"DELAY", DELAY_Symbol), (+"DELTA", DELTA_Symbol), (+"DIGITS", DIGITS_Symbol), (+"DO", DO_Symbol), (+"ELSE", ELSE_Symbol), (+"ELSIF", ELSIF_Symbol), (+"END", END_Symbol), (+"ENTRY", ENTRY_Symbol), (+"EXCEPTION", EXCEPTION_Symbol), (+"EXIT", EXIT_Symbol), (+"FOR", FOR_Symbol), (+"FUNCTION", FUNCTION_Symbol), (+"GENERIC", GENERIC_Symbol), (+"GOTO", GOTO_Symbol), (+"IF", IF_Symbol), (+"IN", IN_Symbol), (+"INTERFACE", INTERFACE_Symbol), -- Ada 2005 (+"IS", IS_Symbol), (+"LIMITED", LIMITED_Symbol), (+"LOOP", LOOP_Symbol), (+"MOD", MOD_Symbol), (+"NEW", NEW_Symbol), (+"NOT", NOT_Symbol), (+"NULL", NULL_Symbol), (+"OF", OF_Symbol), (+"OR", OR_Symbol), (+"OTHERS", OTHERS_Symbol), (+"OUT", OUT_Symbol), (+"OVERRIDING", OVERRIDING_Symbol), -- Ada 2005 (+"PACKAGE", PACKAGE_Symbol), (+"PARALLEL", PARALLEL_Symbol), -- Ada 2022 (+"PRAGMA", PRAGMA_Symbol), (+"PRIVATE", PRIVATE_Symbol), (+"PROCEDURE", PROCEDURE_Symbol), (+"PROTECTED", PROTECTED_Symbol), -- Ada 95 (+"RAISE", RAISE_Symbol), (+"RANGE", RANGE_Keyword_Symbol), (+"RECORD", RECORD_Symbol), (+"REM", REM_Symbol), (+"RENAMES", RENAMES_Symbol), (+"REQUEUE", REQUEUE_Symbol), -- Ada 95 (+"RETURN", RETURN_Symbol), (+"REVERSE", REVERSE_Symbol), (+"SELECT", SELECT_Symbol), (+"SEPARATE", SEPARATE_Symbol), (+"SOME", SOME_Symbol), -- Ada 2012 (+"SUBTYPE", SUBTYPE_Symbol), (+"SYNCHRONIZED", SYNCHRONIZED_Symbol), -- Ada 2005 (+"TAGGED", TAGGED_Symbol), -- Ada 95 (+"TASK", TASK_Symbol), (+"TERMINATE", TERMINATE_Symbol), (+"THEN", THEN_Symbol), (+"TYPE", TYPE_Symbol), (+"UNTIL", UNTIL_Symbol), -- Ada 95 (+"USE", USE_Symbol), (+"WHEN", WHEN_Symbol), (+"WHILE", WHILE_Symbol), (+"WITH", WITH_Symbol), (+"XOR", XOR_Symbol) ); subtype Size_test_a is String (1 .. 19); subtype Size_test_b is Ada.Streams.Stream_Element_Array (1 .. 19); se_equivalent_to_character : constant Boolean := Size_test_a'Size = Size_test_b'Size and Size_test_a'Alignment = Size_test_b'Alignment; procedure Next_Character (CD : in out Compiler_Data) is procedure Get_Next_Line is idx : Integer := CD.CUD.input_line'First - 1; c : Character; procedure Get_Character_from_Buffer with Inline is actually_read : Natural; procedure Refill_Buffer is use Ada.Streams; se_buffer : Stream_Element_Array (1 .. Source_Buffer_String'Length); for se_buffer'Address use CD.CUD.buffer'Address; pragma Import (Ada, se_buffer); last_read : Stream_Element_Offset; begin if se_equivalent_to_character then -- Fast method: CD.CUD.compiler_stream.Read (se_buffer, last_read); actually_read := Natural (last_read); else -- Slow method: actually_read := 0; for cb of CD.CUD.buffer loop Character'Read (CD.CUD.compiler_stream, cb); actually_read := actually_read + 1; end loop; end if; exception when Ada.IO_Exceptions.End_Error => -- Happens with the slow method. -- `actually_read` has been incremented correctly. null; end Refill_Buffer; begin if CD.CUD.buffer_position > CD.CUD.buffer_length then Refill_Buffer; if actually_read = 0 then -- Refill failed, even a partial one -> the -- stream is exhausted. raise Ada.IO_Exceptions.End_Error; end if; CD.CUD.buffer_length := actually_read; CD.CUD.buffer_position := 1; end if; c := CD.CUD.buffer (CD.CUD.buffer_position); CD.CUD.buffer_position := CD.CUD.buffer_position + 1; end Get_Character_from_Buffer; begin loop Get_Character_from_Buffer; -- Fast version of: Character'Read (CD.CUD.compiler_stream, c); exit when c = ASCII.LF; if c /= ASCII.CR then idx := idx + 1; CD.CUD.input_line (idx) := c; end if; end loop; CD.CUD.LL := idx; exception when Ada.IO_Exceptions.End_Error => if idx < CD.CUD.input_line'First then -- `idx` was not changed after its initialization. raise; end if; CD.CUD.LL := idx; -- Avoid trashing a non-empty line ending the stream. end Get_Next_Line; begin if CD.CUD.CC = CD.CUD.LL then if CD.listing_requested then New_Line (CD.listing); end if; CD.CUD.location.line := CD.CUD.location.line + 1; if CD.listing_requested then HAC_Sys.Defs.IIO.Put (CD.listing, HAC_Integer (CD.CUD.location.line), 4); Put (CD.listing, " "); end if; CD.CUD.LL := 0; CD.CUD.CC := 0; Get_Next_Line; -- Append a space: CD.CUD.LL := CD.CUD.LL + 1; CD.CUD.input_line (CD.CUD.LL) := ' '; if CD.listing_requested then New_Line (CD.listing); Put_Line (CD.listing, CD.CUD.input_line); end if; end if; CD.CUD.CC := CD.CUD.CC + 1; CD.CUD.prev_c := CD.CUD.c; CD.CUD.c := CD.CUD.input_line (CD.CUD.CC); -- Change tabs for spaces: if Character'Pos (CD.CUD.c) = 9 then CD.CUD.c := ' '; end if; if CD.CUD.c < ' ' then Error (CD, err_scanner_control_character); end if; end Next_Character; procedure Skip_Blanks (CD : in out Compiler_Data) is begin while CD.CUD.c = ' ' loop Next_Character (CD); end loop; end Skip_Blanks; procedure In_Symbol (CD : in out Compiler_Data) is I, J, K, e : Integer; procedure Read_Scale (allow_minus : Boolean) is S, Sign : Integer; digit_count : Natural := 0; begin Next_Character (CD); Sign := 1; S := 0; case CD.CUD.c is when '+' => Next_Character (CD); when '-' => Next_Character (CD); if allow_minus then Sign := -1; else Error (CD, err_scanner_negative_exponent_for_integer_literal, CD.INum'Image & ".0e- ...", severity => minor); -- minor -> scanning & parsing go on unhindered. end if; when others => null; end case; if CD.CUD.c not in '0' .. '9' then Error (CD, err_scanner_illegal_character_in_number, "; expected digit after 'E'"); else loop if digit_count = integer_digits_max then Error (CD, err_scanner_integer_literal_too_large, severity => minor); -- minor -> scanning & parsing go on unhindered. elsif digit_count > integer_digits_max then null; -- The insult was already issued on digit_count = integer_digits_max... else S := S * 10 + Character'Pos (CD.CUD.c) - Character'Pos ('0'); end if; digit_count := digit_count + 1; Next_Character (CD); exit when CD.CUD.c not in '0' .. '9'; end loop; end if; e := S * Sign + e; end Read_Scale; procedure Adjust_Scale is S : Integer; D, T : HAC_Float; begin if K + e > EMax then Error (CD, err_scanner_exponent_too_large, K'Image & " +" & e'Image & " =" & Integer'Image (K + e) & " > Max =" & EMax'Image, severity => minor); -- minor -> scanning & parsing go on unhindered. elsif K + e < EMin then CD.RNum := 0.0; else S := abs e; T := 1.0; D := 10.0; loop while S rem 2 = 0 loop S := S / 2; D := D ** 2; end loop; S := S - 1; T := D * T; exit when S = 0; end loop; CD.RNum := (if e >= 0 then CD.RNum * T else CD.RNum / T); end if; end Adjust_Scale; procedure Read_with_Sharp is -- For numbers in bases other than 10, we fall back to Ada -- library's parsing, at the price of a less detailed -- error diagnostic. s : Source_Line_String; l : Natural := s'First - 1; has_point : Boolean := False; begin -- Number has been read until the first '#'. loop Next_Character (CD); l := l + 1; s (l) := CD.CUD.c; exit when CD.CUD.c = '#'; -- Second '#'. has_point := has_point or CD.CUD.c = '.'; end loop; Next_Character (CD); if CD.CUD.c in 'E' | 'e' then -- Exponent. Special case because of possible '+' or '-' which -- are not operators (e.g. 8#123#e+5 vs. 8#123#+5, = 8#123# + 5)... -- Otherwise we could have done it all in the previous loop. for c in 1 .. 2 loop l := l + 1; s (l) := CD.CUD.c; -- We concatenate "e+", "e-", "e5". Next_Character (CD); end loop; while CD.CUD.c in '0' .. '9' loop l := l + 1; s (l) := CD.CUD.c; -- We concatenate the rest of the exponent. Next_Character (CD); end loop; end if; declare complete_string : constant String := HAC_Integer'Image (CD.INum) & '#' & s (s'First .. l); begin if has_point then CD.Sy := real_literal; CD.RNum := HAC_Float'Value (complete_string); else CD.Sy := integer_literal; CD.INum := HAC_Integer'Value (complete_string); end if; exception when others => Error (CD, err_scanner_illegal_character_in_number); end; end Read_with_Sharp; procedure Skip_Possible_Underscore_in_Number is begin if CD.CUD.c = '_' then Next_Character (CD); if CD.CUD.c = '_' then Error (CD, err_scanner_double_underline_not_permitted, severity => major); elsif Character_Types (CD.CUD.c) /= Number then Error (CD, err_scanner_digit_expected, severity => major); end if; end if; end Skip_Possible_Underscore_in_Number; procedure Read_Decimal_Float is begin -- Floating-point number 123.456 -- Cursor is here -----------^ if CD.CUD.c = '.' then -- After all, this is not a number with a decimal point, -- but a double dot, like 123..456. CD.CUD.c := c128; return; end if; -- Read decimal part. CD.Sy := real_literal; CD.RNum := HAC_Float (CD.INum); e := 0; while Character_Types (CD.CUD.c) = Number loop e := e - 1; CD.RNum := 10.0 * CD.RNum + HAC_Float (Character'Pos (CD.CUD.c) - Character'Pos ('0')); Next_Character (CD); Skip_Possible_Underscore_in_Number; end loop; if e = 0 then Error (CD, err_scanner_illegal_character_in_number, "; expected digit after '.'"); end if; if CD.CUD.c in 'E' | 'e' then Read_Scale (allow_minus => True); end if; if e /= 0 then Adjust_Scale; end if; end Read_Decimal_Float; procedure Scan_Number (skip_leading_integer : Boolean) is use type HAC_Integer; begin K := 0; CD.INum := 0; CD.Sy := integer_literal; if skip_leading_integer then -- Example: a naughty person has put ".123" in his/her code. -- An error is already emmitted at this point but we continue -- the scanning and parsing. Read_Decimal_Float; else -- Scan the integer part of the number. loop if K = integer_digits_max then -- To do: read a multiprecision integer here, so the limitation -- is not applied to floating-point numbers. -- Challenge: convert accurately the multiprecision integer -- to a floating-point number. Error (CD, err_scanner_integer_literal_too_large, severity => minor); -- minor -> scanning & parsing go on unhindered. elsif K > integer_digits_max then null; -- The insult was already issued on K = integer_digits_max... else CD.INum := CD.INum * 10 + (Character'Pos (CD.CUD.c) - Character'Pos ('0')); end if; K := K + 1; Next_Character (CD); Skip_Possible_Underscore_in_Number; exit when Character_Types (CD.CUD.c) /= Number; end loop; -- Integer part is read (CD.INum). case CD.CUD.c is when '.' => Next_Character (CD); Read_Decimal_Float; when 'E' | 'e' => -- Integer with exponent: 123e4. e := 0; Read_Scale (allow_minus => False); -- NB: a negative exponent issues an error, then e is set to 0. if e > 0 then if K + e > integer_digits_max then Error (CD, err_scanner_exponent_too_large, Integer'Image (K) & " +" & Integer'Image (e) & " =" & Integer'Image (K + e) & " > Max =" & integer_digits_max'Image, severity => minor); -- minor -> scanning & parsing go on unhindered. else CD.INum := CD.INum * 10 ** e; end if; end if; when '#' => Read_with_Sharp; when others => null; -- Number was an integer in base 10. end case; end if; if Character_Types (CD.CUD.c) = Letter then CD.CUD.location.column_start := CD.CUD.CC; CD.CUD.location.column_stop := CD.CUD.CC; Error (CD, err_scanner_space_missing_after_number, severity => minor); -- scanning & parsing go on unhindered. end if; end Scan_Number; procedure Scan_Apostrophe_or_Character is C1, C2 : Character; begin -- We scan a little bit further: 2 characters. Possible legal cases: -- * 1 'c' : character -- * 2 ''' : character -- * 3 'Image : attribute (hope that no-one invents a 1-letter attribute) -- * 4 '(...) : qualified expression -- * 5 '( : (end of a line after last non-blank) start of a qualified expression -- NB: all legal cases but the last have two characters -- on the same line after the first ' -- Blatantly illegal cases: -- * 6 ''x where x is not an ' -- * 7 '' (end of a line after last non-blank) -- * 8 'c (end of a line after last non-blank) c being neither '' nor ( -- * 9 ' (end of a line after last non-blank) -- if CD.CUD.CC = CD.CUD.LL then -- Case (9) above Error (CD, err_scanner_character_zero_chars, severity => major); end if; Next_Character (CD); C1 := CD.CUD.c; if CD.CUD.CC = CD.CUD.LL then -- Cases (5), (7), (8) if C1 = '(' then -- Case (5) CD.Sy := Apostrophe; return; end if; -- Case (7), (8) Error (CD, err_scanner_character_zero_chars, severity => major); end if; -- We peek the next character without moving. -- Possible since CD.CC < CD.LL . C2 := CD.CUD.input_line (CD.CUD.CC + 1); if C1 = ''' and C2 /= ''' then -- Case (6) Error (CD, err_scanner_character_zero_chars, severity => major); end if; -- Until now, case (5) to (9) are treated. if C2 = ''' then -- Cases (1), (2) CD.Sy := character_literal; CD.INum := Character'Pos (C1); Next_Character (CD); Next_Character (CD); else -- Cases (3), (4) CD.Sy := Apostrophe; end if; end Scan_Apostrophe_or_Character; procedure Scan_String_Literal is ST : String renames CD.Strings_Constants_Table; lit_len : Integer; procedure Try_String_Folding is trace_folding : constant Boolean := False; first_char : constant Character := ST (CD.Strings_Table_Top + 1); len : Positive; begin pragma Assert (lit_len > 0); for past_start in Integer'Max (Strings_Constants_Table_Type'First, CD.Strings_Table_Top - string_folding_scan_limit) .. CD.Strings_Table_Top loop len := Integer'Min (lit_len, CD.Strings_Table_Top - past_start + 1); -- NB: from the upper bound of the loop, we know that -- CD.Strings_Table_Top >= past_start. -- We also have assumed above that lit_len > 0. -- Then, len is always > 0 (the substring to match is -- at least one character long). if ST (past_start) = first_char and then ST (past_start .. past_start + len - 1) = ST (CD.Strings_Table_Top + 1 .. CD.Strings_Table_Top + len) then CD.INum := HAC_Integer (past_start); if trace_folding then Put ("Matched... [" & ST (past_start .. past_start + len - 1) & "] "); if len = lit_len then Put_Line ("Full match"); -- Entire new string was found in the existing string table. -- CD.Strings_Table_Top won't be changed. else pragma Assert (len < lit_len); Put_Line ("Partial match; rest is: [" & ST (CD.Strings_Table_Top + len + 1 .. CD.Strings_Table_Top + lit_len) & ']'); -- A partial match makes sense only from the first characters -- rightwards and if the right limit is on CD.Strings_Table_Top. -- Then the table can be completed to the full string. end if; end if; -- Partial match: append rest to last string in the table. for i in 1 .. lit_len - len loop ST (CD.Strings_Table_Top + i) := -- Extension. ST (CD.Strings_Table_Top + i + len); -- Rest of the newly scanned string end loop; -- We will extend the known part of the table only for `lit_len - len` characters. -- In any case `len` is the "compression" gain. lit_len := lit_len - len; exit; end if; end loop; end Try_String_Folding; begin lit_len := 0; loop Next_Character (CD); if CD.CUD.c = '"' then Next_Character (CD); if CD.CUD.c /= '"' then -- ["x] case: we have reached the end of the string. exit; end if; -- [""] case: doubled double-quote which means a single one. end if; lit_len := lit_len + 1; if CD.Strings_Table_Top + lit_len = SMax then Fatal (STRING_CONSTANTS); end if; ST (CD.Strings_Table_Top + lit_len) := CD.CUD.c; if CD.CUD.CC = 1 then lit_len := 0; -- END OF InpLine CD.CUD.location.column_start := 1; CD.CUD.location.column_stop := 1; Error (CD, err_general_error, "missing closing quote on previous line ", severity => major); else null; -- Continue end if; end loop; CD.Sy := string_literal; CD.SLeng := lit_len; CD.INum := HAC_Integer (CD.Strings_Table_Top + 1); -- if lit_len > 0 then if CD.target.Null_Terminated_String_Literals then -- Add a Character'Val (0) to the stored string. lit_len := lit_len + 1; if CD.Strings_Table_Top + lit_len = SMax then Fatal (STRING_CONSTANTS); end if; ST (CD.Strings_Table_Top + lit_len) := Character'Val (0); else Try_String_Folding; end if; CD.Strings_Table_Top := CD.Strings_Table_Top + lit_len; end if; end Scan_String_Literal; procedure Process_Special_Comment (annotation : String) is -- Process "--!" cmd_add_to_path : constant String := "hac_add_to_path "; procedure Add_to_Path (rel_or_abs_dir : String) is use Ada.Directories; cur_dir : constant String := Current_Directory; src_dir : constant String := Containing_Directory (To_String (CD.CUD.source_file_name)); begin -- Go to the specified directory, which is absolute or relative -- to the source file's directory -- -- Put_Line ("Ah ha! [" & rel_or_abs_dir & ']'); Ada.Directories.Set_Directory (src_dir); -- Put_Line ("src_dir [" & src_dir & ']'); Ada.Directories.Set_Directory (rel_or_abs_dir); -- Put_Line ("abs_dir [" & Ada.Directories.Current_Directory & ']'); CD.cat.Add_to_Source_Path (Ada.Directories.Current_Directory); -- Restore current directory: Ada.Directories.Set_Directory (cur_dir); end Add_to_Path; begin if Ada.Strings.Fixed.Index (annotation, cmd_add_to_path) > 0 then Add_to_Path (Ada.Strings.Fixed.Trim (annotation (annotation'First + cmd_add_to_path'Length .. annotation'Last), Ada.Strings.Both)); end if; end Process_Special_Comment; exit_big_loop : Boolean; begin -- In_Symbol CD.prev_sy := CD.Sy; CD.prev_sy_loc := CD.CUD.location; Big_loop : loop Small_loop : loop Skip_Blanks (CD); CD.CUD.location.column_start := CD.CUD.CC; exit Small_loop when Character_Types (CD.CUD.c) /= Illegal; Error (CD, err_scanner_illegal_character); if CD.comp_dump_requested then Put_Line (CD.comp_dump, " Char is => " & Integer'Image (Character'Pos (CD.CUD.c))); end if; if CD.listing_requested then Put_Line (CD.listing, " Char is => " & Integer'Image (Character'Pos (CD.CUD.c))); end if; Next_Character (CD); end loop Small_loop; exit_big_loop := True; case CD.CUD.c is when 'A' .. 'Z' | -- Identifier or keyword 'a' .. 'z' => K := 0; HAT.VStr_Pkg.Set_Unbounded_String (CD.Id_with_case, ""); loop if K < identifier_length_max then K := K + 1; HAT.VStr_Pkg.Append (CD.Id_with_case, CD.CUD.c); if K > 1 and then (CD.CUD.c = '_' and CD.CUD.prev_c = '_') then Error (CD, err_scanner_double_underline_not_permitted, severity => major); end if; else Error (CD, err_scanner_identifier_too_long); end if; Next_Character (CD); exit when CD.CUD.c /= '_' and then special_or_illegal (Character_Types (CD.CUD.c)); end loop; if K > 0 and then CD.CUD.prev_c = '_' then Error (CD, err_scanner_identifier_cannot_end_with_underline, severity => major); end if; -- HAT.VStr_Pkg.Set_Unbounded_String (CD.Id, HAT.ACH.To_Upper (To_String (CD.Id_with_case))); CD.Id_location := No_Id_Cache; -- -- Binary Search -- I := 1; J := ada_keyword'Last; loop K := (I + J) / 2; if CD.Id <= ada_keyword (K).st then J := K - 1; end if; if CD.Id >= ada_keyword (K).st then I := K + 1; end if; exit when I > J; end loop; -- CD.Sy := (if I - 1 > J then ada_keyword (K).sy else IDent); when '0' .. '9' => Scan_Number (skip_leading_integer => False); when '"' => Scan_String_Literal; when ''' => Scan_Apostrophe_or_Character; when ':' => Next_Character (CD); if CD.CUD.c = '=' then CD.Sy := Becomes; Next_Character (CD); else CD.Sy := Colon; end if; when '<' => Next_Character (CD); if CD.CUD.c = '=' then CD.Sy := LEQ; Next_Character (CD); else CD.Sy := LSS; end if; when '>' => Next_Character (CD); if CD.CUD.c = '=' then CD.Sy := GEQ; Next_Character (CD); else CD.Sy := GTR; end if; when '/' => Next_Character (CD); if CD.CUD.c = '=' then CD.Sy := NEQ; Next_Character (CD); else CD.Sy := Divide; end if; when '.' => Next_Character (CD); case CD.CUD.c is when '.' => CD.Sy := Range_Double_Dot_Symbol; Next_Character (CD); when '0' .. '9' => Error (CD, err_general_error, "numeric literal cannot start with point", severity => minor); Scan_Number (skip_leading_integer => True); when others => CD.Sy := Period; end case; when c128 => -- Hathorn CD.Sy := Range_Double_Dot_Symbol; Next_Character (CD); when '-' => Next_Character (CD); if CD.CUD.c = '-' then -- Comment if CD.CUD.CC < CD.CUD.LL and then CD.CUD.input_line (CD.CUD.CC + 1) = '!' then Process_Special_Comment (CD.CUD.input_line (CD.CUD.CC + 2 .. CD.CUD.LL)); end if; CD.CUD.CC := CD.CUD.LL; -- Ignore rest of input line Next_Character (CD); exit_big_loop := False; else CD.Sy := Minus; end if; when '=' => Next_Character (CD); if CD.CUD.c = '>' then CD.Sy := Finger; Next_Character (CD); else CD.Sy := EQL; end if; when '|' => CD.Sy := Alt; Next_Character (CD); when '+' | '*' | '(' | ')' | ',' | '[' | ']' | ';' | '&' => CD.Sy := Special_Symbols (CD.CUD.c); Next_Character (CD); if CD.Sy = Times and then CD.CUD.c = '*' then -- Get the "**" operator symbol CD.Sy := Power; Next_Character (CD); end if; when '$' | '!' | '@' | '\' | '^' | '_' | '?' | '%' | '#' => Error (CD, err_scanner_illegal_character); if CD.comp_dump_requested then Put_Line (CD.comp_dump, " [ $!@\^_?%# ]"); end if; if CD.listing_requested then Put_Line (CD.listing, " [ $!@\^_?%# ]"); end if; Next_Character (CD); exit_big_loop := False; when Character'Val (0) .. ' ' => null; when others => null; end case; -- CD.SD.CH exit Big_loop when exit_big_loop; end loop Big_loop; CD.CUD.location.column_stop := CD.CUD.CC - 1; if CD.comp_dump_requested then Put_Line (CD.comp_dump, CD.CUD.input_line (1 .. CD.CUD.LL)); Put_Line (CD.comp_dump, (CD.CUD.CC - 2) * '.' & '^'); -- Draw: ".......^" Put (CD.comp_dump, '[' & CD.CUD.location.line'Image & ':' & CD.CUD.CC'Image & ":] " & CD.Sy'Image); case CD.Sy is when IDent => Put (CD.comp_dump, ": " & A2S (CD.Id)); when integer_literal => Put (CD.comp_dump, ": " & HAC_Integer'Image (CD.INum)); when real_literal => Put (CD.comp_dump, ": " & HAC_Float'Image (CD.RNum)); when string_literal => Put (CD.comp_dump, ": """); for i in Integer (CD.INum) .. Integer (CD.INum) + CD.SLeng - 1 loop Put (CD.comp_dump, CD.Strings_Constants_Table (i)); end loop; Put (CD.comp_dump, '"'); when Becomes => Put (CD.comp_dump, " := "); when Colon => Put (CD.comp_dump, " : "); when CONSTANT_Symbol => Put (CD.comp_dump, " constant "); when others => null; end case; New_Line (CD.comp_dump, 2); end if; end In_Symbol; end HAC_Sys.Scanner; ================================================ FILE: src/compile/hac_sys-scanner.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Co_Defs; package HAC_Sys.Scanner is -- Source code scanning for the compiler procedure In_Symbol (CD : in out Co_Defs.Compiler_Data); procedure Skip_Blanks (CD : in out Co_Defs.Compiler_Data); end HAC_Sys.Scanner; ================================================ FILE: src/execute/hac_sys-interfacing.adb ================================================ with HAC_Sys.Co_Defs, HAC_Sys.Defs; with HAT; with Ada.Characters.Handling, Ada.Unchecked_Conversion; package body HAC_Sys.Interfacing is use HAT, Defs; function To_HAC (Data : Integer) return HAC_Element is new_element : HAC_Element; begin new_element.I := HAC_Integer (Data); return new_element; end To_HAC; function To_HAC (Data : Long_Float) return HAC_Element is begin return GR_Real (HAT.Real (Data)); end To_HAC; function To_HAC (Data : String) return HAC_Element is begin return GR_VString (Data); end To_HAC; function To_HAC_Any_Integer (Data : Any_Integer) return HAC_Element is new_element : HAC_Element; begin new_element.I := HAC_Integer (Data); return new_element; end To_HAC_Any_Integer; function To_HAC_Any_Enum (Data : Any_Enum) return HAC_Element is new_element : HAC_Element; begin new_element.I := Any_Enum'Pos (Data); return new_element; end To_HAC_Any_Enum; function To_HAC_Any_Float (Data : Any_Float) return HAC_Element is begin return GR_Real (HAT.Real (Data)); end To_HAC_Any_Float; function To_Native (Data : HAC_Element) return Integer is begin return Integer (Data.I); end To_Native; function To_Native (Data : HAC_Element) return Long_Float is begin if Data.Special = Floats then return Long_Float (Data.R); end if; raise HAC_Type_Error with "Expected a HAT.Real, found Integer or " & Typen'Image (Data.Special); end To_Native; function To_Native (Data : HAC_Element) return String is begin if Data.Special = VStrings then return To_String (Data.V); end if; raise HAC_Type_Error with "Expected a VString, found Integer or " & Typen'Image (Data.Special); end To_Native; function To_Native_Any_Integer (Data : HAC_Element) return Any_Integer is begin return Any_Integer (Data.I); end To_Native_Any_Integer; function To_Native_Any_Enum (Data : HAC_Element) return Any_Enum is begin return Any_Enum'Val (Data.I); end To_Native_Any_Enum; function To_Native_Any_Float (Data : HAC_Element) return Any_Float is begin if Data.Special = Floats then return Any_Float (Data.R); end if; raise HAC_Type_Error with "Expected a HAT.Real, found Integer or " & Typen'Image (Data.Special); end To_Native_Any_Float; function Get_VM_Variable (BD : Builder.Build_Data; Name : String) return String is cur : constant Builder.String_Maps.Cursor := BD.global_VM_variables.Find (HAT.To_VString (Name)); use Builder.String_Maps; begin return (if cur = Builder.String_Maps.No_Element then "" else HAT.To_String (Builder.String_Maps.Element (cur))); end Get_VM_Variable; procedure Set_VM_Variable (BD : in out Builder.Build_Data; Name : String; Value : String) is begin BD.global_VM_variables.Include (HAT.To_VString (Name), HAT.To_VString (Value)); end Set_VM_Variable; procedure Register (BD : Builder.Build_Data; Callback : Exported_Procedure; Name : String) is function Convert is new Ada.Unchecked_Conversion (Exported_Procedure, Co_Defs.Dummy_Procedure_Access); use Ada.Characters.Handling; begin if Callback /= null then BD.CD.Exported_Procedures.Include (To_Upper (Name), Convert (Callback)); end if; end Register; procedure Deregister (BD : Builder.Build_Data; Name : String) is use Ada.Characters.Handling; begin BD.CD.Exported_Procedures.Exclude (To_Upper (Name)); end Deregister; end HAC_Sys.Interfacing; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-calls.adb ================================================ with HAC_Sys.Interfacing, HAC_Sys.PCode.Interpreter.Exceptions, HAC_Sys.PCode.Interpreter.Tasking; with Ada.Calendar, Ada.Exceptions, Ada.Unchecked_Conversion; package body HAC_Sys.PCode.Interpreter.Calls is procedure Do_Calling_Operation ( CD : Co_Defs.Compiler_Data; ND : in out In_Defs.Interpreter_Data ) is use Defs, In_Defs; Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); IR : Order renames ND.IR; use type HAC_Integer; procedure Do_Mark_Stack is -- VSize is the maximum stack room needed by the subprogram to be called. VSize : constant Integer := Integer (CD.Blocks_Table (CD.id_table (Integer (IR.Y)).block_or_pkg_ref).VSize); begin if Curr_TCB.T + VSize > Curr_TCB.STACKSIZE then raise Exceptions.VM_Stack_Overflow; end if; Curr_TCB.T := Curr_TCB.T + Co_Defs.fixed_area_size; -- Make room for fixed area ND.S (Curr_TCB.T - 1).I := HAC_Integer (VSize - 1); ND.S (Curr_TCB.T).I := IR.Y; -- CD.IdTab index of called procedure/entry end Do_Mark_Stack; trace_display : constant Boolean := False; procedure Show_Display (D : Co_Defs.Display_Type; L_Max : Nesting_Level; T : String) is use HAT; begin if trace_display then New_Line; Put_Line ("Level Stack base of variables -- " & T); for i in 0 .. L_Max loop Put (Integer (i), 5); Put (D (i)); New_Line; end loop; end if; end Show_Display; procedure Do_Exchange_with_External is use Co_Defs; use Co_Defs.Exported_Procedure_Mapping; proc_entry : Identifier_Table_Entry renames CD.id_table (Integer (IR.Y)); proc_name : constant String := A2S (proc_entry.name); block_idx : constant Index := proc_entry.block_or_pkg_ref; block : Block_Table_Entry renames CD.Blocks_Table (block_idx); base : constant Positive := Curr_TCB.T - block.PSize + 1; -- -- The size of parameters' data can be larger that the size -- taken on stack, as soon as a composite parameter of size -- more than 1 is passed by reference (the reference takes 1 cell). -- function param_data_size return Natural is total : Natural := 0; begin for p in block.First_Param_Id_Idx .. block.Last_Param_Id_Idx loop total := total + Size_of (CD, p); end loop; return total; end param_data_size; -- data : Interfacing.HAC_Element_Array (1 .. param_data_size); -- procedure Data_Exchange (before_call : Boolean) is function Convert is new Ada.Unchecked_Conversion (Interfacing.HAC_Element, Data_Type); function Convert is new Ada.Unchecked_Conversion (Data_Type, Interfacing.HAC_Element); data_idx : Positive := 1; stack_idx : Positive; begin for p in block.First_Param_Id_Idx .. block.Last_Param_Id_Idx loop stack_idx := base + Integer (CD.id_table (p).adr_or_sz); if not CD.id_table (p).normal then -- Dereference. stack_idx := Index (ND.S (stack_idx).I); end if; for count in 1 .. Size_of (CD, p) loop if before_call then if CD.id_table (p).decl_kind /= param_out then data (data_idx) := Convert (ND.S (stack_idx)); end if; else if CD.id_table (p).decl_kind /= param_in then ND.S (stack_idx) := Convert (data (data_idx)); end if; end if; data_idx := data_idx + 1; stack_idx := stack_idx + 1; end loop; end loop; end Data_Exchange; -- function Convert is new Ada.Unchecked_Conversion (Co_Defs.Dummy_Procedure_Access, Interfacing.Exported_Procedure); cur : constant Cursor := CD.Exported_Procedures.Find (proc_name); begin -- Data exchange before call (in, in out) Data_Exchange (before_call => True); -- if cur = No_Element then Exceptions.Raise_Standard (ND, VME_Program_Error, "Import name """ & proc_name & """ not found. Was it registered ?"); else begin Convert (Element (cur)) (data); -- Call to external procedure exception when E : others => Exceptions.Raise_Standard (ND, VME_Program_Error, "Exception raised in callback, message: " & Ada.Exceptions.Exception_Message (E)); end; end if; -- Data exchange after call (in out, out) Data_Exchange (before_call => False); end Do_Exchange_with_External; procedure Do_Call is use Ada.Calendar; F1 : HAC_Float; -- Internal float registers Activation_Record_Base, Ident_Index_of_Called, New_Stack_Top, new_address : Index; Called_Level : Nesting_Level; Task_Entered : Integer; begin -- Procedure and task entry CALL -- Cramer if IR.X = Defs.Timed_Entry_Call then -- Timed entry call F1 := ND.S (Curr_TCB.T).R; -- Pop delay time Pop (ND); end if; Activation_Record_Base := Curr_TCB.T - Integer (IR.Y); Ident_Index_of_Called := Index (ND.S (Activation_Record_Base + 4).I); Called_Level := CD.id_table (Ident_Index_of_Called).lev; Show_Display (Curr_TCB.DISPLAY, Called_Level, "before call"); Curr_TCB.DISPLAY (Called_Level + 1) := Activation_Record_Base; Show_Display (Curr_TCB.DISPLAY, Called_Level + 1, "on call"); New_Stack_Top := Index (ND.S (Activation_Record_Base + 3).I) + Activation_Record_Base; -- ND.S (Activation_Record_Base + 1).I := HAC_Integer (Curr_TCB.PC); -- return address ND.S (Activation_Record_Base + 2).I := HAC_Integer (Curr_TCB.DISPLAY (Called_Level)); -- static link ND.S (Activation_Record_Base + 3).I := HAC_Integer (Curr_TCB.B); -- dynamic link -- Curr_TCB.B := Activation_Record_Base; Curr_TCB.T := New_Stack_Top; case IR.X is -- Call type when Defs.Normal_Procedure_Call => new_address := Index (CD.id_table (Ident_Index_of_Called).adr_or_sz); if new_address < 0 then raise Exceptions.VM_Subprogram_Spec; end if; Curr_TCB.PC := new_address; -- Jump to subprogram start. when Defs.Normal_Entry_Call => Tasking.Queue (CD, ND, Ident_Index_of_Called, ND.CurTask); -- put self on entry queue Curr_TCB.TS := WaitRendzv; Task_Entered := Integer (CD.id_table (Ident_Index_of_Called).adr_or_sz); -- Task being entered if ((ND.TCB (Task_Entered).TS = WaitRendzv) and then (ND.TCB (Task_Entered).SUSPEND = Ident_Index_of_Called)) or else ND.TCB (Task_Entered).TS = TimedWait then -- wake accepting task if necessary ND.TCB (Task_Entered).TS := Ready; ND.TCB (Task_Entered).SUSPEND := 0; end if; ND.SWITCH := True; -- give up control when Defs.Timed_Entry_Call => Tasking.Queue (CD, ND, Ident_Index_of_Called, ND.CurTask); -- put self on entry queue Task_Entered := Integer (CD.id_table (Ident_Index_of_Called).adr_or_sz); -- Task being entered -- if ((ND.TCB (Task_Entered).TS = WaitRendzv) and (ND.TCB (Task_Entered).SUSPEND = Ident_Index_of_Called)) or (ND.TCB (Task_Entered).TS = TimedWait) then -- wake accepting task if necessary Curr_TCB.TS := WaitRendzv; -- suspend self ND.TCB (Task_Entered).TS := Ready; -- wake accepting task ND.TCB (Task_Entered).SUSPEND := 0; else Curr_TCB.TS := TimedRendz; -- Timed Wait For Rendezvous Curr_TCB.R1.I := 1; -- Init R1 to specify NO timeout Curr_TCB.R2.I := HAC_Integer (Ident_Index_of_Called); -- Save address of queue for purge ND.SYSCLOCK := Clock; -- update System Clock Curr_TCB.WAKETIME := ND.SYSCLOCK + Duration (F1); end if; ND.SWITCH := True; -- give up control when Defs.Conditional_Entry_Call => Task_Entered := Integer (CD.id_table (Ident_Index_of_Called).adr_or_sz); -- Task being entered if ((ND.TCB (Task_Entered).TS = WaitRendzv) and then (ND.TCB (Task_Entered).SUSPEND = Ident_Index_of_Called)) or else ND.TCB (Task_Entered).TS = TimedWait then Tasking.Queue (CD, ND, Ident_Index_of_Called, ND.CurTask); -- put self on entry queue Curr_TCB.R1.I := 1; -- Indicate entry successful Curr_TCB.TS := WaitRendzv; ND.TCB (Task_Entered).TS := Ready; -- wake accepting task if required ND.TCB (Task_Entered).SUSPEND := 0; ND.SWITCH := True; -- give up control else -- can't wait, forget about entry call Curr_TCB.R1.I := 0; -- Indicate entry failed in R1 1 -- failure will be acknowledged by next instruction, 32 end if; when others => null; -- [P2Ada]: no otherwise / else in Pascal end case; end Do_Call; procedure Do_Return_Call is -- RETURN entry call or procedure call -- Cramer begin -- Set back stack top as before call: Curr_TCB.T := Curr_TCB.B - 1; if IR.Y = Defs.Normal_Procedure_Call then -- Set back program counter to position of Call: Curr_TCB.PC := Integer (ND.S (Curr_TCB.B + 1).I); -- Normal proc call return end if; if Curr_TCB.PC = 0 then ND.TActive := ND.TActive - 1; Curr_TCB.TS := Completed; ND.SWITCH := True; else -- Set back base of caller: Curr_TCB.B := Integer (ND.S (Curr_TCB.B + 3).I); if IR.Y = Defs.Timed_Entry_Call or else IR.Y = Defs.Conditional_Entry_Call then if IR.Y = Defs.Timed_Entry_Call and then Curr_TCB.R1.I = 0 then Push (ND); end if; -- A JMPC instruction always follows (?) -- timed and conditional entry call -- returns (32). Push entry call ND.S (Curr_TCB.T).I := Curr_TCB.R1.I; -- success indicator for JMPC. end if; end if; end Do_Return_Call; procedure Do_Return_Function is begin -- Set back stack top as before call, plus 1 item (the return value): Curr_TCB.T := Curr_TCB.B; -- Set back program counter to position of Call: Curr_TCB.PC := Integer (ND.S (Curr_TCB.B + 1).I); -- Set back base of caller: Curr_TCB.B := Integer (ND.S (Curr_TCB.B + 3).I); -- if IR.Y = Defs.End_Function_without_Return and then ND.PS /= Exception_Raised then raise Exceptions.VM_Function_End_without_Return; end if; end Do_Return_Function; procedure Do_Update_Display_Vector is -- Emitted at the end of Subprogram_or_Entry_Call, when the -- called subprogram's nesting level is *lower* than the -- caller's block level. This includes the case where P and Q are -- defined at the same level L: when Q calls P, Q's block level -- is L + 1, so it's calling P of level L and the update is -- needed after the call. Low_Level : constant Nesting_Level := Nesting_Level (ND.IR.X); -- Called. High_Level : constant Nesting_Level := Nesting_Level (ND.IR.Y); -- Caller. Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); New_Base : Defs.Index := Curr_TCB.B; -- ^ initial value: stack base of caller (dynamic link) after return from call. Address_Base_Lower_Level : Defs.Index; New_Base_Value : HAC_Integer; L : Nesting_Level := High_Level; begin pragma Assert (Low_Level < High_Level); loop -- At this point: L is always >= 1 since L > Low_Level >= 0. Curr_TCB.DISPLAY (L) := New_Base; L := L - 1; exit when L = Low_Level; Address_Base_Lower_Level := New_Base + 2; -- Written by Do_Call. if Address_Base_Lower_Level not in ND.S'Range then raise Constraint_Error with "Address_Base_Lower_Level = " & Defs.Index'Image (Address_Base_Lower_Level) & " out of stack range"; end if; New_Base_Value := ND.S (Address_Base_Lower_Level).I; if New_Base_Value not in 0 .. HAC_Integer (MaxINT) then raise Constraint_Error with "Invalid New_Base_Value =" & HAC_Integer'Image (New_Base_Value) & " found on stack @ index" & Defs.Index'Image (Address_Base_Lower_Level); end if; New_Base := Defs.Index (New_Base_Value); end loop; Show_Display (Curr_TCB.DISPLAY, High_Level, "after Update_Display_Vector"); end Do_Update_Display_Vector; begin case Calling_Opcode (ND.IR.F) is when k_Mark_Stack => Do_Mark_Stack; when k_Call => Do_Call; when k_Exchange_with_External => Do_Exchange_with_External; when k_Return_Call => Do_Return_Call; when k_Return_Function => Do_Return_Function; when k_Update_Display_Vector => Do_Update_Display_Vector; end case; end Do_Calling_Operation; end HAC_Sys.PCode.Interpreter.Calls; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-calls.ads ================================================ with HAC_Sys.Co_Defs, HAC_Sys.PCode.Interpreter.In_Defs; private package HAC_Sys.PCode.Interpreter.Calls is ----------------------- -- VM Instructions -- ----------------------- -- Execute instruction stored as Opcode in ND.IR.F. -- ND.IR.F is in the Calling_Opcode subtype range. procedure Do_Calling_Operation ( CD : Co_Defs.Compiler_Data; ND : in out In_Defs.Interpreter_Data ); end HAC_Sys.PCode.Interpreter.Calls; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-composite_data.adb ================================================ with HAC_Sys.PCode.Interpreter.Exceptions; package body HAC_Sys.PCode.Interpreter.Composite_Data is procedure Do_Composite_Data_Operation (CD : Compiler_Data; ND : in out Interpreter_Data) is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); IR : Order renames ND.IR; use Defs; use type HAC_Integer; generic size_1 : Boolean; range_check : Boolean; procedure Do_Array_Index; procedure Do_Array_Index is ATI : constant Integer := Integer (IR.Y); ATE : Array_Table_Entry renames CD.Arrays_Table (ATI); Low : constant Index := Index (ATE.Index_xTyp.Discrete_First); High : constant Index := Index (ATE.Index_xTyp.Discrete_Last); Idx : constant Index := Index (ND.S (Curr_TCB.T).I); -- function Out_Message (bound : Defs.Index; excerpt : String) return String is begin return ": index, " & Discrete_Image (CD, HAC_Integer (Idx), ATE.Index_xTyp.TYP, ATE.Index_xTyp.Ref) & ", is " & excerpt & " bound, " & Discrete_Image (CD, HAC_Integer (bound), ATE.Index_xTyp.TYP, ATE.Index_xTyp.Ref); end Out_Message; -- begin if range_check then if Idx < Low then raise Exceptions.VM_Out_of_Range with Out_Message (Low, "below lower"); elsif Idx > High then raise Exceptions.VM_Out_of_Range with Out_Message (High, "above upper"); end if; end if; Pop (ND); -- Pull array index, then adjust array element pointer. ND.S (Curr_TCB.T).I := ND.S (Curr_TCB.T).I + (if size_1 then HAC_Integer (Idx - Low) else HAC_Integer ((Idx - Low) * ATE.Element_Size)); end Do_Array_Index; procedure Do_Array_Index_Size_1 is new Do_Array_Index (size_1 => True, range_check => True); procedure Do_Array_Index_Any_Size is new Do_Array_Index (size_1 => False, range_check => True); procedure Do_Array_Index_Size_1_No_Check is new Do_Array_Index (size_1 => True, range_check => False); procedure Do_Array_Index_Any_Size_No_Check is new Do_Array_Index (size_1 => False, range_check => False); procedure Do_Load_Block is idx, new_top : Index; begin idx := Index (ND.S (Curr_TCB.T).I); -- Pull source address Pop (ND); new_top := Index (IR.Y) + Curr_TCB.T; -- Stack top after pushing block if new_top > Curr_TCB.STACKSIZE then raise Exceptions.VM_Stack_Overflow; end if; while Curr_TCB.T < new_top loop Curr_TCB.T := Curr_TCB.T + 1; ND.S (Curr_TCB.T) := ND.S (idx); idx := idx + 1; end loop; end Do_Load_Block; procedure Do_Load_String_Literal is idx, len, new_top : Index; begin idx := Index (ND.S (Curr_TCB.T).I); -- Index to string table len := Index (ND.S (Curr_TCB.T - 1).I); -- Length of string Pop (ND, 2); new_top := len + Curr_TCB.T; -- Stack top after pushing block if new_top > Curr_TCB.STACKSIZE then raise Exceptions.VM_Stack_Overflow; end if; while Curr_TCB.T < new_top loop Curr_TCB.T := Curr_TCB.T + 1; ND.S (Curr_TCB.T).I := Character'Pos (CD.Strings_Constants_Table (idx)); idx := idx + 1; end loop; end Do_Load_String_Literal; procedure Do_Copy_Block is -- [T-1].all (0 .. IR.Y - 1) := [T].all (0 .. IR.Y - 1) Dst_Addr, Src_Addr, Last : Index; begin Dst_Addr := Index (ND.S (Curr_TCB.T - 1).I); Src_Addr := Index (ND.S (Curr_TCB.T).I); Last := Index (IR.Y) - 1; ND.S (Dst_Addr .. Dst_Addr + Last) := ND.S (Src_Addr .. Src_Addr + Last); Pop (ND, 2); end Do_Copy_Block; procedure Do_String_Literal_Assignment is H1, H2, H3, H4, H5 : Index; begin H1 := Index (ND.S (Curr_TCB.T - 2).I); -- Address of array H2 := Index (ND.S (Curr_TCB.T).I); -- Index to string table H3 := Index (IR.Y); -- Size of array H4 := Index (ND.S (Curr_TCB.T - 1).I); -- Length of string H5 := H1 + (if H3 < H4 then H3 else H4); while H1 < H5 loop -- Copy H5-H1 characters to the stack ND.S (H1).I := Character'Pos (CD.Strings_Constants_Table (H2)); H1 := H1 + 1; H2 := H2 + 1; end loop; -- Padding (does not happen, since lengths are checked at compile-time) H5 := Index (ND.S (Curr_TCB.T - 2).I) + H3; -- H5 = H1 + H3 while H1 < H5 loop -- Fill with blanks if req'd ND.S (H1).I := Character'Pos (' '); H1 := H1 + 1; end loop; Pop (ND, 3); end Do_String_Literal_Assignment; begin case Composite_Data_Opcode (ND.IR.F) is when k_Array_Index_Element_Size_1 => Do_Array_Index_Size_1; when k_Array_Index => Do_Array_Index_Any_Size; when k_Array_Index_No_Check_Element_Size_1 => Do_Array_Index_Size_1_No_Check; when k_Array_Index_No_Check => Do_Array_Index_Any_Size_No_Check; when k_Record_Field_Offset => ND.S (Curr_TCB.T).I := ND.S (Curr_TCB.T).I + IR.Y; when k_Load_Block => Do_Load_Block; when k_Load_String_Literal => Do_Load_String_Literal; when k_Copy_Block => Do_Copy_Block; when k_String_Literal_Assignment => Do_String_Literal_Assignment; end case; end Do_Composite_Data_Operation; end HAC_Sys.PCode.Interpreter.Composite_Data; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-composite_data.ads ================================================ with HAC_Sys.Co_Defs, HAC_Sys.PCode.Interpreter.In_Defs; private package HAC_Sys.PCode.Interpreter.Composite_Data is use Co_Defs, In_Defs; ----------------------- -- VM Instructions -- ----------------------- -- Execute instruction stored as Opcode in ND.IR.F. -- ND.IR.F is in the Composite_Data_Opcode subtype range. procedure Do_Composite_Data_Operation (CD : Compiler_Data; ND : in out Interpreter_Data); end HAC_Sys.PCode.Interpreter.Composite_Data; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-exceptions.adb ================================================ with Ada.Strings.Fixed; package body HAC_Sys.PCode.Interpreter.Exceptions is procedure Raise_Standard ( ND : in out In_Defs.Interpreter_Data; SE : Exception_Type; Msg : String := ""; Stop_Current_Instruction : Boolean := False ) is EI : Exception_Propagation_Data renames ND.TCB (ND.CurTask).Exception_Info; begin EI.Currently_Raised := (SE, 0); EI.Exception_Message := HAT.To_VString (Msg); ND.PS := In_Defs.Exception_Raised; if Stop_Current_Instruction then -- Skip the rest of what the current instruction -- does in the run-time library (e.g. I/O operations). raise VM_Raised_Exception; end if; end Raise_Standard; procedure Raise_VM_Exception_from_Constraint_Error (CE_Message : String) is -- We guess specialized kinds of "Constraint_Error"'s using -- the message provided by the host Ada system. -- For instance on an overflow check failure, GNAT issues CE with the message -- "raised CONSTRAINT_ERROR : xyz.adb:123 overflow check failed". begin if Ada.Strings.Fixed.Index (CE_Message, "overflow check") > 0 then raise VM_Overflow_Error; else raise VM_Constraint_Error; end if; end Raise_VM_Exception_from_Constraint_Error; end HAC_Sys.PCode.Interpreter.Exceptions; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-exceptions.ads ================================================ with HAC_Sys.PCode.Interpreter.In_Defs; package HAC_Sys.PCode.Interpreter.Exceptions is ------------------------ -- HAC's exceptions -- ------------------------ procedure Raise_Standard ( ND : in out In_Defs.Interpreter_Data; SE : Exception_Type; Msg : String := ""; Stop_Current_Instruction : Boolean := False ); --------------------------------------------------------- -- Exceptions raised in the host Ada system during -- -- VM execution, leading to a call to Raise_Standard -- --------------------------------------------------------- VM_Case_Check_Error : exception; VM_Constraint_Error : exception; VM_Division_by_0 : exception; VM_End_Error : exception; VM_Function_End_without_Return : exception; VM_Invalid_Data : exception; VM_Out_of_Range : exception; VM_Overflow_Error : exception; VM_Raised_Exception : exception; -- See Name_Error for an example. VM_Stack_Overflow : exception; VM_Stack_Underflow : exception; VM_Subprogram_Spec : exception; procedure Raise_VM_Exception_from_Constraint_Error (CE_Message : String); end HAC_Sys.PCode.Interpreter.Exceptions; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-in_defs.adb ================================================ with HAC_Sys.PCode.Interpreter.Exceptions; package body HAC_Sys.PCode.Interpreter.In_Defs is procedure Allocate_Text_File ( ND : in out Interpreter_Data; R : in out General_Register ) is use Defs; begin if R.Special /= Text_Files then R := GR_Abstract_Console; end if; if R.Txt = null or else Ada.Text_IO.Is_Open (R.Txt.all) -- ^ Uh oh, someone somewhere in the HAC program forgot to close -- a file at the same VM address. then R.Txt := new Ada.Text_IO.File_Type; ND.Files.Append (R.Txt); end if; end Allocate_Text_File; procedure Free_Allocated_Contents ( ND : in out Interpreter_Data; Open_Files : out Open_Files_Vectors.Vector ) is procedure Free is new Ada.Unchecked_Deallocation (Ada.Text_IO.File_Type, File_Ptr); procedure Free is new Ada.Unchecked_Deallocation (Stack_Type, Stack_Type_Access); open_file : Open_File_Data; use Ada.Text_IO; begin for F of ND.Files loop if F /= null then if Is_Open (F.all) then -- We close, for the distracted programmer, -- all files that are still open. -- In that respect, we do more than required by the RM (A.7(6)): -- "The language does not define what happens to external files -- after the completion of the main program and all the library -- tasks (in particular, if corresponding files have -- not been closed)." open_file.Name := HAT.To_VString (Name (F.all)); open_file.Mode := Mode (F.all); Open_Files.Append (open_file); Ada.Text_IO.Close (F.all); end if; Free (F); end if; end loop; Free (ND.S); end Free_Allocated_Contents; function Get_String_from_Stack (ND : Interpreter_Data; Idx, Size : Integer) return String is Res : String (1 .. Size); Number : Defs.HAC_Integer; begin for i in Res'Range loop Number := ND.S (Idx + i - 1).I; if Number not in Defs.OrdMinChar .. Defs.OrdMaxChar then raise Exceptions.VM_Out_of_Range with ": invalid data: element not in Character's range"; end if; Res (i) := Character'Val (Number); end loop; return Res; end Get_String_from_Stack; function GR_Real (R : Defs.HAC_Float) return General_Register is begin return (Special => Defs.Floats, I => 0, R => R); end GR_Real; function GR_Time (T : Ada.Calendar.Time) return General_Register is begin return (Special => Defs.Times, I => 0, Tim => T); end GR_Time; function GR_Duration (D : Duration) return General_Register is begin return (Special => Defs.Durations, I => 0, Dur => D); end GR_Duration; function GR_VString (S : String) return General_Register is begin return (Special => Defs.VStrings, I => 0, V => HAT.To_VString (S)); end GR_VString; function GR_VString (V : HAT.VString) return General_Register is begin return (Special => Defs.VStrings, I => 0, V => V); end GR_VString; procedure Pop (ND : in out Interpreter_Data; Amount : Positive := 1) is Curr_TCB_Top : Integer renames ND.TCB (ND.CurTask).T; begin Curr_TCB_Top := Curr_TCB_Top - Amount; if Curr_TCB_Top < ND.S'First then raise Exceptions.VM_Stack_Underflow; end if; end Pop; procedure Push (ND : in out Interpreter_Data; Amount : Positive := 1) is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); begin Curr_TCB.T := Curr_TCB.T + Amount; if Curr_TCB.T > Curr_TCB.STACKSIZE then raise Exceptions.VM_Stack_Overflow; end if; end Push; procedure Post_Mortem_Dump (CD : Co_Defs.Compiler_Data; ND : In_Defs.Interpreter_Data) is use Ada.Text_IO, Co_Defs, Defs.IIO, Defs.RIO; BLKCNT, H1, H2, H3 : Integer; -- !! Should use a file for dump !! begin New_Line; Put_Line ("HAC - PCode - Post Mortem Dump"); New_Line; Put_Line ("Processor state: " & Processor_State'Image (ND.PS)); New_Line; Put_Line ( "Stack Variables of Task " & Defs.A2S (CD.id_table (CD.Tasks_Definitions_Table (ND.CurTask)).name) ); H1 := ND.TCB (ND.CurTask).B; -- current bottom of stack BLKCNT := 10; loop New_Line; BLKCNT := BLKCNT - 1; if BLKCNT = 0 then H1 := 0; end if; H2 := Integer (ND.S (H1 + 4).I); -- index into HAC.Data.IdTab for this process if H1 = 0 then Put_Line ("Task Variables"); else Put (Defs.A2S (CD.id_table (H2).name)); Put (" CALLED AT"); Put (ND.S (H1 + 1).I, 5); New_Line; end if; H2 := CD.Blocks_Table (CD.id_table (H2).block_or_pkg_ref).Last_Id_Idx; while H2 /= 0 loop -- [P2Ada]: WITH instruction declare P2Ada_Var_7 : Identifier_Table_Entry renames CD.id_table (H2); use Defs; begin if P2Ada_Var_7.entity in Object_Kind then if Defs.Standard_or_Enum_Typ (P2Ada_Var_7.xtyp.TYP) then if P2Ada_Var_7.normal then H3 := H1 + Integer (P2Ada_Var_7.adr_or_sz); else H3 := Integer (ND.S (H1 + Integer (P2Ada_Var_7.adr_or_sz)).I); end if; Put (" " & A2S (P2Ada_Var_7.name) & " = "); case P2Ada_Var_7.xtyp.TYP is when Defs.Enums | Defs.Ints => Put (ND.S (H3).I); New_Line; when Defs.Bools => BIO.Put (Boolean'Val (ND.S (H3).I)); New_Line; when Defs.Floats => Put (ND.S (H3).R); New_Line; when Defs.Chars => Put (ND.S (H3).I); Put_Line (" (ASCII)"); when others => null; -- [P2Ada]: no otherwise / else in Pascal end case; end if; end if; H2 := P2Ada_Var_7.link; end; -- [P2Ada]: end of WITH end loop; H1 := Integer (ND.S (H1 + 3).I); exit when H1 < 0; end loop; end Post_Mortem_Dump; procedure Check_Discriminant_Type (X : General_Register; Y : Defs.Typen) is use Defs; begin if X.Special /= Y then raise Exceptions.VM_Invalid_Data; end if; end Check_Discriminant_Type; end HAC_Sys.PCode.Interpreter.In_Defs; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-in_defs.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- In_Defs: Internal Interpreter Definitions with HAC_Sys.Co_Defs, HAC_Sys.Defs; with Ada.Calendar, Ada.Containers.Vectors, Ada.Numerics.Float_Random, Ada.Unchecked_Deallocation; package HAC_Sys.PCode.Interpreter.In_Defs is NilTask : constant := -1; subtype TRange is Integer range 0 .. Defs.TaskMax; -- task index type Processor_State is ( Running, -- Normal processor state Exception_Raised, -- FIN, DEADLOCK, WAIT); subtype Running_or_in_Exception is Processor_State range Running .. Exception_Raised; type Task_State is ( -- SmallAda tasking stuff, not tested yet: Completed, Delayed, Ready, -- HAC is currently tested on this: Running, Exception_Raised, -- SmallAda tasking stuff, not tested yet: Critical, WaitRendzv, WaitSem, TimedRendz, TimedWait, Terminated); type PriCB is record -- Priority Control Block UPRI : Integer; -- User specified priority INHERIT : Boolean; -- Priority inheritance enabled end record; type File_Ptr is access Ada.Text_IO.File_Type; Abstract_Console : constant File_Ptr := null; type General_Register (Special : Defs.Typen := Defs.NOTYP) is record -- I is used for most uses: indices in the stack, Integers, Bools, Chars and Enums. I : Defs.HAC_Integer; case Special is -- This part is variant to save place. when Defs.Floats => R : Defs.HAC_Float; when Defs.VStrings => V : HAT.VString; when Defs.Times => Tim : Ada.Calendar.Time; when Defs.Durations => Dur : Duration; when Defs.Text_Files => Txt : File_Ptr := Abstract_Console; when others => null; end case; end record; GR_Abstract_Console : constant General_Register := (Special => Defs.Text_Files, I => 0, Txt => Abstract_Console); function GR_Real (R : Defs.HAC_Float) return General_Register; function GR_Time (T : Ada.Calendar.Time) return General_Register; function GR_Duration (D : Duration) return General_Register; function GR_VString (S : String) return General_Register; function GR_VString (V : HAT.VString) return General_Register; subtype Data_Type is General_Register; type Stack_Type is array (1 .. Defs.StMax) of Data_Type; type Stack_Type_Access is access Stack_Type; type Task_Control_Block is record T : Defs.Index; -- index of current top of stack B : Defs.Index; -- index of current base of stack PC : Defs.Index; -- program counter, next pcode TS : Task_State; -- current task state InRendzv : Integer; -- task in rendz with or -1 WAKETIME : Ada.Calendar.Time; -- end of delay period Pcontrol : PriCB; -- task priority parameter rec. QUANTUM : Duration; -- time slice LASTRUN : Ada.Calendar.Time; -- time last run end (fairness) DISPLAY : Co_Defs.Display_Type; -- Stack base index per nesting level, -- used for addressing variables. STACKSIZE : Defs.Index; -- Stack overflow is raised if exceeded. SUSPEND : Integer; -- id of object suspended on R1, R2, R3 : General_Register; R_Temp : General_Register; Exception_Info : Exception_Propagation_Data; end record; type Enode; type Eptr is access Enode; -- task entry rendzv pointer type Enode is record -- task entry structure Task_Index : TRange; -- index of task enqueued for rendzv Next : Eptr; -- next entry in list end record; procedure Dispose is new Ada.Unchecked_Deallocation (Enode, Eptr); type EHeader is record Task_Index : TRange; -- index of task that contains entry First : Eptr; -- ptr to first node in rendzv queue Last : Eptr; -- ptr to last node in rendzv queue end record; type Entry_Queue is array (1 .. Defs.entry_table_max) of EHeader; package File_Vectors is new Ada.Containers.Vectors (Positive, File_Ptr); type Task_Control_Blocks is array (TRange) of Task_Control_Block; Single_Task : constant := -1; subtype Scheduler_Type is Integer range Single_Task .. 6; type Tick_Type is mod 128; -- Objects of type Interpreter_Data contains data that may be useful -- to be kept post-mortem, or in a snapshot toward the "outside", or -- passed to the scheduler. type Interpreter_Data is record S : Stack_Type_Access; PS : Processor_State; -- Processor status register IR : Order; -- Instruction register CurTask : Integer; -- Index of currently executing task TCB : Task_Control_Blocks; Files : File_Vectors.Vector; Snap : Boolean; -- Snapshot flag to display scheduler status Nb_Callers : Integer; -- AVL TERMINATE Nb_Complete : Integer; -- AVL TERMINATE EList : Entry_Queue; TActive : TRange; -- no. of active tasks Start_Time : Ada.Calendar.Time; SWITCH : Boolean; -- invoke scheduler on next cycle flag SYSCLOCK : Ada.Calendar.Time; -- (ms after 00:00:00 Jan 1, current year) TIMER : Ada.Calendar.Time; -- set to end of current task's time slice Gen : Ada.Numerics.Float_Random.Generator; Scheduler : Scheduler_Type := Single_Task; Single_Task_Delay_Pending : Boolean := False; feedback_tick : Tick_Type; end record; procedure Allocate_Text_File ( ND : in out Interpreter_Data; R : in out General_Register ); procedure Free_Allocated_Contents ( ND : in out Interpreter_Data; Open_Files : out Open_Files_Vectors.Vector ); -- We have an "array of Character" (cf Is_Char_Array) on the stack function Get_String_from_Stack (ND : Interpreter_Data; Idx, Size : Integer) return String; procedure Pop (ND : in out Interpreter_Data; Amount : Positive := 1); pragma Inline (Pop); procedure Push (ND : in out Interpreter_Data; Amount : Positive := 1); pragma Inline (Push); -- Post Mortem Dump of the task stack causing the exception -- procedure Post_Mortem_Dump (CD : Co_Defs.Compiler_Data; ND : In_Defs.Interpreter_Data); procedure Check_Discriminant_Type (X : General_Register; Y : Defs.Typen); pragma Inline (Check_Discriminant_Type); end HAC_Sys.PCode.Interpreter.In_Defs; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-multi_statement.adb ================================================ with HAC_Sys.PCode.Interpreter.Exceptions; package body HAC_Sys.PCode.Interpreter.Multi_Statement is procedure Do_Multi_Statement_Operation (CD : Compiler_Data; ND : in out Interpreter_Data) is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); IR : Order renames ND.IR; use type Defs.HAC_Integer; procedure Do_CASE_Switch_1 is Value : constant Defs.HAC_Integer := ND.S (Curr_TCB.T).I; H2 : Integer; jump : Boolean; begin Pop (ND); H2 := Integer (IR.Y); -- -- Now we loop over a bunch of (k_CASE_Choice_Data, k_CASE_Match_Jump) pairs -- that should covers all cases. -- loop if CD.ObjCode (H2).F not in CASE_Any_Choice then -- We hit the end of (k_CASE_Choice_Data, k_CASE_Match_Jump) pairs. -- This means that Value, or OTHERS, were not found so far. -- This situation should not happen; it should be caught at compile-time. raise Exceptions.VM_Case_Check_Error; end if; case CASE_Any_Choice (CD.ObjCode (H2).F) is when k_CASE_Choice_Value => jump := Value = CD.ObjCode (H2).Y; when k_CASE_Choice_Range => jump := Value in CD.ObjCode (H2).X .. CD.ObjCode (H2).Y; when k_CASE_Choice_Others => jump := True; end case; if jump then -- The interpreter will execute instructions following "=>". -- The address is stored with a k_CASE_Match_Jump instruction just after -- the CASE_Any_Choice instruction. Curr_TCB.PC := Defs.Index (CD.ObjCode (H2 + 1).Y); exit; end if; -- Check the next (CASE_Any_Choice, k_CASE_Match_Jump) instruction pair: H2 := H2 + 2; end loop; end Do_CASE_Switch_1; stack_elements_used_by_FOR_loop : constant := 3; procedure Do_FOR_Forward_Begin is -- Start of a FOR loop, forward direction FOR_Param_Addr : constant Defs.Index := Defs.Index (ND.S (Curr_TCB.T - 2).I); Lower_Bound : constant Defs.HAC_Integer := ND.S (Curr_TCB.T - 1).I; Upper_Bound : constant Defs.HAC_Integer := ND.S (Curr_TCB.T).I; begin if Lower_Bound <= Upper_Bound then -- The range is not empty -> we can start the loop with the first value. ND.S (FOR_Param_Addr).I := Lower_Bound; else -- Empty range -> we don't enter the loop at all -> Jump after loop's end. Curr_TCB.PC := Defs.Index (IR.Y); Pop (ND, stack_elements_used_by_FOR_loop); end if; end Do_FOR_Forward_Begin; procedure Do_FOR_Forward_End is -- End of a FOR loop, forward direction FOR_Param_Addr : constant Defs.Index := Defs.Index (ND.S (Curr_TCB.T - 2).I); Upper_Bound : constant Defs.HAC_Integer := ND.S (Curr_TCB.T).I; Next_Value : Defs.HAC_Integer; begin Next_Value := ND.S (FOR_Param_Addr).I + 1; -- !! Overflow check before here if Next_Value <= Upper_Bound then ND.S (FOR_Param_Addr).I := Next_Value; Curr_TCB.PC := Defs.Index (IR.Y); -- Jump back to loop's begin else Pop (ND, stack_elements_used_by_FOR_loop); -- Leave loop (just go to next instruction) end if; end Do_FOR_Forward_End; procedure Do_FOR_Reverse_Begin is -- Start of a FOR loop, reverse direction FOR_Param_Addr : constant Defs.Index := Defs.Index (ND.S (Curr_TCB.T - 2).I); Lower_Bound : constant Defs.HAC_Integer := ND.S (Curr_TCB.T - 1).I; Upper_Bound : constant Defs.HAC_Integer := ND.S (Curr_TCB.T).I; begin if Lower_Bound <= Upper_Bound then -- The range is not empty -> we can start the loop with the first value. ND.S (FOR_Param_Addr).I := Upper_Bound; else -- Empty range -> we don't enter the loop at all -> Jump after loop's end. Curr_TCB.PC := Defs.Index (IR.Y); Pop (ND, stack_elements_used_by_FOR_loop); end if; end Do_FOR_Reverse_Begin; procedure Do_FOR_Reverse_End is -- End of a FOR loop, reverse direction FOR_Param_Addr : constant Defs.Index := Defs.Index (ND.S (Curr_TCB.T - 2).I); Lower_Bound : constant Defs.HAC_Integer := ND.S (Curr_TCB.T - 1).I; Next_Value : Defs.HAC_Integer; begin Next_Value := ND.S (FOR_Param_Addr).I - 1; -- !! Overflow check before here if Next_Value >= Lower_Bound then ND.S (FOR_Param_Addr).I := Next_Value; Curr_TCB.PC := Defs.Index (IR.Y); -- Jump back to loop's begin else Pop (ND, stack_elements_used_by_FOR_loop); -- Leave loop (just go to next instruction) end if; end Do_FOR_Reverse_End; begin case Multi_Statement_Opcode (ND.IR.F) is when k_CASE_Switch => Do_CASE_Switch_1; when CASE_Data_Opcode => null; -- Only via k_CASE_Switch. when k_FOR_Forward_Begin => Do_FOR_Forward_Begin; when k_FOR_Forward_End => Do_FOR_Forward_End; when k_FOR_Reverse_Begin => Do_FOR_Reverse_Begin; when k_FOR_Reverse_End => Do_FOR_Reverse_End; when k_FOR_Release_Stack => Pop (ND, stack_elements_used_by_FOR_loop * Natural (ND.IR.Y)); end case; end Do_Multi_Statement_Operation; end HAC_Sys.PCode.Interpreter.Multi_Statement; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-multi_statement.ads ================================================ with HAC_Sys.Co_Defs, HAC_Sys.PCode.Interpreter.In_Defs; private package HAC_Sys.PCode.Interpreter.Multi_Statement is use Co_Defs, In_Defs; ----------------------- -- VM Instructions -- ----------------------- -- Execute instruction stored as Opcode in ND.IR.F. -- ND.IR.F is in the Multi_Statement_Opcode subtype range. procedure Do_Multi_Statement_Operation (CD : Compiler_Data; ND : in out Interpreter_Data); end HAC_Sys.PCode.Interpreter.Multi_Statement; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-operators.adb ================================================ with HAC_Sys.Co_Defs, HAC_Sys.Interfacing, HAC_Sys.PCode.Interpreter.Exceptions; with HAT; with Ada.Calendar, Ada.Exceptions, Ada.Numerics, Ada.Strings.Fixed; package body HAC_Sys.PCode.Interpreter.Operators is procedure Do_Unary_Operator (ND : in out In_Defs.Interpreter_Data) is use In_Defs; Curr_TCB_Top : Integer renames ND.TCB (ND.CurTask).T; X : General_Register renames ND.S (Curr_TCB_Top); H1 : Defs.Index; use type Defs.HAC_Float, Defs.HAC_Integer; I_to_F : Defs.HAC_Float; begin case Unary_Operator_Opcode (ND.IR.F) is when k_Dereference => X := ND.S (Defs.Index (X.I)); -- "[T] := ([T].I).all" when k_Dereference_Discrete => X.I := ND.S (Defs.Index (X.I)).I; when k_NOT_Boolean => X.I := Boolean'Pos (not Boolean'Val (X.I)); when k_Unary_MINUS_Float => X.R := -X.R; when k_Unary_MINUS_Integer => if X.I = Defs.HAC_Integer'First then raise Exceptions.VM_Overflow_Error; end if; X.I := -X.I; when k_Integer_to_Float => H1 := Curr_TCB_Top - Defs.Index (ND.IR.Y); I_to_F := Defs.HAC_Float (ND.S (H1).I); ND.S (H1) := GR_Real (I_to_F); end case; end Do_Unary_Operator; procedure Do_Binary_Operator (ND : in out In_Defs.Interpreter_Data) is use In_Defs; Curr_TCB_Top : Integer renames ND.TCB (ND.CurTask).T; X : General_Register renames ND.S (Curr_TCB_Top - 1); -- X = [T-1] Y : General_Register renames ND.S (Curr_TCB_Top); -- Y = [T] use type Defs.HAC_Float, Defs.HAC_Integer, Defs.Typen; -- procedure Check_X_Float is pragma Inline (Check_X_Float); begin if X.Special /= Defs.Floats then raise Exceptions.VM_Invalid_Data; end if; end Check_X_Float; -- procedure Check_X_Y_Float is pragma Inline (Check_X_Y_Float); begin if X.Special /= Defs.Floats or else Y.Special /= Defs.Floats then raise Exceptions.VM_Invalid_Data; end if; end Check_X_Y_Float; use HAT.VStr_Pkg; begin -- We do [T-1] <- ([T-1] operator [T]) and pop later. case Binary_Operator_Opcode (ND.IR.F) is when k_EQL_Float => Check_X_Y_Float; X.I := Boolean'Pos (X.R = Y.R); when k_NEQ_Float => Check_X_Y_Float; X.I := Boolean'Pos (X.R /= Y.R); when k_LSS_Float => Check_X_Y_Float; X.I := Boolean'Pos (X.R < Y.R); when k_LEQ_Float => Check_X_Y_Float; X.I := Boolean'Pos (X.R <= Y.R); when k_GTR_Float => Check_X_Y_Float; X.I := Boolean'Pos (X.R > Y.R); when k_GEQ_Float => Check_X_Y_Float; X.I := Boolean'Pos (X.R >= Y.R); -- when k_EQL_Integer => X.I := Boolean'Pos (X.I = Y.I); when k_NEQ_Integer => X.I := Boolean'Pos (X.I /= Y.I); when k_LSS_Integer => X.I := Boolean'Pos (X.I < Y.I); when k_LEQ_Integer => X.I := Boolean'Pos (X.I <= Y.I); when k_GTR_Integer => X.I := Boolean'Pos (X.I > Y.I); when k_GEQ_Integer => X.I := Boolean'Pos (X.I >= Y.I); -- when k_EQL_VString => X.I := Boolean'Pos (X.V = Y.V); when k_NEQ_VString => X.I := Boolean'Pos (X.V /= Y.V); when k_LSS_VString => X.I := Boolean'Pos (X.V < Y.V); when k_LEQ_VString => X.I := Boolean'Pos (X.V <= Y.V); when k_GTR_VString => X.I := Boolean'Pos (X.V > Y.V); when k_GEQ_VString => X.I := Boolean'Pos (X.V >= Y.V); -- when k_AND_Boolean => X.I := Boolean'Pos (Boolean'Val (X.I) and Boolean'Val (Y.I)); when k_OR_Boolean => X.I := Boolean'Pos (Boolean'Val (X.I) or Boolean'Val (Y.I)); when k_XOR_Boolean => X.I := Boolean'Pos (Boolean'Val (X.I) xor Boolean'Val (Y.I)); -- when k_ADD_Integer => X.I := X.I + Y.I; when k_SUBTRACT_Integer => X.I := X.I - Y.I; when k_MULT_Integer => X.I := X.I * Y.I; when k_DIV_Integer => if Y.I = 0 then raise Exceptions.VM_Division_by_0 with "/"; end if; X.I := X.I / Y.I; when k_MOD_Integer => if Y.I = 0 then raise Exceptions.VM_Division_by_0 with "mod"; end if; X.I := X.I mod Y.I; when k_REM_Integer => if Y.I = 0 then raise Exceptions.VM_Division_by_0 with "rem"; end if; X.I := X.I rem Y.I; when k_Power_Integer => X.I := X.I ** Natural (Y.I); -- when k_ADD_Float => Check_X_Y_Float; X.R := X.R + Y.R; when k_SUBTRACT_Float => Check_X_Y_Float; X.R := X.R - Y.R; when k_MULT_Float => Check_X_Y_Float; X.R := X.R * Y.R; when k_DIV_Float => Check_X_Y_Float; X.R := X.R / Y.R; when k_Power_Float => Check_X_Y_Float; X.R := X.R ** Y.R; when k_Power_Float_Integer => Check_X_Float; X.R := X.R ** Natural (Y.I); end case; Pop (ND); exception when E : Constraint_Error | Ada.Numerics.Argument_Error => Exceptions.Raise_VM_Exception_from_Constraint_Error (Ada.Exceptions.Exception_Message (E)); end Do_Binary_Operator; procedure Do_Multiple_Operator (ND : in out In_Defs.Interpreter_Data) is use In_Defs; Top : Integer renames ND.TCB (ND.CurTask).T; result_pos, terms : Integer; use type Defs.HAC_Float, Defs.HAC_Integer, Defs.Typen; begin -- [T-(terms-1)] := [T-(terms-1)] + [T-(terms-1)+1] + ... + [T-(terms-1)+(terms-1)] terms := Integer (ND.IR.Y); result_pos := Top - (terms - 1); case Multiple_Operator_Opcode (ND.IR.F) is when k_ADD_Integer_Multiple => for term in 2 .. terms loop ND.S (result_pos).I := ND.S (result_pos).I + ND.S (result_pos + term - 1).I; end loop; when k_ADD_Float_Multiple => for cell in 0 .. terms - 1 loop if ND.S (result_pos + cell).Special /= Defs.Floats then raise Exceptions.VM_Invalid_Data; end if; end loop; for term in 2 .. terms loop ND.S (result_pos).R := ND.S (result_pos).R + ND.S (result_pos + term - 1).R; end loop; end case; Pop (ND, terms - 1); exception when E : Constraint_Error => Exceptions.Raise_VM_Exception_from_Constraint_Error (Ada.Exceptions.Exception_Message (E)); end Do_Multiple_Operator; procedure Do_Special_Operator (ND : in out In_Defs.Interpreter_Data) is use In_Defs; Top : Integer renames ND.TCB (ND.CurTask).T; X : General_Register renames ND.S (Top - 2); -- X = [T-2] Y : General_Register renames ND.S (Top - 1); -- Y = [T-1] Z : General_Register renames ND.S (Top); -- Z = [T] use type Defs.HAC_Float, Defs.HAC_Integer, Defs.Typen; -- procedure Check_Y_Z_Float is pragma Inline (Check_Y_Z_Float); begin if Y.Special /= Defs.Floats or else Z.Special /= Defs.Floats then raise Exceptions.VM_Invalid_Data; end if; end Check_Y_Z_Float; begin case Special_Operator_Opcode (ND.IR.F) is when k_MULT_then_ADD_Integer => X.I := X.I + Y.I * Z.I; Pop (ND, 2); when k_MULT_then_ADD_Float => for cell in 0 .. 2 loop if ND.S (Top - cell).Special /= Defs.Floats then raise Exceptions.VM_Invalid_Data; end if; end loop; X.R := X.R + Y.R * Z.R; Pop (ND, 2); when Op_then_Store_Opcode => case Op_then_Store_Opcode (ND.IR.F) is when k_ADD_Integer_then_Store => ND.S (Defs.Index (X.I)).I := Y.I + Z.I; when k_SUBTRACT_Integer_then_Store => ND.S (Defs.Index (X.I)).I := Y.I - Z.I; when k_MULT_Integer_then_Store => ND.S (Defs.Index (X.I)).I := Y.I * Z.I; when Op_Float_then_Store_Opcode => Check_Y_Z_Float; case Op_Float_then_Store_Opcode (ND.IR.F) is when k_ADD_Float_then_Store => ND.S (Defs.Index (X.I)) := GR_Real (Y.R + Z.R); when k_SUBTRACT_Float_then_Store => ND.S (Defs.Index (X.I)) := GR_Real (Y.R - Z.R); when k_MULT_Float_then_Store => ND.S (Defs.Index (X.I)) := GR_Real (Y.R * Z.R); end case; end case; Pop (ND, 3); when Op_Integer_Literal_Opcode => -- No push / pop ! case Op_Integer_Literal_Opcode (ND.IR.F) is when k_ADD_Integer_Literal => Z.I := Z.I + ND.IR.Y; when k_SUBTRACT_Integer_Literal => Z.I := Z.I - ND.IR.Y; when k_MULT_Integer_Literal => Z.I := Z.I * ND.IR.Y; when k_DIV_Integer_Literal => if ND.IR.Y = 0 then raise Exceptions.VM_Division_by_0 with "/"; end if; Z.I := Z.I / ND.IR.Y; when Compare_Integer_Literal_Opcode => case Compare_Integer_Literal_Opcode (ND.IR.F) is when k_EQL_Integer_Literal => Z.I := Boolean'Pos (Z.I = ND.IR.Y); when k_NEQ_Integer_Literal => Z.I := Boolean'Pos (Z.I /= ND.IR.Y); when k_LSS_Integer_Literal => Z.I := Boolean'Pos (Z.I < ND.IR.Y); when k_LEQ_Integer_Literal => Z.I := Boolean'Pos (Z.I <= ND.IR.Y); when k_GTR_Integer_Literal => Z.I := Boolean'Pos (Z.I > ND.IR.Y); when k_GEQ_Integer_Literal => Z.I := Boolean'Pos (Z.I >= ND.IR.Y); end case; end case; when k_NAND_Boolean => Y.I := Boolean'Pos (not (Boolean'Val (Y.I) and Boolean'Val (Z.I))); Pop (ND); when k_NOR_Boolean => Y.I := Boolean'Pos (not (Boolean'Val (Y.I) or Boolean'Val (Z.I))); Pop (ND); end case; exception when E : Constraint_Error => Exceptions.Raise_VM_Exception_from_Constraint_Error (Ada.Exceptions.Exception_Message (E)); end Do_Special_Operator; procedure Do_SF_Operator (BD : Builder.Build_Data; ND : in out In_Defs.Interpreter_Data) is use Defs, In_Defs; CD : Co_Defs.Compiler_Data renames BD.CD.all; Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); Top_Item : General_Register renames ND.S (Curr_TCB.T); idx, len, from, to : Integer; c : Character; code : constant SF_Code := SF_Code'Val (ND.IR.Y); use Exceptions; use Ada.Strings; use type HAC_Integer, HAC_Float, HAT.Time, HAT.VString; Going : Direction; -- begin case code is when SF_Abs_Int => Top_Item.I := abs (Top_Item.I); when SF_Abs_Float => Top_Item.R := abs (Top_Item.R); when SF_T_Val => -- Ord = Character'Val : RM 3.5.5 (5,7) if Top_Item.I not in Defs.OrdMinChar .. Defs.OrdMaxChar then raise VM_Out_of_Range with ": not in Character's range"; end if; when SF_T_Pos => -- S'Pos : RM 3.5.5 (2) null; when SF_T_Succ => Top_Item.I := Top_Item.I + 1; -- S'Succ : RM 3.5 (22) when SF_T_Pred => Top_Item.I := Top_Item.I - 1; -- S'Pred : RM 3.5 (25) when SF_in_discrete_Interval => -- SF_in_discrete_Interval (x, a, b) is equivalent to: `x in a .. b` Pop (ND, 2); -- [T] := [T] in [T+1] .. [T+2] ND.S (Curr_TCB.T).I := Boolean'Pos ( ND.S (Curr_TCB.T).I in ND.S (Curr_TCB.T + 1).I .. ND.S (Curr_TCB.T + 2).I ); when SF_not_in_discrete_Interval => -- SF_not_in_discrete_Interval (x, a, b) is equivalent to: `x not in a .. b` Pop (ND, 2); -- [T] := [T] not in [T+1] .. [T+2] ND.S (Curr_TCB.T).I := Boolean'Pos ( ND.S (Curr_TCB.T).I not in ND.S (Curr_TCB.T + 1).I .. ND.S (Curr_TCB.T + 2).I ); when SF_Round_Float_to_Int => Top_Item.I := HAC_Integer (Top_Item.R); when SF_Trunc_Float_to_Int => Top_Item.I := HAC_Integer (Defs.HAC_Float'Floor (Top_Item.R)); when SF_Float_to_Duration => Top_Item := GR_Duration (Duration (Top_Item.R)); when SF_Duration_to_Float => Top_Item := GR_Real (Defs.HAC_Float (Top_Item.Dur)); when SF_Int_to_Duration => Top_Item := GR_Duration (Duration (Top_Item.I)); when SF_Duration_to_Int => Top_Item.I := HAC_Integer (Top_Item.Dur); when SF_Sin => Top_Item.R := HAT.Sin (Top_Item.R); when SF_Cos => Top_Item.R := HAT.Cos (Top_Item.R); when SF_Exp => Top_Item.R := HAT.Exp (Top_Item.R); when SF_Log => Top_Item.R := HAT.Log (Top_Item.R); when SF_Sqrt => Top_Item.R := HAT.Sqrt (Top_Item.R); when SF_Arctan => Top_Item.R := HAT.Arctan (Top_Item.R); when SF_Sgn_Int => Top_Item.I := (if Top_Item.I > 0 then 1 elsif Top_Item.I < 0 then -1 else 0); when SF_Sgn_Float => Top_Item.R := (if Top_Item.R > 0.0 then 1.0 elsif Top_Item.R < 0.0 then -1.0 else 0.0); when SF_Random_Int => Top_Item.I := HAC_Integer (HAT.Rand (Integer (Top_Item.I))); when SF_Min_Int => Pop (ND); -- [T] := Min ([T], [T+1]) : ND.S (Curr_TCB.T).I := HAC_Integer'Min (ND.S (Curr_TCB.T).I, ND.S (Curr_TCB.T + 1).I); when SF_Max_Int => Pop (ND); -- [T] := Max ([T], [T+1]) : ND.S (Curr_TCB.T).I := HAC_Integer'Max (ND.S (Curr_TCB.T).I, ND.S (Curr_TCB.T + 1).I); when SF_Min_Float => Pop (ND); -- [T] := Min ([T], [T+1]) : ND.S (Curr_TCB.T).R := HAC_Float'Min (ND.S (Curr_TCB.T).R, ND.S (Curr_TCB.T + 1).R); when SF_Max_Float => Pop (ND); -- [T] := Max ([T], [T+1]) : ND.S (Curr_TCB.T).R := HAC_Float'Max (ND.S (Curr_TCB.T).R, ND.S (Curr_TCB.T + 1).R); when SF_String_to_VString => -- Unary "+", equivalent to the call To_VString (S) idx := Integer (ND.S (Curr_TCB.T).I); -- Index in the stack (the string's address) len := Integer (ND.IR.X); -- Length of string ND.S (Curr_TCB.T) := GR_VString (Get_String_from_Stack (ND, idx, len)); when SF_String_Literal_to_VString => -- Unary "+", equivalent to the call To_VString ("abc") Pop (ND); len := Integer (ND.S (Curr_TCB.T).I); -- Length of string idx := Integer (ND.S (Curr_TCB.T + 1).I); -- Index to string table ND.S (Curr_TCB.T) := GR_VString (CD.Strings_Constants_Table (idx .. idx + len - 1)); when SF_VString_to_String => -- The type has just changed to Strings_as_VStrings at parser level. -- For the VM, it's a VString one way or the other. null; when SF_Char_to_VString => -- We create a 1-character temporary String: (1 => Character'Val (...)) and -- convert it to a VString. ND.S (Curr_TCB.T) := GR_VString (HAT.To_VString ((1 => Character'Val (ND.S (Curr_TCB.T).I)))); when SF_Two_VStrings_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T), Defs.VStrings); Check_Discriminant_Type (ND.S (Curr_TCB.T + 1), Defs.VStrings); -- [T] := [T] & [T+1] : ND.S (Curr_TCB.T).V := ND.S (Curr_TCB.T).V & ND.S (Curr_TCB.T + 1).V; when SF_VString_Char_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T), Defs.VStrings); ND.S (Curr_TCB.T).V := ND.S (Curr_TCB.T).V & Character'Val (ND.S (Curr_TCB.T + 1).I); when SF_Char_VString_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T + 1), Defs.VStrings); ND.S (Curr_TCB.T) := GR_VString (Character'Val (ND.S (Curr_TCB.T).I) & ND.S (Curr_TCB.T + 1).V); when SF_LStr_VString_Concat => -- Literal: 2 items, VString: 1 item. Total, 3 items folded into 1 item. Pop (ND, 2); len := Integer (ND.S (Curr_TCB.T).I); -- Length of string idx := Integer (ND.S (Curr_TCB.T + 1).I); -- Index to string table Check_Discriminant_Type (ND.S (Curr_TCB.T + 2), Defs.VStrings); ND.S (Curr_TCB.T) := GR_VString (CD.Strings_Constants_Table (idx .. idx + len - 1) & ND.S (Curr_TCB.T + 2).V); when SF_VString_Int_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T), Defs.VStrings); HAT.VStr_Pkg.Append (ND.S (Curr_TCB.T).V, HAC_Image (ND.S (Curr_TCB.T + 1).I)); when SF_Int_VString_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T + 1), Defs.VStrings); ND.S (Curr_TCB.T) := GR_VString ((HAC_Image (ND.S (Curr_TCB.T).I)) & ND.S (Curr_TCB.T + 1).V); when SF_VString_Float_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T), Defs.VStrings); HAT.VStr_Pkg.Append (ND.S (Curr_TCB.T).V, HAT.HAC_Image (ND.S (Curr_TCB.T + 1).R)); when SF_Float_VString_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T + 1), Defs.VStrings); ND.S (Curr_TCB.T) := GR_VString (HAT."&" (ND.S (Curr_TCB.T).R, ND.S (Curr_TCB.T + 1).V)); when SF_VString_Duration_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T), Defs.VStrings); HAT.VStr_Pkg.Append (ND.S (Curr_TCB.T).V, HAT.Image (ND.S (Curr_TCB.T + 1).Dur)); when SF_Duration_VString_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T + 1), Defs.VStrings); ND.S (Curr_TCB.T) := GR_VString (HAT."&" (ND.S (Curr_TCB.T).Dur, ND.S (Curr_TCB.T + 1).V)); when SF_VString_Boolean_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T), Defs.VStrings); ND.S (Curr_TCB.T).V := HAT."&" (ND.S (Curr_TCB.T).V, Boolean'Val (ND.S (Curr_TCB.T + 1).I)); when SF_Boolean_VString_Concat => Pop (ND); Check_Discriminant_Type (ND.S (Curr_TCB.T + 1), Defs.VStrings); ND.S (Curr_TCB.T) := GR_VString (HAT."&" (Boolean'Val (ND.S (Curr_TCB.T).I), ND.S (Curr_TCB.T + 1).V)); when SF_Element => Pop (ND); -- [T] := Element ([T], [T+1]) : idx := Integer (ND.S (Curr_TCB.T + 1).I); len := HAT.Length (ND.S (Curr_TCB.T).V); if idx < 1 then Raise_Standard (ND, VME_Index_Error, "Element: Index not positive", True); elsif idx > len then Raise_Standard (ND, VME_Index_Error, "Element: Index," & idx'Image & ", is larger than Length (Source)," & len'Image, True); end if; c := HAT.Element (ND.S (Curr_TCB.T).V, idx); ND.S (Curr_TCB.T).I := Character'Pos (c); when SF_Length => -- [T] := Length ([T]) : len := HAT.Length (Top_Item.V); Top_Item.I := HAC_Integer (len); when SF_Slice => Pop (ND, 2); from := Integer (ND.S (Curr_TCB.T + 1).I); to := Integer (ND.S (Curr_TCB.T + 2).I); if from < 1 then Raise_Standard (ND, VME_Constraint_Error, "Slice: Low is not positive:" & Integer'Image (from), True); elsif to < 0 then Raise_Standard (ND, VME_Constraint_Error, "Slice: High is negative: " & Integer'Image (to), True); end if; len := HAT.Length (ND.S (Curr_TCB.T).V); if from > len + 1 then Raise_Standard (ND, VME_Index_Error, "Slice: Low is larger than Length (Source) + 1. See RM A.4.4 (101)", True); elsif to > len then Raise_Standard (ND, VME_Index_Error, "Slice: High is larger than Length (Source). See RM A.4.4 (101)", True); end if; -- [T] := Slice ([T], [T+1], [T+2]) : HAT.VStr_Pkg.Set_Unbounded_String (ND.S (Curr_TCB.T).V, HAT.VStr_Pkg.Slice (ND.S (Curr_TCB.T).V, from, to)); when SF_To_Lower_Char => Top_Item.I := Character'Pos (HAT.To_Lower (Character'Val (Top_Item.I))); when SF_To_Upper_Char => Top_Item.I := Character'Pos (HAT.To_Upper (Character'Val (Top_Item.I))); when SF_To_Lower_VStr => HAT.VStr_Pkg.Set_Unbounded_String (Top_Item.V, HAT.ACH.To_Lower (HAT.VStr_Pkg.To_String (Top_Item.V))); when SF_To_Upper_VStr => HAT.VStr_Pkg.Set_Unbounded_String (Top_Item.V, HAT.ACH.To_Upper (HAT.VStr_Pkg.To_String (Top_Item.V))); when SF_Index | SF_Index_Backward => Going := (if code = SF_Index then Forward else Backward); Pop (ND, 2); from := Integer (ND.S (Curr_TCB.T + 2).I); ND.S (Curr_TCB.T).I := HAC_Integer (if from >= 1 then -- [T] := Index (Source: [T], Pattern: [T+1], From: [T+2], Going) : HAT.VStr_Pkg.Index (ND.S (Curr_TCB.T).V, HAT.VStr_Pkg.To_String (ND.S (Curr_TCB.T + 1).V), from, Going) else -- [T] := Index (Source: [T], Pattern: [T+1], Going) : HAT.VStr_Pkg.Index (ND.S (Curr_TCB.T).V, HAT.VStr_Pkg.To_String (ND.S (Curr_TCB.T + 1).V), Going)); when SF_Head => Pop (ND); -- [T] := Head ([T], [T+1]) : ND.S (Curr_TCB.T).V := HAT.VStr_Pkg.Head (ND.S (Curr_TCB.T).V, Natural (ND.S (Curr_TCB.T + 1).I)); when SF_Tail => Pop (ND); -- [T] := Tail ([T], [T+1]) : ND.S (Curr_TCB.T).V := HAT.VStr_Pkg.Tail (ND.S (Curr_TCB.T).V, Natural (ND.S (Curr_TCB.T + 1).I)); when SF_Head_Before_Match => Pop (ND); -- [T] := Head_Before_Match ([T], [T+1]) : ND.S (Curr_TCB.T).V := HAT.Head_Before_Match (ND.S (Curr_TCB.T).V, ND.S (Curr_TCB.T + 1).V); when SF_Tail_After_Match => Pop (ND); -- [T] := Tail_After_Match ([T], [T+1]) : ND.S (Curr_TCB.T).V := HAT.Tail_After_Match (ND.S (Curr_TCB.T).V, ND.S (Curr_TCB.T + 1).V); when SF_Starts_With => Pop (ND); -- [T] := Starts_With ([T], [T+1]) : ND.S (Curr_TCB.T).I := Boolean'Pos (HAT.Starts_With (ND.S (Curr_TCB.T).V, ND.S (Curr_TCB.T + 1).V)); when SF_Ends_With => Pop (ND); -- [T] := Ends_With ([T], [T+1]) : ND.S (Curr_TCB.T).I := Boolean'Pos (HAT.Ends_With (ND.S (Curr_TCB.T).V, ND.S (Curr_TCB.T + 1).V)); when SF_Year => ND.S (Curr_TCB.T).I := HAC_Integer (Ada.Calendar.Year (ND.S (Curr_TCB.T).Tim)); when SF_Month => ND.S (Curr_TCB.T).I := HAC_Integer (Ada.Calendar.Month (ND.S (Curr_TCB.T).Tim)); when SF_Day => ND.S (Curr_TCB.T).I := HAC_Integer (Ada.Calendar.Day (ND.S (Curr_TCB.T).Tim)); when SF_Seconds => ND.S (Curr_TCB.T) := GR_Duration (Ada.Calendar.Seconds (ND.S (Curr_TCB.T).Tim)); when SF_Int_Times_Char => Pop (ND); if ND.S (Curr_TCB.T).I < 0 then raise VM_Out_of_Range with ": negative value"; end if; -- [T] := [T] * [T+1] : ND.S (Curr_TCB.T) := GR_VString (Natural (ND.S (Curr_TCB.T).I) * Character'Val (ND.S (Curr_TCB.T + 1).I)); when SF_Int_Times_VStr => Pop (ND); if ND.S (Curr_TCB.T).I < 0 then raise VM_Out_of_Range with ": negative value"; end if; -- [T] := [T] * [T+1] : ND.S (Curr_TCB.T) := GR_VString (Natural (ND.S (Curr_TCB.T).I) * ND.S (Curr_TCB.T + 1).V); when SF_Trim_Left => Top_Item.V := HAT.VStr_Pkg.Trim (Top_Item.V, Left); when SF_Trim_Right => Top_Item.V := HAT.VStr_Pkg.Trim (Top_Item.V, Right); when SF_Trim_Both => Top_Item.V := HAT.VStr_Pkg.Trim (Top_Item.V, Both); -- when SF_Time_Subtract => Pop (ND); ND.S (Curr_TCB.T) := GR_Duration (ND.S (Curr_TCB.T).Tim - ND.S (Curr_TCB.T + 1).Tim); when SF_Duration_Subtract => Pop (ND); ND.S (Curr_TCB.T).Dur := ND.S (Curr_TCB.T).Dur - ND.S (Curr_TCB.T + 1).Dur; when SF_Duration_Add => Pop (ND); ND.S (Curr_TCB.T).Dur := ND.S (Curr_TCB.T).Dur + ND.S (Curr_TCB.T + 1).Dur; -- when SF_Image_Ints => Top_Item := GR_VString (HAC_Image (Top_Item.I)); when SF_Image_Floats => Top_Item := GR_VString (HAT.HAC_Image (Top_Item.R)); when SF_Image_Times => Top_Item := GR_VString (HAT.HAC_Image (Top_Item.Tim)); when SF_Image_Durations => Top_Item := GR_VString (HAT.Image (Top_Item.Dur)); -- when SF_Integer_Value | SF_Value_Attribute_Ints => begin Top_Item.I := HAC_Integer'Value (HAT.To_String (Top_Item.V)); exception when E : Constraint_Error => Raise_Standard (ND, VME_Constraint_Error, Ada.Exceptions.Exception_Message (E), True); end; when SF_Float_Value | SF_Value_Attribute_Floats => begin Top_Item := GR_Real (HAC_Float'Value (HAT.To_String (Top_Item.V))); exception when E : Constraint_Error => Raise_Standard (ND, VME_Constraint_Error, Ada.Exceptions.Exception_Message (E), True); end; -- when SF_Image_Attribute_Ints => Top_Item := GR_VString (HAC_Integer'Image (Top_Item.I)); when SF_Image_Attribute_Floats => Top_Item := GR_VString (HAC_Float'Image (Top_Item.R)); when SF_Image_Attribute_Bools => Top_Item := GR_VString (Boolean'Image (Boolean'Val (Top_Item.I))); when SF_Image_Attribute_Chars => Top_Item := GR_VString (Character'Image (Character'Val (Top_Item.I))); when SF_Image_Attribute_Durs => Top_Item := GR_VString (Duration'Image (Top_Item.Dur)); when SF_Image_Attribute_Enums => -- .Name contains the upper case representation as required by RM 3.5 (32). declare full_name : constant String := A2S (CD.id_table (Natural (ND.IR.X) + Natural (Top_Item.I)).name); dot : constant Natural := Ada.Strings.Fixed.Index (full_name, ".", Going => Backward); begin Top_Item := (if dot = 0 then GR_VString (full_name) else GR_VString (full_name (dot + 1 .. full_name'Last))); end; -- when SF_Value_Attribute_Bools => begin Top_Item.I := Boolean'Pos (Boolean'Value (HAT.To_String (Top_Item.V))); exception when E : Constraint_Error => Raise_Standard (ND, VME_Constraint_Error, Ada.Exceptions.Exception_Message (E), True); end; when SF_Value_Attribute_Chars => begin Top_Item.I := Character'Pos (Character'Value (HAT.To_String (Top_Item.V))); exception when E : Constraint_Error => Raise_Standard (ND, VME_Constraint_Error, Ada.Exceptions.Exception_Message (E), True); end; when SF_Value_Attribute_Durs => begin Top_Item := GR_Duration (Duration'Value (HAT.To_String (Top_Item.V))); exception when E : Constraint_Error => Raise_Standard (ND, VME_Constraint_Error, Ada.Exceptions.Exception_Message (E), True); end; when SF_Value_Attribute_Enums => -- If there is a performance issue here, we could replace -- this linear search with something using Hashed_Maps. declare to_match_any_case : constant String := HAT.To_String (Top_Item.V); to_match : constant String := HAT.ACH.To_Upper (to_match_any_case); j : HAC_Integer := -1; begin for i in 0 .. CD.id_table (Natural (ND.IR.X)).xtyp.Discrete_Last loop if CD.id_table (Natural (ND.IR.X) + Natural (i + 1)).name = to_match then j := i; exit; end if; end loop; if j >= 0 then Top_Item.I := j; else Raise_Standard (ND, VME_Constraint_Error, '"' & to_match_any_case & """ is not a literal of enumeration type """ & A2S (CD.id_table (Natural (ND.IR.X)).name_with_case) & '"', True); end if; end; -- when SF_Exists => Top_Item.I := Boolean'Pos (HAT.Exists (Top_Item.V)); when SF_Directory_Exists => Top_Item.I := Boolean'Pos (HAT.Directory_Exists (Top_Item.V)); when SF_File_Exists => Top_Item.I := Boolean'Pos (HAT.File_Exists (Top_Item.V)); when SF_Get_Env => Top_Item.V := HAT.Get_Env (Top_Item.V); when SF_Get_VM_Variable => HAT.VStr_Pkg.Set_Unbounded_String (Top_Item.V, Interfacing.Get_VM_Variable (BD, HAT.To_String (Top_Item.V))); -- when SF_Niladic => -- NILADIC functions need to push a new item (their own result). Push (ND); case SF_Niladic (code) is when SF_Clock => ND.S (Curr_TCB.T) := GR_Time (Ada.Calendar.Clock); when SF_Random_Float => ND.S (Curr_TCB.T) := GR_Real (Defs.HAC_Float (HAT.Rnd)); when SF_Null_VString => ND.S (Curr_TCB.T) := GR_VString (HAT.Null_VString); when SF_Argument_Count | SF_Directory_Separator | SF_Current_Directory | SF_Get_Needs_Skip_Line | SF_Command_Name => -- Those functions have been already processed at an -- upper calling level by Do_Standard_Function. null; end case; when SF_File_or_Console_Information | SF_Argument => -- Those functions have been already processed at an -- upper calling level by Do_Standard_Function. null; when SF_Is_Open => ND.S (Curr_TCB.T).I := Boolean'Pos (HAT.Is_Open (ND.S (Curr_TCB.T).Txt.all)); end case; exception when E : Ada.Numerics.Argument_Error => Exceptions.Raise_VM_Exception_from_Constraint_Error (Ada.Exceptions.Exception_Message (E)); end Do_SF_Operator; end HAC_Sys.PCode.Interpreter.Operators; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-operators.ads ================================================ with HAC_Sys.Builder, HAC_Sys.PCode.Interpreter.In_Defs; private package HAC_Sys.PCode.Interpreter.Operators is ----------------------- -- VM Instructions -- ----------------------- -- Execute operator stored as Opcode in ND.IR.F. procedure Do_Unary_Operator (ND : in out In_Defs.Interpreter_Data); procedure Do_Binary_Operator (ND : in out In_Defs.Interpreter_Data); procedure Do_Multiple_Operator (ND : in out In_Defs.Interpreter_Data); procedure Do_Special_Operator (ND : in out In_Defs.Interpreter_Data); -- Execute operator through the Opcode k_Standard_Functions. procedure Do_SF_Operator (BD : Builder.Build_Data; ND : in out In_Defs.Interpreter_Data); end HAC_Sys.PCode.Interpreter.Operators; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-tasking-scheduler.adb ================================================ -- Translated from newsched.pas on 28-Jun-2022 by (New) P2Ada v. 28-Oct-2009 separate (HAC_Sys.PCode.Interpreter.Tasking) procedure Scheduler (CD : Compiler_Data; ND : in out Interpreter_Data) is TCount : constant Natural := CD.Tasks_Definitions_Count; -- ======================================================================= -- Calc_Priority: Returns dynamic priority of task t. -- -- Dynamic priority is a function of: -- User specified task priority which can be dynamically set via -- SMALL_SP.PRIORITY. -- -- 9X Priority inheritance - if a task is inheriting priorities then -- its dynamic priority is the maximum of the dynamic priorities -- of ALL tasks enqueued to rendezvous with it. Inheritance is -- activated for a task by calling SMALL_SP.INHERITP(TRUE). -- Rendezvous status - if a task X is not inheriting priorities but -- is in rendezvous with another task Y then X's dynamic priority -- is the larger of X's priority and Y's dynamic priority. -- -- ======================================================================= -- Translated from interdef.pas on 28-Jun-2022 by (New) P2Ada v. 28-Oct-2009 -- function Calc_Priority (t : TRange) return Float is Result_Calc_Priority, p1, p2 : Float; et : Eptr; -- Convert integer user priority to real range [0.0, 1.0] function CVTR (upri : Integer) return Float is begin -- upri is in range [0, PriMax] return Float (upri) / Float (Defs.PriMax); end CVTR; -- Scheduling fairness adjustment to be added to static priority function Fairness (t : TRange) return Float is use Ada.Calendar; begin -- Adjustment is directly prop. to elapsed time since last run return Float (Clock - ND.TCB (t).LASTRUN) / 20000.0; -- 20000.0 for tuning end Fairness; begin if ND.TCB (t).Pcontrol.INHERIT then -- Consider ALL tasks waiting on task t p1 := CVTR (ND.TCB (t).Pcontrol.UPRI) + Fairness (t); for e in 1 .. CD.Entries_Count loop -- For each entry if ND.EList (e).Task_Index = t then -- If an entry queue for task t -- then check priority of every task on queue et := ND.EList (e).First; while et /= null loop -- Calc Priority, RECURSIVE p2 := Calc_Priority (et.all.Task_Index); if p2 > p1 then p1 := p2; -- Keep maximum priority end if; et := et.all.Next; -- Next task in queue end loop; end if; end loop; Result_Calc_Priority := p1; elsif ND.TCB (t).InRendzv /= NilTask then -- In Rendezvous with some task -- Compare task t pri. with task in rendezvous with, use max. p1 := CVTR (ND.TCB (t).Pcontrol.UPRI) + Fairness (t); -- task t p2 := Calc_Priority (ND.TCB (t).InRendzv); -- task t's caller Result_Calc_Priority := Float'Max (p1, p2); else -- Not inheriting and not in rendezvous, simplest case. Result_Calc_Priority := CVTR (ND.TCB (t).Pcontrol.UPRI) + Fairness (t); end if; return Result_Calc_Priority; end Calc_Priority; -- The George Washington University -- Department of Electrical Engineering and Computer Science -- Small Ada Schedulers -- Amr El-Kadi Fall 1990 procedure Scheduler_0 (NexTask : in out Integer; PS : in out Processor_State) is maxpriority, p : Float; nready : Integer; allcomplete : Boolean := True; -- check if all tasks are completed dummy : Boolean; begin for t in 0 .. TCount loop if ND.TCB (t).TS /= Completed then allcomplete := False; exit; end if; end loop; if allcomplete then PS := FIN; -- Stop the SmallAda processor else nready := 0; maxpriority := -1.0; for t in 0 .. TCount loop -- Of ready tasks, find one w/ max priority if ND.TCB (t).TS = Ready then p := Calc_Priority (t); if p > maxpriority then maxpriority := p; NexTask := t; end if; nready := nready + 1; end if; end loop; if nready = 0 then -- No ready tasks ; any delayed ? ; if yes then WAIT if Any_Task_Delayed (CD, ND) then -- Update SYSCLOCK and do loop again Wake_Tasks (CD, ND, dummy); -- wakes tasks PS := WAIT; -- there are delayed tasks, put processor -- in a wait state else -- no ready tasks, no delayed tasks, DEADLOCK PS := DEADLOCK; end if; else -- There was at least one ready task ; continue to process PS := Running; -- if (tcb [0].ts = completed) then -- begin -- PS := FIN ; -- for t := 1 to tcount do -- begin -- if ((tcb[t].ts = ready) and (not (tcb [t].term))) then -- begin -- PS := DEADLOCK ; {Check for deadlock} {Oguz Tumer} -- end ; -- end ; -- end ; end if; end if; end Scheduler_0; -- This Scheduler implements the Run Until Blocked strategy -- Amr El-Kadi Fall 1990 procedure Scheduler_1 (NextTask : in out Integer; PS : in out Processor_State) is nready : Integer; allcomplete, dummy : Boolean; begin if ND.TCB (NextTask).TS /= Ready then -- If the task was running, it becomes ready now if ND.TCB (NextTask).TS = Running then ND.TCB (NextTask).TS := Ready; end if; if Any_Task_Delayed (CD, ND) then -- Check if any is delayed Wake_Tasks (CD, ND, dummy); -- wakes tasks PS := WAIT; -- Processor's state is waiting end if; nready := 0; allcomplete := True; for t in 0 .. TCount loop -- Check if all have completed if ND.TCB (t).TS /= Completed then allcomplete := False; if ND.TCB (t).TS = Ready then nready := nready + 1; end if; -- Count ready tasks end if; end loop; if allcomplete then PS := FIN; -- Stop the Processor else if nready = 0 and PS /= WAIT then PS := DEADLOCK; -- No ready or delayed tasks else if nready /= 0 then -- There is at least one ready task PS := Running; -- Search Starting from the current for a ready task NextTask := NextTask + 1; if NextTask > TCount then NextTask := 0; end if; while ND.TCB (NextTask).TS /= Ready loop NextTask := NextTask + 1; if NextTask > TCount then NextTask := 0; end if; end loop; end if; end if; end if; else PS := Running; end if; end Scheduler_1; -- This Scheduler implements the Round Robin strategy (using time slices) -- Amr El-Kadi Fall 1990 procedure Scheduler_2 (NextTask : in out Integer; PS : in out Processor_State) is nready : Integer; allcomplete, dummy : Boolean; begin ND.TCB (NextTask).QUANTUM := ND.TCB (NextTask).QUANTUM - 1.0; -- decrement time given if ND.TCB (NextTask).QUANTUM < 0.0 or ND.TCB (NextTask).TS /= Ready then -- Time slice was exhausted -- If the task was running, it becomes ready now if ND.TCB (NextTask).TS = Running then ND.TCB (NextTask).TS := Ready; end if; if Any_Task_Delayed (CD, ND) then -- Check if any is delayed Wake_Tasks (CD, ND, dummy); -- wakes tasks PS := WAIT; -- Processor's state is waiting end if; nready := 0; allcomplete := True; for t in 0 .. TCount loop -- Check if all have completed if ND.TCB (t).TS /= Completed then allcomplete := False; if ND.TCB (t).TS = Ready then nready := nready + 1; end if; -- Count ready tasks end if; end loop; if allcomplete then PS := FIN; -- Stop the Processor else if nready = 0 and PS /= WAIT then PS := DEADLOCK; -- No ready or delayed tasks else if nready /= 0 then -- There is at least one ready task PS := Running; -- Search Starting from the current for a ready task NextTask := NextTask + 1; if NextTask > TCount then NextTask := 0; end if; while ND.TCB (NextTask).TS /= Ready loop NextTask := NextTask + 1; if NextTask > TCount then NextTask := 0; end if; end loop; ND.TCB (NextTask).QUANTUM := TSlice; -- give it a time slice end if; end if; end if; else PS := Running; end if; -- Time slice was not exhausted end Scheduler_2; -- This procedure searches the list of READY tasks and returns the -- index of the Ready Task with the highest priority -- Amr El-Kadi procedure highest (t : in out Integer) is begin t := 0; for i in 0 .. TCount loop if ND.TCB (i).TS = Ready and then ND.TCB (i).Pcontrol.UPRI > ND.TCB (t).Pcontrol.UPRI then t := i; end if; end loop; end highest; -- This Scheduler implements the Static Priority strategy (using lexical order) -- This does not use time slicing, but it is preemptive -- Amr El-Kadi Fall 1990 procedure Scheduler_3 (NextTask : in out Integer; PS : in out Processor_State) is nready : Integer; allcomplete : Boolean; dummy : Boolean; begin -- If the task was running, it becomes ready now if ND.TCB (NextTask).TS = Running then ND.TCB (NextTask).TS := Ready; end if; if Any_Task_Delayed (CD, ND) then -- Check if any is delayed Wake_Tasks (CD, ND, dummy); -- wakes tasks PS := WAIT; -- Processor's state is waiting end if; nready := 0; allcomplete := True; for t in 0 .. TCount loop -- Check if all have completed if ND.TCB (t).TS /= Completed then allcomplete := False; if ND.TCB (t).TS = Ready then nready := nready + 1; end if; -- Count ready tasks end if; end loop; if allcomplete then PS := FIN; -- Stop the Processor else if nready = 0 and PS /= WAIT then PS := DEADLOCK; -- No ready or delayed tasks else if nready /= 0 then -- There is at least one ready task PS := Running; -- Search for the highest priority task highest (NextTask); end if; end if; end if; end Scheduler_3; -- This Scheduler implements the Static Priority strategy (using lexical order) -- This does use time slicing, and it is not preemptive -- Amr El-Kadi Fall 1990 procedure Scheduler_4 (NextTask : in out Integer; PS : in out Processor_State) is nready : Integer; allcomplete, dummy : Boolean; begin ND.TCB (NextTask).QUANTUM := ND.TCB (NextTask).QUANTUM - 1.0; -- decrement time given if ND.TCB (NextTask).QUANTUM < 0.0 or ND.TCB (NextTask).TS /= Ready then -- Time slice was exhausted -- If the task was running, it becomes ready now if ND.TCB (NextTask).TS = Running then ND.TCB (NextTask).TS := Ready; end if; if Any_Task_Delayed (CD, ND) then -- Check if any is delayed Wake_Tasks (CD, ND, dummy); -- wakes tasks PS := WAIT; -- Processor's state is waiting end if; nready := 0; allcomplete := True; for t in 0 .. TCount loop -- Check if all have completed if ND.TCB (t).TS /= Completed then allcomplete := False; if ND.TCB (t).TS = Ready then nready := nready + 1; end if; -- Count ready tasks end if; end loop; if allcomplete then PS := FIN; -- Stop the Processor else if nready = 0 and PS /= WAIT then PS := DEADLOCK; -- No ready or delayed tasks else if nready /= 0 then -- There is at least one ready task PS := Running; -- Search for the highest priority task highest (NextTask); ND.TCB (NextTask).QUANTUM := TSlice; -- give it a time slice end if; end if; end if; else PS := Running; end if; -- Time slice was not exhausted end Scheduler_4; -- This Scheduler implements the Static Priority strategy (using lexical order) -- This does use time slicing, and it is preemptive -- Amr El-Kadi Fall 1990 procedure Scheduler_5 (NextTask : in out Integer; PS : in out Processor_State) is tt, nready : Integer; allcomplete, dummy : Boolean; begin ND.TCB (NextTask).QUANTUM := ND.TCB (NextTask).QUANTUM - 1.0; -- decrement time given -- If the task was running, it becomes ready now if ND.TCB (NextTask).TS = Running then ND.TCB (NextTask).TS := Ready; end if; if Any_Task_Delayed (CD, ND) then -- Check if any is delayed Wake_Tasks (CD, ND, dummy); -- wakes tasks PS := WAIT; -- Processor's state is waiting end if; nready := 0; allcomplete := True; for t in 0 .. TCount loop -- Check if all have completed if ND.TCB (t).TS /= Completed then allcomplete := False; if ND.TCB (t).TS = Ready then nready := nready + 1; end if; -- Count ready tasks end if; end loop; if allcomplete then PS := FIN; -- Stop the Processor else if nready = 0 and PS /= WAIT then PS := DEADLOCK; -- No ready or delayed tasks else if nready /= 0 then -- There is at least one ready task PS := Running; if ND.TCB (NextTask).QUANTUM < 0.0 or ND.TCB (NextTask).TS /= Ready then -- Time slice was exhausted -- Search for the highest priority task highest (NextTask); ND.TCB (NextTask).QUANTUM := TSlice; -- give it a time slice else tt := NextTask; -- Search for the highest priority task highest (tt); if tt /= NextTask then -- one with higher priority was found ND.TCB (NextTask).QUANTUM := 0.0; -- reset the time slice for the old one NextTask := tt; ND.TCB (NextTask).QUANTUM := TSlice; -- give it a time slice end if; end if; end if; end if; end if; end Scheduler_5; -- This Scheduler implements the Static Priority strategy (using lexical order) -- This does not use time slicing, and it is not preemptive -- Amr El-Kadi Fall 1990 procedure Scheduler_6 (NextTask : in out Integer; PS : in out Processor_State) is nready : Integer; allcomplete, dummy : Boolean; begin ND.TCB (NextTask).QUANTUM := ND.TCB (NextTask).QUANTUM - 1.0; -- decrement time given if ND.TCB (NextTask).TS /= Ready then -- If the task was running, it becomes ready now if ND.TCB (NextTask).TS = Running then ND.TCB (NextTask).TS := Ready; end if; if Any_Task_Delayed (CD, ND) then -- Check if any is delayed Wake_Tasks (CD, ND, dummy); -- wakes tasks PS := WAIT; -- Processor's state is waiting end if; nready := 0; allcomplete := True; for t in 0 .. TCount loop -- Check if all have completed if ND.TCB (t).TS /= Completed then allcomplete := False; if ND.TCB (t).TS = Ready then nready := nready + 1; end if; -- Count ready tasks end if; end loop; if allcomplete then PS := FIN; -- Stop the Processor else if nready = 0 and PS /= WAIT then PS := DEADLOCK; -- No ready or delayed tasks else if nready /= 0 then -- There is at least one ready task PS := Running; -- Search for the highest priority task highest (NextTask); end if; end if; end if; else PS := Running; -- Task did not block yet end if; end Scheduler_6; begin case ND.Scheduler is when 0 => Scheduler_0 (ND.CurTask, ND.PS); when 1 => Scheduler_1 (ND.CurTask, ND.PS); when 2 => Scheduler_2 (ND.CurTask, ND.PS); when 3 => Scheduler_3 (ND.CurTask, ND.PS); when 4 => Scheduler_4 (ND.CurTask, ND.PS); when 5 => Scheduler_5 (ND.CurTask, ND.PS); when 6 => Scheduler_6 (ND.CurTask, ND.PS); when Single_Task => null; end case; end Scheduler; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-tasking.adb ================================================ with Ada.Calendar; with Ada.Numerics.Float_Random; package body HAC_Sys.PCode.Interpreter.Tasking is function Any_Task_Delayed (CD : Compiler_Data; ND : Interpreter_Data) return Boolean is task_delayed : Boolean := False; begin for t in TRange'First .. CD.Tasks_Definitions_Count loop task_delayed := ND.TCB (t).TS = Delayed or ND.TCB (t).TS = TimedRendz or ND.TCB (t).TS = TimedWait; exit when task_delayed; end loop; return task_delayed; end Any_Task_Delayed; function EIndex (CD : Compiler_Data; Entry_Index : Integer) return Integer is i, e : Integer; begin e := -1; i := 1; while i <= CD.Entries_Count and e = -1 loop if Entry_Index = CD.Entries_Table (i) then e := i; end if; i := i + 1; end loop; return e; end EIndex; function First_Caller (CD : Compiler_Data; ND : in out Interpreter_Data; Entry_Index : Integer) return Integer is ix, val : Integer; begin ix := EIndex (CD, Entry_Index); if ND.EList (ix).First = null then val := -1; else val := ND.EList (ix).First.Task_Index; end if; return val; end First_Caller; procedure Queue ( CD : Compiler_Data; ND : in out Interpreter_Data; Entry_Index : Integer; Calling_Task : TRange ) is ix : constant Integer := EIndex (CD, Entry_Index); enode_var : constant Eptr := new Enode'(Task_Index => Calling_Task, Next => null); E_Q_Header : EHeader renames ND.EList (ix); begin -- Queue an entry call by Calling_Task for entry 'Entry'. if E_Q_Header.First = null then E_Q_Header.First := enode_var; else E_Q_Header.Last.Next := enode_var; end if; E_Q_Header.Last := enode_var; end Queue; procedure Do_Tasking_Operation (CD : Compiler_Data; ND : in out Interpreter_Data) is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); IR : Order renames ND.IR; procedure Do_Accept_Rendezvous is -- Hathorn, Cramer H1, H2, H3 : Integer; begin H1 := Integer (IR.Y); -- entry pointer H2 := First_Caller (CD, ND, H1); -- first waiting task H3 := Integer (CD.id_table (H1).lev); -- level of accepting entry if H2 >= 0 then -- start rendzv if call is waiting Curr_TCB.DISPLAY (Defs.Nesting_Level (H3 + 1)) := ND.TCB (H2).B; -- address callers -- parms Curr_TCB.InRendzv := H2; -- indicate that task is in Rendzv if ND.TCB (H2).TS = TimedRendz then ND.TCB (H2).TS := WaitRendzv; end if; else -- or put self to sleep Curr_TCB.SUSPEND := H1; Curr_TCB.TS := WaitRendzv; -- status is waiting for -- rendezvous Curr_TCB.PC := Curr_TCB.PC - 1; -- do this -- step again when awakened end if; ND.SWITCH := True; end Do_Accept_Rendezvous; procedure Do_End_Rendezvous is -- Hathorn function Remove_First (Entry_Index : Integer) return TRange is ix, val : Integer; dmy : Eptr; begin ix := EIndex (CD, Entry_Index); declare E_Q_Header : EHeader renames ND.EList (ix); begin val := E_Q_Header.First.Task_Index; if E_Q_Header.First = E_Q_Header.Last then E_Q_Header.First := null; E_Q_Header.Last := null; else dmy := E_Q_Header.First; E_Q_Header.First := E_Q_Header.First.Next; Dispose (dmy); end if; end; return val; end Remove_First; -- H1, H2 : Integer; begin Curr_TCB.InRendzv := NilTask; -- indicate rendezvous has ended H1 := Integer (ND.IR.Y); -- entry pointer H2 := Remove_First (H1); -- waiting task pointer if H2 >= 0 then -- wake up waiting task ND.TCB (H2).SUSPEND := 0; ND.TCB (H2).TS := Ready; ND.SWITCH := True; end if; end Do_End_Rendezvous; procedure Do_Selective_Wait is use type Defs.HAC_Float, Defs.Nesting_Level, Ada.Calendar.Time; H1, H2, H3 : Integer; begin case IR.X is when 1 => -- Start Selective Wait seq. Curr_TCB.R1.I := 0; -- next instruction if delay expires Curr_TCB.R2 := GR_Real (-1.0); -- delay time when 2 => -- Retain entry ID Curr_TCB.R3.I := IR.Y; when 3 => -- Accept if its still on queue H1 := Integer (Curr_TCB.R3.I); H2 := First_Caller (CD, ND, H1); -- first waiting task H3 := Integer (CD.id_table (H1).lev); -- level of accepting entry if H2 >= 0 then Curr_TCB.DISPLAY (Defs.Nesting_Level (H3 + 1)) := ND.TCB (H2).B; -- address callers parms Curr_TCB.InRendzv := H2; -- indicate task InRendz if ND.TCB (H2).TS = TimedRendz then -- turn off entry timeout ND.TCB (H2).TS := WaitRendzv; -- if it was on end if; else Curr_TCB.PC := Defs.Index (IR.Y); -- Jump to patched in address end if; ND.SWITCH := True; when 4 => -- Update minimum delay time if ND.S (Curr_TCB.T).R > 0.0 then if Curr_TCB.R2.R = -1.0 then Curr_TCB.R2.R := ND.S (Curr_TCB.T).R; Curr_TCB.R1.I := IR.Y; -- ins after JMP else if ND.S (Curr_TCB.T).R < Curr_TCB.R2.R then Curr_TCB.R2.R := ND.S (Curr_TCB.T).R; Curr_TCB.R1.I := IR.Y; -- ins after JMP end if; end if; end if; Pop (ND); when 5 | 6 => -- end of SELECT if Curr_TCB.R2.R > 0.0 then -- Timed Wait Curr_TCB.TS := TimedWait; ND.SYSCLOCK := Ada.Calendar.Clock; Curr_TCB.WAKETIME := ND.SYSCLOCK + Duration (Curr_TCB.R2.R); Curr_TCB.PC := Defs.Index (IR.Y); -- Do SELECT again when awakened by caller ND.SWITCH := True; -- give up control end if; -- AVL -- TERMINATE -- IS THE PARENT TASK COMPLETED? if ND.TCB (0).TS = Completed and then ND.CurTask /= 0 and then IR.X /= 6 then ND.Nb_Callers := 0; -- LET'S SEE IF THERE ARE CALLERS for ITERM in 1 .. CD.Entries_Count loop if ND.EList (ITERM).First /= null then ND.Nb_Callers := ND.Nb_Callers + 1; end if; end loop; -- YES, NO CALLERS if ND.Nb_Callers = 0 then -- YES, NO CALLERS -- ARE THE SIBLING TASKS EITHER COMPLETED OR -- IN THE SAME STATE AS CURTASK? ND.Nb_Complete := 0; for ITERM in 1 .. CD.Tasks_Definitions_Count loop if ND.TCB (ITERM).TS = Completed then ND.Nb_Complete := ND.Nb_Complete + 1; else if ND.TCB (ITERM).TS = Curr_TCB.TS then ND.Nb_Complete := ND.Nb_Complete + 1; else if ND.TCB (ITERM).TS = Ready and then Curr_TCB.TS = Running then ND.Nb_Complete := ND.Nb_Complete + 1; end if; end if; end if; end loop; if CD.Tasks_Definitions_Count = ND.Nb_Complete then -- YES, THEN ALL TASKS ARE NOW TERMINATING for ITERM in 1 .. CD.Tasks_Definitions_Count loop ND.TCB (ITERM).TS := Terminated; end loop; ND.PS := FIN; end if; end if; end if; -- if ir.x = 6 then -- begin -- term := false ; {Task doesn't have a terminate} -- end ; {alternative} -- when others => null; -- [P2Ada]: no otherwise / else in Pascal end case; end Do_Selective_Wait; procedure Do_Signal_Semaphore is H1 : constant Integer := Integer (ND.S (Curr_TCB.T).I); H2, H3 : Integer; use Ada.Numerics.Float_Random; use type Defs.HAC_Integer; begin Pop (ND); H2 := CD.Tasks_Definitions_Count + 1; H3 := Integer (Random (ND.Gen) * Float (H2)); while H2 >= 0 and then ND.TCB (H3).TS /= WaitSem and then ND.TCB (H3).SUSPEND /= H1 loop H3 := (H3 + 1) mod (Defs.TaskMax + 1); H2 := H2 - 1; end loop; if H2 < 0 or else ND.S (H1).I < 0 then ND.S (H1).I := ND.S (H1).I + 1; else ND.TCB (H3).SUSPEND := 0; ND.TCB (H3).TS := Ready; end if; Curr_TCB.TS := Ready; -- end critical section ND.SWITCH := True; end Do_Signal_Semaphore; procedure Do_Wait_Semaphore is H1 : constant Integer := Integer (ND.S (Curr_TCB.T).I); use type Defs.HAC_Integer; begin Pop (ND); if ND.S (H1).I > 0 then ND.S (H1).I := ND.S (H1).I - 1; Curr_TCB.TS := Critical; -- In a critical section, task gets -- exclusive access to the virtual else -- processor until section ends. Curr_TCB.SUSPEND := H1; Curr_TCB.TS := WaitSem; ND.SWITCH := True; end if; end Do_Wait_Semaphore; procedure Do_Set_Quantum_Task is use type Defs.HAC_Float; begin -- Cramer if ND.S (Curr_TCB.T).R <= 0.0 then ND.S (Curr_TCB.T).R := Defs.HAC_Float (TSlice); end if; Curr_TCB.QUANTUM := Duration (ND.S (Curr_TCB.T).R); Pop (ND); end Do_Set_Quantum_Task; procedure Do_Set_Task_Priority is use type Defs.HAC_Integer; begin -- Cramer if ND.S (Curr_TCB.T).I > Defs.PriMax then ND.S (Curr_TCB.T).I := Defs.PriMax; end if; if ND.S (Curr_TCB.T).I < 0 then ND.S (Curr_TCB.T).I := 0; end if; Curr_TCB.Pcontrol.UPRI := Integer (ND.S (Curr_TCB.T).I); Pop (ND); end Do_Set_Task_Priority; procedure Do_Set_Task_Priority_Inheritance is use type Defs.HAC_Integer; begin -- Cramer Curr_TCB.Pcontrol.INHERIT := ND.S (Curr_TCB.T).I /= 0; -- Set priority inherit indicator Pop (ND); end Do_Set_Task_Priority_Inheritance; procedure Do_Delay is use type Ada.Calendar.Time; begin if ND.S (Curr_TCB.T).Dur > 0.0 then if ND.Scheduler = Single_Task then ND.Single_Task_Delay_Pending := True; end if; Curr_TCB.TS := Delayed; -- set task state to delayed ND.SYSCLOCK := Ada.Calendar.Clock; -- update System Clock Curr_TCB.WAKETIME := ND.SYSCLOCK + ND.S (Curr_TCB.T).Dur; -- set wakeup time ND.SWITCH := True; -- give up control end if; Pop (ND); end Do_Delay; procedure Do_Halt_Interpreter is begin if ND.TActive = 0 then ND.PS := FIN; -- OK even when PS = Exception_Raised. -- At this point the exception is clearly unhandled. else ND.TCB (0).TS := Completed; ND.SWITCH := True; Curr_TCB.PC := Curr_TCB.PC - 1; end if; end Do_Halt_Interpreter; begin case Tasking_Opcode (ND.IR.F) is when k_Accept_Rendezvous => Do_Accept_Rendezvous; when k_End_Rendezvous => Do_End_Rendezvous; when k_Wait_Semaphore => Do_Wait_Semaphore; when k_Signal_Semaphore => Do_Signal_Semaphore; when k_Set_Quantum_Task => Do_Set_Quantum_Task; when k_Set_Task_Priority => Do_Set_Task_Priority; when k_Set_Task_Priority_Inheritance => Do_Set_Task_Priority_Inheritance; when k_Selective_Wait => Do_Selective_Wait; when k_Delay => Do_Delay; when k_Halt_Interpreter => Do_Halt_Interpreter; end case; end Do_Tasking_Operation; procedure Init_main_task (CD : Compiler_Data; ND : in out Interpreter_Data) is use Ada.Numerics.Float_Random; use type Defs.HAC_Integer; begin Reset (ND.Gen); -- initialize pseudo-random number generator -- After compiled, just begin exec -- Initialize run-time stack ND.S (1).I := 0; ND.S (2).I := 0; ND.S (3).I := -1; ND.S (4).I := Defs.HAC_Integer (CD.main_proc_id_index); declare Main_TCB : Task_Control_Block renames ND.TCB (0); begin Main_TCB.PC := Defs.Index (CD.id_table (CD.main_proc_id_index).adr_or_sz); -- first pcode instruction Main_TCB.T := CD.Blocks_Table (CD.id_table (CD.main_proc_id_index).block_or_pkg_ref).VSize - 1; Main_TCB.B := 0; Main_TCB.TS := Ready; Main_TCB.InRendzv := NilTask; Main_TCB.DISPLAY (0) := 0; -- Added for modularity (library-level calls), in 2021 Main_TCB.DISPLAY (1) := 0; -- In Pascal-S. Main_TCB.STACKSIZE := Defs.StMax - (CD.Tasks_Definitions_Count * Defs.STKINCR); Main_TCB.SUSPEND := 0; Main_TCB.QUANTUM := TSlice; Main_TCB.Pcontrol.UPRI := 0; Main_TCB.Pcontrol.INHERIT := False; Main_TCB.LASTRUN := ND.Start_Time; Main_TCB.Exception_Info.Currently_Raised := (No_Exception, 0); Main_TCB.WAKETIME := ND.Start_Time; -- Added 2020-06-23 for Single_Task end; end Init_main_task; procedure Init_other_tasks (CD : Compiler_Data; ND : in out Interpreter_Data) is H1 : Integer; use type Defs.HAC_Integer; begin for Task_To_Init in 1 .. CD.Tasks_Definitions_Count loop declare Curr_TCB : Task_Control_Block renames ND.TCB (Task_To_Init); begin H1 := CD.Tasks_Definitions_Table (Task_To_Init); Curr_TCB.PC := Defs.Index (CD.id_table (H1).adr_or_sz); Curr_TCB.B := ND.TCB (Task_To_Init - 1).STACKSIZE + 1; Curr_TCB.T := Curr_TCB.B + CD.Blocks_Table (CD.id_table (H1).block_or_pkg_ref).VSize - 1; ND.S (Curr_TCB.B + 1).I := 0; ND.S (Curr_TCB.B + 2).I := 0; ND.S (Curr_TCB.B + 3).I := -1; ND.S (Curr_TCB.B + 4).I := Defs.HAC_Integer (H1); Curr_TCB.DISPLAY (1) := 0; Curr_TCB.DISPLAY (2) := Curr_TCB.B; Curr_TCB.STACKSIZE := Curr_TCB.B + Defs.STKINCR - 1; Curr_TCB.SUSPEND := 0; Curr_TCB.TS := Ready; Curr_TCB.InRendzv := NilTask; Curr_TCB.QUANTUM := TSlice; Curr_TCB.Pcontrol.UPRI := 0; Curr_TCB.Pcontrol.INHERIT := False; Curr_TCB.LASTRUN := ND.Start_Time; Curr_TCB.Exception_Info.Currently_Raised := (No_Exception, 0); end; end loop; -- Initially no queued entry calls for E_Idx in 1 .. CD.Entries_Count loop ND.EList (E_Idx).Task_Index := TRange (CD.id_table (CD.Entries_Table (E_Idx)).adr_or_sz); -- Task index ND.EList (E_Idx).First := null; ND.EList (E_Idx).Last := null; end loop; ND.TActive := CD.Tasks_Definitions_Count; -- All tasks are active initially ND.Scheduler := (if ND.TActive = 0 then Single_Task else 1); ND.CurTask := 0; -- IT WAS -1 ? ND.SWITCH := True; ND.TIMER := ND.Start_Time; -- was 0.0 ND.PS := Running; end Init_other_tasks; procedure ShowQ ( CD : Compiler_Data; ND : in out Interpreter_Data; Entry_Index : Integer ) is ix : constant Integer := EIndex (CD, Entry_Index); p : Eptr := ND.EList (ix).First; use Defs, Ada.Text_IO; begin Put ("Dumping q for entry " & A2S (CD.id_table (Entry_Index).name) & " entry index="); IIO.Put (HAC_Integer (ix)); New_Line; if p = null then Put ("*** EMPTY ***"); New_Line; else loop Put ("Task "); Put (A2S (CD.id_table (CD.Tasks_Definitions_Table (p.Task_Index)).name)); New_Line; p := p.Next; exit when p = null; end loop; end if; end ShowQ; procedure Wake_Tasks ( CD : Compiler_Data; ND : in out Interpreter_Data; Result : out Boolean ) is procedure Purge (Entry_Index : Integer; t : TRange) is p, q : Eptr; -- has timed out, the entry ix : Integer; -- is purged from the q. begin ix := EIndex (CD, Entry_Index); q := null; p := ND.EList (ix).First; while p /= null loop if p.Task_Index = t then if ND.EList (ix).First = ND. EList (ix).Last then ND.EList (ix).First := null; ND.EList (ix).Last := null; else if p = ND.EList (ix).First then ND.EList (ix).First := p.Next; else if p = ND.EList (ix).Last then ND.EList (ix).Last := q; q.Next := null; else q.Next := p.Next; end if; end if; end if; Dispose (p); p := null; -- to exit loop else -- try next entry in list q := p; p := p.Next; end if; end loop; end Purge; -- count : Integer := 0; use type Ada.Calendar.Time; begin for t in 0 .. CD.Tasks_Definitions_Count loop if (ND.TCB (t).TS = Delayed or else ND.TCB (t).TS = TimedRendz or else ND.TCB (t).TS = TimedWait) and then ND.SYSCLOCK >= ND.TCB (t).WAKETIME then if ND.TCB (t).TS = TimedRendz then ND.TCB (t).R1.I := 0; -- timeout on rendezvous Purge (Integer (ND.TCB (t).R2.I), t); -- remove from callee's q end if; if ND.TCB (t).TS = TimedWait then ND.TCB (t).PC := Defs.Index (ND.TCB (t).R1.I); -- t.out on accept end if; ND.TCB (t).TS := Ready; count := count + 1; end if; end loop; Result := count > 0; end Wake_Tasks; procedure ShowTime is null; procedure SnapShot is null; procedure Scheduler (CD : Compiler_Data; ND : in out Interpreter_Data) is separate; procedure Manage_Scheduling (CD : Compiler_Data; ND : in out Interpreter_Data) is were_tasks_awakened : Boolean; use Ada.Calendar; begin ND.SYSCLOCK := Clock; if ND.Snap then ShowTime; end if; if ND.TCB (ND.CurTask).TS = Critical then -- SmallAda inter.pas line 456 if ND.Snap then SnapShot; end if; else Wake_Tasks (CD, ND, were_tasks_awakened); if ND.SWITCH or else -- ------------> Voluntary release of control ND.SYSCLOCK >= ND.TIMER or else -- ---> Time slice exceeded were_tasks_awakened -- ------> Awakened task causes switch then if ND.CurTask >= 0 then ND.TCB (ND.CurTask).LASTRUN := ND.SYSCLOCK; if ND.TCB (ND.CurTask).TS = Running then ND.TCB (ND.CurTask).TS := Ready; -- SWITCH PROCCESS end if; end if; loop -- Call Main Scheduler (SmallAda inter.pas line 479): Scheduler (CD, ND); ND.SYSCLOCK := Clock; if ND.Snap then ShowTime; end if; if ND.Snap then SnapShot; end if; exit when ND.PS /= WAIT; end loop; -- if ND.PS = DEADLOCK or ND.PS = FIN then return; end if; -- ND.TIMER := ND.SYSCLOCK + ND.TCB (ND.CurTask).QUANTUM; ND.TCB (ND.CurTask).TS := Running; ND.SWITCH := False; if ND.Snap then SnapShot; end if; end if; end if; end Manage_Scheduling; end HAC_Sys.PCode.Interpreter.Tasking; ================================================ FILE: src/execute/hac_sys-pcode-interpreter-tasking.ads ================================================ with HAC_Sys.Co_Defs, HAC_Sys.PCode.Interpreter.In_Defs; private package HAC_Sys.PCode.Interpreter.Tasking is use Co_Defs, In_Defs; ----------------------- -- VM Instructions -- ----------------------- -- Execute tasking instruction stored as Opcode in ND.IR.F. -- ND.IR.F is in the Tasking_Opcode subtype range. procedure Do_Tasking_Operation (CD : Compiler_Data; ND : in out Interpreter_Data); ------------- -- Misc. -- ------------- function Any_Task_Delayed (CD : Compiler_Data; ND : Interpreter_Data) return Boolean; function EIndex (CD : Compiler_Data; Entry_Index : Integer) return Integer; procedure Init_main_task (CD : Compiler_Data; ND : in out Interpreter_Data); procedure Init_other_tasks (CD : Compiler_Data; ND : in out Interpreter_Data); procedure Queue ( CD : Compiler_Data; ND : in out Interpreter_Data; Entry_Index : Integer; Calling_Task : TRange ); procedure ShowQ ( CD : Compiler_Data; ND : in out Interpreter_Data; Entry_Index : Integer ); procedure Wake_Tasks ( CD : Compiler_Data; ND : in out Interpreter_Data; Result : out Boolean ); -- Default Task time-slice in seconds -- Feldman: 60ths of a sec on Mac TSlice : constant Duration := 0.016666666; procedure Manage_Scheduling (CD : Compiler_Data; ND : in out Interpreter_Data); end HAC_Sys.PCode.Interpreter.Tasking; ================================================ FILE: src/execute/hac_sys-pcode-interpreter.adb ================================================ with HAC_Sys.Co_Defs, HAC_Sys.Interfacing, HAC_Sys.PCode.Interpreter.Calls, HAC_Sys.PCode.Interpreter.Composite_Data, HAC_Sys.PCode.Interpreter.Exceptions, HAC_Sys.PCode.Interpreter.In_Defs, HAC_Sys.PCode.Interpreter.Multi_Statement, HAC_Sys.PCode.Interpreter.Operators, HAC_Sys.PCode.Interpreter.Tasking; with HAT; with Ada.Characters.Handling, Ada.Command_Line, Ada.Exceptions, Ada.IO_Exceptions; package body HAC_Sys.PCode.Interpreter is procedure Interpret ( BD : in out Builder.Build_Data; -- Everything is compiled and ready to run Post_Mortem : out Post_Mortem_Data ) is ND : In_Defs.Interpreter_Data; CD : Co_Defs.Compiler_Data renames BD.CD.all; use Co_Defs, Defs, In_Defs, Exceptions; procedure Pop (Amount : Positive := 1) is begin Pop (ND, Amount); end Pop; procedure Push (Amount : Positive := 1) is begin Push (ND, Amount); end Push; procedure Start_Interpreter is begin ND.S := new Stack_Type; ND.PS := Running; ND.Start_Time := Ada.Calendar.Clock; ND.Snap := False; ND.SWITCH := False; -- invoke scheduler on next cycle flag ND.SYSCLOCK := ND.Start_Time; ND.TIMER := ND.SYSCLOCK; -- set to end of current task's time slice ND.feedback_tick := 1; Tasking.Init_main_task (BD.CD.all, ND); Tasking.Init_other_tasks (BD.CD.all, ND); Post_Mortem.Max_Stack_Usage := 0; end Start_Interpreter; procedure Do_HAT_Function is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); Top_Item : General_Register renames ND.S (Curr_TCB.T); Code : constant SF_Code := SF_Code'Val (ND.IR.Y); use type Operand_1_Type; begin case Code is when SF_File_or_Console_Information => if ND.IR.X = 0 then -- Niladic File info function -> abstract console Push; case SF_File_or_Console_Information (Code) is when SF_EOF => ND.S (Curr_TCB.T).I := Boolean'Pos (Console.End_Of_File); when SF_EOLN => ND.S (Curr_TCB.T).I := Boolean'Pos (Console.End_Of_Line); end case; else case SF_File_or_Console_Information (Code) is when SF_EOF => ND.S (Curr_TCB.T).I := Boolean'Pos (HAT.End_Of_File (ND.S (Curr_TCB.T).Txt.all)); when SF_EOLN => ND.S (Curr_TCB.T).I := Boolean'Pos (HAT.End_Of_Line (ND.S (Curr_TCB.T).Txt.all)); end case; end if; when SF_Argument => -- The stack top item may change its type here. declare arg_i : constant Integer := Integer (Top_Item.I); begin if arg_i not in 1 .. System_Calls.Argument_Count then Raise_Standard (ND, VME_Constraint_Error, "Argument number not in 1 .. Argument_Count", True); end if; Top_Item := GR_VString (System_Calls.Argument (arg_i)); end; when SF_Argument_Count => Push; -- Niladic function, needs to push a new item (their own result). ND.S (Curr_TCB.T).I := HAC_Integer (System_Calls.Argument_Count); when SF_Command_Name => Push; -- Niladic function, needs to push a new item (their own result). ND.S (Curr_TCB.T) := GR_VString (System_Calls.Command_Name); when SF_Directory_Separator => Push; -- Niladic function, needs to push a new item (their own result). ND.S (Curr_TCB.T).I := Character'Pos (System_Calls.Directory_Separator); when SF_Current_Directory => Push; -- Niladic function, needs to push a new item (their own result). ND.S (Curr_TCB.T) := GR_VString (HAT.Current_Directory); when SF_Get_Needs_Skip_Line => Push; -- Niladic function, needs to push a new item (their own result). ND.S (Curr_TCB.T).I := Boolean'Pos (Console.Get_Needs_Skip_Line); when others => Operators.Do_SF_Operator (BD, ND); -- Doesn't need generic stuff. end case; end Do_HAT_Function; procedure Do_Text_Read (Code : SP_Code) is CH : Character; Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); Out_Param : constant Index := Index (ND.S (Curr_TCB.T).I); Typ : Typen; Immediate : constant Boolean := Code = SP_Get_Immediate; FP : File_Ptr; String_Length_Decoding : Operand_2_Type; use type Operand_2_Type; begin Typ := Typen'Val (ND.IR.Y mod (2 ** Typen'Size)); if Code in SP_Get .. SP_Get_Line then -- The End_Of_File_Console check is skipped here (disturbs GNAT's run-time). case Typ is when Ints => Console.Get (ND.S (Out_Param).I); when Floats => ND.S (Out_Param) := GR_Real (0.0); -- First, switch type to Floats. Console.Get (ND.S (Out_Param).R); when VStrings => ND.S (Out_Param) := GR_VString (Console.Get_Line); when Chars => if Immediate then Console.Get_Immediate (CH); else Console.Get (CH); end if; ND.S (Out_Param).I := Character'Pos (CH); when Arrays => -- We have a String, with a given length. String_Length_Decoding := ND.IR.Y / (2 ** Typen'Size); for i in 1 .. Index (String_Length_Decoding) loop Console.Get (CH); ND.S (Out_Param + i - 1).I := Character'Pos (CH); end loop; when others => null; end case; if Code = SP_Get_Line and Typ /= VStrings then Console.Skip_Line; end if; Pop; else FP := ND.S (Curr_TCB.T - 1).Txt; if Ada.Text_IO.End_Of_File (FP.all) then raise VM_End_Error; end if; case Typ is when Ints => Defs.IIO.Get (FP.all, ND.S (Out_Param).I); when Floats => declare the_value : Defs.HAC_Float; begin Defs.RIO.Get (FP.all, the_value); ND.S (Out_Param) := GR_Real (the_value); end; when Chars => Ada.Text_IO.Get (FP.all, CH); ND.S (Out_Param).I := Character'Pos (CH); when VStrings => ND.S (Out_Param) := GR_VString (Ada.Text_IO.Get_Line (FP.all)); when Arrays => -- We have a String, with a given length. String_Length_Decoding := ND.IR.Y / (2 ** Typen'Size); for i in 1 .. Index (String_Length_Decoding) loop -- A.10.7 (15): "Determines the length of the given string and -- attempts that number of Get operations for successive -- characters of the string (in particular, no operation -- is performed if the string is null)." if Ada.Text_IO.End_Of_File (FP.all) then raise VM_End_Error; end if; Ada.Text_IO.Get (FP.all, CH); ND.S (Out_Param + i - 1).I := Character'Pos (CH); end loop; when others => null; end case; if Code = SP_Get_Line_File and Typ /= VStrings then Ada.Text_IO.Skip_Line (FP.all); end if; Pop (2); end if; ND.SWITCH := True; -- give up control when doing I/O exception when E : Constraint_Error => Raise_Standard (ND, VME_Constraint_Error, Ada.Exceptions.Exception_Message (E), True); when E : Ada.IO_Exceptions.Data_Error => Raise_Standard (ND, VME_Data_Error, Ada.Exceptions.Exception_Message (E), True); end Do_Text_Read; procedure Do_Write_Formatted (Code : SP_Code) is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); FP : File_Ptr; item_typ : constant Typen := Typen'Val (ND.IR.Y); -- Parameters used: see default_extra_put_param in HAC.Parser.Standard_Procedures. all_params : Positive; pos : Positive := 1; len : Natural := 0; use Ada.Text_IO; begin case item_typ is when Ints => all_params := 3; when Floats => all_params := 4; when Bools => all_params := 2; when String_Literals => all_params := 2; -- Position and length pos := Integer (ND.S (Curr_TCB.T).I); len := Integer (ND.S (Curr_TCB.T - 1).I); when Arrays => all_params := 2; -- Address and size when others => all_params := 1; -- Chars, VStrings, ... end case; if Code in SP_Put .. SP_Put_Line then case item_typ is when Ints => Console.Put (I => ND.S (Curr_TCB.T - 2).I, Width => Field (ND.S (Curr_TCB.T - 1).I), Base => Number_Base (ND.S (Curr_TCB.T).I)); when Floats => Console.Put (F => ND.S (Curr_TCB.T - 3).R, Fore => Field (ND.S (Curr_TCB.T - 2).I), Aft => Field (ND.S (Curr_TCB.T - 1).I), Exp => Field (ND.S (Curr_TCB.T).I)); when Bools => Console.Put (B => Boolean'Val (ND.S (Curr_TCB.T - 1).I), Width => Field (ND.S (Curr_TCB.T).I)); -- !! But there is also a "Set" parameter. when Chars => Console.Put (Character'Val (ND.S (Curr_TCB.T).I)); when VStrings | Strings_as_VStrings => Console.Put (HAT.VStr_Pkg.To_String (ND.S (Curr_TCB.T).V)); when String_Literals => Console.Put (CD.Strings_Constants_Table (pos .. pos + len - 1)); when Arrays => Console.Put (Get_String_from_Stack (ND, Integer (ND.S (Curr_TCB.T - 1).I), Integer (ND.S (Curr_TCB.T).I))); when others => null; end case; if Code = SP_Put_Line then Console.New_Line; end if; else FP := ND.S (Curr_TCB.T - all_params).Txt; case item_typ is when Ints => IIO.Put (FP.all, Item => ND.S (Curr_TCB.T - 2).I, Width => Field (ND.S (Curr_TCB.T - 1).I), Base => Number_Base (ND.S (Curr_TCB.T).I)); when Floats => RIO.Put (FP.all, Item => ND.S (Curr_TCB.T - 3).R, Fore => Field (ND.S (Curr_TCB.T - 2).I), Aft => Field (ND.S (Curr_TCB.T - 1).I), Exp => Field (ND.S (Curr_TCB.T).I)); when Bools => BIO.Put (FP.all, Item => Boolean'Val (ND.S (Curr_TCB.T - 1).I), Width => Field (ND.S (Curr_TCB.T).I)); -- !! But there is also a "Set" parameter. when Chars => HAT.Put (FP.all, Character'Val (ND.S (Curr_TCB.T).I)); when VStrings | Strings_as_VStrings => HAT.Put (FP.all, HAT.VStr_Pkg.To_String (ND.S (Curr_TCB.T).V)); when String_Literals => HAT.Put (FP.all, CD.Strings_Constants_Table (pos .. pos + len - 1)); when Arrays => HAT.Put (FP.all, Get_String_from_Stack (ND, Integer (ND.S (Curr_TCB.T - 1).I), Integer (ND.S (Curr_TCB.T).I))); when others => null; end case; if Code = SP_Put_Line_File then Ada.Text_IO.New_Line (FP.all); end if; all_params := all_params + 1; -- Count the file parameter for popping. end if; Pop (all_params); ND.SWITCH := True; -- give up control when doing I/O end Do_Write_Formatted; procedure Do_Code_for_Automatic_Initialization is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); Var_Addr : constant Index := Index (ND.S (Curr_TCB.T).I); begin case Typen'Val (ND.IR.Y) is when VStrings => ND.S (Var_Addr) := GR_VString (HAT.Null_VString); when Text_Files => Allocate_Text_File (ND, ND.S (Var_Addr)); when others => null; end case; Pop; end Do_Code_for_Automatic_Initialization; procedure Do_HAT_Procedure is Code : constant SP_Code := SP_Code'Val (ND.IR.X); Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); Top_Item : General_Register renames ND.S (Curr_TCB.T); Below_Top_Item : General_Register renames ND.S (Curr_TCB.T - 1); use HAT.VStr_Pkg; use type Defs.HAC_Integer; Lines : Ada.Text_IO.Positive_Count; Shell_Exec_Result : Integer; -- -- !! Workaround for the non-initialization of files in records -- and arrays (bug #2). We can remove this late initialization -- when general implicit initialization (including for composite -- types: arrays, records) is implemented. -- When the memory cell already contains a Text_Files, -- if the previous owner forgot to close the file, we get -- a Status_Error instead of a Use_Error. -- procedure Switch_to_Text_Files (M : in out General_Register) is begin if M.Special /= Defs.Text_Files then Allocate_Text_File (ND, M); end if; end Switch_to_Text_Files; through : Integer; begin case Code is when SP_Copy_File => HAT.Copy_File (Below_Top_Item.V, Top_Item.V); when SP_Create_Directory => HAT.Create_Directory (Top_Item.V); when SP_Create_Path => HAT.Create_Path (Top_Item.V); when SP_Delete_Directory => HAT.Delete_Directory (Top_Item.V); when SP_Delete_File => HAT.Delete_File (Top_Item.V); when SP_Rename => HAT.Rename (Below_Top_Item.V, Top_Item.V); when SP_Set_Directory => HAT.Set_Directory (Top_Item.V); when SP_Set_Env => HAT.Set_Env (Below_Top_Item.V, Top_Item.V); when SP_Set_Exit_Status => HAT.Set_Exit_Status (Integer (Top_Item.I)); -- when SP_Set_VM_Variable => Interfacing.Set_VM_Variable (BD, To_String (Below_Top_Item.V), To_String (Top_Item.V)); when SP_Delete => through := Integer (Top_Item.I); if through > HAT.Length (ND.S (Defs.Index (ND.S (Curr_TCB.T - 2).I)).V) then Raise_Standard (ND, VME_Index_Error, "Delete: Through, " & through'Image & ", is larger than Length (Source)", True); end if; HAT.Delete (Source => ND.S (Defs.Index (ND.S (Curr_TCB.T - 2).I)).V, From => Integer (Below_Top_Item.I), Through => through); -- when SP_Create => Switch_to_Text_Files (ND.S (Defs.Index (Below_Top_Item.I))); HAT.Create (ND.S (Defs.Index (Below_Top_Item.I)).Txt.all, Top_Item.V); when SP_Open => Switch_to_Text_Files (ND.S (Defs.Index (Below_Top_Item.I))); HAT.Open (ND.S (Defs.Index (Below_Top_Item.I)).Txt.all, Top_Item.V); when SP_Append => Switch_to_Text_Files (ND.S (Defs.Index (Below_Top_Item.I))); HAT.Append (ND.S (Defs.Index (Below_Top_Item.I)).Txt.all, Top_Item.V); when SP_Close => Check_Discriminant_Type (ND.S (Defs.Index (Top_Item.I)), Defs.Text_Files); HAT.Close (ND.S (Defs.Index (Top_Item.I)).Txt.all); when SP_Push_Abstract_Console => Push; ND.S (Curr_TCB.T) := GR_Abstract_Console; when SP_Get | SP_Get_Immediate | SP_Get_Line | SP_Get_File | SP_Get_Line_File => Do_Text_Read (Code); when SP_Put .. SP_Put_Line_File => Do_Write_Formatted (Code); when SP_New_Line => Lines := Ada.Text_IO.Positive_Count (Top_Item.I); if Below_Top_Item.Txt = Abstract_Console then Console.New_Line (Lines); else HAT.New_Line (Below_Top_Item.Txt.all, Lines); end if; when SP_Skip_Line => Lines := Ada.Text_IO.Positive_Count (Top_Item.I); if Below_Top_Item.Txt = Abstract_Console then -- The End_Of_File_Console check is skipped here (disturbs GNAT's run-time). Console.Skip_Line (Lines); elsif HAT.End_Of_File (Below_Top_Item.Txt.all) then raise VM_End_Error; else HAT.Skip_Line (Below_Top_Item.Txt.all, Lines); end if; ND.feedback_tick := 0; -- Force feedback before next instruction. when SP_Shell_Execute_without_Result => declare Command : constant String := To_String (Top_Item.V); begin System_Calls.Shell_Execute (Command, Shell_Exec_Result); end; when SP_Shell_Execute_with_Result => declare Command : constant String := To_String (Below_Top_Item.V); Result_Address : constant Defs.Index := Defs.Index (Top_Item.I); begin System_Calls.Shell_Execute (Command, Shell_Exec_Result); ND.S (Result_Address).I := Defs.HAC_Integer (Shell_Exec_Result); end; when SP_Shell_Execute_Output => declare Command : constant String := To_String (Below_Top_Item.V); Output_Address : constant Defs.Index := Defs.Index (Top_Item.I); Shell_Exec_Output : HAT.VString; begin System_Calls.Shell_Execute_Output (Command, Shell_Exec_Result, Shell_Exec_Output); ND.S (Output_Address) := GR_VString (Shell_Exec_Output); end; when SP_Shell_Execute_Result_Output => declare Command : constant String := To_String (ND.S (Curr_TCB.T - 2).V); Result_Address : constant Defs.Index := Defs.Index (Below_Top_Item.I); Output_Address : constant Defs.Index := Defs.Index (Top_Item.I); Shell_Exec_Output : HAT.VString; begin System_Calls.Shell_Execute_Output (Command, Shell_Exec_Result, Shell_Exec_Output); ND.S (Result_Address).I := Defs.HAC_Integer (Shell_Exec_Result); ND.S (Output_Address) := GR_VString (Shell_Exec_Output); end; when SP_Randomize => HAT.Randomize; when SP_Random_Seed => HAT.Random_Seed (Integer (Top_Item.I mod (2 ** (Integer'Size - 1)))); when SP_Wait | SP_Signal | SP_Priority | SP_InheritP | SP_Quantum => null; end case; -- Release the stack: case Code is when SP_Close | SP_Delete_File | SP_Set_Directory | SP_Set_Exit_Status | SP_Shell_Execute_without_Result | SP_Random_Seed => Pop; when SP_Open | SP_Append | SP_Create | SP_Set_Env | SP_Copy_File | SP_Rename | SP_New_Line | SP_Skip_Line | SP_Shell_Execute_with_Result | SP_Shell_Execute_Output => Pop (2); when SP_Shell_Execute_Result_Output | SP_Delete => Pop (3); when others => null; end case; ND.SWITCH := True; -- give up control when doing I/O exception when Ada.Text_IO.Name_Error => case Code is when SP_Open | SP_Create | SP_Append => Raise_Standard (ND, VME_Name_Error, "File not found, or invalid name: " & To_String (Top_Item.V), True); when others => Raise_Standard (ND, VME_Name_Error, Stop_Current_Instruction => True); end case; when E : Ada.Text_IO.Mode_Error => Raise_Standard (ND, VME_Mode_Error, Ada.Exceptions.Exception_Message (E)); when E : Ada.Text_IO.Status_Error => case Code is when SP_Open | SP_Create | SP_Append => Raise_Standard (ND, VME_Status_Error, "File already open", True); when SP_Close => Raise_Standard (ND, VME_Status_Error, "File not open", True); when others => Raise_Standard (ND, VME_Status_Error, "File not open? [" & Ada.Exceptions.Exception_Message (E) & ']', True); end case; when Ada.Text_IO.Use_Error => case Code is when SP_Open | SP_Create | SP_Append => Raise_Standard (ND, VME_Use_Error, "Cannot access file: " & To_String (Top_Item.V), True); when others => Raise_Standard (ND, VME_Use_Error, Stop_Current_Instruction => True); end case; end Do_HAT_Procedure; procedure Add_Stack_Trace_Line (Offset : Natural) is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); D : Debug_Info renames CD.ObjCode (Curr_TCB.PC - Offset).D; use HAT.VStr_Pkg, Ada.Containers; -- Limit huge trace-backs (likely, recursive calls): max_trace_back_length : constant := 500; begin if D.Full_Block_Id /= Universe and then Curr_TCB.Exception_Info.ST_Message.Length < max_trace_back_length then Curr_TCB.Exception_Info.ST_Message.Append (D); end if; end Add_Stack_Trace_Line; procedure Fetch_Instruction with Inline is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); begin if ND.PS = Exception_Raised then -- "Raised" flag is up, we just skip everything -- except a final return and the start of the -- optional exception handler. -- !! To do: add an exception handler NOP instruction. -- !! To do: skip the intermediate return's, otherwise -- the exception handler won't be reached. while not OK_for_Exception (CD.ObjCode (Curr_TCB.PC).F) loop Curr_TCB.PC := Curr_TCB.PC + 1; end loop; end if; ND.IR := CD.ObjCode (Curr_TCB.PC); Curr_TCB.PC := Curr_TCB.PC + 1; end Fetch_Instruction; procedure Execute_Current_Instruction is Curr_TCB : Task_Control_Block renames ND.TCB (ND.CurTask); IR : Order renames ND.IR; use type HAC_Integer; -- procedure Do_Atomic_Data_Push_Operation with Inline is Base : constant Index := Curr_TCB.DISPLAY (Nesting_Level (IR.X)); Address_of_Variable : constant Index := Base + Index (IR.Y); begin Push; case Atomic_Data_Push_Opcode (ND.IR.F) is when k_Push_Address => -- Push "v'Access" of variable v ND.S (Curr_TCB.T).I := HAC_Integer (Address_of_Variable); when k_Push_Value => -- Push variable v's value. ND.S (Curr_TCB.T) := ND.S (Address_of_Variable); when k_Push_Discrete_Value => -- Push variable v's discrete value. ND.S (Curr_TCB.T).I := ND.S (Address_of_Variable).I; when k_Push_Indirect_Value => -- Push "v.all" (variable v contains an access). ND.S (Curr_TCB.T) := ND.S (Index (ND.S (Address_of_Variable).I)); when k_Push_Indirect_Discrete_Value => -- Discrete variant of k_Push_Indirect_Value. ND.S (Curr_TCB.T).I := ND.S (Index (ND.S (Address_of_Variable).I)).I; end case; end Do_Atomic_Data_Push_Operation; -- procedure Do_Literal_Push_Operation with Inline is begin Push; case Literal_Push_Opcode (ND.IR.F) is when k_Push_Discrete_Literal => -- Literal: discrete value (Integer, Character, Boolean, Enum) ND.S (Curr_TCB.T).I := IR.Y; when k_Push_Float_Literal => ND.S (Curr_TCB.T) := GR_Real (CD.Float_Constants_Table (Integer (IR.Y))); when k_Push_Float_First => ND.S (Curr_TCB.T) := GR_Real (HAC_Float'First); when k_Push_Float_Last => ND.S (Curr_TCB.T) := GR_Real (HAC_Float'Last); end case; end Do_Literal_Push_Operation; -- procedure Do_Swap is temp : constant General_Register := ND.S (Curr_TCB.T); begin ND.S (Curr_TCB.T) := ND.S (Curr_TCB.T - 1); ND.S (Curr_TCB.T - 1) := temp; end Do_Swap; -- procedure Check_Lower (bound : HAC_Integer; TYP : Typen; Ref : Index) is pragma Inline (Check_Lower); begin if ND.S (Curr_TCB.T).I < bound then raise VM_Out_of_Range with ": value " & Discrete_Image (CD, ND.S (Curr_TCB.T).I, TYP, Ref) & " is below destination (sub)type's lower bound, " & Discrete_Image (CD, bound, TYP, Ref); end if; end Check_Lower; -- procedure Check_Upper (bound : HAC_Integer; TYP : Typen; Ref : Index) is pragma Inline (Check_Upper); begin if ND.S (Curr_TCB.T).I > bound then raise VM_Out_of_Range with ": value " & Discrete_Image (CD, ND.S (Curr_TCB.T).I, TYP, Ref) & " is above destination (sub)type's upper bound, " & Discrete_Image (CD, bound, TYP, Ref); end if; end Check_Upper; -- procedure Do_Jump with Inline is begin if IR.Y < 0 then raise Abnormal_Termination with "Unpatched jump address"; end if; Curr_TCB.PC := Index (IR.Y); end Do_Jump; -- begin case ND.IR.F is when k_Store => -- [T-1].all := [T], then pop 2x. if Typ_with_Variant_Part (Typen'Val (IR.Y)) and then Typen'Val (IR.Y) /= ND.S (Curr_TCB.T).Special then raise VM_Invalid_Data; -- Source contains uninitialized data. end if; -- NB: we don't check the destination discriminant -- which may be wrong for the right reason, i.e. on first -- assignment to a variable, which has contained garbage -- before the assignment. ND.S (Index (ND.S (Curr_TCB.T - 1).I)) := ND.S (Curr_TCB.T); Pop (2); when k_Store_Discrete => -- [T-1].all := [T], then pop 2x. ND.S (Index (ND.S (Curr_TCB.T - 1).I)).I := ND.S (Curr_TCB.T).I; Pop (2); when k_Store_Discrete_Literal => -- [T].all := IR.Y, then pop. -- Equivalent to: Push_Discrete_Literal, then Store_Discrete. -- No validity check: the value is discrete. -- Range-checked at compile-time (in current version of HAC -- where all ranges & subtypes are static). -- Future versions: possible range checks would be between -- k_Push_Discrete_Literal and k_Store; then, no folding -- into k_Store_Discrete_Literal. ND.S (Index (ND.S (Curr_TCB.T).I)).I := IR.Y; Pop; when k_Store_Float_Literal => -- [T].all := float_table (IR.Y), then pop. ND.S (Index (ND.S (Curr_TCB.T).I)) := GR_Real (CD.Float_Constants_Table (Integer (IR.Y))); Pop; -- when Atomic_Data_Push_Opcode => Do_Atomic_Data_Push_Operation; when Literal_Push_Opcode => Do_Literal_Push_Operation; when Composite_Data_Opcode => Composite_Data.Do_Composite_Data_Operation (CD, ND); when Unary_Operator_Opcode => Operators.Do_Unary_Operator (ND); when Binary_Operator_Opcode => Operators.Do_Binary_Operator (ND); when Multiple_Operator_Opcode => Operators.Do_Multiple_Operator (ND); when Special_Operator_Opcode => Operators.Do_Special_Operator (ND); when Multi_Statement_Opcode => Multi_Statement.Do_Multi_Statement_Operation (CD, ND); when Calling_Opcode => Calls.Do_Calling_Operation (CD, ND); when Tasking_Opcode => Tasking.Do_Tasking_Operation (CD, ND); -- when k_Jump => Do_Jump; when k_Jump_If_Zero_With_Pop => -- NB: this is the original conditional jump in Pascal-S. if ND.S (Curr_TCB.T).I = 0 then Do_Jump; end if; Pop; -- NB: the popping happens regardless of the branch. when k_Jump_If_Zero_No_Pop => if ND.S (Curr_TCB.T).I = 0 then Do_Jump; end if; when k_Jump_If_Non_Zero_No_Pop => if ND.S (Curr_TCB.T).I /= 0 then Do_Jump; end if; -- when k_Check_Lower_Bound => Check_Lower (IR.X, Typen'Val (IR.Y), Index (IR.Z)); when k_Check_Upper_Bound => Check_Upper (IR.X, Typen'Val (IR.Y), Index (IR.Z)); -- when k_Variable_Initialization => Do_Code_for_Automatic_Initialization; when k_HAT_Procedure => Do_HAT_Procedure; when k_HAT_Function => Do_HAT_Function; -- when k_Pop => Pop; when k_Swap => Do_Swap; when k_Pop_to_Temp => Curr_TCB.R_Temp := ND.S (Curr_TCB.T); Pop; when k_Push_Temp => Push; ND.S (Curr_TCB.T) := Curr_TCB.R_Temp; when k_Push_Two_Discrete_Literals => Push (2); ND.S (Curr_TCB.T - 1).I := IR.X; ND.S (Curr_TCB.T).I := IR.Y; when k_Push_Two_Float_Literals => Push (2); ND.S (Curr_TCB.T - 1) := GR_Real (CD.Float_Constants_Table (Integer (IR.X))); ND.S (Curr_TCB.T) := GR_Real (CD.Float_Constants_Table (Integer (IR.Y))); end case; exception when others => Add_Stack_Trace_Line (Offset => 0); ND.PS := Exception_Raised; raise; end Execute_Current_Instruction; procedure Execute_Current_Instruction_with_Exception with Inline is use Ada.Exceptions; begin Execute_Current_Instruction; if ND.PS = Exception_Raised then -- We have just executed a Return, so the last instruction -- (with the program counter back to the caller side), was a Call. Add_Stack_Trace_Line (Offset => 1); end if; exception when VM_Case_Check_Error => Raise_Standard (ND, VME_Program_Error, "CASE Statement doesn't cover all cases"); when VM_Constraint_Error => Raise_Standard (ND, VME_Constraint_Error); when VM_Subprogram_Spec => Raise_Standard (ND, VME_Program_Error, "(HAC bug) Unlinked subprogram specification"); when E : VM_Division_by_0 => Raise_Standard (ND, VME_Constraint_Error, "Division by 0 (operator: " & Exception_Message (E) & ')'); when VM_End_Error => Raise_Standard (ND, VME_End_Error, ""); when VM_Function_End_without_Return => Raise_Standard (ND, VME_Program_Error, "Function's end reached without ""return"" statement"); when VM_Invalid_Data => Raise_Standard (ND, VME_Constraint_Error, "Invalid data (maybe due to an uninitialized variable)"); when E : VM_Out_of_Range => Raise_Standard (ND, VME_Constraint_Error, "Out of range" & Exception_Message (E)); when VM_Overflow_Error => Raise_Standard (ND, VME_Constraint_Error, "Overflow check failed"); when VM_Stack_Overflow => Raise_Standard (ND, VME_Storage_Error, "Stack overflow"); when VM_Stack_Underflow => Raise_Standard (ND, VME_Storage_Error, "Stack underflow"); when VM_Raised_Exception => null; -- HAC exception has been already raised (see Name_Error for an example). end Execute_Current_Instruction_with_Exception; procedure Single_Task_Delays is User_Aborted : Boolean; use Ada.Calendar, Tasking; wake : constant Time := ND.TCB (ND.CurTask).WAKETIME; begin ND.SYSCLOCK := Clock; if wake > ND.SYSCLOCK then while wake - ND.SYSCLOCK > TSlice loop Feedback (Stack_Current => ND.TCB (ND.CurTask).T, Stack_Total => ND.S'Last, Wall_Clock => ND.SYSCLOCK, User_Abort => User_Aborted); -- if User_Aborted then Raise_Standard (ND, VME_User_Abort, ""); end if; delay TSlice; ND.SYSCLOCK := Clock; end loop; delay Duration'Max (0.0, wake - ND.SYSCLOCK); end if; ND.SWITCH := False; ND.Single_Task_Delay_Pending := False; end Single_Task_Delays; User_Aborted : Boolean; begin -- Interpret Start_Interpreter; -- Running_State : loop -- ... until Processor state is not Running or Exception_Raised if ND.Scheduler = Single_Task then if ND.Single_Task_Delay_Pending then Single_Task_Delays; end if; else Tasking.Manage_Scheduling (CD, ND); end if; if ND.feedback_tick = 0 then ND.SYSCLOCK := Ada.Calendar.Clock; Feedback (Stack_Current => ND.TCB (ND.CurTask).T, Stack_Total => ND.S'Last, Wall_Clock => ND.SYSCLOCK, User_Abort => User_Aborted); -- if User_Aborted then Raise_Standard (ND, VME_User_Abort, ""); end if; end if; ND.feedback_tick := ND.feedback_tick + 1; exit Running_State when ND.PS = DEADLOCK or ND.PS = FIN; -- SmallAda inter.pas line 490 -- Fetch_Instruction; -- HERE IS THE POINT WHERE THE TASK MONITORING IS CALLED (removed) Execute_Current_Instruction_with_Exception; Post_Mortem.Max_Stack_Usage := Integer'Max (Post_Mortem.Max_Stack_Usage, ND.TCB (ND.CurTask).T); -- exit Running_State when ND.PS not in Running_or_in_Exception; end loop Running_State; -- if ND.PS not in Exception_Raised .. FIN then Post_Mortem_Dump (CD, ND); end if; -- Free_Allocated_Contents (ND, Post_Mortem.Open_Files); -- Post_Mortem.Unhandled := ND.TCB (ND.CurTask).Exception_Info; Post_Mortem.Stack_Size := In_Defs.Stack_Type'Last; -- Use Is_Exception_Raised to check whether an exception was -- unhandled when leaving the interpreter. case ND.PS is when FIN => null; -- All good, end reached (can have an unhandled exception). when Running => null; -- Should not happen here. when Exception_Raised => null; -- Unhandled exception information stored in Unhandled. when DEADLOCK => raise Abnormal_Termination with "Tasking: Deadlock"; when WAIT => raise Abnormal_Termination with "Tasking: Wait"; end case; end Interpret; function Current_IO_Get_Needs_Skip_Line return Boolean is begin return True; -- The input is buffered with Ada.Text_IO.Get (not Get_Immediate). end Current_IO_Get_Needs_Skip_Line; procedure Interpret_on_Current_IO ( BD_CIO : in out Builder.Build_Data; -- Everything is compiled and ready to run Argument_Shift : in Natural := 0; -- Number of arguments to be skipped Full_Script_Name : in String; -- This is for Command_Name Post_Mortem : out Post_Mortem_Data ) is procedure No_Feedback ( Stack_Current, Stack_Total : in Natural; Wall_Clock : in Ada.Calendar.Time; User_Abort : out Boolean ) is pragma Unreferenced (Stack_Total, Wall_Clock, Stack_Current); begin User_Abort := False; -- Ctrl-C will make it - in a less polite way... end No_Feedback; function Shifted_Argument_Count return Natural is begin return Ada.Command_Line.Argument_Count - Argument_Shift; end Shifted_Argument_Count; function Shifted_Argument (Number : Positive) return String is begin return Ada.Command_Line.Argument (Number + Argument_Shift); end Shifted_Argument; function Custom_Command_Name return String is begin return Full_Script_Name; end Custom_Command_Name; package Current_IO_Console is new Console_Traits (Ada.Text_IO.End_Of_File, Ada.Text_IO.End_Of_Line, Current_IO_Get_Needs_Skip_Line, Defs.IIO.Get, Defs.RIO.Get, Ada.Text_IO.Get, Ada.Text_IO.Get_Immediate, Ada.Text_IO.Get_Line, Ada.Text_IO.Skip_Line, Defs.IIO.Put, Defs.RIO.Put, Defs.BIO.Put, HAT.Put, HAT.Put, Ada.Text_IO.New_Line ); package Custom_System_Calls is new System_Calls_Traits (Shifted_Argument_Count, Shifted_Argument, Custom_Command_Name, HAT.Shell_Execute, HAT.Shell_Execute, -- This profile has an Output parameter. HAT.Directory_Separator ); procedure Interpret_on_Current_IO_Instance is new Interpret (No_Feedback, Current_IO_Console, Custom_System_Calls ); begin Interpret_on_Current_IO_Instance (BD_CIO, Post_Mortem); end Interpret_on_Current_IO; function Image (E : Exception_Propagation_Data) return String is Img : constant String := Exception_Type'Image (E.Currently_Raised.Ex_Typ); begin case E.Currently_Raised.Ex_Typ is when No_Exception => return ""; when VME_User_Abort => return "User_Abort"; when VME_Custom => return "(custom)"; -- needs to use details when Ada_Error_Exception_Type => -- Turn the enumerated item identifier, e.g. VME_MODE_ERROR, to "Mode_Error": return Img (Img'First + 4) & Ada.Characters.Handling.To_Lower (Img (Img'First + 5 .. Img'Last - 6)) & "_Error"; end case; end Image; function Message (E : Exception_Propagation_Data) return String is begin return HAT.To_String (E.Exception_Message); end Message; function Is_Exception_Raised (E : Exception_Propagation_Data) return Boolean is begin return E.Currently_Raised.Ex_Typ /= No_Exception; end Is_Exception_Raised; function Is_User_Abort (E : Exception_Propagation_Data) return Boolean is begin return E.Currently_Raised.Ex_Typ = VME_User_Abort; end Is_User_Abort; procedure Show_Trace_Back (E : Exception_Propagation_Data) is begin for STL of E.ST_Message loop Show_Line_Information ( HAT.To_String (STL.File_Name), HAT.To_String (STL.Full_Block_Id), STL.Line_Number ); end loop; end Show_Trace_Back; end HAC_Sys.PCode.Interpreter; ================================================ FILE: src/execute/hac_sys-pcode-interpreter.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Builder, HAC_Sys.Defs; with Ada.Calendar, Ada.Containers.Vectors, Ada.Text_IO; package HAC_Sys.PCode.Interpreter is ------------------ -- Exceptions -- ------------------ type Exception_Propagation_Data is private; function Is_Exception_Raised (E : Exception_Propagation_Data) return Boolean; function Is_User_Abort (E : Exception_Propagation_Data) return Boolean; function Image (E : Exception_Propagation_Data) return String; function Message (E : Exception_Propagation_Data) return String; generic with procedure Show_Line_Information ( File_Name : String; -- Example: hac-pcode-interpreter.adb Block_Name : String; -- Example: HAC.PCode.Interpreter.Do_Write_Formatted Line_Number : Positive ); procedure Show_Trace_Back (E : Exception_Propagation_Data); ------------------------ -- Post Mortem Data -- ------------------------ type Open_File_Data is record Name : HAT.VString; Mode : Ada.Text_IO.File_Mode; end record; package Open_Files_Vectors is new Ada.Containers.Vectors (Positive, Open_File_Data); type Post_Mortem_Data is record Unhandled : Exception_Propagation_Data; Max_Stack_Usage : Natural; Stack_Size : Positive; Open_Files : Open_Files_Vectors.Vector; end record; ------------------------------------------------------------------------------ -- Here, we provide a ready-to-use, "standard" instantiation of the -- -- interpreter, with Ada.Text_IO, Ada.Command_Line, ..., for the console. -- -- See hac.adb for an example where the console interface is used. -- -- See the LEA project for an example where it is *not* used, and a more -- -- sophisticated interface is used instead. -- ------------------------------------------------------------------------------ procedure Interpret_on_Current_IO ( BD_CIO : in out Builder.Build_Data; -- Everything is compiled and ready to run Argument_Shift : in Natural := 0; -- Number of arguments to be skipped Full_Script_Name : in String; -- This is for Command_Name Post_Mortem : out Post_Mortem_Data ); -- Part of the subprograms useed for the Interpret_on_Current_IO -- instanciation. -- function Current_IO_Get_Needs_Skip_Line return Boolean; --------------------------------------------------------------------------------- -- The following version of the interpreter abstracts ALL console Text I/O, -- -- in case we use something else than a standard terminal / console. -- -- Similarily we abstract Argument_Count and a few others. -- -- See the LEA project for a specific non-trivial (windowed) implementation. -- --------------------------------------------------------------------------------- -- Due to the large amount of abstracted subprograms, we wrap -- some groups into "traits". The idea is explained here: -- https://blog.adacore.com/traits-based-containers -- generic with function End_Of_File return Boolean; with function End_Of_Line return Boolean; with function Get_Needs_Skip_Line return Boolean; -- ^ True for a real console with Ada.Text_IO (line buffer); -- False for input boxes (like in LEA) or other kind of immediate input. with procedure Get (I : out HAC_Sys.Defs.HAC_Integer; Width : Ada.Text_IO.Field := 0); with procedure Get (F : out HAC_Sys.Defs.HAC_Float; Width : Ada.Text_IO.Field := 0); with procedure Get (C : out Character); with procedure Get_Immediate (C : out Character); with function Get_Line return String; with procedure Skip_Line (Spacing : Ada.Text_IO.Positive_Count := 1); -- with procedure Put ( I : HAC_Sys.Defs.HAC_Integer; Width : Ada.Text_IO.Field := HAC_Sys.Defs.IIO.Default_Width; Base : Ada.Text_IO.Number_Base := HAC_Sys.Defs.IIO.Default_Base); with procedure Put ( F : HAC_Sys.Defs.HAC_Float; Fore : Integer := HAC_Sys.Defs.RIO.Default_Fore; Aft : Integer := HAC_Sys.Defs.RIO.Default_Aft; Exp : Integer := HAC_Sys.Defs.RIO.Default_Exp ); with procedure Put ( B : in Boolean; Width : Ada.Text_IO.Field := HAC_Sys.Defs.BIO.Default_Width; Set : Ada.Text_IO.Type_Set := HAC_Sys.Defs.BIO.Default_Setting); with procedure Put (C : in Character); with procedure Put (S : in String); with procedure New_Line (Spacing : Ada.Text_IO.Positive_Count := 1); package Console_Traits is end Console_Traits; generic -- Function profiles for Argument* are from Ada.Command_Line (RM A.15). with function Argument_Count return Natural; with function Argument (Number : in Positive) return String; with function Command_Name return String; -- Shell execution, Directory_Separator, ... are also abstracted. with procedure Shell_Execute (Command : String; Result : out Integer); with procedure Shell_Execute_Output (Command : String; Result : out Integer; Output : out HAT.VString); with function Directory_Separator return Character; package System_Calls_Traits is end System_Calls_Traits; generic with procedure Feedback (Stack_Current, Stack_Total : in Natural; Wall_Clock : in Ada.Calendar.Time; User_Abort : out Boolean); with package Console is new Console_Traits (<>); with package System_Calls is new System_Calls_Traits (<>); -- procedure Interpret ( BD : in out Builder.Build_Data; -- Everything is compiled and ready to run Post_Mortem : out Post_Mortem_Data ); Abnormal_Termination : exception; type Exception_Type is (No_Exception, -- Ada classics: VME_Constraint_Error, VME_Data_Error, VME_End_Error, VME_Index_Error, VME_Mode_Error, VME_Name_Error, VME_Program_Error, VME_Status_Error, VME_Storage_Error, VME_Use_Error, -- VME_User_Abort, VME_Custom ); subtype Ada_Error_Exception_Type is Exception_Type range VME_Constraint_Error .. VME_Use_Error; private subtype Exception_Detail is Integer; -- Currently a placeholder (this is for the VME_Custom choice) type Exception_Identity is record Ex_Typ : Exception_Type; Detail : Integer; -- For the VME_Custom choice end record; package Stack_Trace_Messages is new Ada.Containers.Vectors (Positive, Debug_Info); subtype Stack_Trace_Message is Stack_Trace_Messages.Vector; type Exception_Propagation_Data is record Currently_Raised : Exception_Identity; ST_Message : Stack_Trace_Message; Exception_Message : HAT.VString; end record; end HAC_Sys.PCode.Interpreter; ================================================ FILE: src/execute/hac_sys-pcode.adb ================================================ with HAC_Sys.Errors; with Ada.Strings.Fixed; package body HAC_Sys.PCode is -- type ObjData is ( -- TabT, -- ATabt, -- BTabt, -- CodeT, -- ECountT, -- EntryTABt, -- FatT, -- FcTabt, -- STabT, -- TCountT, -- TaskTabT); -- -- type TArraysTab is array (1 .. AMax) of ATabEntry; -- type TBlockTab is array (1 .. BMax) of BTabEntry; -- type TObjCode is array (0 .. CDMax) of Order; -- type TEntryTAB is array (0 .. EntryMax) of Index; -- type TTskDefTab is array (0 .. TaskMax) of Index; -- type TIdTab is array (0 .. TMax) of TabEntry; -- type TStringTab is array (0 .. SMax) of Character; -- type TFloatPtTab is array (1 .. C2Max) of Float; -- type SMAObject (O : ObjData) is record -- case O is -- when ATabt => ArraysTab : TArraysTab; -- when BTabt => BlockTab : TBlockTab; -- when CodeT => ObjCode : TObjCode; -- when ECountT => ECount : Integer; -- when EntryTABt => EntryTAB : TEntryTAB; -- when FatT => FileIOTab : FilDescr; -- when FcTabt => FloatPtTab : TFloatPtTab; -- when STabT => StringTab : TStringTab; -- when TabT => IdTab : TIdTab; -- when TaskTabT => TskDefTab : TTskDefTab; -- when TCountT => TCount : Integer; -- end case; -- end record; -- package OAIO is new Sequential_IO(SMAObject); -- use OAIO; -- ** The next three functions are almost identical. -- -- * Emit store an object code for an instruction with no -- * arguments, -- * Emit1 store an object code for an instruction with one -- * argument (Y), and -- * Emit2 store an object code for an instruction with two -- * arguments. -- * -- * Originally it was implemented as three procedures. -- * -- * Emit and Emit1 call Emit2 with 0 for unused arguments -- * -- * Manuel * procedure Emit_Instruction ( OC : in out Object_Code_Table; LC : in out Integer; D : Debug_Info; FCT : Opcode; a : Operand_1_Type; B : Operand_2_Type; c : Operand_3_Type; folded : out Boolean; specialized : out Boolean ) is use type Defs.HAC_Integer; FCT_corr : Opcode := FCT; -- -- Replace an instruction by a more specialized instruction. -- procedure Try_Specialization is procedure Specialize (new_value : Opcode) with Inline is begin FCT_corr := new_value; specialized := True; end Specialize; begin case FCT_corr is when k_Store => if Defs.Discrete_Typ (Defs.Typen'Val (B)) then Specialize (k_Store_Discrete); end if; when k_Dereference => if Defs.Discrete_Typ (Defs.Typen'Val (B)) then Specialize (k_Dereference_Discrete); end if; when others => null; end case; end Try_Specialization; -- -- Try folding two instruction into one. -- This technique is only doable within Ada statements, -- otherwise the jumps will be wrong... -- procedure Try_Folding is old : Order renames OC (LC - 1); procedure Simple_Substitution (prev_old_value, prev_new_value : Opcode) is pragma Inline (Simple_Substitution); begin if (not folded) and then old.F = prev_old_value then old.F := prev_new_value; folded := True; end if; end Simple_Substitution; begin case FCT_corr is when k_SUBTRACT_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_SUBTRACT_Integer_Literal); when k_MULT_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_MULT_Integer_Literal); when k_DIV_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_DIV_Integer_Literal); when k_EQL_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_EQL_Integer_Literal); when k_NEQ_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_NEQ_Integer_Literal); when k_LSS_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_LSS_Integer_Literal); when k_LEQ_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_LEQ_Integer_Literal); when k_GTR_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_GTR_Integer_Literal); when k_GEQ_Integer => Simple_Substitution (k_Push_Discrete_Literal, k_GEQ_Integer_Literal); when k_ADD_Integer => case old.F is when k_ADD_Integer => old.F := k_ADD_Integer_Multiple; old.Y := 3; folded := True; when k_ADD_Integer_Multiple => old.Y := old.Y + 1; folded := True; when others => null; end case; Simple_Substitution (k_MULT_Integer, k_MULT_then_ADD_Integer); Simple_Substitution (k_Push_Discrete_Literal, k_ADD_Integer_Literal); when k_ADD_Float => case old.F is when k_ADD_Float => old.F := k_ADD_Float_Multiple; old.Y := 3; folded := True; when k_ADD_Float_Multiple => old.Y := old.Y + 1; folded := True; when others => null; end case; Simple_Substitution (k_MULT_Float, k_MULT_then_ADD_Float); when k_Unary_MINUS_Integer => if old.F = k_Push_Discrete_Literal and then old.Y > Defs.HAC_Integer'First then old.Y := -old.Y; folded := True; end if; when k_Push_Discrete_Literal => if old.F = k_Push_Discrete_Literal then old.F := k_Push_Two_Discrete_Literals; old.X := old.Y; old.Y := B; folded := True; end if; when k_Push_Float_Literal => if old.F = k_Push_Float_Literal then old.F := k_Push_Two_Float_Literals; old.X := old.Y; old.Y := B; folded := True; end if; when k_Store => Simple_Substitution (k_Push_Float_Literal, k_Store_Float_Literal); -- ^ Operand B (for this opcode, special type info) is discarded -- since the TYP is Floats. -- Simple_Substitution (k_ADD_Float, k_ADD_Float_then_Store); Simple_Substitution (k_SUBTRACT_Float, k_SUBTRACT_Float_then_Store); Simple_Substitution (k_MULT_Float, k_MULT_Float_then_Store); when k_Store_Discrete => Simple_Substitution (k_Push_Discrete_Literal, k_Store_Discrete_Literal); -- ^ Operand B (for this opcode, special type info) is discarded -- since we have a (subtype-checked) discrete value. Simple_Substitution (k_ADD_Integer, k_ADD_Integer_then_Store); Simple_Substitution (k_SUBTRACT_Integer, k_SUBTRACT_Integer_then_Store); Simple_Substitution (k_MULT_Integer, k_MULT_Integer_then_Store); when k_NOT_Boolean => Simple_Substitution (k_AND_Boolean, k_NAND_Boolean); Simple_Substitution (k_OR_Boolean, k_NOR_Boolean); when others => null; end case; end Try_Folding; -- begin folded := False; specialized := False; if LC = OC'Last then Errors.Fatal (Errors.Object_Code); end if; Try_Specialization; if LC > OC'First then Try_Folding; end if; if not folded then OC (LC).F := FCT_corr; OC (LC).X := a; OC (LC).Y := B; OC (LC).Z := c; OC (LC).D := D; LC := LC + 1; end if; end Emit_Instruction; procedure Patch_Addresses ( OC : in out Object_Code_Table; dummy_address : Operand_2_Type ) is use Defs; use type HAC_Integer; begin for Op of OC (OC'First .. OC'Last - 1) loop if Op.F in Jump_Opcode and then Op.Y = dummy_address then Op.Y := HAC_Integer (OC'Last); end if; end loop; end Patch_Addresses; procedure Patch_Addresses ( OC : in out Object_Code_Table; PT : Patch_Table; Top : in out Natural ) is begin for Instruction_Address of PT (PT'First .. Top) loop OC (Integer (Instruction_Address)).Y := Operand_2_Type (OC'Last); end loop; Top := 0; end Patch_Addresses; procedure Feed_Patch_Table ( PT : in out Patch_Table; Top : in out Natural; LC : Integer ) is begin if Top < PT'Last then Top := Top + 1; else Errors.Fatal (Errors.PATCHING); end if; PT (Top) := Operand_2_Type (LC); end Feed_Patch_Table; procedure Dump ( OC : Object_Code_Table; Str_Const : String; Flt_Const : Defs.Float_Constants_Table_Type; Text : Ada.Text_IO.File_Type ) is use Ada.Strings.Fixed, Ada.Text_IO, Defs; package Opcode_IO is new Enumeration_IO (Opcode); package Code_Pos_IO is new Integer_IO (Natural); package Operand1_IO is new Integer_IO (Operand_1_Type); package Operand2_IO is new Integer_IO (Operand_2_Type); function HAC_Image is new HAT.HAC_Generic_Image (Defs.HAC_Integer); SF_C : SF_Code; SP_C : SP_Code; Old_X1 : Operand_1_Type := 0; Old_Y1 : Operand_2_Type := 0; -- function Padded_Opcode (o : Opcode) return String is s : String (1 .. Opcode'Width); begin Opcode_IO.Put (s, o); return s; end Padded_Opcode; use type Operand_2_Type; begin Put_Line (Text, "Position : Opcode " & (Opcode'Width - 7) * ' ' & "Level/X " & "Addr/Val/Y" & "; Approx source location; Extra information"); Put_Line (Text, 120 * '-'); for i in OC'Range loop Code_Pos_IO.Put (Text, i); Put (Text, ": " & Padded_Opcode (OC (i).F)); case OC (i).F is -- Omit showing X for some 1-operand instructions when k_Return_Call | k_Return_Function | k_Mark_Stack | k_Push_Discrete_Literal | k_Push_Float_Literal .. k_Push_Float_Last | k_Store | k_Pop | Unary_Operator_Opcode | Binary_Operator_Opcode | Special_Operator_Opcode | Jump_Opcode => Put (Text, " "); when others => Operand1_IO.Put (Text, OC (i).X, 5); end case; case OC (i).F is -- Omit showing Y for some 0-operand instructions when k_Pop | k_Push_Float_First .. k_Push_Float_Last | Binary_Operator_Opcode | k_ADD_Integer_Multiple .. k_MULT_Float_then_Store | k_NAND_Boolean | k_NOR_Boolean => Put (Text, " "); when others => Operand2_IO.Put (Text, OC (i).Y); end case; Put (Text, "; "); Code_Pos_IO.Put (Text, OC (i).D.Line_Number); Put (Text, " " & HAT.VStr_Pkg.To_String (OC (i).D.Full_Block_Id)); case OC (i).F is -- Show extra information when k_Push_Float_Literal => Put (Text, "; " & HAT.HAC_Image (Flt_Const (Integer (OC (i).Y)))); when k_Push_Float_First => Put (Text, "; HAT.Real'First: " & HAC_Float'Image (HAT.Real'First)); when k_Push_Float_Last => Put (Text, "; HAT.Real'Last: " & HAC_Float'Image (HAT.Real'Last)); when k_Variable_Initialization => Put (Text, "; " & Defs.Typen'Image (Defs.Typen'Val (OC (i).Y))); when k_HAT_Function => SF_C := SF_Code'Val (OC (i).Y); Put (Text, "; " & SF_Code'Image (SF_C)); when k_HAT_Procedure => SP_C := SP_Code'Val (OC (i).X); Put (Text, "; " & SP_Code'Image (SP_C)); case SP_C is when SP_Get .. SP_Get_Line => Put (Text, "; " & Defs.Typen'Image (Defs.Typen'Val (OC (i).Y))); when SP_Put .. SP_Put_Line => if Defs.Typen'Val (OC (i).Y) = Defs.String_Literals then -- We know that a string literal was pushed just before, -- as a pair of discrete literals (CD.target.Emit_Push_Discrete_Literals). Put (Text, "; """ & Str_Const (Integer (Old_Y1) .. Integer (Old_Y1 + Old_X1 - 1)) & '"'); end if; when others => null; end case; when k_FOR_Release_Stack => Put (Text, "; Release stack used by FOR loop(s)"); when k_CASE_Switch => Put (Text, "; (CASE) Jump to the switch block"); when k_CASE_Choice_Value => Put (Text, "; (CASE) WHEN " & HAC_Image (OC (i).Y) & " =>"); when k_CASE_Choice_Range => Put (Text, "; (CASE) WHEN " & HAC_Image (OC (i).X) & " .." & HAC_Image (OC (i).Y) & " =>"); when k_CASE_Choice_Others => Put (Text, "; (CASE) WHEN OTHERS =>"); when k_Mark_Stack => Put (Text, "; Mark stack for calling subprogram with ID #" & HAC_Image (OC (i).Y)); when k_Call => Put (Text, "; Call with PSize = " & HAC_Image (OC (i).Y + 1)); when k_Update_Display_Vector => Put (Text, "; Update: low level (called) = " & HAC_Image (OC (i).X) & ", high level (caller) = " & HAC_Image (OC (i).Y)); when others => null; end case; New_Line (Text); -- Old_X1 := OC (i).X; Old_Y1 := OC (i).Y; end loop; end Dump; -------------------------------------------------------------SaveOBJ---- procedure SaveOBJ (FileName : String) is -- ObjFile: OAIO.File_Type; -- Buffer: SMAObject; begin -- Create( ObjFile, name => FileName & ".Obj"); -- -- FOR I IN 1.. AMax LOOP -- Buffer.ArraysTab(I) := ArraysTab(I); -- END LOOP; -- Write(ObjFile, Buffer); -- -- FOR I IN 1.. BMax LOOP -- Buffer.BlockTab(I) := BlockTab(I); -- END LOOP; -- Write(ObjFile, Buffer); -- -- FOR I IN 0.. CDMax LOOP -- Buffer.ObjCode(I) := ObjCode(I); -- END LOOP; -- Write(ObjFile, Buffer); -- -- Buffer.ECount := ECount; -- Write(ObjFile, Buffer); -- -- FOR I IN 0.. EntryMax LOOP -- Buffer.EntryTAB(I) := EntryTAB(I); -- END LOOP; -- Write(ObjFile, Buffer); -- -- --{Buffer.FileIOTab := FileIOTab;} --{ Error assigning file } -- -- FOR I IN 1.. C2Max LOOP -- Buffer.FloatPtTab(I) := FloatPtTab(I); -- END LOOP; -- Write(ObjFile, Buffer); -- -- FOR I IN 0.. SMax LOOP -- Buffer.StringTab(I) := StringTab(I); -- END LOOP; -- Write(ObjFile, Buffer); -- -- FOR I IN 0.. TMax LOOP -- Buffer.IdTab(I) := IdTab(I); -- END LOOP; -- Write(ObjFile, Buffer); -- -- FOR I IN 0.. TaskMax LOOP -- Buffer.TskDefTab(I) := TskDefTab(I); -- END LOOP; -- Write(ObjFile, Buffer); -- -- Buffer.TCount := TCount; -- Write(ObjFile, Buffer); -- -- Close(ObjFile); null; -- will be streamed... end SaveOBJ; ----------------------------------------------------------RestoreOBJ----} procedure RestoreOBJ (FileName : String) is -- ObjFile: OAIO.File_Type; -- Buffer: SMAObject; begin -- BEGIN -- Open(ObjFile, in_file, FileName & ".Obj"); -- EXCEPTION -- when others=> -- IF qDebug THEN -- Text_IO.Put_Line("Cannot find file : " & FileName & ".Obj"); -- END IF; -- raise Failure_1_0; -- END; -- -- Read(ObjFile, Buffer); -- FOR I IN 1.. AMax LOOP -- ArraysTab(I) := Buffer.ArraysTab(I); -- END LOOP; -- -- Read(ObjFile, Buffer); -- FOR I IN 1.. BMax LOOP -- BlockTab(I) := Buffer.BlockTab(I); -- END LOOP; -- -- Read(ObjFile, Buffer); -- FOR I IN 0.. CDMax LOOP -- ObjCode(I) := Buffer.ObjCode(I); -- END LOOP; -- -- Read(ObjFile, Buffer); -- ECount := Buffer.ECount; -- -- Read(ObjFile, Buffer); -- FOR I IN 0.. EntryMax LOOP -- EntryTAB(I) := Buffer.EntryTAB(I); -- END LOOP; -- -- Read(ObjFile, Buffer); -- --{FileIOTab := Buffer.FileIOTab;} --{ Error assigning file } -- Read(ObjFile, Buffer); -- FOR I IN 1.. C2Max LOOP -- FloatPtTab(I) := Buffer.FloatPtTab(I); -- END LOOP; -- -- Read(ObjFile, Buffer); -- FOR I IN 0.. SMax LOOP -- StringTab(I) := Buffer.StringTab(I); -- END LOOP; -- -- Read(ObjFile, Buffer); -- FOR I IN 0.. TMax LOOP -- IdTab(I) := Buffer.IdTab(I); -- END LOOP; -- -- Read(ObjFile, Buffer); -- FOR I IN 0.. TaskMax LOOP -- TskDefTab(I) := Buffer.TskDefTab(I); -- END LOOP; -- -- Read(ObjFile, Buffer); -- TCount := Buffer.TCount; -- -- Close(ObjFile); null; -- will be streamed... end RestoreOBJ; end HAC_Sys.PCode; ================================================ FILE: src/execute/hac_sys-pcode.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- This package defines the PCode Virtual Machine. with HAC_Sys.Defs; with HAT; with Ada.Text_IO; -- Only used for file descriptors package HAC_Sys.PCode is -----------------------------------------------------PCode Opcodes---- type Opcode is ( k_Push_Address, k_Push_Value, k_Push_Discrete_Value, k_Push_Indirect_Value, k_Push_Indirect_Discrete_Value, -- k_Push_Discrete_Literal, k_Push_Float_Literal, k_Push_Float_First, k_Push_Float_Last, -- k_Push_Two_Discrete_Literals, k_Push_Two_Float_Literals, -- k_Pop, -- k_Variable_Initialization, k_Store, k_Store_Discrete, -- Like Store, but copies only the discrete field. k_Store_Discrete_Literal, -- Equivalent to: Push_Discrete_Literal, then Store_Discrete. k_Store_Float_Literal, -- Equivalent to: Push_Float_Literal, then Store. k_Swap, -- Swap the two items at the top of the stack. k_Pop_to_Temp, -- Pop top item to a temp register. k_Push_Temp, -- Push temp register on the stack. k_Check_Lower_Bound, k_Check_Upper_Bound, -- k_Jump, k_Jump_If_Zero_With_Pop, -- Jump if [T].I = 0, always pop -> general use k_Jump_If_Zero_No_Pop, -- Jump if [T].I = 0, no pop -> for "and then" k_Jump_If_Non_Zero_No_Pop, -- Jump if [T].I /= 0, no pop -> for "or else" -- k_CASE_Switch, k_CASE_Choice_Value, k_CASE_Choice_Range, k_CASE_Choice_Others, k_CASE_Match_Jump, k_CASE_No_Choice_Found, -- k_FOR_Forward_Begin, k_FOR_Reverse_Begin, k_FOR_Forward_End, k_FOR_Reverse_End, k_FOR_Release_Stack, -- k_Array_Index_Element_Size_1, k_Array_Index, k_Array_Index_No_Check_Element_Size_1, k_Array_Index_No_Check, -- k_Record_Field_Offset, k_Load_Block, -- Push a composite type's data on the stack. k_Load_String_Literal, -- Push a string literal's contents on the stack. k_Copy_Block, k_String_Literal_Assignment, -- k_Mark_Stack, -- First instruction for a Call k_Call, -- Procedure and task entry Call k_Exchange_with_External, k_Return_Call, k_Return_Function, k_Update_Display_Vector, -- -- Unary operators -- k_Integer_to_Float, -- The reverse conversion is done by a k_Standard_Functions k_Dereference, k_Dereference_Discrete, k_Unary_MINUS_Float, -- 2020-04-04 k_Unary_MINUS_Integer, k_NOT_Boolean, -- -- Binary operators -- k_EQL_Integer, k_NEQ_Integer, k_LSS_Integer, k_LEQ_Integer, k_GTR_Integer, k_GEQ_Integer, -- k_EQL_VString, k_NEQ_VString, k_LSS_VString, k_LEQ_VString, k_GTR_VString, k_GEQ_VString, -- k_EQL_Float, k_NEQ_Float, k_LSS_Float, k_LEQ_Float, k_GTR_Float, k_GEQ_Float, -- k_ADD_Integer, k_SUBTRACT_Integer, k_MULT_Integer, k_DIV_Integer, k_MOD_Integer, k_REM_Integer, k_Power_Integer, -- 2018-03-18 : 3 ** 6 -- k_ADD_Float, k_SUBTRACT_Float, k_MULT_Float, k_DIV_Float, k_Power_Float, -- 2018-03-22 : 3.14 ** 6.28 k_Power_Float_Integer, -- 2018-03-22 : 3.14 ** 6 -- k_AND_Boolean, k_OR_Boolean, k_XOR_Boolean, -- -- Special operators, resulting of folding of two or more instructions -- k_ADD_Integer_Multiple, -- 2022-05-21 : add 3 or more terms k_ADD_Float_Multiple, -- 2022-05-21 : add 3 or more terms k_MULT_then_ADD_Integer, -- 2022-05-21 : i + j * k k_MULT_then_ADD_Float, -- 2022-05-21 : i + j * k -- k_ADD_Integer_then_Store, k_SUBTRACT_Integer_then_Store, k_MULT_Integer_then_Store, -- k_ADD_Float_then_Store, k_SUBTRACT_Float_then_Store, k_MULT_Float_then_Store, -- k_ADD_Integer_Literal, k_SUBTRACT_Integer_Literal, k_MULT_Integer_Literal, k_DIV_Integer_Literal, k_EQL_Integer_Literal, k_NEQ_Integer_Literal, k_LSS_Integer_Literal, k_LEQ_Integer_Literal, k_GTR_Integer_Literal, k_GEQ_Integer_Literal, -- k_NAND_Boolean, k_NOR_Boolean, -- k_HAT_Procedure, k_HAT_Function, -- -- k_Halt_Interpreter, -- Switch off the processor's running loop -- -- Tasking stuff -- k_Accept_Rendezvous, k_End_Rendezvous, k_Wait_Semaphore, k_Signal_Semaphore, k_Delay, k_Set_Quantum_Task, k_Set_Task_Priority, k_Set_Task_Priority_Inheritance, k_Selective_Wait ); subtype Unary_Operator_Opcode is Opcode range k_Integer_to_Float .. k_NOT_Boolean; subtype Binary_Operator_Opcode is Opcode range k_EQL_Integer .. k_XOR_Boolean; subtype Multiple_Operator_Opcode is Opcode range k_ADD_Integer_Multiple .. k_ADD_Float_Multiple; subtype Special_Operator_Opcode is Opcode range k_MULT_then_ADD_Integer .. k_NOR_Boolean; subtype Op_then_Store_Opcode is Special_Operator_Opcode range k_ADD_Integer_then_Store .. k_MULT_Float_then_Store; subtype Op_Float_then_Store_Opcode is Op_then_Store_Opcode range k_ADD_Float_then_Store .. k_MULT_Float_then_Store; subtype Op_Integer_Literal_Opcode is Special_Operator_Opcode range k_ADD_Integer_Literal .. k_GEQ_Integer_Literal; subtype Compare_Integer_Literal_Opcode is Op_Integer_Literal_Opcode range k_EQL_Integer_Literal .. k_GEQ_Integer_Literal; -- subtype Atomic_Data_Push_Opcode is Opcode range k_Push_Address .. k_Push_Indirect_Discrete_Value; subtype Literal_Push_Opcode is Opcode range k_Push_Discrete_Literal .. k_Push_Float_Last; subtype Calling_Opcode is Opcode range k_Mark_Stack .. k_Update_Display_Vector; subtype CASE_Any_Choice is Opcode range k_CASE_Choice_Value .. k_CASE_Choice_Others; subtype CASE_Data_Opcode is Opcode range k_CASE_Choice_Value .. k_CASE_No_Choice_Found; subtype Composite_Data_Opcode is Opcode range k_Array_Index_Element_Size_1 .. k_String_Literal_Assignment; subtype Jump_Opcode is Opcode range k_Jump .. k_Jump_If_Non_Zero_No_Pop; subtype Multi_Statement_Opcode is Opcode range k_CASE_Switch .. k_FOR_Release_Stack; subtype Tasking_Opcode is Opcode range k_Halt_Interpreter .. k_Selective_Wait; For_END_Instruction : constant array (k_FOR_Forward_Begin .. k_FOR_Reverse_Begin) of Opcode := (k_FOR_Forward_Begin => k_FOR_Forward_End, k_FOR_Reverse_Begin => k_FOR_Reverse_End); type Opcode_Set is array (Opcode) of Boolean; OK_for_Exception : constant Opcode_Set := (k_Return_Call .. k_Return_Function | k_Halt_Interpreter => True, others => False); -- Type for operand 2 (Y) is large enough for containing -- addresses, plus signed integer values *in* HAC programs. -- subtype Operand_1_Type is Defs.HAC_Integer; subtype Operand_2_Type is Defs.HAC_Integer; subtype Operand_3_Type is Defs.HAC_Integer; type Debug_Info is record -- Line number in the source code. Line_Number : Positive; -- Current block's path (if any). Example: hac-pcode-interpreter.adb. Full_Block_Id : HAT.VString; -- Source code file name. Example: HAC.PCode.Interpreter.Do_Write_Formatted. File_Name : HAT.VString; end record; -- PCode instruction record (stores a compiled PCode instruction) type Order is record F : Opcode; -- Opcode (or instruction field) X : Operand_1_Type; -- Operand 1 is mostly used to point to the static level Y : Operand_2_Type; -- Operand 2 is used to pass addresses and sizes to the -- instructions, or to pass immediate discrete values (k_Literal). Z : Operand_3_Type; D : Debug_Info; end record; type Object_Code_Table is array (Natural range <>) of Order; -- For jumps forward in the code towards an ELSE, ELSIF, END IF, END LOOP, ... -- When the code is emited, the address is still unknown. -- When the address is known, jump addresses are patched. -- Patching using dummy addresses. -- For loops, this technique can be used only for exiting -- the current loop. dummy_address_if : constant := -1; dummy_address_loop : constant := -2; -- Patch to OC'Last all addresses of Jump_Opcode's which are equal to dummy_address. procedure Patch_Addresses ( OC : in out Object_Code_Table; dummy_address : Operand_2_Type ); -- Mechanism for patching instructions at selected addresses. type Patch_Table is array (Positive range <>) of Operand_2_Type; subtype Fixed_Size_Patch_Table is Patch_Table (1 .. HAC_Sys.Defs.Patch_Max); -- Patch to OC'Last all addresses for Jump instructions whose -- addresses are contained in the Patch_Table, up to index Top. -- Reset Top to 0. procedure Patch_Addresses ( OC : in out Object_Code_Table; PT : Patch_Table; Top : in out Natural ); -- Add new instruction address to a Patch_Table. procedure Feed_Patch_Table ( PT : in out Patch_Table; Top : in out Natural; LC : Integer ); procedure Dump ( OC : Object_Code_Table; Str_Const : String; Flt_Const : Defs.Float_Constants_Table_Type; Text : Ada.Text_IO.File_Type ); -- Store PCode instruction in the object code table OC at position LC and increments LC. procedure Emit_Instruction ( OC : in out Object_Code_Table; LC : in out Integer; D : Debug_Info; FCT : Opcode; a : Operand_1_Type; B : Operand_2_Type; c : Operand_3_Type; folded : out Boolean; specialized : out Boolean ); -- Save and restore an object file procedure SaveOBJ (FileName : String); procedure RestoreOBJ (FileName : String); end HAC_Sys.PCode; ================================================ FILE: src/hac_sys-interfacing.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- This package defines the interfacing mechanism between HAC and a "full Ada" app. -- Demo in: demo/data_exchange/exchange_native_side.adb with HAC_Sys.Builder, HAC_Sys.PCode.Interpreter.In_Defs; package HAC_Sys.Interfacing is type HAC_Element is private; ------------------------------------ -- Native -> HAC conversions -- ------------------------------------ function To_HAC (Data : Integer) return HAC_Element; function To_HAC (Data : Long_Float) return HAC_Element; function To_HAC (Data : String) return HAC_Element; generic type Any_Integer is range <>; function To_HAC_Any_Integer (Data : Any_Integer) return HAC_Element; generic type Any_Enum is (<>); function To_HAC_Any_Enum (Data : Any_Enum) return HAC_Element; generic type Any_Float is digits <>; function To_HAC_Any_Float (Data : Any_Float) return HAC_Element; ------------------------------------ -- HAC -> Native conversions -- ------------------------------------ function To_Native (Data : HAC_Element) return Integer; function To_Native (Data : HAC_Element) return Long_Float; function To_Native (Data : HAC_Element) return String; generic type Any_Integer is range <>; function To_Native_Any_Integer (Data : HAC_Element) return Any_Integer; generic type Any_Enum is (<>); function To_Native_Any_Enum (Data : HAC_Element) return Any_Enum; generic type Any_Float is digits <>; function To_Native_Any_Float (Data : HAC_Element) return Any_Float; HAC_Type_Error : exception; type HAC_Element_Array is array (Positive range <>) of HAC_Element; ---------------------- -- Call-back type -- ---------------------- type Exported_Procedure is access procedure (Data : in out HAC_Element_Array); -- Registration. You can register call-backs any time: before compilation, -- after compilation, or even during HAC's run-time if you can control, -- from the Native program, when a call-back is called. For instance, -- the registration of a call-back to some Native procedure or another one -- might be done during another call-back. -- procedure Register (BD : Builder.Build_Data; Callback : Exported_Procedure; Name : String); procedure Deregister (BD : Builder.Build_Data; Name : String); --------------------------------- -- Virtual Machine Variables -- --------------------------------- -- The strings set as Virtual Machine Variables can be read and written -- from a HAC program via the HAT.Get_VM_Variable and HAT.Set_VM_Variable -- subprograms. This way, data can be exchanged, before and after running -- a program through the HAC VM interpreter, between that program and the -- program that runs HAC. The strings are as persistent as an object -- of type Builder.Build_Data is. -- See demo/data_exchange/exchange_native_side_pkg.adb for an example. function Get_VM_Variable (BD : Builder.Build_Data; Name : String) return String; procedure Set_VM_Variable (BD : in out Builder.Build_Data; Name : String; Value : String); private type HAC_Element is new HAC_Sys.PCode.Interpreter.In_Defs.Data_Type; end HAC_Sys.Interfacing; ================================================ FILE: src/hac_sys.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Version / date / download info: see the version, reference, web strings -- defined at the end of the public part of this package. -- -- Legal licensing note: -- -- Copyright (c) 2013 .. 2026 Gautier de Montmollin -- -- History and authors list of works HAC was originally -- derived from can be found in hac.txt. -- -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be included in -- all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -- NB: this is the MIT License, as found 12-Sep-2013 on the site -- http://www.opensource.org/licenses/mit-license.php -- ------------------------------------------------------------------------------------- -- package HAC_Sys is -------------------------------------------------------------- -- Information about this package - e.g. for an "about" box -- -------------------------------------------------------------- version : constant String := "0.42"; reference : constant String := "31-Jan-2026"; -- Hopefully the latest version is reachable at one of those URLs: web : constant String := "https://hacadacompiler.sourceforge.io/"; web2 : constant String := "https://sourceforge.net/projects/hacadacompiler/"; web3 : constant String := "https://github.com/zertovitch/hac"; web4 : constant String := "https://alire.ada.dev/crates/hac"; end HAC_Sys; ================================================ FILE: src/hat-non_standard.adb ================================================ -- GNAT version. with Interfaces.C; separate (HAT) package body Non_Standard is function GNAT_Sys (Arg : Interfaces.C.char_array) return Interfaces.C.int; pragma Import (C, GNAT_Sys, "system"); procedure Sys (Command : String; Result : out Integer) is -- https://rosettacode.org/wiki/Execute_a_system_command#Ada begin Result := Integer (GNAT_Sys (Interfaces.C.To_C (Command))); end Sys; GNAT_Directory_Separator : constant Character; pragma Import (C, GNAT_Directory_Separator, "__gnat_dir_separator"); function Directory_Separator return Character is begin return GNAT_Directory_Separator; end Directory_Separator; end Non_Standard; ================================================ FILE: src/hat-non_standard_oawin64.adb ================================================ -- ObjectAda64 for Windows version. -- with Ada.Unchecked_Conversion; -- with Win32.Crt.Process; with Interfaces.C; separate (HAT) package body Non_Standard is function MS_Sys (Arg : Interfaces.C.char_array) return Interfaces.C.int; pragma Import (C, MS_Sys, "system"); -- You may (or not) need to add the following search path to the OA .prj project: -- C:\Program Files (x86)\PTC\ObjectAda64\win32ada\binding\lib\ -- -- In ADA.LIB (in, e.g., the hac_objectada-Win32(Intel)-Debug directory): -- -- PATH -- PATHNAME: ..\..\..\program files (x86)\ptc\objectada64\lib\rts -- ---> PATHNAME: ..\..\..\program files (x86)\ptc\objectada64\win32ada\binding\lib -- ENDPATH procedure Sys (Command : String; Result : out Integer) is -- cmd_nul : aliased Interfaces.C.char_array := Interfaces.C.To_C (Command); -- type p_Char is access all Interfaces.C.char_array; -- p_cmd_nul : p_Char := cmd_nul'Access; -- function Convert is new Ada.Unchecked_Conversion (p_Char, Win32.PCSTR); begin Result := Integer (MS_Sys (Interfaces.C.To_C (Command))); -- Result := Integer (Win32.Crt.Process.System (Convert (p_cmd_nul))); end Sys; function Directory_Separator return Character is begin return '\'; end Directory_Separator; end Non_Standard; ================================================ FILE: src/hat.adb ================================================ with Ada.Containers.Hashed_Maps, Ada.Numerics.Float_Random, Ada.Numerics.Generic_Elementary_Functions, Ada.Streams.Stream_IO, Ada.Strings.Fixed, Ada.Strings.Unbounded.Hash, Ada.Text_IO.Text_Streams; package body HAT is package REF is new Ada.Numerics.Generic_Elementary_Functions (Real); function "**" (F1, F2 : Real) return Real is begin return REF."**" (F1, F2); end "**"; function Sqrt (I : Integer) return Real is begin return REF.Sqrt (Real (I)); end Sqrt; function Sqrt (F : Real) return Real is begin return REF.Sqrt (F); end Sqrt; function Chr (I : Integer) return Character is begin return Character'Val (I); end Chr; function Ord (C : Character) return Integer is begin return Character'Pos (C); end Ord; function Succ (C : Character) return Character is begin return Character'Succ (C); end Succ; function Pred (C : Character) return Character is begin return Character'Pred (C); end Pred; function Round (F : Real) return Integer is begin return Integer (F); end Round; function Trunc (F : Real) return Integer is begin return Integer (Real'Floor (F)); end Trunc; function Sin (F : Real) return Real is begin return REF.Sin (F); end Sin; function Cos (F : Real) return Real is begin return REF.Cos (F); end Cos; function Arctan (F : Real) return Real is begin return REF.Arctan (F); end Arctan; function Log (F : Real) return Real is begin return REF.Log (F); end Log; function Exp (F : Real) return Real is begin return REF.Exp (F); end Exp; function Sgn (I : Integer) return Integer is begin return (if I > 0 then 1 elsif I < 0 then -1 else 0); end Sgn; function Sgn (F : Real) return Real is begin return (if F > 0.0 then 1.0 elsif F < 0.0 then -1.0 else 0.0); end Sgn; function Rand (I : Integer) return Integer is res : Integer; begin loop res := Trunc (Rnd * Real (I + 1)); exit when res < I + 1; -- In extremely rare cases we have res = I + 1. end loop; return res; end Rand; gen : Ada.Numerics.Float_Random.Generator; function Rnd return Real is begin return Real (Ada.Numerics.Float_Random.Random (gen)); end Rnd; procedure Randomize is begin Ada.Numerics.Float_Random.Reset (gen); end Randomize; procedure Random_Seed (New_Seed : Positive) is begin Ada.Numerics.Float_Random.Reset (gen, New_Seed); end Random_Seed; function HAC_Image (I : Integer) return String is Im : constant String := Integer'Image (I); begin -- Return image without leading ' ' on non-negative values. return (if I < 0 then Im else Im (Im'First + 1 .. Im'Last)); end HAC_Image; function HAC_Image (T : Ada.Calendar.Time) return String is use Ada; -- Time_display returns date & time, current or given. -- E.g.: "2013/08/01 05:49:51" -- Useful for a log file or a display of a lengthy operation. -- This is Ada 83 compatible. Format accepted by SQL queries. -- -- 32- or 64-bit: DEC/Compaq/HP Ada (83), GNAT (95/2005), ObjectAda (95) -- 16-bit: Meridian (83) -> Long_Integer is 32-bit -- 16-bit: Janus 2.x (83): KO: no Long_Integer -- -- Test program in following comment: -- -- with Text_IO,Time_display;procedure Test is begin Text_IO.Put(Time_display);end; -- function Time_display ( T : Calendar.Time := Calendar.Clock; Seconds : Boolean := True; Intra_day : Boolean := True ) return String is subtype Sec_int is Long_Integer; -- must contain 86_400 s : constant Sec_int := Sec_int (Calendar.Seconds (T)); m : constant Sec_int := s / 60; -- + 100: trick for obtaining 0x sY : constant String := Integer'Image (Year (T)); sM : constant String := Integer'Image (Month (T) + 100); sD : constant String := Integer'Image (Day (T) + 100); shr : constant String := Sec_int'Image (m / 60 + 100); smn : constant String := Sec_int'Image (m mod 60 + 100); ssc : constant String := Sec_int'Image (s mod 60 + 100); -- function Optional_seconds return String is begin return (if Seconds then ':' & ssc (ssc'Last - 1 .. ssc'Last) else ""); end Optional_seconds; -- -- The "if expression" version of that function -- confuses ObjectAda 10.4. -- -- function Optional_intra_day return String is -- begin -- return -- (if Intra_day then -- " " & shr (shr'Last - 1 .. shr'Last) & ':' & -- smn (smn'Last - 1 .. smn'Last) & Optional_seconds -- else -- ""); -- end Optional_intra_day; function Optional_intra_day return String is begin if Intra_day then return " " & shr (shr'Last - 1 .. shr'Last) & ':' & smn (smn'Last - 1 .. smn'Last) & Optional_seconds; else return ""; end if; end Optional_intra_day; begin return sY (sY'Last - 3 .. sY'Last) & '/' & -- not Year 10'000 compliant. sM (sM'Last - 1 .. sM'Last) & '/' & sD (sD'Last - 1 .. sD'Last) & Optional_intra_day; end Time_display; begin return Time_display (T); end HAC_Image; function To_VString (C : Character) return VString is begin return To_VString ((1 => C)); end To_VString; function Slice (Source : VString; Low : Positive; High : Natural) return VString is begin return +VStr_Pkg.Slice (Source, Low, High); end Slice; function "&" (I : Integer; V : VString) return VString is begin return HAC_Image (I) & V; end "&"; function "&" (V : VString; I : Integer) return VString is begin return V & HAC_Image (I); end "&"; function "&" (R : Real; V : VString) return VString is begin return HAC_Image (R) & V; end "&"; function "&" (V : VString; R : Real) return VString is begin return V & HAC_Image (R); end "&"; function "&" (D : Duration; V : VString) return VString is begin return Image (D) & V; end "&"; function "&" (V : VString; D : Duration) return VString is begin return V & Image (D); end "&"; function Nice_Image (B : Boolean) return VString is img : constant String := Boolean'Image (B); begin return +(img (img'First) & ACH.To_Lower (img (img'First + 1 .. img'Last))); end Nice_Image; function "&" (B : Boolean; V : VString) return VString is begin return Nice_Image (B) & V; end "&"; function "&" (V : VString; B : Boolean) return VString is begin return V & Nice_Image (B); end "&"; function To_Lower (Item : VString) return VString is begin return +Ada.Characters.Handling.To_Lower (VStr_Pkg.To_String (Item)); end To_Lower; function To_Upper (Item : VString) return VString is begin return +Ada.Characters.Handling.To_Upper (VStr_Pkg.To_String (Item)); end To_Upper; function Head (Source : VString; Count : Natural) return VString is begin return VStr_Pkg.Head (Source, Count); -- We use the default padding: ' '. end Head; function Tail (Source : VString; Count : Natural) return VString is begin return VStr_Pkg.Tail (Source, Count); -- We use the default padding: ' '. end Tail; function Head_Before_Match (Source : VString; Pattern : Character) return VString is begin return Head_Before_Match (Source, (1 => Pattern)); end Head_Before_Match; function Head_Before_Match (Source : VString; Pattern : String) return VString is begin return Head_Before_Match (Source, +Pattern); end Head_Before_Match; function Head_Before_Match (Source : VString; Pattern : VString) return VString is i : constant Natural := Index (Source, Pattern); begin return (if i = 0 then Null_VString else Slice (Source, 1, i - 1)); end Head_Before_Match; function Tail_After_Match (Source : VString; Pattern : Character) return VString is begin return Tail_After_Match (Source, (1 => Pattern)); end Tail_After_Match; function Tail_After_Match (Source : VString; Pattern : String) return VString is begin return Tail_After_Match (Source, +Pattern); end Tail_After_Match; function Tail_After_Match (Source : VString; Pattern : VString) return VString is ------------------------------------------------------------------------------ -- Description : Extract a substring from Source starting after the Pattern, -- to the end -- Arguments : String to scan and Search pattern -- Return : A substring from the character after the first Pattern -- found backward to the String's end -- Author : Stephane Riviere, 2021 -- -- Examples : -- -- Tail_After_Match (+"/etc/genesix/gnx-startup", -- +"/")) returns "gnx-startup" -- +"ix")) returns "/gnx-startup" -- +"gene")) returns "six/gnx-startup" -- +"etc/genesix/gnx-startu")) returns "p" -- +"/etc/genesix/gnx-startu")) returns "p" -- +"/etc/genesix/gnx-startup")) returns empty string -- +"/etc/genesix/gnx-startupp")) returns empty string ------------------------------------------------------------------------------ Result : VString := +""; Source_Length : constant Natural := Length (Source); Pattern_Length : constant Natural := Length (Pattern); begin for I in reverse 1 .. Source_Length - Pattern_Length loop if Slice (Source, I, I + Pattern_Length - 1) = Pattern then Result := Slice (Source, I + Pattern_Length, Source_Length); exit; end if; end loop; return Result; end Tail_After_Match; function Starts_With (Item : VString; Pattern : Character) return Boolean is begin return 1 <= Length (Item) and then Element (Item, 1) = Pattern; end Starts_With; function Starts_With (Item : VString; Pattern : String) return Boolean is begin return Pattern'Length <= Length (Item) and then VStr_Pkg.To_String (VStr_Pkg.Head (Item, Pattern'Length)) = Pattern; end Starts_With; function Starts_With (Item : VString; Pattern : VString) return Boolean is begin return Length (Pattern) <= Length (Item) and then VStr_Pkg.Head (Item, Length (Pattern)) = Pattern; end Starts_With; function Ends_With (Item : VString; Pattern : Character) return Boolean is begin return 1 <= Length (Item) and then Element (Item, Length (Item)) = Pattern; end Ends_With; function Ends_With (Item : VString; Pattern : String) return Boolean is begin return Pattern'Length <= Length (Item) and then VStr_Pkg.To_String (VStr_Pkg.Tail (Item, Pattern'Length)) = Pattern; end Ends_With; function Ends_With (Item : VString; Pattern : VString) return Boolean is begin return Length (Pattern) <= Length (Item) and then VStr_Pkg.Tail (Item, Length (Pattern)) = Pattern; end Ends_With; ------------- -- Index -- ------------- function Index (Source : VString; Pattern : Character) return Natural is begin return VStr_Pkg.Index (Source, (1 => Pattern)); end Index; function Index (Source : VString; Pattern : String) return Natural is begin return VStr_Pkg.Index (Source, Pattern); end Index; function Index (Source : VString; Pattern : VString) return Natural is begin return VStr_Pkg.Index (Source, VStr_Pkg.To_String (Pattern)); end Index; function Index (Source : VString; Pattern : Character; From : Positive) return Natural is begin return VStr_Pkg.Index (Source, (1 => Pattern), From); end Index; function Index (Source : VString; Pattern : String; From : Positive) return Natural is begin return VStr_Pkg.Index (Source, Pattern, From); end Index; function Index (Source : VString; Pattern : VString; From : Positive) return Natural is begin return VStr_Pkg.Index (Source, VStr_Pkg.To_String (Pattern), From); end Index; ---------------------- -- Index_Backward -- ---------------------- function Index_Backward (Source : VString; Pattern : Character) return Natural is begin return VStr_Pkg.Index (Source, (1 => Pattern), Ada.Strings.Backward); end Index_Backward; function Index_Backward (Source : VString; Pattern : String) return Natural is begin return VStr_Pkg.Index (Source, Pattern, Ada.Strings.Backward); end Index_Backward; function Index_Backward (Source : VString; Pattern : VString) return Natural is begin return VStr_Pkg.Index (Source, VStr_Pkg.To_String (Pattern), Ada.Strings.Backward); end Index_Backward; function Index_Backward (Source : VString; Pattern : Character; From : Positive) return Natural is begin return VStr_Pkg.Index (Source, (1 => Pattern), From, Ada.Strings.Backward); end Index_Backward; function Index_Backward (Source : VString; Pattern : String; From : Positive) return Natural is begin return VStr_Pkg.Index (Source, Pattern, From, Ada.Strings.Backward); end Index_Backward; function Index_Backward (Source : VString; Pattern : VString; From : Positive) return Natural is begin return VStr_Pkg.Index (Source, VStr_Pkg.To_String (Pattern), From, Ada.Strings.Backward); end Index_Backward; function "*" (Num : Natural; Pattern : String) return VString is begin return +Ada.Strings.Fixed."*" (Num, Pattern); end "*"; function Trim_Left (Source : VString) return VString is begin return VStr_Pkg.Trim (Source, Ada.Strings.Left); end Trim_Left; function Trim_Right (Source : VString) return VString is begin return VStr_Pkg.Trim (Source, Ada.Strings.Right); end Trim_Right; function Trim_Both (Source : VString) return VString is begin return VStr_Pkg.Trim (Source, Ada.Strings.Both); end Trim_Both; function Image (I : Integer) return VString is function HAC_Image_for_Integer is new HAT.HAC_Generic_Image (Abstract_Integer => Integer); begin return +HAC_Image_for_Integer (I); end Image; function Image (F : Real) return VString is begin return +HAC_Image (F); end Image; function Image (T : Ada.Calendar.Time) return VString is begin return +HAC_Image (T); end Image; function Image (D : Duration) return VString is Im : constant String := Duration'Image (D); begin -- Return image without leading ' ' on non-negative values. return (if D < 0.0 then +Im else +Im (Im'First + 1 .. Im'Last)); end Image; function Integer_Value (V : VString) return Integer is begin return Integer'Value (VStr_Pkg.To_String (V)); end Integer_Value; function Float_Value (V : VString) return Real is begin return Real'Value (VStr_Pkg.To_String (V)); end Float_Value; procedure Open (File : in out File_Type; Name : String) is use Ada.Text_IO; begin Open (File, In_File, Name); end Open; procedure Open (File : in out File_Type; Name : VString) is begin Open (File, VStr_Pkg.To_String (Name)); end Open; procedure Create (File : in out File_Type; Name : String) is use Ada.Text_IO; begin Create (File, Out_File, Name); end Create; procedure Create (File : in out File_Type; Name : VString) is begin Create (File, VStr_Pkg.To_String (Name)); end Create; procedure Append (File : in out File_Type; Name : String) is use Ada.Text_IO; begin Open (File, Append_File, Name); end Append; procedure Append (File : in out File_Type; Name : VString) is begin Append (File, VStr_Pkg.To_String (Name)); end Append; --------- -- GET -- --------- procedure Get (I : out Integer) is begin IIO.Get (I); end Get; procedure Get (I : out Interfaces.Integer_64) is begin IIO_64.Get (I); end Get; procedure Get (File : File_Type; I : out Integer) is begin IIO.Get (File, I); end Get; procedure Get (File : File_Type; I : out Interfaces.Integer_64) is begin IIO_64.Get (File, I); end Get; procedure Get (F : out Real) is begin RIO.Get (F); end Get; procedure Get (File : File_Type; F : out Real) is begin RIO.Get (File, F); end Get; -------------- -- GET_LINE -- -------------- procedure Get_Line (C : out Character) is begin Get (C); Skip_Line; end Get_Line; procedure Get_Line (File : File_Type; C : out Character) is begin Get (File, C); Skip_Line (File); end Get_Line; procedure Get_Line (I : out Integer) is begin Get (I); Skip_Line; end Get_Line; procedure Get_Line (I : out Interfaces.Integer_64) is begin Get (I); Skip_Line; end Get_Line; procedure Get_Line (File : File_Type; I : out Integer) is begin Get (File, I); Skip_Line (File); end Get_Line; procedure Get_Line (File : File_Type; I : out Interfaces.Integer_64) is begin Get (File, I); Skip_Line (File); end Get_Line; procedure Get_Line (F : out Real) is begin Get (F); Skip_Line; end Get_Line; procedure Get_Line (File : File_Type; F : out Real) is begin Get (File, F); Skip_Line (File); end Get_Line; procedure Get_Line (V : out VString) is begin V := +Ada.Text_IO.Get_Line; end Get_Line; procedure Get_Line (File : File_Type; V : out VString) is begin V := +Ada.Text_IO.Get_Line (File); end Get_Line; --------- -- PUT -- --------- procedure Put (C : Character) is begin Character'Write (Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Current_Output), C); end Put; procedure Put (File : File_Type; C : Character) is begin Character'Write (Ada.Text_IO.Text_Streams.Stream (File), C); end Put; procedure Put (B : Boolean; Width : Ada.Text_IO.Field := BIO.Default_Width) is begin BIO.Put (B, Width); end Put; procedure Put (File : File_Type; B : Boolean; Width : Ada.Text_IO.Field := BIO.Default_Width) is begin BIO.Put (File, B, Width); end Put; procedure Put (S : in String) is begin String'Write (Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Current_Output), S); end Put; procedure Put (File : File_Type; S : in String) is begin String'Write (Ada.Text_IO.Text_Streams.Stream (File), S); end Put; procedure Put (V : in VString) is begin Put (VStr_Pkg.To_String (V)); end Put; procedure Put (File : File_Type; V : in VString) is begin Put (File, VStr_Pkg.To_String (V)); end Put; -------------- -- PUT_LINE -- -------------- procedure Put_Line (C : Character) is begin Put (C); New_Line; end Put_Line; procedure Put_Line (File : File_Type; C : in Character) is begin Put (File, C); New_Line (File); end Put_Line; procedure Put_Line (I : Integer; Width : Ada.Text_IO.Field := IIO.Default_Width; Base : Ada.Text_IO.Number_Base := IIO.Default_Base) is begin Put (I, Width, Base); New_Line; end Put_Line; procedure Put_Line (File : File_Type; I : Integer; Width : Ada.Text_IO.Field := IIO.Default_Width; Base : Ada.Text_IO.Number_Base := IIO.Default_Base) is begin Put (File, I, Width, Base); New_Line (File); end Put_Line; procedure Put_Line (F : Real; Fore : Integer := RIO.Default_Fore; Aft : Integer := RIO.Default_Aft; Expo : Integer := RIO.Default_Exp) is begin Put (F, Fore, Aft, Expo); New_Line; end Put_Line; procedure Put_Line (File : File_Type; F : Real; Fore : Integer := RIO.Default_Fore; Aft : Integer := RIO.Default_Aft; Expo : Integer := RIO.Default_Exp) is begin Put (File, F, Fore, Aft, Expo); New_Line (File); end Put_Line; procedure Put_Line (B : Boolean; Width : Ada.Text_IO.Field := BIO.Default_Width) is begin Put (B, Width); New_Line; end Put_Line; procedure Put_Line (File : File_Type; B : Boolean; Width : Ada.Text_IO.Field := BIO.Default_Width) is begin Put (File, B, Width); New_Line (File); end Put_Line; procedure Put_Line (V : VString) is begin Put_Line (VStr_Pkg.To_String (V)); end Put_Line; procedure Put_Line (File : File_Type; V : VString) is begin Put_Line (File, VStr_Pkg.To_String (V)); end Put_Line; ---------- -- WAIT -- ---------- procedure Wait (S : Semaphore) is begin raise Program_Error with "WAIT unimplemented"; end Wait; ------------ -- SIGNAL -- ------------ procedure Signal (S : Semaphore) is begin raise Program_Error with "SIGNAL unimplemented"; end Signal; function Argument (Number : Positive) return VString is begin return +Ada.Command_Line.Argument (Number); end Argument; function Command_Name return VString is begin return +Ada.Command_Line.Command_Name; end Command_Name; procedure Set_Exit_Status (Code : in Integer) is begin Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Exit_Status (Code)); end Set_Exit_Status; function Get_Env (Name : String) return VString is use Ada.Environment_Variables; begin return (if Ada.Environment_Variables.Exists (Name) then +Value (Name) else Null_VString); end Get_Env; function Get_Env (Name : VString) return VString is begin return Get_Env (VStr_Pkg.To_String (Name)); end Get_Env; procedure Set_Env (Name : VString; Value : String) is begin Set_Env (VStr_Pkg.To_String (Name), Value); end Set_Env; procedure Set_Env (Name : String; Value : VString) is begin Set_Env (Name, VStr_Pkg.To_String (Value)); end Set_Env; procedure Set_Env (Name : VString; Value : VString) is begin Set_Env (VStr_Pkg.To_String (Name), VStr_Pkg.To_String (Value)); end Set_Env; package String_Maps is new Ada.Containers.Hashed_Maps (Key_Type => VString, Element_Type => VString, Hash => Ada.Strings.Unbounded.Hash, Equivalent_Keys => HAT."=", "=" => HAT."="); -- We emulate here the pool of VM variables attached to the HAC VM. global_VM_variables : String_Maps.Map; function Get_VM_Variable (Name : String) return VString is begin return Get_VM_Variable (+Name); end Get_VM_Variable; function Get_VM_Variable (Name : VString) return VString is cur : constant String_Maps.Cursor := global_VM_variables.Find (Name); use String_Maps; begin return (if cur = String_Maps.No_Element then Null_VString else String_Maps.Element (cur)); end Get_VM_Variable; procedure Set_VM_Variable (Name : String; Value : String) is begin Set_VM_Variable (+Name, +Value); end Set_VM_Variable; procedure Set_VM_Variable (Name : VString; Value : String) is begin Set_VM_Variable (Name, +Value); end Set_VM_Variable; procedure Set_VM_Variable (Name : String; Value : VString) is begin Set_VM_Variable (+Name, Value); end Set_VM_Variable; procedure Set_VM_Variable (Name : VString; Value : VString) is begin global_VM_variables.Include (Name, Value); end Set_VM_Variable; function Current_Directory return VString is begin return +Ada.Directories.Current_Directory; end Current_Directory; procedure Set_Directory (Directory : VString) is begin Set_Directory (VStr_Pkg.To_String (Directory)); end Set_Directory; procedure Copy_File (Source_Name : String; Target_Name : String) is begin Ada.Directories.Copy_File (Source_Name, Target_Name); -- Form: default value "". end Copy_File; procedure Copy_File (Source_Name : VString; Target_Name : String) is begin Copy_File (VStr_Pkg.To_String (Source_Name), Target_Name); end Copy_File; procedure Copy_File (Source_Name : String; Target_Name : VString) is begin Copy_File (Source_Name, VStr_Pkg.To_String (Target_Name)); end Copy_File; procedure Copy_File (Source_Name : VString; Target_Name : VString) is begin Copy_File (VStr_Pkg.To_String (Source_Name), VStr_Pkg.To_String (Target_Name)); end Copy_File; procedure Create_Directory (New_Directory : String) is begin Ada.Directories.Create_Directory (New_Directory); -- Form is left as default. end Create_Directory; procedure Create_Directory (New_Directory : VString) is begin Create_Directory (VStr_Pkg.To_String (New_Directory)); end Create_Directory; procedure Create_Path (New_Path : String) is begin Ada.Directories.Create_Path (New_Path); -- Form is left as default. end Create_Path; procedure Create_Path (New_Path : VString) is begin Create_Path (VStr_Pkg.To_String (New_Path)); end Create_Path; procedure Delete_Directory (Directory : VString) is begin Delete_Directory (VStr_Pkg.To_String (Directory)); end Delete_Directory; procedure Delete_File (Name : VString) is begin Delete_File (VStr_Pkg.To_String (Name)); end Delete_File; function Exists (Name : VString) return Boolean is begin return Exists (VStr_Pkg.To_String (Name)); end Exists; function Directory_Exists (Name : String) return Boolean is use Ada.Directories; begin return Exists (Name) and then Kind (Name) = Directory; end Directory_Exists; function Directory_Exists (Name : VString) return Boolean is begin return Directory_Exists (VStr_Pkg.To_String (Name)); end Directory_Exists; function File_Exists (Name : String) return Boolean is use Ada.Directories; begin return Exists (Name) and then Kind (Name) = Ordinary_File; end File_Exists; function File_Exists (Name : VString) return Boolean is begin return File_Exists (VStr_Pkg.To_String (Name)); end File_Exists; procedure Rename (Old_Name : VString; New_Name : String) is begin Rename (VStr_Pkg.To_String (Old_Name), New_Name); end Rename; procedure Rename (Old_Name : String; New_Name : VString) is begin Rename (Old_Name, VStr_Pkg.To_String (New_Name)); end Rename; procedure Rename (Old_Name : VString; New_Name : VString) is begin Rename (VStr_Pkg.To_String (Old_Name), VStr_Pkg.To_String (New_Name)); end Rename; function HAC_Generic_Image (I : Abstract_Integer) return String is Im : constant String := Abstract_Integer'Image (I); begin -- Return image without leading ' ' on non-negative values. return (if I < 0 then Im else Im (Im'First + 1 .. Im'Last)); end HAC_Generic_Image; largest_without_exponent : constant := 10.0 ** (Real'Digits - 1); function HAC_Image (F : Real) return String is -- Code from TeXCAD (tc.adb, TeX_Number), -- less a few simplifications. s : String (1 .. Real'Digits + 15); na, nb, np, ne : Natural; function Image_with_exponent return String is begin RIO.Put (s, F); na := s'First; for i in s'Range loop case s (i) is when ' ' => na := i + 1; -- * Trim spaces on the left when others => null; end case; end loop; ne := Ada.Strings.Fixed.Index (s, "0E"); if ne > 0 then -- Simplify "4.56000000000000E+68" into "4.56E+68". -- * Remove extra '0's... nb := ne - 1; while s (nb) = '0' loop nb := nb - 1; end loop; if s (nb) = '.' then -- "4.E+68" from "4.00000000000000E+68" would be too much trimming... nb := nb + 1; -- We keep one '0' -> "4.0E+68". end if; return s (na .. nb) & s (ne + 1 .. s'Last); end if; return s (na .. s'Last); end Image_with_exponent; -- function Count_Nonzero_Digits (any : String) return Natural is n : Natural := 0; begin for c of any loop exit when c = 'E'; -- Ignore exponent part. if c in '1' .. '9' then n := n + 1; end if; end loop; return n; end Count_Nonzero_Digits; begin if abs F >= largest_without_exponent then return Image_with_exponent; end if; -- Image without exponent (E). -- If the number is too large for this layout, the Layout_Error -- exception is raised and we call Image_with_exponent. RIO.Put (s, F, Exp => 0); declare F_image : constant String := Real'Image (F); tolerance : constant := 1; begin if Count_Nonzero_Digits (s) + tolerance < Count_Nonzero_Digits (F_image) then return Image_with_exponent; -- Significant loss of significant digits. -- Typically 6.62607015e-34 is displayed as 0.0[0] unless the -- type Real has a 34 digits precision (unlikely...). See Strings test. -- The tolerance is due to the case where s is, e.g., "123.4567890" -- and F_image is "1.234567891E+02". Spot the last significant -- digit: '0' vs. '1'. Such an accuracy error is normal. end if; end; -- We don't want to lose any digit in the decimal representation without exponent. na := s'First; nb := s'Last; np := 0; for i in s'Range loop case s (i) is when '.' => np := i; exit; -- Find a decimal point when ' ' => na := i + 1; -- * Trim spaces on the left when others => null; end case; end loop; if np > 0 then -- In case of a decimal point. while nb > np + 1 and then s (nb) = '0' loop nb := nb - 1; -- * Remove extra '0's except for "x.0" end loop; end if; return s (na .. nb); exception when Ada.Text_IO.Layout_Error => -- Number too large, we fall back to show the version with exponent. return Image_with_exponent; end HAC_Image; package Non_Standard is procedure Sys (Command : String; Result : out Integer); function Directory_Separator return Character; end Non_Standard; package body Non_Standard is separate; procedure Shell_Execute (Command : String; Result : out Integer) is -- https://rosettacode.org/wiki/Execute_a_system_command#Ada begin Non_Standard.Sys (Command, Result); end Shell_Execute; procedure Shell_Execute (Command : VString; Result : out Integer) is begin Shell_Execute (VStr_Pkg.To_String (Command), Result); end Shell_Execute; procedure Shell_Execute (Command : String) is Dummy : Integer; begin Shell_Execute (Command, Dummy); end Shell_Execute; procedure Shell_Execute (Command : VString) is begin Shell_Execute (VStr_Pkg.To_String (Command)); end Shell_Execute; -- Versions with outward piping: procedure Shell_Execute (Command : String; Result : out Integer; Output : out VString) is package SIO renames Ada.Streams.Stream_IO; temp_1, temp_2 : SIO.File_Type; begin SIO.Create (temp_1, SIO.Out_File, ""); declare temp_name_2 : constant String := SIO.Name (temp_1) & "_shell_exec.tmp"; begin Non_Standard.Sys (Command & '>' & temp_name_2, Result); if Exists (temp_name_2) then SIO.Open (temp_2, SIO.In_File, temp_name_2); declare size : constant SIO.Count := SIO.Size (temp_2); buffer : String (1 .. Natural (size)); begin if SIO.">" (size, 0) then String'Read (SIO.Stream (temp_2), buffer); Output := To_VString (buffer); else Output := Null_VString; end if; end; SIO.Delete (temp_2); else Output := Null_VString; end if; end; SIO.Close (temp_1); end Shell_Execute; procedure Shell_Execute (Command : VString; Result : out Integer; Output : out VString) is begin Shell_Execute (VStr_Pkg.To_String (Command), Result, Output); end Shell_Execute; procedure Shell_Execute (Command : String; Output : out VString) is Dummy : Integer; begin Shell_Execute (Command, Dummy, Output); end Shell_Execute; procedure Shell_Execute (Command : VString; Output : out VString) is begin Shell_Execute (VStr_Pkg.To_String (Command), Output); end Shell_Execute; function Directory_Separator return Character is begin return Non_Standard.Directory_Separator; end Directory_Separator; function Search_File (simple_file_name, path : String) return String is sep_pos : Natural := path'First - 1; new_sep_pos : Natural; begin for i in path'Range loop new_sep_pos := sep_pos; if path (i) in ',' | ';' then new_sep_pos := i; elsif i = path'Last then new_sep_pos := i + 1; end if; if new_sep_pos > sep_pos then declare full_file_name : constant String := path (sep_pos + 1 .. new_sep_pos - 1) & HAT.Directory_Separator & simple_file_name; begin if HAT.Exists (full_file_name) then return full_file_name; end if; end; end if; sep_pos := new_sep_pos; end loop; return ""; end Search_File; begin pragma Assert (Real'Digits >= Interfaces.IEEE_Float_64'Digits, "HAT.Real must have at least the precision of IEEE Double Precision"); Ada.Numerics.Float_Random.Reset (gen); -- Randomize. end HAT; ================================================ FILE: src/hat.ads ================================================ -- HAT - HAC Ada Toolbox ------------------------- -- -- The HAT package and possible children contains definitions -- that are useful for HAC in its minimal operating mode. -- -- HAT is compilable by a "full Ada" compiler like GNAT or ObjectAda, -- so the HAC programs can be run on both HAC and a full Ada system. -- -- Another purpose of this specification is to have a document, -- automatically verified by "full Ada" systems, of the standard types -- and subprograms available in HAC. -- -- Furthermore, some items of HAT are used in the HAC virtual machine. -- See occurrences of "HAT" in HAC.PCode.Interpreter's body. ------------------------ -- -- Legal licensing note: -- -- Copyright (c) 2020 .. 2024 Gautier de Montmollin -- -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be included in -- all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -- NB: this is the MIT License, as found 12-Sep-2013 on the site -- http://www.opensource.org/licenses/mit-license.php -- ------------------------------------------------------------------------------------- -- with Ada.Calendar, Ada.Characters.Handling, Ada.Command_Line, Ada.Directories, Ada.Environment_Variables, Ada.Numerics, Ada.Strings.Unbounded, Ada.Text_IO; with Interfaces; with System; -- Disable GNAT warning: declaration of "=" hides predefined operator. pragma Warnings ("H"); package HAT is ----------------------------------------- -- Floating-point numeric type: Real -- ----------------------------------------- type Real is digits System.Max_Digits; package RIO is new Ada.Text_IO.Float_IO (Real); function "**" (F1, F2 : Real) return Real with Inline; -- Square Root function Sqrt (I : Integer) return Real with Inline; function Sqrt (F : Real) return Real with Inline; -- Integer to Character (equivalent to Character'Val (I)) function Chr (I : Integer) return Character with Inline; -- Character to Integer (equivalent to Character'Pos (C)) function Ord (C : Character) return Integer with Inline; -- Next Character (equivalent to Character'Succ (C)) function Succ (C : Character) return Character with Inline; -- Previous Character (equivalent to Character'Pred (C)) function Pred (C : Character) return Character with Inline; -- Round to an Integer (equivalent to Integer (F)) function Round (F : Real) return Integer with Inline; -- Truncate function Trunc (F : Real) return Integer with Inline; -- Min & Max function Min (I, J : Integer) return Integer renames Integer'Min; function Max (I, J : Integer) return Integer renames Integer'Max; function Min (I, J : Interfaces.Integer_64) return Interfaces.Integer_64 renames Interfaces.Integer_64'Min; function Max (I, J : Interfaces.Integer_64) return Interfaces.Integer_64 renames Interfaces.Integer_64'Max; function Min (F, G : Real) return Real renames Real'Min; function Max (F, G : Real) return Real renames Real'Max; Pi : constant := Ada.Numerics.Pi; -- Trigonometric functions w/ arguments in radians function Sin (F : Real) return Real with Inline; function Cos (F : Real) return Real with Inline; function Arctan (F : Real) return Real with Inline; -- Logarithmic / Exponential functions function Log (F : Real) return Real with Inline; function Exp (F : Real) return Real with Inline; -- Sign function function Sgn (I : Integer) return Integer with Inline; function Sgn (F : Real) return Real with Inline; ----------------------------- -- Pseudo-random numbers -- ----------------------------- -- Pseudo-random number in the real range [0, I+1[ , truncated to lowest -- integer. For example, Rand (10) returns equiprobable integer values -- from 0 to 10 (so, there are 11 possible values). function Rand (I : Integer) return Integer; -- Pseudo-random number from 0 to 1, uniform. function Rnd return Real; procedure Randomize; procedure Random_Seed (New_Seed : Positive); -- package IIO is new Ada.Text_IO.Integer_IO (Integer); package IIO_64 is new Ada.Text_IO.Integer_IO (Interfaces.Integer_64); package BIO is new Ada.Text_IO.Enumeration_IO (Boolean); ------------------------------------------ -- Variable-size string type: VString -- ------------------------------------------ package VStr_Pkg renames Ada.Strings.Unbounded; -- Could use XStrings instead. subtype VString is VStr_Pkg.Unbounded_String; Null_VString : VString renames VStr_Pkg.Null_Unbounded_String; function To_VString (S : String) return VString renames VStr_Pkg.To_Unbounded_String; function To_VString (C : Character) return VString; function To_String (V : VString) return String renames VStr_Pkg.To_String; package ACH renames Ada.Characters.Handling; -- procedure Delete (Source : in out VString; From : Positive; Through : Natural) renames VStr_Pkg.Delete; function Element (Source : VString; Index : Positive) return Character renames VStr_Pkg.Element; function Ends_With (Item : VString; Pattern : Character) return Boolean; function Ends_With (Item : VString; Pattern : String) return Boolean; function Ends_With (Item : VString; Pattern : VString) return Boolean; function Head (Source : VString; Count : Natural) return VString; -- function Index (Source : VString; Pattern : Character) return Natural; function Index (Source : VString; Pattern : String) return Natural; function Index (Source : VString; Pattern : VString) return Natural; function Index (Source : VString; Pattern : Character; From : Positive) return Natural; function Index (Source : VString; Pattern : String; From : Positive) return Natural; function Index (Source : VString; Pattern : VString; From : Positive) return Natural; -- function Index_Backward (Source : VString; Pattern : Character) return Natural; function Index_Backward (Source : VString; Pattern : String) return Natural; function Index_Backward (Source : VString; Pattern : VString) return Natural; function Index_Backward (Source : VString; Pattern : Character; From : Positive) return Natural; function Index_Backward (Source : VString; Pattern : String; From : Positive) return Natural; function Index_Backward (Source : VString; Pattern : VString; From : Positive) return Natural; -- function Length (Source : VString) return Natural renames VStr_Pkg.Length; function Slice (Source : VString; Low : Positive; High : Natural) return VString; function Starts_With (Item : VString; Pattern : Character) return Boolean; function Starts_With (Item : VString; Pattern : String) return Boolean; function Starts_With (Item : VString; Pattern : VString) return Boolean; function Tail (Source : VString; Count : Natural) return VString; -- Head_Before_Match returns the head of Source preceding first occurrence of Pattern. -- The result is empty if Pattern is not found. function Head_Before_Match (Source : VString; Pattern : Character) return VString; function Head_Before_Match (Source : VString; Pattern : String) return VString; function Head_Before_Match (Source : VString; Pattern : VString) return VString; -- Tail_After_Match returns the tail of Source following last occurrence of Pattern. -- The result is empty if Pattern is not found. function Tail_After_Match (Source : VString; Pattern : Character) return VString; function Tail_After_Match (Source : VString; Pattern : String) return VString; function Tail_After_Match (Source : VString; Pattern : VString) return VString; function To_Lower (Item : Character) return Character renames ACH.To_Lower; -- RM A.3.2 (6) function To_Upper (Item : Character) return Character renames ACH.To_Upper; -- RM A.3.2 (6) function To_Lower (Item : VString) return VString; function To_Upper (Item : VString) return VString; function Trim_Left (Source : VString) return VString; function Trim_Right (Source : VString) return VString; function Trim_Both (Source : VString) return VString; -- function "+" (S : String) return VString renames To_VString; function "+" (C : Character) return VString renames To_VString; function "-" (V : VString) return String renames To_String; -- function "*" (Num : Natural; Pattern : Character) return VString renames VStr_Pkg."*"; function "*" (Num : Natural; Pattern : String) return VString; function "*" (Num : Natural; Pattern : VString) return VString renames VStr_Pkg."*"; -- function "&" (V1, V2 : VString) return VString renames VStr_Pkg."&"; -- function "&" (V : VString; S : String) return VString renames VStr_Pkg."&"; function "&" (S : String; V : VString) return VString renames VStr_Pkg."&"; -- function "&" (V : VString; C : Character) return VString renames VStr_Pkg."&"; function "&" (C : Character; V : VString) return VString renames VStr_Pkg."&"; -- function "&" (I : Integer; V : VString) return VString; function "&" (V : VString; I : Integer) return VString; -- function "&" (R : Real; V : VString) return VString; function "&" (V : VString; R : Real) return VString; -- function "&" (D : Duration; V : VString) return VString; function "&" (V : VString; D : Duration) return VString; -- function "&" (B : Boolean; V : VString) return VString; function "&" (V : VString; B : Boolean) return VString; -- function "=" (Left, Right : VString) return Boolean renames VStr_Pkg."="; function "<" (Left, Right : VString) return Boolean renames VStr_Pkg."<"; function "<=" (Left, Right : VString) return Boolean renames VStr_Pkg."<="; function ">" (Left, Right : VString) return Boolean renames VStr_Pkg.">"; function ">=" (Left, Right : VString) return Boolean renames VStr_Pkg.">="; -- function "=" (Left : VString; Right : String) return Boolean renames VStr_Pkg."="; function "<" (Left : VString; Right : String) return Boolean renames VStr_Pkg."<"; function "<=" (Left : VString; Right : String) return Boolean renames VStr_Pkg."<="; function ">" (Left : VString; Right : String) return Boolean renames VStr_Pkg.">"; function ">=" (Left : VString; Right : String) return Boolean renames VStr_Pkg.">="; function Image (I : Integer) return VString; function Image (F : Real) return VString; -- "nice" image of F function Image (T : Ada.Calendar.Time) return VString; function Image (D : Duration) return VString; function Integer_Value (V : VString) return Integer; function Float_Value (V : VString) return Real; ------------------------- -- Text Input/Output -- -- 1) Console I/O -- ------------------------- -- We have a real console/terminal input where several -- inputs can be made on the same line, followed by a -- "Return". It behaves like for a file. Actually it -- *could* be a file, if run like this: prog ; function HAC_Generic_Image (I : Abstract_Integer) return String; function HAC_Image (F : Real) return String; function HAC_Image (T : Ada.Calendar.Time) return String; function Search_File (simple_file_name, path : String) return String; private -- type SEMAPHORE is new INTEGER; end HAT; ================================================ FILE: src/manage/hac_sys-files-default.adb ================================================ with Ada.Directories, Ada.Text_IO.Text_Streams, Ada.Unchecked_Deallocation; package body HAC_Sys.Files.Default is overriding function Exists (cat : File_Catalogue; name : String) return Boolean is begin return Ada.Directories.Exists (name); exception when others => return False; end Exists; overriding function Full_Source_Name (cat : File_Catalogue; name : String) return String is begin return Ada.Directories.Full_Name (name); end Full_Source_Name; overriding function Full_Spec_Source_Name (cat : File_Catalogue; name : String) return String is other_name : String := name; begin if name'Length > 0 then other_name (other_name'Last) := 's'; -- GNAT convention: .ads for spec. end if; return other_name; end Full_Spec_Source_Name; overriding function Full_Body_Source_Name (cat : File_Catalogue; name : String) return String is other_name : String := name; begin if name'Length > 0 then other_name (other_name'Last) := 'b'; -- GNAT convention: .adb for body. end if; return other_name; end Full_Body_Source_Name; overriding function Is_Open (cat : File_Catalogue; name : String) return Boolean is file : Text_File_Access; begin if cat.read_open_map.Contains (name) then file := cat.read_open_map.Element (name); if file /= null then return Ada.Text_IO.Is_Open (file.all); end if; end if; return False; end Is_Open; overriding procedure Source_Open (cat : in out File_Catalogue; name : in String; stream : out Root_Stream_Class_Access) is new_file : Text_File_Access; begin if cat.read_open_map.Contains (name) then raise Constraint_Error with "Attempt to re-open file named """ & name & '"'; end if; new_file := new Ada.Text_IO.File_Type; cat.read_open_map.Insert (name, new_file); Ada.Text_IO.Open (new_file.all, Ada.Text_IO.In_File, name); stream := Root_Stream_Class_Access (Ada.Text_IO.Text_Streams.Stream (new_file.all)); end Source_Open; overriding procedure Skip_Shebang (cat : in out File_Catalogue; name : in String; shebang_offset : out Natural) is file : Text_File_Access; begin shebang_offset := 0; if cat.read_open_map.Contains (name) then file := cat.read_open_map.Element (name); if file /= null and then Ada.Text_IO.Is_Open (file.all) and then not Ada.Text_IO.End_Of_File (file.all) then declare possible_shebang : constant String := Ada.Text_IO.Get_Line (file.all); begin if possible_shebang'Length >= 2 and then possible_shebang (possible_shebang'First .. possible_shebang'First + 1) = "#!" then -- Ignore the first line, but count it. shebang_offset := 1; else -- Uh-oh: not a shebang. Then we need to reset the file. Ada.Text_IO.Reset (file.all); end if; end; end if; end if; end Skip_Shebang; overriding procedure Close (cat : in out File_Catalogue; name : String) is procedure Free is new Ada.Unchecked_Deallocation (Ada.Text_IO.File_Type, Text_File_Access); file : Text_File_Access; begin -- Permissive implementation: -- OK if file is unknown to catalogue or not open. if cat.read_open_map.Contains (name) then file := cat.read_open_map.Element (name); if file /= null then if Ada.Text_IO.Is_Open (file.all) then Ada.Text_IO.Close (file.all); end if; Free (file); end if; cat.read_open_map.Delete (name); end if; end Close; end HAC_Sys.Files.Default; ================================================ FILE: src/manage/hac_sys-files-default.ads ================================================ with Ada.Containers.Indefinite_Hashed_Maps, Ada.Strings.Hash, Ada.Text_IO; package HAC_Sys.Files.Default is -- This implementation deals with "physical" text files, without a search path. type File_Catalogue is limited new Files.Abstract_File_Catalogue with private; overriding function Exists (cat : File_Catalogue; name : String) return Boolean; overriding function Full_Source_Name (cat : File_Catalogue; name : String) return String; overriding function Full_Spec_Source_Name (cat : File_Catalogue; name : String) return String; overriding function Full_Body_Source_Name (cat : File_Catalogue; name : String) return String; overriding function Is_Open (cat : File_Catalogue; name : String) return Boolean; overriding procedure Source_Open (cat : in out File_Catalogue; name : in String; stream : out Root_Stream_Class_Access); overriding procedure Skip_Shebang (cat : in out File_Catalogue; name : in String; shebang_offset : out Natural); overriding procedure Close (cat : in out File_Catalogue; name : String); overriding procedure Add_to_Source_Path (cat : in out File_Catalogue; new_dir : String) is null; -- No search path by default. private type Text_File_Access is access Ada.Text_IO.File_Type; package Default_File_Name_Mapping is new Ada.Containers.Indefinite_Hashed_Maps (Key_Type => String, Element_Type => Text_File_Access, Hash => Ada.Strings.Hash, Equivalent_Keys => "="); type File_Catalogue is limited new Files.Abstract_File_Catalogue with record read_open_map : Default_File_Name_Mapping.Map; end record; end HAC_Sys.Files.Default; ================================================ FILE: src/manage/hac_sys-files.ads ================================================ with Ada.Streams.Stream_IO; package HAC_Sys.Files is -- This package deals with files in a broad sense. -- -- A file can be, for instance: -- - in the operating system's file system, in current directory -- - in one of a set of directories (a search path) -- - a remote file accessed through the Internet -- - in one or more Zip archives (.har) -- - in a database -- - in a set of open editor windows, with or without -- a "physical" file (see the LEA project as an example). -- -- In the last four examples, it could be that the "physical" file -- cannot be accessed via Ada.*_IO, or doesn't even exists. subtype Root_Stream_Class_Access is Ada.Streams.Stream_IO.Stream_Access; type Abstract_File_Catalogue is limited interface; type Abstract_File_Catalogue_Reference is access all Abstract_File_Catalogue'Class; function Exists (cat : Abstract_File_Catalogue; name : String) return Boolean is abstract; function Full_Source_Name (cat : Abstract_File_Catalogue; name : String) return String is abstract; function Full_Spec_Source_Name (cat : Abstract_File_Catalogue; name : String) return String is abstract; function Full_Body_Source_Name (cat : Abstract_File_Catalogue; name : String) return String is abstract; function Is_Open (cat : Abstract_File_Catalogue; name : String) return Boolean is abstract; -- A source file is a text and its search path -- may be specific to source files. -- procedure Source_Open (cat : in out Abstract_File_Catalogue; name : in String; stream : out Root_Stream_Class_Access) is abstract; -- Skip a possible shebang line (such as "#!/usr/bin/env hac") that may -- exist as first line of a main unit's source file. -- -- shebang_offset = 0 if no shebang was found, -- shebang_offset = 1 if a shebang was found. -- procedure Skip_Shebang (cat : in out Abstract_File_Catalogue; name : in String; shebang_offset : out Natural) is abstract; procedure Close (cat : in out Abstract_File_Catalogue; name : String) is abstract; -- Inform the File Catalogue that it may have to search a supplemental -- directory. -- It happens for instance on the "--!hac_add_to_path " special comment -- within a HAC program. -- procedure Add_to_Source_Path (cat : in out Abstract_File_Catalogue; new_dir : String) is abstract; end HAC_Sys.Files; ================================================ FILE: src/manage/hac_sys-librarian-built_in_packages.adb ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Defs, HAC_Sys.Compiler.PCode_Emit, HAC_Sys.Parser.Packages; with HAT; with Interfaces; package body HAC_Sys.Librarian.Built_In_Packages is procedure Enter_and_Register_Built_In_Package ( CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data; name : in String ) is use Co_Defs, Defs; unit : Library_Unit := (full_name => HAT.To_VString (name), kind => Package_Declaration, status => Done, id_index => No_Id, id_body_index => No_Id, spec_context => Co_Defs.Id_Maps.Empty_Map); begin Enter_Library_Level_Def (CD, name, paquetage, NOTYP, 0, is_built_in => True); Parser.Packages.Feed_Packages_Table (CD); -- Feed library: unit.id_index := CD.Id_Count; Register_Unit (LD, unit); end Enter_and_Register_Built_In_Package; procedure Define_and_Register_Standard ( CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data ) is use Co_Defs, Defs; procedure Enter_Std_Typ (Name : String; T : Typen; First, Last : HAC_Integer) is begin Enter_Library_Level_Def (CD, "Standard." & Name, type_mark, T, 1, First, Last, True); end Enter_Std_Typ; begin Enter_Library_Level_Def (CD, "", constant_object, NOTYP, 0); -- Unreachable Id with invalid Link. -- Enter_and_Register_Built_In_Package (CD, LD, "Standard"); -- Enter_Library_Level_Def (CD, "Standard.False", declared_number_or_enum_item, Bools, 0, is_built_in => True); Enter_Library_Level_Def (CD, "Standard.True", declared_number_or_enum_item, Bools, 1, is_built_in => True); -- Enter_Std_Typ ("Character", Chars, 0, 255); Enter_Std_Typ ("Boolean", Bools, 0, 1); Enter_Std_Typ (HAC_Integer_Name, Ints, HAC_Integer'First, HAC_Integer'Last); -- -- The "String" type identifier is treated separately in the Type_Definition parser -- and returns a constrained array of Character. -- Here we just reserve the "String" identifier at library level, with a bogus base, -- type String_Literals, which is actually used only for string literals like "abcd". Enter_Std_Typ ("String", String_Literals, 0, 0); CD.String_Id_Index := CD.Id_Count; -- Enter_Std_Typ ("Natural", Ints, 0, HAC_Integer'Last); Enter_Std_Typ ("Positive", Ints, 1, HAC_Integer'Last); Enter_Std_Typ ("Duration", Durations, 0, 0); -- CD.Packages_Table (CD.Packages_Count).last_public_declaration := CD.Id_Count; end Define_and_Register_Standard; procedure Define_and_Register_Interfaces ( CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data ) is use Co_Defs, Defs, Interfaces; procedure Enter_Interfaces_Typ (Name : String; T : Typen; First, Last : HAC_Integer) is begin Enter_Library_Level_Def (CD, "Interfaces." & Name, type_mark, T, 1, First, Last, True); end Enter_Interfaces_Typ; begin Enter_and_Register_Built_In_Package (CD, LD, "Interfaces"); -- Enter_Interfaces_Typ ("Integer_64", Ints, -2**63, 2**63 - 1); Enter_Interfaces_Typ ("Integer_32", Ints, -2**31, 2**31 - 1); Enter_Interfaces_Typ ("Integer_16", Ints, -2**15, 2**15 - 1); Enter_Interfaces_Typ ("Integer_8", Ints, -2**7, 2**7 - 1); -- CD.Packages_Table (CD.Packages_Count).last_public_declaration := CD.Id_Count; end Define_and_Register_Interfaces; procedure Define_and_Register_HAT ( CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data ) is use Co_Defs, Defs; procedure Enter_HAT_Const (Name : String; Value : HAC_Float) is Float_Index : Integer; begin Compiler.PCode_Emit.Enter_or_find_Float (CD, Value, Float_Index); Enter_Library_Level_Def (CD, HAT_Name & '.' & Name, declared_number_or_enum_item, Floats, Float_Index, is_built_in => True); end Enter_HAT_Const; procedure Enter_HAT_Typ (Name : String; T : Typen; First, Last : HAC_Integer) is begin Enter_Library_Level_Def (CD, HAT_Name & '.' & Name, type_mark, T, 1, First, Last, True); end Enter_HAT_Typ; procedure Enter_HAT_Funct (Name : String; T : Typen; Code : Defs.SF_Code) is begin Enter_Library_Level_Def (CD, HAT_Name & '.' & Name, funktion_intrinsic, T, Defs.SF_Code'Pos (Code), is_built_in => True); end Enter_HAT_Funct; procedure Enter_HAT_Proc (Name : String; Code : Defs.SP_Code) is begin Enter_Library_Level_Def (CD, HAT_Name & '.' & Name, prozedure_intrinsic, NOTYP, Defs.SP_Code'Pos (Code), is_built_in => True); end Enter_HAT_Proc; begin Enter_and_Register_Built_In_Package (CD, LD, HAT_Name); -- Enter_HAT_Typ ("File_Type", Text_Files, 0, 0); -- 2020.05.17 Enter_HAT_Typ (HAC_Float_Name, Floats, 0, 0); -- Moved from Std 2021.12.26 Enter_HAT_Typ ("Semaphore", Ints, 0, 0); Enter_HAT_Typ ("Time", Times, 0, 0); Enter_HAT_Typ ("VString", VStrings, 0, 0); -- 2020.05.02 -- -- Standard functions -- Enter_HAT_Funct ("Chr", Chars, SF_T_Val); -- S'Val : RM 3.5.5 (5) Enter_HAT_Funct ("Ord", Ints, SF_T_Pos); -- S'Pos : RM 3.5.5 (2) Enter_HAT_Funct ("Succ", Chars, SF_T_Succ); -- S'Succ : RM 3.5 (22) Enter_HAT_Funct ("Pred", Chars, SF_T_Pred); -- S'Pred : RM 3.5 (25) -- Enter_HAT_Funct ("Round", Ints, SF_Round_Float_to_Int); Enter_HAT_Funct ("Trunc", Ints, SF_Trunc_Float_to_Int); -- Enter_HAT_Funct ("Min", Ints, SF_Min_Int); -- Overloaded for floats Enter_HAT_Funct ("Max", Ints, SF_Max_Int); -- Overloaded for floats -- Enter_HAT_Const ("Pi", HAT.Pi); Enter_HAT_Funct ("Sin", Floats, SF_Sin); Enter_HAT_Funct ("Cos", Floats, SF_Cos); Enter_HAT_Funct ("Exp", Floats, SF_Exp); Enter_HAT_Funct ("Log", Floats, SF_Log); Enter_HAT_Funct ("Sqrt", Floats, SF_Sqrt); Enter_HAT_Funct ("Arctan", Floats, SF_Arctan); Enter_HAT_Funct ("Sgn", Ints, SF_Sgn_Int); -- Overloaded for floats -- Enter_HAT_Funct ("Rand", Ints, SF_Random_Int); Enter_HAT_Funct ("Rnd", Floats, SF_Random_Float); Enter_HAT_Proc ("Randomize", SP_Randomize); Enter_HAT_Proc ("Random_Seed", SP_Random_Seed); Enter_HAT_Funct ("Clock", Times, SF_Clock); -- Enter_HAT_Funct ("Null_VString", VStrings, SF_Null_VString); Enter_HAT_Funct ("Element", Chars, SF_Element); Enter_HAT_Funct ("Index", Ints, SF_Index); Enter_HAT_Funct ("Index_Backward", Ints, SF_Index_Backward); Enter_HAT_Funct ("Length", Ints, SF_Length); Enter_HAT_Funct ("Slice", VStrings, SF_Slice); Enter_HAT_Funct ("To_Lower", Chars, SF_To_Lower_Char); Enter_HAT_Funct ("To_Upper", Chars, SF_To_Upper_Char); Enter_HAT_Funct ("To_VString", VStrings, SF_String_Literal_to_VString); Enter_HAT_Funct ("To_String", Strings_as_VStrings, SF_VString_to_String); -- Enter_HAT_Funct ("Trim_Left", VStrings, SF_Trim_Left); Enter_HAT_Funct ("Trim_Right", VStrings, SF_Trim_Right); Enter_HAT_Funct ("Trim_Both", VStrings, SF_Trim_Both); -- Enter_HAT_Funct ("Head", VStrings, SF_Head); Enter_HAT_Funct ("Head_Before_Match", VStrings, SF_Head_Before_Match); Enter_HAT_Funct ("Tail", VStrings, SF_Tail); Enter_HAT_Funct ("Tail_After_Match", VStrings, SF_Tail_After_Match); Enter_HAT_Funct ("Starts_With", Bools, SF_Starts_With); Enter_HAT_Funct ("Ends_With", Bools, SF_Ends_With); -- -- Ada.Calendar-like functions -- Enter_HAT_Funct ("Year", Ints, SF_Year); Enter_HAT_Funct ("Month", Ints, SF_Month); Enter_HAT_Funct ("Day", Ints, SF_Day); Enter_HAT_Funct ("Seconds", Durations, SF_Seconds); -- -- Attribute-like functions -- Enter_HAT_Funct ("Image", VStrings, SF_Image_Ints); Enter_HAT_Funct ("Integer_Value", Ints, SF_Integer_Value); Enter_HAT_Funct ("Float_Value", Floats, SF_Float_Value); -- -- Ada.Command_Line & Ada.Environment_Variables - like functions -- Enter_HAT_Funct ("Argument_Count", Ints, SF_Argument_Count); Enter_HAT_Funct ("Argument", VStrings, SF_Argument); Enter_HAT_Funct ("Command_Name", VStrings, SF_Command_Name); Enter_HAT_Funct ("Get_Env", VStrings, SF_Get_Env); Enter_HAT_Funct ("Get_VM_Variable", VStrings, SF_Get_VM_Variable); -- -- Ada.Directories-like functions -- Enter_HAT_Funct ("Current_Directory", VStrings, SF_Current_Directory); Enter_HAT_Funct ("Directory_Exists", Bools, SF_Directory_Exists); Enter_HAT_Funct ("Exists", Bools, SF_Exists); Enter_HAT_Funct ("File_Exists", Bools, SF_File_Exists); -- This one is *not* in Ada.Directories: Enter_HAT_Funct ("Directory_Separator", Chars, SF_Directory_Separator); -- Enter_HAT_Funct ("Get_Needs_Skip_Line", Bools, SF_Get_Needs_Skip_Line); -- -- Ada.Text_IO-like subprograms -- Enter_HAT_Proc ("Create", SP_Create); Enter_HAT_Proc ("Open", SP_Open); Enter_HAT_Proc ("Append", SP_Append); Enter_HAT_Proc ("Close", SP_Close); Enter_HAT_Proc ("Get", SP_Get); Enter_HAT_Proc ("Get_Immediate", SP_Get_Immediate); Enter_HAT_Proc ("Get_Line", SP_Get_Line); Enter_HAT_Proc ("Skip_Line", SP_Skip_Line); Enter_HAT_Proc ("Put", SP_Put); Enter_HAT_Proc ("Put_Line", SP_Put_Line); Enter_HAT_Proc ("New_Line", SP_New_Line); Enter_HAT_Funct ("End_Of_File", Bools, SF_EOF); Enter_HAT_Funct ("End_Of_Line", Bools, SF_EOLN); Enter_HAT_Funct ("Is_Open", Bools, SF_Is_Open); -- -- Ada.Environment_Variables-like procedures -- Enter_HAT_Proc ("Set_Env", SP_Set_Env); Enter_HAT_Proc ("Set_VM_Variable", SP_Set_VM_Variable); -- -- Ada.Directories-like procedures -- Enter_HAT_Proc ("Copy_File", SP_Copy_File); Enter_HAT_Proc ("Create_Directory", SP_Create_Directory); Enter_HAT_Proc ("Create_Path", SP_Create_Path); Enter_HAT_Proc ("Delete_Directory", SP_Delete_Directory); Enter_HAT_Proc ("Delete_File", SP_Delete_File); Enter_HAT_Proc ("Rename", SP_Rename); Enter_HAT_Proc ("Set_Directory", SP_Set_Directory); -- Enter_HAT_Proc ("Shell_Execute", SP_Shell_Execute_with_Result); Enter_HAT_Proc ("Set_Exit_Status", SP_Set_Exit_Status); -- -- Ada.Strings.Unbounded-like procedures -- Enter_HAT_Proc ("Delete", SP_Delete); -- -- Tasking related (from SmallAda) -- Enter_HAT_Proc ("Wait", SP_Wait); Enter_HAT_Proc ("Signal", SP_Signal); Enter_HAT_Proc ("Quantum", SP_Quantum); Enter_HAT_Proc ("Priority", SP_Priority); Enter_HAT_Proc ("InheritP", SP_InheritP); -- CD.Packages_Table (CD.Packages_Count).last_public_declaration := CD.Id_Count; end Define_and_Register_HAT; end HAC_Sys.Librarian.Built_In_Packages; ================================================ FILE: src/manage/hac_sys-librarian-built_in_packages.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- -- This package provides the insertion "by hand" of packages -- of HAC's run-time library into compiler and library data. with HAC_Sys.Co_Defs; private package HAC_Sys.Librarian.Built_In_Packages is --------------------------------------------- -- Enter "manually" the Standard package -- --------------------------------------------- procedure Define_and_Register_Standard ( CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data ); ----------------------------------------------- -- Enter "manually" the Interfaces package -- ----------------------------------------------- procedure Define_and_Register_Interfaces ( CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data ); ---------------------------------------- -- Enter "manually" the HAT package -- ---------------------------------------- procedure Define_and_Register_HAT ( CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data ); end HAC_Sys.Librarian.Built_In_Packages; ================================================ FILE: src/manage/hac_sys-librarian.adb ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Compiler, HAC_Sys.Librarian.Built_In_Packages, HAC_Sys.Parser.Helpers, HAC_Sys.Parser.Packages, HAC_Sys.Errors; with Ada.Characters.Handling, Ada.Exceptions; package body HAC_Sys.Librarian is --------------------------------------------- -- Introduce a new unit into the library -- --------------------------------------------- procedure Register_Unit (LD : in out Library_Data; Descriptor : in Library_Unit) is use Librarian.Library_Name_Mapping; UVFN : constant HAT.VString := HAT.To_Upper (Descriptor.full_name); is_new : Boolean; begin is_new := LD.map.Find (UVFN) = No_Element; if not is_new then raise Program_Error with "Duplicate registration for unit " & HAT.To_String (Descriptor.full_name) & ". This case should be handled by Apply_WITH"; end if; LD.library.Append (Descriptor); LD.map.Insert (UVFN, LD.library.Last_Index); -- HAT.PUT_LINE ("Registering: " & Full_Name); end Register_Unit; procedure Change_Unit_Details (LD : in out Library_Data; Descriptor : in Library_Unit) is use Library_Name_Mapping; UVFN : constant HAT.VString := HAT.To_Upper (Descriptor.full_name); c : Cursor; book_nr : Positive; begin c := LD.map.Find (UVFN); if c = No_Element then raise Program_Error with "Change_Unit_Status called on non-registered unit"; end if; book_nr := Element (c); LD.library.Replace_Element (book_nr, Descriptor); end Change_Unit_Details; procedure Enter_Library_Level_Def (CD : in out Co_Defs.Compiler_Data; Full_Ident : in String; -- "Main", "Standard.False", ... New_Entity : in Co_Defs.Entity_Kind; Base_Type : in Defs.Typen; Size : in Integer; Discrete_First : in Defs.HAC_Integer := Defs.HAC_Integer'First; Discrete_Last : in Defs.HAC_Integer := Defs.HAC_Integer'Last; is_built_in : in Boolean := False) is use Ada.Characters.Handling, Co_Defs, Defs; use type Nesting_Level; Alfa_Ident : constant Alfa := S2A (Full_Ident); Alfa_Ident_Upper : constant Alfa := S2A (To_Upper (Full_Ident)); last : Index := CD.Id_Count; begin CD.Id_Count := CD.Id_Count + 1; -- Find the last library-level definition: while last > 0 and then CD.id_table (last).lev > 0 loop last := last - 1; end loop; CD.id_table (CD.Id_Count) := (name => Alfa_Ident_Upper, name_with_case => Alfa_Ident, link => last, entity => New_Entity, decl_kind => complete, xtyp => (TYP => Base_Type, Ref => 0, Is_Range => False, Discrete_First => Discrete_First, Discrete_Last => Discrete_Last), block_or_pkg_ref => 0, normal => True, lev => 0, adr_or_sz => HAC_Integer (Size), is_referenced => False, is_read => no, is_written_after_init => no, is_initialized => none, location => (0, 0, 0)); CD.target.Mark_Declaration (is_built_in); CD.Blocks_Table (0).Last_Id_Idx := CD.Id_Count; CD.CUD.level_0_def.Include (Alfa_Ident_Upper, CD.Id_Count); end Enter_Library_Level_Def; procedure Set_File_Catalogue (LD : in out Library_Data; cat : in Files.Abstract_File_Catalogue_Reference) is begin LD.cat := cat; end Set_File_Catalogue; function Find_Unit_File_Name (LD : Library_Data; Unit_Name : String) return String is GNAT_prefix : constant String := GNAT_File_Naming (Unit_Name); spec_fn : constant String := GNAT_prefix & ".ads"; body_fn : constant String := GNAT_prefix & ".adb"; begin if LD.cat.Exists (spec_fn) then return spec_fn; elsif LD.cat.Exists (body_fn) then return body_fn; else return ""; end if; end Find_Unit_File_Name; procedure Activate_Unit (CD : in out Co_Defs.Compiler_Data; Upper_Name : in String) is use Co_Defs, Defs; unit_idx : Natural; upper_name_alfa : constant Alfa := S2A (Upper_Name); use type Nesting_Level; begin -- HAT.PUT_LINE ("WITH: Activating " & Upper_Name); -- Activate the unit itself: unit_idx := Parser.Helpers.Locate_Identifier (CD, upper_name_alfa, Level => 0, Level_0_Filter => False); CD.CUD.level_0_def.Include (upper_name_alfa, unit_idx); -- Only packages specifications need to have their items made visible. if CD.id_table (unit_idx).entity = paquetage then declare pkg_table_entry : Package_Table_Entry renames CD.Packages_Table (CD.id_table (unit_idx).block_or_pkg_ref); begin for declaration_in_pkg_index in pkg_table_entry.first_public_declaration .. pkg_table_entry.last_public_declaration loop if CD.id_table (declaration_in_pkg_index).lev = 0 then -- We check that the level is 0 because subprogram -- parameters have level 1 and of course we don't -- want *them* to be globally visible. An inclusion -- of parameters would be especially nasty because -- the identifiers don't have any prefix! CD.CUD.level_0_def.Include (CD.id_table (declaration_in_pkg_index).name, declaration_in_pkg_index); end if; end loop; end; end if; end Activate_Unit; procedure Compile_WITHed_Unit (CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data; upper_name : in String) is fn : constant String := Find_Unit_File_Name (LD, upper_name); -- ^ NB: if there is a spec, priority is with the spec. use Co_Defs, Defs, Errors; as_specification, needs_body : Boolean; -- unit : Library_Unit := (full_name => HAT.To_VString (upper_name), kind => Package_Declaration, -- Temporary value status => In_Progress, -- Temporary value. id_index => No_Id, -- Temporary value. id_body_index => No_Id, -- Temporary value. spec_context => Id_Maps.Empty_Map); begin -- -- Add new unit name to the library catalogue -- -- Register_Unit (LD, unit); -- if fn = "" then Error (CD, err_library_error, "no file found matching the name """ & GNAT_File_Naming (upper_name) & ".ad*""", severity => major); else as_specification := fn (fn'Last) = 's'; -- ".ads" extension ? Then it's a spec. -- Compiler.Compile_Unit (CD => CD, LD => LD, upper_name => upper_name, file_name => fn, as_specification => as_specification, as_main_unit => False, needs_opening_a_stream => True, first_compilation => False, specification_id_index => Co_Defs.No_Id, new_id_index => unit.id_index, unit_context => unit.spec_context, kind => unit.kind, needs_body => needs_body); -- if as_specification then case unit.kind is when Subprogram_Unit => unit.status := Body_Postponed; when Package_Declaration => unit.status := (if needs_body then Body_Postponed else Spec_Only); when Package_Body => null; -- Not relevant (spec.) end case; else unit.status := Done; end if; Change_Unit_Details (LD, unit); -- -- Activate unit library-level declaration for the first time. -- It must be visible to the WITH-ing unit. -- Activate_Unit (CD, upper_name); end if; end Compile_WITHed_Unit; procedure Apply_WITH (CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data; Upper_Name : in String) is use Ada.Exceptions, Defs, HAT, Errors; UVN : constant VString := To_VString (Upper_Name); begin if LD.map.Contains (UVN) then if LD.library.Element (LD.map.Element (UVN)).status = In_Progress then -- Ouch, we are WITH-ing a unit which is being compiled. raise Circular_Unit_Dependency with Upper_Name; end if; -- Definition is already somewhere in CD (from the compilation -- of another unit), we just need to reactivate it. -- This situation includes the duplicate WITH case (not nice but correct). -- Packages Standard, Interfaces and HAT are also reactivated on -- second WITH (implicitly for Standard). Activate_Unit (CD, Upper_Name); elsif Upper_Name = "STANDARD" then Built_In_Packages.Define_and_Register_Standard (CD, LD); elsif Upper_Name = "INTERFACES" then Built_In_Packages.Define_and_Register_Interfaces (CD, LD); elsif Upper_Name = "ADA" or else (Upper_Name'Length > 3 and then Upper_Name (Upper_Name'First .. Upper_Name'First + 3) = "ADA.") then Error (CD, err_library_error, "Ada package (and children) are not yet part of" & " HAC's predefined library. Consider the " & HAT_Name & " package.", severity => major); elsif Upper_Name = HAT_Name then Built_In_Packages.Define_and_Register_HAT (CD, LD); elsif Upper_Name in "HAC_PACK" | "HAL" then Error (CD, err_obsolete_hat_name, HAT_Name, Upper_Name, severity => major); else begin Compile_WITHed_Unit (CD, LD, Upper_Name); exception when E : Circular_Unit_Dependency => -- Re-raise the exception but add current unit to the -- dependency chain. raise Circular_Unit_Dependency with Upper_Name & " -> " & Exception_Message (E); end; end if; end Apply_WITH; procedure Apply_WITH_USE_Standard (CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data) is begin Apply_WITH (CD, LD, "STANDARD"); Parser.Packages.Apply_USE_Clause (CD, Library_Level, False, Parser.Helpers.Locate_Identifier (CD, Defs.S2A ("STANDARD"), 0)); end Apply_WITH_USE_Standard; function GNAT_File_Naming (Unit_Name : String) return String is result : String := Ada.Characters.Handling.To_Lower (Unit_Name); begin for c of result loop if c = '.' then c := '-'; end if; end loop; return result; end GNAT_File_Naming; function Ada_RM_Casing (Identifier : String) return String is use Ada.Characters.Handling; copy : String := To_Lower (Identifier); first_letter : Boolean := True; begin for i in copy'Range loop if first_letter then copy (i) := To_Upper (copy (i)); end if; first_letter := copy (i) = '_'; end loop; return copy; end Ada_RM_Casing; end HAC_Sys.Librarian; ================================================ FILE: src/manage/hac_sys-librarian.ads ================================================ ------------------------------------------------------------------------------------- -- -- HAC - HAC Ada Compiler -- -- A compiler in Ada for an Ada subset -- -- Copyright, license, etc. : see top package. -- ------------------------------------------------------------------------------------- -- with HAC_Sys.Co_Defs, HAC_Sys.Defs, HAC_Sys.Files.Default; with HAT; with Ada.Containers.Hashed_Maps, Ada.Containers.Vectors, Ada.Strings.Unbounded.Hash; package HAC_Sys.Librarian is Library_Level : constant := 0; type Build_Mode is (Read_HCU_Files -- ^ Full compilation around main unit is done in memory. -- If available and { up-to-date or no source file present }, -- .hcu files are downloaded to the compilation tables. -- Write_HCU_Files -- -- If a .hcu file not yet available or out-of-date, -- -- the source is compiled and the .hcu file is (re)written. ); -- HAC Compiled Unit files have the .hcu extension. Some may be stored in .zip library files. type Compilation_Status is (In_Progress, -- Specification or body-only is in progress. Body_Postponed, -- Specification done, body will be done later. Spec_Only, -- Specification-only is done, but we need to check absence of body. Done); -- Specification done; possible body is done or its absence is checked. subtype Spec_Done is Compilation_Status range Body_Postponed .. Spec_Only; -- RM 10.1.1 type Unit_Kind is (Package_Declaration, Package_Body, Procedure_Unit, Function_Unit); subtype Subprogram_Unit is Unit_Kind range Procedure_Unit .. Function_Unit; type Library_Unit is record full_name : HAT.VString; -- Full unit name, like "Ada.Strings.Fixed" kind : Unit_Kind; status : Compilation_Status; id_index : Natural; id_body_index : Natural; spec_context : Co_Defs.Id_Maps.Map; -- WITH & USE's visible to the spec. end record; package Library_Unit_Vectors is new Ada.Containers.Vectors (Positive, Library_Unit); package Library_Name_Mapping is new Ada.Containers.Hashed_Maps (Key_Type => HAT.VString, -- Upper case of full unit name Element_Type => Positive, -- Index in the library Hash => Ada.Strings.Unbounded.Hash, Equivalent_Keys => Ada.Strings.Unbounded."="); -- Global object used as a default for library file management: default_file_catalogue : aliased Files.Default.File_Catalogue; type Library_Data is tagged record -- !! details -> private library : Library_Unit_Vectors.Vector; -- The library itself (= the "books") map : Library_Name_Mapping.Map; -- Quick access by name to unit number cat : Files.Abstract_File_Catalogue_Reference := default_file_catalogue'Access; end record; -- Method used internally by HAC. -- Prefer using Build_Data's Set_File_Catalogue method. -- procedure Set_File_Catalogue (LD : in out Library_Data; cat : in Files.Abstract_File_Catalogue_Reference); -- Search for file (physical or not, depending on the -- LD.cat.Exists function) corresponding to unit name. -- First a spec, then a body. -- If nothing found, return empty string. -- function Find_Unit_File_Name (LD : Library_Data; Unit_Name : String) return String; ----------------------------------------------------- -- Apply WITH clause for any unit, including the -- -- Standard package and the special HAT package. -- ----------------------------------------------------- procedure Apply_WITH (CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data; Upper_Name : in String); ---------------------------------------------------------- -- Apply the invisible "with Standard; use Standard;" -- ---------------------------------------------------------- procedure Apply_WITH_USE_Standard (CD : in out Co_Defs.Compiler_Data; LD : in out Library_Data); ---------------------------------------------------------------------- -- Add a new definition to the identifier table, at library level -- ---------------------------------------------------------------------- procedure Enter_Library_Level_Def (CD : in out Co_Defs.Compiler_Data; Full_Ident : in String; -- "Main", "Standard.False", ... New_Entity : in Co_Defs.Entity_Kind; Base_Type : in Defs.Typen; Size : in Integer; Discrete_First : in Defs.HAC_Integer := Defs.HAC_Integer'First; Discrete_Last : in Defs.HAC_Integer := Defs.HAC_Integer'Last; is_built_in : in Boolean := False); Circular_Unit_Dependency : exception; procedure Register_Unit (LD : in out Library_Data; Descriptor : in Library_Unit); procedure Change_Unit_Details (LD : in out Library_Data; Descriptor : in Library_Unit); -- ^ Changes in the library the details for -- unit named Descriptor.Full_Name. ---------------------------------------------------------------------- -- GNAT_File_Naming returns the file name that GNAT expects for -- -- a unit with the name Unit_Name. -- ---------------------------------------------------------------------- function GNAT_File_Naming (Unit_Name : String) return String; function Ada_RM_Casing (Identifier : String) return String; private end HAC_Sys.Librarian; ================================================ FILE: test/all_noisy_tests.adb ================================================ -- We launch new instances of HAC (possibly from HAC itself, too). -- Usage: hac all_noisy_tests.adb with HAT; procedure All_Noisy_Tests is use HAT; procedure Launch_Tests is procedure Shell (command : VString; echo : Boolean) is begin if echo then Put_Line ("Executing: [" & command & ']'); end if; Shell_Execute (command); end Shell; procedure Launch_HAC (Ada_file_name : VString) is begin Put_Line ("-------------------------------------------------------"); Shell ( +".." & Directory_Separator & "hac -v1 " & Ada_file_name, False ); end Launch_HAC; procedure Build_HAC is begin if Get_Env ("hacbuild") = "done" then return; end if; Put_Line ("(Re-)building HAC, in case the present program isn't run from HAC..."); Shell (+"gprbuild -P .." & Directory_Separator & "hac", True); end Build_HAC; procedure Pause is dummy : Character; begin Put ("--- Press any key to continue in the HAC noisy test suite..."); Get_Immediate (dummy); New_Line; end Pause; begin Put_Line (" ___________ _________________________________"); Put_Line (" / * HAC * \ / ""Noisy tests"": a human is \"); Put_Line (" \__Testing__/ \__required to check the output.__/"); New_Line; Build_HAC; -- Redundant if this program is itself run through HAC. -- Put_Line ("----> Launching tests (one instance of HAC each)..."); for e in 1 .. 4 loop Launch_HAC (+"exception_0" & e & ".adb"); end loop; Pause; Launch_HAC (+"if_then_elsif_else.adb"); Pause; Launch_HAC (+"digitz.adb"); Put_Line ("----> Done."); end Launch_Tests; begin Launch_Tests; end All_Noisy_Tests; ================================================ FILE: test/all_silent_tests.adb ================================================ -- This program runs a series of more than 115 regression tests to check -- the correct operation of the HAC compiler. -- -- The failures and success are accounted and the sums are shown at the end. -- -- NB: the individual tests, or this program itself, can actually be used -- for testing any Ada compiler. For that, all you have to do is to -- customize the procedure Launch_HAC below. -- -- For each test we launch, possibly from HAC itself, a new instance of -- the HAC command-line tool (`hac` or `hac.exe`), which will build the -- test sources as a virtual machine executable and run it. -- -- Usage (if run from `hac` or `hac.exe`): hac all_silent_tests.adb with HAT; with Testing_Utilities; procedure All_Silent_Tests is use HAT; procedure Launch_Tests is procedure Shell (command : VString; echo : Boolean; success : out Boolean) is r : Integer; begin if echo then Put_Line ("Executing: [" & command & ']'); end if; Shell_Execute (command, r); success := r = Testing_Utilities.OK_Code; if not success then Put_Line (+"*** Command: [" & command & "] FAILED ***. Return code: " & r); end if; end Shell; procedure Build_HAC (success : out Boolean) is begin if Get_Env ("hacbuild") = "done" then success := True; return; end if; Put_Line ("(Re-)building HAC, in case the present program isn't run from HAC..."); Shell (+"gprbuild -P .." & Directory_Separator & "hac", True, success); end Build_HAC; successes, failures : Natural := 0; procedure Launch_HAC (Ada_file_name, args : VString; ups : Positive) is success : Boolean; begin Shell ( ups * (+".." & Directory_Separator) & "hac " & Ada_file_name & ' ' & args, False, success ); if success then successes := successes + 1; else failures := failures + 1; end if; end Launch_HAC; procedure Normal_Test (Ada_file_name : VString) is short : VString; sep : constant Natural := Index_Backward (Ada_file_name, Directory_Separator); spc : constant Natural := Index_Backward (Ada_file_name, ' '); begin if spc > 0 then short := Slice (Ada_file_name, sep + 1, spc - 1); else short := Slice (Ada_file_name, sep + 1, Length (Ada_file_name)); end if; Put_Line (+" " & short); Launch_HAC (Ada_file_name, +"", 1); end Normal_Test; -- Advent of Code procedure Launch_AoC (Year, Day, Solutions : VString) is begin if Index (Current_Directory, Year) = 0 then New_Line; Set_Directory (+".." & Directory_Separator & Year); Put_Line (" Advent of Code " & Year & " in " & Current_Directory & ':'); Put (" "); end if; Put (Day & ' '); Launch_HAC (+"aoc_" & Year & '_' & Day & ".adb ", Solutions, -- ^ Solutions are validated by https://adventofcode.com/ . -- It's the pair of answers, each appearing after -- "Your puzzle answer was ", separated by a space. 3); end Launch_AoC; hac_build_success : Boolean; examples_dir : constant VString := +".." & Directory_Separator & "exm" & Directory_Separator; generate : constant VString := +".." & Directory_Separator & "hac " & examples_dir & "pkg_demo_gen.adb"; begin Put_Line (" ______________________ _____________________________________________"); Put_Line (" / * H A C * \ / ""Silent tests"": when the failure count \"); Put_Line (" | Regression Testing | | is zero, then the test suite is all fine. |"); Put_Line (" \______________________/ \_____________________________________________/"); New_Line; Build_HAC (hac_build_success); -- Redundant if this program is itself run through HAC. if not hac_build_success then Put_Line ("--- HAC build failed (called from all_silent_tests.adb) ---"); return; end if; -- Put_Line ("----> Launching tests."); Put_Line (" One instance of HAC is called each time, with compilation and execution..."); New_Line; Put_Line (+" Normal tests in " & Current_Directory & ':'); Normal_Test (+"attributes_test.adb"); Normal_Test (examples_dir & "barnes.adb 3816547290"); Normal_Test (+"case_statement.adb"); Normal_Test (+"constants.adb"); Normal_Test (+"declarations.adb"); Normal_Test (+"enumerations.adb"); Normal_Test (+"floats.adb"); Normal_Test (+"forward.adb"); Normal_Test (+"integers.adb"); Normal_Test (+"loops.adb"); Normal_Test (+"object_init.adb"); -- Create the X_* packages, run pkg_demo and finally delete the X_* packages . Shell_Execute (generate); Normal_Test (+"-I. .." & Directory_Separator & "exm" & Directory_Separator & "pkg_demo.adb test_mode"); Shell_Execute (generate & " delete"); -- Normal_Test (+"recursion.adb"); Normal_Test (+"remarks_check.adb"); Normal_Test (+"sorting_tests.adb"); Normal_Test (+"strings.adb"); Normal_Test (examples_dir & "tasking" & Directory_Separator & "tasks_02.adb x"); Normal_Test (+"type_conversion.adb"); -- Set_Directory (+".." & Directory_Separator & "exm" & Directory_Separator & "aoc" & Directory_Separator & "2021"); -- <- We put on purpose the wrong starting year. -- Launch_AoC (+"2020", +"02", +"607 321"); -- Password Philosophy Launch_AoC (+"2020", +"03", +"218 3847183340"); -- Toboggan Trajectory Launch_AoC (+"2020", +"04", +"228 175"); -- Passport Processing Launch_AoC (+"2020", +"05", +"835"); -- Binary Boarding Launch_AoC (+"2020", +"06", +"6532 3427"); -- Custom Customs Launch_AoC (+"2020", +"07", +"169 82372"); -- Handy Haversacks Launch_AoC (+"2020", +"08", +"1394 1626"); -- Handheld Halting Launch_AoC (+"2020", +"09", +"138879426 23761694"); -- Encoding Error Launch_AoC (+"2020", +"10", +"2277 37024595836928"); -- Adapter Array Launch_AoC (+"2020", +"11", +"37 26"); -- Seating System Launch_AoC (+"2020", +"12", +"1631 58606"); -- Rain Risk Launch_AoC (+"2020", +"13", +"222 408270049879073"); -- Shuttle Search Launch_AoC (+"2020", +"15", +"436 1 10 27 78 438 1836 249"); -- Rambunctious Recitation Launch_AoC (+"2020", +"16", +"23954 453459307723"); -- Ticket Translation Launch_AoC (+"2020", +"17", +"207"); -- Conway Cubes Launch_AoC (+"2020", +"20", +"83775126454273"); -- Jurassic Jigsaw Launch_AoC (+"2020", +"22", +"31957"); -- Crab Combat Launch_AoC (+"2020", +"23", +"67384529 49576328"); -- Crab Cups Launch_AoC (+"2020", +"24", +"341 285"); -- Lobby Layout -- Launch_AoC (+"2021", +"01", +"1154 1127"); -- Sonar Sweep Launch_AoC (+"2021", +"02", +"2187380 2086357770"); -- Dive! Launch_AoC (+"2021", +"03", +"3549854 3765399"); -- Binary Diagnostic Launch_AoC (+"2021", +"04", +"39984 8468"); -- Giant Squid Launch_AoC (+"2021", +"05", +"6225 22116"); -- Hydrothermal Venture Launch_AoC (+"2021", +"06", +"388419 1740449478328"); -- Lanternfish Launch_AoC (+"2021", +"07", +"340052 92948968"); -- The Treachery of Whales Launch_AoC (+"2021", +"08", +"440 1046281"); -- Seven Segment Search Launch_AoC (+"2021", +"09", +"423 1198704"); -- Smoke Basin Launch_AoC (+"2021", +"10", +"388713 3539961434"); -- Syntax Scoring Launch_AoC (+"2021", +"11", +"1679 519"); -- Dumbo Octopus Launch_AoC (+"2021", +"12", +"3497"); -- Passage Pathing Launch_AoC (+"2021", +"13", +"602"); -- Transparent Origami Launch_AoC (+"2021", +"14", +"2345 2432786807053"); -- Extended Polymerization Launch_AoC (+"2021", +"15", +"656"); -- Chiton Launch_AoC (+"2021", +"16", +"927 1725277876501"); -- Packet Decoder Launch_AoC (+"2021", +"21", +"684495 152587196649184"); -- Dirac Dice -- Launch_AoC (+"2022", +"01", +"68442 204837"); -- Calorie Counting Launch_AoC (+"2022", +"02", +"14531 11258"); -- Rock Paper Scissors Launch_AoC (+"2022", +"03", +"8185 2817"); -- Rucksack Reorganization Launch_AoC (+"2022", +"04", +"657 938"); -- Camp Cleanup Launch_AoC (+"2022", +"05", +"VQZNJMWTR NLCDCLVMQ"); -- Supply Stacks Launch_AoC (+"2022", +"06", +"1802 3551"); -- Tuning Trouble Launch_AoC (+"2022", +"07", +"1749646 1498966"); -- No Space Left On Device Launch_AoC (+"2022", +"08", +"1843 180000"); -- Treetop Tree House Launch_AoC (+"2022", +"09", +"6314 2504"); -- Rope Bridge Launch_AoC (+"2022", +"10", +"12880"); -- Cathode-Ray Tube Launch_AoC (+"2022", +"11", +"102399 23641658401"); -- Monkey in the Middle Launch_AoC (+"2022", +"12", +"440 439"); -- Hill Climbing Algorithm Launch_AoC (+"2022", +"13", +"6568 19493"); -- Distress Signal Launch_AoC (+"2022", +"14", +"964 32041"); -- Regolith Reservoir Launch_AoC (+"2022", +"17", +"3193 1577650429835"); -- Pyroclastic Flow Launch_AoC (+"2022", +"18", +"3374 2010"); -- Boiling Boulders Launch_AoC (+"2022", +"21", +"286698846151845 3759566892642"); -- Monkey Math Launch_AoC (+"2022", +"22", +"26558 110400"); -- Monkey Map Launch_AoC (+"2022", +"23", +"3689 965"); -- Unstable Diffusion -- Launch_AoC (+"2023", +"01", +"52974 53340"); -- Trebuchet?! Launch_AoC (+"2023", +"02", +"2176 63700"); -- Cube Conundrum Launch_AoC (+"2023", +"03", +"539590 80703636"); -- Gear Ratios Launch_AoC (+"2023", +"04", +"23750 13261850"); -- Scratchcards Launch_AoC (+"2023", +"05", +"261668924 24261545"); -- If You Give A Seed A Fertilizer Launch_AoC (+"2023", +"06", +"393120 36872656"); -- Wait For It Launch_AoC (+"2023", +"07", +"252656917 253499763"); -- Camel Cards Launch_AoC (+"2023", +"08", +"12737 9064949303801"); -- Haunted Wasteland Launch_AoC (+"2023", +"09", +"1884768153 1031"); -- Mirage Maintenance Launch_AoC (+"2023", +"10", +"6897 367"); -- Pipe Maze Launch_AoC (+"2023", +"11", +"10173804 634324905172"); -- Cosmic Expansion Launch_AoC (+"2023", +"12", +"7007 3476169006222"); -- Hot Springs Launch_AoC (+"2023", +"13", +"33728 28235"); -- Point of Incidence Launch_AoC (+"2023", +"14", +"113078 94255"); -- Parabolic Reflector Dish Launch_AoC (+"2023", +"15", +"513172 237806"); -- Lens Library Launch_AoC (+"2023", +"16", +"7996"); -- The Floor Will Be Lava Launch_AoC (+"2023", +"17", +"102 94"); -- Clumsy Crucible (example's data) Launch_AoC (+"2023", +"18", +"53300 64294334780659"); -- Lavaduct Lagoon Launch_AoC (+"2023", +"19", +"19114 167409079868000"); -- Aplenty Launch_AoC (+"2023", +"20", +"806332748 228060006554227"); -- Pulse Propagation Launch_AoC (+"2023", +"21", +"3677"); -- Step Counter Launch_AoC (+"2023", +"22", +"5 7"); -- Sand Slabs (example's data) Launch_AoC (+"2023", +"23", +"94 154"); -- A Long Walk (example's data) -- Launch_AoC (+"2023", +"24", +"24192 664822352550558"); -- Never Tell Me The Odds (depends on floating-point accuracy of HAT.Real) Launch_AoC (+"2023", +"25", +"54"); -- Snowverload (example's data) -- Launch_AoC (+"2024", +"01", +"2086478 24941624"); -- Historian Hysteria (sorting) Launch_AoC (+"2024", +"02", +"332 398"); -- Red-Nosed Reports Launch_AoC (+"2024", +"03", +"173529487 99532691"); -- Mull It Over Launch_AoC (+"2024", +"04", +"2483 1925"); -- Ceres Search Launch_AoC (+"2024", +"05", +"5166"); -- Print Queue Launch_AoC (+"2024", +"06", +"5461"); -- Guard Gallivant (part 2 takes 4 minutes on HAC!) Launch_AoC (+"2024", +"07", +"850435817339"); -- Bridge Repair (part 2 takes 3 minutes on HAC!) Launch_AoC (+"2024", +"08", +"409 1308"); -- Resonant Collinearity Launch_AoC (+"2024", +"09", +"6340197768906"); -- Disk Fragmenter (part 2 takes 34 seconds on HAC!) Launch_AoC (+"2024", +"10", +"737 1619"); -- Hoof It Launch_AoC (+"2024", +"11", +"198089 236302670835517"); -- Plutonian Pebbles Launch_AoC (+"2024", +"12", +"1319878 784982"); -- Garden Groups Launch_AoC (+"2024", +"13", +"36954 79352015273424"); -- Claw Contraption Launch_AoC (+"2024", +"14", +"226236192"); -- Restroom Redoubt (part 2 is visual) Launch_AoC (+"2024", +"15", +"1515788 1516544"); -- Warehouse Woes Launch_AoC (+"2024", +"16", +"74392"); -- Reindeer Maze (part 2 takes long even on GNAT) Launch_AoC (+"2024", +"17", +"4635635210"); -- Chronospatial Computer (example's data) Launch_AoC (+"2024", +"18", +"298 52,32"); -- RAM Run Launch_AoC (+"2024", +"19", +"260 639963796864990"); -- Linen Layout Launch_AoC (+"2024", +"20", +"44 285"); -- Race Condition (example's data) Launch_AoC (+"2024", +"21", +"222670 271397390297138"); -- Keypad Conundrum Launch_AoC (+"2024", +"22", +"37990510 23"); -- Monkey Market (example's data) Launch_AoC (+"2024", +"23", +"1227 cl,df,ft,ir,iy,ny,qp,rb,sh,sl,sw,wm,wy"); -- LAN Party Launch_AoC (+"2024", +"24", +"57270694330992"); -- Crossed Wires Launch_AoC (+"2024", +"25", +"3395"); -- Code Chronicle -- Launch_AoC (+"2025", +"01", +"989 5941"); -- Secret Entrance Launch_AoC (+"2025", +"02", +"1227775554 4174379265"); -- Gift Shop (example's data) Launch_AoC (+"2025", +"03", +"17613 175304218462560"); -- Lobby Launch_AoC (+"2025", +"04", +"1320 8354"); -- Printing Department Launch_AoC (+"2025", +"05", +"798 366181852921027"); -- Cafeteria Launch_AoC (+"2025", +"06", +"4449991244405 9348430857627"); -- Trash Compactor Launch_AoC (+"2025", +"07", +"1562 24292631346665"); -- Laboratories Launch_AoC (+"2025", +"08", +"40 25272"); -- Playground (example's data) Launch_AoC (+"2025", +"09", +"4749838800 1624057680"); -- Movie Theater Launch_AoC (+"2025", +"10", +"7"); -- Factory Launch_AoC (+"2025", +"11", +"423 333657640517376"); -- Reactor -- New_Line (2); New_Line; Put_Line ("----> Done."); New_Line; if failures = 0 then Put_Line ("All tests passed successfully."); else Put_Line (+"*** There are FAILED tests ***"); end if; Put_Line ("Summary:"); Put_Line (+" " & successes & " successes"); Put_Line (+" " & failures & " failures"); New_Line; end Launch_Tests; begin Launch_Tests; end All_Silent_Tests; ================================================ FILE: test/attributes_test.adb ================================================ with HAT; with Testing_Utilities; procedure Attributes_Test is use HAT, Testing_Utilities; type Enum is (aa, bb, cc, dd); subtype Sub_Enum is Enum range bb .. cc; dummy_e : Enum; dummy_i, sum : Integer; type A is array (Sub_Enum) of HAT.Real; type M is array (-5 .. -2, bb .. dd) of Integer; mm : M; type R is record x : Real; y : M; end record; mmm : array (10 .. 20) of R; begin Assert (Enum'Image (bb) < Enum'Image (cc), +"""<"" on values Strings_as_VStrings, Image"); Assert (Enum'First = aa, +"S'First"); Assert (Enum'Last = dd, +"S'Last"); Assert (Enum'Pred (dd) = cc, +"S'Pred"); Assert (Enum'Succ (bb) = cc, +"S'Succ"); Assert (bb = A'First, +"A'First"); Assert (cc = A'Last, +"A'Last"); Assert (2 = A'Length, +"A'Length"); Assert (M'First (1) = -5, +"M'First (1)"); Assert (M'Last (1) = -2, +"M'Last (1)"); Assert (bb = M'First (2), +"M'First (2)"); Assert (dd = M'Last (2), +"M'Last (2)"); for i in M'Range (1) loop for j in M'Range (2) loop mm (i, j) := i * Enum'Pos (j); end loop; end loop; sum := 0; for j in M'Range (2) loop for i in M'Range (1) loop sum := sum + mm (i, j); end loop; end loop; Assert (sum = -84, +"M'Range (N)"); -- Calm down the warning [-rv] about a variable read but never written: mmm (10).x := 123.0; Assert (-2 = mmm (10).y'Last (1), +"Obj.Last (1)"); Assert (bb = mmm (15).y'First (2), +"Obj.First (2)"); end Attributes_Test; ================================================ FILE: test/case_statement.adb ================================================ with HAT; with Testing_Utilities; procedure Case_Statement is use HAT, Testing_Utilities; after_int_case : Boolean := False; procedure Test_Int (i : Integer) is begin case (2 * (i + 1)) / 2 - 1 is when 1 | -1 => Assert (abs i = 1, +"Compiler bug [CASE test, Int, A]"); when -7 => Assert (i + 7 = 0, +"Compiler bug [CASE test, Int, B]"); when others => null; -- -- when 9 | others => null; -- the choice "others" must appear alone and last -- when 2 => null; -- the choice "others" must appear alone and last -- when 2 .. 9223372036854775807 => null; -- when -9223372036854775807 .. -8 => null; -- Integer'First as literal not supported (overflow) end case; after_int_case := True; end Test_Int; some_vowels_occurrences : Integer := 0; small_consonants_occurrences : Integer := 0; procedure Test_Char (c : Character) is begin case c is when 'a' | 'A' => if (c /= 'a') and (c /= 'A') then Put (c); Put_Line (" Compiler bug [Char, A]"); Set_Exit_Status (1); -- Compiler test failed. end if; some_vowels_occurrences := some_vowels_occurrences + 1; when '*' => null; when 'e' => some_vowels_occurrences := some_vowels_occurrences + 1; when 'b' .. 'd' | 'f' .. 'h' | 'j' .. 'n' | 'p' .. 't' | 'v' .. 'x' | 'z' => small_consonants_occurrences := small_consonants_occurrences + 1; when others => null; end case; end Test_Char; big_A : constant Character := 'A'; -- 8-bit character begin for i in -10 .. 10 loop Test_Int (i); end loop; Assert (after_int_case, +"Compiler bug [CASE, Int, Z]"); -- for c in big_A .. 'z' loop Test_Char (c); end loop; Assert (some_vowels_occurrences = 3, +"Char, CASE 1"); Assert (small_consonants_occurrences = 20, +"Char, CASE 2"); end Case_Statement; ================================================ FILE: test/constants.adb ================================================ -- Output must be empty if the compiler is correct. -- The order of the declarations is a bit random, it is on purpose. -- Especially we want to detect eventual memory corruption (buggy compilers). with HAT; with Testing_Utilities; procedure Constants is use HAT, Testing_Utilities; n1, n2 : constant := 9.0; -- Numeric constant (universal float) n3 : constant := 1.0; r1 : Real; r2 : Real := 123.0; r3 : constant Real := 456.0; minus_pi : constant := -Pi; i1 : constant Integer := 7; type R is record a, b : Integer; end record; s1 : R; procedure Test_In (x : in R) is null; procedure Test_Out (x : out R) is null; procedure Test_In_Out (x : in out R) is null; procedure Test_12_34 (x : R) is y : constant R := x; begin Assert (y.a = 12 and y.b = 34, +"Compiler bug [Constants, 12_34]"); -- x.a := 666; -- must be rejected (cannot modify "in" parameter) -- y.a := 666; -- must be rejected (cannot modify constant) Test_In (x); -- Test_Out (y); -- must be rejected (cannot modify constant) -- Test_In_Out (x); -- must be rejected (cannot modify constant) end Test_12_34; type Animal is (ant, bat, cat, dog); pet : constant Animal := dog; begin r1 := 123000.0; Assert (Pi + minus_pi = 0.0, +"Compiler bug [Constants, Pi - (Minus_Pi)]"); Assert (r2 * 1000.0 = r1 and r3 - 333.0 = r2, +"Compiler bug [Constants, 123]"); Assert (n1 + n2 - 17.0 = n3, +"Compiler bug [Constants, num const]"); r2 := 7.0; Assert (Integer (r2) = i1, +"Compiler bug [Constants, i1 = 7]"); -- s3.a := 4; -- must be rejected (cannot modify constant) -- i1 := 6; -- must be rejected (cannot modify constant) -- r3 := 6.0; -- must be rejected (cannot modify constant) s1.a := 12; s1.b := 34; Test_12_34 (s1); for i in 1 .. 5 loop null; -- i := 1; -- must be rejected (cannot modify constant) end loop; end Constants; ================================================ FILE: test/declarations.adb ================================================ -- Declarations in Ada can be in any order. -- In Pascal it is: constants, types, variables, subprograms. -- SmallAda (and early versions of HAC) has some remnants of Pascal and funny other bugs... with HAT; use HAT; procedure Declarations is Called_Mimi_Me : Boolean := False; Called_Micro_Me : Boolean := False; procedure Declarations is procedure Declarations is begin Called_Micro_Me := True; return; Put ("Noooo wayyyy (inner level 2)"); end; begin Declarations; Called_Mimi_Me := True; return; -- SmallAda & HAC < rev. 331: sees CD.Main_Program_ID and triggers "ILLEGAL RETURN STATEMENT FROM MAIN" !... Put ("Noooo wayyyy (inner level 1)"); Set_Exit_Status (1); -- Compiler test failed. end ; -- SmallAda & HAC < rev. 332: sees CD.Main_Program_ID and triggers "Incorrectly used symbol" !... type ee is (r, r2); procedure Test (I : Integer) is begin null; end Test; procedure Not_Yet_Done (a : Integer) is null; -- Ada 2005 null procedure. -- HAC 0.01: a type right after a subprogram borked the parser! type rec is record x, y : Integer; end record; a, b : rec; begin a.x := 5; a.y := 7; b.x := 3; b.y := 4; if a.x + a.y - b.x * b.y /= 000 then Put_Line ("Compiler bug [A]"); Set_Exit_Status (1); -- Compiler test failed. end if; Not_Yet_Done (123); Declarations; -- Subprogram with the same name. if not (Called_Mimi_Me and Called_Micro_Me) then Set_Exit_Status (1); -- Compiler test failed. return; -- HAC >= rev. 331: return from main emits a k_Halt_Interpreter end if; return; -- HAC >= rev. 331: return from main emits a k_Halt_Interpreter Put ("Noooo wayyyy (inner level 0)"); Set_Exit_Status (1); -- Compiler test failed. end Declarations; ================================================ FILE: test/digitz.adb ================================================ with HAT; procedure Digitz is use HAT; procedure Smalls is -- Check accuracy of decimal image without exponent ("E...") -- Was a problem till rev. 241. begin Put_Line ("[00] " & Image (Real (0.0))); Put_Line ("[01] " & Image (Real (1.0E-10))); Put_Line ("[02] " & Image (Real (0.0000000001))); Put_Line ("[03] " & Image (Real (0.00000000012))); Put_Line ("[04] " & Image (Real (0.000000000123))); Put_Line ("[05] " & Image (Real (0.0000000001234))); Put_Line ("[06] " & Image (Real (0.00000000012345))); Put_Line ("[07] " & Image (Real (0.000000000123456))); Put_Line ("[08] " & Image (Real (0.0000000001234567))); Put_Line ("[09] " & Image (Real (0.00000000012345678))); Put_Line ("[10] " & Image (Real (0.000000000123456789))); Put_Line ("[11] " & Image (Real (0.00000000012345678901))); Put_Line ("[12] " & Image (Real (0.00000000012345678901234))); Put_Line ("[13] " & Image (Real (0.00000000012345678901234567))); Put_Line ("[14] " & Image (Real (0.00000100012345678901234567))); Put_Line ("[15] " & Image (Real (0.0000010001))); Put_Line ("[16] " & Image (Real (0.00000100012345))); Put_Line ("[17] " & Image (Real (0.000001000123456))); -- Put_Line ("[18] " & Real'Image (7.77e-5)); Put_Line ("[19] " & Real'Image (7.77e-15)); Put_Line ("[20] " & Real'Image (7.77e-100)); end Smalls; procedure Larges is function RImage (r : Real) return VString is -- Solve Real vs. Duration ambiguity with literals. begin return Image (r); end RImage; begin Put_Line ("[50] " & RImage (1.0)); Put_Line ("[51] " & RImage (12.0)); Put_Line ("[52] " & RImage (123.0)); Put_Line ("[53] " & RImage (1234.0)); Put_Line ("[54] " & RImage (12345.0)); Put_Line ("[55] " & RImage (123456.0)); Put_Line ("[56] " & RImage (1234567.0)); Put_Line ("[57] " & RImage (12345678.0)); Put_Line ("[58] " & RImage (123456789.0)); Put_Line ("[59] " & RImage (1234567890.0)); Put_Line ("[60] " & RImage (12345678901.0)); Put_Line ("[61] " & RImage (123456789012.0)); Put_Line ("[62] " & RImage (1234567890123.0)); Put_Line ("[63] " & RImage (12345678901234.0)); Put_Line ("[64] " & RImage (123456789012345.0)); Put_Line ("[65] " & RImage (1234567890123456.0)); Put_Line ("[66] " & RImage (12345678901234567.0)); Put_Line ("[67] " & RImage (123456789012345678.0)); Put_Line ("[68] " & RImage (123456789012345678.0 * 10.0)); Put_Line ("[69] " & RImage (123456789012345678.0 * 100.0)); Put_Line ("[70] " & RImage (-12345678901.0)); Put_Line ("[71] " & RImage (-123456789012.0)); Put_Line ("[72] " & RImage (-1234567890123.0)); Put_Line ("[73] " & RImage (-12345678901234.0)); Put_Line ("[74] " & RImage (-123456789012345.0)); Put_Line ("[75] " & RImage (-1234567890123456.0)); Put_Line ("[76] " & RImage (-12345678901234567.0)); Put_Line ("[77] " & RImage (-123456789012345678.0)); Put_Line ("[78] " & RImage (-123456789012345678.0 * 10.0)); Put_Line ("[79] " & RImage (-123456789012345678.0 * 100.0)); end Larges; begin Smalls; Larges; end Digitz; ================================================ FILE: test/enumerations.adb ================================================ -- Output should be empty if the compiler is correct. with HAT; with Testing_Utilities; procedure Enumerations is use HAT, Testing_Utilities; type E1 is (a); type E2 is (b, c); type E3 is (d, e, f); type E4 is (g, h, i, j); procedure Test_ARRAY is aa : array (E3) of E4; begin aa (e) := g; end Test_ARRAY; x1 : E1; x2 : E2; x3 : E3; type R is record x1 : E1; x2 : E2; x3 : E3; x4 : E4; end record; ww : array (1 .. 7) of R; v : R; zz : array (E3) of R; type Animal is (ant, bat, cat, dog); pet2 : Animal; procedure Test_CASE is a : Animal := dog; begin case a is -- when d => null; -- <-- wrong enum type when dog => Assert (a = dog, +"Compiler bug [Enumerations, CASE]"); when others => null; end case; end Test_CASE; subtype Beast is Animal; subtype Insect is Animal range ant .. ant; subtype Mammal is Animal range bat .. dog; begin v.x1 := a; v.x2 := c; x3 := e; v.x3 := f; Assert (x3 = e, +"Compiler bug [Enumerations, A]"); x1 := v.x1; Assert (x1 = a, +"Compiler bug [Enumerations, B]"); -- Former HAC bug with selectors for enums x3 := v.x3; Assert (x3 = f, +"Compiler bug [Enumerations, C]"); -- Former HAC bug with selectors for enums ww (1).x3 := e; ww (5).x3 := ww (1).x3; ww (1).x3 := f; -- zz (d).x4 := j; zz (e).x4 := i; zz (f).x4 := h; -- v.x3 := d; v.x2 := b; Assert (ww (5).x3 = e, +"Compiler bug [Enumerations, D]"); -- Assert (zz (d).x4 = j, +"Compiler bug [Enumerations, E1]"); Assert (zz (e).x4 = i, +"Compiler bug [Enumerations, E2]"); Assert (zz (f).x4 = h, +"Compiler bug [Enumerations, E3]"); -- for pet in Mammal loop pet2 := pet; Assert (not (pet2 in Insect), +"Compiler bug: Enumerations, membership 1 (IN)"); Assert (not (pet2 not in Mammal), +"Compiler bug: Enumerations, membership 2 (NOT IN)"); end loop; -- Test_CASE; -- end Enumerations; ================================================ FILE: test/exception_01.adb ================================================ procedure Exception_01 is a : array (1 .. 3) of Integer; i : Integer := 4; begin -- a (4) := 1234; -- Compile-time error: "error in range constraint: -- value of index (4) is out of the array's range, 1 .. 3" a (i) := 1234; -- 4 is out-of-range -> raises Constraint_Error. end Exception_01; ================================================ FILE: test/exception_02.adb ================================================ procedure Exception_02 is i : Integer := 3; begin i := i / 0; end; ================================================ FILE: test/exception_03.adb ================================================ procedure Exception_03 is procedure P1 is function F2 return Integer is a : array (1 .. 3) of Integer; i : Integer := 0; begin -- a (0) := 123; -- Compile-time error: "error in range constraint: -- value of index (0) is out of the array's range, 1 .. 3" a (i) := 123; -- <- *** Boom! *** : 0 is out-of-range return 0; end F2; i : Integer := F2; -- <- Trace-back should show this line begin null; end P1; dummy : Integer; begin P1; -- <- Trace-back should show this line dummy := 1234; dummy := 4321; P1; -- <- No executed due to previously raised exception. end Exception_03; ================================================ FILE: test/exception_04.adb ================================================ -- We demonstrate a trace-back occurring on a non-trivial call -- structure (recursion). procedure Exception_04 is procedure Nest is -- Copy of some code from: recursion.adb Max_L : constant := 5; procedure NTF is -- Outer calls inner and vice-versa. function Add_n_shift (N : Integer; Level : Integer) return Integer is function Shift_n_add (N : Integer) return Integer is a : array (1 .. 3) of Integer; minus_4 : Integer := -4; begin if Level > 1 then return Add_n_shift (N * 2, Level - 1); -- <- Trace-back should show this line else a (minus_4) := 5; -- <- *** Boom! *** : -4 is out-of-range end if; return N; end Shift_n_add; begin return Shift_n_add (N + 1); -- <- Trace-back should show this line end Add_n_shift; begin for L in reverse 1 .. Max_L loop if Add_n_shift (0, L) /= 2 ** L - 1 then -- <- Trace-back should show this line null; end if; end loop; end NTF; begin NTF; -- <- Trace-back should show this line end Nest; procedure P1 is null; dummy : Integer; begin dummy := 1234; Nest; -- <- Trace-back should show this line dummy := 4321; P1; -- <- No executed due to previously raised exception. end Exception_04; ================================================ FILE: test/floats.adb ================================================ -- Output should be empty if the compiler is correct. with HAT; with Testing_Utilities; procedure Floats is use HAT, Testing_Utilities; procedure Test_Exp_Log is scale : constant := 500.0; steps : constant := 100; x1, x2 : Real; begin for i in 0 .. steps loop x1 := Real (i) * scale * (1.0 / Real (steps)); x2 := Log (Exp (x1)); Assert (abs (x2 - x1) <= 1.0e-15, +"Compiler bug [Floats, Exp_Log]"); end loop; end Test_Exp_Log; procedure Test_Trigo is scale : constant Real := Pi * 0.25; steps : constant := 100; x, s, c, t : Real; begin for i in 0 .. steps loop x := Real (i) * scale * (1.0 / Real (steps)); s := Sin (x); c := Cos (x); if abs c > 0.0 then t := s / c; Assert (abs (Arctan (t) - x) <= 1.0e-15, +"Compiler bug [Floats, Trigo]"); end if; end loop; end Test_Trigo; x1 : Real; x2 : Real; x3 : Real; type R is record x1 : Real; x2 : Real; x3 : Real; end record; ww : array (1 .. 7) of R; v : R; neg_float_value : constant := -5.07; function Almost_Equal (x, y : Real) return Boolean is eps : constant := 1.0e-14; -- = 9.99999... * 10**(-Real'Digits). -- 2.22044604925031E-16 = Real'Base'Model_Epsilon tol : Real := eps; z, ax, ay, ma : Real; eq : Boolean; begin z := abs (x - y); ax := abs x; ay := abs y; ma := ax; if ay < ma then ma := ay; end if; -- ma is the minimum of absolute values of x and y. tol := tol * ma; -- Relative tolerance eq := z <= tol; Assert (eq, +"Issue on equality test: x=" & Real'Image (x) & ", y=" & Real'Image (y) & ", x-y=" & Real'Image (x - y) & ", tol=" & Real'Image (tol) & "] "); return eq; end Almost_Equal; procedure Base_Test is begin -- Even with the same Real'Image, the difference in parsing (HAC for 10-base numbers, -- GNAT otherwise) induces differences which are beyond Real's precision, but large -- enough to have a non-zero z in computation. if not Almost_Equal (10#920.4323#e-20, 9.20432300000000E-18) then Put_Line ("[A]"); end if; if not Almost_Equal (10#8793.0#e-13, 8.79300000000000E-10) then Put_Line ("[B]"); end if; -- -- Here we have pasted from the output of floats.adb, -- with: Produce_Base_Test (True); -- if not Almost_Equal (+13#62A.A#e+19, 1.53614085896374E+24) then Put_Line ("[1]"); end if; if not Almost_Equal (+9#4458.4818#e17, 5.49270617585333E+19) then Put_Line ("[2]"); end if; if not Almost_Equal (-13#19A.C7206#e7, -1.86341399270000E+10) then Put_Line ("[3]"); end if; if not Almost_Equal (-6#3153.21#e-12, -3.29551144938688E-07) then Put_Line ("[4]"); end if; if not Almost_Equal (-8#60.65#, -4.88281250000000E+01) then Put_Line ("[5]"); end if; if not Almost_Equal (-16#62.17#, -9.80898437500000E+01) then Put_Line ("[6]"); end if; if not Almost_Equal (+6#15.32111#e7, 3.23636400000000E+06) then Put_Line ("[7]"); end if; if not Almost_Equal (-14#5.B7#e9, -1.20276808064000E+11) then Put_Line ("[8]"); end if; if not Almost_Equal (-2#11.0#e-16, -4.57763671875000E-05) then Put_Line ("[9]"); end if; if not Almost_Equal (+2#111.100#e+13, 6.14400000000000E+04) then Put_Line ("[10]"); end if; if not Almost_Equal (-4#31331.311#e+16, -3.83896256512000E+12) then Put_Line ("[11]"); end if; if not Almost_Equal (7#6353.1#e3, 7.69398000000000E+05) then Put_Line ("[12]"); end if; if not Almost_Equal (9#54.74871#, 4.98392182763468E+01) then Put_Line ("[13]"); end if; if not Almost_Equal (13#22548.A7#, 6.24218106508876E+04) then Put_Line ("[14]"); end if; if not Almost_Equal (-2#1011.000#e9, -5.63200000000000E+03) then Put_Line ("[15]"); end if; if not Almost_Equal (+12#48535.8A84#, 9.75297409336420E+04) then Put_Line ("[16]"); end if; if not Almost_Equal (2#0.01#, 2.50000000000000E-01) then Put_Line ("[17]"); end if; if not Almost_Equal (10#985.84#e-1, 9.85840000000000E+01) then Put_Line ("[18]"); end if; if not Almost_Equal (-2#11.101#, -3.62500000000000E+00) then Put_Line ("[19]"); end if; if not Almost_Equal (-2#10.1001#e19, -1.34348800000000E+06) then Put_Line ("[20]"); end if; if not Almost_Equal (4#11.32000#, 5.87500000000000E+00) then Put_Line ("[21]"); end if; if not Almost_Equal (+10#437.94309#, 4.37943090000000E+02) then Put_Line ("[22]"); end if; if not Almost_Equal (16#70.461D#, 1.12273880004883E+02) then Put_Line ("[23]"); end if; if not Almost_Equal (+13#A8.26877#, 1.38193254384004E+02) then Put_Line ("[24]"); end if; if not Almost_Equal (-3#22120.1000#e7, -5.05926000000000E+05) then Put_Line ("[25]"); end if; if not Almost_Equal (-2#10.10101#e+12, -1.08800000000000E+04) then Put_Line ("[26]"); end if; if not Almost_Equal (+13#64C4.7869#e8, 1.14353935858760E+13) then Put_Line ("[27]"); end if; if not Almost_Equal (-7#32465.145#e6, -9.56749794000000E+08) then Put_Line ("[28]"); end if; if not Almost_Equal (+14#696C6.B05#, 2.56542787536443E+05) then Put_Line ("[29]"); end if; if not Almost_Equal (-13#454B.90#e-8, -1.18871240938495E-05) then Put_Line ("[30]"); end if; if not Almost_Equal (-3#0022.2101#, -8.79012345679012E+00) then Put_Line ("[31]"); end if; if not Almost_Equal (-6#32012.22#e-18, -4.26190501736889E-11) then Put_Line ("[32]"); end if; if not Almost_Equal (+10#19586.80#, 1.95868000000000E+04) then Put_Line ("[33]"); end if; if not Almost_Equal (-7#355.052#, -1.87107871720117E+02) then Put_Line ("[34]"); end if; if not Almost_Equal (-16#79D6.5339E#e+8, -1.33961426264064E+14) then Put_Line ("[35]"); end if; if not Almost_Equal (+7#1.10#, 1.14285714285714E+00) then Put_Line ("[36]"); end if; if not Almost_Equal (13#1.011#, 1.00637232589895E+00) then Put_Line ("[37]"); end if; if not Almost_Equal (-11#50.2938#e6, -9.78946870000000E+07) then Put_Line ("[38]"); end if; if not Almost_Equal (+5#220.020#, 6.00800000000000E+01) then Put_Line ("[39]"); end if; if not Almost_Equal (2#0.1#, 5.00000000000000E-01) then Put_Line ("[40]"); end if; if not Almost_Equal (-9#31351.26#, -2.07012962962963E+04) then Put_Line ("[41]"); end if; if not Almost_Equal (-10#1.471#e-20, -1.47100000000000E-20) then Put_Line ("[42]"); end if; if not Almost_Equal (-16#E5744.2#, -9.39844125000000E+05) then Put_Line ("[43]"); end if; if not Almost_Equal (-12#439.7#e+11, -4.61841619746816E+14) then Put_Line ("[44]"); end if; if not Almost_Equal (-16#535ED.6ACFC#, -3.41485417232513E+05) then Put_Line ("[45]"); end if; if not Almost_Equal (+9#3.2347#, 3.26581313824112E+00) then Put_Line ("[46]"); end if; if not Almost_Equal (13#31A3.189C5#, 6.89312879047006E+03) then Put_Line ("[47]"); end if; if not Almost_Equal (-14#39C.513B#e18, -3.10069271780268E+23) then Put_Line ("[48]"); end if; if not Almost_Equal (+3#2.0210#, 2.25925925925926E+00) then Put_Line ("[49]"); end if; if not Almost_Equal (7#4513.415#e0, 1.62760641399417E+03) then Put_Line ("[50]"); end if; end Base_Test; procedure Produce_Base_Test (do_it : Boolean) is digitz : constant String (1 .. 16) := "0123456789ABCDEF"; function Rand_Digits (base : Integer) return VString is r : VString := +""; begin for d in 1 .. 1 + Rand (4) loop r := r & digitz (1 + Rand (base - 1)); end loop; return r; end Rand_Digits; b : Integer; n, nn : VString; begin if not do_it then return; -- We stay silent end if; for it in 51 .. 100 loop n := +""; case Rand (2) is when 0 => n := n & '+'; when 1 => n := n & '-'; when others => null; end case; b := 2 + Rand (14); -- TBD: could it be that GNAT is less accurate for non-10 bases ?... n := n & b & (+"#") & Rand_Digits (b) & '.' & Rand_Digits (b) & '#'; if Rnd > 0.5 then n := n & 'e'; case Rand (2) is when 0 => n := n & '+'; when 1 => n := n & '-'; when others => null; end case; n := n & Rand (20); end if; nn := +Real'Image (Float_Value (n)); Put_Line (" if not Almost_Equal (" & n & (+", ") & nn & ") then Put_Line (""[" & it & "]""); end if;"); end loop; end Produce_Base_Test; -- This is a copy of an example (see "exm/three_lakes_s.adb") of a -- deterministic dynamic system (in this case, a differential equation). -- Here, we check the end result of the calculation. -- procedure Three_Lakes_S is type Lake is (Morat, Neuchatel, Bienne); type Lake_Vector is array (Lake) of Real; procedure Times (l : Real; v : Lake_Vector; r : out Lake_Vector) is begin for i in Lake loop r (i) := v (i) * l; end loop; end Times; procedure Plus (a, b : Lake_Vector; r : out Lake_Vector) is begin for i in Lake loop r (i) := a (i) + b (i); end loop; end Plus; function Sign (i : Real) return Real is begin if i < 0.0 then return -1.0; elsif i = 0.0 then return 0.0; else return 1.0; end if; end Sign; ivs : Lake_Vector; procedure Init_Sensitivity is begin ivs (Morat) := 1.0 / 2.2820e7; ivs (Neuchatel) := 1.0 / 2.1581e8; ivs (Bienne) := 1.0 / 4.0870e7; end Init_Sensitivity; procedure Evolution (x : in out Lake_Vector; q_e : Lake_Vector; q_sb, h : Real) is procedure f (x : Lake_Vector; r : out Lake_Vector) is q_tr_mn, q_tr_nb : Real; -- procedure Flux_tansfert is begin q_tr_mn := -- Canal de la Broye: Morat -> Neuchatel. Sign (x (Morat) - x (Neuchatel)) * -- sens d'ecoulement 15.223 * -- facteur de debit (((x (Morat) + x (Neuchatel)) * 0.5 - 426.0)**1.868) * -- effet du niveau moyen ((abs (x (Morat) - x (Neuchatel)))**0.483); -- effet de la diff. de niveaux -- q_tr_nb := -- Canal de la Thielle: Neuchatel -> Bienne. Sign (x (Neuchatel) - x (Bienne)) * -- sens d'ecoulement 18.582 * -- facteur de debit (((x (Neuchatel) + x (Bienne)) * 0.5 - 426.0)**2.511) * -- effet du niveau moyen ((abs (x (Neuchatel) - x (Bienne)))**0.482); -- effet de la diff. de niveaux end Flux_tansfert; begin Flux_tansfert; r (Morat) := (q_e (Morat) - q_tr_mn) * ivs (Morat); r (Neuchatel) := (q_e (Neuchatel) + q_tr_mn - q_tr_nb) * ivs (Neuchatel); r (Bienne) := (q_e (Bienne) + q_tr_nb - q_sb) * ivs (Bienne); end f; k1, k2, k3, k4, tmp_a, tmp_b, dbk2, dbk3 : Lake_Vector; begin -- Runge-Kutta, Order 4 f (x, k1); -- Times (h * 0.5, k1, tmp_a); Plus (x, tmp_a, tmp_b); -- tmp_b = x + h * 0.5 * k1 f (tmp_b, k2); -- Times (h * 0.5, k2, tmp_a); Plus (x, tmp_a, tmp_b); -- tmp_b = x + h * 0.5 * k2 f (tmp_b, k3); -- Times (h, k3, tmp_a); Plus (x, tmp_a, tmp_b); -- tmp_b = x + h * k3 f (tmp_b, k4); -- Times (2.0, k2, dbk2); Times (2.0, k3, dbk3); Plus (k1, dbk2, tmp_a); Plus (tmp_a, dbk3, tmp_b); Plus (tmp_b, k4, tmp_a); -- tmp_a = (k1 + 2.0 * k2 + 2.0 * k3 + k4) Times (h * (1.0 / 6.0), tmp_a, tmp_b); Plus (x, tmp_b, tmp_a); x := tmp_a; end Evolution; procedure Simulation is x, q_e : Lake_Vector; q_sb, h : Real; n_iter : Integer; begin h := 3600.0; n_iter := 24 * 20; x (Morat) := 428.2; x (Neuchatel) := 429.0; x (Bienne) := 429.4; q_e (Morat) := 40.0; q_e (Neuchatel) := 70.0; q_e (Bienne) := 100.0; q_sb := 200.0; for i in 0 .. n_iter loop Evolution (x, q_e, q_sb, h); end loop; Assert (abs (x (Neuchatel) - 429.06377) <= 0.0002, +"Compiler bug [Floats, Three_Lakes_S]"); end Simulation; begin Init_Sensitivity; Simulation; end Three_Lakes_S; begin v.x1 := 1.0; v.x2 := 3.0; x3 := 5.0; v.x3 := 6.0; Assert (x3 = 5.0, +"Compiler bug [Floats, A]"); x1 := v.x1; Assert (x1 = 1.0, +"Compiler bug [Floats, B]"); x3 := v.x2; Assert (x3 = 3.0, +"Compiler bug [Floats, C]"); ww (1).x3 := 3.4_5_6_7_8_9; ww (5).x3 := ww (1).x3; ww (1).x3 := 7.89; v.x3 := 1.0; v.x2 := 2.0; Assert (abs (ww (5).x3 - (2.345_678 + 1.111111)) <= 0.000_000_1, +"Compiler bug [Floats, D]"); x2 := neg_float_value; Assert (-x2 = 5.07, +"Compiler bug [Floats, E]"); -- Former HAC bug: unary minus was ineffective for floats -- Test_Exp_Log; Test_Trigo; -- Produce_Base_Test (False); Base_Test; Three_Lakes_S; -- Assert (Almost_Equal (HAT.Max (1.0, 2.0), 2.0), +"HAT.Max [1]"); Assert (Almost_Equal (HAT.Max (2.0, 1.0), 2.0), +"HAT.Max [2]"); -- Assert (Almost_Equal (HAT.Min (1.0, 2.0), 1.0), +"HAT.Min [1]"); Assert (Almost_Equal (HAT.Min (2.0, 1.0), 1.0), +"HAT.Min [2]"); -- Assert (Almost_Equal (HAT.Sgn (123.0), 1.0), +"HAT.Sgn [1]"); Assert (Almost_Equal (HAT.Sgn (0.0), 0.0), +"HAT.Sgn [2]"); Assert (Almost_Equal (HAT.Sgn (-123.0), -1.0), +"HAT.Sgn [3]"); end Floats; ================================================ FILE: test/forward.adb ================================================ -- Test forward subprogram declaration -- https://en.wikipedia.org/wiki/Forward_declaration -- Code taken from: -- http://rosettacode.org/wiki/Mutual_recursion#Ada -- -- Hofstadter Female and Male sequences -- -- F : 1 1 2 2 3 3 4 5 5 6 6 7 8 8 9 9 10 11 11 12 13 13 14 14 -- M : 0 0 1 2 2 3 4 4 5 6 6 7 7 8 9 9 10 11 11 12 12 13 14 14 -- -- N : 1 1 1 -- 0 1 2 3 4 5 6 7 8 9 0 1 2 -- with HAT; with Testing_Utilities; procedure Forward is use HAT, Testing_Utilities; function M (N : Integer) return Integer; -- Forward declaration of M. function F (N : Integer) return Integer is begin if N = 0 then return 1; else return N - M (F (N - 1)); end if; end F; function M (N : Integer) return Integer is begin if N = 0 then return 0; else return N - F (M (N - 1)); end if; end M; begin Assert (4 = F (6), +"F (6)"); Assert (4 = M (6), +"M (6)"); Assert (8 = F (12), +"F (12)"); Assert (7 = M (12), +"M (12)"); end Forward; ================================================ FILE: test/future/block_statements.adb ================================================ -- Testing Block Statements -- -- RM: 5.6 Block Statements -- https://www.adaic.org/resources/add_content/standards/05rm/html/RM-5-6.html -- -- [declare] begin [exception] end procedure Block_Statements is begin L: for x in 1 .. 10 loop M: for y in 1 .. 10 loop declare procedure P is begin null; -- exit; -- "cannot exit from body or accept statement -- enclosed in loop (RM 5.7 (4))" L: for x in 1 .. 10 loop -- Another L exit L; end loop L; end; begin exit L; end; end loop M; end loop L; null; -- exit; -- "no loop to exit from" end Block_Statements; ================================================ FILE: test/hac_test.gpr ================================================ -- This is a GNAT, GCC or GNAT Studio project file -- for the examples of the HAC project -- ( http://hacadacompiler.sf.net/ or https://github.com/zertovitch/hac ). -- -- These examples give (or should give...) the same output on a real -- Ada compiler as when compiled and run by HAC. -- -- The official regression test for HAC is `all_silent_tests.adb` -- and runs most of the tests below. -- -- Build me with "gprbuild -P hac_test", or open me with GNAT Studio. -- project HAC_Test is type HAC_Build_Mode_Type is ("Debug", "Fast"); HAC_Build_Mode : HAC_Build_Mode_Type := external ("HAC_Build_Mode", "Debug"); for Main use ( "all_noisy_tests.adb", "all_silent_tests.adb", "silent_tests_single_build.adb", -- "attributes_test.adb", "case_statement.adb", "constants.adb", "declarations.adb", "digitz.adb", "enumerations.adb", "exception_01.adb", "exception_02.adb", "exception_03.adb", "exception_04.adb", "floats.adb", "forward.adb", "if_then_elsif_else.adb", "integers.adb", "loops.adb", "object_init.adb", "recursion.adb", "sorting_tests.adb", "strings.adb", "type_conversion.adb", "test.adb", "test1.adb" ); case HAC_Build_Mode is when "Debug" => for Object_Dir use "../obj/debug"; when "Fast" => for Object_Dir use "../obj/fast"; end case; for Source_Dirs use (".", "../src", "../exm"); for Exec_Dir use "."; for Create_Missing_Dirs use "True"; -- Flips by default the "-p" switch package Pretty_Printer is for Default_Switches ("ada") use ("-i2"); end Pretty_Printer; Common_Compiler_Options := ( "-gnatwa", -- Warnings switches (a:turn on all info/warnings marked with +) "-gnatwcijkmopruvz.c.p.t.w.x", -- Warnings switches (run "gnatmake" for full list) "-gnatwCKMUV", -- Warnings switches (turn OFF some that are irrelevant for the tests) "-gnatwh", -- Warnings switches (h:turn on warnings for hiding declarations) "-gnatf", -- Full errors. Verbose details, all undefined references "-gnatq", -- Don't quit, try semantics, even if parse errors "-gnatQ", -- Don't quit, write ali/tree file even if compile errors -- "-gnatyaknpr", -- Style: check all casings: a:attribute, k:keywords, n:package Standard identifiers, p:pragma, r:identifier references "-gnatybfhiu", -- Style: check b:no blanks at end of lines, f:no ff/vtabs, h: no htabs, i:if-then layout, u:no unnecessary blank lines "-gnatyx", -- Style: check x:no extra parens -- "-gnatye", -- Style: check e:end/exit labels present "-gnatytc" -- Style: check t:token separation rules, c:comment format (two spaces) ); Debug_Options := ( "-gnata", -- Assertions enabled "-gnato", -- Enable overflow checking in STRICT mode "-gnatVa", -- Enable all validity checking options "-fstack-check", "-fno-inline", -- "-g" -- Generate debugging information ); Fast_Options := ( "-O2", "-gnatpn", "-fipa-cp-clone", "-fgcse-after-reload", "-funroll-loops", "-fpeel-loops", "-funswitch-loops", "-ftracer", "-fweb", "-ftree-vectorize", "-frename-registers", "-ffunction-sections", "-g" ); package Compiler is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use Common_Compiler_Options & Debug_Options; when "Fast" => for Default_Switches ("ada") use Common_Compiler_Options & Fast_Options; end case; end Compiler; package Binder is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use ("-Es"); when "Fast" => end case; end Binder; package Linker is case HAC_Build_Mode is when "Debug" => for Default_Switches ("ada") use ("-g"); when "Fast" => for Default_Switches ("ada") use ("-s", "-Wl,--gc-sections"); end case; end Linker; package Builder is -- "If -j0 is used, then the maximum number of simultaneous compilation -- jobs is the number of core processors on the platform." for Default_Switches ("ada") use ("-g", "-j0"); end Builder; end HAC_Test; ================================================ FILE: test/if_then_elsif_else.adb ================================================ with HAT; use HAT; procedure If_Then_Elsif_Else is procedure Test (I : Integer) is begin Put (I); Put (" compared to 10, 20 and 30 is : "); if I < 10 then Put_Line ("the smallest"); elsif I < 20 then Put_Line ("in [10, 19]"); elsif I <= 30 then Put_Line ("in [20, 30]"); else Put_Line ("the largest"); end if; end Test; begin for J in 8 .. 32 loop Test (J); end loop; end If_Then_Elsif_Else; ================================================ FILE: test/integers.adb ================================================ -- Output should be empty if the compiler is correct. with HAT; with Testing_Utilities; procedure Integers is use HAT, Testing_Utilities; x1 : Integer; x2 : Integer; x3 : Integer; function Fibonacci (P : Integer) return Integer is begin if P <= 2 then return 1; else return Fibonacci (P - 1) + Fibonacci (P - 2); end if; end Fibonacci; type R is record x1 : Integer; x2 : Integer; x3 : Integer; end record; v : R; procedure Test_Patching is -- -1 is the value of dummy_address for patching IF jumps... patch_trap : constant := -1; pt : Integer; begin for i in 1 .. 1 loop -- SmallAda and early HAC versions patched all -- instructions with an operand = -1 !... pt := patch_trap; if -pt /= 1 then Put (pt); Failure (+" Compiler bug [Integers, IF Patch]"); end if; end loop; end Test_Patching; begin v.x1 := 1; v.x2 := 3; x3 := 5; v.x3 := 6; Assert (x3 = 5, +"Compiler bug [Integers, A]"); x1 := v.x1; Assert (x1 = 1, +"Compiler bug [Integers, B]"); x3 := v.x3; Assert (x3 = 6, +"Compiler bug [Integers, C]"); -- for i in 1 .. 10 loop v.x1 := Fibonacci (i); v.x2 := Fibonacci (i + 1); v.x3 := Fibonacci (i + 2); Assert (v.x1 - v.x3 + v.x2 = 0, +"Compiler bug [Integers, D]"); end loop; -- Assert (12_000 = 12e003, +"Compiler bug [Integers, E]"); -- Test_Patching; -- Assert (HAT.Max (1, 2) = 2, +"HAT.Max [1]"); Assert (HAT.Max (2, 1) = 2, +"HAT.Max [2]"); -- Assert (HAT.Min (1, 2) = 1, +"HAT.Min [1]"); Assert (HAT.Min (2, 1) = 1, +"HAT.Min [2]"); -- Assert (HAT.Sgn (123) = 1, +"HAT.Sgn [1]"); Assert (HAT.Sgn (0) = 0, +"HAT.Sgn [2]"); Assert (HAT.Sgn (-123) = -1, +"HAT.Sgn [3]"); end Integers; ================================================ FILE: test/loops.adb ================================================ -- Output should be empty if the compiler is correct. with HAT; with Testing_Utilities; procedure Loops is use HAT, Testing_Utilities; begin Ident_For : for i in 1 .. 10 loop exit when i = 5; Assert (i < 5, +"Compiler bug [A (missed exit]"); end loop Ident_For; -- for i in reverse 1 .. 10 loop exit when i = 5; Assert (i > 5, +"Compiler bug [B (missed exit]"); end loop; -- L1_a : for i in 10001 .. 10010 loop L2_a : for j in 20002 .. 20007 loop exit L1_a when i = 10005; -- exiting L2 would pass i = 10006, ... Assert (i < 10005, +"Compiler bug [C (missed exit]" & i'Image); end loop L2_a; end loop L1_a; -- L1_b : for i in 30001 .. 30010 loop L2_b : loop L3_b : for j in 40002 .. 40007 loop L4_b : for k in 50004 .. 50008 loop exit L1_b when i = 30005; -- exiting L2, L3, L4 would pass i = 30006, ... Assert (i < 30005, +"Compiler bug [D (missed exit]" & i'Image); end loop L4_b; end loop L3_b; exit L2_b; end loop L2_b; end loop L1_b; end Loops; ================================================ FILE: test/object_init.adb ================================================ -- Test object initialization, -- implicit or explicit. with HAT; with Testing_Utilities; procedure Object_Init is use HAT, Testing_Utilities; procedure Test_Atomics is -- Test "atomic" (<- in the PCode sense) variables, explicit -- initialization. procedure Atomic_Explicit is a, b, c : Integer := 777; d, e, f : constant Integer := 111; begin Assert (a - 666 = d and b / 7 = e and c + f = 888, +"Compiler bug [Atomic_Explicit]"); a := 3; b := 4; c := 5; end Atomic_Explicit; -- Test "atomic" (<- in the PCode sense) variables, implicit -- initialization. procedure Atomic_Implicit is a, b, c : VString; -- Initialized as empty VString's (= Unbounded_String's). begin a := a & b & "abc" & c; Assert (a = "abc", +"Compiler bug [Atomic_Implicit]"); b := +"gruik"; c := +"grrrr"; end Atomic_Implicit; tries : constant := 3; begin for trie in 1 .. tries loop Atomic_Explicit; end loop; for trie in 1 .. tries loop Atomic_Implicit; end loop; for trie in 1 .. tries loop Atomic_Explicit; Atomic_Implicit; end loop; end Test_Atomics; procedure Old_Tests is type Rec_1 is record i : Integer; r : Real; j : Integer; end record; subtype Arr_Range is Integer range 7 .. 13; type Arr_1 is array (Arr_Range, Arr_Range) of Rec_1; type Rec_2 is record n : Integer; a : Arr_1; end record; type Arr_2 is array (Boolean) of Rec_2; n1 : constant := 1234; n2 : constant := 4567; procedure Init_Nest_Arr (u : Arr_2; v : out Arr_2) is w1, w2 : Arr_2 := u; -- The actual test is here :-) . begin w1 (False).n := w2 (True).n; -- Does nothing meaningful w2 (False).n := w1 (True).n; -- Does nothing meaningful for r1 in Arr_Range loop for r2 in Arr_Range loop v (True).a (r1, r2).i := n1 * w1 (True).a (r1, r2).j; end loop; end loop; end Init_Nest_Arr; dummy_1 : Real := 101010.0; procedure Init_Nest_Rec (u : Rec_2; v : out Rec_2) is w1, w2 : constant Rec_2 := u; -- The actual test is here :-) . begin v.n := w2.n; -- Does nothing meaningful for r1 in Arr_Range loop for r2 in Arr_Range loop v.a (r1, r2).i := n2 * w1.a (r1, r2).j; end loop; end loop; end Init_Nest_Rec; dummy_2 : Integer := 1000 * 200 * 30; x, y, z : Arr_2; -- Two complicated data r : Rec_2; begin for b in Boolean loop x (b).n := n1; y (b).n := n2; -- for r1 in Arr_Range loop for r2 in Arr_Range loop x (b).a (r1, r2).i := r1; x (b).a (r1, r2).j := r1 * r2; end loop; end loop; y (b).a := x (b).a; end loop; -- Init_Nest_Arr (y, z); Assert (z (True).a (9, 11).i = 9 * 11 * n1, +"Compiler bug [Arr]"); Init_Nest_Rec (y (True), r); Assert (r.a (7, 13).i = 7 * 13 * n2, +"Compiler bug [Rec]"); end Old_Tests; begin Test_Atomics; Old_Tests; end Object_Init; ================================================ FILE: test/open_files.adb ================================================ -- Files f and g are left open (not closed) during the variables lifetime. -- `hac -v1 open_files.adb` will show their names. with HAT; procedure Open_Files is use HAT; procedure Sub is g : File_Type; begin Open (g, "floats.adb"); end; f : File_Type; begin Sub; Open (f, "open_files.adb"); end Open_Files; ================================================ FILE: test/optim.adb ================================================ -- This test is to be used with the "-a" option from the HAC command-line executable: -- hac -a optim.adb -- -- We check here some optimizations, such as the removal of unnecessary range checks. with HAT; procedure Optim is subtype Chiffre is Integer range 1 .. 9; subtype Fuzzy is Integer range -100 .. 8; type Animal is (ant, bat, cat, dog); subtype Beast is Animal; subtype Insect is Animal range ant .. ant; subtype Mammal is Animal range bat .. dog; procedure Assignment_No_Checks is x : Chiffre; a : Animal; i : Insect; begin x := 1; -- Low and high bound checks are optimized out. for j in 2 .. 9 loop x := j; -- Low and high bound checks are optimized out. end loop; -- i := dog; -- This issues (as it should) a compilation error. i := ant; a := i; end; procedure Assignment_Upper_Bound_Check_Only (y : Positive) is x : Chiffre; a : Animal; i : Insect; begin x := y; -- Low bound check is optimized out, high check remains. HAT.Put_Line (Animal'Image (Animal'Last)); HAT.Put_Line (Animal'Image (Insect'Last)); a := cat; i := a; -- HAC: run-time error on upper bound check. -- GNAT issues even a compile-time error! end; procedure Assignment_Lower_Bound_Check_Only (y : Fuzzy) is x : Chiffre; begin x := y; -- High bound check is optimized out, low check remains. end; procedure Assignment_Both_Checks (y : Integer) is x : Chiffre; begin x := y; -- Low and high bound checks remain. end; procedure Array_With_Check (y : Integer) is a : array (Chiffre) of Character; begin a (y) := 'x'; end; procedure Array_No_Check (y : Chiffre) is a : array (Chiffre) of Character; begin a (y) := 'x'; a (1) := 'a'; for idx in 2 .. 4 loop a (idx) := 'a'; end loop; for idx in Chiffre loop a (idx) := 'a'; end loop; for idx in a'Range loop a (idx) := 'a'; end loop; end; i : Integer; p : Positive; m5 : constant := -5; begin HAT.Put_Line (1 + (2 + (3 + 4))); -- Add_Multiple instruction HAT.Put_Line (1.0 + (2.0 + (3.0 + 4.0))); -- Add_Multiple instruction HAT.Put_Line (1 + 2 * 3); -- Mult_then_Add instruction HAT.Put_Line (1.0 + 2.0 * 3.0); -- Mult_then_Add instruction p := -m5; p := -(-5); i := 0; i := 5 + i * p; -- Mult_then_Add instruction -- -- i := -Integer'First; -- This issues (as it should) a compilation error. Assignment_No_Checks; Assignment_Upper_Bound_Check_Only (Chiffre'Last); i := -5; -- Fold K_PUSH_DISCRETE_LITERAL & K_UNARY_MINUS_INTEGER into K_PUSH_DISCRETE_LITERAL. end Optim; ================================================ FILE: test/recursion.adb ================================================ -- We check numerical recursive functions (and also a bit the -- correctness of array operations, and nested subprograms too). with HAT; with Testing_Utilities; procedure Recursion is use HAT, Testing_Utilities; function Fibonacci (P : Natural) return Positive is begin if P <= 2 then return 1; else return Fibonacci (P - 1) + Fibonacci (P - 2); end if; end Fibonacci; function Ackermann (M, N : Natural) return Positive is begin if M = 0 then return N + 1; elsif N = 0 then return Ackermann (M - 1, 1); else return Ackermann (M - 1, Ackermann (M, N - 1)); end if; end Ackermann; procedure Ackarray is M_Max : constant := 3; N_Max : constant := 4; type Storage is array (0 .. M_Max, 0 .. N_Max) of Integer; -- Noise_1 : constant Integer := 11111; A : Storage; Noise_2 : Integer; B : Storage; Noise_3 : Integer; begin for M in 0 .. M_Max loop for N in reverse 0 .. N_Max loop A (M, N) := Ackermann (M, N); end loop; end loop; -- Noise_2 := 22222; B := A; Noise_3 := 33333; -- for N in reverse 0 .. N_Max loop for M in 0 .. M_Max loop Assert (B (M, N) = Ackermann (M, N), +"Compiler bug [Recursion, Ackermannm, Array]"); end loop; end loop; -- Assert (Noise_1 + Noise_2 = Noise_3, +"Compiler bug [Stack]"); end Ackarray; procedure Nesting_Tests is -- We compute in an horribly complicated way the value: 2 ** Level - 1. -- This is for testing recursion *and* nested subprograms together. Max_L : constant := 20; type Usine_a_Gaz is record ant, bat : Real; N : Integer; cat, dog : Boolean; end record; procedure Nesting_Test_P is -- Outer calls inner and vice-versa. procedure Add_1_and_shift (U : in out Usine_a_Gaz; Level : Integer) is procedure Shift_and_add_1 (U : in out Usine_a_Gaz) is begin if Level > 1 then U.N := U.N * 2; Add_1_and_shift (U, Level - 1); end if; end Shift_and_add_1; begin U.N := U.N + 1; Shift_and_add_1 (U); end Add_1_and_shift; R : Usine_a_Gaz; begin for L in 1 .. Max_L loop R.N := 0; Add_1_and_shift (R, L); Assert (R.N = 2 ** L - 1, +"Compiler bug [Recursion, Nesting_Test_P]"); end loop; end Nesting_Test_P; procedure Nesting_Test_F is -- Outer calls inner and vice-versa. function Add_1_and_shift (N : Integer; Level : Integer) return Integer is function Shift_and_add_1 (N : Integer) return Integer is begin if Level > 1 then return Add_1_and_shift (N * 2, Level - 1); end if; return N; end Shift_and_add_1; begin return Shift_and_add_1 (N + 1); end Add_1_and_shift; begin for L in 1 .. Max_L loop Assert (Add_1_and_shift (0, L) = 2 ** L - 1, +"Compiler bug [Recursion, Nesting_Test_F]"); end loop; end Nesting_Test_F; begin Nesting_Test_P; Nesting_Test_F; end Nesting_Tests; begin Assert (Fibonacci (22) = 17_711, +"Compiler bug [Recursion, Fibonacci]"); Assert (Ackermann (3, 4) = 125, +"Compiler bug [Recursion, Ackermann]"); Ackarray; Nesting_Tests; end Recursion; ================================================ FILE: test/remarks_check.adb ================================================ -- Check for regression in HAC's production of remarks (warnings or notes). with HAT; with Testing_Utilities; procedure Remarks_Check is use HAT; -- Primitive file comparison for text files that should be identical. procedure File_Comp (name_1, name_2 : VString; ok : out Boolean) is f1, f2 : File_Type; l1, l2 : VString; begin ok := True; Open (f1, name_1); Open (f2, name_2); while not (End_Of_File (f1) or End_Of_File (f2)) loop Get_Line (f1, l1); Get_Line (f2, l2); if l1 /= l2 then Put_Line ("*** Difference found:"); Put_Line (name_1 & ':'); Put_Line (" " & l1); Put_Line (name_2 & ':'); Put_Line (" " & l2); ok := False; exit; end if; end loop; if ok then if not End_Of_File (f1) then Put_Line ("*** Difference found: " & name_1 & " is longer."); ok := False; elsif not End_Of_File (f2) then Put_Line ("*** Difference found: " & name_2 & " is longer."); ok := False; end if; end if; Close (f1); Close (f2); end File_Comp; procedure Check (letter : Character) is prefix : constant VString := +"remarks_" & letter & '_'; name_ok : constant VString := prefix & "ok.txt"; name_new : constant VString := prefix & "new.txt"; ok : Boolean; begin -- -r0 disables all remarks Shell_Execute (+".." & Directory_Separator & "hac -c -r0 -r" & letter & " ../exm/remarks.adb 2>" & name_new); File_Comp (name_ok, name_new, ok); if not ok then Testing_Utilities.Failure (+"Remarks_Check: possible regression in HAC's remarks (warnings or notes)"); end if; end Check; begin Check ('k'); Check ('r'); Check ('u'); Check ('v'); end Remarks_Check; ================================================ FILE: test/remarks_k_ok.txt ================================================ ../exm/remarks.adb: 24:3-4: note: variable "b0" is not modified, could be declared constant [-rk] ../exm/remarks.adb: 21:3-3: note: variable "g" is not modified, could be declared constant [-rk] ../exm/remarks.adb: 17:3-3: note: variable "d" is not modified, could be declared constant [-rk] ================================================ FILE: test/remarks_r_ok.txt ================================================ ../exm/remarks.adb: 13:7-16: note: "use" clause already applied, in same declarative part, for package "Interfaces" [-rr] ../exm/remarks.adb: 110:5-7: note: "when others" is redundant here: all values are already explicitly covered [-rr] ================================================ FILE: test/remarks_u_ok.txt ================================================ ../exm/remarks.adb: 30:6-7: note: parameter "c1" is not referenced [-ru] ../exm/remarks.adb: 29:6-7: note: parameter "b1" is not referenced [-ru] ../exm/remarks.adb: 28:6-7: note: parameter "a1" is not referenced [-ru] ../exm/remarks.adb: 43:6-7: note: parameter "b2" is not referenced [-ru] ../exm/remarks.adb: 93:13-15: note: procedure "Tom" is not referenced [-ru] ../exm/remarks.adb: 71:12-22: note: function "Max_Array_2" is not referenced [-ru] ../exm/remarks.adb: 60:12-20: note: function "Max_Array" is not referenced [-ru] ../exm/remarks.adb: 50:12-18: note: function "Useless" is not referenced [-ru] ../exm/remarks.adb: 41:13-26: note: procedure "OK_Read_Writes" is not referenced [-ru] ../exm/remarks.adb: 27:13-31: note: procedure "Missing_Read_Writes" is not referenced [-ru] ../exm/remarks.adb: 24:3-4: note: variable "b0" is not referenced [-ru] ../exm/remarks.adb: 23:19-20: note: item "y0" is not referenced [-ru] ../exm/remarks.adb: 20:3-3: note: variable "f" is never read [-ru] ../exm/remarks.adb: 19:3-3: note: variable "e" is never read [-ru] ../exm/remarks.adb: 17:3-3: note: variable "d" is not referenced [-ru] ../exm/remarks.adb: 16:13-13: note: procedure "C" is not referenced [-ru] ../exm/remarks.adb: 15:17-17: note: item "y" is not referenced [-ru] ../exm/remarks.adb: 15:14-14: note: item "x" is not referenced [-ru] ../exm/remarks.adb: 15:8-8: note: type "B" is not referenced [-ru] ../exm/remarks.adb: 14:3-3: note: variable "a" is not referenced [-ru] ================================================ FILE: test/remarks_v_ok.txt ================================================ ../exm/remarks.adb: 36:11-11: warning: parameter "d1" is read before it is ever written [-rv] ../exm/remarks.adb: 37:11-11: warning: parameter "e1" is read before it is ever written [-rv] ../exm/remarks.adb: 32:6-7: warning: parameter "d1" is read but never written [-rv] ../exm/remarks.adb: 30:6-7: warning: parameter "c1" is never written [-rv] ../exm/remarks.adb: 64:22-25: warning: variable "Max" is read before it is ever written [-rv] ../exm/remarks.adb: 77:26-29: warning: variable "Max_2" may be read before it is ever written [-rv] ../exm/remarks.adb: 97:15-15: warning: variable "I" is read before it is ever written [-rv] ../exm/remarks.adb: 94:6-6: warning: variable "I" is never written, but is possibly read [-rv] ../exm/remarks.adb: 115:13-13: warning: variable "h" is read before it is ever written [-rv] ../exm/remarks.adb: 22:3-3: warning: variable "h" is read but never written [-rv] ================================================ FILE: test/shell_test.adb ================================================ with HAT; use HAT; procedure Shell_Test is -- Corresponds to POSIX' WEXITSTATUS in common implementations. function Exit_Status (Shell_Result : Integer) return Integer is begin Return Shell_Result / 256 mod 256; end Exit_Status; -- Corresponds to POSIX' WSTOPSIG in common implementations. function Stop_Signal (Shell_Result : Integer) return Integer is begin Return Shell_Result / 256 mod 128; end Stop_Signal; -- Corresponds to POSIX' WTERMSIG in common implementations. function Termination_Signal (Shell_Result : Integer) return Integer is begin Return Shell_Result mod 128; end Termination_Signal ; procedure Pipe_Test (n: Integer) is r : Integer; command : constant VString := +"exit " & n; contents : VString; begin Put (+"Command: " & command & ". Result..."); Shell_Execute (command, r); Put (+" without pipe: " & r & ", POSIX: " & Exit_Status (r)); Shell_Execute (command, r, contents); Put (+", with pipe: " & r & ", POSIX: " & Exit_Status (r)); Shell_Execute (command & ">dummy_output.txt", r); Put (+", with explicit pipe: " & r & ", POSIX: " & Exit_Status (r)); New_Line; end Pipe_Test; -- begin for n in 0 .. 15 loop Pipe_Test (n); end loop; for n in 255 .. 258 loop Pipe_Test (n); end loop; end Shell_Test; ================================================ FILE: test/silent_tests_single_build.adb ================================================ -- Single-build version of All_Silent_Tests. -- Differences: -- - The test framework targets entirely the compiler used for the build around -- `silent_tests_single_build.adb`. -- - Reversely, All_Silent_Tests calls specifically HAC for individual tests. with HAT; with Attributes_Test, Case_Statement, Constants, Declarations, Enumerations, Floats, Forward, Integers, Loops, Object_Init, Recursion, Sorting_Tests, Strings, Type_Conversion; procedure Silent_Tests_Single_Build is use HAT; begin Put_Line ("Silent_Tests_Single_Build can be used for testing any Ada compiler."); New_Line; Put_Line (+"Please use All_Silent_Tests for specifically " & "and throughfully testing HAC (actual regression test)."); New_Line; Put_Line ("Attributes_Test"); Attributes_Test; Put_Line ("Case_Statement"); Case_Statement; Put_Line ("Constants"); Constants; Put_Line ("Declarations"); Declarations; Put_Line ("Enumerations"); Enumerations; Put_Line ("Floats"); Floats; Put_Line ("Forward"); Forward; Put_Line ("Integers"); Integers; Put_Line ("Loops"); Loops; Put_Line ("Object_Init"); Object_Init; Put_Line ("Recursion"); Recursion; Put_Line ("Sorting_Tests"); Sorting_Tests; Put_Line ("Strings"); Strings; Put_Line ("Type_Conversion"); Type_Conversion; end Silent_Tests_Single_Build; ================================================ FILE: test/sorting_tests.adb ================================================ -- Silent versions of merge_sort.adb and shell_sort.adb. -- We check the result. No output <=> compiler is correct. with HAT; with Testing_Utilities; procedure Sorting_Tests is use HAT; expected_result : constant String (1 .. 26) := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; procedure Merge is type Vector is array (1 .. 26) of Character; v : Vector; temp_array : Vector; max : Integer; cur_length : Integer; m : Integer; left, top_left : Integer; right, top_right : Integer; begin v := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; max := 26; -- cur_length := 1; while cur_length < max loop -- New phase temp_array := v; left := 1; m := 1; while left <= max loop -- Find pair of subarrays right := left + cur_length; top_left := right; if top_left > max then top_left := max + 1; end if; top_right := right + cur_length; if top_right > max then top_right := max + 1; end if; -- Merge subarrays -- Go until one subarray runs out while (left < top_left) and (right < top_right) loop if temp_array (left) <= temp_array (right) then v (m) := temp_array (left); left := left + 1; else v (m) := temp_array (right); right := right + 1; end if; m := m + 1; end loop; -- Now "copy tail" of whichever subarray remains while left < top_left loop v (m) := temp_array (left); m := m + 1; left := left + 1; end loop; while right < top_right loop v (m) := temp_array (right); right := right + 1; m := m + 1; end loop; left := top_right; end loop; -- Now double size of subarrays and go back for next phase cur_length := cur_length * 2; end loop; for k in 1 .. 26 loop Testing_Utilities.Assert (v (k) = expected_result (k), +"Wrong result in Merge Sort"); end loop; end Merge; procedure Shell is b : String (1 .. 26); i, j, step : Integer; step_size : array (1 .. 4) of Integer; stop : Boolean; temp : Character; begin b := "ZYXWVUTSRQPONMLKJIHGFEDCBA"; -- 'steps' contains decreasing increments for each -- pass. The last pass has increment 1. step_size (4) := 1; for pass in reverse 1 .. 3 loop step_size (pass) := 2 * step_size (pass + 1); end loop; for pass in 1 .. 4 loop step := step_size (pass); -- Do a straight insertion sort with 'step' as -- an increment instead of 1. i := step + 1; while i <= 26 loop temp := b (i); j := i; stop := False; while (j > step) and not stop loop j := j - step; if b (j) > temp then b (j + step) := b (j); else b (j + step) := temp; stop := True; end if; end loop; if not stop then b (1) := temp; end if; i := i + step; end loop; end loop; -- for pass in 1..npass for k in 1 .. 26 loop Testing_Utilities.Assert (b (k) = expected_result (k), +"Wrong result in Shell Sort"); end loop; end Shell; begin Merge; Shell; end Sorting_Tests; ================================================ FILE: test/strings.adb ================================================ with HAT; with Testing_Utilities; procedure Strings is use HAT, Testing_Utilities; s1, s2, s3, s4, s4_s4, s4_s4_copy : VString; Planck : constant Real := 6.62607015e-34; Pi_9_dgt : constant Real := 3.141592653; Avogadro : constant Real := 6.02214076e023; r : Real; fs_1 : String (4 .. 6); c : Character := '!'; type Enum is (U, V, W); subtype Str_6 is String (1 .. 6); procedure Test_String_Literal_Param (s : Str_6; i : Integer) is begin Assert (s = "world!", +"Literal string passed as value is incorrect"); Assert (i = 1234, +"Stack corruption following literal string passed as value"); end Test_String_Literal_Param; begin Test_String_Literal_Param ("world!", 1200 + 34); s4 := To_VString ("abc") & 'd' & "ef"; if s4 /= +"abcdef" then Failure (+"Comparing VString to VString, or converting Literal String to VString"); end if; if s4 /= "abcdef" then Failure (+"Comparing VString to Literal String"); end if; -- if Element (s4, 3) /= 'c' then Failure (+"VString Element"); end if; if Length (s4) /= 6 then Failure (+"VString Length"); end if; if Slice (s4, 3, 5) /= "cde" then Failure (+"VString Slice"); end if; -- s1 := +"ab"; s2 := +"cdef"; s3 := 'b' & s2; -- if s1 & s2 /= s4 then Failure (+"VString & VString"); end if; if s1 & "cdef" /= s4 then Failure (+"VString & String"); end if; if "ab" & s2 /= s4 then Failure (+"String & VString"); end if; if 'a' & s3 /= s4 then Failure (+"Character & VString"); end if; if 7 & s1 /= +"7ab" then Failure (+"Int & VString"); end if; -- if s1 & 7 /= +"ab7" then Failure (+"VStr & Int = +Str_Lit"); end if; if s1 & 7 /= "ab7" then Failure (+"VStr & Int = Str_Lit"); end if; -- if Real (3.14) & s2 /= "3.14cdef" then Failure (+"R & VString"); end if; if s2 & Pi_9_dgt /= "cdef3.141592653" then Failure (+"VString & R"); end if; if s2 & Avogadro /= +"cdef6.02214076E+23" then Failure (+"Compiler bug - HAC_Image for HAC_Float - Avogadro : " & Avogadro); Put_Line (Avogadro); end if; if s1 & Planck /= +"ab6.62607015E-34" then Failure (+"Compiler bug - HAC_Image for HAC_Float - Planck : " & Planck); Put_Line (Planck); Put_Line (Planck, 1, 7, 0); end if; if not (+"A" < +"B") then Failure (+"VString < VString"); end if; if not (+"AA" > +"A") then Failure (+"VString > VString"); end if; -- if not (+"A" <= +"B") then Failure (+"VString <= VString"); end if; if not (+"AA" >= +"A") then Failure (+"VString >= VString"); end if; if not (+"A" <= +"A") then Failure (+"VString <= VString"); end if; if not (+"A" >= +"A") then Failure (+"VString >= VString"); end if; -- if To_Lower (+"X") /= +"x" then Failure (+"To_Lower VString"); end if; if To_Lower ('X') /= 'x' then Failure (+"To_Lower Char"); end if; if To_Upper (+"x") /= +"X" then Failure (+"To_Upper VString"); end if; if To_Upper ('x') /= 'X' then Failure (+"To_Upper Char"); end if; -- if Index (s4, +"cat") /= 0 then Failure (+"Index, #1"); end if; if Index (s4, +"cde") /= 3 then Failure (+"Index, #2"); end if; if Index (s4, "cat") /= 0 then Failure (+"Index, #3"); end if; if Index (s4, "cde") /= 3 then Failure (+"Index, #4"); end if; -- s4_s4 := s4 & s4; -- abcdefabcdef -- 123456789012 if Index (s4_s4, +"cd") /= 3 or Index (s4_s4, "cd") /= 3 or Index (s4_s4, 'c') /= 3 then Failure (+"Index"); end if; if Index (s4_s4, +"cd", 4) /= 9 or Index (s4_s4, "cd", 4) /= 9 or Index (s4_s4, 'c', 4) /= 9 then Failure (+"Index, From"); end if; if Index_Backward (s4_s4, +"cd") /= 9 or Index_Backward (s4_s4, "cd") /= 9 or Index_Backward (s4_s4, 'c') /= 9 then Failure (+"Index_Backward"); end if; if Index_Backward (s4_s4, +"cd", 8) /= 3 or Index_Backward (s4_s4, "cd", 8) /= 3 or Index_Backward (s4_s4, 'c', 8) /= 3 then Failure (+"Index_Backward, From"); end if; s4_s4_copy := s4_s4; -- "abcdefabcdef" Delete (s4_s4_copy, 4, 6); Assert (s4_s4_copy = "abcabcdef", +"Delete"); -- if 0 * 'x' /= +"" then Failure (+"""*"", #1"); end if; if 10 * 'x' /= +"xxxxxxxxxx" then Failure (+"""*"", #2"); end if; if 0 * (+"Fritz") /= +"" then Failure (+"""*"", #3"); end if; if 3 * (+"Fritz") /= +"FritzFritzFritz" then Failure (+"""*"", #4"); end if; -- for i in -5 .. 5 loop if Integer_Value (Image (i)) /= i then Failure (+"Im/Val I"); end if; r := Real (i); if Float_Value (Image (r)) /= r then Failure (+"Im/Val R 1"); end if; r := Real (i) * 1.0e20; if Float_Value (Image (r)) /= r then Failure (+"Im/Val R 2"); end if; -- put_line (image(r)); end loop; -- fs_1 := "def"; if +fs_1 /= Slice (s4, 4, 6) then Failure (+"Fixed String to VString"); end if; if +"abc" & fs_1 /= +"abcdef" then Failure (+"VString & String"); end if; if fs_1 & (+"ghi") /= +"defghi" then Failure (+"String & VString"); end if; -- -- Strings_as_VStrings -- if Enum'Image (V) /= "V" then Failure (+"Strings_as_VStrings"); end if; -- -- Concatenation between the three String internal types or with Character. -- Codes in brackets like [12] are explained in String_Concatenation, -- HAC_Sys.Parser.Expressions. -- Assert (Enum'Image (U) & Enum'Image (V) = "UV", +"SVS_Concat, [11]"); Assert (Enum'Image (U) & fs_1 = "Udef", +"SVS_Concat, [12]"); Assert (Enum'Image (W) & "aw" = "Waw", +"SVS_Concat, [13]"); Assert (Enum'Image (U) & 'V' = "UV", +"SVS_Concat, [14]"); -- Assert (fs_1 & Enum'Image (W) = "defW", +"SVS_Concat, [21]"); Assert ("UB" & Enum'Image (U) = "UBU", +"SVS_Concat, [31]"); Assert ('U' & Enum'Image (V) = "UV", +"SVS_Concat, [41]"); -- Combinations without any Strings_as_VStrings. Assert (fs_1 & fs_1 = "defdef", +"SVS_Concat, [22]"); Assert (fs_1 & "xyz" = "defxyz", +"SVS_Concat, [23]"); Assert (fs_1 & '$' = "def$", +"SVS_Concat, [24]"); -- Assert ("hac" & fs_1 & c = "hacdef!", +"SVS_Concat, [32]"); Assert ("hac" & "xyz" & c = "hacxyz!", +"SVS_Concat, [33]"); Assert ("hac" & '$' & c = "hac$!", +"SVS_Concat, [34]"); -- Assert ('%' & fs_1 & c = "%def!", +"SVS_Concat, [42]"); Assert ('%' & "xyz" & c = "%xyz!", +"SVS_Concat, [43]"); Assert ('%' & '$' & c = "%$!", +"SVS_Concat, [44]"); -- if To_String (To_VString ("abcd") & (+"ef")) /= "abcdef" then Failure (+"String <-> VString, #1"); end if; -- -- Testing HAT functions -- Assert (not Starts_With (+"package", "proc"), +"SW_1"); Assert (not Starts_With (+"package", +"proc"), +"SW_2"); Assert (Starts_With (+"package", "pack"), +"SW_3"); Assert (Starts_With (+"package", +"pack"), +"SW_4"); -- Assert (not Ends_With (+"package", "proc"), +"EW_1"); Assert (not Ends_With (+"package", +"proc"), +"EW_2"); Assert (Ends_With (+"package", "age"), +"EW_3"); Assert (Ends_With (+"package", +"age"), +"EW_4"); -- Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", '/') = "gnx-startup", +"TAM_1"); Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", "ix") = "/gnx-startup", +"TAM_2"); Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", +"gene") = "six/gnx-startup", +"TAM_3"); Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", +"etc/genesix/gnx-startu") = "p", +"TAM_4"); Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", +"/etc/genesix/gnx-startu") = "p", +"TAM_5"); Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", +"/etc/genesix/gnx-startup") = "", +"TAM_6"); Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", +"/etc/genesix/gnx-startupp") = "", +"TAM_7"); Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", "/g") = "nx-startup", +"TAM_8"); -- Must match the last "/g" Assert (Tail_After_Match (+"/etc/genesix/gnx-startup", "/g") /= "enesix/gnx-startup", +"TAM_9"); -- Assert (Head_Before_Match (+"the quick brown fox jumps", "fox") = "the quick brown ", +"HBM_1"); Assert (Head_Before_Match (+"the quick brown fox jumps", "dog") = "", +"HBM_2"); Assert (Head_Before_Match (+"the quick brown fox jumps", "jumps ") = "", +"HBM_3"); Assert (Head_Before_Match (+"the quick brown fox jumps", +"quick") = "the ", +"HBM_4"); Assert (Head_Before_Match (+"the quick brown fox jumps", 'k') = "the quic", +"HBM_5"); -- -- The following test is in one answer of -- https://stackoverflow.com/questions/62080743/how-do-you-check-if-string-ends-with-another-string-in-ada Assert (Ends_With (+"John Johnson", "son") = True, +"EW_101"); Assert (Ends_With (+"", "") = True, +"EW_102"); Assert (Ends_With (+" ", "") = True, +"EW_103"); Assert (Ends_With (+"", " ") = False, +"EW_104"); Assert (Ends_With (+" ", " ") = True, +"EW_105"); Assert (Ends_With (+"", "n") = False, +"EW_106"); Assert (Ends_With (+"n", "") = True, +"EW_107"); Assert (Ends_With (+"n ", "n ") = True, +"EW_108"); Assert (Ends_With (+" n", "n") = True, +"EW_109"); Assert (Ends_With (+"n", " n") = False, +"EW_110"); Assert (Ends_With (+" n", " n") = True, +"EW_111"); end Strings; ================================================ FILE: test/t.cmd ================================================ @echo off rem HAC regression test rem ------------------- rem This script is basically the command "hac -v2 all_silent_tests.adb" rem preceded by a potential rebuild of the hac executable. echo (Re-)building HAC cd.. set hacbuild=unknown gprbuild -P hac.gpr hac if NOT "%ERRORLEVEL%" == "0" goto hac_build_failed cd test set hacbuild=done if "%1"=="" goto regression_tests rem Try without extension if exist %1.adb ..\hac -v2 %1.adb if exist %1.adb goto fin rem Try with extension ..\hac -v2 %1 goto fin :regression_tests rem Here HAC will call itself for each test!... ..\hac -v2 all_silent_tests.adb pause goto fin :verbose_tests ..\hac -v2 all_noisy_tests.adb goto fin :gnat rem ******* Building all tests with GNAT. gprbuild hac_test.gpr echo ******* Running all tests with GNAT. for %%e in (*.exe) do %%e pause goto fin :hac_build_failed echo --- HAC build failed (called from t.cmd) --- cd test :fin set hacbuild=unknown ================================================ FILE: test/test.adb ================================================ -- This is a fuzzy test for HAC, the HAC Ada compiler. -- -- Historically, this was the first program to -- run with HAC after "hello world". -- -- The official regression test for HAC is `all_silent_tests.adb`. with HAT; use HAT; procedure Test is -- type Type1 is record x : Integer; y : Real; end record; -- z1 : Type1; -- function Add (x, y : Integer) return Integer is value : Integer; begin value := x + y; return value; end Add; -- x_glob : Integer; procedure Do_0 is begin x_glob := 54321; end Do_0; -- procedure Do_1 (a : Integer) is begin x_glob := a; end Do_1; -- procedure Do_1_param_in_out (a : in out Integer) is sept : constant := 7; septante : constant Integer := 70; begin a := septante + sept; Put_Line ("NOT in a block statement"); a := 700 + a; -- -- *** Block statements temporarily disabled (details in roland_01.adb) *** -- -- What_a_nice_block: -- declare -- sept_cents: constant Integer:= 700; -- sept * 100 too complicated !! -- begin -- a:= sept_cents + a; -- Put_Line("Block statement"); -- end What_a_nice_block; -- Put_Line("NOT in a block statement"); -- what_a_nice_block_2: -- begin -- Put_Line("Another block statement"); -- what_a_NICE_block_3: -- begin -- Put_Line("Yet another block statement"); -- end what_a_NICE_block_3; -- end what_a_nice_block_2; -- Put_Line("NOT in a block statement"); end Do_1_param_in_out; -- -- type My_String is array(1..5) of Character; -- s: String(1..5); -- ms: My_String; -- -- ----------------------------------------------- -- Recursive Fibonacci numbers demonstration -- ----------------------------------------------- procedure Fibo_demo (X : Natural) is function Fib (P : Natural) return Positive is begin if P <= 2 then return 1; else return Fib (P - 1) + Fib (P - 2); end if; end Fib; begin Put (" Fibonacci("); Put (X, 2); Put (") = "); Put (Fib (X), 5); New_Line; end Fibo_demo; ------------------------------------- -- Testing multidimensional arrays -- ------------------------------------- procedure Test_multi_arrays is l1 : constant := -3; h1 : constant := 9; l2 : constant := 1; h2 : constant := 6; type T1 is array (l1 .. h1, l2 .. h2) of Integer; a : T1; b : array (l1 .. h1, l2 .. h2) of Real; type T2 is array (6 .. 9) of Integer; type T3 is record x : Integer; y : T2; end record; c : array (l1 .. h1, l2 .. h2) of T3; begin for step in 1 .. 6 loop -- !! HAC: compiles 1..7 OK without "when 7", interpreter crashes Put ("Multidimensional array: Step"); Put (step); New_Line; for i in l1 .. h1 loop for j in l2 .. h2 loop case step is when 1 => -- fill array a a (i, j) := i * j; when 2 => -- display array a Put (a (i, j)); if j = h2 then New_Line; end if; when 3 => -- fill array b -- HAC 0.01 accepted "b(i,j):= i * j" without Real(...); b (i, j) := Real (i * j); when 4 => -- display array b Put (b (i, j), 5, 1, 0); -- Fore, Aft, Exp. Put (' '); if j = h2 then New_Line; end if; when 5 => -- fill array c c (i, j).y (7) := i * j; when 6 => -- display array c Put (c (i, j).y (7)); if j = h2 then New_Line; end if; end case; end loop; end loop; end loop; end Test_multi_arrays; Twenty : constant := 20; Ten_point_one : constant := 10.1; c : Character; -- ABCDEFGHIJKLMNOPQRSTUVWXYZ: Character; -- Testing a long identifier hs : String (1 .. 7); procedure Show_hs is begin Put_Line (hs); end Show_hs; procedure Int_Layout is procedure IL_Base (b : Integer) is procedure IL_Val (i : Integer) is procedure IL_Width (w : Integer) is begin -- if i >= 0 then Put (' '); end if; Put ('['); Put (i, w, b); Put (']'); end IL_Width; begin Put (" "); for w in 0 .. 4 loop IL_Width (w); end loop; IL_Width (8); IL_Width (12); New_Line; end IL_Val; begin IL_Val (+123); IL_Val (-123); end IL_Base; begin Put_Line ("Integer layout: "); IL_Base (2); IL_Base (10); IL_Base (16); end Int_Layout; procedure Float_Layout is procedure FL_Exp (e : Integer) is procedure FL_Val (r : Real) is procedure FL_Fore (f : Integer) is begin -- if i >= 0 then Put (' '); end if; Put ('['); Put (r, f, 2, e); Put (']'); end FL_Fore; begin Put (" "); for w in 0 .. 5 loop FL_Fore (w); end loop; New_Line; end FL_Val; begin FL_Val (+123.0); FL_Val (-123.0); end FL_Exp; begin Put_Line ("Float layout: "); FL_Exp (0); FL_Exp (4); end Float_Layout; begin Put ('A'); c := 'B'; Put (c); c := '''; Put (c); Put ('"'); Put (""); New_Line; -- hs := """Hello"""; Show_hs; hs := """Hel""lo"; Show_hs; hs := "Hel""lo"""; Show_hs; hs := "Hel""l""o"; Show_hs; hs := "Hel'l'o"; Show_hs; -- Int_Layout; Float_Layout; -- My_Put(s, 1 , 5); New_Line; Put (Twenty); Put_Line (" ... should be: 20"); Put (Ten_point_one); Put_Line (" ... should be: 1.01000E+01"); x_glob := 123; z1.x := Add (432, x_glob); -- then: z1.x = 555 Put (z1.x); Put_Line (" ... should be: 555"); z1.y := 1.8; Put (z1.y); Put_Line (" ... should be: 1.80000E+00"); Put_Line ("Do_0: output 54321"); Do_0; Put (x_glob); New_Line; Put_Line ("6-3+2 = 5"); Put (6 - 3 + 2); New_Line; -- Do_1 (123); Do_1_param_in_out (x_glob); case x_glob is when 123 => Put ("123 (wrong)"); when 456 => Put ("456 (wrong)"); when 777 => Put ("777 (correct)"); when others => Put (x_glob); Put (" (wrong)"); end case; New_Line; Put ("Bla bla"); Put (""); Put_Line (" and more bla bla!"); for gagl in 1 .. 20 loop Put (gagl); Put (" choice : "); case gagl is when 4 => Put_Line ("... four"); when 2 => Put_Line ("... two"); when 7 => Put_Line ("... seven"); when others => Put (gagl, 1); Put_Line (" (others)"); end case; exit when gagl = 8; end loop; -- Put_Line ("Recursive Fibonacci:"); for n in 1 .. 22 loop Fibo_demo (n); end loop; -- Test_multi_arrays; end Test; ================================================ FILE: test/test1.adb ================================================ -- This was the initial test program for the Small-Ada Compiler. -- Small-Ada is a restricted subset of the full Ada Language. -- The Small-Ada compiler was derived from the Co-Pascal -- compiler which in turn was derived from Pascal-S. -- -- The official regression test for HAC is `all_silent_tests.adb`. with HAT; use HAT; procedure Test1 is -- Declarations Ten : constant Integer := 10; -- Integer (* test *) Twenty : constant := 20; Zwanzig : Integer; Ten_plus_0_Point_One : constant := 10.1; -- Real CA : constant Character := 'A'; -- Character CE : constant Character := 'E'; -- Character B1, B2 : constant Boolean := True; -- Boolean type Type1 is record X : Integer; Y : Real; end record; -- TYPE Type2 IS String(1..10); type Type3 is array (1 .. 4) of Type1; -- TYPE Type4 IS RECORD -- ay: array(1..Ten) of integer; -- END RECORD; type Day is (Sun, Mon, Tue, Wed, Thu, Fri, Sat); I1, I2, I3 : Integer := 99; I4 : constant Integer := -I1 + 10; R1 : Real := 1.23; R2 : Real := Ten_plus_0_Point_One; C2 : constant Character := '+'; C1 : constant Character := '+'; C3 : constant Character := CA; B3, B4, B5 : Boolean := False; X3 : Type3; A : array (1 .. 5) of Integer; r : Real; function Add (X, Y : Integer) return Integer is Value : Integer; begin Value := X + Y; return Value; end Add; procedure IComp (X, Y : Integer) is begin if X <= Y then Put ("In "); Put_Line ("Order"); else Put_Line ("Reverse Order"); end if; end IComp; weekday : Day; procedure Comp_10_20 (I1 : Integer) is begin Put (I1); Put (" compared to 10 and 20 is : "); if I1 < 10 then Put_Line ("the smallest"); elsif I1 < 20 then Put_Line ("in the middle"); else Put_Line ("the largest"); end if; end Comp_10_20; begin for d in Sun .. Sat loop case d is when Sun => Put ("Sunday. "); when Mon => Put ("Monday. "); when Tue => Put ("Tuesday. "); when Wed => Put ("Wednesday. "); when Thu => Put ("Thursday. "); when Fri => Put ("Friday! "); weekday := d; when Sat => Put ("Saturday."); end case; end loop; New_Line; for i in 1 .. 4 loop X3 (i).X := i; X3 (i).Y := Real (i); end loop; r := 1.0; for i in 1 .. 4 loop r := r * X3 (i).Y; end loop; Put_Line (+"Expected: 24, computed: " & r); -- CONSTANT Check Put_Line ("CONSTANT Check"); Put ("Ten = "); Put_Line (Ten); Put ("Twenty = "); Put (Twenty, 11, 16); Put_Line (" in base 16"); Put ("Ten_plus_0_Point_One = "); Put (Ten_plus_0_Point_One, 10, 16); Put_Line (" with 16 digits"); Put ("Ten_plus_0_Point_One = "); Put (Ten_plus_0_Point_One, 10, 16, 0); Put_Line (" with 16 digits, no exponent"); Put ("CA = "); Put (CA); New_Line; Put ("B1, B2 = "); Put (B1); Put (' '); Put_Line (B2); New_Line; Put_Line ("Initialization Check"); Put ("i1, i2, i3 "); Put (I1); Put (I2); Put (I3); New_Line; Put ("i4 "); Put (I4); New_Line; Put_Line ("r1, r2 (1.23, 10.1): "); Put (R1); Put (R2); New_Line; Put_Line ("c1, c2, c3 (++A):"); Put (C1); Put (C2); Put (C3); New_Line; Put_Line ("b1, .., b5. Expected: (T,T,F,F,F):"); Put (" "); Put (B1); Put (' '); Put (B2); Put (' '); Put (B3); Put (' '); Put (B4); Put (' '); Put (B5); New_Line; B3 := weekday = Fri; B4 := weekday /= Mon; B5 := B3 = not B4; Put_Line ("b1, .., b5. Expected: (T,T,T,T,F):"); Put (" "); Put (B1); Put (' '); Put (B2); Put (' '); Put (B3); Put (' '); Put (B4); Put (' '); Put (B5); New_Line; New_Line; Put_Line ("ARITHMETIC Check"); I1 := 13; Put (I1); Put_Line (" (i1:= 13)"); I2 := Ten; Put (I2); Put_Line (" (i2:= 10)"); I3 := I1 + I2 + 5; Put (I3); Put_Line (" (i3:= i1+i2+5 = 28)"); I3 := I1 - Twenty; Put (I3); Put_Line (" (i3:= i1-20 = -7)"); I3 := I2 * I1; Put (I3); Put_Line (" (i3:= i1*i2 = 130)"); I3 := I1 / 5; Put (I3); Put_Line (" (i3:= i1 DIV 5)"); I3 := I1 mod 5; Put (I3); Put_Line (" (i3:= i1 MOD 5)"); R1 := 20.4; Put (R1); Put_Line (" (r1:= 20.4)"); R2 := R1 / 2.0; Put (R2); Put_Line (" (r2:= r1/2.0 = 10.2)"); Put (10.0 * Ten_plus_0_Point_One); Put_Line (" (10*10.1)"); New_Line; Put_Line ("LOOP and ARRAY Check"); I1 := 10; Put_Line ("Single FOR LOOP 1..5: filling array"); for I in 1 .. 5 loop A (I) := I * 2; end loop; Put_Line ("Single FOR LOOP 1..5: reading array"); for N in 1 .. 5 loop Put (" n = "); Put (N); Put ("; a(n) = n*2 = "); Put (A (N)); New_Line; end loop; New_Line; Put_Line ("Double FOR LOOP: 1..2, then A..E"); for I in 1 .. 2 loop Put (" Line: "); Put (I); Put (' '); for J in CA .. CE loop Put (J); end loop; New_Line; end loop; Put_Line ("Reverse FOR LOOP 1..7"); for I1 in reverse 1 .. 7 loop Put (I1); end loop; Put (" i1 = "); Put (I1); New_Line (2); Put_Line ("WHILE Check 1..5"); I1 := 0; while I1 < 5 loop I1 := I1 + 1; Put (I1); end loop; New_Line; -- REPEAT Check New_Line; Put_Line ("REPEAT Check, until Ten"); loop Put_Line (+"Rpt " & I1); I1 := I1 + 1; exit when I1 = Ten; end loop; New_Line; -- Function and Procedure Check New_Line; Put_Line ("FUNCTION and PROCEDURE Check"); Put (" compare 10 to 20 "); IComp (Ten, Twenty); Put (" compare 20 to 10 "); IComp (Twenty, Ten); Put (Ten); Put (5); Put (" ADD = "); Put (Add (Ten, 5)); New_Line; New_Line; Put_Line ("IF and BOOLEAN Check"); Zwanzig := Ten + Ten + X3 (3).X - 3; if Ten > Zwanzig then Put (Ten); Put ('>'); Put (Twenty); Put_Line ("O_o: bug with IF or with "">"" operator"); else Put (Ten); Put ("<="); Put (Twenty); Put_Line (" (Waw, the "">"" operator works on integers)"); end if; Comp_10_20 (-6); Comp_10_20 (99); Comp_10_20 (19); New_Line; if not False then Put_Line ("(1/2) NOT is OK"); else Put_Line ("(1/2) NOT is not OK"); end if; if not True then Put_Line ("(2/2) NOT is not OK"); else Put_Line ("(2/2) NOT is OK"); end if; New_Line; if False and False then Put_Line ("(1/4) AND is not OK"); else Put_Line ("(1/4) AND is OK"); end if; if True and False then Put_Line ("(2/4) AND is not OK"); else Put_Line ("(2/4) AND is OK"); end if; if False and True then Put_Line ("(3/4) AND is not OK"); else Put_Line ("(3/4) AND is OK"); end if; if True and True then Put_Line ("(4/4) AND is OK"); else Put_Line ("(4/4) AND is not OK"); end if; New_Line; if False or False then Put_Line ("(1/4) OR is not OK"); else Put_Line ("(1/4) OR is OK"); end if; if True or False then Put_Line ("(2/4) OR is OK"); else Put_Line ("(2/4) OR is not OK"); end if; if False or True then Put_Line ("(3/4) OR is OK"); else Put_Line ("(3/4) OR is not OK"); end if; if True or True then Put_Line ("(4/4) OR is OK"); else Put_Line ("(4/4) OR is not OK"); end if; New_Line; if False xor False then Put_Line ("(1/4) XOR is not OK"); else Put_Line ("(1/4) XOR is OK"); end if; if True xor False then Put_Line ("(2/4) XOR is OK"); else Put_Line ("(2/4) XOR is not OK"); end if; if False xor True then Put_Line ("(3/4) XOR is OK"); else Put_Line ("(3/4) XOR is not OK"); end if; if True xor True then Put_Line ("(4/4) XOR is not OK"); else Put_Line ("(4/4) XOR is OK"); end if; New_Line; if False and then False then Put_Line ("(1/4) AND THEN is not OK"); else Put_Line ("(1/4) AND THEN is OK"); end if; if True and then False then Put_Line ("(2/4) AND THEN is not OK"); else Put_Line ("(2/4) AND THEN is OK"); end if; if False and then True then Put_Line ("(3/4) AND THEN is not OK"); else Put_Line ("(3/4) AND THEN is OK"); end if; if True and then True then Put_Line ("(4/4) AND THEN is OK"); else Put_Line ("(4/4) AND THEN is not OK"); end if; New_Line; if False or else False then Put_Line ("(1/4) OR ELSE is not OK"); else Put_Line ("(1/4) OR ELSE is OK"); end if; if True or else False then Put_Line ("(2/4) OR ELSE is OK"); else Put_Line ("(2/4) OR ELSE is not OK"); end if; if False or else True then Put_Line ("(3/4) OR ELSE is OK"); else Put_Line ("(3/4) OR ELSE is not OK"); end if; if True or else True then Put_Line ("(4/4) OR ELSE is OK"); else Put_Line ("(4/4) OR ELSE is not OK"); end if; New_Line; -- CASE Check Put_Line ("CASE Check"); I1 := -1; Put ("Selector value ="); Put (I1); New_Line; case I1 is when 1 | 2 => Put ("Case is 1 or 2 ..."); Put_Line ("that's OK"); when 3 => Put_Line ("Case = 3, "); when 4 => Put_Line ("Case = 4, "); when others => Put ("Case is "); Put_Line ("Others (not 1,2,3,4)"); end case; New_Line; Put_Line ("END OF TEST"); end Test1; ================================================ FILE: test/test_tail_after_match.adb ================================================ with HAT; procedure Test_Tail_After_Match is use HAT; Path : VString := +"/etc/genesix/gnx-startup"; begin Put_Line (Tail_After_Match (Path, '/')); -- returns "gnx-startup" Put_Line (Tail_After_Match (Path, "ix")); -- returns "/gnx-startup" Put_Line (Tail_After_Match (Path, "gene")); -- returns "six/gnx-startup" Put_Line (Tail_After_Match (Path, "etc/genesix/gnx-startu")); -- returns "p" Put_Line (Tail_After_Match (Path, "/etc/genesix/gnx-startu")); -- returns "p" Put_Line (Tail_After_Match (Path, "/etc/genesix/gnx-startup")); -- returns empty string Put_Line (Tail_After_Match (Path, +"/etc/genesix/gnx-startupp")); -- returns empty string Put_Line (Tail_After_Match (Path, +"/etc/geneseven")); -- returns empty string end Test_Tail_After_Match; ================================================ FILE: test/testing_utilities.adb ================================================ package body Testing_Utilities is use HAT; function OK_Code return Integer is begin return 0; -- 0 is the default exit code. end OK_Code; procedure Failure (Message : VString) is begin Put_Line (+" ----> Failure in test: [" & Message & ']'); Set_Exit_Status (1); -- Test failed. end Failure; procedure Assert (Check : in Boolean; Message : VString) is begin if not Check then Failure (Message & ", assertion"); end if; end Assert; end Testing_Utilities; ================================================ FILE: test/testing_utilities.ads ================================================ with HAT; package Testing_Utilities is function OK_Code return Integer; procedure Failure (Message : HAT.VString); procedure Assert (Check : in Boolean; Message : HAT.VString); -- Similar to pragma Assert (RM 11.4.2) but sets an exit status -- instead of raising an exception. end Testing_Utilities; ================================================ FILE: test/tf.cmd ================================================ @echo off rem HAC regression test rem ------------------- rem Regression test in "fast" mode. echo (Re-)building HAC cd.. del hac.exe gprbuild -XHAC_Build_Mode=Fast -P hac -largs obj/hac_icon.rbj cd test set hacbuild=done ..\hac -v2 all_silent_tests.adb pause ================================================ FILE: test/toa.cmd ================================================ @echo off echo HAC, *ObjectAda* build cd.. COPY /b hac_objectada-Win32(Intel)-Debug\hac.exe . cd test set hacbuild=done if "%1"=="" goto gallery rem Try without extension if exist %1.adb ..\hac -v2 %1.adb if exist %1.adb goto fin rem Try with extension ..\hac -v2 %1 goto fin :gallery REM We run the *GNAT-Compiled* executable of all_silent_tests REM Reason is that Shell_Execute in HAC compiled by OA fails. all_silent_tests.exe REM ..\hac -v2 all_silent_tests.adb pause goto fin :verbose_tests ..\hac -v2 if_then_elsif_else.adb goto fin :gnat rem ******* Building all tests with GNAT. gprbuild hac_test.gpr echo ******* Running all tests with GNAT. for %%e in (*.exe) do %%e pause :fin ================================================ FILE: test/ts.cmd ================================================ @echo off rem HAC regression test rem ------------------- rem Regression test in "small" mode. echo (Re-)building HAC cd.. del hac.exe gprbuild -XHAC_Build_Mode=Small -P hac -largs obj/hac_icon.rbj strip -s hac*.exe cd test set hacbuild=done ..\hac -v2 all_silent_tests.adb pause ================================================ FILE: test/type_conversion.adb ================================================ -- This example contains a feature that was missing in HAC 0.01 but is present in HAC 0.02. -- -- 4.6 Type Conversions with HAT; with Testing_Utilities; procedure Type_Conversion is use HAT, Testing_Utilities; function To_Int (x : Real) return Integer is begin return Integer (x); end To_Int; subtype Day_Range is Integer range 1 .. 31; i, j : Integer; x, y : Real; d, e : Duration; oa_duration_delta : constant := 0.00006103515625; -- ObjectAda Win 32 & 64: type Duration is delta 2.0**(-14) range -131072.0..+131072.0-2.0**(-14); dd : Day_Range; begin i := 1234; x := Real (i); -- dd := Day_Range (x); -- <---- This should raise a Constraint_Error (not in range) -- dd := 1; i := dd; x := 0.0 * x + 2.0; y := x + Real (i); j := i + To_Int (3.51); -- Assert (y = 3.0, +"Compiler bug [Type_Conversion, A]"); Assert (j = 5, +"Compiler bug [Type_Conversion, B]"); -- -- Duration <-> Real -- d := 0.01; e := Duration (0.2 * 5.0); delay d; x := Real (d); if abs (x * 100.0 - Real (e)) > 100.0 * oa_duration_delta then Put_Line ("Type_Conversion, Compiler bug [C]"); Put_Line (+"100 * x = " & 100.0 * x); Put_Line (+"e = " & Image (e)); Failure (+""); end if; end Type_Conversion; ================================================ FILE: test/verif_hac.aru ================================================ ------------------------------------------------ -- AdaControl verification rules -- -- https://www.adalog.fr/en/adacontrol.html -- ------------------------------------------------ -- Set for HAC (HAC Ada Compiler). -------------------------------------- -- (1) Required ("check" command) -- -------------------------------------- check style (no_closing_name); check style (negative_condition); check style (casing_keyword, lowercase); ------------------------------------------------------------------ -- (2) Acceptable, but should be looked at ("search" command) -- ------------------------------------------------------------------ search simplifiable_statements;