From 0cb12b95ef11fe283731e862e3953f27eeea8757 Mon Sep 17 00:00:00 2001 From: omagdy Date: Thu, 12 Dec 2024 18:31:50 +0200 Subject: Day 11 done. --- 2024/go/src/day01/main.go | 77 +++++++++++++++++++ 2024/go/src/day02/main.go | 99 ++++++++++++++++++++++++ 2024/go/src/day03/main.go | 75 ++++++++++++++++++ 2024/go/src/day04/main.go | 133 ++++++++++++++++++++++++++++++++ 2024/go/src/day05/main.go | 179 +++++++++++++++++++++++++++++++++++++++++++ 2024/go/src/day06/main.go | 188 +++++++++++++++++++++++++++++++++++++++++++++ 2024/go/src/day07/main.go | 190 ++++++++++++++++++++++++++++++++++++++++++++++ 2024/go/src/day08/main.go | 139 +++++++++++++++++++++++++++++++++ 2024/go/src/day09/main.go | 169 +++++++++++++++++++++++++++++++++++++++++ 2024/go/src/day1/main.go | 77 ------------------- 2024/go/src/day11/main.go | 107 ++++++++++++++++++++++++++ 2024/go/src/day2/main.go | 99 ------------------------ 2024/go/src/day3/main.go | 75 ------------------ 2024/go/src/day4/main.go | 133 -------------------------------- 2024/go/src/day5/main.go | 179 ------------------------------------------- 2024/go/src/day6/main.go | 188 --------------------------------------------- 2024/go/src/day7/main.go | 190 ---------------------------------------------- 2024/go/src/day8/main.go | 139 --------------------------------- 2024/go/src/day9/main.go | 169 ----------------------------------------- 19 files changed, 1356 insertions(+), 1249 deletions(-) create mode 100644 2024/go/src/day01/main.go create mode 100644 2024/go/src/day02/main.go create mode 100644 2024/go/src/day03/main.go create mode 100644 2024/go/src/day04/main.go create mode 100644 2024/go/src/day05/main.go create mode 100644 2024/go/src/day06/main.go create mode 100644 2024/go/src/day07/main.go create mode 100644 2024/go/src/day08/main.go create mode 100644 2024/go/src/day09/main.go delete mode 100644 2024/go/src/day1/main.go create mode 100644 2024/go/src/day11/main.go delete mode 100644 2024/go/src/day2/main.go delete mode 100644 2024/go/src/day3/main.go delete mode 100644 2024/go/src/day4/main.go delete mode 100644 2024/go/src/day5/main.go delete mode 100644 2024/go/src/day6/main.go delete mode 100644 2024/go/src/day7/main.go delete mode 100644 2024/go/src/day8/main.go delete mode 100644 2024/go/src/day9/main.go (limited to '2024/go/src') diff --git a/2024/go/src/day01/main.go b/2024/go/src/day01/main.go new file mode 100644 index 0000000..4e52825 --- /dev/null +++ b/2024/go/src/day01/main.go @@ -0,0 +1,77 @@ +package main + +import ( + "fmt" + "os" + "sort" + "strconv" + "strings" +) + +func AbsInt(x int) int { + if x < 0 { + return -x + } + return x +} + +func solve_part_one(data string) int { + var list_1 []int + var list_2 []int + + ans := 0 + for _, line := range strings.Split(data, "\n") { + if len(line) > 0 { + elements := strings.Split(line, " ") + ele1, _ := strconv.Atoi(elements[0]) + ele2, _ := strconv.Atoi(elements[1]) + list_1 = append(list_1, ele1) + list_2 = append(list_2, ele2) + } + } + sort.Ints(list_1) + sort.Ints(list_2) + for i := range len(list_1) { + ans += AbsInt(list_1[i] - list_2[i]) + } + return ans +} + +func solve_part_two(data string) int { + var list_1 []int + var list_2 []int + + ans := 0 + for _, line := range strings.Split(data, "\n") { + if len(line) > 0 { + elements := strings.Split(line, " ") + ele1, _ := strconv.Atoi(elements[0]) + ele2, _ := strconv.Atoi(elements[1]) + list_1 = append(list_1, ele1) + list_2 = append(list_2, ele2) + } + } + counts := make(map[int]int) + + for _, num := range list_2 { + counts[num]++ + } + for i := range len(list_1) { + ans += list_1[i] * counts[list_1[i]] + } + return ans +} + +func main() { + test_1, _ := os.ReadFile("../input/day1.test") + test_2, _ := os.ReadFile("../input/day1_2.test") + prod, _ := os.ReadFile("../input/day01.prod") + content_test_1 := string(test_1) + content_test_2 := string(test_2) + content_prod := string(prod) + + fmt.Println("Part_1 test: ", solve_part_one(content_test_1)) + fmt.Println("Part_1 prod: ", solve_part_one(content_prod)) + fmt.Println("Part_2 test: ", solve_part_two(content_test_2)) + fmt.Println("Part_2 prod: ", solve_part_two(content_prod)) +} diff --git a/2024/go/src/day02/main.go b/2024/go/src/day02/main.go new file mode 100644 index 0000000..2658198 --- /dev/null +++ b/2024/go/src/day02/main.go @@ -0,0 +1,99 @@ +package main + +import ( + "fmt" + "os" + "strconv" + "strings" +) + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) + +} + +func parseInput(data string) [][]int { + var reports [][]int + for _, line := range strings.Split(data, "\n") { + var report []int + if len(line) > 0 { + elements := strings.Split(line, " ") + for _, ele := range elements { + e, err := strconv.Atoi(ele) + if err != nil { + fmt.Println("Couldn't parse string to int ", err) + } + report = append(report, e) + } + reports = append(reports, report) + } + } + return reports +} + +func isSafe(report []int) bool { + increasing := report[0] < report[1] + flag := true + for i := range len(report) - 1 { + if increasing { + diff := report[i+1] - report[i] + if report[i] >= report[i+1] || diff > 3 || diff < 1 { + flag = false + break + } + } else { + diff := report[i] - report[i+1] + if report[i] <= report[i+1] || diff > 3 || diff < 1 { + flag = false + break + } + } + } + return flag +} + +func solve_part_one(data string) int { + reports := parseInput(data) + cnt := 0 + for _, report := range reports { + if isSafe(report) { + cnt += 1 + } + } + return cnt +} + +func solve_part_two(data string) int { + reports := parseInput(data) + cnt := 0 + for _, report := range reports { + if isSafe(report) { + cnt += 1 + } else { + for i := range len(report) { + reportTmp := make([]int, len(report)) + copy(reportTmp, report) + newReport := append(reportTmp[:i], reportTmp[i+1:]...) + if isSafe(newReport) { + cnt += 1 + break + } + } + } + } + return cnt +} + +func main() { + test := FileRead("../input/day02.test") + prod := FileRead("../input/day02.prod") + + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day03/main.go b/2024/go/src/day03/main.go new file mode 100644 index 0000000..11e9f47 --- /dev/null +++ b/2024/go/src/day03/main.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + "os" + "regexp" + "strconv" +) + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) + +} + +func solve_part_one(data string) int { + pattern := `mul\((\d+),(\d+)\)` + regex := regexp.MustCompile(pattern) + + // FindStringSubmatch returns the full match and all capture groups + matches := regex.FindAllStringSubmatch(data, -1) + + ans := 0 + + // Iterate over all matches + for _, match := range matches { + // fmt.Printf("Match %d:\n", i+1) + // fmt.Println(" Full match:", match[0]) // Entire match + left, _ := strconv.Atoi(match[1]) + right, _ := strconv.Atoi(match[2]) + ans += left * right + } + return ans +} + +func solve_part_two(data string) int { + pattern := `mul\((\d+),(\d+)\)|don't\(\)|do\(\)` + regex := regexp.MustCompile(pattern) + + // FindStringSubmatch returns the full match and all capture groups + matches := regex.FindAllStringSubmatch(data, -1) + + ans := 0 + enabled := true + + // Iterate over all matches + for _, match := range matches { + left, _ := strconv.Atoi(match[1]) + right, _ := strconv.Atoi(match[2]) + if match[0] == "don't()" { + enabled = false + } else if match[0] == "do()" { + enabled = true + } + if enabled { + ans += left * right + } + } + return ans +} + +func main() { + test := FileRead("../input/day03.test") + test_2 := FileRead("../input/day03_2.test") + prod := FileRead("../input/day03.prod") + // Define the regex pattern with capture groups + + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test_2)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day04/main.go b/2024/go/src/day04/main.go new file mode 100644 index 0000000..cb33819 --- /dev/null +++ b/2024/go/src/day04/main.go @@ -0,0 +1,133 @@ +package main + +import ( + "fmt" + "os" + "strings" +) + +type Direction string + +const ( + Up Direction = "up" + Down Direction = "down" + Left Direction = "left" + Right Direction = "right" + TopLeft Direction = "topleft" + TopRight Direction = "topRight" + BottomLeft Direction = "botleft" + BottomRight Direction = "botRight" +) + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) + +} + +func parseInput(data string) []string { + return strings.Split(data, "\n") +} + +func isValid(x int, y int, n int, m int) bool { + return x >= 0 && x < n && y >= 0 && y < m +} + +func solve_part_one(data string) int { + grid := parseInput(data) + grid = grid[:len(grid)-1] + n := len(grid) + m := len(grid[0]) + dx := [8]int{1, -1, 0, 0, 1, 1, -1, -1} + dy := [8]int{0, 0, 1, -1, 1, -1, 1, -1} + var words []string + for x := range len(grid) { + for y := range len(grid[0]) { + if grid[x][y] == byte('X') { + for i := range 8 { + word := "X" + for j := 1; j <= 3; j++ { + nx := x + dx[i]*j + ny := y + dy[i]*j + if isValid(nx, ny, n, m) { + word += string(grid[nx][ny]) + } + words = append(words, word) + } + } + } + } + } + cnt := 0 + for _, word := range words { + if word == "XMAS" { + cnt++ + + } + } + return cnt +} + +func iSXMAS(window []string) bool { + patterns := [][]string{{"M.M", + ".A.", + "S.S"}, {"M.S", + ".A.", + "M.S"}, {"S.S", + ".A.", + "M.M"}, {"S.M", + ".A.", + "S.M"}} + for _, pat := range patterns { + flag := true + for i := range len(window) { + for j := range len(window[0]) { + if pat[i][j] != '.' { + flag = flag && (pat[i][j] == window[i][j]) + } + } + } + if flag { + return true + } + } + return false +} + +func solve_part_two(data string) int { + grid := parseInput(data) + grid = grid[:len(grid)-1] + n := len(grid) + m := len(grid[0]) + var windows [][]string + for x := range n - 2 { + for y := range m - 2 { + var window []string + for i := range 3 { + window = append(window, grid[i+y][x:x+3]) + } + windows = append(windows, window) + } + } + cnt := 0 + // fmt.Println(windows) + for _, window := range windows { + if iSXMAS(window) { + cnt += 1 + } + } + return cnt +} + +func main() { + test := FileRead("../input/day04.test") + prod := FileRead("../input/day04.prod") + + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day05/main.go b/2024/go/src/day05/main.go new file mode 100644 index 0000000..6250ed9 --- /dev/null +++ b/2024/go/src/day05/main.go @@ -0,0 +1,179 @@ +package main + +import ( + "fmt" + "os" + "slices" + "sort" + "strconv" + "strings" +) + +type SafetyManual struct { + pageOrderingRules [][2]int + updates [][]int +} + +func (s SafetyManual) String() string { + var builder strings.Builder + + // Format pageOrderingRules + builder.WriteString("Page Ordering Rules: [") + for i, rule := range s.pageOrderingRules { + if i > 0 { + builder.WriteString(", ") + } + builder.WriteString(fmt.Sprintf("[%d, %d]", rule[0], rule[1])) + } + builder.WriteString("]\n") + + // Format updates + builder.WriteString("Updates: [") + for i, update := range s.updates { + if i > 0 { + builder.WriteString(", ") + } + builder.WriteString("[") + for j, val := range update { + if j > 0 { + builder.WriteString(", ") + } + builder.WriteString(fmt.Sprintf("%d", val)) + } + builder.WriteString("]") + } + builder.WriteString("]") + + return builder.String() +} + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) + +} + +func parseInput(data string) SafetyManual { + section := strings.Split(data, "\n\n") + first_section := strings.Split(section[0], "\n") + second_section := strings.Split(section[1], "\n") + var pageOrderingRules [][2]int + var updates [][]int + for _, rule := range first_section { + pages := strings.Split(rule, "|") + pageOne, _ := strconv.Atoi(pages[0]) + pageTwo, _ := strconv.Atoi(pages[1]) + arr := [2]int{pageOne, pageTwo} + pageOrderingRules = append(pageOrderingRules, arr) + } + for _, line := range second_section { + line := strings.Split(line, ",") + var update []int + for _, ele := range line { + ele, _ := strconv.Atoi(ele) + update = append(update, ele) + } + updates = append(updates, update) + } + return SafetyManual{ + pageOrderingRules: pageOrderingRules, + updates: updates, + } + +} + +func filter_relevant_rules(s *SafetyManual, update *[]int) [][2]int { + var filtered_rules [][2]int + for _, rule := range s.pageOrderingRules { + if slices.Contains(*update, rule[0]) && slices.Contains(*update, rule[1]) { + filtered_rules = append(filtered_rules, rule) + } + } + return filtered_rules +} + +func makeProperList(items [][2]int) []int { + counter := make(map[int]int) + + for _, item := range items { + counter[item[0]]++ + if _, exists := counter[item[1]]; !exists { + counter[item[1]] = 0 + } + } + + var sorted [][2]int + + for val, fq := range counter { + arr := [2]int{fq, val} + sorted = append(sorted, arr) + } + + sort.Slice(sorted, func(i, j int) bool { + return sorted[i][0] > sorted[j][0] + }) + + var properList []int + + for _, x := range sorted { + if len(x) == 0 { + break + } + properList = append(properList, x[1]) + } + + return properList +} + +func solve_part_one(data string) int { + section := parseInput(data) + ans := 0 + for _, update := range section.updates { + filtered_rules := filter_relevant_rules(§ion, &update) + properList := makeProperList(filtered_rules) + flag := true + for i := range properList { + if properList[i] != update[i] { + flag = false + break + } + } + if flag { + ans += update[len(update)/2] + } + } + return ans +} + +func solve_part_two(data string) int { + section := parseInput(data) + ans := 0 + for _, update := range section.updates { + filtered_rules := filter_relevant_rules(§ion, &update) + properList := makeProperList(filtered_rules) + flag := true + for i := range properList { + if properList[i] != update[i] { + flag = false + break + } + } + if !flag { + ans += properList[len(properList)/2] + } + } + return ans +} + +func main() { + test := FileRead("../input/day05.test") + prod := FileRead("../input/day05.prod") + + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day06/main.go b/2024/go/src/day06/main.go new file mode 100644 index 0000000..10c1042 --- /dev/null +++ b/2024/go/src/day06/main.go @@ -0,0 +1,188 @@ +package main + +import ( + "fmt" + "os" + "slices" + "strings" +) + +type Orientation = int + +const ( + Up Orientation = 0 + Right Orientation = 1 + Down Orientation = 2 + Left Orientation = 3 +) + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) + +} + +func turn90(orientation Orientation) Orientation { + orientations := [4]Orientation{Up, Right, Down, Left} + return orientations[(orientation+1)%4] +} + +type Grid = []string + +func isValid(grid *Grid, x int, y int) bool { + n, m := len(*grid), len((*grid)[0]) + return x >= 0 && x < n && y >= 0 && y < m + +} + +func replaceCharGrid(grid *Grid, x int, y int, ch rune) { + str := (*grid)[x] + runes := []rune(str) + runes[y] = ch + (*grid)[x] = string(runes) +} + +func simulateTrail(grid *Grid, gPos [2]int) int { + set := make(map[[2]int]struct{}) + set[gPos] = struct{}{} + curOrientation := getOrientation((*grid)[gPos[0]][gPos[1]]) + dx := [4]int{-1, 0, 1, 0} // Up, Right, Down, Left + dy := [4]int{0, 1, 0, -1} + for { + nx := gPos[0] + dx[curOrientation] + ny := gPos[1] + dy[curOrientation] + if isValid(grid, nx, ny) { + curPoint := (*grid)[nx][ny] + if !isObstacle(curPoint) { + gPos = [2]int{nx, ny} + replaceCharGrid(grid, nx, ny, 'X') + set[gPos] = struct{}{} + } else { + curOrientation = turn90(curOrientation) + } + } else { + break + } + } + return len(set) +} + +func parseInput(data string) Grid { + var grid Grid + for _, line := range strings.Split(data, "\n") { + if len(line) > 0 { + grid = append(grid, line) + } + } + return grid +} + +func getOrientation(ch byte) Orientation { + if ch == '^' { + return Up + } else if ch == '>' { + return Right + } else if ch == '<' { + return Left + } else { + return Down + } +} + +func isGaurd(ch byte) bool { + return slices.Contains([]string{"^", ">", "<", "V"}, string(ch)) +} + +func isObstacle(ch byte) bool { + return ch == '#' +} + +func solve_part_one(data string) int { + grid := parseInput(data) + var guardPosition [2]int + for i, row := range grid { + for j, ch := range row { + if isGaurd(byte(ch)) { + guardPosition = [2]int{i, j} + } + } + } + trailCount := simulateTrail(&grid, guardPosition) + return trailCount +} + +func isStuck(grid *Grid, gPos [2]int) bool { + // n, m := len(*grid), len((*grid)[0]) + var visited [130][130][4]bool + // visited := make([][][]bool, 4) + // for i := range visited { + // visited[i] = make([][]bool, n) + // for j := range visited[i] { + // visited[i][j] = make([]bool, m) + // } + // } + curOrientation := getOrientation((*grid)[gPos[0]][gPos[1]]) + visited[gPos[0]][gPos[1]][curOrientation] = true + dx := [4]int{-1, 0, 1, 0} // Up, Right, Down, Left + dy := [4]int{0, 1, 0, -1} + for { + nx := gPos[0] + dx[curOrientation] + ny := gPos[1] + dy[curOrientation] + if isValid(grid, nx, ny) { + curPoint := (*grid)[nx][ny] + if !isObstacle(curPoint) { + gPos = [2]int{nx, ny} + if visited[nx][ny][curOrientation] { + return true + } + visited[nx][ny][curOrientation] = true + } else { + curOrientation = turn90(curOrientation) + } + } else { + break + } + } + return false +} + +func solve_part_two(data string) int { + grid := parseInput(data) + var guardPosition [2]int + for i, row := range grid { + for j, ch := range row { + if isGaurd(byte(ch)) { + guardPosition = [2]int{i, j} + } + } + } + n, m := len(grid), len(grid[0]) + ans := 0 + for i := range n { + for j := range m { + if !(i == guardPosition[0] && j == guardPosition[1]) { + flag := grid[i][j] == '.' + replaceCharGrid(&grid, i, j, '#') + if isStuck(&grid, guardPosition) { + ans++ + } + if flag { + replaceCharGrid(&grid, i, j, '.') + } + } + } + } + return ans +} + +func main() { + test := FileRead("../input/day06.test") + prod := FileRead("../input/day06.prod") + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day07/main.go b/2024/go/src/day07/main.go new file mode 100644 index 0000000..06c7438 --- /dev/null +++ b/2024/go/src/day07/main.go @@ -0,0 +1,190 @@ +package main + +import ( + "fmt" + "os" + "strconv" + "strings" +) + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) + +} + +type Op = string + +const ( + Plus Op = "+" + Mul Op = "*" + Concat Op = "||" +) + +var OpsOne = []Op{Plus, Mul} +var OpsTwo = []Op{Plus, Mul, Concat} + +type Calibration struct { + target int + vals []int +} + +type Expression = []string + +func (c Calibration) String() string { + valsStr := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(c.vals)), ", "), "[]") + return fmt.Sprintf("Calibration(target: %d, vals: [%s])", c.target, valsStr) +} + +func parseInput(data string) []Calibration { + lines := strings.Split(data, "\n") + + var cals []Calibration + + for _, line := range lines { + if len(line) > 0 { + cal := strings.Split(line, ": ") + target, _ := strconv.Atoi(cal[0]) + var vals []int + for _, num := range strings.Split(cal[1], " ") { + val, _ := strconv.Atoi(num) + vals = append(vals, val) + } + calibration := Calibration{ + target: target, + vals: vals, + } + cals = append(cals, calibration) + } + } + + return cals +} + +func generatePossibleExpressions(opsLeft int, expr *Expression, expressions *[]Expression, Ops []string) { + if opsLeft == 0 { + comb := make([]string, len(*expr)) + copy(comb, *expr) + *expressions = append(*expressions, comb) + } else { + for _, op := range Ops { + // choose + *expr = append(*expr, op) + + // explore + generatePossibleExpressions(opsLeft-1, expr, expressions, Ops) + + // unchoose + *expr = (*expr)[:len(*expr)-1] + } + } + +} + +func removeElement(s []int, i int) ([]int, error) { + if i >= len(s) || i < 0 { + return nil, fmt.Errorf("Index is out of range. Index is %d with slice length %d", i, len(s)) + } + return append(s[:i], s[i+1:]...), nil +} + +func removeElementString(s []string, i int) ([]string, error) { + if i >= len(s) || i < 0 { + return nil, fmt.Errorf("Index is out of range. Index is %d with slice length %d", i, len(s)) + } + return append(s[:i], s[i+1:]...), nil +} + +func evalPartOne(vals []int, expression *Expression) int { + for _, op := range *expression { + left := vals[0] + right := vals[1] + if op == Mul { + vals, _ = removeElement(vals, 0) + vals[0] = left * right + } else if op == Plus { + vals, _ = removeElement(vals, 0) + vals[0] = left + right + } + } + + return vals[0] +} +func evalPartTwo(vals []int, expression *Expression) int { + for _, op := range *expression { + left := vals[0] + right := vals[1] + if op == Mul { + vals, _ = removeElement(vals, 0) + vals[0] = left * right + } else if op == Plus { + vals, _ = removeElement(vals, 0) + vals[0] = left + right + } else if op == "||" { + vals, _ = removeElement(vals, 0) + // vals[0], _ = strconv.Atoi(strconv.Itoa(left) + strconv.Itoa(right)) + multiplier := 1 + for temp := right; temp > 0; temp /= 10 { + multiplier *= 10 + } + vals[0] = left*multiplier + right + } + } + + // fmt.Printf("expression: %v\n", (*expression)) + // fmt.Printf("vals: %v\n", vals) + + return vals[0] +} +func solve_part_one(data string) int64 { + calibrations := parseInput(data) + var ans int64 = 0 + for _, calibration := range calibrations { + var expressions []Expression + generatePossibleExpressions((len(calibration.vals) - 1), &[]string{}, &expressions, OpsOne) + for _, expr := range expressions { + copy_vals := make([]int, len(calibration.vals)) + copy(copy_vals, calibration.vals) + if evalPartOne(copy_vals, &expr) == calibration.target { + // fmt.Printf("expr: %v\n", expr) + ans += int64(calibration.target) + break + } + } + // fmt.Printf("expressions: %v\n", expressions) + expressions = []Expression{} + } + return ans +} + +func solve_part_two(data string) int64 { + calibrations := parseInput(data) + var ans int64 = 0 + for _, calibration := range calibrations { + var expressions []Expression + generatePossibleExpressions((len(calibration.vals) - 1), &[]string{}, &expressions, OpsTwo) + for _, expr := range expressions { + copy_vals := make([]int, len(calibration.vals)) + copy(copy_vals, calibration.vals) + if evalPartTwo(copy_vals, &expr) == calibration.target { + // fmt.Printf("expr: %v\n", expr) + ans += int64(calibration.target) + break + } + } + expressions = []Expression{} + } + return ans +} + +func main() { + test := FileRead("../input/day07.test") + prod := FileRead("../input/day07.prod") + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day08/main.go b/2024/go/src/day08/main.go new file mode 100644 index 0000000..d3bce0c --- /dev/null +++ b/2024/go/src/day08/main.go @@ -0,0 +1,139 @@ +package main + +import ( + "fmt" + "os" + "strings" +) + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) + +} + +type Grid = [][]rune + +func printGrid(grid [][]rune) { + for _, row := range grid { + for _, cell := range row { + fmt.Print(string(cell)) + } + fmt.Println() + } +} + +func parseInput(data string) Grid { + lines := strings.Split(data, "\n") + + var grid Grid + + for _, line := range lines { + if len(line) > 0 { + runes := []rune(line) + grid = append(grid, runes) + } + } + return grid +} + +func inBounds(x, y, n, m int) bool { + return x >= 0 && x < n && y >= 0 && y < m +} + +type Point = [2]int +type Points = [][2]int + +func getPosMap(grid *Grid) map[rune]Points { + n, m := len(*grid), len((*grid)[0]) + antinodes := make(map[rune]Points) + for i := 0; i < n; i++ { + for j := 0; j < m; j++ { + curPos := Point{i, j} + curRune := (*grid)[i][j] + if curRune != '.' { + antinodes[curRune] = append(antinodes[curRune], curPos) + } + } + } + return antinodes +} + +func isValidAntenna(grid *Grid, i, j int) bool { + n, m := len(*grid), len((*grid)[0]) + if inBounds(i, j, n, m) { + return true + } + return false +} + +func solve_part_one(data string) int { + grid := parseInput(data) + antennas := getPosMap(&grid) + antinodes := make(map[Point]struct{}) + for _, val := range antennas { + for i := 0; i < len(val); i++ { + curPosI := val[i] + for j := i + 1; j < len(val); j++ { + curPosJ := val[j] + diffOne := [2]int{curPosI[0] - curPosJ[0], curPosI[1] - curPosJ[1]} + diffTwo := [2]int{curPosJ[0] - curPosI[0], curPosJ[1] - curPosI[1]} + firstAntennaPos := [2]int{curPosI[0] + diffOne[0], curPosI[1] + diffOne[1]} + secondAntennaPos := [2]int{curPosJ[0] + diffTwo[0], curPosJ[1] + diffTwo[1]} + if isValidAntenna(&grid, firstAntennaPos[0], firstAntennaPos[1]) { + antinodes[firstAntennaPos] = struct{}{} + } + if isValidAntenna(&grid, secondAntennaPos[0], secondAntennaPos[1]) { + antinodes[secondAntennaPos] = struct{}{} + } + } + } + } + return len(antinodes) +} + +func solve_part_two(data string) int { + grid := parseInput(data) + antennas := getPosMap(&grid) + cnt := 0 + for _, val := range antennas { + for i := 0; i < len(val); i++ { + curPosI := val[i] + for j := i + 1; j < len(val); j++ { + curPosJ := val[j] + diffOne := [2]int{curPosI[0] - curPosJ[0], curPosI[1] - curPosJ[1]} + diffTwo := [2]int{curPosJ[0] - curPosI[0], curPosJ[1] - curPosI[1]} + firstAntennaPos := [2]int{curPosI[0] + diffOne[0], curPosI[1] + diffOne[1]} + secondAntennaPos := [2]int{curPosJ[0] + diffTwo[0], curPosJ[1] + diffTwo[1]} + for isValidAntenna(&grid, firstAntennaPos[0], firstAntennaPos[1]) { + grid[firstAntennaPos[0]][firstAntennaPos[1]] = '#' + firstAntennaPos = [2]int{firstAntennaPos[0] + diffOne[0], firstAntennaPos[1] + diffOne[1]} + } + for isValidAntenna(&grid, secondAntennaPos[0], secondAntennaPos[1]) { + grid[secondAntennaPos[0]][secondAntennaPos[1]] = '#' + secondAntennaPos = [2]int{secondAntennaPos[0] + diffTwo[0], secondAntennaPos[1] + diffTwo[1]} + } + } + } + } + for i := 0; i < len(grid); i++ { + for j := 0; j < len(grid); j++ { + if grid[i][j] != '.' { + cnt++ + } + } + } + return cnt +} + +func main() { + test := FileRead("../input/day08.test") + prod := FileRead("../input/day08.prod") + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day09/main.go b/2024/go/src/day09/main.go new file mode 100644 index 0000000..db2d99a --- /dev/null +++ b/2024/go/src/day09/main.go @@ -0,0 +1,169 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func InsertAt(arr *[]FileBlock, index int, value FileBlock) error { + if index < 0 || index > len(*arr) { + return fmt.Errorf("index out of range") + } + *arr = append((*arr)[:index], append([]FileBlock{value}, (*arr)[index:]...)...) + return nil +} + +func RemoveAt(arr *[]FileBlock, index int) (FileBlock, error) { + if index < 0 || index >= len(*arr) { + return FileBlock{}, fmt.Errorf("index out of range") + } + ele := (*arr)[index] + *arr = append((*arr)[:index], (*arr)[index+1:]...) + return ele, nil +} + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) + +} + +func parseInput(data string) string { + return data +} + +func genereateBlockMap(diskMap string) []string { + var blockMap []string + id := 0 + for i, ch := range diskMap { + rep, _ := strconv.Atoi(string(ch)) + if i%2 == 0 { + for i := 0; i < rep; i++ { + blockMap = append(blockMap, strconv.Itoa(id)) + } + id += 1 + } else { + for i := 0; i < rep; i++ { + blockMap = append(blockMap, ".") + } + } + } + return blockMap +} + +func genereateFileBlocks(diskMap string) []FileBlock { + var fileBlocks []FileBlock + id := 0 + for i, ch := range diskMap { + rep, _ := strconv.Atoi(string(ch)) + if i%2 == 0 { + block := FileBlock{id: id, space: rep} + fileBlocks = append(fileBlocks, block) + id += 1 + } else { + block := FileBlock{id: -1, space: rep} + if rep > 0 { + fileBlocks = append(fileBlocks, block) + } + } + } + return fileBlocks +} + +func moveBlocks(blockMap []string) { + i := 0 + j := len(blockMap) - 1 + for i < j { + if blockMap[i] == "." { + if blockMap[j] != "." { + blockMap[i], blockMap[j] = blockMap[j], blockMap[i] + i++ + } + j-- + } else { + i++ + } + } +} + +type FileBlock struct { + id int // id -1 will be the free block '.' + space int +} + +func moveBlocksPartTwo(fileBlocks []FileBlock) []string { + for i := 0; i < len(fileBlocks); i++ { + if fileBlocks[i].id != -1 { + continue + } + for j := len(fileBlocks) - 1; j >= i; j-- { + if fileBlocks[j].id == -1 { + continue + } + if fileBlocks[i].space == fileBlocks[j].space { + fileBlocks[i], fileBlocks[j] = fileBlocks[j], fileBlocks[i] + i++ + j-- + break + } else if fileBlocks[i].space > fileBlocks[j].space { + _ = InsertAt(&fileBlocks, i+1, FileBlock{id: -1, space: fileBlocks[i].space - fileBlocks[j].space}) + spaceJ := fileBlocks[j+1].space + fileBlocks[i], fileBlocks[j+1] = fileBlocks[j+1], fileBlocks[i] + fileBlocks[j+1].id = -1 + fileBlocks[j+1].space = spaceJ + break + } + } + } + var blocks []string + for _, block := range fileBlocks { + if block.id == -1 { + for i := 0; i < block.space; i++ { + blocks = append(blocks, ".") + } + } else { + for i := 0; i < block.space; i++ { + blocks = append(blocks, strconv.Itoa(block.id)) + } + } + } + return blocks +} + +func checkSum(blockMap []string) int64 { + var sum int64 = 0 + for i, ch := range blockMap { + if ch == "." { + continue + } + id, _ := strconv.Atoi(ch) + sum += int64(id) * int64(i) + } + return sum +} +func solve_part_one(data string) int64 { + diskMap := parseInput(data) + blockMap := genereateBlockMap(diskMap) + moveBlocks(blockMap) + return checkSum(blockMap) +} + +func solve_part_two(data string) int64 { + diskMap := parseInput(data) + fileBlocks := genereateFileBlocks(diskMap) + blocks := moveBlocksPartTwo(fileBlocks) + return checkSum(blocks) +} + +func main() { + test := FileRead("../input/day09.test") + prod := FileRead("../input/day09.prod") + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day1/main.go b/2024/go/src/day1/main.go deleted file mode 100644 index 17cfa54..0000000 --- a/2024/go/src/day1/main.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "fmt" - "os" - "sort" - "strconv" - "strings" -) - -func AbsInt(x int) int { - if x < 0 { - return -x - } - return x -} - -func solve_part_one(data string) int { - var list_1 []int - var list_2 []int - - ans := 0 - for _, line := range strings.Split(data, "\n") { - if len(line) > 0 { - elements := strings.Split(line, " ") - ele1, _ := strconv.Atoi(elements[0]) - ele2, _ := strconv.Atoi(elements[1]) - list_1 = append(list_1, ele1) - list_2 = append(list_2, ele2) - } - } - sort.Ints(list_1) - sort.Ints(list_2) - for i := range len(list_1) { - ans += AbsInt(list_1[i] - list_2[i]) - } - return ans -} - -func solve_part_two(data string) int { - var list_1 []int - var list_2 []int - - ans := 0 - for _, line := range strings.Split(data, "\n") { - if len(line) > 0 { - elements := strings.Split(line, " ") - ele1, _ := strconv.Atoi(elements[0]) - ele2, _ := strconv.Atoi(elements[1]) - list_1 = append(list_1, ele1) - list_2 = append(list_2, ele2) - } - } - counts := make(map[int]int) - - for _, num := range list_2 { - counts[num]++ - } - for i := range len(list_1) { - ans += list_1[i] * counts[list_1[i]] - } - return ans -} - -func main() { - test_1, _ := os.ReadFile("../input/day1.test") - test_2, _ := os.ReadFile("../input/day1_2.test") - prod, _ := os.ReadFile("../input/day_1.prod") - content_test_1 := string(test_1) - content_test_2 := string(test_2) - content_prod := string(prod) - - fmt.Println("Part_1 test: ", solve_part_one(content_test_1)) - fmt.Println("Part_1 prod: ", solve_part_one(content_prod)) - fmt.Println("Part_2 test: ", solve_part_two(content_test_2)) - fmt.Println("Part_2 prod: ", solve_part_two(content_prod)) -} diff --git a/2024/go/src/day11/main.go b/2024/go/src/day11/main.go new file mode 100644 index 0000000..afe54c9 --- /dev/null +++ b/2024/go/src/day11/main.go @@ -0,0 +1,107 @@ +package main + +import ( + "fmt" + "math" + "os" + "strconv" + "strings" +) + +func FileRead(path string) string { + file, err := os.ReadFile(path) + if err != nil { + fmt.Println("Couldn't Read file: ", err) + } + return string(file) +} + +func parseInput(data string) []int { + var stones []int + for _, x := range strings.Split(data, " ") { + x := strings.TrimRight(x, "\n") + stone, _ := strconv.Atoi(x) + stones = append(stones, stone) + } + return stones +} + +func insert(slice []int, index int, value int) []int { + if index < 0 || index > len(slice) { + return slice // Or handle the error as you prefer + } + return append(slice[:index], append([]int{value}, slice[index:]...)...) +} + +func getNumDigits(digit int) int { + cnt := 0 + for digit != 0 { + digit /= 10 + cnt++ + } + return cnt +} + +func splitNumber(num int) (int, int) { + digits := getNumDigits(num) + divisor := int(math.Pow10(digits / 2)) + left := num / divisor + right := num % divisor + return left, right +} + +func isEvenDigits(digit int) bool { + return getNumDigits(digit)%2 == 0 +} + +func processStone(cache *map[[2]int]int, stone, blinks int) int { + result := 0 + if blinks == 0 { + return 1 + } else { + _, exists := (*cache)[[2]int{stone, blinks}] + if !exists { + if stone == 0 { + result = processStone(cache, 1, blinks-1) + } else if isEvenDigits(stone) { + left, right := splitNumber(stone) + result += processStone(cache, left, blinks-1) + result += processStone(cache, right, blinks-1) + } else { + result = processStone(cache, stone*2024, blinks-1) + } + (*cache)[[2]int{stone, blinks}] = result + } + return (*cache)[[2]int{stone, blinks}] + } +} +func processStones(stones []int, blinks int) int { + cache := make(map[[2]int]int) + ans := 0 + n := len(stones) + for j := 0; j < n; j++ { + ans += processStone(&cache, stones[j], blinks) + } + return ans +} + +func solve_part_one(data string) int { + stones := parseInput(data) + ans := processStones(stones, 25) + return ans +} + +func solve_part_two(data string) int { + stones := parseInput(data) + ans := processStones(stones, 75) + return ans +} + +func main() { + test := FileRead("../input/day11.test") + prod := FileRead("../input/day11.prod") + fmt.Println("Part_1 test: ", solve_part_one(test)) + fmt.Println("Part_1 prod: ", solve_part_one(prod)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) +} diff --git a/2024/go/src/day2/main.go b/2024/go/src/day2/main.go deleted file mode 100644 index b06bed4..0000000 --- a/2024/go/src/day2/main.go +++ /dev/null @@ -1,99 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strconv" - "strings" -) - -func FileRead(path string) string { - file, err := os.ReadFile(path) - if err != nil { - fmt.Println("Couldn't Read file: ", err) - } - return string(file) - -} - -func parseInput(data string) [][]int { - var reports [][]int - for _, line := range strings.Split(data, "\n") { - var report []int - if len(line) > 0 { - elements := strings.Split(line, " ") - for _, ele := range elements { - e, err := strconv.Atoi(ele) - if err != nil { - fmt.Println("Couldn't parse string to int ", err) - } - report = append(report, e) - } - reports = append(reports, report) - } - } - return reports -} - -func isSafe(report []int) bool { - increasing := report[0] < report[1] - flag := true - for i := range len(report) - 1 { - if increasing { - diff := report[i+1] - report[i] - if report[i] >= report[i+1] || diff > 3 || diff < 1 { - flag = false - break - } - } else { - diff := report[i] - report[i+1] - if report[i] <= report[i+1] || diff > 3 || diff < 1 { - flag = false - break - } - } - } - return flag -} - -func solve_part_one(data string) int { - reports := parseInput(data) - cnt := 0 - for _, report := range reports { - if isSafe(report) { - cnt += 1 - } - } - return cnt -} - -func solve_part_two(data string) int { - reports := parseInput(data) - cnt := 0 - for _, report := range reports { - if isSafe(report) { - cnt += 1 - } else { - for i := range len(report) { - reportTmp := make([]int, len(report)) - copy(reportTmp, report) - newReport := append(reportTmp[:i], reportTmp[i+1:]...) - if isSafe(newReport) { - cnt += 1 - break - } - } - } - } - return cnt -} - -func main() { - test := FileRead("../input/day2.test") - prod := FileRead("../input/day2.prod") - - fmt.Println("Part_1 test: ", solve_part_one(test)) - fmt.Println("Part_1 prod: ", solve_part_one(prod)) - fmt.Println("Part_2 test: ", solve_part_two(test)) - fmt.Println("Part_2 prod: ", solve_part_two(prod)) -} diff --git a/2024/go/src/day3/main.go b/2024/go/src/day3/main.go deleted file mode 100644 index 661d7aa..0000000 --- a/2024/go/src/day3/main.go +++ /dev/null @@ -1,75 +0,0 @@ -package main - -import ( - "fmt" - "os" - "regexp" - "strconv" -) - -func FileRead(path string) string { - file, err := os.ReadFile(path) - if err != nil { - fmt.Println("Couldn't Read file: ", err) - } - return string(file) - -} - -func solve_part_one(data string) int { - pattern := `mul\((\d+),(\d+)\)` - regex := regexp.MustCompile(pattern) - - // FindStringSubmatch returns the full match and all capture groups - matches := regex.FindAllStringSubmatch(data, -1) - - ans := 0 - - // Iterate over all matches - for _, match := range matches { - // fmt.Printf("Match %d:\n", i+1) - // fmt.Println(" Full match:", match[0]) // Entire match - left, _ := strconv.Atoi(match[1]) - right, _ := strconv.Atoi(match[2]) - ans += left * right - } - return ans -} - -func solve_part_two(data string) int { - pattern := `mul\((\d+),(\d+)\)|don't\(\)|do\(\)` - regex := regexp.MustCompile(pattern) - - // FindStringSubmatch returns the full match and all capture groups - matches := regex.FindAllStringSubmatch(data, -1) - - ans := 0 - enabled := true - - // Iterate over all matches - for _, match := range matches { - left, _ := strconv.Atoi(match[1]) - right, _ := strconv.Atoi(match[2]) - if match[0] == "don't()" { - enabled = false - } else if match[0] == "do()" { - enabled = true - } - if enabled { - ans += left * right - } - } - return ans -} - -func main() { - test := FileRead("../input/day3.test") - test_2 := FileRead("../input/day3_2.test") - prod := FileRead("../input/day3.prod") - // Define the regex pattern with capture groups - - fmt.Println("Part_1 test: ", solve_part_one(test)) - fmt.Println("Part_1 prod: ", solve_part_one(prod)) - fmt.Println("Part_2 test: ", solve_part_two(test_2)) - fmt.Println("Part_2 prod: ", solve_part_two(prod)) -} diff --git a/2024/go/src/day4/main.go b/2024/go/src/day4/main.go deleted file mode 100644 index ec90ed1..0000000 --- a/2024/go/src/day4/main.go +++ /dev/null @@ -1,133 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strings" -) - -type Direction string - -const ( - Up Direction = "up" - Down Direction = "down" - Left Direction = "left" - Right Direction = "right" - TopLeft Direction = "topleft" - TopRight Direction = "topRight" - BottomLeft Direction = "botleft" - BottomRight Direction = "botRight" -) - -func FileRead(path string) string { - file, err := os.ReadFile(path) - if err != nil { - fmt.Println("Couldn't Read file: ", err) - } - return string(file) - -} - -func parseInput(data string) []string { - return strings.Split(data, "\n") -} - -func isValid(x int, y int, n int, m int) bool { - return x >= 0 && x < n && y >= 0 && y < m -} - -func solve_part_one(data string) int { - grid := parseInput(data) - grid = grid[:len(grid)-1] - n := len(grid) - m := len(grid[0]) - dx := [8]int{1, -1, 0, 0, 1, 1, -1, -1} - dy := [8]int{0, 0, 1, -1, 1, -1, 1, -1} - var words []string - for x := range len(grid) { - for y := range len(grid[0]) { - if grid[x][y] == byte('X') { - for i := range 8 { - word := "X" - for j := 1; j <= 3; j++ { - nx := x + dx[i]*j - ny := y + dy[i]*j - if isValid(nx, ny, n, m) { - word += string(grid[nx][ny]) - } - words = append(words, word) - } - } - } - } - } - cnt := 0 - for _, word := range words { - if word == "XMAS" { - cnt++ - - } - } - return cnt -} - -func iSXMAS(window []string) bool { - patterns := [][]string{{"M.M", - ".A.", - "S.S"}, {"M.S", - ".A.", - "M.S"}, {"S.S", - ".A.", - "M.M"}, {"S.M", - ".A.", - "S.M"}} - for _, pat := range patterns { - flag := true - for i := range len(window) { - for j := range len(window[0]) { - if pat[i][j] != '.' { - flag = flag && (pat[i][j] == window[i][j]) - } - } - } - if flag { - return true - } - } - return false -} - -func solve_part_two(data string) int { - grid := parseInput(data) - grid = grid[:len(grid)-1] - n := len(grid) - m := len(grid[0]) - var windows [][]string - for x := range n - 2 { - for y := range m - 2 { - var window []string - for i := range 3 { - window = append(window, grid[i+y][x:x+3]) - } - windows = append(windows, window) - } - } - cnt := 0 - // fmt.Println(windows) - for _, window := range windows { - if iSXMAS(window) { - cnt += 1 - } - } - return cnt -} - -func main() { - test := FileRead("../input/day4.test") - prod := FileRead("../input/day4.prod") - - fmt.Println("Part_1 test: ", solve_part_one(test)) - fmt.Println("Part_1 prod: ", solve_part_one(prod)) - fmt.Println("Part_2 test: ", solve_part_two(test)) - fmt.Println("Part_2 prod: ", solve_part_two(prod)) -} diff --git a/2024/go/src/day5/main.go b/2024/go/src/day5/main.go deleted file mode 100644 index 65900e5..0000000 --- a/2024/go/src/day5/main.go +++ /dev/null @@ -1,179 +0,0 @@ -package main - -import ( - "fmt" - "os" - "slices" - "sort" - "strconv" - "strings" -) - -type SafetyManual struct { - pageOrderingRules [][2]int - updates [][]int -} - -func (s SafetyManual) String() string { - var builder strings.Builder - - // Format pageOrderingRules - builder.WriteString("Page Ordering Rules: [") - for i, rule := range s.pageOrderingRules { - if i > 0 { - builder.WriteString(", ") - } - builder.WriteString(fmt.Sprintf("[%d, %d]", rule[0], rule[1])) - } - builder.WriteString("]\n") - - // Format updates - builder.WriteString("Updates: [") - for i, update := range s.updates { - if i > 0 { - builder.WriteString(", ") - } - builder.WriteString("[") - for j, val := range update { - if j > 0 { - builder.WriteString(", ") - } - builder.WriteString(fmt.Sprintf("%d", val)) - } - builder.WriteString("]") - } - builder.WriteString("]") - - return builder.String() -} - -func FileRead(path string) string { - file, err := os.ReadFile(path) - if err != nil { - fmt.Println("Couldn't Read file: ", err) - } - return string(file) - -} - -func parseInput(data string) SafetyManual { - section := strings.Split(data, "\n\n") - first_section := strings.Split(section[0], "\n") - second_section := strings.Split(section[1], "\n") - var pageOrderingRules [][2]int - var updates [][]int - for _, rule := range first_section { - pages := strings.Split(rule, "|") - pageOne, _ := strconv.Atoi(pages[0]) - pageTwo, _ := strconv.Atoi(pages[1]) - arr := [2]int{pageOne, pageTwo} - pageOrderingRules = append(pageOrderingRules, arr) - } - for _, line := range second_section { - line := strings.Split(line, ",") - var update []int - for _, ele := range line { - ele, _ := strconv.Atoi(ele) - update = append(update, ele) - } - updates = append(updates, update) - } - return SafetyManual{ - pageOrderingRules: pageOrderingRules, - updates: updates, - } - -} - -func filter_relevant_rules(s *SafetyManual, update *[]int) [][2]int { - var filtered_rules [][2]int - for _, rule := range s.pageOrderingRules { - if slices.Contains(*update, rule[0]) && slices.Contains(*update, rule[1]) { - filtered_rules = append(filtered_rules, rule) - } - } - return filtered_rules -} - -func makeProperList(items [][2]int) []int { - counter := make(map[int]int) - - for _, item := range items { - counter[item[0]]++ - if _, exists := counter[item[1]]; !exists { - counter[item[1]] = 0 - } - } - - var sorted [][2]int - - for val, fq := range counter { - arr := [2]int{fq, val} - sorted = append(sorted, arr) - } - - sort.Slice(sorted, func(i, j int) bool { - return sorted[i][0] > sorted[j][0] - }) - - var properList []int - - for _, x := range sorted { - if len(x) == 0 { - break - } - properList = append(properList, x[1]) - } - - return properList -} - -func solve_part_one(data string) int { - section := parseInput(data) - ans := 0 - for _, update := range section.updates { - filtered_rules := filter_relevant_rules(§ion, &update) - properList := makeProperList(filtered_rules) - flag := true - for i := range properList { - if properList[i] != update[i] { - flag = false - break - } - } - if flag { - ans += update[len(update)/2] - } - } - return ans -} - -func solve_part_two(data string) int { - section := parseInput(data) - ans := 0 - for _, update := range section.updates { - filtered_rules := filter_relevant_rules(§ion, &update) - properList := makeProperList(filtered_rules) - flag := true - for i := range properList { - if properList[i] != update[i] { - flag = false - break - } - } - if !flag { - ans += properList[len(properList)/2] - } - } - return ans -} - -func main() { - test := FileRead("../input/day5.test") - prod := FileRead("../input/day5.prod") - - fmt.Println("Part_1 test: ", solve_part_one(test)) - fmt.Println("Part_1 prod: ", solve_part_one(prod)) - fmt.Println("Part_2 test: ", solve_part_two(test)) - fmt.Println("Part_2 prod: ", solve_part_two(prod)) -} diff --git a/2024/go/src/day6/main.go b/2024/go/src/day6/main.go deleted file mode 100644 index fd629e6..0000000 --- a/2024/go/src/day6/main.go +++ /dev/null @@ -1,188 +0,0 @@ -package main - -import ( - "fmt" - "os" - "slices" - "strings" -) - -type Orientation = int - -const ( - Up Orientation = 0 - Right Orientation = 1 - Down Orientation = 2 - Left Orientation = 3 -) - -func FileRead(path string) string { - file, err := os.ReadFile(path) - if err != nil { - fmt.Println("Couldn't Read file: ", err) - } - return string(file) - -} - -func turn90(orientation Orientation) Orientation { - orientations := [4]Orientation{Up, Right, Down, Left} - return orientations[(orientation+1)%4] -} - -type Grid = []string - -func isValid(grid *Grid, x int, y int) bool { - n, m := len(*grid), len((*grid)[0]) - return x >= 0 && x < n && y >= 0 && y < m - -} - -func replaceCharGrid(grid *Grid, x int, y int, ch rune) { - str := (*grid)[x] - runes := []rune(str) - runes[y] = ch - (*grid)[x] = string(runes) -} - -func simulateTrail(grid *Grid, gPos [2]int) int { - set := make(map[[2]int]struct{}) - set[gPos] = struct{}{} - curOrientation := getOrientation((*grid)[gPos[0]][gPos[1]]) - dx := [4]int{-1, 0, 1, 0} // Up, Right, Down, Left - dy := [4]int{0, 1, 0, -1} - for { - nx := gPos[0] + dx[curOrientation] - ny := gPos[1] + dy[curOrientation] - if isValid(grid, nx, ny) { - curPoint := (*grid)[nx][ny] - if !isObstacle(curPoint) { - gPos = [2]int{nx, ny} - replaceCharGrid(grid, nx, ny, 'X') - set[gPos] = struct{}{} - } else { - curOrientation = turn90(curOrientation) - } - } else { - break - } - } - return len(set) -} - -func parseInput(data string) Grid { - var grid Grid - for _, line := range strings.Split(data, "\n") { - if len(line) > 0 { - grid = append(grid, line) - } - } - return grid -} - -func getOrientation(ch byte) Orientation { - if ch == '^' { - return Up - } else if ch == '>' { - return Right - } else if ch == '<' { - return Left - } else { - return Down - } -} - -func isGaurd(ch byte) bool { - return slices.Contains([]string{"^", ">", "<", "V"}, string(ch)) -} - -func isObstacle(ch byte) bool { - return ch == '#' -} - -func solve_part_one(data string) int { - grid := parseInput(data) - var guardPosition [2]int - for i, row := range grid { - for j, ch := range row { - if isGaurd(byte(ch)) { - guardPosition = [2]int{i, j} - } - } - } - trailCount := simulateTrail(&grid, guardPosition) - return trailCount -} - -func isStuck(grid *Grid, gPos [2]int) bool { - // n, m := len(*grid), len((*grid)[0]) - var visited [130][130][4]bool - // visited := make([][][]bool, 4) - // for i := range visited { - // visited[i] = make([][]bool, n) - // for j := range visited[i] { - // visited[i][j] = make([]bool, m) - // } - // } - curOrientation := getOrientation((*grid)[gPos[0]][gPos[1]]) - visited[gPos[0]][gPos[1]][curOrientation] = true - dx := [4]int{-1, 0, 1, 0} // Up, Right, Down, Left - dy := [4]int{0, 1, 0, -1} - for { - nx := gPos[0] + dx[curOrientation] - ny := gPos[1] + dy[curOrientation] - if isValid(grid, nx, ny) { - curPoint := (*grid)[nx][ny] - if !isObstacle(curPoint) { - gPos = [2]int{nx, ny} - if visited[nx][ny][curOrientation] { - return true - } - visited[nx][ny][curOrientation] = true - } else { - curOrientation = turn90(curOrientation) - } - } else { - break - } - } - return false -} - -func solve_part_two(data string) int { - grid := parseInput(data) - var guardPosition [2]int - for i, row := range grid { - for j, ch := range row { - if isGaurd(byte(ch)) { - guardPosition = [2]int{i, j} - } - } - } - n, m := len(grid), len(grid[0]) - ans := 0 - for i := range n { - for j := range m { - if !(i == guardPosition[0] && j == guardPosition[1]) { - flag := grid[i][j] == '.' - replaceCharGrid(&grid, i, j, '#') - if isStuck(&grid, guardPosition) { - ans++ - } - if flag { - replaceCharGrid(&grid, i, j, '.') - } - } - } - } - return ans -} - -func main() { - test := FileRead("../input/day6.test") - prod := FileRead("../input/day6.prod") - fmt.Println("Part_1 test: ", solve_part_one(test)) - fmt.Println("Part_1 prod: ", solve_part_one(prod)) - fmt.Println("Part_2 test: ", solve_part_two(test)) - fmt.Println("Part_2 prod: ", solve_part_two(prod)) -} diff --git a/2024/go/src/day7/main.go b/2024/go/src/day7/main.go deleted file mode 100644 index 413086c..0000000 --- a/2024/go/src/day7/main.go +++ /dev/null @@ -1,190 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strconv" - "strings" -) - -func FileRead(path string) string { - file, err := os.ReadFile(path) - if err != nil { - fmt.Println("Couldn't Read file: ", err) - } - return string(file) - -} - -type Op = string - -const ( - Plus Op = "+" - Mul Op = "*" - Concat Op = "||" -) - -var OpsOne = []Op{Plus, Mul} -var OpsTwo = []Op{Plus, Mul, Concat} - -type Calibration struct { - target int - vals []int -} - -type Expression = []string - -func (c Calibration) String() string { - valsStr := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(c.vals)), ", "), "[]") - return fmt.Sprintf("Calibration(target: %d, vals: [%s])", c.target, valsStr) -} - -func parseInput(data string) []Calibration { - lines := strings.Split(data, "\n") - - var cals []Calibration - - for _, line := range lines { - if len(line) > 0 { - cal := strings.Split(line, ": ") - target, _ := strconv.Atoi(cal[0]) - var vals []int - for _, num := range strings.Split(cal[1], " ") { - val, _ := strconv.Atoi(num) - vals = append(vals, val) - } - calibration := Calibration{ - target: target, - vals: vals, - } - cals = append(cals, calibration) - } - } - - return cals -} - -func generatePossibleExpressions(opsLeft int, expr *Expression, expressions *[]Expression, Ops []string) { - if opsLeft == 0 { - comb := make([]string, len(*expr)) - copy(comb, *expr) - *expressions = append(*expressions, comb) - } else { - for _, op := range Ops { - // choose - *expr = append(*expr, op) - - // explore - generatePossibleExpressions(opsLeft-1, expr, expressions, Ops) - - // unchoose - *expr = (*expr)[:len(*expr)-1] - } - } - -} - -func removeElement(s []int, i int) ([]int, error) { - if i >= len(s) || i < 0 { - return nil, fmt.Errorf("Index is out of range. Index is %d with slice length %d", i, len(s)) - } - return append(s[:i], s[i+1:]...), nil -} - -func removeElementString(s []string, i int) ([]string, error) { - if i >= len(s) || i < 0 { - return nil, fmt.Errorf("Index is out of range. Index is %d with slice length %d", i, len(s)) - } - return append(s[:i], s[i+1:]...), nil -} - -func evalPartOne(vals []int, expression *Expression) int { - for _, op := range *expression { - left := vals[0] - right := vals[1] - if op == Mul { - vals, _ = removeElement(vals, 0) - vals[0] = left * right - } else if op == Plus { - vals, _ = removeElement(vals, 0) - vals[0] = left + right - } - } - - return vals[0] -} -func evalPartTwo(vals []int, expression *Expression) int { - for _, op := range *expression { - left := vals[0] - right := vals[1] - if op == Mul { - vals, _ = removeElement(vals, 0) - vals[0] = left * right - } else if op == Plus { - vals, _ = removeElement(vals, 0) - vals[0] = left + right - } else if op == "||" { - vals, _ = removeElement(vals, 0) - // vals[0], _ = strconv.Atoi(strconv.Itoa(left) + strconv.Itoa(right)) - multiplier := 1 - for temp := right; temp > 0; temp /= 10 { - multiplier *= 10 - } - vals[0] = left*multiplier + right - } - } - - // fmt.Printf("expression: %v\n", (*expression)) - // fmt.Printf("vals: %v\n", vals) - - return vals[0] -} -func solve_part_one(data string) int64 { - calibrations := parseInput(data) - var ans int64 = 0 - for _, calibration := range calibrations { - var expressions []Expression - generatePossibleExpressions((len(calibration.vals) - 1), &[]string{}, &expressions, OpsOne) - for _, expr := range expressions { - copy_vals := make([]int, len(calibration.vals)) - copy(copy_vals, calibration.vals) - if evalPartOne(copy_vals, &expr) == calibration.target { - // fmt.Printf("expr: %v\n", expr) - ans += int64(calibration.target) - break - } - } - // fmt.Printf("expressions: %v\n", expressions) - expressions = []Expression{} - } - return ans -} - -func solve_part_two(data string) int64 { - calibrations := parseInput(data) - var ans int64 = 0 - for _, calibration := range calibrations { - var expressions []Expression - generatePossibleExpressions((len(calibration.vals) - 1), &[]string{}, &expressions, OpsTwo) - for _, expr := range expressions { - copy_vals := make([]int, len(calibration.vals)) - copy(copy_vals, calibration.vals) - if evalPartTwo(copy_vals, &expr) == calibration.target { - // fmt.Printf("expr: %v\n", expr) - ans += int64(calibration.target) - break - } - } - expressions = []Expression{} - } - return ans -} - -func main() { - test := FileRead("../input/day7.test") - prod := FileRead("../input/day7.prod") - fmt.Println("Part_1 test: ", solve_part_one(test)) - fmt.Println("Part_1 prod: ", solve_part_one(prod)) - fmt.Println("Part_2 test: ", solve_part_two(test)) - fmt.Println("Part_2 prod: ", solve_part_two(prod)) -} diff --git a/2024/go/src/day8/main.go b/2024/go/src/day8/main.go deleted file mode 100644 index e801340..0000000 --- a/2024/go/src/day8/main.go +++ /dev/null @@ -1,139 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strings" -) - -func FileRead(path string) string { - file, err := os.ReadFile(path) - if err != nil { - fmt.Println("Couldn't Read file: ", err) - } - return string(file) - -} - -type Grid = [][]rune - -func printGrid(grid [][]rune) { - for _, row := range grid { - for _, cell := range row { - fmt.Print(string(cell)) - } - fmt.Println() - } -} - -func parseInput(data string) Grid { - lines := strings.Split(data, "\n") - - var grid Grid - - for _, line := range lines { - if len(line) > 0 { - runes := []rune(line) - grid = append(grid, runes) - } - } - return grid -} - -func inBounds(x, y, n, m int) bool { - return x >= 0 && x < n && y >= 0 && y < m -} - -type Point = [2]int -type Points = [][2]int - -func getPosMap(grid *Grid) map[rune]Points { - n, m := len(*grid), len((*grid)[0]) - antinodes := make(map[rune]Points) - for i := 0; i < n; i++ { - for j := 0; j < m; j++ { - curPos := Point{i, j} - curRune := (*grid)[i][j] - if curRune != '.' { - antinodes[curRune] = append(antinodes[curRune], curPos) - } - } - } - return antinodes -} - -func isValidAntenna(grid *Grid, i, j int) bool { - n, m := len(*grid), len((*grid)[0]) - if inBounds(i, j, n, m) { - return true - } - return false -} - -func solve_part_one(data string) int { - grid := parseInput(data) - antennas := getPosMap(&grid) - antinodes := make(map[Point]struct{}) - for _, val := range antennas { - for i := 0; i < len(val); i++ { - curPosI := val[i] - for j := i + 1; j < len(val); j++ { - curPosJ := val[j] - diffOne := [2]int{curPosI[0] - curPosJ[0], curPosI[1] - curPosJ[1]} - diffTwo := [2]int{curPosJ[0] - curPosI[0], curPosJ[1] - curPosI[1]} - firstAntennaPos := [2]int{curPosI[0] + diffOne[0], curPosI[1] + diffOne[1]} - secondAntennaPos := [2]int{curPosJ[0] + diffTwo[0], curPosJ[1] + diffTwo[1]} - if isValidAntenna(&grid, firstAntennaPos[0], firstAntennaPos[1]) { - antinodes[firstAntennaPos] = struct{}{} - } - if isValidAntenna(&grid, secondAntennaPos[0], secondAntennaPos[1]) { - antinodes[secondAntennaPos] = struct{}{} - } - } - } - } - return len(antinodes) -} - -func solve_part_two(data string) int { - grid := parseInput(data) - antennas := getPosMap(&grid) - cnt := 0 - for _, val := range antennas { - for i := 0; i < len(val); i++ { - curPosI := val[i] - for j := i + 1; j < len(val); j++ { - curPosJ := val[j] - diffOne := [2]int{curPosI[0] - curPosJ[0], curPosI[1] - curPosJ[1]} - diffTwo := [2]int{curPosJ[0] - curPosI[0], curPosJ[1] - curPosI[1]} - firstAntennaPos := [2]int{curPosI[0] + diffOne[0], curPosI[1] + diffOne[1]} - secondAntennaPos := [2]int{curPosJ[0] + diffTwo[0], curPosJ[1] + diffTwo[1]} - for isValidAntenna(&grid, firstAntennaPos[0], firstAntennaPos[1]) { - grid[firstAntennaPos[0]][firstAntennaPos[1]] = '#' - firstAntennaPos = [2]int{firstAntennaPos[0] + diffOne[0], firstAntennaPos[1] + diffOne[1]} - } - for isValidAntenna(&grid, secondAntennaPos[0], secondAntennaPos[1]) { - grid[secondAntennaPos[0]][secondAntennaPos[1]] = '#' - secondAntennaPos = [2]int{secondAntennaPos[0] + diffTwo[0], secondAntennaPos[1] + diffTwo[1]} - } - } - } - } - for i := 0; i < len(grid); i++ { - for j := 0; j < len(grid); j++ { - if grid[i][j] != '.' { - cnt++ - } - } - } - return cnt -} - -func main() { - test := FileRead("../input/day8.test") - prod := FileRead("../input/day8.prod") - fmt.Println("Part_1 test: ", solve_part_one(test)) - fmt.Println("Part_1 prod: ", solve_part_one(prod)) - fmt.Println("Part_2 test: ", solve_part_two(test)) - fmt.Println("Part_2 prod: ", solve_part_two(prod)) -} diff --git a/2024/go/src/day9/main.go b/2024/go/src/day9/main.go deleted file mode 100644 index 0a9b51b..0000000 --- a/2024/go/src/day9/main.go +++ /dev/null @@ -1,169 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strconv" -) - -func InsertAt(arr *[]FileBlock, index int, value FileBlock) error { - if index < 0 || index > len(*arr) { - return fmt.Errorf("index out of range") - } - *arr = append((*arr)[:index], append([]FileBlock{value}, (*arr)[index:]...)...) - return nil -} - -func RemoveAt(arr *[]FileBlock, index int) (FileBlock, error) { - if index < 0 || index >= len(*arr) { - return FileBlock{}, fmt.Errorf("index out of range") - } - ele := (*arr)[index] - *arr = append((*arr)[:index], (*arr)[index+1:]...) - return ele, nil -} - -func FileRead(path string) string { - file, err := os.ReadFile(path) - if err != nil { - fmt.Println("Couldn't Read file: ", err) - } - return string(file) - -} - -func parseInput(data string) string { - return data -} - -func genereateBlockMap(diskMap string) []string { - var blockMap []string - id := 0 - for i, ch := range diskMap { - rep, _ := strconv.Atoi(string(ch)) - if i%2 == 0 { - for i := 0; i < rep; i++ { - blockMap = append(blockMap, strconv.Itoa(id)) - } - id += 1 - } else { - for i := 0; i < rep; i++ { - blockMap = append(blockMap, ".") - } - } - } - return blockMap -} - -func genereateFileBlocks(diskMap string) []FileBlock { - var fileBlocks []FileBlock - id := 0 - for i, ch := range diskMap { - rep, _ := strconv.Atoi(string(ch)) - if i%2 == 0 { - block := FileBlock{id: id, space: rep} - fileBlocks = append(fileBlocks, block) - id += 1 - } else { - block := FileBlock{id: -1, space: rep} - if rep > 0 { - fileBlocks = append(fileBlocks, block) - } - } - } - return fileBlocks -} - -func moveBlocks(blockMap []string) { - i := 0 - j := len(blockMap) - 1 - for i < j { - if blockMap[i] == "." { - if blockMap[j] != "." { - blockMap[i], blockMap[j] = blockMap[j], blockMap[i] - i++ - } - j-- - } else { - i++ - } - } -} - -type FileBlock struct { - id int // id -1 will be the free block '.' - space int -} - -func moveBlocksPartTwo(fileBlocks []FileBlock) []string { - for i := 0; i < len(fileBlocks); i++ { - if fileBlocks[i].id != -1 { - continue - } - for j := len(fileBlocks) - 1; j >= i; j-- { - if fileBlocks[j].id == -1 { - continue - } - if fileBlocks[i].space == fileBlocks[j].space { - fileBlocks[i], fileBlocks[j] = fileBlocks[j], fileBlocks[i] - i++ - j-- - break - } else if fileBlocks[i].space > fileBlocks[j].space { - _ = InsertAt(&fileBlocks, i+1, FileBlock{id: -1, space: fileBlocks[i].space - fileBlocks[j].space}) - spaceJ := fileBlocks[j+1].space - fileBlocks[i], fileBlocks[j+1] = fileBlocks[j+1], fileBlocks[i] - fileBlocks[j+1].id = -1 - fileBlocks[j+1].space = spaceJ - break - } - } - } - var blocks []string - for _, block := range fileBlocks { - if block.id == -1 { - for i := 0; i < block.space; i++ { - blocks = append(blocks, ".") - } - } else { - for i := 0; i < block.space; i++ { - blocks = append(blocks, strconv.Itoa(block.id)) - } - } - } - return blocks -} - -func checkSum(blockMap []string) int64 { - var sum int64 = 0 - for i, ch := range blockMap { - if ch == "." { - continue - } - id, _ := strconv.Atoi(ch) - sum += int64(id) * int64(i) - } - return sum -} -func solve_part_one(data string) int64 { - diskMap := parseInput(data) - blockMap := genereateBlockMap(diskMap) - moveBlocks(blockMap) - return checkSum(blockMap) -} - -func solve_part_two(data string) int64