diff --git a/2025/01/kylepritchard.v b/2025/01/kylepritchard.v new file mode 100644 index 0000000..2d57c3f --- /dev/null +++ b/2025/01/kylepritchard.v @@ -0,0 +1,59 @@ +module main + +import os +import strconv + +fn main() { + codes := os.read_file('rotations.input') or { panic('Failed to read file') } + + mut start := 50 + mut count := 0 + mut count2 := 0 + + for line in codes.split_into_lines() { + if line.len == 0 { + continue + } + + if line[0] == `L` { + move_str := line[1..].trim_space() + mut move := strconv.atoi(move_str) or { 0 } + + for move > 0 { + start-- + if start == 0 { + count2++ + } + if start == -1 { + start = 99 + } + move-- + } + + if start == 0 { + count++ + } + } else { + move_str := line[1..].trim_space() + mut move := strconv.atoi(move_str) or { 0 } + + for move > 0 { + start++ + if start == 100 { + start = 0 + } + if start == 0 { + count2++ + } + move-- + } + + if start == 0 { + count++ + } + } + } + + println('Part 1: ${count}') + println('Part 2: ${count2}') +} diff --git a/2025/02/kylepritchard.v b/2025/02/kylepritchard.v new file mode 100644 index 0000000..4b18041 --- /dev/null +++ b/2025/02/kylepritchard.v @@ -0,0 +1,85 @@ +module main + +import os +import strconv + +fn has_exact_two_halves(s string) bool { + if s.len % 2 != 0 { + return false + } + half := s.len / 2 + return s[0..half] == s[half..] +} + +fn has_repeating_pattern(s string) bool { + for pattern_len in 1 .. s.len / 2 + 1 { + if s.len % pattern_len != 0 { + continue + } + + pattern := s[0..pattern_len] + mut matches := true + + repetitions := s.len / pattern_len + for rep in 1 .. repetitions { + start := rep * pattern_len + end := start + pattern_len + if s[start..end] != pattern { + matches = false + break + } + } + + if matches { + return true + } + } + return false +} + +fn main() { + content := os.read_file('ids.input') or { panic('Failed to read file: ${err}') } + + ids := content.split(',') + + mut sum1 := i64(0) + mut sum2 := i64(0) + + for id in ids { + if id.len == 0 { + continue + } + + range_parts := id.split('-') + + start_str := range_parts[0].trim_space() + end_str := range_parts[1].trim_space() + + start := strconv.parse_int(start_str, 10, 64) or { + eprintln('Start number isn\'t valid: "${id}"') + continue + } + + end := strconv.parse_int(end_str, 10, 64) or { + eprintln('End number isn\'t valid: "${id}"') + continue + } + + for num in start .. end + 1 { + num_str := num.str() + + // Part 1 + if has_exact_two_halves(num_str) { + sum1 += num + } + + // Part 2 + if has_repeating_pattern(num_str) { + sum2 += num + } + } + } + + println('Part 1: ${sum1}') + println('Part 2: ${sum2}') +} diff --git a/2025/03/kylepritchard.v b/2025/03/kylepritchard.v new file mode 100644 index 0000000..ee74310 --- /dev/null +++ b/2025/03/kylepritchard.v @@ -0,0 +1,71 @@ +module main + +import os +import strconv + +fn max_sequence(s string, k int) string { + to_remove := s.len - k + mut remove_left := to_remove + + mut stack := []u8{len: 0, cap: s.len} + + for i in 0 .. s.len { + c := s[i] + for stack.len > 0 && remove_left > 0 && stack[stack.len - 1] < c { + stack.delete_last() + remove_left-- + } + stack << c + } + + if remove_left > 0 { + stack = stack[..stack.len - remove_left].clone() + } + + if stack.len > k { + stack = stack[..k].clone() + } + + return stack.bytestr() +} + +fn main() { + content := os.read_file('banks.input') or { panic('Failed to read file: ${err}') } + lines := content.split_into_lines() + + // Part 1 + mut total_joltage := i64(0) + for line in lines { + if line.len == 0 { + continue + } + + seq := max_sequence(line, 2) + if seq.len == 0 { + continue + } + + num := strconv.parse_int(seq, 10, 64) or { 0 } + total_joltage += num + } + + println('Part 1: ${total_joltage}') + + // Part 2 + total_joltage = 0 + for line in lines { + if line.len == 0 { + continue + } + + seq := max_sequence(line, 12) + if seq.len == 0 { + continue + } + + num := strconv.parse_int(seq, 10, 64) or { 0 } + total_joltage += num + } + + println('Part 2: ${total_joltage}') +} diff --git a/2025/04/kylepritchard.v b/2025/04/kylepritchard.v new file mode 100644 index 0000000..adfad0d --- /dev/null +++ b/2025/04/kylepritchard.v @@ -0,0 +1,159 @@ +module main + +import os + +struct Pos { + row int + col int +} + +struct Offset { + dr int + dc int +} + +fn count_adjacent(grid []u8, rows int, cols int, i int, j int, neighbors []Offset) int { + mut count := 0 + + for offset in neighbors { + ni := i + offset.dr + nj := j + offset.dc + + if ni >= 0 && nj >= 0 && ni < rows && nj < cols { // inside grid + nidx := ni * cols + nj + if grid[nidx] == `@` { + count++ + if count >= 4 { + break + } + } + } + } + return count +} + +fn main() { + // Read input file + content := os.read_file('department.input') or { panic('Failed to read file: ${err}') } + lines := content.split_into_lines() + + mut grid_lines := []string{} + for line in lines { + if line.len > 0 { + grid_lines << line + } + } + + rows := grid_lines.len + cols := grid_lines[0].len + + mut grid1 := []u8{len: rows * cols, cap: rows * cols} + mut grid2 := []u8{len: rows * cols, cap: rows * cols} + + for i in 0 .. rows { + line := grid_lines[i] + row_start := i * cols + for j in 0 .. cols { + grid1[row_start + j] = line[j] + grid2[row_start + j] = line[j] + } + } + + neighbors := [ + Offset{-1, -1}, // diagonal above left + Offset{-1, 0}, // above + Offset{-1, 1}, // diagional above right + Offset{0, -1}, // left + Offset{0, 1}, // right + Offset{1, -1}, // diagonal below left + Offset{1, 0}, // below + Offset{1, 1}, // diagonal below right + ] + + // Part 1 + mut part1_count := 0 + for i in 0 .. rows { + row_start := i * cols + for j in 0 .. cols { + idx := row_start + j + if grid1[idx] == `@` { + adj_count := count_adjacent(grid1, rows, cols, i, j, neighbors) + if adj_count < 4 { + part1_count++ + } + } + } + } + + println('Part 1: ${part1_count}') + + // Part 2 + mut total_removed := 0 + mut current_grid := grid2.clone() + mut changed := true + + mut to_check := []Pos{cap: rows * cols} + + for i in 0 .. rows { + for j in 0 .. cols { + to_check << Pos{i, j} + } + } + + for changed { + changed = false + mut to_remove := []Pos{cap: to_check.len} + mut next_to_check := []Pos{cap: rows * cols} + mut modified := []bool{len: rows * cols, init: false} + + for pos in to_check { + i := pos.row + j := pos.col + idx := i * cols + j + + if current_grid[idx] != `@` { + continue + } + + adj_count := count_adjacent(current_grid, rows, cols, i, j, neighbors) + if adj_count < 4 { + to_remove << pos + } + } + + // Remove rolls + if to_remove.len > 0 { + changed = true + total_removed += to_remove.len + + // Mark positions as removed and track their neighbors + for pos in to_remove { + i := pos.row + j := pos.col + idx := i * cols + j + current_grid[idx] = `.` + modified[idx] = true + + // Add neighbors to next iteration's check list + for offset in neighbors { + ni := i + offset.dr + nj := j + offset.dc + if ni >= 0 && nj >= 0 && ni < rows && nj < cols { + nidx := ni * cols + nj + if !modified[nidx] { + modified[nidx] = true + next_to_check << Pos{ni, nj} + } + } + } + } + + to_check = next_to_check.clone() + } else { + // No more to remove + break + } + } + + println('Part 2: ${total_removed}') +} diff --git a/known/2025/01/kylepritchard.out b/known/2025/01/kylepritchard.out new file mode 100644 index 0000000..9803ffb --- /dev/null +++ b/known/2025/01/kylepritchard.out @@ -0,0 +1,2 @@ +Part 1: 3 +Part 2: 6 diff --git a/known/2025/02/kylepritchard.out b/known/2025/02/kylepritchard.out new file mode 100644 index 0000000..234165a --- /dev/null +++ b/known/2025/02/kylepritchard.out @@ -0,0 +1,2 @@ +Part 1: 1227775554 +Part 2: 4174379265 diff --git a/known/2025/03/kylepritchard.out b/known/2025/03/kylepritchard.out new file mode 100644 index 0000000..8a9b064 --- /dev/null +++ b/known/2025/03/kylepritchard.out @@ -0,0 +1,2 @@ +Part 1: 357 +Part 2: 3121910778619 diff --git a/known/2025/04/kylepritchard.out b/known/2025/04/kylepritchard.out new file mode 100644 index 0000000..e150868 --- /dev/null +++ b/known/2025/04/kylepritchard.out @@ -0,0 +1,2 @@ +Part 1: 13 +Part 2: 43