Robert Mion

Posted on

# High-Entropy Passphrases

## Part 1

1. Inventory Management System Redux!
2. Writing my working algorithm

### Inventory Management System Redux!

• Remember 2018 Day 2?
• It asked me to find exact counts of letters within strings
• This feels similar, but easier, in my opinion
• Because I don't need to build an object of letter counts for each string
• I just need an `Array` and a `Set`, so I can compare `length` and `size`!

### Writing my working algorithm

``````Split the input at each newline character into an array of strings

For each string, accumulate a tally, starting at 0
Split the string at each space character into an array of strings
If the length of the array is the same as the size of a Set generated from that array
Increment the tally by 1, because there are no duplicate phrases
Else
Leave the tally unchanged

Return the tally
``````

In JavaScript, I use `reduce()`, `split()`, `Array.length`, `Set.size` and a `ternary operator` in a one long chained statement:

``````input.split('\n')
.reduce((tally, current) => {
return tally += current.split(' ').length
== new Set(current.split(' ')).size
? 1 : 0
}, 0)
``````

## Part 2

1. What a delightful twist!
2. Three `reduce()`rs, that's how!
3. Revealing my working `reduce()`rs

### What a delightful twist!

• Anagrams, eh? How fun!
• And also...complicating

Hmm...how should I attempt to solve this?

### Three `reduce()`rs, that's how!

This is going to get complex really fast, so bear with me:

1. An outer `reduce()` to track the tallies of valid passphrases
2. An inner `reduce()` to collect all the stringified letter tallies for each word
3. An inner-most `reduce()` to generate a stringified letter tally for one word

This animation illustrates each of the `reduce()`rs using the last example set of passphrases:

### Revealing my working `reduce()`rs

This is the JavaScript I'm proud to have written in about 15 minutes:

``````return input
.split('\n')
.reduce((passphrases, passphrase) => {
let letterCounts = passphrase
.split(' ')
.reduce((list, group) => {
let counts = group
.split(' ')
.reduce((tallies, letter) => {
tallies[letter] = (tallies[letter] || 0) + 1
return tallies
}, {})
list.push(
Object.keys(counts)
.sort()
.map(el => el + '|' + counts[el]).join(''))
return list
}, [])
return passphrases += letterCounts.length
== new Set(letterCounts).size
? 1 : 0
}, 0)
``````

## I did it!!

• I solved both parts!
• I used a ton of `reduce()`!
• I made a detailed GIF showing what each `reduce()` does!
• I really enjoyed solving Part 2!
• I'm now tied for my personal best star score in a given year: `40`!