gettc 1.2.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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +41 -0
  3. data/bin/gettc +63 -0
  4. data/core/lib/topcoder.rb +3 -0
  5. data/core/lib/topcoder/download.rb +89 -0
  6. data/core/lib/topcoder/generate.rb +131 -0
  7. data/core/lib/topcoder/parse.rb +231 -0
  8. data/core/lib/topcoder/print.rb +56 -0
  9. data/core/lib/topcoder/problem.rb +33 -0
  10. data/core/lib/topcoder/signature.rb +55 -0
  11. data/core/lib/topcoder/types.rb +62 -0
  12. data/core/test/topcoder/download_test.rb +29 -0
  13. data/core/test/topcoder/generate_test.rb +31 -0
  14. data/core/test/topcoder/parse_test.rb +104 -0
  15. data/core/test/topcoder/signature_test.rb +52 -0
  16. data/core/test/topcoder/types_test.rb +24 -0
  17. data/dist/config.yml +2 -0
  18. data/dist/include/cpp/engine.rb +90 -0
  19. data/dist/include/cpp/topcoder +212 -0
  20. data/dist/include/haskell/TopCoder.hs +82 -0
  21. data/dist/include/haskell/engine.rb +122 -0
  22. data/dist/include/java/TopCoder.jar +0 -0
  23. data/dist/include/java/engine.rb +207 -0
  24. data/dist/template/bin/runner.sh +113 -0
  25. data/dist/template/data/demo/{examples_d} +0 -0
  26. data/dist/template/data/sys/{systests_d} +0 -0
  27. data/dist/template/prob/images/{images_d} +0 -0
  28. data/dist/template/prob/{name}.html +8 -0
  29. data/dist/template/prob/{name}.md +1 -0
  30. data/dist/template/solve/cpp/Makefile +30 -0
  31. data/dist/template/solve/cpp/{name}.cpp +11 -0
  32. data/dist/template/solve/cpp/{name}Runner.cpp +26 -0
  33. data/dist/template/solve/cpp/{name}Test.cpp +8 -0
  34. data/dist/template/solve/haskell/Makefile +30 -0
  35. data/dist/template/solve/haskell/{name}.hs +7 -0
  36. data/dist/template/solve/haskell/{name}Runner.hs +27 -0
  37. data/dist/template/solve/haskell/{name}Test.hs +10 -0
  38. data/dist/template/solve/java/build.xml +78 -0
  39. data/dist/template/solve/java/{name}.java +9 -0
  40. data/dist/template/solve/java/{name}Runner.java +32 -0
  41. data/dist/template/solve/java/{name}Test.java +8 -0
  42. data/dist/template/util/check/Makefile +5 -0
  43. data/dist/template/util/check/check.cpp +26 -0
  44. metadata +121 -0
@@ -0,0 +1,56 @@
1
+ require 'topcoder/problem'
2
+ require 'bluecloth'
3
+
4
+ module TopCoder
5
+ class Problem
6
+ def to_md
7
+ out = "# [#{@name}](#{@url})\n"
8
+ out << "*#{@source}*\n\n"
9
+
10
+ out << "## Statement\n"
11
+ out << @statement << "\n\n"
12
+
13
+ if not @definitions.empty? then
14
+ out << "## Definitions\n"
15
+ @definitions.each do |k, v| out << "- *#{k}*: `#{v}`\n" end
16
+ out << "\n"
17
+ end
18
+
19
+ if not @notes.empty? then
20
+ out << "## Notes\n"
21
+ @notes.each do |note| out << "- #{note}\n" end
22
+ out << "\n"
23
+ end
24
+
25
+ if not @constraints.empty? then
26
+ out << "## Constraints\n"
27
+ @constraints.each do |constraint|
28
+ out << "- #{constraint}\n"
29
+ end
30
+ out << "\n"
31
+ end
32
+
33
+ if not @examples.empty? then
34
+ out << "## Examples\n"
35
+ @examples.each_index do |i|
36
+ example = @examples[i]
37
+ out << "### Example #{i + 1}\n"
38
+ out << "#### Input\n<c>"
39
+ out << example.input.gsub("\n", '<br />')
40
+ out << "</c>\n"
41
+ out << "#### Output\n<c>"
42
+ out << example.output.gsub("\n", '<br />')
43
+ out << "</c>\n"
44
+ if not example.reason.empty? then
45
+ out << "#### Reason\n#{example.reason}\n\n"
46
+ end
47
+ end
48
+ end
49
+ return out
50
+ end
51
+ def to_html
52
+ bc = BlueCloth.new to_md
53
+ return bc.to_html
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,33 @@
1
+ module TopCoder
2
+ class Case
3
+ attr_accessor :input, :output, :reason
4
+ def initialize
5
+ @input = ''
6
+ @output = ''
7
+ @reason = ''
8
+ end
9
+ end
10
+ class Image
11
+ attr_accessor :name, :content
12
+ def initialize
13
+ @name = ''
14
+ @content = ''
15
+ end
16
+ end
17
+ class Problem
18
+ attr_accessor :name, :url, :source, :statement, :definitions, :notes,
19
+ :constraints, :examples, :systests, :images
20
+ def initialize
21
+ @name = ''
22
+ @url = ''
23
+ @source = ''
24
+ @statement = ''
25
+ @definitions = { }
26
+ @notes = []
27
+ @constraints = []
28
+ @examples = []
29
+ @systests = []
30
+ @images = []
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,55 @@
1
+ require 'topcoder/types'
2
+
3
+ module TopCoder
4
+ class SignatureError < StandardError
5
+ end
6
+ class CannotParseSignature < SignatureError
7
+ attr_accessor :source
8
+ def initialize source, msg = 'Cannot parse signature'
9
+ @source = source
10
+ super "#{msg} (#{source}"
11
+ end
12
+ end
13
+ class InvalidVariableName < SignatureError
14
+ attr_accessor :name
15
+ def initialize name, msg = 'Invalid variable name'
16
+ @name = name
17
+ super "#{msg} (#{name})"
18
+ end
19
+ end
20
+ class Signature
21
+ attr_accessor :type, :name
22
+ def initialize type, name
23
+ @type = type
24
+ @name = name
25
+ end
26
+ end
27
+ def parse_signature str
28
+ str.strip!
29
+ parts = str.split
30
+ raise CannotParseSignature.new str if parts.size != 2
31
+ type = parse_type parts[0]
32
+ name = parts[1]
33
+ if name =~ /^[a-zA-Z_]\w*$/
34
+ return Signature.new type, name
35
+ else
36
+ raise InvalidVariableName.new name
37
+ end
38
+ end
39
+ def parse_method_signature str
40
+ str.strip!
41
+ sigs = []
42
+ parts = str.split '('
43
+ raise CannotParseSignature.new str if parts.size != 2
44
+ sigs << parse_signature(parts[0])
45
+
46
+ str = parts[1]
47
+ raise CannotParseSignature.new str if str[-1] != ')'
48
+ str.chop!
49
+
50
+ parts = str.split ','
51
+ parts.each do |sig| sigs << parse_signature(sig) end
52
+
53
+ return sigs
54
+ end
55
+ end
@@ -0,0 +1,62 @@
1
+ require 'singleton'
2
+
3
+ module TopCoder
4
+ class TypeError < StandardError
5
+ end
6
+ class UnrecognizedType < TypeError
7
+ attr_accessor :type
8
+ def initialize type = nil, msg = 'Not a valid TopCoder type'
9
+ @type = type
10
+ super "#{msg} (#{type})"
11
+ end
12
+ end
13
+ class Type
14
+ def initialize is_object
15
+ @is_object = is_object
16
+ end
17
+ def obj?
18
+ return @is_object
19
+ end
20
+ end
21
+ TBoolean = Type.new false
22
+ TInt = Type.new false
23
+ TLong = Type.new false
24
+ TFloat = Type.new false
25
+ TDouble = Type.new false
26
+ TChar = Type.new false
27
+ TString = Type.new true
28
+ class TArray < Type
29
+ attr_accessor :subtype
30
+ def initialize subtype
31
+ raise UnrecognizedType.new subtype if not subtype.is_a? Type
32
+ @subtype = subtype
33
+ end
34
+ def == ary
35
+ return false if not ary.is_a? TArray
36
+ return @subtype == ary.subtype
37
+ end
38
+ def obj?
39
+ return true
40
+ end
41
+ end
42
+ def parse_type str
43
+ return TArray.new parse_type str[0 .. -3] if str[-2 .. -1] == '[]'
44
+ case str
45
+ when 'boolean'
46
+ return TBoolean
47
+ when 'int'
48
+ return TInt
49
+ when 'long'
50
+ return TLong
51
+ when 'float'
52
+ return TFloat
53
+ when 'double'
54
+ return TDouble
55
+ when 'char'
56
+ return TChar
57
+ when 'String'
58
+ return TString
59
+ end
60
+ raise UnrecognizedType.new str
61
+ end
62
+ end
@@ -0,0 +1,29 @@
1
+ require 'test/unit'
2
+ require 'topcoder/download'
3
+ include TopCoder
4
+
5
+ class DownloadTest < Test::Unit::TestCase
6
+ def setup
7
+ @account = Account.new 'gettc', 'algorithm'
8
+ end
9
+ def test_wrong_account
10
+ assert_raises LoginFailed do
11
+ Downloader.new Account.new 'username', 'password'
12
+ end
13
+ end
14
+ def test_wrong_id
15
+ assert_raises IDNotAvailable do
16
+ (Downloader.new @account).download_problem 1000000
17
+ end
18
+ end
19
+ def test_download_ok
20
+ ids = [10297, 10324, 10329, 10330, 10505, 10685, 10686, 10690, 11264,
21
+ 11266, 11303, 11315, 11322, 11350, 11357, 11419, 8763, 8819, 9995]
22
+ downloader = Downloader.new @account
23
+ 3.times do
24
+ id = ids[rand ids.size]
25
+ html = downloader.download_problem id
26
+ assert_match '<h3>Problem Statement</h3>', html
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ require 'test/unit'
2
+ require 'fileutils'
3
+ require 'tmpdir'
4
+
5
+ require 'topcoder/generate'
6
+ include TopCoder
7
+
8
+ class GenerateTest < Test::Unit::TestCase
9
+ def setup
10
+ @source_d = File.join File.dirname(__FILE__), '../../../dist/template'
11
+ @target_d = File.join Dir.tmpdir, 'gettc'
12
+ FileUtils.mkdir @target_d if not File.directory? @target_d
13
+ @generator = Generator.new @source_d, @target_d
14
+ end
15
+ def test_initialize
16
+ assert_raise SourceDirNotExist do
17
+ Generator.new 'this_directory_must_not_exist', @target_d
18
+ end
19
+ assert_raise TargetDirNotExist do
20
+ Generator.new @source_d, 'this_directory_must_not_exist'
21
+ end
22
+ end
23
+ def test_prob_dir_exists
24
+ prob = Problem.new
25
+ prob.name = 'JustATest'
26
+ prob_d = File.join @target_d, prob.name
27
+ FileUtils.mkdir prob_d if not File.exists? prob_d
28
+ assert_raise ProblemDirExists do @generator.generate prob end
29
+ FileUtils.rmdir prob_d
30
+ end
31
+ end
@@ -0,0 +1,104 @@
1
+ require 'test/unit'
2
+ require 'topcoder/parse'
3
+ include TopCoder
4
+
5
+ class ParseTest < Test::Unit::TestCase
6
+ def setup
7
+ downloader = Downloader.new Account.new 'gettc', 'algorithm'
8
+ @parser = Parser.new downloader
9
+ @datadir = File.join File.dirname(__FILE__), '../../files/stats'
10
+ end
11
+ def get_problem_raw prob
12
+ return File.read File.join @datadir, prob + '.htm'
13
+ end
14
+ def test_indexes
15
+ assert_equal [0, 3], @parser.indexes('abcde', 'bc')
16
+ assert_equal nil, @parser.indexes('abcde', 'f')
17
+ end
18
+ def test_filter
19
+ assert_equal 'Lorem Ipsum', @parser.filter('<xml> Lorem Ipsum </xml> ')
20
+ assert_equal '2^(3)', @parser.filter('2<sup>3</sup>')
21
+ assert_equal '*hi*', @parser.filter(' <b>hi</b>')
22
+ html = <<-END
23
+ <img src=
24
+ "http://www.topcoder.com/contest/problem/CirclesCountry/case1.gif">
25
+ END
26
+ assert_equal '![image](images/case1.gif)', @parser.filter(html)
27
+ end
28
+ def test_PageNumbers
29
+ html = get_problem_raw 'PageNumbers'
30
+ prob = @parser.parse html
31
+ assert_equal 'PageNumbers', prob.name
32
+ assert_equal 5, prob.definitions.size
33
+ assert_equal 1, prob.notes.size
34
+ assert_equal 1, prob.constraints.size
35
+ assert_equal 5, prob.examples.size
36
+ assert_equal 118, prob.systests.size
37
+ assert_equal 0, prob.images.size
38
+ end
39
+ def test_CirclesCountry
40
+ html = get_problem_raw 'CirclesCountry'
41
+ prob = @parser.parse html
42
+ assert_equal 'CirclesCountry', prob.name
43
+ assert_equal 5, prob.definitions.size
44
+ assert_equal 0, prob.notes.size
45
+ assert_equal 7, prob.constraints.size
46
+ assert_equal 5, prob.examples.size
47
+ assert_equal 228, prob.systests.size
48
+ assert_equal 4, prob.images.size
49
+ end
50
+ def test_TheTournamentDivOne
51
+ html = get_problem_raw 'TheTournamentDivOne'
52
+ prob = @parser.parse html
53
+ assert_equal 'TheTournamentDivOne', prob.name
54
+ assert_equal 5, prob.definitions.size
55
+ assert_equal 0, prob.notes.size
56
+ assert_equal 4, prob.constraints.size
57
+ assert_equal 4, prob.examples.size
58
+ assert_equal 0, prob.systests.size
59
+ assert_equal 0, prob.images.size
60
+ end
61
+ def test_FunnyGames
62
+ html = get_problem_raw 'FunnyGames'
63
+ prob = @parser.parse html
64
+ assert_equal 'FunnyGames', prob.name
65
+ assert_equal 5, prob.definitions.size
66
+ assert_equal 0, prob.notes.size
67
+ assert_equal 6, prob.constraints.size
68
+ assert_equal 5, prob.examples.size
69
+ assert_equal 0, prob.systests.size
70
+ assert_equal 0, prob.images.size
71
+ end
72
+ def test_BuildingRoads
73
+ html = get_problem_raw 'BuildingRoads'
74
+ prob = @parser.parse html
75
+ assert_equal 'BuildingRoads', prob.name
76
+ assert_equal 5, prob.definitions.size
77
+ assert_equal 2, prob.notes.size
78
+ assert_equal 10, prob.constraints.size
79
+ assert_equal 5, prob.examples.size
80
+ assert_equal 0, prob.systests.size
81
+ assert_equal 2, prob.images.size
82
+ end
83
+ def test_Acronyms
84
+ html = get_problem_raw 'Acronyms'
85
+ prob = @parser.parse html
86
+ assert_equal 'Acronyms', prob.name
87
+ assert_equal 5, prob.definitions.size
88
+ assert_equal 1, prob.notes.size
89
+ assert_equal 8, prob.constraints.size
90
+ assert_equal 8, prob.examples.size
91
+ assert_equal 39, prob.systests.size
92
+ assert_equal 0, prob.images.size
93
+ end
94
+ def test_BackyardTrees
95
+ html = get_problem_raw 'BackyardTrees'
96
+ prob = @parser.parse html
97
+ assert_equal 'BackyardTrees', prob.name
98
+ assert_equal 5, prob.definitions.size
99
+ assert_equal 0, prob.notes.size
100
+ assert_equal 4, prob.constraints.size
101
+ assert_equal 6, prob.examples.size
102
+ assert_equal 2, prob.images.size
103
+ end
104
+ end
@@ -0,0 +1,52 @@
1
+ require 'test/unit'
2
+ require 'topcoder/signature'
3
+ include TopCoder
4
+
5
+ class SignatureTest < Test::Unit::TestCase
6
+ def test_parse_signature
7
+ assert_raise CannotParseSignature do
8
+ parse_signature 'invalid_signature'
9
+ end
10
+ assert_raise UnrecognizedType do
11
+ parse_signature 'strange_type name'
12
+ end
13
+ assert_raise InvalidVariableName do
14
+ parse_signature 'int not&ok&name'
15
+ end
16
+ assert_raise InvalidVariableName do parse_signature 'int 0zero' end
17
+ sig = parse_signature 'String[] a_valid_nam3'
18
+ assert_equal TArray.new(TString), sig.type
19
+ assert_equal 'a_valid_nam3', sig.name
20
+ end
21
+ def test_parse_method_signature
22
+ assert_raise CannotParseSignature do
23
+ parse_method_signature 'there are no brackets'
24
+ end
25
+ assert_raise CannotParseSignature do
26
+ parse_method_signature 'int main(int main())'
27
+ end
28
+ assert_raise CannotParseSignature do
29
+ parse_method_signature 'int main(oops forget to close bracket'
30
+ end
31
+ method = ' int leastBorders(String[] X , int[] Y, double[] R,'
32
+ method += ' char my_x1, long y1 , float x2, int[][] y2) '
33
+ sigs = parse_method_signature method
34
+ assert_equal 8, sigs.size
35
+ assert_equal TInt, sigs[0].type
36
+ assert_equal 'leastBorders', sigs[0].name
37
+ assert_equal TArray.new(TString), sigs[1].type
38
+ assert_equal 'X', sigs[1].name
39
+ assert_equal TArray.new(TInt), sigs[2].type
40
+ assert_equal 'Y', sigs[2].name
41
+ assert_equal TArray.new(TDouble), sigs[3].type
42
+ assert_equal 'R', sigs[3].name
43
+ assert_equal TChar, sigs[4].type
44
+ assert_equal 'my_x1', sigs[4].name
45
+ assert_equal TLong, sigs[5].type
46
+ assert_equal 'y1', sigs[5].name
47
+ assert_equal TFloat, sigs[6].type
48
+ assert_equal 'x2', sigs[6].name
49
+ assert_equal TArray.new(TArray.new(TInt)), sigs[7].type
50
+ assert_equal 'y2', sigs[7].name
51
+ end
52
+ end
@@ -0,0 +1,24 @@
1
+ require 'test/unit'
2
+ require 'topcoder/types'
3
+ include TopCoder
4
+
5
+ class TypesTest < Test::Unit::TestCase
6
+ def test_parse_type
7
+ assert_raise UnrecognizedType do array = TArray.new 123 end
8
+ assert_raise UnrecognizedType do type = parse_type '' end
9
+ assert_raise UnrecognizedType do type = parse_type ' ' end
10
+ assert_raise UnrecognizedType do type = parse_type '[]' end
11
+ assert_raise UnrecognizedType do type = parse_type 'vector' end
12
+ assert_raise UnrecognizedType do type = parse_type 'vector[]' end
13
+ assert_equal TBoolean, parse_type('boolean')
14
+ assert_equal TInt, parse_type('int')
15
+ assert_equal TLong, parse_type('long')
16
+ assert_equal TFloat, parse_type('float')
17
+ assert_equal TDouble, parse_type('double')
18
+ assert_equal TChar, parse_type('char')
19
+ assert_equal TString, parse_type('String')
20
+ assert_equal TArray.new(TBoolean), parse_type('boolean[]')
21
+ assert_equal TArray.new(TInt), parse_type('int[]')
22
+ assert_equal TArray.new(TArray.new(TString)), parse_type('String[][]')
23
+ end
24
+ end