diff --git a/README.md b/README.md
index 2c48387..b524da0 100644
--- a/README.md
+++ b/README.md
@@ -9,3 +9,5 @@ Day | Name | Type of Algo
1 | The Tyranny of the Rocket Equation | - Simple math problem
2 | Program Alarm | - Intro to the crazy Intcode problems that are half the AoC days...
- Array (slice...) manipulation
- I used recursion
3 | Crossed Wires | - Geometry kind of algo, finding intersections of lines on a grid
+4 | Secure Container | - May appear math-y, but it's really a string manipulation problem
+5 |
\ No newline at end of file
diff --git a/day04/input.txt b/day04/input.txt
new file mode 100644
index 0000000..a5d5848
--- /dev/null
+++ b/day04/input.txt
@@ -0,0 +1 @@
+138307-654504
diff --git a/day04/main.go b/day04/main.go
deleted file mode 100644
index e8ac0ec..0000000
--- a/day04/main.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package main
-
-import (
- "fmt"
- "strconv"
-)
-
-func numMatching(sliceToEnd []rune) int {
- // fmt.Println(sliceToEnd)
- // gets in a slice from a character to the end, returns an int of the matching characters
- result := 1
- for i := 1; i < len(sliceToEnd); i++ {
- if sliceToEnd[i] == sliceToEnd[0] {
- result += 1
- } else {
- break
- }
- }
- // fmt.Println(result)
- return result
-}
-
-func testNumber(num int) bool {
- // cast to string to iterate through digits?
- strNum := strconv.Itoa(num)
- runesSlice := []rune(strNum)
-
- duplicate := false
-
- for i := 0; i < len(runesSlice)-1; {
- if runesSlice[i] > runesSlice[i+1] {
- return false
- }
-
- matches := numMatching(runesSlice[i:len(runesSlice)])
- if matches == 2 {
- duplicate = true
- i++
- } else if matches == 1 {
- i++
- } else if matches > 2 {
- i += (matches - 1)
- }
- }
-
- // if the entire for loop passes, return if there was a duplicate or not
- return duplicate
-}
-
-func main() {
- start, end := 138307, 654504
- possibleCombinations := 0
-
- for i := start; i <= end; i++ {
- if testNumber(i) {
- possibleCombinations++
- }
- }
-
- fmt.Println(possibleCombinations)
- // fmt.Println(testNumber(111122))
- // fmt.Println(testNumber(123444))
- // fmt.Println(testNumber(112233))
-}
diff --git a/day04/part1/main.go b/day04/part1/main.go
new file mode 100644
index 0000000..6116614
--- /dev/null
+++ b/day04/part1/main.go
@@ -0,0 +1,47 @@
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ start, end := 138307, 654504
+ possibleCombinations := 0
+
+ for i := start; i <= end; i++ {
+ digits := makeDigitsSlice(i)
+ if isIncreasing(digits) && hasDuplicate(digits) {
+ possibleCombinations++
+ }
+ }
+
+ fmt.Println(possibleCombinations)
+}
+
+func makeDigitsSlice(num int) []int {
+ result := make([]int, 6)
+ for i := 5; num > 0; i-- {
+ result[i] = num % 10
+ num -= num % 10
+ num /= 10
+ }
+ return result
+}
+
+func isIncreasing(digits []int) bool {
+ for i := 1; i < len(digits); i++ {
+ if digits[i] < digits[i-1] {
+ return false
+ }
+ }
+ return true
+}
+
+func hasDuplicate(digits []int) bool {
+ for i := 1; i < len(digits); i++ {
+ if digits[i-1] == digits[i] {
+ return true
+ }
+ }
+ return false
+}
diff --git a/day04/part2/main.go b/day04/part2/main.go
new file mode 100644
index 0000000..01883ca
--- /dev/null
+++ b/day04/part2/main.go
@@ -0,0 +1,80 @@
+/*
+Only change from part1 is adding a decorator to the digit slices to shrink large
+groups (more than 2 digits) into a single digit. Then pass that into the same
+checks for a duplicate & all decreasing
+*/
+
+package main
+
+import "fmt"
+
+func main() {
+ start, end := 138307, 654504
+ possibleCombinations := 0
+
+ for i := start; i <= end; i++ {
+ digits := shrinkLargeGroups(makeDigitsSlice(i))
+ if isIncreasing(digits) && hasDuplicate(digits) {
+ possibleCombinations++
+ }
+ }
+
+ fmt.Println(possibleCombinations)
+}
+
+func makeDigitsSlice(num int) []int {
+ result := make([]int, 6)
+ for i := 5; num > 0; i-- {
+ result[i] = num % 10
+ num -= num % 10
+ num /= 10
+ }
+ return result
+}
+
+/*
+shrinkLargeGroups will return a new slice with any groups larger than 2 shrinked
+down to 1. e.g. 111223 -> 1223
+*/
+func shrinkLargeGroups(digits []int) []int {
+ // from start of number & ensure i+2 is within bounds of the digits slice
+ for i := 0; i+2 < len(digits); i++ {
+ if digits[i] == digits[i+1] && digits[i] == digits[i+2] {
+ // figure out how many items to remove
+ removeUpTo := i + 1
+ for removeUpTo < len(digits) && digits[i] == digits[removeUpTo] {
+ removeUpTo++
+ }
+
+ // copy the values into a new slice
+ newSli := make([]int, 0)
+ for j := 0; j <= i; j++ {
+ newSli = append(newSli, digits[j])
+ }
+ for removeUpTo < len(digits) {
+ newSli = append(newSli, digits[removeUpTo])
+ removeUpTo++
+ }
+ digits = newSli
+ }
+ }
+ return digits
+}
+
+func isIncreasing(digits []int) bool {
+ for i := 1; i < len(digits); i++ {
+ if digits[i] < digits[i-1] {
+ return false
+ }
+ }
+ return true
+}
+
+func hasDuplicate(digits []int) bool {
+ for i := 1; i < len(digits); i++ {
+ if digits[i-1] == digits[i] {
+ return true
+ }
+ }
+ return false
+}