marmalade 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +78 -30
- data/examples/file-fix-it/A-small-practice.in +1415 -0
- data/examples/file-fix-it/README.md +4 -0
- data/examples/file-fix-it/file-fix-it.rb +60 -0
- data/examples/reverse-words/reverse-words.rb +2 -1
- data/examples/rope-intranet/rope-intranet.rb +17 -15
- data/lib/marmalade/puzzle.rb +65 -39
- data/lib/marmalade/test_case.rb +37 -0
- data/lib/marmalade/version.rb +1 -1
- data/lib/marmalade.rb +6 -2
- data/marmalade.gemspec +1 -0
- data/spec/marmalade/puzzle_spec.rb +95 -93
- data/spec/marmalade/test_case_spec.rb +42 -0
- data/templates/main.rb +10 -2
- metadata +25 -3
data/README.md
CHANGED
@@ -10,8 +10,8 @@ Most Code Jam input files look like something like this:
|
|
10
10
|
456 # Second line to read
|
11
11
|
789 # Third line to read
|
12
12
|
9 8 # Start of test case 2
|
13
|
-
|
14
|
-
When beginning a puzzle, wouldn't it be nice to focus on what you need to do to solve it rather than messing with
|
13
|
+
|
14
|
+
When beginning a puzzle, wouldn't it be nice to focus on what you need to do to solve it rather than messing with reading the file in the right increments, debugging it, and making sure it's doing what you expect? This is where Marmalade comes in. It gives you tools to use in order to quickly get down to the work of solving the actual problem. After all, time is of the essence!
|
15
15
|
|
16
16
|
## Installation
|
17
17
|
|
@@ -26,29 +26,33 @@ At the moment, the requirements for using it are:
|
|
26
26
|
|
27
27
|
## Basic Usage
|
28
28
|
|
29
|
-
Once the gem is installed, use the generator to create a project
|
29
|
+
Once the gem is installed, use the generator to create yourself a project:
|
30
30
|
|
31
31
|
$ jam example
|
32
|
-
|
33
|
-
This command will create a directory called "example" under the current directory and will create a file in the directory called "example.rb", which is an executable Ruby file set up for using Marmalade to do the dirty work for you. Running this file with the `--help` option lets you know about a few things it can do out of the box:
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
33
|
+
This command will create a directory called `example` under the current directory and will create a file in the directory called `example.rb`, which is an executable Ruby file set up for using Marmalade to do the dirty work for you. Running this file with the `--help` option lets you know about a few things it can do out of the box:
|
34
|
+
|
35
|
+
$ cd example
|
36
|
+
$ ./example.rb --help
|
37
|
+
Options:
|
38
|
+
--file, -f <s>: Input file to read
|
39
|
+
--debug, -d: Debug mode
|
40
|
+
--step, -s: Step through each case
|
41
|
+
--case, -c <i>: Only run the given case
|
42
|
+
--parallel, -p: Run the cases in parallel processes
|
43
|
+
--processes, -r <i>: Specify the number of processes to use
|
44
|
+
--help, -h: Show this message
|
43
45
|
|
44
|
-
Say we have an input file like the one described above
|
46
|
+
Say we have an input file like the one described above. The first line of the file declares how many test cases the file contains. The first number in each test case is called `k` and the second is `n`, which is the number of `lines` to read in for each puzzle. Assuming we have a method called `solve_case` that returns the result we're looking for, we can edit example.rb and instruct Marmalade to read that for us like so:
|
45
47
|
|
46
48
|
Marmalade.jam do
|
47
49
|
read_num_cases
|
48
50
|
test_cases do
|
49
51
|
read [:k, :n], :type => :int
|
50
52
|
read :lines, :count => @n
|
51
|
-
|
53
|
+
run_case do
|
54
|
+
puts solve_case(@k, @lines)
|
55
|
+
end
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
@@ -62,9 +66,21 @@ Marmalade reads in each line and will assign the values to the instance variable
|
|
62
66
|
Case #2: 55
|
63
67
|
# and so on...
|
64
68
|
|
69
|
+
## Using multiple cores
|
70
|
+
|
71
|
+
Marmalade supports running test cases over multiple CPU cores by running them in parallel processes. In order to run your cases in parallel, supply the `--parallel` command line option to the script. For example:
|
72
|
+
|
73
|
+
./example.rb -f input_file.txt --parallel
|
74
|
+
|
75
|
+
When this option is supplied, Marmalade will use as many processes as there are CPU cores on your machine. To control how many processes are used, supply the `--processes=X` command line option. For instance, to run a test using 4 parallel processes, do the following:
|
76
|
+
|
77
|
+
./example.rb -f input_file.txt --processes=4
|
78
|
+
|
79
|
+
Note that if you supply a processes count, you do not have to also supply the `--parallel` option.
|
80
|
+
|
65
81
|
## Reading the number of test cases
|
66
82
|
|
67
|
-
As shown in the example
|
83
|
+
As shown in the example above, the call to `read_num_cases` reads the next line from the file, interpreting it as an integer and assigning it to the `@num_cases` instance variable. It is functionally equivalent to the following call:
|
68
84
|
|
69
85
|
read :num_cases, :type => :int
|
70
86
|
|
@@ -80,10 +96,10 @@ Many times, Code Jam puzzles have lines with multiple values that you want to pr
|
|
80
96
|
|
81
97
|
A B C D E
|
82
98
|
|
83
|
-
|
99
|
+
By default, Marmalade will read that line as a single strin. If you'd rather read it as an array, you can use the `:split` argument to `read` like so:
|
84
100
|
|
85
101
|
read :letters, :split => true
|
86
|
-
|
102
|
+
|
87
103
|
The result would be an instance variable `@letters` which will be the array `['A', 'B', 'C', 'D', 'E']`. Similarly, if the line were a series of number like this:
|
88
104
|
|
89
105
|
1 2 3 4 5 6 7
|
@@ -91,47 +107,79 @@ The result would be an instance variable `@letters` which will be the array `['A
|
|
91
107
|
You can combine `:split` with `:type`:
|
92
108
|
|
93
109
|
read :numbers, :split => true, :type => :int
|
94
|
-
|
110
|
+
|
95
111
|
The `@numbers` instance variable would then contain the array `[1, 2, 3, 4, 5, 6, 7]`.
|
96
112
|
|
97
113
|
Finally, here is how you'd read multiple lines of integer arrays:
|
98
114
|
|
99
115
|
read :matrix, :count => 3, :split => true, :type => :int
|
100
|
-
|
116
|
+
|
101
117
|
If you had an input file that looks like this:
|
102
118
|
|
103
119
|
1 2 3
|
104
120
|
4 5 6
|
105
121
|
7 8 9
|
106
|
-
|
122
|
+
|
107
123
|
Then the `@matrix` instance variable will be an array of arrays: `[[1, 2, 3], [4, 5, 6], [7, 8, 9]]`.
|
108
124
|
|
109
|
-
##
|
125
|
+
## Helper methods
|
110
126
|
|
111
|
-
|
127
|
+
There are two ways to define methods that help you organize your solution code. The first is to simple define the method right within the `run_case` block like so:
|
112
128
|
|
113
|
-
|
129
|
+
Marmalade.jam do
|
130
|
+
read_num_cases
|
131
|
+
test_cases do
|
132
|
+
read :words, :split => true
|
133
|
+
run_case do
|
134
|
+
def solve_case(arr)
|
135
|
+
puts_dbg "array is: #{arr.inspect}"
|
136
|
+
arr.reverse
|
137
|
+
end
|
138
|
+
puts solve_case(@words)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
The second (and preferable) way is to open the `TestCase` class and define methods there. Since code within a `run_case` block runs within the context of a `TestCase` instance, all methods defined within that class will be available when running the case.
|
114
144
|
|
115
|
-
|
145
|
+
class TestCase
|
146
|
+
def solve_case(arr)
|
147
|
+
puts_dbg "array is: #{arr.inspect}"
|
148
|
+
arr.reverse
|
149
|
+
end
|
150
|
+
end
|
116
151
|
|
117
152
|
Marmalade.jam do
|
118
153
|
read_num_cases
|
119
154
|
test_cases do
|
120
|
-
read
|
121
|
-
read :lines, :count => @n
|
122
|
-
# run_case tells Marmalade that the following code is test case processing code
|
155
|
+
read :words, :split => true
|
123
156
|
run_case do
|
124
|
-
puts solve_case(@
|
157
|
+
puts solve_case(@words)
|
125
158
|
end
|
126
159
|
end
|
127
160
|
end
|
128
161
|
|
129
|
-
|
162
|
+
Of course, defining methods in the global context of the file itself will work fine, but then they won't have access to the instance variables read from the file, or the modified `puts` or `puts_dbg` methods (see below).
|
163
|
+
|
164
|
+
## Debugging
|
165
|
+
|
166
|
+
Marmalade gives you a few ways to help debug as you solve puzzles. Firstly, you can pass `--debug` as a command line argument, which enables debug mode. As you go along, you can use `puts_dbg` to write debug messages to the console only if debug mode is enabled. This comes in handy when you want to do your final run to generate your submitted output file.
|
167
|
+
|
168
|
+
Passing the `--step` command line argument will cause Marmalade to pause for user input between every test case. This is particularly handy when you're validating your solution to a puzzle and want to follow your debug output as the program runs through test cases.
|
169
|
+
|
170
|
+
Sometimes you hit a tricky test case and want to work on just that case. Passing `--case X` will cause it to only process case X and skip all other cases. However, in order to enable this functionality, you must make sure the work in each case is done in a `run_case` block. For example, this command:
|
130
171
|
|
131
172
|
$ ./example.rb -f sample.txt --case 5
|
132
173
|
|
133
174
|
Will run `solve_case` only for test case 5.
|
134
175
|
|
176
|
+
## Updating from 0.2 to 0.3
|
177
|
+
|
178
|
+
Two things have changed between v0.2 and v0.3 that may break your previous scripts:
|
179
|
+
|
180
|
+
* In version 0.2, Marmalade did not require that test case code was contained in a `run_case` block. This is now required.
|
181
|
+
* Version 0.2 was able to use globally-scoped helper functions, which is now deprecated. For version 0.3, please open the TestCase class or create helper methods directly in the `run_case` block.
|
182
|
+
|
135
183
|
## Contributing
|
136
184
|
|
137
185
|
1. Fork it
|