trackler 2.0.1.1 → 2.0.1.2
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/bin/update +4 -0
- data/common/exercises/minesweeper/canonical-data.json +3 -3
- data/fixtures/common/exercises/imbe/description.md +2 -0
- data/fixtures/common/exercises/imbe/metadata.yml +3 -0
- data/fixtures/common/exercises/no-metadata/description.md +1 -0
- data/fixtures/tracks/fruit/exercises/imbe/.meta/everything_in_meta_is_ignored.txt +0 -0
- data/fixtures/tracks/fruit/exercises/imbe/CaSe_iNSeNSiTiVe_eXaMPLe.TXT +0 -0
- data/fixtures/tracks/fruit/exercises/imbe/HINTS.md +1 -0
- data/fixtures/tracks/fruit/exercises/imbe/also_an_example.txt +1 -0
- data/fixtures/tracks/fruit/exercises/imbe/example.ext +1 -0
- data/fixtures/tracks/fruit/exercises/imbe/imbe.txt +1 -0
- data/lib/trackler/file_bundle.rb +27 -9
- data/lib/trackler/implementation.rb +7 -6
- data/lib/trackler/problem.rb +62 -37
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +9 -0
- data/tracks/c/exercises/series/makefile +16 -0
- data/tracks/c/exercises/series/src/example.c +24 -0
- data/tracks/c/exercises/series/src/series.h +28 -0
- data/tracks/c/exercises/series/test/test_series.c +63 -0
- data/tracks/c/exercises/series/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/series/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/series/test/vendor/unity_internals.h +701 -0
- data/tracks/crystal/src/generator/exercises/binary.cr +3 -3
- data/tracks/crystal/src/generator/exercises/forth.cr +3 -3
- data/tracks/crystal/src/generator/exercises/hello_world.cr +1 -1
- data/tracks/haskell/exercises/bob/test/Tests.hs +2 -10
- data/tracks/haskell/exercises/sublist/test/Tests.hs +6 -1
- data/tracks/java/config.json +13 -1
- data/tracks/java/exercises/bracket-push/build.gradle +17 -0
- data/tracks/java/exercises/bracket-push/src/example/java/BracketChecker.java +45 -0
- data/tracks/java/exercises/bracket-push/src/main/java/BracketChecker.java +5 -0
- data/tracks/java/exercises/bracket-push/src/test/java/BracketCheckerTest.java +102 -0
- data/tracks/java/exercises/robot-simulator/build.gradle +17 -0
- data/tracks/java/exercises/robot-simulator/src/example/java/GridPosition.java +1 -0
- data/tracks/java/exercises/robot-simulator/src/example/java/Orientation.java +1 -0
- data/tracks/java/exercises/robot-simulator/src/example/java/Robot.java +71 -0
- data/tracks/java/exercises/robot-simulator/src/main/java/GridPosition.java +29 -0
- data/tracks/java/exercises/robot-simulator/src/main/java/Orientation.java +5 -0
- data/tracks/java/exercises/robot-simulator/src/main/java/Robot.java +5 -0
- data/tracks/java/exercises/robot-simulator/src/test/java/RobotTest.java +244 -0
- data/tracks/java/exercises/settings.gradle +2 -0
- data/tracks/ocaml/exercises/say/test.ml +52 -56
- data/tracks/ocaml/tools/test-generator/src/codegen.ml +2 -1
- data/tracks/ocaml/tools/test-generator/src/special_cases.ml +10 -4
- data/tracks/ocaml/tools/test-generator/src/test_generator.ml +5 -0
- data/tracks/ocaml/tools/test-generator/templates/say/template.ml +21 -0
- data/tracks/ocaml/tools/test-generator/test/special_cases_test.ml +2 -2
- metadata +30 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b688c37ee3986356aaadb9bd39b4dd72524ed7f
|
4
|
+
data.tar.gz: 0023dcfdc396190c1c7ee84988a9e183d9ec1459
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c723690b00d103e004d70e3b1436ce5fb406e2ad06dd4d18e120f16578c3b31164430936bc3f5127e2431426be5a2e814923b98cfca95af03247ef64044708aa
|
7
|
+
data.tar.gz: a45271733dc3dc85ba092a50293cf267acdd14343cecffa9fac2cbf980be3b9b7b8c26e29f90c5b3fc499faef4ad4f2a5671070ab03c827cb2ba88d4393e9488
|
data/bin/update
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
This exercise should have no metadata.yml file.
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
Hints file is ignored.
|
@@ -0,0 +1 @@
|
|
1
|
+
This file is also ignored.
|
@@ -0,0 +1 @@
|
|
1
|
+
Any file containing example is ignored.
|
@@ -0,0 +1 @@
|
|
1
|
+
All files in this directory, EXCEPT for this file, should be ignored.
|
data/lib/trackler/file_bundle.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
require 'zip'
|
2
2
|
|
3
3
|
module Trackler
|
4
|
-
# FileBundle is a
|
4
|
+
# A FileBundle is a collection of files from within an exercise directory
|
5
|
+
# It contains all the files that will be provided by the `exercism fetch` command
|
6
|
+
# EXCEPT for those whose names match any of the ignore patterns.
|
5
7
|
class FileBundle
|
6
|
-
|
7
|
-
|
8
|
-
@dir = dir
|
8
|
+
def initialize(base_directory, ignore_patterns = [])
|
9
|
+
@base_directory = base_directory
|
9
10
|
@ignore_patterns = ignore_patterns
|
10
11
|
end
|
11
12
|
|
12
13
|
def zip
|
13
14
|
Zip::OutputStream.write_buffer do |io|
|
14
15
|
paths.each do |path|
|
15
|
-
io.put_next_entry(path.relative_path_from(
|
16
|
+
io.put_next_entry(path.relative_path_from(base_directory))
|
16
17
|
io.print IO.read(path)
|
17
18
|
end
|
18
19
|
yield io if block_given?
|
@@ -20,10 +21,27 @@ module Trackler
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def paths
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
all_files_below(base_directory).reject { |file| ignored? file }.sort
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :base_directory, :ignore_patterns
|
30
|
+
|
31
|
+
def all_files_below(dir)
|
32
|
+
Pathname.glob("#{dir}/**/*", File::FNM_DOTMATCH)
|
33
|
+
end
|
34
|
+
|
35
|
+
def ignored?(file)
|
36
|
+
ignored_by_name?(file) || ignored_by_type?(file)
|
37
|
+
end
|
38
|
+
|
39
|
+
def ignored_by_name?(file)
|
40
|
+
ignore_patterns.any? { |pattern| file.to_s =~ pattern }
|
41
|
+
end
|
42
|
+
|
43
|
+
def ignored_by_type?(file)
|
44
|
+
file.directory?
|
27
45
|
end
|
28
46
|
end
|
29
47
|
end
|
@@ -8,6 +8,7 @@ module Trackler
|
|
8
8
|
Regexp.new("HINTS\.md$"),
|
9
9
|
Regexp.new("example", Regexp::IGNORECASE),
|
10
10
|
Regexp.new("\/\.$"),
|
11
|
+
Regexp.new("/\.meta/")
|
11
12
|
]
|
12
13
|
|
13
14
|
attr_reader :track_id, :repo, :problem, :root, :file_bundle
|
@@ -17,16 +18,16 @@ module Trackler
|
|
17
18
|
@repo = repo
|
18
19
|
@problem = problem
|
19
20
|
@root = Pathname.new(root)
|
20
|
-
@file_bundle = FileBundle.new(
|
21
|
+
@file_bundle = FileBundle.new(track_directory, IGNORE)
|
21
22
|
end
|
22
23
|
|
23
24
|
def exists?
|
24
|
-
File.exist?(
|
25
|
+
File.exist?(track_directory)
|
25
26
|
end
|
26
27
|
|
27
28
|
def files
|
28
29
|
@files ||= Hash[file_bundle.paths.map {|path|
|
29
|
-
[path.relative_path_from(
|
30
|
+
[path.relative_path_from(track_directory).to_s, File.read(path)]
|
30
31
|
}].merge("README.md" => readme)
|
31
32
|
end
|
32
33
|
|
@@ -55,8 +56,8 @@ module Trackler
|
|
55
56
|
|
56
57
|
private
|
57
58
|
|
58
|
-
def
|
59
|
-
@
|
59
|
+
def track_directory
|
60
|
+
@track_directory ||= track_dir.join(exercise_dir)
|
60
61
|
end
|
61
62
|
|
62
63
|
def track_dir
|
@@ -105,7 +106,7 @@ It's possible to submit an incomplete solution so you can see how others have co
|
|
105
106
|
end
|
106
107
|
|
107
108
|
def implementation_hint
|
108
|
-
read File.join(
|
109
|
+
read File.join(track_directory, 'HINTS.md')
|
109
110
|
end
|
110
111
|
|
111
112
|
def read(f)
|
data/lib/trackler/problem.rb
CHANGED
@@ -10,78 +10,103 @@ module Trackler
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def exists?
|
13
|
-
!!
|
13
|
+
!!description && !!metadata
|
14
14
|
end
|
15
15
|
|
16
16
|
def name
|
17
|
-
|
17
|
+
slug.split('-').map(&:capitalize).join(' ')
|
18
18
|
end
|
19
19
|
|
20
20
|
def description
|
21
|
-
@description
|
21
|
+
return @description unless @description.nil?
|
22
|
+
filename = common_metadata_path(description_path)
|
23
|
+
if File.exists?(filename)
|
24
|
+
@description = File.read(filename)
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
def source_markdown
|
25
|
-
|
26
|
-
|
27
|
-
if url.empty? && body.empty?
|
28
|
-
""
|
29
|
-
else
|
30
|
-
"## Source\n\n" + [body, url].reject(&:empty?).join(" ")
|
31
|
-
end
|
29
|
+
text = [source, markdown_link(source_url)].reject(&:empty?).join(" ")
|
30
|
+
text.empty? ? text : "## Source\n\n#{text}"
|
32
31
|
end
|
33
32
|
|
33
|
+
######
|
34
|
+
# Deprecated methods
|
35
|
+
# TODO: remove external references to these methods.
|
36
|
+
# found in: x-api
|
37
|
+
# NOT in: exercism.io, cli
|
38
|
+
# Anywhere else we need to look?
|
39
|
+
# Should this output a warning or raise an error?
|
34
40
|
def md_url
|
35
|
-
|
41
|
+
description_url
|
36
42
|
end
|
37
43
|
|
38
44
|
def json_url
|
39
|
-
|
45
|
+
canonical_data_url
|
40
46
|
end
|
41
47
|
|
42
48
|
def yaml_url
|
43
|
-
|
49
|
+
metadata_url
|
44
50
|
end
|
51
|
+
# End deprecated methods
|
52
|
+
######
|
45
53
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
54
|
+
def description_url
|
55
|
+
repo_url(description_path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def canonical_data_url
|
59
|
+
repo_url(canonical_data_path) if File.exists?(common_metadata_path(canonical_data_path))
|
60
|
+
end
|
61
|
+
|
62
|
+
def metadata_url
|
63
|
+
repo_url(metadata_path)
|
64
|
+
end
|
65
|
+
|
66
|
+
def blurb
|
67
|
+
metadata['blurb'].to_s.strip
|
68
|
+
end
|
69
|
+
|
70
|
+
def source
|
71
|
+
metadata['source'].to_s.strip
|
72
|
+
end
|
73
|
+
|
74
|
+
def source_url
|
75
|
+
metadata['source_url'].to_s.strip
|
50
76
|
end
|
51
77
|
|
52
78
|
private
|
53
79
|
|
54
|
-
def
|
55
|
-
|
56
|
-
"exercises/%s/canonical-data.json" % slug,
|
57
|
-
"%s.json" % slug,
|
58
|
-
].find { |path| File.exist?(filepath(path)) }
|
80
|
+
def canonical_data_path
|
81
|
+
"exercises/%s/canonical-data.json" % slug
|
59
82
|
end
|
60
83
|
|
61
|
-
def
|
62
|
-
|
63
|
-
"exercises/%s/metadata.yml" % slug,
|
64
|
-
"%s.yml" % slug,
|
65
|
-
].find { |path| File.exist?(filepath(path)) }
|
84
|
+
def metadata_path
|
85
|
+
"exercises/%s/metadata.yml" % slug
|
66
86
|
end
|
67
87
|
|
68
|
-
def
|
69
|
-
|
70
|
-
"exercises/%s/description.md" % slug,
|
71
|
-
"%s.md" % slug,
|
72
|
-
].find { |path| File.exist?(filepath(path)) }
|
88
|
+
def description_path
|
89
|
+
"exercises/%s/description.md" % slug
|
73
90
|
end
|
74
91
|
|
75
92
|
def repo_url(path)
|
76
|
-
"https://github.com/exercism/x-common/blob/master
|
93
|
+
"https://github.com/exercism/x-common/blob/master/#{path}" unless path.nil?
|
77
94
|
end
|
78
95
|
|
79
|
-
def
|
80
|
-
|
96
|
+
def metadata
|
97
|
+
return @metadata unless @metadata.nil?
|
98
|
+
filename = common_metadata_path(metadata_path)
|
99
|
+
if File.exists?(filename)
|
100
|
+
@metadata = YAML.load(File.read(filename))
|
101
|
+
end
|
81
102
|
end
|
82
103
|
|
83
|
-
def
|
84
|
-
|
104
|
+
def common_metadata_path(path)
|
105
|
+
File.join(root, "common", path)
|
106
|
+
end
|
107
|
+
|
108
|
+
def markdown_link(url)
|
109
|
+
url.empty? ? url : format("[%s](%s)", url, url)
|
85
110
|
end
|
86
111
|
end
|
87
112
|
end
|
data/lib/trackler/version.rb
CHANGED
data/tracks/c/config.json
CHANGED
@@ -180,6 +180,15 @@
|
|
180
180
|
"text formatting",
|
181
181
|
"preprocessor (x-macros in test)"
|
182
182
|
]
|
183
|
+
}, {
|
184
|
+
"difficulty": 2,
|
185
|
+
"slug": "series",
|
186
|
+
"topics": [
|
187
|
+
"control-flow (if-statements)",
|
188
|
+
"strings",
|
189
|
+
"text formatting",
|
190
|
+
"memory management"
|
191
|
+
]
|
183
192
|
}],
|
184
193
|
"deprecated": [
|
185
194
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
CFLAGS = -std=c99
|
2
|
+
CFLAGS += -Wall
|
3
|
+
CFLAGS += -Wextra
|
4
|
+
CFLAGS += -pedantic
|
5
|
+
CFLAGS += -Werror
|
6
|
+
|
7
|
+
|
8
|
+
test: tests.out
|
9
|
+
@./tests.out
|
10
|
+
|
11
|
+
clean:
|
12
|
+
rm -f *.o *.out
|
13
|
+
|
14
|
+
tests.out: test/test_series.c src/series.c src/series.h
|
15
|
+
@echo Compiling $@
|
16
|
+
@cc $(CFLAGS) src/series.c test/vendor/unity.c test/test_series.c -o tests.out
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
|
5
|
+
#include "series.h"
|
6
|
+
|
7
|
+
SeriesResults_t series(char *inputText, unsigned int substringLength)
|
8
|
+
{
|
9
|
+
int substringCount = strlen(inputText) - (substringLength - 1);
|
10
|
+
SeriesResults_t results;
|
11
|
+
|
12
|
+
memset(&results, 0, sizeof(results));
|
13
|
+
if ((substringCount > 0) && (substringLength > 0)) {
|
14
|
+
results.substringCount = substringCount;
|
15
|
+
results.substring = malloc(sizeof(char *) * substringCount);
|
16
|
+
for (int index = 0; index < substringCount; index++) {
|
17
|
+
results.substring[index] =
|
18
|
+
malloc(sizeof(char) * (substringLength + 1));
|
19
|
+
sprintf(results.substring[index], "%.*s", substringLength,
|
20
|
+
&inputText[index]);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
return results;
|
24
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#ifndef _SERIES_H
|
2
|
+
#define _SERIES_H
|
3
|
+
|
4
|
+
#define MAX_INPUT_TEXT_LENGTH (8)
|
5
|
+
#define MAX_SERIES_RESULTS (MAX_INPUT_TEXT_LENGTH)
|
6
|
+
#define MAX_SERIES_LENGTH (5)
|
7
|
+
|
8
|
+
// results structure
|
9
|
+
typedef struct SeriesResults {
|
10
|
+
unsigned int substringCount;
|
11
|
+
char **substring; // array of pointers of dimension substringCount
|
12
|
+
} SeriesResults_t;
|
13
|
+
|
14
|
+
// series - routine to split up input text into consecutive substrings of text of a given substringLength
|
15
|
+
//
|
16
|
+
// inputs:
|
17
|
+
// inputText - bounded to MAX_INPUT_TEXT_LENGTH
|
18
|
+
// substringLength - the desired length of substrings that are returned bounded to MAX_SERIES_LENGTH
|
19
|
+
//
|
20
|
+
// outputs:
|
21
|
+
// SeriesResult_t results - structure containing count of the substring and an array of
|
22
|
+
// pointers to the substrings.
|
23
|
+
//
|
24
|
+
// calling routine will free memory associated with each of the substrings and
|
25
|
+
// the pointers to the substrings.
|
26
|
+
SeriesResults_t series(char *inputText, unsigned int substringLength);
|
27
|
+
|
28
|
+
#endif
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include "vendor/unity.h"
|
3
|
+
#include "../src/series.h"
|
4
|
+
|
5
|
+
// helper routines to validate test results
|
6
|
+
static void testSolution(SeriesResults_t * expectedSolution,
|
7
|
+
SeriesResults_t * actualSolution)
|
8
|
+
{
|
9
|
+
// result count correct
|
10
|
+
TEST_ASSERT_EQUAL(expectedSolution->substringCount,
|
11
|
+
actualSolution->substringCount);
|
12
|
+
|
13
|
+
// test each substring...
|
14
|
+
for (unsigned int index = 0; index < expectedSolution->substringCount;
|
15
|
+
index++) {
|
16
|
+
TEST_ASSERT_EQUAL_STRING(expectedSolution->substring[index],
|
17
|
+
actualSolution->substring[index]);
|
18
|
+
free(actualSolution->substring[index]);
|
19
|
+
}
|
20
|
+
if (actualSolution->substringCount) {
|
21
|
+
free(actualSolution->substring);
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
#define EXPAND_SERIES_TEST_CASES_AS_TEST(test_name, inputText, substringLength, expectedResultCount, expectedResultSubstrings)\
|
26
|
+
void test_name(void)\
|
27
|
+
{\
|
28
|
+
char *substrings[] = expectedResultSubstrings;\
|
29
|
+
SeriesResults_t expected = {expectedResultCount, &substrings[0]};\
|
30
|
+
SeriesResults_t actual = series(inputText, substringLength);\
|
31
|
+
testSolution(&expected, &actual);\
|
32
|
+
}\
|
33
|
+
|
34
|
+
#define ASSEMBLE_STRING_ARRAY(...) __VA_ARGS__
|
35
|
+
|
36
|
+
// Test cases
|
37
|
+
#define SERIES_TEST_CASES(ENTRY) \
|
38
|
+
ENTRY(test_slices_of_one, "01234", 1, 5, { ASSEMBLE_STRING_ARRAY("0","1","2","3","4") })\
|
39
|
+
ENTRY(test_slices_of_two, "97867564", 2, 7, { ASSEMBLE_STRING_ARRAY("97","78","86","67","75","56", "64") })\
|
40
|
+
ENTRY(test_slices_of_three, "97867564", 3, 6, { ASSEMBLE_STRING_ARRAY("978","786","867","675","756","564") })\
|
41
|
+
ENTRY(test_slices_of_four, "01234", 4, 2, { ASSEMBLE_STRING_ARRAY("0123","1234") })\
|
42
|
+
ENTRY(test_slices_of_five, "01234", 5, 1, { ASSEMBLE_STRING_ARRAY("01234") })\
|
43
|
+
ENTRY(test_overly_long_slice, "012", 4, 0, { ASSEMBLE_STRING_ARRAY("") })\
|
44
|
+
ENTRY(test_overly_short_slice, "01234", 0, 0, { ASSEMBLE_STRING_ARRAY("") })\
|
45
|
+
|
46
|
+
SERIES_TEST_CASES(EXPAND_SERIES_TEST_CASES_AS_TEST)
|
47
|
+
|
48
|
+
int main(void)
|
49
|
+
{
|
50
|
+
UnityBegin("test/test_word_count.c");
|
51
|
+
|
52
|
+
RUN_TEST(test_slices_of_one);
|
53
|
+
RUN_TEST(test_slices_of_two);
|
54
|
+
RUN_TEST(test_slices_of_three);
|
55
|
+
RUN_TEST(test_slices_of_four);
|
56
|
+
RUN_TEST(test_slices_of_five);
|
57
|
+
RUN_TEST(test_overly_long_slice);
|
58
|
+
RUN_TEST(test_overly_short_slice);
|
59
|
+
|
60
|
+
UnityEnd();
|
61
|
+
|
62
|
+
return 0;
|
63
|
+
}
|