advent_of_code_cli 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +58 -1
- data/lib/advent_of_code_cli/commands/command.rb +8 -0
- data/lib/advent_of_code_cli/commands/download.rb +4 -1
- data/lib/advent_of_code_cli/commands/example/new.rb +48 -0
- data/lib/advent_of_code_cli/commands/example/solve.rb +62 -0
- data/lib/advent_of_code_cli/commands/example.rb +38 -0
- data/lib/advent_of_code_cli/commands/scaffold.rb +9 -9
- data/lib/advent_of_code_cli/commands/solve.rb +1 -3
- data/lib/advent_of_code_cli/commands.rb +1 -0
- data/lib/advent_of_code_cli/version.rb +1 -1
- data/lib/advent_of_code_cli.rb +5 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 975ed7c8275bc2111366961b426b01ba4805835876aa47ada28cb45a8296a56d
|
4
|
+
data.tar.gz: e3ecbe525361d68da73e13906adda1594354d9bfc1727a85a752f57114673685
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bcc6d477acc45cb34b0bbea2c7f2f0cb904b3e76b80847267de80db2d2f5dfcaf96ec0078c080e6de44a4cd45cbe008708199090d4cd0a59fda6147bf2d556e
|
7
|
+
data.tar.gz: 7b912eaa46ee7e047aed2bc94ed7997e097317fef923ad4fdbd36d69885ff6be07002cf43ba0409d3b0e0ee916711301a85d1e7775f24c91c349f628dff9f48c
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
AllCops:
|
2
2
|
TargetRubyVersion: 2.6
|
3
|
+
NewCops: enable
|
3
4
|
|
4
5
|
Style/Documentation:
|
5
6
|
Enabled: false
|
@@ -14,3 +15,9 @@ Style/StringLiteralsInInterpolation:
|
|
14
15
|
|
15
16
|
Layout/LineLength:
|
16
17
|
Max: 120
|
18
|
+
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Metrics/MethodLength:
|
23
|
+
Enabled: false
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
> ⚠️ **Note:** This tool is under active development. I built in in a couple hours with no automated tests. Things may change between versions!
|
4
4
|
|
5
|
-
A little CLI tool that scaffolds and runs [Advent of Code](https://
|
5
|
+
A little CLI tool that scaffolds and runs [Advent of Code](https://adventofcode.com) solutions in Ruby.
|
6
6
|
|
7
7
|
This project is heavily based on [advent-of-code-rust](https://github.com/arturopala/advent-of-code-rust). Go check it out!
|
8
8
|
|
@@ -52,6 +52,8 @@ module Day01
|
|
52
52
|
end
|
53
53
|
```
|
54
54
|
|
55
|
+
...where `input` is an `Array[String]` of all the lines without newlines.
|
56
|
+
|
55
57
|
I would love to make this structure configurable in the future.
|
56
58
|
|
57
59
|
### Download
|
@@ -111,6 +113,61 @@ Done!
|
|
111
113
|
|
112
114
|
This command expects files to be in the format provided by the `scaffold` command. Once again, I would love to make this configurable but haven't gotten around to it yet.
|
113
115
|
|
116
|
+
### Examples
|
117
|
+
|
118
|
+
It is often helpful to run our solutions against example input. The `example` command can help you create and run examples of your own invention.
|
119
|
+
|
120
|
+
#### Create a new example
|
121
|
+
|
122
|
+
You can create a new file for example input by running the following command:
|
123
|
+
|
124
|
+
```
|
125
|
+
bundle exec aoc_cli example new 1 A
|
126
|
+
```
|
127
|
+
|
128
|
+
The first argument specifies the day, and the second argument is the name of the example. You may choose whatever name you'd like.
|
129
|
+
|
130
|
+
This will generate the following output:
|
131
|
+
|
132
|
+
```
|
133
|
+
Creating examples/01/A.txt...
|
134
|
+
Creating examples/01/A_expected.yml...
|
135
|
+
Done!
|
136
|
+
```
|
137
|
+
|
138
|
+
- `examples/01/A.txt` is a blank text file where you can enter your own input for the problem.
|
139
|
+
- `examples/01/A_expected.yml` is a YAML file with the following content:
|
140
|
+
|
141
|
+
```
|
142
|
+
part_one: ~
|
143
|
+
part_two: ~
|
144
|
+
```
|
145
|
+
|
146
|
+
Replace the two tildes (`~`) with the expected result of running your solution against the example input provided.
|
147
|
+
|
148
|
+
#### Running examples
|
149
|
+
|
150
|
+
You can check your solution against an example with the following command:
|
151
|
+
|
152
|
+
```
|
153
|
+
bundle exec aoc_cli example solve 1 A
|
154
|
+
```
|
155
|
+
|
156
|
+
This will output the following:
|
157
|
+
|
158
|
+
```
|
159
|
+
Reading input...
|
160
|
+
Loading solution...
|
161
|
+
|
162
|
+
Running part one with example A...
|
163
|
+
Part one result: 1034 ✅
|
164
|
+
Took 0.000259 seconds to solve
|
165
|
+
|
166
|
+
Running part two with example A...
|
167
|
+
Part two result: 7934 ✅
|
168
|
+
Took 0.000253 seconds to solve
|
169
|
+
```
|
170
|
+
|
114
171
|
## Contributing
|
115
172
|
|
116
173
|
Issues and code contributions are welcome! Happy Advent of Code to all who celebrate! 🎁
|
@@ -25,6 +25,14 @@ module AdventOfCode
|
|
25
25
|
"inputs/#{day_string}.txt"
|
26
26
|
end
|
27
27
|
|
28
|
+
def example_file_name
|
29
|
+
"examples/#{day_string}/#{@name}.txt"
|
30
|
+
end
|
31
|
+
|
32
|
+
def example_expected_file_name
|
33
|
+
"examples/#{day_string}/#{@name}_expected.yml"
|
34
|
+
end
|
35
|
+
|
28
36
|
def create_file(file_name, contents = nil)
|
29
37
|
File.open(file_name, "w") do |file|
|
30
38
|
file.puts contents if contents
|
@@ -31,7 +31,7 @@ module AdventOfCode
|
|
31
31
|
private
|
32
32
|
|
33
33
|
def cookie
|
34
|
-
@cookie ||= ENV
|
34
|
+
@cookie ||= ENV.fetch("AOC_COOKIE", nil)
|
35
35
|
end
|
36
36
|
|
37
37
|
def cookie_present?
|
@@ -46,6 +46,9 @@ module AdventOfCode
|
|
46
46
|
|
47
47
|
request = Net::HTTP::Get.new(url)
|
48
48
|
request["Cookie"] = "session=#{cookie}"
|
49
|
+
# The creator of Advent of Code has requested that automated tools send identifying information
|
50
|
+
# when making requests: https://www.reddit.com/r/adventofcode/comments/z9dhtd
|
51
|
+
request["User-Agent"] = "github.com/egiurleo/advent_of_code_cli by emily.samp@icloud.com"
|
49
52
|
|
50
53
|
response = https.request(request)
|
51
54
|
response.read_body
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AdventOfCode
|
4
|
+
module Commands
|
5
|
+
module Example
|
6
|
+
class New < Command
|
7
|
+
def initialize(day:, name:)
|
8
|
+
@name = name
|
9
|
+
super(day: day)
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
unless Dir.exist?("examples")
|
14
|
+
say("Creating examples directory...")
|
15
|
+
Dir.mkdir("examples")
|
16
|
+
end
|
17
|
+
|
18
|
+
unless Dir.exist?("examples/#{day_string}")
|
19
|
+
say("Creating examples/#{day_string} directory...")
|
20
|
+
Dir.mkdir("examples/#{day_string}")
|
21
|
+
end
|
22
|
+
|
23
|
+
if File.exist?(example_file_name)
|
24
|
+
raise ExampleAlreadyExistsError,
|
25
|
+
"could not create example file because file #{example_file_name} already exists"
|
26
|
+
end
|
27
|
+
|
28
|
+
say("Creating #{example_file_name}...")
|
29
|
+
create_file(example_file_name)
|
30
|
+
|
31
|
+
say("Creating #{example_expected_file_name}...")
|
32
|
+
create_file(example_expected_file_name, expected_file_contents)
|
33
|
+
|
34
|
+
say "Done!", :green
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def expected_file_contents
|
40
|
+
<<~RUBY
|
41
|
+
part_one: ~
|
42
|
+
part_two: ~
|
43
|
+
RUBY
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module AdventOfCode
|
6
|
+
module Commands
|
7
|
+
module Example
|
8
|
+
class Solve < Command
|
9
|
+
def initialize(day:, name:)
|
10
|
+
@name = name
|
11
|
+
super(day: day)
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute
|
15
|
+
raise MissingExampleError unless File.exist?(example_file_name)
|
16
|
+
raise MissingExampleError unless File.exist?(example_expected_file_name)
|
17
|
+
raise MissingSolutionError unless File.exist?(solution_file_name)
|
18
|
+
|
19
|
+
say "Reading input..."
|
20
|
+
input = File.readlines(example_file_name, chomp: true)
|
21
|
+
|
22
|
+
say "Loading solution..."
|
23
|
+
load(solution_file_name)
|
24
|
+
|
25
|
+
module_name = "Day#{day_string}"
|
26
|
+
|
27
|
+
say "\nRunning part one with example #{@name}..."
|
28
|
+
solution(module_name, "one", input)
|
29
|
+
|
30
|
+
say "\nRunning part two with example #{@name}..."
|
31
|
+
solution(module_name, "two", input)
|
32
|
+
|
33
|
+
say "\nDone!", :green
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def solution(module_name, part, input)
|
39
|
+
start_time = Time.now
|
40
|
+
result = Object.const_get(module_name).send("part_#{part}", input)
|
41
|
+
end_time = Time.now
|
42
|
+
|
43
|
+
expected_result = expected_answers["part_#{part}"]
|
44
|
+
|
45
|
+
if expected_result.nil?
|
46
|
+
say "Part #{part} result: #{result} ⚠️ (no expectation provided)"
|
47
|
+
elsif result == expected_result
|
48
|
+
say "Part #{part} result: #{result} ✅"
|
49
|
+
else
|
50
|
+
say "Part #{part} result: #{result} ❌ (expected #{expected_result})"
|
51
|
+
end
|
52
|
+
|
53
|
+
say "Took #{end_time - start_time} seconds to solve"
|
54
|
+
end
|
55
|
+
|
56
|
+
def expected_answers
|
57
|
+
@expected_answers ||= YAML.safe_load(File.read(example_expected_file_name))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "example/new"
|
4
|
+
require_relative "example/solve"
|
5
|
+
|
6
|
+
module AdventOfCode
|
7
|
+
module Commands
|
8
|
+
module Example
|
9
|
+
class CLI < Thor
|
10
|
+
desc "new DAY NAME", "creates an example file with name NAME for day DAY"
|
11
|
+
def new(day, name)
|
12
|
+
New.new(day: day.to_i, name: name).execute
|
13
|
+
rescue ExampleAlreadyExistsError => e
|
14
|
+
say(e.message, :red)
|
15
|
+
rescue InvalidDayError
|
16
|
+
rescue_invalid_day_error
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "solve DAY NAME", "runs the example with name NAME for day DAY"
|
20
|
+
def solve(day, name)
|
21
|
+
Solve.new(day: day.to_i, name: name).execute
|
22
|
+
rescue InvalidDayError
|
23
|
+
rescue_invalid_day_error
|
24
|
+
rescue MissingExampleError
|
25
|
+
say "Error: Cannot find example file.", :red
|
26
|
+
rescue AdventOfCode::MissingSolutionError
|
27
|
+
say "Error: Cannot find solution file.", :red
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def rescue_invalid_day_error
|
33
|
+
say "Error: The day argument must be an integer between 1 and 25.", :red
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -32,17 +32,17 @@ module AdventOfCode
|
|
32
32
|
|
33
33
|
def solution_file_contents
|
34
34
|
<<~RUBY
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
module Day#{day_string}
|
36
|
+
class << self
|
37
|
+
def part_one(input)
|
38
|
+
raise NotImplementedError
|
39
|
+
end
|
40
|
+
|
41
|
+
def part_two(input)
|
42
|
+
raise NotImplementedError
|
43
|
+
end
|
43
44
|
end
|
44
45
|
end
|
45
|
-
end
|
46
46
|
RUBY
|
47
47
|
end
|
48
48
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'benchmark'
|
4
|
-
|
5
3
|
module AdventOfCode
|
6
4
|
module Commands
|
7
5
|
class Solve < Command
|
@@ -34,7 +32,7 @@ module AdventOfCode
|
|
34
32
|
end_time = Time.now
|
35
33
|
|
36
34
|
say "Part #{part} result: #{result}"
|
37
|
-
say "Took #{end_time-start_time} seconds to solve"
|
35
|
+
say "Took #{end_time - start_time} seconds to solve"
|
38
36
|
end
|
39
37
|
end
|
40
38
|
end
|
data/lib/advent_of_code_cli.rb
CHANGED
@@ -7,8 +7,10 @@ require_relative "advent_of_code_cli/commands"
|
|
7
7
|
|
8
8
|
module AdventOfCode
|
9
9
|
class Error < StandardError; end
|
10
|
+
class ExampleAlreadyExistsError < Error; end
|
10
11
|
class InvalidDayError < Error; end
|
11
12
|
class MissingCookieError < Error; end
|
13
|
+
class MissingExampleError < Error; end
|
12
14
|
class MissingInputError < Error; end
|
13
15
|
class MissingSolutionError < Error; end
|
14
16
|
|
@@ -41,6 +43,9 @@ module AdventOfCode
|
|
41
43
|
say "Error: Cannot find solution file.", :red
|
42
44
|
end
|
43
45
|
|
46
|
+
desc "example", "create and run example files"
|
47
|
+
subcommand "example", Commands::Example::CLI
|
48
|
+
|
44
49
|
private
|
45
50
|
|
46
51
|
def rescue_invalid_day_error
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: advent_of_code_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emily Samp
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -45,6 +45,9 @@ files:
|
|
45
45
|
- lib/advent_of_code_cli/commands.rb
|
46
46
|
- lib/advent_of_code_cli/commands/command.rb
|
47
47
|
- lib/advent_of_code_cli/commands/download.rb
|
48
|
+
- lib/advent_of_code_cli/commands/example.rb
|
49
|
+
- lib/advent_of_code_cli/commands/example/new.rb
|
50
|
+
- lib/advent_of_code_cli/commands/example/solve.rb
|
48
51
|
- lib/advent_of_code_cli/commands/scaffold.rb
|
49
52
|
- lib/advent_of_code_cli/commands/solve.rb
|
50
53
|
- lib/advent_of_code_cli/version.rb
|
@@ -54,6 +57,7 @@ licenses:
|
|
54
57
|
metadata:
|
55
58
|
homepage_uri: https://github.com/egiurleo/advent_of_code_cli
|
56
59
|
source_code_uri: https://github.com/egiurleo/advent_of_code_cli
|
60
|
+
rubygems_mfa_required: 'true'
|
57
61
|
post_install_message:
|
58
62
|
rdoc_options: []
|
59
63
|
require_paths:
|
@@ -69,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
73
|
- !ruby/object:Gem::Version
|
70
74
|
version: '0'
|
71
75
|
requirements: []
|
72
|
-
rubygems_version: 3.3.
|
76
|
+
rubygems_version: 3.3.26
|
73
77
|
signing_key:
|
74
78
|
specification_version: 4
|
75
79
|
summary: A CLI tool to scaffold and run Advent of Code solutions.
|