Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file removed 2025/09/.gitkeep
Empty file.
153 changes: 153 additions & 0 deletions 2025/09/dy-tea.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import os
import math

fn react_area(x1 i64, y1 i64, x2 i64, y2 i64) u64 {
dx := math.abs(x1 - x2) + 1
dy := math.abs(y1 - y2) + 1
return u64(dx) * u64(dy)
}

@[flag]
enum Direction {
x_pos
x_neg
y_pos
y_neg
}

fn Direction.new(x1 u32, y1 u32, x2 u32, y2 u32) Direction {
return match true {
x1 == x2 && y1 < y2 { .y_pos }
x1 == x2 && y1 > y2 { .y_neg }
y1 == y2 && x1 < x2 { .x_pos }
else { .x_neg }
}
}

struct DirectedPoint {
x u32
y u32
e u32
d Direction
}

fn DirectedPoint.new(x1 u32, y1 u32, x2 u32, y2 u32) DirectedPoint {
dx := if x2 > x1 { x2 - x1 } else { x1 - x2 }
dy := if y2 > y1 { y2 - y1 } else { y1 - y2 }
return DirectedPoint{
x: x1
y: y1
e: math.max(dx, dy)
d: Direction.new(x1, y1, x2, y2)
}
}

fn (dp DirectedPoint) extent_overlaps(x1 u32, y1 u32, x2 u32, y2 u32) bool {
rx_min := math.min(x1, x2)
rx_max := math.max(x1, x2)
ry_min := math.min(y1, y2)
ry_max := math.max(y1, y2)

ro_min, ro_max := match dp.d {
.x_neg { dp.x - dp.e, dp.x }
.x_pos { dp.x, dp.x + dp.e }
.y_neg { dp.y - dp.e, dp.y }
.y_pos { dp.y, dp.y + dp.e }
else { u32(0), u32(0) }
}

return match dp.d {
.x_neg, .x_pos {
rx_min < ro_max && ro_min < rx_max
}
.y_neg, .y_pos {
ry_min < ro_max && ro_min < ry_max
}
else {
false
}
}
}

fn is_red_inside(points []DirectedPoint, x1 u32, y1 u32, x2 u32, y2 u32, xs u32, xe u32, ys u32, ye u32) bool {
return points.filter(fn [x1, x2, y1, y2] (p DirectedPoint) bool {
return p.x != x1 && p.x != x2 && p.y != y1 && p.y != y2
}).any(fn [xs, xe, ys, ye] (p DirectedPoint) bool {
return xs <= p.x && p.x <= xe && ys <= p.y && p.y <= ye
})
}

fn valid_area(points []DirectedPoint, x1 u32, y1 u32, x2 u32, y2 u32) ?u64 {
minx := math.min(x1, x2)
maxx := math.max(x1, x2)
miny := math.min(y1, y2)
maxy := math.max(y1, y2)

if is_red_inside(points, x1, y1, x2, y2, minx, maxx, miny, maxy) {
return none
}

region_x_min := minx + 1
region_x_max := maxx
region_y_min := miny + 1
region_y_max := maxy

if points.filter(fn [region_x_min, region_x_max, region_y_min, region_y_max] (p DirectedPoint) bool {
return (region_x_min <= p.x && p.x < region_x_max && (p.d == .y_pos || p.d == .y_neg))
|| (region_y_min <= p.y && p.y < region_y_max && (p.d == .x_pos || p.d == .x_neg))
}).any(fn [x1, y1, x2, y2] (p DirectedPoint) bool {
return p.extent_overlaps(x1, y1, x2, y2)
})
{
return none
}

dx := if x2 > x1 { x2 - x1 } else { x1 - x2 }
dy := if y2 > y1 { y2 - y1 } else { y1 - y2 }
return u64(dx + 1) * u64(dy + 1)
}

lines := os.read_lines('tiles.input')!
coords := lines.map(fn (line string) []i64 {
x, y := line.split_once(',') or { panic('invalid input') }
return [x.i64(), y.i64()]
})

// part 1
mut max_area := u64(0)
for i := 0; i < coords.len - 1; i++ {
x, y := coords[i][0], coords[i][1]
for j := i + 1; j < coords.len; j++ {
xx, yy := coords[j][0], coords[j][1]
area := react_area(x, y, xx, yy)
if area > max_area {
max_area = area
}
}
}
println(max_area)

// part 2
red_tiles := coords.map(fn (c []i64) []u32 {
return [u32(c[0]), u32(c[1])]
})
mut tiles_with_directions := []DirectedPoint{cap: red_tiles.len}
for i := 0; i < red_tiles.len; i++ {
next_i := (i + 1) % red_tiles.len
p1 := red_tiles[i]
p2 := red_tiles[next_i]
tiles_with_directions << DirectedPoint.new(p1[0], p1[1], p2[0], p2[1])
}
max_area = 0
for i := 0; i < red_tiles.len - 1; i++ {
p1 := red_tiles[i]
for j := i + 1; j < red_tiles.len; j++ {
p2 := red_tiles[j]
if area := valid_area(tiles_with_directions, p1[0], p1[1], p2[0], p2[1]) {
if area > max_area {
max_area = area
}
}
}
}
println(max_area)
8 changes: 8 additions & 0 deletions 2025/09/tiles.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
7,1
11,1
11,7
9,7
9,5
2,5
2,3
7,3
Empty file removed 2025/10/.gitkeep
Empty file.
211 changes: 211 additions & 0 deletions 2025/10/dy-tea.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import os
import math

struct Machine {
lights []bool
buttons [][]u32
joltages []u32
}

fn generate_combos(mut result [][]int, current []int, start int, n int, k int) {
if current.len == k {
result << current.clone()
return
}
for i in start .. n {
mut next := current.clone()
next << i
generate_combos(mut result, next, i + 1, n, k)
}
}

fn get_combinations(n int, k int) [][]int {
mut result := [][]int{}
if k == 0 {
return [[]]
}
if k > n {
return result
}
generate_combos(mut result, []int{}, 0, n, k)
return result
}

@[direct_array_access]
fn (m Machine) min_light_presses() int {
button_len := m.buttons.len
lights_len := m.lights.len
for press_count in 1 .. button_len {
combinations := get_combinations(button_len, press_count)
for combo in combinations {
mut test := []bool{len: lights_len}
for button_idx in combo {
for light_idx in m.buttons[button_idx] {
test[light_idx] = !test[light_idx]
}
}
if test == m.lights {
return press_count
}
}
}
return button_len
}

@[direct_array_access]
fn (m Machine) min_joltage_presses() int {
n := m.buttons.len
mm := m.joltages.len

mut matrix := [][]f64{len: mm, init: []f64{len: n + 1}}
for eq in 0 .. mm {
for var in 0 .. n {
mut affects := false
for jolt_idx in m.buttons[var] {
if int(jolt_idx) == eq {
affects = true
break
}
}
matrix[eq][var] = if affects { 1.0 } else { 0.0 }
}
matrix[eq][n] = f64(m.joltages[eq])
}

eps := 1e-9
mut row := 0
mut pivot_col := []int{len: n, init: -1}

for col in 0 .. n {
if row >= mm {
break
}

mut sel := row
for i in row .. mm {
if math.abs(matrix[i][col]) > math.abs(matrix[sel][col]) {
sel = i
}
}

if math.abs(matrix[sel][col]) < eps {
continue
}

matrix[sel], matrix[row] = matrix[row], matrix[sel]

div := matrix[row][col]
for j in col .. n + 1 {
matrix[row][j] /= div
}

for i in 0 .. mm {
if i != row {
f := matrix[i][col]
for j in col .. n + 1 {
matrix[i][j] -= f * matrix[row][j]
}
}
}

pivot_col[col] = row
row++
}

mut free_vars := []int{}
for j in 0 .. n {
if pivot_col[j] == -1 {
free_vars << j
}
}
fc := free_vars.len

mut base := []f64{len: n}
mut coeff := [][]f64{len: n, init: []f64{len: fc}}
for var in 0 .. n {
if pivot_col[var] == -1 {
for k in 0 .. fc {
if free_vars[k] == var {
coeff[var][k] = 1.0
}
}
} else {
r := pivot_col[var]
base[var] = matrix[r][n]
for k in 0 .. fc {
coeff[var][k] = -matrix[r][free_vars[k]]
}
}
}

if fc == 0 {
mut sum := i64(0)
for var in 0 .. n {
xi := i64(base[var] + 0.5)
sum += xi
}
return int(sum)
}

max_val := 200
mut best_sum := math.maxof[i64]()
mut t := []int{len: fc}

for {
mut ok := true
mut sum := i64(0)
for var in 0 .. n {
mut xv := base[var]
for k in 0 .. fc {
xv += coeff[var][k] * f64(t[k])
}
xi := i64(xv + 0.5)
if math.abs(xv - f64(xi)) > 1e-9 || xi < 0 {
ok = false
break
}
sum += xi
}
if ok && sum < best_sum {
best_sum = sum
}
mut idx := 0
for idx < fc {
if t[idx] < max_val {
t[idx]++
break
}
t[idx] = 0
idx++
}
if idx == fc {
break
}
}
return int(best_sum)
}

lines := os.read_lines('manual.input')!
machines := lines.map(fn (line string) Machine {
l, rest := line.split_once(' ') or { panic('Invalid input') }
lights := l[1..l.len - 1].runes().map(|r| r == `#`)
b, r := rest.rsplit_once('{') or { panic('Invalid input') }
bb := b.replace(' ', '')
buttons := bb[1..bb.len - 1].split(')(').map(|s| s.split(',').map(|d| d.u32()))
joltages := r[..r.len - 1].split(',').map(|d| d.u32())
return Machine{lights, buttons, joltages}
})

// part 1
mut sum := 0
for m in machines {
sum += m.min_light_presses()
}
println(sum)

// part 2
sum = 0
for m in machines {
sum += m.min_joltage_presses()
}
println(sum)
3 changes: 3 additions & 0 deletions 2025/10/manual.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}
Empty file removed 2025/11/.gitkeep
Empty file.
10 changes: 10 additions & 0 deletions 2025/11/connections_part1.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
aaa: you hhh
you: bbb ccc
bbb: ddd eee
ccc: ddd eee fff
ddd: ggg
eee: out
fff: out
ggg: out
hhh: ccc fff iii
iii: out
Loading