at_coder_friends 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +1 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/config/default.yml +3 -0
- data/docs/CONFIGURATION.md +74 -9
- data/lib/at_coder_friends.rb +10 -5
- data/lib/at_coder_friends/cli.rb +2 -5
- data/lib/at_coder_friends/context.rb +4 -0
- data/lib/at_coder_friends/emitter.rb +2 -2
- data/lib/at_coder_friends/generator/cxx_builtin.rb +191 -0
- data/lib/at_coder_friends/generator/main.rb +53 -0
- data/lib/at_coder_friends/generator/ruby_builtin.rb +128 -0
- data/lib/at_coder_friends/parser/binary.rb +39 -0
- data/lib/at_coder_friends/parser/constraints.rb +36 -0
- data/lib/at_coder_friends/parser/{format_parser.rb → input_format.rb} +42 -30
- data/lib/at_coder_friends/parser/interactive.rb +29 -0
- data/lib/at_coder_friends/parser/main.rb +6 -3
- data/lib/at_coder_friends/parser/sample_data.rb +24 -0
- data/lib/at_coder_friends/parser/section_wrapper.rb +49 -0
- data/lib/at_coder_friends/parser/{page_parser.rb → sections.rb} +44 -50
- data/lib/at_coder_friends/problem.rb +40 -24
- data/lib/at_coder_friends/scraping/agent.rb +1 -5
- data/lib/at_coder_friends/scraping/authentication.rb +2 -2
- data/lib/at_coder_friends/scraping/session.rb +1 -1
- data/lib/at_coder_friends/scraping/tasks.rb +2 -6
- data/lib/at_coder_friends/test_runner/base.rb +36 -31
- data/lib/at_coder_friends/test_runner/judge.rb +2 -6
- data/lib/at_coder_friends/test_runner/sample.rb +8 -6
- data/lib/at_coder_friends/version.rb +1 -1
- data/tasks/regression/check_diff.rake +29 -0
- data/tasks/regression/check_parse.rake +56 -0
- data/tasks/regression/regression.rb +67 -0
- data/tasks/regression/section_list.rake +41 -0
- data/tasks/regression/setup.rake +48 -0
- data/templates/cxx_builtin_default.cxx +26 -0
- data/templates/cxx_builtin_interactive.cxx +61 -0
- data/templates/ruby_builtin_default.rb +5 -0
- data/templates/ruby_builtin_interactive.rb +32 -0
- metadata +21 -8
- data/lib/at_coder_friends/cxx_generator.rb +0 -169
- data/lib/at_coder_friends/parser/constraints_parser.rb +0 -26
- data/lib/at_coder_friends/ruby_generator.rb +0 -97
- data/tasks/regression.rake +0 -163
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'regression'
|
4
|
+
|
5
|
+
module AtCoderFriends
|
6
|
+
# tasks for regression
|
7
|
+
module Regression
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def section_list
|
11
|
+
list = local_pbm_list.flat_map do |contest, q, url|
|
12
|
+
page = agent.get(url)
|
13
|
+
%w[h2 h3].flat_map do |tag|
|
14
|
+
page.search(tag).map do |h|
|
15
|
+
{ contest: contest, q: q, text: normalize(h.content) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
list.group_by { |sec| sec[:text] }.each do |k, vs|
|
20
|
+
puts [k, vs.size, vs[0][:contest], vs[0][:q]].join("\t")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def normalize(s)
|
25
|
+
s
|
26
|
+
.tr(' 0-9A-Za-z', ' 0-9A-Za-z')
|
27
|
+
.gsub(/[^一-龠_ぁ-ん_ァ-ヶーa-zA-Z0-9 ]/, '')
|
28
|
+
.gsub(/\d+/, '{N}')
|
29
|
+
.gsub(' ', '')
|
30
|
+
.downcase
|
31
|
+
.strip
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
namespace :regression do
|
37
|
+
desc 'list all section titles'
|
38
|
+
task :section_list do
|
39
|
+
AtCoderFriends::Regression.section_list
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'regression'
|
4
|
+
|
5
|
+
module AtCoderFriends
|
6
|
+
# tasks for regression
|
7
|
+
module Regression
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def setup
|
11
|
+
rmdir_force(PAGES_DIR)
|
12
|
+
rmdir_force(EMIT_ORG_DIR)
|
13
|
+
contest_id_list.each do |contest|
|
14
|
+
setup_by_contest(contest)
|
15
|
+
sleep 3
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def setup_by_contest(contest)
|
20
|
+
scraping_agent(EMIT_ORG_DIR, contest).fetch_all do |pbm|
|
21
|
+
setup_by_pbm(contest, pbm)
|
22
|
+
end
|
23
|
+
rescue StandardError => e
|
24
|
+
p e
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_by_pbm(contest, pbm)
|
28
|
+
html_path = File.join(PAGES_DIR, contest, "#{pbm.q}.html")
|
29
|
+
save_file(html_path, pbm.page.body)
|
30
|
+
pipeline(pbm)
|
31
|
+
rescue StandardError => e
|
32
|
+
p e
|
33
|
+
end
|
34
|
+
|
35
|
+
def save_file(path, content)
|
36
|
+
dir = File.dirname(path)
|
37
|
+
FileUtils.makedirs(dir) unless Dir.exist?(dir)
|
38
|
+
File.binwrite(path, content)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
namespace :regression do
|
44
|
+
desc 'setup regression environment'
|
45
|
+
task :setup do
|
46
|
+
AtCoderFriends::Regression.setup
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
// /*** URL ***/
|
2
|
+
|
3
|
+
#include <cstdio>
|
4
|
+
|
5
|
+
using namespace std;
|
6
|
+
|
7
|
+
#define REP(i,n) for(int i=0; i<(int)(n); i++)
|
8
|
+
#define FOR(i,b,e) for(int i=(b); i<=(int)(e); i++)
|
9
|
+
|
10
|
+
/*** CONSTS ***/
|
11
|
+
|
12
|
+
/*** DCLS ***/
|
13
|
+
|
14
|
+
void solve() {
|
15
|
+
/*** OUTPUT ***/
|
16
|
+
}
|
17
|
+
|
18
|
+
void input() {
|
19
|
+
/*** INPUTS ***/
|
20
|
+
}
|
21
|
+
|
22
|
+
int main() {
|
23
|
+
input();
|
24
|
+
solve();
|
25
|
+
return 0;
|
26
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
// /*** URL ***/
|
2
|
+
|
3
|
+
#include <cstdio>
|
4
|
+
#include <vector>
|
5
|
+
#include <string>
|
6
|
+
|
7
|
+
using namespace std;
|
8
|
+
|
9
|
+
#define DEBUG
|
10
|
+
#define REP(i,n) for(int i=0; i<(int)(n); i++)
|
11
|
+
#define FOR(i,b,e) for(int i=(b); i<=(int)(e); i++)
|
12
|
+
|
13
|
+
//------------------------------------------------------------------------------
|
14
|
+
const int BUFSIZE = 1024;
|
15
|
+
char req[BUFSIZE];
|
16
|
+
char res[BUFSIZE];
|
17
|
+
#ifdef DEBUG
|
18
|
+
char source[BUFSIZE];
|
19
|
+
vector<string> responses;
|
20
|
+
#endif
|
21
|
+
|
22
|
+
void query() {
|
23
|
+
printf("? %s\n", req);
|
24
|
+
fflush(stdout);
|
25
|
+
#ifdef DEBUG
|
26
|
+
sprintf(res, "generate response from source");
|
27
|
+
responses.push_back(res);
|
28
|
+
#else
|
29
|
+
scanf("%s", res);
|
30
|
+
#endif
|
31
|
+
}
|
32
|
+
|
33
|
+
//------------------------------------------------------------------------------
|
34
|
+
/*** CONSTS ***/
|
35
|
+
|
36
|
+
/*** DCLS ***/
|
37
|
+
|
38
|
+
void solve() {
|
39
|
+
printf("! %s\n", ans);
|
40
|
+
fflush(stdout);
|
41
|
+
#ifdef DEBUG
|
42
|
+
printf("query count: %d\n", responses.size());
|
43
|
+
puts("query results:");
|
44
|
+
REP(i, responses.size()) {
|
45
|
+
puts(responses[i].c_str());
|
46
|
+
}
|
47
|
+
#endif
|
48
|
+
}
|
49
|
+
|
50
|
+
void input() {
|
51
|
+
/*** INPUTS ***/
|
52
|
+
#ifdef DEBUG
|
53
|
+
scanf("%s", source);
|
54
|
+
#endif
|
55
|
+
}
|
56
|
+
|
57
|
+
int main() {
|
58
|
+
input();
|
59
|
+
solve();
|
60
|
+
return 0;
|
61
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# ### URL ###
|
2
|
+
|
3
|
+
def query(*args)
|
4
|
+
puts "? #{args.join(' ')}"
|
5
|
+
STDOUT.flush
|
6
|
+
if $DEBUG
|
7
|
+
res = 'generate response from @source'
|
8
|
+
res.tap { |res| @responses << res }
|
9
|
+
else
|
10
|
+
gets.chomp
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
$DEBUG = true
|
15
|
+
|
16
|
+
### DCLS ###
|
17
|
+
|
18
|
+
if $DEBUG
|
19
|
+
@responses = []
|
20
|
+
@source = gets.chomp
|
21
|
+
end
|
22
|
+
|
23
|
+
puts "! #{ans}"
|
24
|
+
STDOUT.flush
|
25
|
+
|
26
|
+
if $DEBUG
|
27
|
+
puts "----------------------------------------"
|
28
|
+
puts "query count: #{@responses.size}"
|
29
|
+
puts "query results:"
|
30
|
+
@responses.each { |res| puts res }
|
31
|
+
puts "----------------------------------------"
|
32
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: at_coder_friends
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nejiko96
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -156,16 +156,21 @@ files:
|
|
156
156
|
- lib/at_coder_friends/cli.rb
|
157
157
|
- lib/at_coder_friends/config_loader.rb
|
158
158
|
- lib/at_coder_friends/context.rb
|
159
|
-
- lib/at_coder_friends/cxx_generator.rb
|
160
159
|
- lib/at_coder_friends/emitter.rb
|
161
160
|
- lib/at_coder_friends/errors.rb
|
162
|
-
- lib/at_coder_friends/
|
163
|
-
- lib/at_coder_friends/
|
161
|
+
- lib/at_coder_friends/generator/cxx_builtin.rb
|
162
|
+
- lib/at_coder_friends/generator/main.rb
|
163
|
+
- lib/at_coder_friends/generator/ruby_builtin.rb
|
164
|
+
- lib/at_coder_friends/parser/binary.rb
|
165
|
+
- lib/at_coder_friends/parser/constraints.rb
|
166
|
+
- lib/at_coder_friends/parser/input_format.rb
|
167
|
+
- lib/at_coder_friends/parser/interactive.rb
|
164
168
|
- lib/at_coder_friends/parser/main.rb
|
165
|
-
- lib/at_coder_friends/parser/
|
169
|
+
- lib/at_coder_friends/parser/sample_data.rb
|
170
|
+
- lib/at_coder_friends/parser/section_wrapper.rb
|
171
|
+
- lib/at_coder_friends/parser/sections.rb
|
166
172
|
- lib/at_coder_friends/path_util.rb
|
167
173
|
- lib/at_coder_friends/problem.rb
|
168
|
-
- lib/at_coder_friends/ruby_generator.rb
|
169
174
|
- lib/at_coder_friends/scraping/agent.rb
|
170
175
|
- lib/at_coder_friends/scraping/authentication.rb
|
171
176
|
- lib/at_coder_friends/scraping/custom_test.rb
|
@@ -177,7 +182,15 @@ files:
|
|
177
182
|
- lib/at_coder_friends/test_runner/sample.rb
|
178
183
|
- lib/at_coder_friends/verifier.rb
|
179
184
|
- lib/at_coder_friends/version.rb
|
180
|
-
- tasks/regression.rake
|
185
|
+
- tasks/regression/check_diff.rake
|
186
|
+
- tasks/regression/check_parse.rake
|
187
|
+
- tasks/regression/regression.rb
|
188
|
+
- tasks/regression/section_list.rake
|
189
|
+
- tasks/regression/setup.rake
|
190
|
+
- templates/cxx_builtin_default.cxx
|
191
|
+
- templates/cxx_builtin_interactive.cxx
|
192
|
+
- templates/ruby_builtin_default.rb
|
193
|
+
- templates/ruby_builtin_interactive.rb
|
181
194
|
homepage: https://github.com/nejiko96/at_coder_friends
|
182
195
|
licenses:
|
183
196
|
- MIT
|
@@ -1,169 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AtCoderFriends
|
4
|
-
# generates C++ source code from definition
|
5
|
-
class CxxGenerator
|
6
|
-
TEMPLATE = <<~TEXT
|
7
|
-
#include <cstdio>
|
8
|
-
|
9
|
-
using namespace std;
|
10
|
-
|
11
|
-
#define REP(i,n) for(int i=0; i<(int)(n); i++)
|
12
|
-
#define FOR(i,b,e) for(int i=(b); i<=(int)(e); i++)
|
13
|
-
|
14
|
-
/*** CONSTS ***/
|
15
|
-
|
16
|
-
/*** DCLS ***/
|
17
|
-
|
18
|
-
void solve() {
|
19
|
-
int ans = 0;
|
20
|
-
printf("%d\\n", ans);
|
21
|
-
}
|
22
|
-
|
23
|
-
void input() {
|
24
|
-
/*** READS ***/
|
25
|
-
}
|
26
|
-
|
27
|
-
int main() {
|
28
|
-
input();
|
29
|
-
solve();
|
30
|
-
return 0;
|
31
|
-
}
|
32
|
-
TEXT
|
33
|
-
|
34
|
-
SCANF_FMTS = [
|
35
|
-
'scanf("%<fmt>s", %<addr>s);',
|
36
|
-
'REP(i, %<sz1>s) scanf("%<fmt>s", %<addr>s);',
|
37
|
-
'REP(i, %<sz1>s) REP(j, %<sz2>s) scanf("%<fmt>s", %<addr>s);'
|
38
|
-
].freeze
|
39
|
-
|
40
|
-
FMT_FMTS = { number: '%d', string: '%s', char: '%s' }.freeze
|
41
|
-
|
42
|
-
ADDR_FMTS = {
|
43
|
-
single: {
|
44
|
-
number: '&%<v>s',
|
45
|
-
string: '%<v>s'
|
46
|
-
},
|
47
|
-
harray: {
|
48
|
-
number: '%<v>s + i',
|
49
|
-
string: '%<v>s[i]',
|
50
|
-
char: '%<v>s'
|
51
|
-
},
|
52
|
-
varray: {
|
53
|
-
number: '%<v>s + i',
|
54
|
-
string: '%<v>s[i]'
|
55
|
-
},
|
56
|
-
matrix: {
|
57
|
-
number: '&%<v>s[i][j]',
|
58
|
-
string: '%<v>s[i][j]',
|
59
|
-
char: '%<v>s[i]'
|
60
|
-
}
|
61
|
-
}.freeze
|
62
|
-
|
63
|
-
def process(pbm)
|
64
|
-
src = generate(pbm.defs, pbm.constraints)
|
65
|
-
pbm.add_src(:cxx, src)
|
66
|
-
end
|
67
|
-
|
68
|
-
def generate(defs, constraints)
|
69
|
-
consts = gen_consts(constraints)
|
70
|
-
dcls = gen_decls(defs)
|
71
|
-
reads = gen_reads(defs)
|
72
|
-
TEMPLATE
|
73
|
-
.sub('/*** CONSTS ***/', consts.join("\n"))
|
74
|
-
.sub('/*** DCLS ***/', dcls.join("\n"))
|
75
|
-
.sub('/*** READS ***/', reads.map { |s| ' ' + s }.join("\n"))
|
76
|
-
end
|
77
|
-
|
78
|
-
def gen_consts(constraints)
|
79
|
-
constraints
|
80
|
-
.select { |c| c.type == :max }
|
81
|
-
.map { |c| "const int #{c.name.upcase}_MAX = #{c.value};" }
|
82
|
-
end
|
83
|
-
|
84
|
-
def gen_decls(defs)
|
85
|
-
defs.map { |inpdef| gen_decl(inpdef) }.flatten
|
86
|
-
end
|
87
|
-
|
88
|
-
def gen_decl(inpdef)
|
89
|
-
case inpdef.container
|
90
|
-
when :single
|
91
|
-
gen_single_decl(inpdef)
|
92
|
-
when :harray
|
93
|
-
gen_harray_decl(inpdef)
|
94
|
-
when :varray
|
95
|
-
gen_varray_decl(inpdef)
|
96
|
-
when :matrix
|
97
|
-
gen_matrix_decl(inpdef)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def gen_single_decl(inpdef)
|
102
|
-
names = inpdef.names
|
103
|
-
case inpdef.item
|
104
|
-
when :number
|
105
|
-
dcl = names.join(', ')
|
106
|
-
"int #{dcl};"
|
107
|
-
when :string
|
108
|
-
names.map { |v| "char #{v}[#{v.upcase}_MAX + 1];" }
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def gen_harray_decl(inpdef)
|
113
|
-
v = inpdef.names[0]
|
114
|
-
sz = gen_arr_size(inpdef.size)[0]
|
115
|
-
case inpdef.item
|
116
|
-
when :number
|
117
|
-
"int #{v}[#{sz}];"
|
118
|
-
when :string
|
119
|
-
"char #{v}[#{sz}][#{v.upcase}_MAX + 1];"
|
120
|
-
when :char
|
121
|
-
"char #{v}[#{sz} + 1];"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def gen_varray_decl(inpdef)
|
126
|
-
names = inpdef.names
|
127
|
-
sz = gen_arr_size(inpdef.size)[0]
|
128
|
-
case inpdef.item
|
129
|
-
when :number
|
130
|
-
names.map { |v| "int #{v}[#{sz}];" }
|
131
|
-
when :string
|
132
|
-
names.map { |v| "char #{v}[#{sz}][#{v.upcase}_MAX + 1];" }
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def gen_matrix_decl(inpdef)
|
137
|
-
v = inpdef.names[0]
|
138
|
-
sz1, sz2 = gen_arr_size(inpdef.size)
|
139
|
-
case inpdef.item
|
140
|
-
when :number
|
141
|
-
"int #{v}[#{sz1}][#{sz2}];"
|
142
|
-
when :string
|
143
|
-
"char #{v}[#{sz1}][#{sz2}][#{v.upcase}_MAX + 1];"
|
144
|
-
when :char
|
145
|
-
"char #{v}[#{sz1}][#{sz2} + 1];"
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def gen_arr_size(szs)
|
150
|
-
szs.map { |sz| sz =~ /\D/ ? "#{sz.upcase}_MAX" : sz }
|
151
|
-
end
|
152
|
-
|
153
|
-
def gen_reads(defs)
|
154
|
-
defs.map { |inpdef| gen_read(inpdef) }.flatten
|
155
|
-
end
|
156
|
-
|
157
|
-
# rubocop:disable Metrics/AbcSize
|
158
|
-
def gen_read(inpdef)
|
159
|
-
dim = inpdef.size.size - (inpdef.item == :char ? 1 : 0)
|
160
|
-
scanf = SCANF_FMTS[dim]
|
161
|
-
sz1, sz2 = inpdef.size
|
162
|
-
fmt = FMT_FMTS[inpdef.item] * inpdef.names.size
|
163
|
-
addr_fmt = ADDR_FMTS[inpdef.container][inpdef.item]
|
164
|
-
addr = inpdef.names.map { |v| format(addr_fmt, v: v) }.join(', ')
|
165
|
-
format(scanf, sz1: sz1, sz2: sz2, fmt: fmt, addr: addr)
|
166
|
-
end
|
167
|
-
# rubocop:enable Metrics/AbcSize
|
168
|
-
end
|
169
|
-
end
|