DEV Community

Samuel Nitsche
Samuel Nitsche

Posted on • Originally published at cleandatabase.wordpress.com on

Advent Of Code 2020 in SQL – Day 2: “Password Philosophy”

Today’s challenge is to analyze a given list of passwords towards the provided policy.

The policy of part 1 is that the given character must occur in the password inside a given threshold – sounds like we could use some regex.

The biggest challenge – again – was to get the input data into the database (I want to avoid setting up tables if I can). sys.odcivarchar2list seems like a good choice, but the input has 1000 entries and the constructor of odcivarchar2list only supports 999 items.

Luckily, we got the UNION ALL operator 🙂

select column_value line from table(sys.odcivarchar2list(
      '9-10 m: mmmmnxmmmwm',
      '6-8 w: wpwwhxnv',
      ... -- up to 999 items
      ))
    union all
    select column_value from table(sys.odcivarchar2list('17-18 b: jnlntbblbbqbkqmbbb'))
Enter fullscreen mode Exit fullscreen mode

To make the implementation more readable, I use a lot of WITH-selects. Thanks to regexp_substrfor parsing and regexp_countit’s straight forward to solve the puzzle.

with
  input as (
    select column_value line 
    from table(sys.odcivarchar2list(...))
  ),
  regex_pattern as (
    select '([0-9]+)-([0-9]+) ([a-z]): ([a-z]+)' pattern 
      from dual
  ),
  parsed_input as (
    select
      regexp_replace(line, regex.pattern, '\1') min_occurence,
      regexp_replace(line, regex.pattern, '\2') max_occurence,
      regexp_replace(line, regex.pattern, '\3') search_char,
      regexp_replace(line, regex.pattern, '\4') password,
      line original_line
      from input, regex_pattern regex
  )
select
  count(*)
  from parsed_input
  where regexp_count(password, search_char) 
    between min_occurence and max_occurence
;
Enter fullscreen mode Exit fullscreen mode

Part 2 now changes the policy from analyzing the occurence to check whether exactly one of the chars at the two given positions in the string match the searched character.

Good thing we have the casestatement in SQL:

with
  input as (
    select column_value line 
    from table(sys.odcivarchar2list(...))
  ),
  regex_pattern as (
    select '([0-9]+)-([0-9]+) ([a-z]): ([a-z]+)' pattern 
      from dual
  ),
  parsed_input as (
    select
      regexp_replace(line, regex.pattern, '\1') first_position,
      regexp_replace(line, regex.pattern, '\2') second_position,
      regexp_replace(line, regex.pattern, '\3') search_char,
      regexp_replace(line, regex.pattern, '\4') password,
      line original_line
      from input, regex_pattern regex
  ),
  positions_analyzed as (
    select
      password,
      case
        when substr(password, first_position, 1) = search_char 
        then
          1
        else
          0
        end first_pos_found,
      case
        when substr(password, second_position, 1) = search_char 
        then
          1
        else
          0
        end second_pos_found
      from parsed_input
  )
select
  count(*)
  from positions_analyzed
  where (first_pos_found+second_pos_found) = 1;
Enter fullscreen mode Exit fullscreen mode

You can find the solution to both parts on Oracle LiveSQL.

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay