# Advent of Code Day 4: Code Golf and Irresponsible Password Practices

### Emily Giurleo γ»3 min read

After yesterday, I was hoping for a puzzle that involved a little bit less breaking my brain, and Advent of Code, Day 4 did not disappoint.

Here's part one:

You arrive at the Venus fuel depot only to discover it's protected by a password. The Elves had written the password on a sticky note, but someone threw it out.

However, they do remember a few key facts about the password:

It is a six-digit number.

The value is within the range given in your puzzle input.

Two adjacent digits are the same (like 22 in 122345).

Going from left to right, the digits never decrease; they only ever increase or stay the same (like 111123 or 135679).

Other than the range rule, the following are true:How many different passwords within the range given in your puzzle input meet these criteria?

First, I wrote two methods: one that checks that all digits in a number are ascending, and another that checks whether there are any adjacent digits in a number.

Originally, these methods involved some pretty ugly for loops (I don't think I've ever used a for loop in production-level Ruby code, but I digress...), so I did some digging into methods I could use to make them more elegant, and I stumbled on something I had never seen before: `Array#each_cons`

. Here's what it looks like:

```
# Returns true if every digit in num
# is less than or equal to the digit after it.
def ascending_digits?(num)
num_str = num.to_s
digits = num_str.split('').map(&:to_i)
digits.each_cons(2).all? do |dig1, dig2|
dig1 <= dig2
end
end
# Returns true if any two adjacent
# digits in the string are the same
def adjacent_digits?(num)
num_str = num.to_s
digits = num_str.split('')
digits.each_cons(2).any? do |dig1, dig2|
dig1 == dig2
end
end
```

To break it down -- `#each_cons`

is an `Enumerable`

method that allows you to pull elements from the array in groups, rather than one at a time. In this case, I've used it with the `Enumerable`

methods `any?`

and `all?`

to check whether any/all of the groups of array elements match the specified criteria. Isn't that cool?

Using these two methods, I iterated through all the numbers in my input range to find which ones were viable passwords:

```
input = '206938-679128'
low, high = input.split('-').map(&:to_i
part_one_result = (low..high)
.to_a
.select do |num|
adjacent_digits?(num) && ascending_digits?(num)
end.length
puts "The solution to part one is: #{part_one_result}"
```

Unsurprisingly, this actually takes a couple seconds to run, and I wonder if there's a faster way to cut down on the solution space before doing expensive string manipulations. However, this does return the correct answer, so I decided not to worry too much about it.

Here's part two:

An Elf just remembered one more important detail: the two adjacent matching digits are not part of a larger group of matching digits.

How many different passwords within the range given in your puzzle input meet all of the criteria?

This problem was definitely tricker, because I had to check not just that digits were being repeated, but how many times they were being repeated. I continued to use `#each_cons`

, but I kept some other variables with information about which number was currently being repeated, and how many times it had been repeated. Here's what it looks like:

```
def two_adjacent_digits?(num)
num_str = num.to_s
digits = num_str.split('')
num_matching = 1
num_to_match = digits.first
digits.each_cons(2).each do |dig1, dig2|
if dig1 == dig2
num_matching += 1
else
return true if num_matching == 2
num_matching = 1
num_to_match = dig1
end
end
num_matching == 2
end
```

This is still a bit bulky, and if anybody came up with a shorter solution, I'd love to see it!

Finally, I used this new method to find a solution for part two:

```
part_two_result = (low..high)
.to_a
.select do |num|
two_adjacent_digits?(num) && ascending_digits?(num)
end.length
puts "The solution to part two is: #{part_two_result}
```

I suspect that we will soon get to a point where the input is too large for a brute-force solution like this to be viable, and I'm excited to start thinking a little more about data structures and algorithms. It was cool to learn about a new Ruby method that I had never used before, and I'm glad that I took the time to go back and clean up all the ugly for-loops in my code.

That being said, if we've learned anything today, it's to use a password manager and not be like these elves. π See you tomorrow!

As always, you can view my complete Ruby solution on my GitHub repo:

# Advent of Code 2019

Here are my solutions to the Advent of Code 2019 puzzles! Enjoy.

Advent of Code 2019, Day 3 - π- Advent of Code 2019, Day 5

My Ruby solution was purely based on regex pattern matching:

github.com/chron/advent-of-code/bl...

That was racing to complete as quickly as possible, so it's not particularly pretty.

Afterwards I golfed it a little and the best I came up with so far is:

But I'm sure there are a few more improvements to be made :)

That's cool! So interesting to see the wide variety of solutions that people came up with. Thanks for sharing!

No surprise the solution is slow, since you do a /lot/ of string manipulation. If you use 6 nested loops, things are much easier, consider the below approach (Progress 4GL, but syntax is clear I think). Progress is not known for its brute force speed, since it's a 4GL, but this runs in 47msec

That's a cool solution! Thanks for sharing.