diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..060a358 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Advent of Code +/session +/inputs/* +!/inputs/test/ + +# JetBrains +.idea/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..b596c47 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# Advent of Code 2023 + +Solutions for Advent of Code 2023 in Ruby + +https://adventofcode.com/2023 + +### Instructions +Put the value of your adventofcode.com `session` cookie in a file called `session` to automatically download input files diff --git a/days/day00.rb b/days/day00.rb new file mode 100644 index 0000000..19e5348 --- /dev/null +++ b/days/day00.rb @@ -0,0 +1,19 @@ +require_relative '../lib/aoc' + +module Day00 + extend AOC::Day + + @num = 0 + @ans_test1 = -1 + @ans_test2 = -1 + + def self.solve_part1(input) + return 0 + end + + def self.solve_part2(input) + return 0 + end +end + +Day00.run diff --git a/lib/aoc.rb b/lib/aoc.rb new file mode 100644 index 0000000..632ddc0 --- /dev/null +++ b/lib/aoc.rb @@ -0,0 +1,117 @@ +require 'open-uri' + +module AOC + + YEAR = 2023 + + module Day + # Settings + attr_accessor :num, :ans_test1, :ans_test2 + + # Instance variables + attr_accessor :input, :test_input, :test_input1, :test_input2 + + def run + attr_defaults + puts "--- Running day #{@num} ---".yellow + + load_inputs + + if @input.nil? + puts "Input is missing".red + return + end + + run_part 1 + run_part 2 + end + + def load_inputs + # Load inputs + if @input.nil? + # Load actual input of this day + path = "inputs/input%02d" % @num + unless File.exist?(path) + return unless AOC::Net.configured? and @num != 0 + AOC::Net.retrieve_input @num + end + @input = File.read(path) + end + if @test_input.nil? and not (@ans_test1.nil? and @ans_test2.nil?) + # TODO: Allow part 1 and 2 to have different inputs + # Load test input of this day + path = "inputs/test/test_input%02d" % @num + if File.exist?(path) + @test_input = File.read(path) + end + end + end + + def run_part(part) + puts "--- Part #{part} ---".yellow + + # Check if the solve_partX method is implemented + unless self.respond_to?("solve_part#{part}") + puts "This part has not been implemented".red + return + end + + # Run test if configured + ans_test = self.send("ans_test#{part}") + if not ans_test.nil? and not @test_input.nil? + test = self.send("solve_part#{part}", @test_input) + + if test != ans_test + puts "Test failed, result '#{test}', expected '#{ans_test}'".red + return + end + + puts "Test successful".green + end + + # Solve this part + result = self.send("solve_part#{part}", @input) + puts "Result: #{result}" + end + + def attr_defaults + @num = 0 if @num.nil? + end + end + + module Net + @base_url = "https://adventofcode.com" + + def self.configured? + if @session.nil? and File.exist?("session") + @session = File.read("session") + end + return !@session.nil? + end + + def self.retrieve_input(day) + return unless configured? + + puts "Downloading input file..." + + local_path = "inputs/input%02d" % day + + url = "#{@base_url}/#{AOC::YEAR}/day/#{day}/input" + headers = [ + "User-Agent" => "https://github.com/Aeilko/Advent-of-Code-#{@year}", + "Cookie" => "session=#{@session}", + ] + + content = URI.open(url, *headers).read + File.write(local_path, content, mode: "w") + + content + end + end +end + +class String + def red; "\e[31m#{self}\e[0m" end + def green; "\e[32m#{self}\e[0m" end + def yellow; "\e[33;1m#{self}\e[0m" end +end