advent of code 2025 in ts and nix
1{
2 description = "Advent of Code 2025 Solutions";
3
4 inputs = {
5 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
6 flake-utils.url = "github:numtide/flake-utils";
7 };
8
9 outputs = { self, nixpkgs, flake-utils }:
10 flake-utils.lib.eachDefaultSystem (system:
11 let
12 pkgs = nixpkgs.legacyPackages.${system};
13 gum = pkgs.gum;
14
15 # Get list of available days
16 getDays = ''
17 days=()
18 for dir in ts/* nix/*; do
19 if [ -d "$dir" ]; then
20 day=$(basename "$dir")
21 if [[ ! " ''${days[@]} " =~ " ''${day} " ]]; then
22 days+=("$day")
23 fi
24 fi
25 done
26 echo "''${days[@]}" | tr ' ' '\n' | sort
27 '';
28
29 # Run a specific day's solution
30 runDay = day: lang: ''
31 if [ "$lang" = "ts" ] && [ -f "ts/${day}/index.ts" ]; then
32 ${gum}/bin/gum style --border rounded --border-foreground 212 --padding "0 1" --margin "1 0" "Day ${day} (TypeScript)"
33 (cd ts/${day} && ${pkgs.bun}/bin/bun run index.ts)
34 elif [ "$lang" = "nix" ] && [ -f "nix/${day}/solution.nix" ]; then
35 ${gum}/bin/gum style --border rounded --border-foreground 212 --padding "0 1" --margin "1 0" "Day ${day} (Nix)"
36 result=$(${pkgs.nix}/bin/nix-instantiate --eval --strict --json nix/${day}/solution.nix)
37 part1=$(echo "$result" | ${pkgs.jq}/bin/jq -r '.part1')
38 part2=$(echo "$result" | ${pkgs.jq}/bin/jq -r '.part2')
39 echo "part 1: $part1"
40 echo "part 2: $part2"
41 fi
42 '';
43
44 # Interactive runner with gum
45 runner = pkgs.writeShellScriptBin "aoc" ''
46 set -e
47
48 ${gum}/bin/gum style \
49 --border double \
50 --border-foreground 212 \
51 --padding "1 2" \
52 --margin "1 0" \
53 "$(${gum}/bin/gum style --foreground 212 '🎄 Advent of Code 2025 🎄')"
54
55 # Choose action
56 action=$(${gum}/bin/gum choose "Run specific day" "Run all solutions" "Exit")
57
58 case "$action" in
59 "Run specific day")
60 # Get available days
61 days=$(${getDays})
62
63 if [ -z "$days" ]; then
64 ${gum}/bin/gum style --foreground 196 "No solutions found!"
65 exit 1
66 fi
67
68 day=$(echo "$days" | ${gum}/bin/gum choose)
69
70 # Check what languages are available for this day
71 langs=()
72 [ -f "ts/$day/index.ts" ] && langs+=("TypeScript")
73 [ -f "nix/$day/solution.nix" ] && langs+=("Nix")
74 langs+=("Both")
75
76 lang=$(printf '%s\n' "''${langs[@]}" | ${gum}/bin/gum choose)
77
78 echo ""
79 case "$lang" in
80 "TypeScript")
81 if [ -f "ts/$day/index.ts" ]; then
82 ${gum}/bin/gum style --border rounded --border-foreground 212 --padding "0 1" "Day $day"
83 echo ""
84 ${gum}/bin/gum style --foreground 212 "TypeScript:"
85 (cd ts/$day && ${pkgs.bun}/bin/bun run index.ts)
86 fi
87 ;;
88 "Nix")
89 if [ -f "nix/$day/solution.nix" ]; then
90 ${gum}/bin/gum style --border rounded --border-foreground 212 --padding "0 1" "Day $day"
91 echo ""
92 ${gum}/bin/gum style --foreground 212 "Nix:"
93 result=$(${pkgs.nix}/bin/nix-instantiate --eval --strict --json nix/$day/solution.nix)
94 echo "$result" | ${pkgs.jq}/bin/jq -r 'to_entries | .[] | "\(.key): \(.value)"'
95 fi
96 ;;
97 "Both")
98 ${gum}/bin/gum style --border rounded --border-foreground 212 --padding "0 1" "Day $day"
99 echo ""
100 if [ -f "ts/$day/index.ts" ]; then
101 ${gum}/bin/gum style --foreground 212 "TypeScript:"
102 (cd ts/$day && ${pkgs.bun}/bin/bun run index.ts)
103 echo ""
104 fi
105 if [ -f "nix/$day/solution.nix" ]; then
106 ${gum}/bin/gum style --foreground 212 "Nix:"
107 result=$(${pkgs.nix}/bin/nix-instantiate --eval --strict --json nix/$day/solution.nix)
108 echo "$result" | ${pkgs.jq}/bin/jq -r 'to_entries | .[] | "\(.key): \(.value)"'
109 fi
110 ;;
111 esac
112 ;;
113
114 "Run all solutions")
115 # Collect all unique days
116 all_days=()
117 for dir in ts/* nix/*; do
118 if [ -d "$dir" ]; then
119 day=$(basename "$dir")
120 if [[ ! " ''${all_days[@]} " =~ " ''${day} " ]]; then
121 all_days+=("$day")
122 fi
123 fi
124 done
125
126 # Sort and run each day
127 for daynum in $(printf '%s\n' "''${all_days[@]}" | sort); do
128 ${gum}/bin/gum style --border rounded --border-foreground 212 --padding "0 1" "Day $daynum"
129 echo ""
130
131 if [ -f "ts/$daynum/index.ts" ]; then
132 ${gum}/bin/gum style --foreground 212 "TypeScript:"
133 (cd ts/$daynum && ${pkgs.bun}/bin/bun run index.ts)
134 echo ""
135 fi
136
137 if [ -f "nix/$daynum/solution.nix" ]; then
138 ${gum}/bin/gum style --foreground 212 "Nix:"
139 result=$(${pkgs.nix}/bin/nix-instantiate --eval --strict --json nix/$daynum/solution.nix)
140 echo "$result" | ${pkgs.jq}/bin/jq -r 'to_entries | .[] | "\(.key): \(.value)"'
141 echo ""
142 fi
143 done
144 ;;
145
146 "Exit")
147 ${gum}/bin/gum style --foreground 212 "Happy coding! 🎅"
148 exit 0
149 ;;
150 esac
151 '';
152
153 in {
154 # Development shell with all tools
155 devShells.default = pkgs.mkShell {
156 packages = with pkgs; [
157 bun
158 jq
159 gum
160 runner
161 ];
162
163 shellHook = ''
164 ${gum}/bin/gum style --foreground 212 "🎄 Advent of Code 2025 🎄"
165 echo ""
166 ${gum}/bin/gum style "Run 'aoc' to start the interactive runner"
167 '';
168 };
169
170 # Packages
171 packages = {
172 default = runner;
173 };
174
175 # Apps
176 apps = {
177 default = {
178 type = "app";
179 program = "${runner}/bin/aoc";
180 };
181 };
182 }
183 );
184}