Add 2020-02
Signed-off-by: AKU <tom@tdpain.net>
This commit is contained in:
parent
2413554b24
commit
c8fd7ad9ba
5 changed files with 266 additions and 0 deletions
31
challenges/2020/02-passwordPhilosophy/README.md
Normal file
31
challenges/2020/02-passwordPhilosophy/README.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# [Day 2: Password Philosophy](https://adventofcode.com/2020/day/2)
|
||||||
|
|
||||||
|
<details><summary>Script output</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
❯ python .\python\
|
||||||
|
AoC 2020: day 2 - Password Philosophy
|
||||||
|
Python 3.8.5
|
||||||
|
|
||||||
|
Test cases
|
||||||
|
1.1 pass
|
||||||
|
2.1 pass
|
||||||
|
|
||||||
|
Answers
|
||||||
|
Part 1: 500
|
||||||
|
Part 2: 313
|
||||||
|
|
||||||
|
❯ go run .\go\
|
||||||
|
AoC 2020: day 2 - Password Philosophy
|
||||||
|
Go go1.15.2
|
||||||
|
|
||||||
|
Test cases
|
||||||
|
1.1 pass
|
||||||
|
2.1 pass
|
||||||
|
|
||||||
|
Answers
|
||||||
|
Part 1: 500
|
||||||
|
Part 2: 313
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
23
challenges/2020/02-passwordPhilosophy/benchmark.txt
Normal file
23
challenges/2020/02-passwordPhilosophy/benchmark.txt
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Day 2 (Password Philosophy) benchmark
|
||||||
|
|
||||||
|
Dir: challenges/2020/02-passwordPhilosophy
|
||||||
|
Runs per part: 50
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Golang
|
||||||
|
|
||||||
|
benchmark.part.1.avg: 0.001280 seconds
|
||||||
|
benchmark.part.1.min: 0.000806 seconds
|
||||||
|
benchmark.part.1.max: 0.002234 seconds
|
||||||
|
benchmark.part.2.avg: 0.001383 seconds
|
||||||
|
benchmark.part.2.min: 0.000786 seconds
|
||||||
|
benchmark.part.2.max: 0.005438 seconds
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Python
|
||||||
|
|
||||||
|
benchmark.part.1.avg: 0.005367 seconds
|
||||||
|
benchmark.part.1.min: 0.002311 seconds
|
||||||
|
benchmark.part.1.max: 0.010500 seconds
|
||||||
|
benchmark.part.2.avg: 0.004618 seconds
|
||||||
|
benchmark.part.2.min: 0.001737 seconds
|
||||||
|
benchmark.part.2.max: 0.011591 seconds
|
||||||
|
--------------------------------------------------------------------------------
|
97
challenges/2020/02-passwordPhilosophy/go/challenge.go
Normal file
97
challenges/2020/02-passwordPhilosophy/go/challenge.go
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package challenge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/codemicro/adventOfCode/lib/aocgo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Challenge struct {
|
||||||
|
aocgo.BaseChallenge
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Challenge) One(instr string) (interface{}, error) {
|
||||||
|
inputSlice := parse(instr)
|
||||||
|
|
||||||
|
type Password struct {
|
||||||
|
plaintext string
|
||||||
|
targetLetter rune
|
||||||
|
minRepeats int
|
||||||
|
maxRepeats int
|
||||||
|
}
|
||||||
|
|
||||||
|
var passwords []Password
|
||||||
|
for _, line := range inputSlice {
|
||||||
|
matches := parserRegex.FindAllStringSubmatch(line, -1)
|
||||||
|
miR, _ := strconv.Atoi(matches[0][1])
|
||||||
|
maR, _ := strconv.Atoi(matches[0][2])
|
||||||
|
passwords = append(passwords, Password{
|
||||||
|
plaintext: matches[0][4],
|
||||||
|
targetLetter: rune(matches[0][3][0]),
|
||||||
|
minRepeats: miR,
|
||||||
|
maxRepeats: maR,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var num_valid_passwords int
|
||||||
|
|
||||||
|
for _, password := range passwords {
|
||||||
|
var target_letter_count int
|
||||||
|
for _, char := range password.plaintext {
|
||||||
|
if char == password.targetLetter {
|
||||||
|
target_letter_count += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_letter_count >= password.minRepeats) && (target_letter_count <= password.maxRepeats) {
|
||||||
|
num_valid_passwords += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_valid_passwords, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Challenge) Two(instr string) (interface{}, error) {
|
||||||
|
inputSlice := parse(instr)
|
||||||
|
|
||||||
|
type Password struct {
|
||||||
|
plaintext string
|
||||||
|
targetLetter rune
|
||||||
|
positionOne int
|
||||||
|
positionTwo int
|
||||||
|
}
|
||||||
|
|
||||||
|
var passwords []Password
|
||||||
|
for _, line := range inputSlice {
|
||||||
|
matches := parserRegex.FindAllStringSubmatch(line, -1)
|
||||||
|
miR, _ := strconv.Atoi(matches[0][1])
|
||||||
|
maR, _ := strconv.Atoi(matches[0][2])
|
||||||
|
passwords = append(passwords, Password{
|
||||||
|
plaintext: matches[0][4],
|
||||||
|
targetLetter: rune(matches[0][3][0]),
|
||||||
|
positionOne: miR - 1,
|
||||||
|
positionTwo: maR - 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var num_valid_passwords int
|
||||||
|
|
||||||
|
for _, password := range passwords {
|
||||||
|
positionOneMatches := rune(password.plaintext[password.positionOne]) == password.targetLetter
|
||||||
|
positionTwoMatches := rune(password.plaintext[password.positionTwo]) == password.targetLetter
|
||||||
|
|
||||||
|
if positionOneMatches != positionTwoMatches {
|
||||||
|
num_valid_passwords += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_valid_passwords, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(instr string) []string {
|
||||||
|
return strings.Split(strings.TrimSpace(string(instr)), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
var parserRegex = regexp.MustCompile(`(?m)(\d+)-(\d+) ([a-z]): (.+)`)
|
17
challenges/2020/02-passwordPhilosophy/info.json
Normal file
17
challenges/2020/02-passwordPhilosophy/info.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"inputFile": "input.txt",
|
||||||
|
"testCases": {
|
||||||
|
"one": [
|
||||||
|
{
|
||||||
|
"input": "1-3 a: abcde\n1-3 b: cdefg\n2-9 c: ccccccccc",
|
||||||
|
"expected": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"two": [
|
||||||
|
{
|
||||||
|
"input": "1-3 a: abcde\n1-3 b: cdefg\n2-9 c: ccccccccc",
|
||||||
|
"expected": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
98
challenges/2020/02-passwordPhilosophy/py/__init__.py
Normal file
98
challenges/2020/02-passwordPhilosophy/py/__init__.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
import re
|
||||||
|
from typing import List
|
||||||
|
from aocpy import BaseChallenge
|
||||||
|
|
||||||
|
|
||||||
|
class Challenge(BaseChallenge):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def one(instr: str) -> int:
|
||||||
|
input_string = parse(instr)
|
||||||
|
|
||||||
|
class Password:
|
||||||
|
plaintext: str
|
||||||
|
target_letter: str
|
||||||
|
min_repeats: int
|
||||||
|
max_repeats: int
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, plaintext: str, target_letter: str, min_repeats: int, max_repeats: int
|
||||||
|
) -> None:
|
||||||
|
self.plaintext = plaintext
|
||||||
|
self.target_letter = target_letter
|
||||||
|
self.min_repeats = min_repeats
|
||||||
|
self.max_repeats = max_repeats
|
||||||
|
|
||||||
|
parser_regex = r"(\d+)-(\d+) ([a-z]): (.+)"
|
||||||
|
|
||||||
|
passwords = []
|
||||||
|
|
||||||
|
for line in input_string:
|
||||||
|
m = re.match(parser_regex, line)
|
||||||
|
passwords.append(
|
||||||
|
Password(m.group(4), m.group(3), int(m.group(1)), int(m.group(2)))
|
||||||
|
)
|
||||||
|
|
||||||
|
num_valid_passwords = 0
|
||||||
|
|
||||||
|
for password in passwords:
|
||||||
|
target_letter_count = 0
|
||||||
|
for char in password.plaintext:
|
||||||
|
if char == password.target_letter:
|
||||||
|
target_letter_count += 1
|
||||||
|
|
||||||
|
if password.min_repeats <= target_letter_count <= password.max_repeats:
|
||||||
|
num_valid_passwords += 1
|
||||||
|
|
||||||
|
return num_valid_passwords
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def two(instr: str) -> int:
|
||||||
|
input_string = parse(instr)
|
||||||
|
|
||||||
|
class Password:
|
||||||
|
plaintext: str
|
||||||
|
target_letter: str
|
||||||
|
position_one: int
|
||||||
|
position_two: int
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
plaintext: str,
|
||||||
|
target_letter: str,
|
||||||
|
position_one: int,
|
||||||
|
position_two: int,
|
||||||
|
) -> None:
|
||||||
|
self.plaintext = plaintext
|
||||||
|
self.target_letter = target_letter
|
||||||
|
self.position_one = position_one - 1 # No concept of index zero... eurgh
|
||||||
|
self.position_two = position_two - 1
|
||||||
|
|
||||||
|
parser_regex = r"(\d+)-(\d+) ([a-z]): (.+)"
|
||||||
|
|
||||||
|
passwords = []
|
||||||
|
|
||||||
|
for line in input_string:
|
||||||
|
m = re.match(parser_regex, line)
|
||||||
|
passwords.append(
|
||||||
|
Password(m.group(4), m.group(3), int(m.group(1)), int(m.group(2)))
|
||||||
|
)
|
||||||
|
|
||||||
|
num_valid_passwords = 0
|
||||||
|
|
||||||
|
for password in passwords:
|
||||||
|
position_one_matches = (
|
||||||
|
password.plaintext[password.position_one] == password.target_letter
|
||||||
|
)
|
||||||
|
position_two_matches = (
|
||||||
|
password.plaintext[password.position_two] == password.target_letter
|
||||||
|
)
|
||||||
|
|
||||||
|
if position_one_matches ^ position_two_matches:
|
||||||
|
num_valid_passwords += 1
|
||||||
|
|
||||||
|
return num_valid_passwords
|
||||||
|
|
||||||
|
|
||||||
|
def parse(instr: str) -> List:
|
||||||
|
return instr.strip().split("\n")
|
Loading…
Add table
Add a link
Reference in a new issue