" Your flight departs in a few days from the coastal airport;
" the easiest way down to the coast from here is via toboggan.

" The shopkeeper at the North Pole Toboggan Rental Shop is having a bad day.
" "Something's wrong with our computers; we can't log in!" You ask if you can take a look.

" Their password database seems to be a little corrupted:
" some of the passwords wouldn't have been allowed by the Official Toboggan Corporate Policy
" that was in effect when they were chosen.

" To try to debug the problem, they have created a list (your puzzle input)
" of passwords (according to the corrupted database) and the corporate policy when that password was set.

" For example, suppose you have the following list:

" 1-3 a: abcde
" 1-3 b: cdefg
" 2-9 c: ccccccccc

" 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.

" In the above example, 2 passwords are valid. The middle password, cdefg, is not;
" it contains no instances of b, but needs at least 1. The first and third passwords are valid:
" they contain one a or nine c, both within the limits of their respective policies.

" How many passwords are valid according to their policies?

" Your puzzle answer was 519.

" --- Part Two ---
" While it appears you validated the passwords correctly,
" they don't seem to be what the Official Toboggan Corporate Authentication System is expecting.

" The shopkeeper suddenly realizes that he just accidentally explained the password policy rules from his old job
" at the sled rental place down the street! The Official Toboggan Corporate Policy actually works a little differently.

" Each policy actually describes two positions in the password, where 1 means the first character,
" 2 means the second character, and so on. (Be careful; Toboggan Corporate Policies have no concept of "index zero"!)
" Exactly one of these positions must contain the given letter.
" Other occurrences of the letter are irrelevant for the purposes of policy enforcement.

" Given the same example list from above:

" 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.

" How many passwords are valid according to the new interpretation of the policies?

" Your puzzle answer was 708.

CLASS zcl_advent2020_day02_schmelto DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES zif_advent2020_schmelto .

    TYPES: BEGIN OF ty_password,
             min      TYPE string,
             max      TYPE string,
             letter   TYPE c LENGTH 1,
             password TYPE string,
           END OF ty_password.

    TYPES: ty_passwords TYPE STANDARD TABLE OF ty_password WITH EMPTY KEY.
    METHODS parse
      IMPORTING
        !input                   TYPE string
      RETURNING VALUE(passwords) TYPE ty_passwords.
    METHODS part1
      IMPORTING
        !input        TYPE string
      RETURNING
        VALUE(output) TYPE string .
    METHODS part2
      IMPORTING
        !input        TYPE string
      RETURNING
        VALUE(output) TYPE string .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_advent2020_day02_schmelto IMPLEMENTATION.

  METHOD parse.

    DATA strings TYPE STANDARD TABLE OF string.
    DATA password LIKE LINE OF passwords.

    SPLIT input AT |\r\n| INTO TABLE strings.

    LOOP AT strings INTO DATA(string).
      CLEAR password.
      FIND REGEX '(\d+)-(\d+) (\w): (\w+)' IN string
        SUBMATCHES password-min password-max password-letter password-password.
      ASSERT sy-subrc = 0.
      APPEND password TO passwords.
    ENDLOOP.

  ENDMETHOD.

  METHOD part1.

    DATA(passwords) = parse( input ).
    DATA(valid) = 0.

    LOOP AT passwords INTO DATA(password).
      FIND ALL OCCURRENCES OF password-letter IN password-password MATCH COUNT DATA(count).
      IF count BETWEEN password-min AND password-max.
        valid = valid + 1.
      ENDIF.
    ENDLOOP.

    output = valid.
    CONDENSE output.

  ENDMETHOD.

  METHOD part2.

    DATA(lt_passwords) = parse( input ).
    DATA(lv_valid) = 0.

    LOOP AT lt_passwords INTO DATA(ls_password).
      DATA(lv_pos1) = ls_password-min - 1.
      DATA(lv_pos2) = ls_password-max - 1.

      DATA(lv_val1) = ls_password-password+lv_pos1(1).
      DATA(lv_val2) = ls_password-password+lv_pos2(1).

      IF ( lv_val1 = ls_password-letter AND lv_val2 <> ls_password-letter )
          OR ( lv_val1 <> ls_password-letter AND lv_val2 = ls_password-letter ).
        lv_valid = lv_valid + 1.
      ENDIF.
    ENDLOOP.

    output = lv_valid.
    CONDENSE output.

  ENDMETHOD.

  METHOD zif_advent2020_schmelto~solve.

    output = part2( input ).

  ENDMETHOD.
ENDCLASS.