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