# Day 4: Secure Container

Join the Tildes private leaderboard! You can do that on this page, by entering join code `730956-de85ce0c`.

Please post your solutions in your own top-level comment. Here's a template you can copy-paste into your comment to format it nicely, with the code collapsed by default inside an expandable section with syntax highlighting (you can replace `python` with any of the "short names" listed in this page of supported languages):

``````<details>
<summary>Part 1</summary>

```python
```

</details>
``````

1. markh
Join the leaderboard using code 730956-de85ce0c! This was, to me, the easiest challenge so far. Here's a simple, dirty solution in Javascript. Part 1 const generateArray = (low, high) => { let...

# Join the leaderboard using code `730956-de85ce0c`!

This was, to me, the easiest challenge so far. Here's a simple, dirty solution in Javascript.

Part 1
``````const generateArray = (low, high) => {
let array = [];
for (var i = low; i <= high; i++) {
array.push(i);
}
return array;
}

const isSixDigits = x => {
const a = x.toString().split('');
return a.length === 6;
}

const hasAdjacentDigits = x => {
const a = x.toString().split('');
const b = a.filter((el, idx, arr) => {
return el === arr[idx + 1];
});
return b.length > 0;
}

const digitsNeverDecrease = x => {
const a = x.toString().split('');
const b = a.filter((el, idx, arr) => {
return el <= arr[idx + 1];
})
return b.length === 5;
}

const entireRange = generateArray(193651, 649729);

console.log(filteredRange.length);
``````
Part 2
``````const generateArray = (low, high) => {
let array = [];
for (var i = low; i <= high; i++) {
array.push(i);
}
return array;
}

const isSixDigits = x => {
const a = x.toString().split('');
return a.length === 6;
}

const a = x.toString().split('');
const b = a.filter((el, idx, arr) => {
const matchesNext = el === arr[idx + 1];
const matchesTwoInFront = el === arr[idx + 2]
const matchesPrevious = el === arr[idx - 1];

if (matchesNext && !(matchesTwoInFront || matchesPrevious)) {
return el === arr[idx + 1];
}
});

return b.length > 0;
}

const digitsNeverDecrease = x => {
const a = x.toString().split('');
const b = a.filter((el, idx, arr) => {
return el <= arr[idx + 1];
})
return b.length === 5;
}

const entireRange = generateArray(193651, 649729);

console.log(filteredRange.length);
``````
2. tesseractcat
(edited )
Day 4 in Befunge Day 4 took a long time, partially because I had to fix some kinks in my interpreter so it functioned more accurately according to the spec, so I could feed my code into an ultra...

# Day 4 in Befunge

Day 4 took a long time, partially because I had to fix some kinks in my interpreter so it functioned more accurately according to the spec, so I could feed my code into an ultra fast Befunge compiler and get the answer in a reasonable amount of time. The other reason it took a while was because I initially had my code only check in 3 sections, so `` would have been valid, and I had a hard to see error with end of number detection. But I fixed it all eventually. I haven't completed part 2 yet.

Part 1

For this to complete in any reasonable amount of time, I recommend BefunExec to run it.

``````v
>069*0p066*0p067*0p068*0pv
v                        <
v
>&:10p30p&20p    v_v# - g02 g03  <

>68*0g .@
> 69*0g1+69*0p v
v\-10 p03:+1g03 \$p0*660 \$p0*760<  Advent of Code 2019 - Day 4 Pt. 1
v v      \$<                    >^
>  >:0`#v_^
>:52*% \52*/v    <-- Convert to digits  v                   <
=^                <          #                                    \$
v    g05    _v#+1:<   >\$\$\$\$\$\$^          <     <                   \$
\            >\$      :|                                           \$
:
5
0
p
\
>-:#v_77*66*0p\$   ^   >67*0g#^_ 66*0g#v_^>  68*0g1+68*0p          ^
>0`#v_77*67*0p^                   >  ^
>         ^
``````
Part 2
``````v
>069*0p066*0p067*0p068*0pv
v                        <
v
>&:10p30p&20p    v_v# - g02 g03  <

>68*0g .@     ^                           <
> 69*0g1+69*0p v>" ":65*1p:66*1p:67*1p:68*1p^
v\-10 p03:+1g03 \$p0*660 \$p0*760<  Advent of Code 2019 - Day 4
v v      \$<                    >^
>  >:0`#v_^
>:52*% \52*/v    <-- Convert to digits  v              \$\$\$\$\$<
^                <          #                                    \$
v    g05    _v#+1:<   >\$\$\$\$\$\$^  \$\$\$\$\$\$\$\$<    <<                   \$
\            >\$      :|                                           \$
:
5
0 Part 2 - If a rabbit were an elf, would it's ears look like this <o.^ or like this <o.)
p                 #                          #                    #
\
>-:#v_77*66*0p\$   ^   >67*0g#^_ 66*0g#v_^>   v >      68*0g1+68*0p^
>0`#v_77*67*0p^                   >  ^   #                >:65*1g-#v_66*1g1+66*1p            v
>         ^                          ^_^#-1g1*76 \$<            >:65*1p 66*1g2-#v_167*1p> v
^              <       <
>      66*1g2-#^_167*1p^
>\$30g >:0`#v_^    v           <           >166*1p ^
>:52*%^>\52*/v     ^                     <
^                 <
``````
3. mftrhu
This one was almost trivial to implement, and I ended up doing it on my phone during a break at work. I'll have to rewrite it in Julia once I'll be back home, though. Part 1 from itertools import...

This one was almost trivial to implement, and I ended up doing it on my phone during a break at work. I'll have to rewrite it in Julia once I'll be back home, though.

Part 1
``````from itertools import combinations_with_replacement
import re

def has_double(n):
return re.search(r"(\d)\1", str(n))

def in_range(n):
return 357253 <= n <= 892942

candidates = combinations_with_replacement("123456789", 6)
candidates = map(lambda t: int(''.join(t)), candidates)
candidates = filter(in_range, candidates)
candidates = filter(has_double, candidates)
candidates = list(candidates)
print(len(candidates))
``````
Part 2
``````from itertools import combinations_with_replacement
import re

def has_double(n):
n = str(n)
m = re.findall(r"(\d)\1", n)
return m and (not
all(re.search(r"%s{3,}" % d, n) for d in m))

def in_range(n):
return 357253 <= n <= 892942

candidates = combinations_with_replacement("123456789", 6)
candidates = map(lambda t: int(''.join(t)), candidates)
candidates = filter(in_range, candidates)
candidates = filter(has_double, candidates)
candidates = list(candidates)
print(len(candidates))
``````
4. mozz
I'm trying out the advent challenges as an opportunity to learn go. This is the first day that my code is clean enough that I'm not actively embarrassed by it. Part 1 package main import ( "fmt"...

I'm trying out the advent challenges as an opportunity to learn go. This is the first day that my code is clean enough that I'm not actively embarrassed by it.

Part 1
``````package main

import (
"fmt"
"strconv"
)

func check(number int) bool {
previous, hasRepeating := rune(0), false
for _, char := range strconv.Itoa(number) {
if char == previous {
hasRepeating = true
} else if char < previous {
// The digits should never decrease
return false
}
previous = char
}
return hasRepeating
}

func main() {
start, end := 359282, 820401
count:= 0
for i := start; i <= end; i++ {
if check(i) {
count++
}
}
fmt.Println(count)
}
``````
5. Crestwave
Whew, I thought it was almost getting too hard for me with yesterday's challenge, but this one seems much easier. Here's a quick and dirty awk implementation; might clean it up a bit later. Part 1...

Whew, I thought it was almost getting too hard for me with yesterday's challenge, but this one seems much easier. Here's a quick and dirty `awk` implementation; might clean it up a bit later.

Part 1
``````#!/usr/bin/awk -f
{
split(\$0, range, "-")
for (i = range; i < range; ++i) {
for (j = 1; j < length(i); ++j) {
if (substr(i, j, 1) == substr(i, j+1, 1))
double = 1

if (substr(i, j, 1) > substr(i, j+1, 1)) {
double = 0
break
}
}

unique += double
double = 0
}

print unique
}
``````
Part 2

The same as part 1, except with line 6 extended to this:

``````if (substr(i, j, 1) == substr(i, j+1, 1) && substr(i, j+2, 1) != substr(i, j, 1) && (j == 1 || substr(i, j-1, 1) != substr(i, j, 1)))
``````

Yes, I meant it when I said quick and dirty.

6. 
asterisk
PHP functions.php <?php function isSixtLength(\$input) { return strlen((string) \$input) == 6; } function isSameAdjent(\$input) { for (\$i = 0; \$i < strlen(\$input); \$i++) { if (\$i && \$input[\$i] ==...
PHP

`functions.php`

``````<?php

function isSixtLength(\$input)
{
return strlen((string) \$input) == 6;
}

{
for (\$i = 0; \$i < strlen(\$input); \$i++) {
if (\$i && \$input[\$i] == \$input[\$i - 1]) {
return true;
}
}
return false;
}

function isDecrease(\$input)
{
for (\$i = 0; \$i < strlen(\$input); \$i++) {
if (\$i && \$input[\$i] < \$input[\$i - 1]) {
return true;
}
}
return false;
}

function findBi(\$input)
{
for (\$i = 0; \$i < strlen(\$input); \$i++) {
switch (\$i) {
case 0:
if (\$input[\$i] == \$input[\$i + 1] && \$input[\$i] != \$input[\$i + 2]) {
return true;
}
break;
case 1:
if (
\$input[\$i] == \$input[\$i + 1] && \$input[\$i] != \$input[\$i + 2] && \$input[\$i] != \$input[\$i - 1]
|| \$input[\$i] == \$input[\$i - 1] && \$input[\$i] != \$input[\$i + 1]
) {
return true;
}
break;
case strlen(\$input) - 2:
if (
\$input[\$i] == \$input[\$i + 1] && \$input[\$i] != \$input[\$i - 1]
|| \$input[\$i] == \$input[\$i - 1] && \$input[\$i] != \$input[\$i - 2] && \$input[\$i] != \$input[\$i + 1]
) {
return true;
}
break;
case strlen(\$input) - 1:
if (\$input[\$i] == \$input[\$i - 1] && \$input[\$i] != \$input[\$i - 2]) {
return true;
}
break;
default:
if (
\$input[\$i] == \$input[\$i + 1] && \$input[\$i] != \$input[\$i + 2] && \$input[\$i] != \$input[\$i - 1]
|| \$input[\$i] == \$input[\$i - 1] && \$input[\$i] != \$input[\$i - 2] && \$input[\$i] != \$input[\$i + 1]
) {
return true;
}
}
}
return false;
}
``````

`part-1.php`

``````<?php include('functions.php');

\$count = 0;
foreach (range(197487, 673251) as \$number) {
if (isSixtLength(\$number) && isSameAdjent((string) \$number) && !isDecrease((string) \$number)) {
\$count++;
}
}

echo \$count;
``````

`part-2.php`

``````<?php include('functions.php');

\$count = 0;
foreach (range(197487, 673251) as \$number) {
if (isSixtLength(\$number) && findBi((string) \$number) && !isDecrease((string) \$number)) {
\$count++;
}
}

echo \$count;
``````
1. asterisk
Rewrited function findBi() <?php function findBi(\$input) { if (isSameAdjent(substr(\$input, 0, 2)) && !isSameAdjent(substr(\$input, 1, 2)) || !isSameAdjent(substr(\$input, strlen(\$input)-3, 2)) &&...
Rewrited function findBi()
``````<?php function findBi(\$input)
{
return true;
}

for (\$i = 1; \$i < strlen(\$input) - 1; \$i++) {
return true;
}
}
return false;
}
``````
1 vote
7. 9000
Language: Rust As everyone else is saying, this one was much easier. I felt that there was probably a pure math way to solve this, but I couldn't quite work it out and I don't think it would work...

## Language: Rust

As everyone else is saying, this one was much easier. I felt that there was probably a pure math way to solve this, but I couldn't quite work it out and I don't think it would work for arbitrary ranges. Anyway, the solution:

Solution
``````fn main() {
let mut num_1: usize = 0;
let mut num_2: usize = 0;
for n in 382345..843167{
let mut increasing = true;
let mut double_1 = false;
let mut double_2 = false;
let mut prev_digit = n % 10;
let mut run_length = 1;
for digit in 1..6 {
let next_digit = (n / 10_u32.pow(digit)) % 10;
if prev_digit < next_digit {
increasing = false;
break;
} else if prev_digit == next_digit {
double_1 = true;
run_length += 1;
} else {
if run_length == 2 {
double_2 = true;
}
run_length = 1;
}
prev_digit = next_digit;
}
if increasing && double_1 {
num_1 += 1;
}
if increasing && (double_2 || run_length == 2) {
num_2 += 1;
}
}

println!("Number of passwords (Part 1): {}", num_1);
println!("Number of passwords (Part 2): {}", num_2);
}
``````
8. nothis
(edited )
This one felt significantly easier. Maybe because I was actually trying to concentrate and doing it fast (seeing the top-100 swoosh by, of course). The main difficulty seems to have been getting...

This one felt significantly easier. Maybe because I was actually trying to concentrate and doing it fast (seeing the top-100 swoosh by, of course). The main difficulty seems to have been getting the digits but it's almost a programming exercise cliche.

I hard-coded almost all of it, expecting it to bite me in the ass for the second star (varying number of digits, etc) but it seems for the second star just copy-pasting it manually was also the fastest way. Anyway, couldn't help but clean it up a tiny little bit.

Part 1
``````const getPossiblesCount = (min, max) => {
let count = 0;

for (let i = min; i <= max; i++) {
const digits = getDigits(i);
let doubles = false;
let increasing = true;

for (let d = 0; d < digits.length - 1; d++) {
if (digits[d] === digits[d + 1]) {
doubles = true;
}
if (digits[d] > digits[d + 1]) {
increasing = false;
}
}

if (doubles && increasing) {
count++;
}
}

return count;
};

const getDigits = number => {
let digits = [];

for (let d = 100000; d >= 1; d = d / 10) {
let digit = Math.floor(number / d);
digits.push(digit);
number -= digit * d;
}

return digits;
};

console.log(getPossiblesCount(130254, 678275));
``````
Part 2
``````const getPossiblesCount = (min, max) => {
let count = 0;

for (let i = min; i <= max; i++) {
const digits = getDigits(i);
let doubles = false;
let increasing = true;

for (let d = 0; d < digits.length - 1; d++) {
if (digits[d] === digits[d + 1]) {
if (
(d === 0 && digits[d + 1] !== digits[d + 2]) ||
(d === digits.length - 1 &&
digits[digits.length - 3] !== digits[digits.length - 2]) ||
(digits[d - 1] !== digits[d] && digits[d + 1] !== digits[d + 2])
) {
doubles = true;
}
}
if (digits[d] > digits[d + 1]) {
increasing = false;
}
}

if (doubles && increasing) {
count++;
}
}

return count;
};

const getDigits = number => {
let digits = [];

for (let d = 100000; d >= 1; d = d / 10) {
let digit = Math.floor(number / d);
digits.push(digit);
number -= digit * d;
}

return digits;
};

console.log(getPossiblesCount(130254, 678275));
``````

Part of me likes how simple these exercises are (especially that the outcome is a single number so you don't have to fiddle with formatting), part of me would love there to be a higher emphasis on optimization challenges (though that would limit the amount of possible languages you can use). I heard this will get harder so I assume the later ones might simply run too long if you don't optimize?

1 vote
9. Crespyl
After days 2 and 3 it's nice to see a simpler one again to take a breather (even as excited as I am to revisit the VM puzzle). Part 1, Crystal/Ruby #!/usr/bin/env crystal RANGE_MIN = 171309...

After days 2 and 3 it's nice to see a simpler one again to take a breather (even as excited as I am to revisit the VM puzzle).

Part 1, Crystal/Ruby
``````#!/usr/bin/env crystal

RANGE_MIN = 171309
RANGE_MAX = 643603

def check_digits(n)
n.to_s.size == 6
end

def check_range(n)
n >= RANGE_MIN && n <= RANGE_MAX
end

result = false
n.to_s.chars.reduce('0') { |prev, char|
if prev == char
result = true
end
char
}
return result
end

def check_increase(n)
result = true
n.to_s.chars.reduce('0') { |prev, char|
if prev.to_i > char.to_i
result = false
end
char
}
return result
end

def check(n)
check_digits(n) && check_range(n) && check_increase(n) && check_adjacency(n)
end

matches = 0
(RANGE_MIN..RANGE_MAX).each do |i|
matches += 1 if check(i)
end
puts matches
``````
Part 2

Same as before, except I refactored the `check_adjacency` bit with an improved version

``````def check_adjacency_p2(n)
n.to_s.chars.group_by { |c| c }.any? { |k,v| v.size == 2 }
end
``````
1 vote
10. Hvv
I think that my code always tends towards "dumpster fire that also happens to be correct" so in the future I will probably try to focus on good code beyond strict correctness. Part 2 is included...

I think that my code always tends towards "dumpster fire that also happens to be correct" so in the future I will probably try to focus on good code beyond strict correctness.

Part 2 is included as a module in the code, since the problem makes it very easy to add Part 2 to Part 1.

Parts 1/2, C++
``````#include <bits/stdc++.h>
using namespace std;
//Manually checks all possible numbers in the given range
//Complexity O(n 10^n) where n is the number of digits
//Luckily n = 6, so this is reasonably fast
//Part 2 is quite modular, so it's also included in this code

//Check A:
//Are the digits nondecreasing left to right, or equivalently, nonincreasing right to left?
bool cha(int a) {
int val = 10;
//Dirty code note: an int will cast to false if zero and to true if nonzero
//That might be false but is almost surely true for nonnegative ints
while(a) {
if(a%10 > val) return false;
val = a%10;
a /= 10;
}
return true;
}
//Check B:
//Is there some consecutive pair of digits that are the same?
bool chb(int a) {
int ld = -1;
while(a) {
if(ld == a%10) return true;
ld = a%10;
a /= 10;
}
return false;
}
//Check C (stricter check than Check B):
//Is there a streak of exactly two digits in the (6-digit) number?
bool chc(int a) {
int ld = -1;
int ct = 0;
while(a) {
if(ld == a%10) {
ct++;
} else {
if(ct == 1) return true;
ct = 0;
}
ld = a%10;
a /= 10;
}
return ct == 1;
}
//The 6 digit check is automatically fulfilled by the bounds
int main() {
int l,r;
//scanf will happily take the input as is and crunch them into the right format
scanf("%d-%d",&l,&r);
//Count all the valid numbers from the left bound to the right bound
int ctr = 0;
//It doesn't say whether those bounds are inclusive, but luckily it doesn't matter
for(int i=l;i<=r;i++) {
if(cha(i) && chb(i)) {				//Part 1 solution implementation
//if(cha(i) && chc(i)) {			//Part 2 solution implementation
ctr++;
}
}
cout << ctr << '\n';
}
``````
1 vote
11. Bauke
(edited )
Today was pretty easy for me, a lot easier than yesterday's at least. Part One function partOne(): void { const lowerBound = 246515; const upperBound = 739105; const matches: number[] = []; for...

Today was pretty easy for me, a lot easier than yesterday's at least.

Part One
``````function partOne(): void {
const lowerBound = 246515;
const upperBound = 739105;
const matches: number[] = [];
for (let index = lowerBound; index < upperBound; index++) {
const indexString = String(index);
let previousChar: string = indexString;
let isAscending = false;
for (const char of indexString.slice(1)) {
if (Number(previousChar) > Number(char)) {
isAscending = false;
break;
}

isAscending = true;
if (char === previousChar) {
}

previousChar = char;
}

matches.push(index);
}
}

console.log(`Part One: there are \${matches.length} different passwords.`);
}

partOne();
``````
Part Two

For part two I basically just copied the first part and tacked on the extra adjacent requirement at the end. This could definitely be refactored to be clearer and faster but I figured I'd just leave it as is. There is beauty in ugliness! Or something like that. :P

``````function partTwo(): void {
const lowerBound = 246515;
const upperBound = 739105;
const matches: number[] = [];
for (let index = lowerBound; index < upperBound; index++) {
const indexString = String(index);
let isAscending = false;
let previousChar: string = indexString;
for (const char of indexString.slice(1)) {
if (Number(previousChar) > Number(char)) {
isAscending = false;
break;
}

isAscending = true;
if (char === previousChar) {
}

previousChar = char;
}

matches.push(index);
}
}

const newMatches: number[] = [];
for (const match of matches) {
const matchString = String(match);
const blockMatches: RegExpMatchArray = [];
for (const char of matchString) {
const regex = new RegExp(`\${char}{2,}`);
blockMatches.push(...(regex.exec(matchString) ?? []));
}

if (blockMatches.some(val => val.length === 2)) {
newMatches.push(match);
}
}

console.log(`Part Two: there are \${newMatches.length} different passwords.`);
}

partTwo();
``````

Click to go to list of all days.

1 vote
12. Gyrfalcon
This one was pretty easy on the first part, but the second part took some thinking (and guessing) to get right. Things started to fall into place once I realized it would be more readable and...

This one was pretty easy on the first part, but the second part took some thinking (and guessing) to get right. Things started to fall into place once I realized it would be more readable and easier to understand if I split some of my increasingly ugly conditional expressions into multiple if statements. I've added comments this time, but I may have overcompensated for my past uncommented spaghetti.

I am also a little miffed that these release right at my bed time. It's tough to make it on the leaderboard when I often don't have a chance to really work on them until the following afternoon!

Parts 1&2, Python 3
``````# Just reads in the data and gets it formatted right

with open(file_name, 'r') as fid:

for idx in range(len(code_range)):
code_range[idx] = int(code_range[idx])

return code_range

# Does ths simple validation routine for part one
def validate_code(code):

# Get our code as a list of integers
code = [int(num) for num in str(code)]

# Make sure they are strictly ascending
for idx in range(len(code) - 1):
if code[idx] > code[idx + 1]:
return 0 # Code is invalid

# Check if there are any repeats
for idx in range(len(code) - 1):
if code[idx] == code[idx + 1]:
return 1 # Code is valid

# If there's no repeats, the code is invalid
return 0

# Does the more complex validation routine for part 2

# Get our code as a list of integers
code = [int(num) for num in str(code)]

# Make sure they are strictly ascending
for idx in range(len(code) - 1):
if code[idx] > code[idx + 1]:
return 0 # Code is invalid

# Check for repeats, not including 3+
for idx in range(len(code) - 1):
# If you arent right at the end and it isn't a 3 going forward
if idx < len(code) - 2 and (code[idx] == code[idx + 1]
and code[idx+1] != code[idx+2]):
# If it's right at the beginning it can't have a 3 going backward
if  idx == 0:
return 1 # Code is valid
# Otherwise check backward to be sure
elif code[idx] != code[idx - 1]:
return 1 # Code is valid
# Check that if it's at the very end, there's no 3 going backward
elif idx == (len(code) - 2) and code[idx] == code[idx + 1]:

if idx >= 1 and code[idx] != code[idx - 1]:
return 1 # Code is valid
# If there's no repeats without 3+, then the code is invalid
return 0

# Applies the simple validation function over a range defined in a file and sums
# up the number of valid codes
def validate_range(file_name):

num_valid = 0
for code in range(code_range, code_range + 1):
num_valid += validate_code(code)

return num_valid

# Applies the advanced validation function over a range defined in a file and
# sums up the number of valid codes

num_valid = 0
for code in range(code_range, code_range + 1):