at_coder_friends 0.6.2 → 0.6.3

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 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