Skip to content

Commit

Permalink
DayTwenty
Browse files Browse the repository at this point in the history
  • Loading branch information
ayoubzulfiqar committed Dec 20, 2024
1 parent 851363d commit b70292f
Show file tree
Hide file tree
Showing 4 changed files with 318 additions and 0 deletions.
103 changes: 103 additions & 0 deletions 2024/Go/Day20/part_1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package main

import (
"bufio"
"fmt"
"os"
)

func picoSecondsCheats() {
// Read the input from the file
file, err := os.Open("input.txt")
if err != nil {
fmt.Println("Error reading file:", err)
return
}
defer file.Close()

// Read all lines from the file into grid
var grid []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
grid = append(grid, scanner.Text())
}

if err := scanner.Err(); err != nil {
fmt.Println("Error reading lines:", err)
return
}

// Find start and end positions
start := findPosition(grid, 'S')
end := findPosition(grid, 'E')

// Track visited positions and their step counts
track := make(map[[2]int]int)
track[start] = 0
cur := start
curStep := 0

// Perform BFS-like traversal
for cur != end {
curStep++
i, j := cur[0], cur[1]
found := false
for _, dir := range [][2]int{{-1, 0}, {0, -1}, {0, 1}, {1, 0}} {
newI, newJ := i+dir[0], j+dir[1]
if isValid(newI, newJ, grid) && !isInTrack(track, [2]int{newI, newJ}) && isValidChar(grid[newI][newJ]) {
cur = [2]int{newI, newJ}
track[cur] = curStep
found = true
break
}
}
if !found {
break
}
}

// Count pairs that satisfy the condition
count := 0
for p1 := range track {
for _, dir := range [][2]int{{-1, 0}, {0, -1}, {0, 1}, {1, 0}} {
newI, newJ := p1[0]+dir[0], p1[1]+dir[1]
if isInTrack(track, [2]int{newI, newJ}) {
continue
}
otherPos := [2]int{newI + dir[0], newJ + dir[1]}
if isInTrack(track, otherPos) && track[otherPos]-track[p1] >= 102 {
count++
}
}
}

fmt.Println(count)
}

// Helper function to find the position of a character in the grid
func findPosition(grid []string, char rune) [2]int {
for i, line := range grid {
for j, cell := range line {
if cell == char {
return [2]int{i, j}
}
}
}
return [2]int{-1, -1}
}

// Check if the position is valid within the grid
func isValid(i, j int, grid []string) bool {
return i >= 0 && i < len(grid) && j >= 0 && j < len(grid[i])
}

// Check if a character is 'S', 'E' or '.'
func isValidChar(c byte) bool {
return c == 'S' || c == 'E' || c == '.'
}

// Check if a position is already in the track map
func isInTrack(track map[[2]int]int, pos [2]int) bool {
_, exists := track[pos]
return exists
}
121 changes: 121 additions & 0 deletions 2024/Go/Day20/part_2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package main

import (
"bufio"
"fmt"
"math"
"os"
)

func saveHundredPicoSecondCheats() {
// Read the input from the file
file, err := os.Open("input.txt")
if err != nil {
fmt.Println("Error reading file:", err)
return
}
defer file.Close()

// Read the grid into a 2D slice
var grid [][]rune
scanner := bufio.NewScanner(file)
for scanner.Scan() {
grid = append(grid, []rune(scanner.Text()))
}

if err := scanner.Err(); err != nil {
fmt.Println("Error reading lines:", err)
return
}

// Find start and end positions
start := reallyFindPosition(grid, 'S')
end := reallyFindPosition(grid, 'E')

// Track visited positions and their step counts
track := make(map[[2]int]int)
track[start] = 0
cur := start
curStep := 0

// Perform BFS-like traversal
for cur != end {
curStep++
i, j := cur[0], cur[1]
found := false
for _, dir := range [][2]int{{-1, 0}, {0, -1}, {0, 1}, {1, 0}} {
newI, newJ := i+dir[0], j+dir[1]
if isReallyValid(newI, newJ, grid) && !isReallyInTrack(track, [2]int{newI, newJ}) && isReallyValidChar(grid[newI][newJ]) {
cur = [2]int{newI, newJ}
track[cur] = curStep
found = true
break
}
}
if !found {
break
}
}

// Count valid pairs
count := 0
for coords := range track {
potentials := cheatEndpoints(coords, track)
for otherCoords := range potentials {
if track[otherCoords]-track[coords]-manhattanDistance(coords, otherCoords) >= 100 {
count++
}
}
}

fmt.Println(count)
}

// Helper function to find the position of a character in the grid
func reallyFindPosition(grid [][]rune, char rune) [2]int {
for i, line := range grid {
for j, cell := range line {
if cell == char {
return [2]int{i, j}
}
}
}
return [2]int{-1, -1}
}

// Check if the position is valid within the grid
func isReallyValid(i, j int, grid [][]rune) bool {
return i >= 0 && i < len(grid) && j >= 0 && j < len(grid[i])
}

// Check if a character is 'S', 'E' or '.'
func isReallyValidChar(c rune) bool {
return c == 'S' || c == 'E' || c == '.'
}

// Check if a position is already in the track map
func isReallyInTrack(track map[[2]int]int, pos [2]int) bool {
_, exists := track[pos]
return exists
}

// Function to find possible endpoints in the neighborhood
func cheatEndpoints(coords [2]int, track map[[2]int]int) map[[2]int]struct{} {
i, j := coords[0], coords[1]
output := make(map[[2]int]struct{})
for di := -20; di <= 20; di++ {
djMax := 20 - int(math.Abs(float64(di)))
for dj := -djMax; dj <= djMax; dj++ {
newPos := [2]int{i + di, j + dj}
if _, exists := track[newPos]; exists {
output[newPos] = struct{}{}
}
}
}
return output
}

// Manhattan distance between two coordinates
func manhattanDistance(coord1, coord2 [2]int) int {
return int(math.Abs(float64(coord1[0]-coord2[0]))) + int(math.Abs(float64(coord1[1]-coord2[1])))
}
46 changes: 46 additions & 0 deletions 2024/Python/Day20/part_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from collections import deque
from itertools import combinations


def parseInput():
with open("input.txt", "r") as file:
content = file.read()
grid = [list(line) for line in content.strip().split("\n")]
start, end = (0, 0), (0, 0)
for r, row in enumerate(grid):
for c, cell in enumerate(row):
if cell == "S":
start = (r, c)
elif cell == "E":
end = (r, c)
return grid, start, end


def bfs(grid, start, end):
queue = deque([(start[0], start[1], 0)])
dists = {}
while queue:
r, c, n = queue.popleft()
if (r, c) in dists:
continue
dists[(r, c)] = n
if (r, c) == end:
continue
for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
rr, cc = r + dr, c + dc
if 0 <= rr < len(grid) and 0 <= cc < len(grid[0]) and grid[rr][cc] != "#":
queue.append((rr, cc, n + 1))
return dists


# Part -1
def picoSecondsCheats() -> int:
grid, start, end = parseInput()
dists = bfs(grid, start, end)
p1 = 0
for ((r1, c1), n1), ((r2, c2), n2) in combinations(dists.items(), 2):
d = abs(r1 - r2) + abs(c1 - c2)
if d <= 2 and abs(n2 - n1) >= d + 100:
p1 += 1
print(p1)
return p1
48 changes: 48 additions & 0 deletions 2024/Python/Day20/part_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from collections import deque
from itertools import combinations



def parseInput():
with open("input.txt", "r") as file:
content = file.read()
grid = [list(line) for line in content.strip().split("\n")]
start, end = (0, 0), (0, 0)
for r, row in enumerate(grid):
for c, cell in enumerate(row):
if cell == "S":
start = (r, c)
elif cell == "E":
end = (r, c)
return grid, start, end


def bfs(grid, start, end):
queue = deque([(start[0], start[1], 0)])
dists = {}
while queue:
r, c, n = queue.popleft()
if (r, c) in dists:
continue
dists[(r, c)] = n
if (r, c) == end:
continue
for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
rr, cc = r + dr, c + dc
if 0 <= rr < len(grid) and 0 <= cc < len(grid[0]) and grid[rr][cc] != "#":
queue.append((rr, cc, n + 1))
return dists



# Part -2
def saveHundredPicoSecondCheats() -> int:
grid, start, end = parseInput()
dists = bfs(grid, start, end)
p2 = 0
for ((r1, c1), n1), ((r2, c2), n2) in combinations(dists.items(), 2):
d = abs(r1 - r2) + abs(c1 - c2)
if d <= 20 and abs(n2 - n1) >= d + 100:
p2 += 1
print(p2)
return p2

0 comments on commit b70292f

Please sign in to comment.