at_coder_friends 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b8025722558e20114e202913981972cc89885a7f
4
- data.tar.gz: 52975c30a2ac79ca4b459b2466de8c8b244f2296
3
+ metadata.gz: 9a7432316e843545fb879309e242139dc2c0405c
4
+ data.tar.gz: 9e22a2dcde9e98a171ed393365de8fd308957996
5
5
  SHA512:
6
- metadata.gz: 14a7f27ec8de72d1ecafe5e27810ac781aedc23c5604e33005856398250e07617ed803dc6641ad17e45b7de8f8ae09c20fffd9997f64a34e1f4dc3f10beb63d6
7
- data.tar.gz: 0fb4f2e1afb371a7ad49ad69e9ae22fe169856a7268daf4fc78054192bba532181b82e9290d5965d5cf608ea92d85b23bb4c71f976c814adac32e704e4311eeb
6
+ metadata.gz: 70e350831761899ee4178e65f8563cbd328a0b8e70971e4620015d623484c0297fa60a6a5ce447bb349d3b2fa06799b336fb270913a34b8efb857dc97e9dfaa3
7
+ data.tar.gz: ff84c2c7fb80dda6105561d82d94c697c7e5133e91219c9f6530f8e7db083192a5ac8a5148a204fd5740c3cf470d53fd56ac5026b908738f12ccb671d824dd39
data/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  ## master (unreleased)
4
4
 
5
+ ## 0.6.3 (2020-01-05)
6
+ ### Added
7
+ - 'vertical array + matrix' input format support.
8
+ - 'matrix + vertical array' input format support.
9
+ - 'vertically expanded matrices' input format support.
10
+ - 'horizontally expanded matrices' input format support.
11
+ - decimal type support.
12
+ - input data with delimiter(- : /) support.
13
+ - input data of mixed type support.
14
+ - input of N-1 lines support.
15
+
16
+ ### Changed
17
+ - Change template file format to ERB.
18
+ - Template file integration
19
+
20
+ ### Deleted
21
+ - Template file for interactive problems.
22
+ - '### OUTPUT ###' embedding pattern.
23
+ - '### URL ###' embedding pattern.
24
+
5
25
  ## 0.6.2 (2019-11-18)
6
26
  ### Added
7
27
  - add ```check-and-go``` command.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- at_coder_friends (0.6.2)
4
+ at_coder_friends (0.6.3)
5
5
  colorize (~> 0.8.1)
6
6
  launchy (~> 2.4.3)
7
7
  mechanize (~> 2.0)
@@ -41,7 +41,7 @@ GEM
41
41
  net-http-digest_auth (1.4.1)
42
42
  net-http-persistent (3.1.0)
43
43
  connection_pool (~> 2.2)
44
- nokogiri (1.10.4)
44
+ nokogiri (1.10.5)
45
45
  mini_portile2 (~> 2.4.0)
46
46
  ntlm-http (0.1.1)
47
47
  public_suffix (4.0.1)
@@ -198,14 +198,12 @@ ext_settings:
198
198
  ### Settings for RubyBuiltin generator
199
199
  | Setting | Description | Default |
200
200
  |---------|-------------|---------|
201
- |default_template|Source template file path|[/templates/ruby_builtin_default.rb](/templates/ruby_builtin_default.rb)|
202
- |interactive_template|Source template file path for interactive problems|[/templates/ruby_builtin_interactive.rb](/templates/ruby_builtin_interactive.rb)|
201
+ |default_template|Source template file path|[/templates/ruby_builtin.rb.erb](/templates/ruby_builtin.rb.erb)|
203
202
 
204
203
  ### Settings for CxxBuiltin generator
205
204
  | Setting | Description | Default |
206
205
  |---------|-------------|---------|
207
- |default_template|Source template file path|[/templates/cxx_builtin_default.cxx](/templates/cxx_builtin_default.cxx)|
208
- |interactive_template|Source template file path for interactive problems|[/templates/cxx_builtin_interactive.cxx](/templates/cxx_builtin_interactive.cxx)|
206
+ |default_template|Source template file path|[/templates/cxx_builtin.cxx.erb](/templates/cxx_builtin.cxx.erb)|
209
207
 
210
208
  ### Language ID list (2019/09/16)
211
209
 
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module AtCoderFriends
6
+ module Generator
7
+ Attributes = Struct.new(:file_ext, :default_template)
8
+
9
+ # common behavior of generators
10
+ class Base
11
+ attr_reader :cfg, :pbm
12
+
13
+ def initialize(cfg = nil)
14
+ @cfg = cfg || {}
15
+ end
16
+
17
+ def process(pbm)
18
+ pbm.add_src(attrs.file_ext, generate(pbm))
19
+ end
20
+
21
+ def generate(pbm)
22
+ @pbm = pbm
23
+ src = File.read(select_template)
24
+ src = ERB.new(src).result(binding)
25
+ render(src)
26
+ end
27
+
28
+ def select_template
29
+ cfg['default_template'] || attrs.default_template
30
+ end
31
+
32
+ def embed_lines(src, pat, lines)
33
+ re = Regexp.escape(pat)
34
+ src.gsub(
35
+ /^(.*)#{re}(.*)$\n/,
36
+ lines.compact.map { |s| "\\1#{s}\\2\n" }.join
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,96 +2,8 @@
2
2
 
3
3
  module AtCoderFriends
4
4
  module Generator
5
- module CxxBuiltinConstants
6
- ACF_HOME = File.realpath(File.join(__dir__, '..', '..', '..'))
7
- TMPL_DIR = File.join(ACF_HOME, 'templates')
8
- DEFAULT_TMPL = File.join(TMPL_DIR, 'cxx_builtin_default.cxx')
9
- INTERACTIVE_TMPL = File.join(TMPL_DIR, 'cxx_builtin_interactive.cxx')
10
- SCANF_FMTS = [
11
- 'scanf("%<fmt>s", %<addr>s);',
12
- 'REP(i, %<sz1>s) scanf("%<fmt>s", %<addr>s);',
13
- 'REP(i, %<sz1>s) REP(j, %<sz2>s) scanf("%<fmt>s", %<addr>s);'
14
- ].freeze
15
- FMT_FMTS = { number: '%d', string: '%s', char: '%s' }.freeze
16
- ADDR_FMTS = {
17
- single: {
18
- number: '&%<v>s',
19
- string: '%<v>s'
20
- },
21
- harray: {
22
- number: '%<v>s + i',
23
- string: '%<v>s[i]',
24
- char: '%<v>s'
25
- },
26
- varray: {
27
- number: '%<v>s + i',
28
- string: '%<v>s[i]'
29
- },
30
- matrix: {
31
- number: '&%<v>s[i][j]',
32
- string: '%<v>s[i][j]',
33
- char: '%<v>s[i]'
34
- }
35
- }.freeze
36
- DEFAULT_OUTPUT = <<~TEXT
37
- int ans = 0;
38
- printf("%d\\n", ans);
39
- TEXT
40
- BINARY_OUTPUT_FMT = <<~TEXT
41
- bool cond = false;
42
- puts(cond ? "%s" : "%s");
43
- TEXT
44
- end
45
-
46
- # generates C++ source from problem description
47
- class CxxBuiltin
48
- include CxxBuiltinConstants
49
-
50
- attr_reader :cfg, :pbm
51
-
52
- def initialize(cfg = nil)
53
- @cfg = cfg || {}
54
- end
55
-
56
- def process(pbm)
57
- src = generate(pbm)
58
- pbm.add_src(:cxx, src)
59
- end
60
-
61
- def generate(pbm)
62
- @pbm = pbm
63
- src = File.read(select_template)
64
- src = embed_lines(src, '/*** URL ***/', [pbm.url])
65
- src = embed_lines(src, '/*** CONSTS ***/', gen_consts)
66
- src = embed_lines(src, '/*** DCLS ***/', gen_decls)
67
- src = embed_lines(src, '/*** INPUTS ***/', gen_inputs)
68
- embed_lines(src, '/*** OUTPUT ***/', gen_output.split("\n"))
69
- end
70
-
71
- def embed_lines(src, pat, lines)
72
- re = Regexp.escape(pat)
73
- src.gsub(
74
- /^(.*)#{re}(.*)$/,
75
- lines.map { |s| '\1' + s + '\2' }.join("\n")
76
- )
77
- end
78
-
79
- def select_template(interactive = pbm.options.interactive)
80
- interactive ? interactive_template : default_template
81
- end
82
-
83
- def default_template
84
- cfg['default_template'] || DEFAULT_TMPL
85
- end
86
-
87
- def interactive_template
88
- cfg['interactive_template'] || INTERACTIVE_TMPL
89
- end
90
-
91
- def gen_consts(constants = pbm.constants)
92
- constants.map { |c| gen_const(c) }
93
- end
94
-
5
+ # generates C++ constants
6
+ module CxxBuiltinConstGen
95
7
  def gen_const(c)
96
8
  v = cnv_const_value(c.value)
97
9
  if c.type == :max
@@ -107,98 +19,239 @@ module AtCoderFriends
107
19
  .sub(/\b2\^/, '1<<')
108
20
  .gsub(',', "'")
109
21
  end
22
+ end
110
23
 
111
- def gen_decls(inpdefs = pbm.formats)
112
- inpdefs.map { |inpdef| gen_decl(inpdef) }.flatten
113
- end
114
-
24
+ # generates C++ variable declarations
25
+ module CxxBuiltinDeclGen
26
+ TYPE_TBL = {
27
+ number: 'int',
28
+ decimal: 'double',
29
+ string: 'char',
30
+ char: 'char'
31
+ }.tap { |h| h.default = 'int' }
115
32
  def gen_decl(inpdef)
116
- case inpdef.container
117
- when :single
118
- gen_single_decl(inpdef)
119
- when :harray
120
- gen_harray_decl(inpdef)
121
- when :varray
122
- gen_varray_decl(inpdef)
123
- when :matrix
124
- gen_matrix_decl(inpdef)
33
+ if inpdef.components
34
+ inpdef.components.map { |cmp| gen_decl(cmp) }
35
+ else
36
+ case inpdef.container
37
+ when :single
38
+ gen_single_decl(inpdef)
39
+ when :harray
40
+ gen_harray_decl(inpdef)
41
+ when :varray
42
+ gen_varray_decl(inpdef)
43
+ when :matrix, :vmatrix, :hmatrix
44
+ gen_matrix_decl(inpdef)
45
+ end
125
46
  end
126
47
  end
127
48
 
128
49
  def gen_single_decl(inpdef)
129
- names = inpdef.names
130
- case inpdef.item
131
- when :number
50
+ names, cols = inpdef.vars.transpose
51
+ if cols.uniq.size == 1 && cols[0] != :string
52
+ type = TYPE_TBL[cols[0]]
132
53
  dcl = names.join(', ')
133
- "int #{dcl};"
134
- when :string
135
- names.map { |v| "char #{v}[#{v.upcase}_MAX + 1];" }
54
+ "#{type} #{dcl};"
55
+ else
56
+ inpdef.vars.map do |v, item|
57
+ type = TYPE_TBL[item]
58
+ dcl = v
59
+ dcl += "[#{v.upcase}_MAX + 1]" if item == :string
60
+ "#{type} #{dcl};"
61
+ end
136
62
  end
137
63
  end
138
64
 
139
65
  def gen_harray_decl(inpdef)
66
+ type = TYPE_TBL[inpdef.item]
140
67
  v = inpdef.names[0]
141
68
  sz = gen_arr_size(inpdef.size)[0]
142
69
  case inpdef.item
143
- when :number
144
- "int #{v}[#{sz}];"
70
+ when :number, :decimal
71
+ "#{type} #{v}[#{sz}];"
145
72
  when :string
146
- "char #{v}[#{sz}][#{v.upcase}_MAX + 1];"
73
+ "#{type} #{v}[#{sz}][#{v.upcase}_MAX + 1];"
147
74
  when :char
148
- "char #{v}[#{sz} + 1];"
75
+ "#{type} #{v}[#{sz} + 1];"
149
76
  end
150
77
  end
151
78
 
152
79
  def gen_varray_decl(inpdef)
153
- names = inpdef.names
154
80
  sz = gen_arr_size(inpdef.size)[0]
155
- case inpdef.item
156
- when :number
157
- names.map { |v| "int #{v}[#{sz}];" }
158
- when :string
159
- names.map { |v| "char #{v}[#{sz}][#{v.upcase}_MAX + 1];" }
81
+ inpdef.vars.map do |v, item|
82
+ type = TYPE_TBL[item]
83
+ dcl = "#{v}[#{sz}]"
84
+ dcl += "[#{v.upcase}_MAX + 1]" if item == :string
85
+ "#{type} #{dcl};"
160
86
  end
161
87
  end
162
88
 
163
89
  def gen_matrix_decl(inpdef)
164
- v = inpdef.names[0]
165
90
  sz1, sz2 = gen_arr_size(inpdef.size)
166
- case inpdef.item
167
- when :number
168
- "int #{v}[#{sz1}][#{sz2}];"
169
- when :string
170
- "char #{v}[#{sz1}][#{sz2}][#{v.upcase}_MAX + 1];"
171
- when :char
172
- "char #{v}[#{sz1}][#{sz2} + 1];"
91
+ inpdef.vars.map do |v, item|
92
+ type = TYPE_TBL[item]
93
+ dcl = "#{v}[#{sz1}]"
94
+ dcl += item == :char ? "[#{sz2} + 1]" : "[#{sz2}]"
95
+ dcl += "[#{v.upcase}_MAX + 1]" if item == :string
96
+ "#{type} #{dcl};"
173
97
  end
174
98
  end
175
99
 
176
100
  def gen_arr_size(szs)
177
101
  szs.map { |sz| sz.gsub(/([a-z][a-z0-9_]*)/i, '\1_MAX').upcase }
178
102
  end
103
+ end
179
104
 
180
- def gen_inputs(inpdefs = pbm.formats)
181
- inpdefs.map { |inpdef| gen_input(inpdef) }.flatten
182
- end
105
+ # generates C++ input source
106
+ module CxxBuiltinInputGen
107
+ SCANF_FMTS = [
108
+ 'scanf("%<fmt>s", %<addr>s);',
109
+ 'REP(i, %<sz1>s) scanf("%<fmt>s", %<addr>s);',
110
+ 'REP(i, %<sz1>s) REP(j, %<sz2>s) scanf("%<fmt>s", %<addr>s);'
111
+ ].freeze
112
+ SCANF_FMTS_CMB = {
113
+ varray_matrix:
114
+ [
115
+ <<~TEXT,
116
+ REP(i, %<sz1>s) {
117
+ scanf("%<fmt1>s", %<addr1>s);
118
+ scanf("%<fmt2>s", %<addr2>s);
119
+ }
120
+ TEXT
121
+ <<~TEXT
122
+ REP(i, %<sz1>s) {
123
+ scanf("%<fmt1>s", %<addr1>s);
124
+ REP(j, %<sz2>s[i]) scanf("%<fmt2>s", %<addr2>s);
125
+ }
126
+ TEXT
127
+ ],
128
+ matrix_varray:
129
+ [
130
+ <<~TEXT,
131
+ REP(i, %<sz1>s) {
132
+ scanf("%<fmt1>s", %<addr1>s);
133
+ scanf("%<fmt2>s", %<addr2>s);
134
+ }
135
+ TEXT
136
+ <<~TEXT
137
+ REP(i, %<sz1>s) {
138
+ REP(j, %<sz2>s) scanf("%<fmt1>s", %<addr1>s);
139
+ scanf("%<fmt2>s", %<addr2>s);
140
+ }
141
+ TEXT
142
+ ]
143
+ }.tap { |h| h.default = h[:varray_matrix] }
144
+ FMT_FMTS = {
145
+ number: '%d',
146
+ decimal: '%lf',
147
+ string: '%s',
148
+ char: '%s'
149
+ }.tap { |h| h.default = h[:number] }
150
+ SINGLE_ADDR_FMTS = {
151
+ number: '&%<v>s',
152
+ decimal: '&%<v>s',
153
+ string: '%<v>s'
154
+ }.tap { |h| h.default = h[:number] }
155
+ ARRAY_ADDR_FMTS = {
156
+ number: '%<v>s + i',
157
+ decimal: '%<v>s + i',
158
+ string: '%<v>s[i]',
159
+ char: '%<v>s'
160
+ }.tap { |h| h.default = h[:number] }
161
+ MATRIX_ADDR_FMTS = {
162
+ number: '&%<v>s[i][j]',
163
+ decimal: '&%<v>s[i][j]',
164
+ string: '%<v>s[i][j]',
165
+ char: '%<v>s[i]'
166
+ }.tap { |h| h.default = h[:number] }
167
+ ADDR_FMTS = {
168
+ single: SINGLE_ADDR_FMTS,
169
+ harray: ARRAY_ADDR_FMTS,
170
+ varray: ARRAY_ADDR_FMTS,
171
+ matrix: MATRIX_ADDR_FMTS,
172
+ vmatrix: MATRIX_ADDR_FMTS,
173
+ hmatrix: MATRIX_ADDR_FMTS
174
+ }.tap { |h| h.default = h[:single] }
183
175
 
184
- # rubocop:disable Metrics/AbcSize
185
176
  def gen_input(inpdef)
186
- dim = inpdef.size.size - (inpdef.item == :char ? 1 : 0)
187
- scanf = SCANF_FMTS[dim]
177
+ if inpdef.components
178
+ gen_cmb_input(inpdef)
179
+ else
180
+ gen_plain_input(inpdef)
181
+ end
182
+ end
183
+
184
+ def gen_plain_input(inpdef)
185
+ scanf = SCANF_FMTS[inpdef.size.size - (inpdef.item == :char ? 1 : 0)]
188
186
  sz1, sz2 = inpdef.size
189
- fmt = FMT_FMTS[inpdef.item] * inpdef.names.size
190
- addr_fmt = ADDR_FMTS[inpdef.container][inpdef.item]
191
- addr = inpdef.names.map { |v| format(addr_fmt, v: v) }.join(', ')
187
+ fmt, addr = scanf_params(inpdef)
192
188
  format(scanf, sz1: sz1, sz2: sz2, fmt: fmt, addr: addr)
193
189
  end
194
- # rubocop:enable Metrics/AbcSize
195
190
 
196
- def gen_output(vs = pbm.options.binary_values)
197
- if vs
198
- format(BINARY_OUTPUT_FMT, *vs)
199
- else
200
- DEFAULT_OUTPUT
201
- end
191
+ def gen_cmb_input(inpdef)
192
+ scanf = SCANF_FMTS_CMB.dig(
193
+ inpdef.container, inpdef.item == :char ? 0 : 1
194
+ )
195
+ sz1 = inpdef.size[0]
196
+ sz2 = inpdef.size[1].split('_')[0]
197
+ fmt1, addr1, fmt2, addr2 =
198
+ inpdef.components.map { |cmp| scanf_params(cmp) }.flatten
199
+ format(
200
+ scanf,
201
+ sz1: sz1, sz2: sz2,
202
+ fmt1: fmt1, addr1: addr1,
203
+ fmt2: fmt2, addr2: addr2
204
+ ).split("\n")
205
+ end
206
+
207
+ def scanf_params(inpdef)
208
+ [scanf_fmt(inpdef), scanf_addr(inpdef)]
209
+ end
210
+
211
+ def scanf_fmt(inpdef)
212
+ inpdef.vars.map { |(_v, item)| FMT_FMTS[item] }.join
213
+ end
214
+
215
+ def scanf_addr(inpdef)
216
+ inpdef.vars.map do |(v, item)|
217
+ addr_fmt = ADDR_FMTS.dig(inpdef.container, item)
218
+ format(addr_fmt, v: v)
219
+ end.join(', ')
220
+ end
221
+ end
222
+
223
+ # generates C++ source from problem description
224
+ class CxxBuiltin < Base
225
+ include CxxBuiltinConstGen
226
+ include CxxBuiltinDeclGen
227
+ include CxxBuiltinInputGen
228
+
229
+ ACF_HOME = File.realpath(File.join(__dir__, '..', '..', '..'))
230
+ TMPL_DIR = File.join(ACF_HOME, 'templates')
231
+ DEFAULT_TMPL = File.join(TMPL_DIR, 'cxx_builtin.cxx.erb')
232
+ ATTRS = Attributes.new(:cxx, DEFAULT_TMPL)
233
+
234
+ def attrs
235
+ ATTRS
236
+ end
237
+
238
+ def render(src)
239
+ src = embed_lines(src, '/*** CONSTS ***/', gen_consts)
240
+ src = embed_lines(src, '/*** DCLS ***/', gen_decls)
241
+ src = embed_lines(src, '/*** INPUTS ***/', gen_inputs)
242
+ src
243
+ end
244
+
245
+ def gen_consts(constants = pbm.constants)
246
+ constants.map { |c| gen_const(c) }
247
+ end
248
+
249
+ def gen_decls(inpdefs = pbm.formats)
250
+ inpdefs.map { |inpdef| gen_decl(inpdef) }.flatten
251
+ end
252
+
253
+ def gen_inputs(inpdefs = pbm.formats)
254
+ inpdefs.map { |inpdef| gen_input(inpdef) }.flatten
202
255
  end
203
256
  end
204
257
  end
@@ -14,8 +14,13 @@ module AtCoderFriends
14
14
  def process(pbm)
15
15
  generators = ctx.config.dig('generators') || []
16
16
  generators.each do |gen_name|
17
- gen_obj = load_obj(gen_name)
18
- gen_obj.process(pbm)
17
+ begin
18
+ gen_obj = load_obj(gen_name)
19
+ gen_obj.process(pbm)
20
+ rescue StandardError => e
21
+ puts "an error occurred in generator:#{gen_name}."
22
+ p e
23
+ end
19
24
  end
20
25
  end
21
26