at_coder_friends 0.5.2 → 0.6.0
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 +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
|