Advent of Code solutions

start a script to run all and record stats

+241
+3
2025/README.md
··· 1 + # Advent of Code 2025 2 + 3 + Back to (mostly) Trilogy this time, depending on performance needs; Trilogy (post-rewrite) was just barely functioning this time around.
+238
all.rb
··· 1 + #!/usr/bin/env ruby 2 + 3 + require 'json' 4 + 5 + def which cmd 6 + exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] 7 + ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| 8 + exts.each do |ext| 9 + exe = File.join(path, "#{cmd}#{ext}") 10 + return exe if File.executable?(exe) && !File.directory?(exe) 11 + end 12 + end 13 + nil 14 + end 15 + 16 + def measure 17 + before = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) 18 + yield 19 + after = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) 20 + after - before 21 + end 22 + 23 + def report label 24 + answer = nil 25 + time = measure do 26 + answer = yield 27 + end 28 + return :program_error unless $?.success? 29 + answer = answer.chomp 30 + puts "\t#{label}: #{answer} in #{(time / 10000).to_f / 100}ms" 31 + return { 32 + duration_ns: time, 33 + answer: answer 34 + } 35 + end 36 + 37 + module Rust 38 + def self.available? 39 + which "rustc" != nil 40 + end 41 + 42 + def self.implemented? part 43 + File.exist? "p#{part}.rs" 44 + end 45 + 46 + def self.run part 47 + `rustc p#{part}.rs 2> /dev/null` 48 + return :rustc_error unless $?.success? 49 + report "p#{part}.rs" do 50 + `timeout 1m ./p#{part} < input` 51 + end 52 + end 53 + end 54 + 55 + module Haskell 56 + def self.available? 57 + which "ghc" != nil 58 + end 59 + 60 + def self.implemented? part 61 + File.exist? "p#{part}.hs" 62 + end 63 + 64 + def self.run part 65 + `ghc p#{part}.hs 2> /dev/null` 66 + return :ghc_error unless $?.success? 67 + report "p#{part}.hs" do 68 + `timeout 1m ./p#{part} < input` 69 + end 70 + end 71 + end 72 + 73 + module Trilogy 74 + def self.clang 75 + return "clang" if which "clang" 76 + return "clang-19" if which "clang-19" 77 + nil 78 + end 79 + 80 + def self.available? 81 + which "trilogy" != nil and self.clang != nil 82 + end 83 + 84 + def self.implemented? part 85 + File.exist? "p#{part}.tri" 86 + end 87 + 88 + def self.run part 89 + `trilogy compile p#{part}.tri 2> /dev/null | #{self.clang} -O3 -o p#{part} -x ir -` 90 + return :trilogy_error unless $?.success? 91 + report "p#{part}.tri" do 92 + `timeout 1m ./p#{part} < input` 93 + end 94 + end 95 + end 96 + 97 + module C 98 + def self.clang 99 + return "clang" if which "clang" 100 + return "clang-19" if which "clang-19" 101 + return "gcc" if which "gcc" 102 + nil 103 + end 104 + 105 + def self.available? 106 + self.clang != nil 107 + end 108 + 109 + def self.implemented? part 110 + File.exist? "p#{part}.c" 111 + end 112 + 113 + def self.run part 114 + `#{self.clang} -O3 -o p#{part} p#{part}.c` 115 + return :clang_error unless $?.success? 116 + report "p#{part}.c" do 117 + `timeout 1m ./p#{part} < input` 118 + end 119 + end 120 + end 121 + 122 + module Cpp 123 + def self.available? 124 + which "g++" != nil 125 + end 126 + 127 + def self.implemented? part 128 + File.exist? "p#{part}.cpp" 129 + end 130 + 131 + def self.run part 132 + `g++ -std=c++2c -O3 -o p#{part} p#{part}.cpp` 133 + return :gcc_error unless $?.success? 134 + report "p#{part}.cpp" do 135 + `timeout 1m ./p#{part} < input` 136 + end 137 + end 138 + end 139 + 140 + module Swift 141 + def self.available? 142 + which "swiftc" != nil 143 + end 144 + 145 + def self.implemented? part 146 + File.exist? "p#{part}.swift" 147 + end 148 + 149 + def self.run part 150 + `swiftc p#{part} p#{part}.swift` 151 + return :swiftc_error unless $?.success? 152 + report "p#{part}.swift" do 153 + `timeout 1m ./p#{part} < input` 154 + end 155 + end 156 + end 157 + 158 + module Python 159 + def self.python 160 + return "python3" if which "python3" 161 + return "python" if which "python" 162 + return nil 163 + end 164 + 165 + def self.available? 166 + self.python != nil 167 + end 168 + 169 + def self.implemented? part 170 + File.exist? "p#{part}.py" 171 + end 172 + 173 + def self.run part 174 + report "p#{part}.py" do 175 + `timeout 1m #{self.python} p#{part}.py < input` 176 + end 177 + end 178 + end 179 + 180 + module Ruby 181 + def self.available? 182 + which "ruby" != nil 183 + end 184 + 185 + def self.implemented? part 186 + File.exist? "p#{part}.rb" 187 + end 188 + 189 + def self.run part 190 + report "p#{part}.rb" do 191 + `timeout 1m ruby p#{part}.rb < input` 192 + end 193 + end 194 + end 195 + 196 + module TypeScript 197 + def self.available? 198 + which "deno" != nil 199 + end 200 + 201 + def self.implemented? part 202 + File.exist? "p#{part}.ts" 203 + end 204 + 205 + def self.run part 206 + report "p#{part}.ts" do 207 + `timeout 1m deno p#{part}.ts < input` 208 + end 209 + end 210 + end 211 + 212 + languages = [Haskell, Rust, Trilogy, C, Cpp, Swift, Python, Ruby, TypeScript] 213 + .filter { |lang| lang.available? } 214 + 215 + root = Dir.pwd 216 + report = {} 217 + 218 + for year in `ls .`.split.filter { |x| /^\d+$/ =~ x } do 219 + report[year] = {} 220 + for day in 1..25 do 221 + next unless Dir.exist? "#{year}/#{day}" 222 + report[year][day] = {} 223 + puts "year #{year} day #{day}" 224 + `just get #{day} #{year} 2> /dev/null` 225 + 226 + Dir.chdir "#{year}/#{day}" 227 + for part in ['1', '2'] do 228 + report[year][day]["p#{part}"] = {} 229 + for lang in languages do 230 + next unless lang.implemented? part 231 + report[year][day]["p#{part}"][lang] = lang.run part 232 + end 233 + end 234 + Dir.chdir root 235 + end 236 + end 237 + 238 + File.write "report.json", JSON.pretty_generate(report)