Repository navigation
Expand file tree
/
Copy pathcpp-worker.js
More file actions
506 lines (485 loc) · 123 KB
/
Copy pathcpp-worker.js
File metadata and controls
506 lines (485 loc) · 123 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
(()=>{var G={versao:"76a681ed29d6",arquivos:{clang:{partes:[{url:"cpp/clang-1.json",bytes:8666737},{url:"cpp/clang-2.json",bytes:5372217}],bytes:31214472,gzip:10529111,sha1:"67e021dcca3f"},lld:{partes:[{url:"cpp/lld-1.json",bytes:8666735},{url:"cpp/lld-2.json",bytes:283815}],bytes:19490094,gzip:6712811,sha1:"3e9dcba6918e"},sysroot:{partes:[{url:"cpp/sysroot-1.json",bytes:2271779}],bytes:8642560,gzip:1703779,sha1:"4221a59f18b7"}},memfs:{url:"cpp/memfs.wasm",bytes:345442}};var no=`// Cobra Code — suporte de execução ligado a todo programa C++ do curso (compilado uma vez, ao iniciar).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <__debug>
// Canal com o executor (JavaScript): relógio, relatórios dos testes, entradas e captura de saída.
extern "C" int __cobra_canal(int op, const char* dados, int tamanho);
// Esvazia os buffers de saída. O executor chama antes de entregar uma entrada (cin/scanf), para a pergunta
// aparecer antes do que foi digitado, e quando o programa para por erro ou por tempo.
extern "C" void __cobra_flush(void) {
fflush(stdout);
fflush(stderr);
}
// Saída com buffer de linha, como num terminal de verdade (cout e cerr aparecem na ordem certa).
__attribute__((constructor(101))) static void __cobra_inicio(void) {
setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
__cobra_canal(9, 0, 0);
}
// Verificações do libc++ (compilado com _LIBCPP_DEBUG=0): front()/back()/pop_back() de vector ou string
// vazio, *opt de optional vazio, *p ou p-> de unique_ptr/shared_ptr vazio, v.at(i) fora do limite... Cada caso
// para numa função com nome próprio; o executor lê o nome na pilha de chamadas e explica o erro em português
// (diagnosticos.js). v[i] e s[i] continuam sem conferir o índice, como o curso ensina (remendo no build_cpp.py).
extern "C" {
__attribute__((noinline, noreturn)) void __cobra_erro_indice_vector(void) { __builtin_trap(); }
__attribute__((noinline, noreturn)) void __cobra_erro_indice_string(void) { __builtin_trap(); }
__attribute__((noinline, noreturn)) void __cobra_erro_vazio(void) { __builtin_trap(); }
__attribute__((noinline, noreturn)) void __cobra_erro_optional_vazio(void) { __builtin_trap(); }
__attribute__((noinline, noreturn)) void __cobra_erro_ponteiro_vazio(void) { __builtin_trap(); }
__attribute__((noinline, noreturn)) void __cobra_erro_biblioteca(void) { __builtin_trap(); }
}
// v.at(i) / s.at(i) fora do limite (remendo dos cabeçalhos no build_cpp.py): manda o índice e o tamanho ao executor.
void __cobra_indice_vector(unsigned long i, unsigned long n) noexcept {
__cobra_canal(10, (const char*)i, (int)n);
__cobra_erro_indice_vector();
}
void __cobra_indice_string(unsigned long i, unsigned long n) noexcept {
__cobra_canal(10, (const char*)i, (int)n);
__cobra_erro_indice_string();
}
static bool __cobra_tem(const char* msg, const char* trecho) { return msg && strstr(msg, trecho) != NULL; }
static void __cobra_verificacao(const std::__libcpp_debug_info& info) {
const char* m = info.__msg_;
if (__cobra_tem(m, "disengaged")) __cobra_erro_optional_vazio();
if (__cobra_tem(m, "null dereference")) __cobra_erro_ponteiro_vazio(); // remendo do build_cpp.py
if (__cobra_tem(m, "empty")) __cobra_erro_vazio();
__cobra_erro_biblioteca();
}
_LIBCPP_BEGIN_NAMESPACE_STD
__libcpp_debug_function_type __libcpp_debug_function = __cobra_verificacao;
_LIBCPP_END_NAMESPACE_STD
// Usado só se o aluno não escreveu main(): avisa o executor, que explica o problema.
extern "C" __attribute__((weak)) int main(int argc, char** argv) {
(void)argc;
(void)argv;
__cobra_canal(2, 0, 0);
return 0;
}
`;var _e=new TextEncoder,io=new TextDecoder,be=class extends Error{constructor(t){super("exit "+t),this.codigo=t}},lo="8.0.1",at=["-isysroot","/","-internal-isystem","/include/c++/v1","-internal-isystem","/include","-internal-isystem","/lib/clang/8.0.1/include"],Ne=["-disable-free",...at,"-std=c++17","-O0","-Wall","-fdiagnostics-show-option","-fno-threadsafe-statics","-mthread-model","single","-ferror-limit","12","-fmessage-length","0","-ftemplate-backtrace-limit","4","-D_LIBCPP_DEBUG=0"],rt=["-debug-info-kind=line-tables-only","-dwarf-version=4"],st=8*1024*1024,nt=256*1024*1024,ve={iostream:["iostream"]},uo="o4",xe=class{constructor({clang:t,lld:o,memfs:a,sysroot:r}){this.mClang=t,this.mLld=o,this.mMemfs=a,this.sysroot=r,this.pch={},this.ferramentaMem=null,this.bufSaida=[]}iniciar(){let t=this,o=()=>new Uint8Array(t.ferramentaMem.buffer),a=()=>new DataView(t.ferramentaMem.buffer),r={memfs_log(){},abort(){throw new Error("memfs abort")},host_write(n,c,l,u){let f=a(),m=0;for(let d=0;d<l;d++){let i=f.getUint32(c+8*d,!0),p=f.getUint32(c+8*d+4,!0);t.bufSaida.push(o().slice(i,i+p)),m+=p}return f.setUint32(u,m,!0),0},host_read(n,c,l,u){return a().setUint32(u,0,!0),0},copy_out(n,c,l){o().set(new Uint8Array(t.memfs.exports.memory.buffer,c,l),n)},copy_in(n,c,l){new Uint8Array(t.memfs.exports.memory.buffer,n,l).set(o().subarray(c,c+l))}};this.memfs=new WebAssembly.Instance(this.mMemfs,{env:r}),this.memfs.exports.init(),this.temIostreamO=!1,this._untar(this.sysroot),this.sysroot=null,this.escrever("/cobra/cobra.imports",`__cobra_canal
`),this.escrever("/cobra/rt.cpp",no);let s=this.clang(["-emit-obj",...Ne,"-o","/cobra/rt.o","-x","c++","/cobra/rt.cpp"]);if(s.codigo!==0)throw new Error(`não consegui compilar o suporte de execução:
`+s.texto)}_mem(){return new Uint8Array(this.memfs.exports.memory.buffer)}_caminho(t){let o=_e.encode(t.replace(/^\/+/,""));return this._mem().set(o,this.memfs.exports.GetPathBuf()),o.length}escrever(t,o){let a=typeof o=="string"?_e.encode(o):o,r=this._caminho(t),s=this.memfs.exports.AddFileNode(r,a.length);this._mem().set(a,this.memfs.exports.GetFileNodeAddress(s))}diretorio(t){let o=this._caminho(t);this.memfs.exports.AddDirectoryNode(o)}ler(t){let o=this._caminho(t),a=this.memfs.exports.FindNode(o),r=this.memfs.exports.GetFileNodeAddress(a),s=this.memfs.exports.GetFileNodeSize(a);return this._mem().slice(r,r+s)}_untar(t){let o=0,a=(r,s)=>io.decode(t.subarray(r,s)).replace(/\0.*$/s,"");for(;o+512<=t.length;){let r=a(o,o+100);if(!r)break;let s=a(o+345,o+500),n=parseInt(a(o+124,o+136).trim()||"0",8),c=String.fromCharCode(t[o+156]),l=(s&&a(o+257,o+263)==="ustar"?s+"/":"")+r;o+=512,c==="5"?this.diretorio(l.replace(/\/$/,"")):(c==="0"||c==="\0")&&(this.escrever(l,t.subarray(o,o+n)),l==="lib/wasm32-wasi/cobra-iostream.o"&&(this.temIostreamO=!0)),o+=Math.ceil(n/512)*512}this.diretorio("cobra")}_rodar(t,o){this.bufSaida=[];let a=o.map(i=>_e.encode(i+"\0")),r=this,s=()=>new Uint8Array(r.ferramentaMem.buffer),n=()=>new DataView(r.ferramentaMem.buffer),c={...this.memfs.exports,proc_exit(i){throw new be(i)},environ_sizes_get(i,p){let _=n();return _.setUint32(i,0,!0),_.setUint32(p,0,!0),0},environ_get(){return 0},args_sizes_get(i,p){let _=n();return _.setUint32(i,a.length,!0),_.setUint32(p,a.reduce((h,v)=>h+v.length,0),!0),0},args_get(i,p){let _=n();for(let h of a)_.setUint32(i,p,!0),i+=4,s().set(h,p),p+=h.length;return 0},random_get(i,p){let _=s();for(let h=0;h<p;h++)_[i+h]=Math.random()*256|0;return 0},clock_time_get(i,p,_){return n().setBigUint64(_,BigInt(Math.round(Date.now()*1e6)),!0),0},poll_oneoff(){return 52},sched_yield(){return 0}},l=new WebAssembly.Instance(t,{wasi_unstable:c});this.ferramentaMem=l.exports.memory;let u=0;try{l.exports._start()}catch(i){i instanceof be?u=i.codigo:(u=1,this.bufSaida.push(_e.encode(`
(o compilador falhou: ${i&&i.message})
`)))}finally{this.ferramentaMem=null}let f=this.bufSaida.reduce((i,p)=>i+p.length,0),m=new Uint8Array(f),d=0;for(let i of this.bufSaida)m.set(i,d),d+=i.length;return this.bufSaida=[],{codigo:u,texto:io.decode(m)}}clang(t){return this._rodar(this.mClang,["clang","-cc1",...t])}lld(t){return this._rodar(this.mLld,["wasm-ld",...t])}escolherPch(t){let o=it(t),a=null;for(let[r,s]of Object.entries(ve))s.every(n=>o.has(n))&&(!a||s.length>ve[a].length)&&(a=r);return a}prepararPch(t){if(this.pch[t]!==void 0)return this.pch[t];let o=`/cobra/pch_${t}.hpp`,a=`/cobra/pch_${t}.pch`;this.escrever(o,ve[t].map(s=>`#include <${s}>
`).join(""));let r=this.clang(["-emit-pch",...Ne,"-o",a,"-x","c++-header",o]);return this.pch[t]=r.codigo===0?a:null,this.pch[t]}bytesPch(t){return this.pch[t]?this.ler(this.pch[t]):null}carregarPch(t,o){let a=`/cobra/pch_${t}.pch`;this.escrever(`/cobra/pch_${t}.hpp`,ve[t].map(r=>`#include <${r}>
`).join("")),this.escrever(a,o),this.pch[t]=a}compilar(t,{arquivo:o="/cobra/main.cpp",objeto:a="/cobra/main.o",pchDe:r=null}={}){this.escrever(o,t);let s=[],n=this.escolherPch(r??t);n&&this.pch[n]&&s.push("-include-pch",this.pch[n]);let c=f=>["-emit-obj",...Ne,...rt,...f,"-main-file-name","main.cpp","-o",a,"-x","c++",o],l=this.clang(c(s)),u=s.length>0;return u&&l.codigo!==0&&/PCH file|precompiled header|\.pch/i.test(l.texto)&&(this.pch[n]=null,l=this.clang(c([])),u=!1),{ok:l.codigo===0,texto:co(l.texto),objeto:a,pch:u?n:null}}ligar(t,{saida:o="/cobra/prog.wasm",iostream:a=!1}={}){let r=a&&this.temIostreamO?["/lib/wasm32-wasi/cobra-iostream.o"]:[],s=this.lld(["--no-threads","-z",`stack-size=${st}`,"--stack-first",`--max-memory=${nt}`,"--allow-undefined-file=/cobra/cobra.imports","--export=__cobra_flush","-L/lib/wasm32-wasi","/lib/wasm32-wasi/crt1.o",...r,...t,"/cobra/rt.o","-lc","-lc++","-lc++abi","/lib/clang/8.0.1/lib/wasi/libclang_rt.builtins-wasm32.a","-o",o]);return{ok:s.codigo===0,texto:co(s.texto),wasm:s.codigo===0?this.ler(o):null}}};function co(e){return e.replace(/\/cobra\//g,"")}function it(e){let t=new Set,o=e.replace(/^\uFEFF/,"");for(;;){o=o.replace(/^(\s+|\/\/[^\n]*|\/\*[\s\S]*?\*\/)+/,"");let a=/^#[ \t]*include[ \t]*<([\w./+-]+)>[ \t]*(\/\/[^\n]*)?(\n|$)/.exec(o);if(!a)break;t.add(a[1]),o=o.slice(a[0].length)}return t}function A(e,t){let o=0,a=0,r;do r=e[t++],o+=(r&127)*2**a,a+=7;while(r&128);return[o,t]}function ct(e,t,o=32){let a=0n,r=0n,s;do s=e[t++],a|=BigInt(s&127)<<r,r+=7n;while(s&128);return r<BigInt(o+7)&&s&64&&(a-=1n<<r),[a,t]}function D(e,t){for(;e[t++]&128;);return t}function I(e){let t=[];do{let o=e%128;e=Math.floor(e/128),e&&(o|=128),t.push(o)}while(e);return t}function lt(e){let t=[];for(let o=0;o<5;o++){let a=e&127;e>>>=7,o<4&&(a|=128),t.push(a)}return t}var ne=new TextDecoder;function mo(e){if(e[0]!==0||e[1]!==97||e[2]!==115||e[3]!==109)throw new Error("não é WebAssembly");let t=[],o=8;for(;o<e.length;){let a=o,r=e[o++],s;[s,o]=A(e,o);let n={id:r,inicio:a,ini:o,fim:o+s,nome:""};if(r===0){let c,l;[c,l]=A(e,o),n.nome=ne.decode(e.subarray(l,l+c)),n.dados=l+c}t.push(n),o+=s}return t}var po=new Set;for(let e=40;e<=62;e++)po.add(e);function ut(e,t,o){switch(t){case 2:case 3:case 4:return D(e,o);case 12:case 13:case 16:case 32:case 33:case 34:case 35:case 36:case 37:case 38:case 210:return D(e,o);case 14:{let a;[a,o]=A(e,o);for(let r=0;r<=a;r++)o=D(e,o);return o}case 17:return o=D(e,o),D(e,o);case 28:{let a;return[a,o]=A(e,o),o+a}case 63:case 64:case 208:return o+1;case 65:case 66:return D(e,o);case 67:return o+4;case 68:return o+8;case 252:{let a;return[a,o]=A(e,o),a<=7?o:a===8?(o=D(e,o),o+1):a===9||a===13||a===15||a===16||a===17?D(e,o):a===10?o+2:a===11?o+1:a===12||a===14?(o=D(e,o),D(e,o)):-1}default:return po.has(t)?(o=D(e,o),D(e,o)):t<=1||t===5||t===11||t===15||t===26||t===27||t>=69&&t<=196||t===209?o:-1}}function fo(e,{modulo:t="env",nome:o="__cobra_canal",global:a="__cobra_orc",inicial:r=2e4}={}){let s=mo(e),n=x=>s.find(q=>q.id===x),c=n(1),l=n(2),u=n(3),f=n(6),m=n(7),d=n(10);if(!c||!u||!d)return null;let i,p,_;[_,i]=A(e,c.ini);let h=0,v=0,g=-1;if(l){[p,i]=A(e,l.ini);for(let x=0;x<p;x++){let q;[q,i]=A(e,i);let T=ne.decode(e.subarray(i,i+q));i+=q,[q,i]=A(e,i);let j=ne.decode(e.subarray(i,i+q));i+=q;let U=e[i++];if(U===0)[,i]=A(e,i),T===t&&j===o&&(g=h),h++;else if(U===1){i++;let M=e[i++];[,i]=A(e,i),M&1&&([,i]=A(e,i))}else if(U===2){let M=e[i++];[,i]=A(e,i),M&1&&([,i]=A(e,i))}else if(U===3)i+=2,v++;else return null}}if(g<0)return null;let b;[b]=A(e,u.ini);let y=0;f&&([y]=A(e,f.ini));let C=v+y,E=h+b,w=_,z=I(C),re=I(E),fe=Uint8Array.from([35,...z,65,127,106,36,...z,35,...z,69,4,64,16,...re,11]),L=fe.length,he;if([he,i]=A(e,d.ini),he!==b)return null;let Zo=[],Jo=0,ze=[],ca=x=>{Zo.push(x),Jo+=x.length};for(let x=0;x<he;x++){let q;[q,i]=A(e,i);let T=i,j=i+q,U=T,M;[M,U]=A(e,U);for(let V=0;V<M;V++)[,U]=A(e,U),U++;let J=[U],k=U;for(;k<j;){let V=e[k++],Ie=ut(e,V,k);if(Ie<0)return null;V===3&&J.push(Ie),k=Ie}if(k!==j)return null;ze.push({ini:T,fim:j,insercoes:J}),i=j}let Qe=Uint8Array.from([0,65,0,65,0,65,0,16,...I(g),26,11]),Ye=[],Te=0,X=x=>{Ye.push(x),Te+=x.length};X(Uint8Array.from(I(he+1)));let Ko=[];for(let x of ze){let q=x.fim-x.ini+L*x.insercoes.length;X(Uint8Array.from(lt(q))),x.novoIniRel=Te;let T=x.ini;for(let j of x.insercoes)X(e.subarray(T,j)),X(fe),T=j;X(e.subarray(T,x.fim)),Ko.push(x.novoIniRel)}X(Uint8Array.from(I(Qe.length))),X(Qe);function ge(x,q){let T,j;[T,j]=A(e,x.ini);let U=e.subarray(j,x.fim);return se([Uint8Array.from(I(T+1)),U,Uint8Array.from(q)])}let Qo=ge(c,[96,0,0]),Yo=ge(u,I(w)),eo=[127,1,65,...dt(r),11],oo=f?ge(f,eo):se([Uint8Array.from([1]),Uint8Array.from(eo)]),to=new TextEncoder().encode(a),ao=[...I(to.length),...to,3,...I(C)],ro=m?ge(m,ao):se([Uint8Array.from([1]),Uint8Array.from(ao)]),je=[e.subarray(0,8)],Pe=8,Me=0,Z=(x,q)=>{let T=Uint8Array.from([x,...I(q.length)]);return je.push(T,q),Pe+=T.length+q.length,Pe-q.length},De=!1,Re=!1;for(let x of s)if(!De&&!f&&x.id>6&&x.id!==0&&(Z(6,oo),De=!0),!Re&&!m&&x.id>7&&x.id!==0&&(Z(7,ro),Re=!0),x.id===1)Z(1,Qo);else if(x.id===3)Z(3,Yo);else if(x.id===6)Z(6,oo),De=!0;else if(x.id===7)Z(7,ro),Re=!0;else if(x.id===10)Me=Z(10,se(Ye,Te));else{let q=e.subarray(x.inicio,x.fim);je.push(q),Pe+=q.length}let et=se(je),so=ze.map(x=>({novoIni:Me+x.novoIniRel,novoFim:Me+x.novoIniRel+(x.fim-x.ini)+L*x.insercoes.length,ini:x.ini,insercoes:x.insercoes}));return{bytes:et,mapa:{tamanhoInsercao:L,original(x){let q=0,T=so.length-1;for(;q<=T;){let j=q+T>>1,U=so[j];if(x<U.novoIni)T=j-1;else if(x>=U.novoFim)q=j+1;else{let M=x-U.novoIni,J=U.ini;for(let k of U.insercoes){let V=k-J;if(M<V)return J+M;if(M-=V,J=k,M<L)return k;M-=L}return J+M}}return x}},global:a}}function dt(e){let t=[],o=!0;for(;o;){let a=e&127;e>>=7,e===0&&!(a&64)||e===-1&&a&64?o=!1:a|=128,t.push(a)}return t}function se(e,t){t===void 0&&(t=e.reduce((r,s)=>r+s.length,0));let o=new Uint8Array(t),a=0;for(let r of e)o.set(r,a),a+=r.length;return o}function ho(e){let t=mo(e),o=t.find(n=>n.id===10),a=t.find(n=>n.id===0&&n.nome===".debug_line"),r=[];if(o&&a)try{mt(e,a.dados,a.fim,r)}catch{}r.sort((n,c)=>n[0]-c[0]||(c[3]?1:0)-(n[3]?1:0));let s=o?o.ini:0;return{vazia:r.length===0,procurar(n){let c=n-s,l=0,u=r.length-1,f=-1;for(;l<=u;){let p=l+u>>1;r[p][0]<=c?(f=p,l=p+1):u=p-1}if(f<0)return null;let[,m,d,i]=r[f];if(i)return null;if(d===0){for(let p=f+1;p<r.length&&p<f+12&&!r[p][3];p++)if(r[p][2]>0&&r[p][1]===m)return{arquivo:m,linha:r[p][2]};return null}return{arquivo:m,linha:d}}}}function mt(e,t,o,a){let r=new DataView(e.buffer,e.byteOffset,e.byteLength),s=t;for(;s<o;){let n=r.getUint32(s,!0);s+=4;let c=s+n,l=r.getUint16(s,!0);s+=2;let u=r.getUint32(s,!0);s+=4;let f=s+u,m=e[s++];l>=4&&s++;let d=e[s++],i=e[s++]<<24>>24,p=e[s++],_=e[s++],h=[];for(let w=1;w<_;w++)h.push(e[s++]);for(;e[s]!==0;)for(;e[s++]!==0;);s++;let v=[null];for(;e[s]!==0;){let w=s;for(;e[w]!==0;)w++;v.push(ne.decode(e.subarray(s,w))),s=w+1,[,s]=A(e,s),[,s]=A(e,s),[,s]=A(e,s)}s=f;let g=0,b=1,y=1,C=()=>{g=0,b=1,y=1},E=(w=!1)=>a.push([g,v[b]||"?",y,w]);for(;s<c;){let w=e[s++];if(w>=_){let z=w-_;g+=Math.floor(z/p)*m,y+=i+z%p,E()}else if(w===0){let z;[z,s]=A(e,s);let re=e[s],fe=s+z;if(re===1)E(!0),C();else if(re===2)g=r.getUint32(s+1,!0);else if(re===3){let L=s+1;for(;e[L]!==0;)L++;v.push(ne.decode(e.subarray(s+1,L)))}s=fe}else if(w===1)E();else if(w===2){let z;[z,s]=A(e,s),g+=z*m}else if(w===3){let z;[z,s]=ct(e,s),y+=Number(z)}else if(w===4)[b,s]=A(e,s);else if(w===5)[,s]=A(e,s);else if(w===8)g+=Math.floor((255-_)/p)*m;else if(w===9)g+=r.getUint16(s,!0),s+=2;else if(!(w===6||w===7||w===10||w===11))for(let z=0;z<(h[w-1]||0);z++)[,s]=A(e,s)}s=c}}var pt=/^(.+?):(\d+):(\d+): (fatal error|error|warning|note): (.*)$/,bo=new TextEncoder,xo=new TextDecoder;function $e(e){let t=[],o=null,a=[];for(let s of String(e||"").split(`
`)){let n=pt.exec(s);if(n){o={arquivo:n[1],linha:+n[2],coluna:+n[3],nivel:n[4],msg:n[5],linhas:[s],incluido:a},a=[],t.push(o);continue}let c=/^In file included from (.+?):(\d+):/.exec(s);if(c){a.push({arquivo:c[1],linha:+c[2]}),o=null;continue}if(/^\d+ (errors?|warnings?)( and \d+ (errors?|warnings?))? generated\.$/.test(s)){o=null;continue}let l=/^(fatal error|error|warning): (.*)$/.exec(s);if(l){o={arquivo:null,linha:null,coluna:null,nivel:l[1],msg:l[2],linhas:[s],incluido:[]},t.push(o);continue}o&&s!==""&&o.linhas.push(s)}let r=[];for(let s of t)s.nivel==="note"&&r.length?r[r.length-1].notas.push(s):(s.notas=[],r.push(s));return r.filter(s=>!/^too many errors emitted/.test(s.msg))}var ft=e=>e.nivel==="error"||e.nivel==="fatal error",Fe=e=>e.filter(ft),K=e=>e==="main.cpp"||/^teste\d+\.cpp$/.test(e||""),$o={cout:"iostream",cin:"iostream",endl:"iostream",cerr:"iostream",clog:"iostream",vector:"vector",string:"string",getline:"string",to_string:"string",stoi:"string",stol:"string",stoll:"string",stod:"string",stof:"string",map:"map",multimap:"map",set:"set",multiset:"set",unordered_map:"unordered_map",unordered_set:"unordered_set",list:"list",deque:"deque",queue:"queue",priority_queue:"queue",stack:"stack",array:"array",pair:"utility",make_pair:"utility",tuple:"tuple",make_tuple:"tuple",optional:"optional",nullopt:"optional",variant:"variant",sort:"algorithm",reverse:"algorithm",max_element:"algorithm",min_element:"algorithm",find:"algorithm",find_if:"algorithm",count:"algorithm",count_if:"algorithm",unique:"algorithm",fill:"algorithm",accumulate:"numeric",iota:"numeric",sqrt:"cmath",pow:"cmath",fabs:"cmath",floor:"cmath",ceil:"cmath",round:"cmath",trunc:"cmath",sin:"cmath",cos:"cmath",tan:"cmath",log:"cmath",log10:"cmath",exp:"cmath",hypot:"cmath",setprecision:"iomanip",setw:"iomanip",setfill:"iomanip",stringstream:"sstream",istringstream:"sstream",ostringstream:"sstream",rand:"cstdlib",srand:"cstdlib",exit:"cstdlib",time:"ctime",unique_ptr:"memory",make_unique:"memory",shared_ptr:"memory",make_shared:"memory",function:"functional",INT_MAX:"climits",INT_MIN:"climits",LLONG_MAX:"climits",numeric_limits:"limits",printf:"cstdio",scanf:"cstdio",puts:"cstdio",strlen:"cstring",strcmp:"cstring",strcpy:"cstring",isdigit:"cctype",isalpha:"cctype",toupper:"cctype",tolower:"cctype",ifstream:"fstream",ofstream:"fstream",basic_string:"string",basic_stringstream:"sstream",basic_istringstream:"sstream",basic_ostringstream:"sstream",basic_ifstream:"fstream",basic_ofstream:"fstream"},ht=new Set(Object.keys($o).filter(e=>!/^[A-Z]/.test(e)&&!/^(printf|scanf|puts|strlen|strcmp|strcpy)$/.test(e))),gt=/^(sort|stable_sort|reverse|count|count_if|find|find_if|max_element|min_element|accumulate|unique|fill|all_of|any_of|none_of|for_each|transform|remove|remove_if|binary_search|lower_bound|upper_bound)$/;function ie(e){let t=$o[e];if(!t)return null;let o=ht.has(e)?` e escreva std::${e} (ou use using namespace std;)`:"";return`Para usar ${e}, coloque #include <${t}> no começo do arquivo${o}.`}function $(e){return String(e).replace(/ \(aka '[^']*'\)/g,"").replace(/std::__2::/g,"std::").replace(/std::basic_string<char(, std::char_traits<char>, std::allocator<char> )?>/g,"std::string").replace(/basic_string<char(, char_traits<char>, allocator<char> )?>/g,"std::string").replace(/, std::allocator<[^<>]*(<[^<>]*>)?[^<>]*> >/g,">").replace(/, std::default_delete<[^<>]*> >/g,">").replace(/, std::less<[^<>]*(<[^<>]*>)?[^<>]*>/g,"").replace(/std::basic_ostream<char(, std::char_traits<char> )?>/g,"std::ostream").replace(/std::basic_istream<char(, std::char_traits<char> )?>/g,"std::istream")}var O="'([^']+)'(?: \\(aka '([^']+)'\\))?",P=(e,t)=>$(e[t+1]||e[t]),R=(e,t)=>new RegExp(e,t),_t=e=>String(e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),vt="Neste curso, o C++ roda com as exceções desligadas: throw, try e catch não compilam aqui. Trate os erros com valores de retorno (um bool, um código de erro ou std::optional).";function N(e){return e.linhas.length>1?e.linhas[1]:""}function yo(e){let t=N(e);if(!e.coluna||!t)return"";let o=xo.decode(bo.encode(t).subarray(0,Math.max(0,e.coluna-1)));return t.slice(o.length)}function wo(e){let t=/^(<<=|>>=|<<|>>|<=|>=|==|!=|&&|\|\||[-+*/%<>&|^!=?])/.exec(yo(e));return t?t[1]:null}function Ao(e){let t=yo(e),o=0;for(;o<t.length&&!"({;=".includes(t[o]);)o++;if(o>=t.length)return null;if(t[o]==="="&&/^=\s*\{/.test(t.slice(o)))o=t.indexOf("{",o);else if(t[o]===";"||t[o]==="=")return"";let a=0,r=o,s=null;for(;r<t.length;r++){let n=t[r];if(s){n==="\\"?r++:n===s&&(s=null);continue}if(n==='"'||n==="'"){s=n;continue}if("({[".includes(n))a++;else if(")}]".includes(n)&&--a===0)break}return t.slice(o+1,r).trim()}function qo(e){let t=[],o=0,a="",r=null;for(let s=0;s<e.length;s++){let n=e[s];if(r){a+=n,n==="\\"?a+=e[++s]||"":n===r&&(r=null);continue}if(n==='"'||n==="'"){r=n,a+=n;continue}if("({[<".includes(n)&&o++,")}]>".includes(n)&&o--,n===","&&o===0){t.push(a.trim()),a="";continue}a+=n}return a.trim()&&t.push(a.trim()),t}function bt(e){return/^"(?:[^"\\]|\\.)*"$/.test(e)?"string":/^'(?:[^'\\]|\\.)+'$/.test(e)?"char":/^[-+]?\d+$/.test(e)?"int":/^[-+]?(\d+\.\d*|\.\d+)(e[-+]?\d+)?f?$/i.test(e)?"double":/^(true|false)$/.test(e)?"bool":null}var Y=e=>/^(const )?char \[\d+\]$|^(const )?char \*$|std::string|basic_string/.test(e),Le=e=>/^(const )?(unsigned |signed )?(int|double|float|long|long long|short|char|bool|size_t|long double)$/.test(e),Co=e=>/ostream|ostringstream|stringstream|basic_ostream/.test(e),xt=e=>/istream|istringstream|basic_istream/.test(e)&&!/ostream/.test(e),ee=e=>/iterator|__wrap_iter|__tree_|__map_|__hash_/.test(e),Eo=e=>/^(const )?(std::)?(vector|map|set|list|deque|array|pair|unordered_map|unordered_set|multimap|multiset|queue|stack|optional|tuple)</.test(e),F=e=>!Y(e)&&!Le(e)&&!Eo(e)&&!ee(e)&&!/std::|^void$|nullptr_t|\*|\[/.test(e),Uo=e=>/^(const )?char \[\d+\]$/.test(e)?"um texto entre aspas":/^(const )?char$/.test(e)?"um caractere (char)":e;function $t(e,t){let o=P(e,1),a=P(e,3),r=wo(t)||"?",s=n=>n.replace(/^const /,"");if(Co(o)){if(r==="<")return"Para mostrar valores com cout, use << (dois sinais de menor): cout << x;";if(r==="<<"){if(a==="void")return"O valor à direita de << é void: a função chamada não devolve nada, então não há o que mostrar. Chame a função sozinha (sem cout) ou faça ela devolver um valor.";if(Eo(a))return`cout não sabe mostrar um ${s(a).replace(/<.*/,"")} inteiro de uma vez. Percorra com um for e mostre item por item: for (auto x : v) cout << x << " ";`;if(F(a)){let n=s(a);return`cout não sabe mostrar um ${n}. Mostre os campos (cout << obj.nome;) ou crie a função ostream& operator<<(ostream& os, const ${n}& obj) { os << ...; return os; }, fora da classe.`}return"Esse valor não pode ser mostrado com << (os tipos aparecem entre parênteses na mensagem)."}return`Sem parênteses, o C++ junta o cout << ... primeiro e depois tenta aplicar ${r} ao cout. Coloque a conta ou a comparação entre parênteses: cout << (a ${r==="?"?"==":r} b);`}if(xt(o))return r===">"?"Para ler um valor com cin, use >> (dois sinais de maior): cin >> x;":r===">>"&&Y(a)?"cin >> guarda o que foi digitado numa variável — não num texto entre aspas: cin >> nome;":r===">>"&&F(a)?`cin não sabe ler um ${s(a)} inteiro: leia os campos um por um (cin >> obj.nome >> obj.idade;).`:"Operação inválida com cin. Para ler um valor, use >> e uma variável: cin >> x;";if(o==="void"&&r==="<<")return"O lado esquerdo de << é void. Se você escreveu um operator<<, ele precisa devolver o stream (ostream& ... { ...; return os; }) para dar para encadear: cout << a << endl;";if(F(o)||F(a)){let n=s(F(o)?o:a),l=["==","!=","<",">","<=",">="].includes(r)?`bool operator${r}(const ${n}& outro) const { ... }`:`${n} operator${r}(const ${n}& outro) const { ... }`;return`${n} não tem o operador ${r}: o C++ não sabe fazer ${r} com objetos que você criou. Compare ou calcule campo por campo, ou crie o operador na classe: ${l}`}return/^(const )?char \[\d+\]$/.test(o)&&/^(const )?char \[\d+\]$/.test(a)&&r==="+"?'Não dá para juntar dois textos entre aspas com + (eles ainda não são string). Faça pelo menos um lado ser string — string("Olá, ") + "mundo" — ou use uma variável string: nome + "!".':Y(o)&&/^(const )?char$/.test(a)||/^(const )?char$/.test(o)&&Y(a)?`Você comparou um texto (string) com um caractere (char). Para comparar textos, use aspas duplas: s == "a". Para comparar um caractere do texto, use aspas simples: s[0] == 'a'.`:Y(o)&&Le(a)||Le(o)&&Y(a)?'Não dá para juntar texto e número com +. Use std::to_string(numero) para virar texto, ou mostre em partes: cout << "Idade: " << idade;':(ee(o)||ee(a))&&(/nullptr_t|^int$/.test(o)||/nullptr_t|^int$/.test(a))?"find (e begin, end...) devolvem um iterador, não um ponteiro nem um número. Para saber se achou, compare com o fim: if (m.find(chave) != m.end()).":"Essa operação não existe entre esses dois tipos (eles aparecem entre parênteses na mensagem). Confira os tipos dos valores."}function Be(e,t,o=null){let a=$(e),r=$(t),s=o?N(o):"";if(/^(const )?char$/.test(a)&&/char \[\d+\]|char \*/.test(r))return"Aspas duplas criam um texto; um caractere (char) vai entre aspas simples: 'a'.";if(/std::string/.test(a)&&/^(const )?char$/.test(r))return'Aspas simples criam um caractere (char); um texto (string) vai entre aspas duplas: "a". (Para virar string, use string(1, c).)';if(/^(const )?char$/.test(a)&&/std::string/.test(r))return"Uma string não cabe num char. Para pegar um caractere do texto, use a posição: s[0] (ou s.at(0)).";if(/char \[\d+\]|const char \*|std::string/.test(r)&&/^(int|double|float|long|bool)$/.test(a))return`Você tentou guardar um texto (${r}) numa variável do tipo ${a}. Texto entre aspas não é número: para converter, use std::stoi / std::stod.`;if(/std::string/.test(a)&&/^(int|double|float|long|bool)$/.test(r))return`Você tentou guardar um número (${r}) numa std::string. Para converter, use std::to_string(numero).`;if(/unique_ptr/.test(r)&&/ \*$/.test(a))return"Para pegar o ponteiro guardado num unique_ptr (sem tirar a posse dele), use .get(): Item* p = dono.get();";if(/optional/.test(r))return"Um optional pode estar vazio. Confira antes com has_value() (ou if (opt)) e pegue o valor com *opt ou opt.value().";if(ee(r)&&ee(a))return"O contêiner aqui é const, então o iterador também precisa ser (const_iterator). O mais simples é deixar o C++ decidir: auto it = v.begin();";if(ee(r)){if(/\bfind(_if)?\s*\(/.test(s))return"find devolve um iterador (uma posição dentro do contêiner), não o valor nem o índice. Guarde com auto it = find(...); confira se achou com it != v.end(); depois, *it é o valor e it - v.begin() é o índice.";let n=(/\b((?:max|min)_element)\s*\(/.exec(s)||[])[1]||"max_element";return`${n} devolve um iterador (uma posição dentro do contêiner), não o valor. Para o valor, use * na frente: *${n}(v.begin(), v.end()). Para o índice, subtraia o começo: ${n}(v.begin(), v.end()) - v.begin().`}return/ \*$/.test(a)&&a.replace(/ \*$/,"")===r.replace(/^const /,"")?"Um ponteiro guarda um endereço. Para guardar o endereço de uma variável, use &: ponteiro = &variavel;":/ \*$/.test(r)&&r.replace(/ \*$/,"")===a.replace(/^const /,"")?"Isso é um ponteiro (um endereço). Para pegar o valor que ele aponta, use *: int valor = *p;":`Os tipos não combinam: era esperado ${a}, mas o valor é ${r}.`}function Ve(e,t=""){for(let o of e.notas){if(/\(the implicit (copy|move|default) constructor\)/.test(o.msg))continue;let a=/deduced conflicting types for parameter '(\w+)' \('(.+?)' vs\. '(.+?)'\)/.exec(o.msg);if(a)return`Os valores passados têm tipos diferentes (${$(a[2])} e ${$(a[3])}), mas o template usa o mesmo ${a[1]} para os dois. Passe valores do mesmo tipo (ex.: 1.0 em vez de 1) ou diga o tipo: ${t||"funcao"}<${$(a[3])}>(...).`;if(a=/requires (?:(?:at least |at most )?(\d+) arguments?|(single) argument(?: '\w+')?|no arguments), but (\d+|no) (?:arguments? )?(?:was|were) provided/.exec(o.msg),a){let r=a[1]||(a[2]?"1":"0"),s=a[3]==="no"?"0":a[3];return`A versão que existe pede ${r} argumento${r==="1"?"":"s"}, mas a chamada passou ${s}.`}if(a=R(`no known conversion from ${O} to ${O} for (\\d+)(?:st|nd|rd|th) argument`).exec(o.msg),a)return`O ${a[5]}º argumento deveria ser ${P(a,3)}, mas é ${P(a,1)}.`;if(a=/expects an l-value for (\d+)(?:st|nd|rd|th) argument/.exec(o.msg),a)return`O ${a[1]}º parâmetro é uma referência (tipo&): ele precisa de uma variável, não de um valor solto como 5 ou a + b. Se a função não muda o valor, use const tipo& ou passe por valor.`}return""}function yt(e,t){let o=Ao(t);if(gt.test(e)&&o!==null&&qo(o).length===1)return`${e} recebe o começo e o fim do intervalo, e não o contêiner: ${e}(v.begin(), v.end()${e==="count"||e==="find"?", valor":""}).`;let a=Ve(t,e);return`A função ${e} existe, mas não aceita esses argumentos. ${a||"Confira a quantidade e os tipos dos valores passados."}`.trim()}function Oo(e,t){let o=Ve(t,e);if(e==="push_back"||e==="insert"||e==="push"){let a=R(`no known conversion from ${O} to ${O}`).exec(t.notas.map(r=>r.msg).join(`
`));if(a){let r=P(a,3).replace(/^const /,"").replace(/&$/,"").trim();return`${e} recebeu um valor de outro tipo: o contêiner guarda ${r}, e o valor é ${Uo(P(a,1))}. Confira o tipo entre < > na declaração (ex.: vector<string> para textos).`}}return`O método ${e} existe, mas não aceita esses argumentos. ${o||"Confira a quantidade e os tipos dos valores."}`.trim()}function wt(e,t){let o=R(`${_t(t)}\\s*\\(([^)]*)\\)`).exec(N(e));return o?`${t}(${o[1].trim()})`:`${t}(...)`}function So(e,t,{teste:o=!1}={}){let a=$(e).replace(/^(struct|class) /,"").replace(/ \[\d*\]$/,"").replace(/<.*$/,"").replace(/^.*::/,""),r=/ \[\d*\]$/.test(e),s=K(t.arquivo)?t:t.notas.find(g=>K(g.arquivo)&&/requested here/.test(g.msg)),n=t.notas.map(g=>/but (no|\d+) (?:arguments? )?(?:was|were) provided/.exec(g.msg)).find(Boolean),c=!!n&&(n[1]==="no"||n[1]==="0"),l=r?` (${a} arr[N] cria N objetos assim)`:t.notas.some(g=>/::(vector|resize)' requested here/.test(g.msg))?` (vector<${a}> v(n) e v.resize(n) criam objetos assim)`:"",u=c||r?"":s?Ao(s):null,f=u?qo(u):[],m=u===null?null:`${a}(${u})`,d=o?"o teste":"o código",i=t.notas.filter(g=>/^candidate constructor/.test(g.msg)&&!/\(the implicit/.test(g.msg)&&K(g.arquivo));if(i.length){let g=i.slice(0,3).map(E=>`${wt(E,a)} (linha ${E.linha})`),b=g.length===1?`o construtor que existe é ${g[0]}`:`os construtores que existem são ${g.join(", ")}`;if(u==="")return`Para criar ${a} sem passar valores${l}, a classe precisa de um construtor sem parâmetros, mas ${b}. Passe os valores que ele pede ou crie também um construtor sem parâmetros: ${a}() { ... } (ou ${a}() = default; se os atributos já têm valor inicial).`;let y="",C=i.length===1&&R(`no known conversion from ${O} to ${O} for (\\d+)(?:st|nd|rd|th) argument`).exec(i[0].msg);return C&&(y=` O ${C[5]}º valor deveria ser ${P(C,3).replace(/^const /,"").replace(/ ?&$/,"")}, mas é ${Uo(P(C,1))}.`),`Nenhum construtor de ${a} recebe esses valores${m?`: ${d} tentou ${m}`:""}, e ${b}.${y} `+(o?"Confira os parâmetros pedidos na tarefa (quantidade, ordem e tipos).":"Confira a quantidade, a ordem e os tipos dos valores — ou crie um construtor com esses parâmetros.")}let p=f.map(bt),_=f.length&&p.every(Boolean)?` — aqui, algo como ${a}(${p.join(", ")})`:"",v=t.notas.some(g=>/\bstruct\b/.test(N(g)))&&f.length&&!o?` Uma struct simples, sem construtor, também pode ser criada com chaves: ${a} obj{${u}};`:"";return`${a} ainda não tem um construtor que receba valores${m?`, então ${m}${o?" (usado pelo teste)":""} não funciona`:""}. Crie ${o?"o construtor pedido na tarefa":"o construtor dentro da classe"}, com um parâmetro para cada valor${_}, e guarde os valores nos atributos.${v}`}function At(e){let t=e.notas.find(s=>/hidden overloaded virtual function/.test(s.msg)),o=t&&/function '([^']+)'/.exec(t.msg),a="",r;if(t&&(r=/different qualifiers \((.+?) vs (.+?)\)/.exec(t.msg))){let s=r[1].replace(/'/g,""),n=r[2].replace(/'/g,"");a=s==="const"?`Na base, ${o?o[1]:"o método"} é const, e aqui falta o const: ...() const override.`:n==="const"?`Na base, ${o?o[1]:"o método"} não é const, e aqui ele é.`:"A diferença está no const."}else t&&(r=R(`type mismatch at (\\d+)(?:st|nd|rd|th) parameter \\(${O} vs ${O}\\)`).exec(t.msg))?a=`O ${r[1]}º parâmetro é ${P(r,2)} na base e ${P(r,4)} aqui.`:t&&(r=/different number of parameters \((\d+) vs (\d+)\)/.exec(t.msg))?a=`Na base, o método tem ${r[1]} parâmetro(s); aqui, ${r[2]}.`:t&&/different return type/.test(t.msg)&&(a="O tipo de retorno é diferente do da base.");return`Este método tem override, mas a assinatura não é igual à do método virtual da base, então ele não substitui o da base. ${a} `+"Para substituir, repita exatamente o nome, os parâmetros e o const.".replace(/\s+/g," ")}function zo(e,t,o,{teste:a=!1}={}){let r=o.notas.find(c=>/declared here/.test(c.msg)&&c.arquivo==="main.cpp"),s=r?` (a declaração está na linha ${r.linha})`:"";return`${a?`O teste usa um objeto const ${$(t)} e chama ${e}(), mas um objeto const só pode chamar métodos marcados como const.`:`Aqui o objeto é const (por exemplo, um parâmetro const ${$(t)}&), e um objeto const só pode chamar métodos marcados como const.`} Se ${e}() só consulta o objeto, sem mudar nada, marque-o const${s}: escreva const depois dos parênteses — ${e}(...) const { ... }.`}function go(e,t){let o=$(e),a=[...new Set(t.notas.map(l=>/unimplemented pure virtual method '(\w+)' in '(.+?)'/.exec(l.msg)).filter(Boolean).map(l=>l[1]+"()"))];if(/^parameter type/.test(t.msg))return`Um parâmetro não pode ser uma classe abstrata passada por valor. Receba por referência (const ${o}&) ou por ponteiro.`;let r=a.join(", "),s=t.notas.find(l=>/unimplemented pure virtual method/.test(l.msg)&&l.arquivo==="main.cpp"),n=s?`, linha ${s.linha}`:"",c=a.length>1?`os métodos virtuais puros ${r} (declarados com = 0${n}) não foram implementados`:a.length?`o método virtual puro ${r} (declarado com = 0${n}) não foi implementado`:"ela tem método virtual puro (= 0) sem implementação";return`${o} é uma classe abstrata: ${c} em ${o}, então não dá para criar objetos de ${o}. Se ${o} é a classe base, crie um objeto de uma classe filha. Se ${o} é a filha, implemente ${r||"esses métodos"} nela com exatamente a mesma assinatura da base (inclusive o const) — e marque com override, para o compilador conferir.`}function qt(e,t){let o=$(e);if(/unique_ptr/.test(o)){let a=K(t.arquivo)?N(t):t.notas.filter(u=>K(u.arquivo)&&/requested here/.test(u.msg)).map(N).pop()||"",r=/\bfor\s*\(\s*(?:const\s+)?(?:auto|[\w:]+\s*<[^&:]*>)\s+(\w+)\s*:/.exec(a);if(r)return`Este for copia cada item para ${r[1]}, e unique_ptr não pode ser copiado (só um unique_ptr é dono do objeto). Percorra por referência: for (auto& ${r[1]} : ...) — ou const auto& se for só ler.`;let s=/^\s*(?:class|struct)\s+(\w+)/.exec(a);if(s){let u=s[1];return`${u} guarda unique_ptr, então um ${u} não pode ser copiado (unique_ptr tem um dono só). Procure onde o código copia um ${u} — quase sempre um parâmetro por valor, como void f(${u} x), ou auto y = x; — e use uma referência: ${u}& (ou const ${u}&).`}if(t.notas.some(u=>/::vector' requested here/.test(u.msg)))return"Um vector de unique_ptr não pode ser copiado: cada unique_ptr tem um dono só. Use uma referência (auto& outro = v; num parâmetro, const vector<unique_ptr<T>>&) — ou std::move(v) para transferir tudo.";let n=t.notas.some(u=>/passing argument to parameter/.test(u.msg)),c=t.notas.some(u=>/::(push_back|push_front|insert|emplace|emplace_back|push|resize)' requested here/.test(u.msg))||/\.(push_back|push_front|insert|push)\s*\(/.test(N(t)),l="unique_ptr não pode ser copiado: só um unique_ptr é dono do objeto. ";return n?l+"A função recebe o unique_ptr por valor (uma cópia): passe std::move(p) para entregar a posse, ou mude o parâmetro para referência (const unique_ptr<T>&) — ou receba só T& / T*.":c?l+"Para guardar num vector, mova: v.push_back(std::move(p)); — ou crie direto: v.push_back(make_unique<T>(...));":l+"Para passar a posse, use std::move(p) (depois disso, p fica vazio); para só usar o objeto, use uma referência (*p) ou p.get()."}return`${o} não pode ser copiado (a cópia dele foi desativada). Passe por referência (const ${o}&) ou use std::move.`}function Ct(e,t,o){let a=$(t),r=(/(?:^|::)(vector|string|map|set|unordered_map|unordered_set|list|deque|array)\b/.exec(a)||[])[1];return r==="vector"&&e==="length"?"vector não tem length(): o tamanho de um vector é v.size().":r==="vector"&&/^(append|add|push)$/.test(e)?"Para pôr um item no fim de um vector, use v.push_back(x).":r==="vector"&&e==="push_front"?"vector não tem push_front. Para pôr no começo, use v.insert(v.begin(), x) (ou um deque).":(r==="set"||r==="unordered_set")&&/^push/.test(e)?`${r} não tem ${e}: para acrescentar, use s.insert(x).`:(r==="map"||r==="unordered_map")&&/^push/.test(e)?`${r} não tem ${e}: use m[chave] = valor; ou m.insert({chave, valor}).`:/^(map|set|unordered_map|unordered_set)$/.test(r||"")&&e==="contains"?"contains só existe a partir do C++20. Aqui, use m.count(chave) > 0 (ou m.find(chave) != m.end()).":r==="string"&&e==="lenght"?"O certo é length() (ou size()).":`${a} não tem o membro ${e}.${o?` Talvez você quis escrever ${o}.`:" Confira a grafia (maiúsculas contam)."}`}function To(e,t){let o=e[1],a=$(e[3]);if(t.notas.some(c=>/private inheritance/.test(c.msg))){let c=(/class (\w+)\s*:/.exec(N(t.notas.find(l=>/private inheritance/.test(l.msg))))||[])[1];return`A herança está privada: numa class, herdar sem dizer nada é private, e aí tudo o que veio de ${a} fica escondido. Escreva ${c?`class ${c} : public ${a}`:`: public ${a}`}.`}let r=N(t),n=/\b(os|out|saida|stream)\s*<</.test(r)||/\boperator\s*\S+\s*\(/.test(r)?` Se este é um operator<< (ou outra função) fora da classe, declare-o friend dentro de ${a}: friend ostream& operator<<(ostream& os, const ${a}& obj);`:"";return e[2]==="private"?`${o} é privado (private) em ${a}: só os métodos da própria classe podem usá-lo. Use um método público (um getter, por exemplo).${n}`:`${o} é protegido (protected) em ${a}: só a própria classe e as classes filhas podem usá-lo.${n}`}function Et(e){let t="",o=0;for(;o<e.length;){let a=e[o],r=e[o+1];if(a==="/"&&r==="/"){for(;o<e.length&&e[o]!==`
`;)t+=" ",o++;continue}if(a==="/"&&r==="*"){for(t+=" ",o+=2;o<e.length&&!(e[o]==="*"&&e[o+1]==="/");)t+=e[o]===`
`?`
`:" ",o++;o<e.length&&(t+=" ",o+=2);continue}if(a==='"'||a==="'"){for(t+=a,o++;o<e.length&&e[o]!==a&&e[o]!==`
`;)e[o]==="\\"&&e[o+1]!==`
`&&(t+=" ",o++),t+=" ",o++;o<e.length&&e[o]===a&&(t+=a,o++);continue}t+=a,o++}return t}var Ut=/^(int|double|float|char|bool|long|short|unsigned|signed|auto|void|size_t|string|string_view|vector|map|set|multimap|multiset|unordered_map|unordered_set|list|deque|queue|stack|priority_queue|array|pair|tuple|optional|variant|unique_ptr|shared_ptr|function|ostream|istream|ostringstream|istringstream|stringstream|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t)$/;function Ot(e,t){let o=Et(e),a=new Set;for(let d of o.matchAll(/\b(?:class|struct|enum(?:\s+class)?|union)\s+(\w+)/g))a.add(d[1]);for(let d of o.matchAll(/\busing\s+(\w+)\s*=/g))a.add(d[1]);for(let d of o.matchAll(/\btypedef\b[^;]*?(\w+)\s*;/g))a.add(d[1]);for(let d of o.matchAll(/\btemplate\s*<([^>]*)>/g))for(let i of d[1].matchAll(/\b(?:typename|class)\s+(\w+)/g))a.add(i[1]);let r=d=>{let i=d.replace(/^(?:std::)+/,"").replace(/\s*<[\s\S]*$/,"");return Ut.test(i)||a.has(i)},s=d=>{let i=[],p=0;for(let h=0;h<d&&h<o.length;h++){let v=o[h];if(v==="{"){let g=/\b(?:class|struct)\s+(\w+)[^;{}()=]*$/.exec(o.slice(Math.max(0,h-300),h));i.push({classe:g?g[1]:null,pos:h})}else v==="}"?i.pop():v==="("?p++:v===")"&&(p=Math.max(0,p-1))}let _=0;for(;_<i.length&&i[_].classe;)_++;return{pilha:i,parens:p,raiz:_<i.length?i[_].pos:-1,classes:i.map(h=>h.classe).filter(Boolean)}},n=new RegExp("(^|[;{}(,])\\s*(?:(?:const|static|constexpr|unsigned|signed|long|short|inline|virtual|mutable)\\s+)*((?:std::)?[A-Za-z_]\\w*(?:\\s*<[^;{}()]*>)?)\\s*(?:const\\s*)?[&*]*\\s*\\b"+t+"\\s*(=(?!=)|;|\\(|\\[|\\{|,|\\)|:(?!:))","gm"),c=String(e).split(`
`),l=d=>c.slice(0,d-1).reduce((i,p)=>i+p.length+1,0),u=[],f;for(;f=n.exec(o);){if(!r(f[2]))continue;let d=o.lastIndexOf(t,f.index+f[0].length-f[3].length),i=s(d),p=o.slice(0,d).split(`
`).length,_=i.pilha.length?i.pilha[i.pilha.length-1].classe:null,h=i.parens>0&&i.raiz===-1?o.indexOf("{",d):i.raiz;if(u.push({linha:p,raiz:h,classe:_&&i.parens===0?_:null,funcao:f[3]==="("&&i.pilha.length===0&&i.parens===0,metodo:f[3]==="(",texto:c[p-1]||""}),u.length>20)break}return{lista:u,noErro:(d,i)=>{let p=c[d-1]||"",_=xo.decode(bo.encode(p).subarray(0,Math.max(0,(i||1)-1))).length;return s(l(d)+_)}}}function St(e,t){if(!t.fonte||t.arquivo!=="main.cpp"||!t.linha)return null;let{lista:o,noErro:a}=Ot(t.fonte,e),r=o.filter(m=>m.linha!==t.linha);if(!r.length)return null;let s=a(t.linha,t.coluna),n=r.find(m=>m.classe);if(n){if(s.classes.includes(n.classe))return null;let m=n.classe;return`${e} é membro da classe ${m} (linha ${n.linha}), e fora da classe ele só existe dentro dos métodos de ${m}. Se este código é um método definido fora da classe, ponha ${m}:: antes do nome do método — void ${m}::metodo(...) { ... }. Numa função comum, use um objeto: obj.${e}${n.metodo?"()":""}.`}let c=r.find(m=>m.raiz!==-1&&m.raiz!==s.raiz),l=r.filter(m=>m.raiz===-1||m.raiz===s.raiz),u=l.filter(m=>m.linha<t.linha&&m.raiz!==-1);if(u.length){let m=u[u.length-1];return`${e} foi criado na linha ${m.linha}, dentro de um bloco (um for, if, while ou { }) que já terminou: a variável só existe lá dentro. Para usar aqui, crie a variável antes do bloco, no mesmo nível em que ela é usada.`}let f=l.filter(m=>m.linha>t.linha);if(f.length){let m=f[0];if(m.funcao){let d=new RegExp("^\\s*(.*?\\b"+e+"\\s*\\([^)]*\\))").exec(m.texto);return`A função ${e} só aparece mais abaixo (linha ${m.linha}), mas foi usada antes, na linha ${t.linha}. Em C++, uma função precisa ser declarada antes de ser usada: mova a função para cima (antes de quem a chama) — ou deixe-a onde está e coloque só o protótipo lá em cima: ${d?d[1].trim()+";":`tipo ${e}(parâmetros);`}`}return`${e} só é criado mais abaixo (linha ${m.linha}), mas foi usado antes, na linha ${t.linha}. Em C++, uma variável precisa ser criada antes de ser usada: mova a declaração para cima.`}return c?`${e} foi criado em outra função (linha ${c.linha}), e uma variável só existe dentro da função onde foi criada. Para usar o valor aqui, receba-o como parâmetro desta função e mande o valor na chamada.`:null}var zt=[[/^cannot use '(throw|try)' with exceptions disabled/,()=>vt],[/^expected ';' in 'for' statement specifier/,()=>"Dentro do for, as três partes são separadas por ponto e vírgula: for (int i = 0; i < n; i++)."],[/^expected ';' after (?:class|struct)/,()=>"Faltou o ponto e vírgula depois da chave que fecha a classe/struct: struct Ponto { ... };"],[/^expected ';'/,()=>"Faltou o ponto e vírgula (;) no fim do comando. Em C++ todo comando termina com ; — o compilador aponta o lugar logo depois de onde ele faltou (às vezes, o fim da linha de cima)."],[/^use of undeclared identifier '(\w+)'; did you mean 'std::(\w+)'\?/,e=>`${e[1]} mora no espaço de nomes std: escreva std::${e[2]} (ou coloque using namespace std; depois dos #include).`],[/^use of undeclared identifier 'std'/,()=>"O compilador não conhece std: faltou o #include do cabeçalho (por exemplo, #include <iostream> para usar std::cout)."],[/^use of undeclared identifier '(True|False)'/,()=>"Em C++, os valores lógicos são true e false, com letras minúsculas."],[/^use of undeclared identifier '(\w+)'; did you mean '(.+?)'\?/,e=>`O compilador não conhece o nome ${e[1]}. Talvez você quis escrever ${e[2]} (maiúsculas e minúsculas contam).`],[/^use of undeclared identifier '(\w+)'/,(e,t)=>ie(e[1])||St(e[1],t)||`O compilador não conhece o nome ${e[1]}. Você declarou essa variável ou função antes (acima) de usar? Confira a grafia — maiúsculas contam. Se era um texto, faltaram as aspas.`],[/^invalid use of 'this' outside of a non-static member function/,()=>"this só existe dentro dos métodos de uma classe. Se esta função é um método definido fora da classe, escreva o nome da classe na frente: void Conta::depositar(...) { ... }."],[/^unknown type name 'string'/,()=>"string mora no espaço de nomes std: escreva std::string (ou use using namespace std;) e inclua <string> (ou <iostream>)."],[/^unknown type name '(\w+)'/,e=>ie(e[1])||`O compilador não conhece o tipo ${e[1]}. Confira a grafia e se o tipo (struct, classe) foi declarado antes de ser usado.`],[/^no template named '(\w+)'; did you mean 'std::(\w+)'\?/,e=>`${e[1]} mora no espaço de nomes std: escreva std::${e[2]} (ou coloque using namespace std; depois dos #include).`],[/^no (?:template|type|member) named '(\w+)' in namespace 'std'/,e=>ie(e[1])||`std::${e[1]} não existe. Confira a grafia e o #include.`],[/^no template named '(\w+)'/,e=>ie(e[1])||`O compilador não conhece o modelo (template) ${e[1]}.`],[/^implicit instantiation of undefined template '(?:std::(?:__2::)?)?(\w+)/,e=>ie(e[1])||`O tipo ${e[1]} foi usado sem o #include do cabeçalho dele.`],[/^'bits\/stdc\+\+\.h' file not found/,()=>"<bits/stdc++.h> existe só no compilador GCC. Aqui, inclua cada cabeçalho que usar: <iostream>, <vector>, <string>, <algorithm>..."],[/^'(.+)' file not found/,e=>`O cabeçalho <${e[1]}> não existe. Confira o nome (por exemplo <iostream>, <string>, <vector>, <cmath>) — sem .h no fim.`],[/^'main' must return 'int'/,()=>"Em C++, a função principal é sempre int main() (e não void main())."],[R(`^invalid operands to binary expression \\(${O} and ${O}\\)`),$t],[R(`^comparison between pointer and integer \\(${O} and ${O}\\)`),e=>/char/.test(P(e,1))||/char/.test(P(e,3))?"Você comparou um caractere (char) com um texto entre aspas duplas. Para comparar com um caractere, use aspas simples: s[0] == 'a' (ou resposta == 's').":"Você comparou um ponteiro com um número. Confira os tipos dos dois lados."],[/^'this' argument to member function '(\w+)' has type 'const (.+?)', but function is not marked const/,(e,t)=>zo(e[1],e[2],t)],[/^'this' argument to member function '(\w+)' has type '(.+?)', but function is not marked/,e=>`O método ${e[1]} não pode ser chamado neste objeto (${$(e[2])}): confira o const.`],[/^cannot assign to non-static data member within const member function '(\w+)'/,e=>`O método ${e[1]} é const (tem const depois dos parênteses), então não pode mudar os atributos do objeto. Se ele precisa alterar o objeto, tire o const; métodos const são para consultar.`],[/^no matching constructor for initialization of '([^']+)'/,(e,t)=>So(e[1],t)],[/^no matching member function for call to '(\w+)'/,(e,t)=>Oo(e[1],t)],[/^no matching function for call to '([^']+)'/,(e,t)=>yt(e[1],t)],[/^too (many|few) arguments to function call, expected (?:at (?:least|most) )?(\d+), have (\d+)/,e=>`A função pede ${e[2]} argumento(s), mas foi chamada com ${e[3]}. Confira os parâmetros.`],[/^redefinition of '(\w+)'/,e=>`${e[1]} foi declarado duas vezes. Para mudar o valor de uma variável que já existe, não repita o tipo: escreva só ${e[1]} = ...;`],[/^expected '}'/,()=>`Faltou fechar uma chave }. Cada { precisa do seu } — a nota "to match this '{'" mostra qual ficou aberta.`],[/^extraneous closing brace/,()=>"Tem uma chave } sobrando: ela fecha um bloco que não foi aberto. Confira os pares { }."],[/^expected '\)'/,()=>"Faltou fechar um parêntese. Cada ( precisa do seu )."],[/^expected '\]'/,()=>"Faltou fechar um colchete ]."],[/^expected '\(' after '(if|while|for|switch)'/,e=>`Depois de ${e[1]} vem a condição entre parênteses: ${e[1]} (x > 0) { ... }`],[/^missing terminating '(["'])' character/,e=>e[1]==='"'?'Um texto começou com aspas " e não terminou. Feche as aspas na mesma linha.':"Um caractere começou com aspas simples ' e não terminou."],[/^character too large for enclosing character literal type|^multi-character character constant/,()=>`Aspas simples ' ' são para UM caractere (char), como 'a'. Para texto, use aspas duplas: "texto".`],[/^expected expression/,(e,t)=>{let o=N(t).trim();return/^else\b/.test(o)?"Esse else não tem um if logo antes. Se o if tem mais de um comando, eles precisam estar entre chaves { }.":"O compilador esperava um valor ou uma conta aqui. Confira se não sobrou um operador, uma vírgula ou um parêntese."}],[/^cannot initialize a variable of type '(.+?)' with an [lr]value of type 'void'/,()=>"A função chamada não devolve nada (é void), então não dá para guardar o resultado numa variável."],[R(`^cannot initialize (?:a variable|a parameter|return object) of type ${O} with an [lr]value of type ${O}`),(e,t)=>Be(e[2]||e[1],e[4]||e[3],t)],[R(`^no viable conversion from (?:returned value of type )?${O} to (?:function return type )?${O}`),(e,t)=>Be(e[4]||e[3],e[2]||e[1],t)],[R(`^assigning to ${O} from incompatible type ${O}`),(e,t)=>Be(e[2]||e[1],e[4]||e[3],t)],[/^no viable overloaded operator\[\] for type 'const (?:std::(?:__2::)?)?(map|unordered_map)/,e=>`Este ${e[1]} é const (por exemplo, recebido como const ${e[1]}<...>&), e nele [] não pode ser usado, porque [] cria a chave quando ela não existe. Use .at(chave) quando a chave com certeza existe, ou .find(chave) / .count(chave) para conferir antes.`],[/^call to (?:implicitly-)?deleted (?:copy )?constructor of '([^']+)'/,(e,t)=>qt(e[1],t)],[/^object of type '([^']+)' cannot be assigned because its copy assignment operator is implicitly deleted/,e=>/unique_ptr/.test(e[1])?"unique_ptr não pode ser copiado com =: só um unique_ptr é dono do objeto. Para passar a posse, use b = std::move(a); (a fica vazio).":`${$(e[1])} não pode ser copiado com =.`],[/^no viable overloaded '='/,()=>"Os tipos dos dois lados do = não combinam."],[/^cannot assign to variable '(\w+)' with const-qualified type/,e=>`${e[1]} é const: o valor não pode mudar depois de criado.`],[/^cannot assign to (?:non-static data member|return value).*const/,()=>"Esse valor é const (ou está num método const) e não pode ser alterado."],[/^expression is not assignable/,()=>"Do lado esquerdo do = precisa ficar uma variável. (Para comparar, use ==.)"],[/^array type '(.+?)' is not assignable/,()=>"Um array não pode receber outro de uma vez com =. Mude os elementos um por um (a[0] = 1;) ou use um std::vector (ou std::array), que aceitam =."],[/^cannot cast '(.+?)' to its private base class '(?:const )?(.+?)'/,e=>`${$(e[1])} herda de ${$(e[2])} de forma privada. Numa class, a herança é private se você não disser nada: escreva class ${$(e[1])} : public ${$(e[2])}.`],[/^'(\w+)' is a (private|protected) member of '(.+?)'/,To],[/^constructor for '(.+?)' must explicitly initialize the base class '(.+?)' which does not have a default constructor/,e=>`O construtor de ${$(e[1])} precisa chamar o construtor de ${$(e[2])} na lista de inicialização, porque ${$(e[2])} não tem construtor sem parâmetros: ${$(e[1])}(...) : ${$(e[2])}(valores) { ... }`],[/^constructor for '(.+?)' must explicitly initialize the member '(\w+)' which does not have a default constructor/,(e,t)=>{let o=t.notas.find(r=>/^'(.+?)' declared here/.test(r.msg)),a=o?$(/^'(.+?)'/.exec(o.msg)[1]):"";return`O atributo ${e[2]} é um objeto${a?` de ${a}`:""}, que não tem construtor sem parâmetros. Passe os valores dele na lista de inicialização do construtor: ${$(e[1])}(...) : ${e[2]}(valores) { ... }`}],[/^constructor for '(.+?)' must explicitly initialize the (const |reference )member '(\w+)'/,e=>`O atributo ${e[3]} é ${e[2]==="const "?"const":"uma referência"} e precisa receber o valor na lista de inicialização: ${$(e[1])}(...) : ${e[3]}(valor) { ... }`],[/^constructor cannot have a return type/,()=>"Construtor não tem tipo de retorno — nem void. Escreva só o nome da classe: Personagem(string nome) { ... }"],[/^out-of-line definition of '(\w+)' does not match any declaration in '(.+?)'/,e=>`A definição ${$(e[2])}::${e[1]}(...) aqui fora da classe não bate com a declaração lá dentro: os tipos dos parâmetros (e o const) precisam ser iguais nos dois lugares.`],[/^initializer '(\w+)' does not name a non-static data member or base class(?:; did you mean the member '(\w+)'\?)?/,e=>`Na lista de inicialização do construtor, cada nome precisa ser um atributo da classe (ou a classe base)${e[2]?`: talvez você quis escrever ${e[2]}`:""}.`],[/^invalid use of non-static data member '(\w+)'/,e=>`${e[1]} é um atributo: cada objeto tem o seu. Use objeto.${e[1]} (dentro de um método da própria classe, só ${e[1]}).`],[/^call to non-static member function without an object argument/,()=>"Um método é chamado a partir de um objeto: objeto.metodo(). (Classe::metodo() só funciona com métodos static.)"],[/^C\+\+ requires a type specifier for all declarations/,()=>"Faltou o tipo: toda declaração precisa dizer o tipo — int x;, void mostrar(), int getVida()... Só construtores e destrutores não têm tipo."],[/^(?:variable|field) has incomplete type '(.+?)'/,e=>$(e[1])==="void"?"Variáveis não podem ser void: void só serve como tipo de retorno de função.":`${$(e[1])} foi só anunciado (class ${$(e[1])};) ou é usado antes de ser definido. Defina a classe completa, com as chaves, antes de criar objetos dela.`],[/^(?:variable|field|parameter|return) type '(.+?)' is an abstract class/,(e,t)=>go(e[1],t)],[/^allocating an object of abstract class type '(.+?)'/,(e,t)=>go(e[1],t)],[/^only virtual member functions can be marked 'override'/,()=>"override só vale para um método que substitui um método virtual da classe base. Declare o método na base como virtual (virtual void f() ...) — e confira se a classe filha herda mesmo da base (class Filha : public Base)."],[/^non-virtual member function marked 'override' hides virtual member function/,(e,t)=>At(t)],[/^(.+) marked 'override' but does not override any member functions/,()=>"O método tem override, mas não existe método virtual igual na classe base. Confira o nome, os parâmetros e o const."],[/^'virtual' can only be specified inside the class definition/,()=>"virtual aparece só na declaração, dentro da classe; na definição fora dela (Classe::metodo() { ... }) não se repete. O mesmo vale para override e static."],[/^'(\w+)' is not polymorphic/,e=>`dynamic_cast só funciona com classes polimórficas (com pelo menos um método virtual). Dê a ${e[1]} um destrutor virtual: virtual ~${e[1]}() {}`],[/^overloaded 'operator(<<|>>)' must be a binary operator \(has 3 parameters\)/,e=>`operator${e[1]} com (stream, objeto) deve ser uma função fora da classe (ou friend dentro dela): dentro da classe, o próprio objeto já conta como um parâmetro.`],[/^overloaded 'operator(\S+)' must be a (?:unary|binary|unary or binary) operator \(has (\d+) parameters?\)/,e=>`operator${e[1]} está com parâmetros demais. Como método da classe, o objeto da esquerda já é o próprio objeto (this): um operador binário recebe só o outro lado.`],[/^reference to overloaded function could not be resolved; did you mean to call it\?/,()=>"O compilador não soube qual função usar aqui. Faltaram os parênteses para chamar a função (f() e não f)? Se a linha usa um operator<< escrito por você, ele precisa devolver o stream (ostream& ... return os;) — senão o << seguinte não tem onde se apoiar."],[/^reference to non-static member function must be called/,()=>"Faltaram os parênteses para chamar o método: por exemplo, s.size() e não s.size."],[/^called object type '(.+?)' is not a function or function pointer/,()=>"Você usou parênteses ( ) em algo que não é uma função."],[/^no member named '(\w+)' in '(.+?)'(?:; did you mean '(\w+)'\?)?/,e=>Ct(e[1],e[2],e[3])],[/^cannot jump from switch statement to this case label/,()=>"Uma variável foi criada dentro de um case sem chaves. Coloque os comandos desse case entre { } (e o break dentro delas)."],[/^statement requires expression of integer type \('([^']+)'/,e=>/string/.test(e[1])?"switch só funciona com números inteiros, char e enum — não com string. Para textos, use if / else if com ==.":`switch só funciona com números inteiros, char e enum (aqui o valor é ${$(e[1])}).`],[/^expected unqualified-id|^no type named '(\w+)' in namespace 'std'/,()=>"O compilador não entendeu esta linha. Comandos como cout << ... precisam estar dentro de uma função (como main). Confira também se sobrou algum símbolo."],[/^void function '(\w+)' should not return a value/,e=>`${e[1]} é void: ela não devolve valor, então use só return; (sem valor) — ou mude o tipo da função.`],[/^non-void function '(\w+)' should return a value/,e=>`${e[1]} precisa devolver um valor: return seguido do valor.`],[/^member reference base type '(.+?)' is not a structure or union/,e=>`Você usou . (ponto) num valor do tipo ${$(e[1])}, que não tem membros. O ponto é para objetos (string, vector, struct, classe).`],[/^member reference type '(.+?)' is a pointer; did you mean to use '->'\?/,()=>"É um ponteiro: para acessar o membro, use -> (ou (*p).membro)."],[/^member reference type '(.+?)' is not a pointer; did you mean to use '\.'\?/,()=>"Isso é um objeto, não um ponteiro: use . (ponto) para acessar o membro. A seta -> é só para ponteiros."],[/^indirection requires pointer operand \('(.+?)' invalid\)/,e=>`O * na frente de um nome só funciona com ponteiros, e aqui o valor é ${$(e[1])}. Se queria o valor, use a variável direto; se queria o endereço, use &.`],[/^cannot delete expression of type '(.+?)'/,()=>"delete só serve para ponteiros que vieram de new."],[/^declaration of reference variable '(\w+)' requires an initializer/,e=>`Uma referência precisa nascer ligada a uma variável: int& ${e[1]} = outra;`],[/^cannot take the address of an rvalue/,()=>"O & (endereço de) só funciona com variáveis — um valor solto, como 5 ou a + b, não tem endereço."],[/^array subscript is not an integer/,()=>"O índice entre [ ] precisa ser um número inteiro."],[/^subscripted value is not an array, pointer, or vector/,()=>"Você usou [ ] em algo que não é array, vector nem string."],[/^invalid range expression of type '(.+?)'; no viable 'begin' function available/,e=>`O for de intervalo — for (x : coisa) — só funciona com coleções (vector, string, array, map...), e aqui o valor é ${$(e[1])}. Para repetir n vezes, use for (int i = 0; i < n; i++).`],[/cannot be narrowed from type '(.+?)' to '(.+?)'/,e=>`Com chaves { }, o C++ não deixa perder informação (${$(e[1])} → ${$(e[2])}). Use o tipo certo ou converta com static_cast.`],[/^excess elements in (array|scalar) initializer/,()=>"Há mais valores entre as chaves do que cabem."],[/^invalid suffix '(.+?)' on (integer|floating) constant/,()=>"Um nome não pode começar com número (ex.: 2x), e números não podem ter letras grudadas."],[/^variable has incomplete type 'void'|^.* declared as void/,()=>"Variáveis não podem ser void: void só serve como tipo de retorno de função."],[/^declaration of variable '(\w+)' with deduced type 'auto' requires an initializer/,e=>`auto descobre o tipo pelo valor inicial, então ${e[1]} precisa de um: auto ${e[1]} = 0;`],[/^type '(.+?)' decomposes into (\d+) elements?, but (\d+) names? (?:was|were) provided/,e=>`${$(e[1])} tem ${e[2]} parte(s), mas você deu ${e[3]} nome(s). Use um nome para cada parte: auto [a, b] = ...;`],[/^variable '(\w+)' cannot be implicitly captured in a lambda with no capture-default specified/,e=>`A lambda usa ${e[1]}, que é de fora dela, sem capturar. Ponha o nome entre os colchetes: [${e[1]}](...) { ... } (cópia) ou [&${e[1]}] (referência). [=] e [&] capturam tudo o que for usado.`],[/^no viable constructor or deduction guide for deduction of template arguments of '(\w+)'|^use of class template '(\w+)' requires template arguments/,e=>`Diga o tipo entre < >: ${e[1]||e[2]}<int> x; — um template de classe precisa saber com que tipo vai trabalhar.`],[/^too few template arguments for class template '(\w+)'/,e=>/map$/.test(e[1])?`${e[1]} precisa de dois tipos: ${e[1]}<chave, valor> — por exemplo, ${e[1]}<string, int>.`:`Faltaram tipos entre < > para ${e[1]}.`],[/^too many template arguments for class template '(\w+)'/,e=>`Sobraram tipos entre < > para ${e[1]}.`],[/^expected (identifier|member name)/,()=>"Faltou um nome aqui (de variável, função ou tipo)."],[/^use of overloaded operator '(<<|>>)' is ambiguous/,()=>"O compilador não sabe qual versão do operador usar com esses tipos."],[/^call to '(\w+)' is ambiguous/,e=>`Há mais de uma versão de ${e[1]} que serve para esses argumentos. Deixe os tipos dos argumentos mais claros.`],[/^static_assert failed/,()=>"Uma verificação em tempo de compilação (static_assert) falhou."],[/error in backend|^LLVM ERROR/,()=>"O compilador encontrou um problema interno com este código (uma limitação desta versão do Clang no navegador). Tente escrever esse trecho de outro jeito."]];function le(e){for(let[t,o]of zt){let a=t.exec(e.msg);if(a){let r=o(a,e);if(r)return r}}return null}var _o="O compilador encontrou um erro nesta linha. A mensagem (em inglês) diz o que ele esperava; às vezes o problema de verdade está na linha de cima.";function Tt(e,t){if(e.arquivo===t)return e.linha;for(let o of e.notas)if(o.arquivo===t)return o.linha;for(let o of e.incluido)if(o.arquivo===t)return o.linha;return null}function ke(e,{maxNotas:t=2}={}){let o=[...e.linhas],a=e.notas.filter(r=>K(r.arquivo));for(let r of a.slice(0,t))o.push(...r.linhas);return a.length>t&&t>0&&o.push(`(+${a.length-t} nota(s) do compilador)`),o.join(`
`)}function jo(e,{arquivo:t="main.cpp",fonte:o=""}={}){let a=$e(e);for(let f of a)f.fonte=o;let r=Fe(a);if(!r.length)return{tipo:"Erro de compilação",texto:String(e||"").trim()||"O compilador falhou.",linha:null,dica:_o};let s=r[0],n=null,c=a.filter(f=>f.arquivo===s.arquivo&&f.linha===s.linha),l=c.find(f=>/^missing terminating/.test(f.msg));if(l&&(n=le(l)),!n){let f=c.find(m=>/in 'for' statement specifier/.test(m.msg));f&&(n=le(f))}n||(n=le(s)||_o);let u=[ke(s)];l&&u.unshift(l.linhas.join(`
`));for(let f of r.slice(1,3))u.push(ke(f,{maxNotas:0}));return r.length>3&&u.push(`(e mais ${r.length-3} erro${r.length-3>1?"s":""})`),{tipo:"Erro de compilação",texto:u.join(`
`),linha:Tt(s,t),dica:n}}var jt=[[/all paths through this function will call itself/,()=>"A função sempre chama a si mesma: falta um caso base (um if que devolve um valor sem chamar a função de novo)."],[/^missing terminating '(["'])' character/,e=>e[1]==='"'?'Um texto começou com aspas " e não terminou. Feche as aspas na mesma linha.':"Um caractere começou com aspas simples ' e não terminou."],[/multi-character character constant/,()=>`Aspas simples ' ' são para UM caractere (char), como 'a'. Para texto, use aspas duplas: "texto".`],[/control (may )?reach(es)? end of non-void function/,()=>"A função pode terminar sem return: todo caminho de uma função que não é void precisa devolver um valor."],[/variable '(\w+)' is (?:uninitialized|used uninitialized)/,e=>`A variável ${e[1]} pode ser usada antes de receber um valor — em C++ ela começa com lixo. Dê um valor inicial (ex.: int ${e[1]} = 0;).`],[/field '(\w+)' is uninitialized when used here/,e=>`O atributo ${e[1]} é usado antes de receber um valor. Confira a ordem na lista de inicialização do construtor.`],[/using the result of an assignment as a condition/,()=>"Você usou = dentro de uma condição: isso GUARDA um valor. Para comparar, use ==."],[/unused variable '(\w+)'/,e=>`A variável ${e[1]} foi criada e nunca usada.`],[/private field '(\w+)' is not used/,e=>`O atributo ${e[1]} nunca é usado.`],[/(if|for|while) statement has empty body/,()=>"Tem um ; logo depois do if/for/while (...): ele termina o comando ali, e o bloco de baixo roda sempre (uma vez só)."],[/adding '.+?' to a string does not append to the string/,()=>'Somar um número a um texto entre aspas NÃO junta os dois. Use std::to_string(numero) ou mostre em partes: cout << "Idade: " << idade;'],[/implicit conversion from '(.+?)' to '(.+?)' changes value from (.+?) to (.+)$/,e=>`O valor ${e[3]} vira ${e[4]} ao ser guardado como ${$(e[2])} (a parte decimal é perdida).`],[/array index (-?\d+) is (past the end|before the beginning) of the array/,()=>"Índice fora do array: um array de N elementos vai do índice 0 até N - 1."],[/format specifies type '(.+?)' but the argument has type '(.+?)'/,()=>"O formato do printf não combina com o valor: %d é para int, %f para double, %c para char e %s para texto C."],[/result of comparison against a string literal is unspecified/,()=>"Comparar com um texto entre aspas desse jeito não funciona. Para um caractere, use aspas simples (c == 's'); para textos, guarde numa std::string e compare com ==."],[/division by zero is undefined|remainder by zero is undefined/,()=>"Divisão (ou resto) por zero: o programa vai travar quando chegar aqui."],[/(relational|equality) comparison result unused/,()=>"Esta comparação não faz nada. Se a ideia era guardar um valor, use = (um sinal só)."],[/expression result unused/,()=>"Esta expressão calcula algo, mas o resultado não é usado. Faltou um cout << ou uma atribuição?"],[/add explicit braces to avoid dangling else/,()=>"Use chaves { } para deixar claro a qual if o else pertence."],[/field '(\w+)' will be initialized after field '(\w+)'/,()=>"A lista de inicialização do construtor deve seguir a ordem em que os atributos foram declarados na classe."],[/address of stack memory associated with (local variable|parameter) '(\w+)' returned|reference to stack memory associated/,e=>`Você devolveu o endereço (ou uma referência) de ${e[2]?e[2]:"uma variável local"}, que deixa de existir quando a função termina.`],[/delete called on .* that is abstract but has non-virtual destructor|has virtual functions but non-virtual destructor/,()=>"Classes base com métodos virtuais precisam de destrutor virtual: virtual ~Base() = default;"],[/'delete' applied to a pointer that was allocated with 'new\[\]'/,()=>"Memória criada com new[] é liberada com delete[] (com colchetes)."],[/'(.+?)' hides overloaded virtual function/,()=>"Este método tem o mesmo nome de um método virtual da base, mas outra assinatura (parâmetros ou const), então não substitui o da base. Deixe a assinatura igual e marque com override."],[/'(\w+)' overrides a member function but is not marked 'override'/,e=>`${e[1]} substitui um método da classe base: marque com override (os outros métodos da classe já usam).`],[/address of function '(\w+)' will always evaluate to 'true'/,e=>`Faltaram os parênteses para chamar a função: ${e[1]}(). Sem eles, o C++ usa o endereço da função.`],[/self-comparison always evaluates to|explicitly assigning value of variable of type '.+?' to itself/,()=>"Você comparou (ou atribuiu) uma variável com ela mesma."],[/comparison of (?:constant|integers of different signs)/,()=>""]];function ue(e,{arquivo:t="main.cpp"}={}){let o=[];for(let a of $e(e)){if(a.nivel!=="warning"||a.arquivo!==t)continue;let r="";for(let[s,n]of jt){let c=s.exec(a.msg);if(c){r=n(c)||"";break}}if(o.push({linha:a.linha,texto:ke(a,{maxNotas:1}),dica:r,msg:a.msg}),o.length>=8)break}return o}function Ge(e){let t=String(e||"").split(`
`).filter(r=>r.trim()).slice(0,6).join(`
`).replace(/wasm-ld: error: [^:\n]*\.o: /g,"wasm-ld: error: "),o="O programa compilou, mas não deu para juntar as partes (ligação). Confira se toda função usada foi definida.",a=/undefined symbol: main\b/.exec(t);return a?o="Seu programa não tem a função main — é por ela que todo programa em C++ começa: int main() { ... }":/undefined symbol: (system|popen|fork|exec\w*|getch|_getch|kbhit)\b/.test(t)?o='Essa função do sistema operacional não existe aqui (o programa roda no navegador). Para pausar, não precisa de system("pause"): o console continua aberto sozinho.':(a=/undefined symbol: (?:vtable for |typeinfo for )(\w+)/.exec(t))?o=`Algum método virtual de ${a[1]} foi declarado mas não foi definido (falta o corpo { ... }). Defina todos, ou marque como virtual puro (= 0) os que só as classes filhas implementam.`:(a=/undefined symbol: ([^\n]+)/.exec(t))?o=`A função ${a[1].trim()} foi declarada (tem o protótipo) mas não foi definida — falta o corpo { ... } — ou foi definida com outro nome ou outros tipos de parâmetro.`:(a=/duplicate symbol: ([^\n]+)/.exec(t))&&(o=`${a[1].trim()} foi definido duas vezes.`),{tipo:"Erro de ligação",texto:t,linha:null,dica:o}}var vo=/^(_start|__original_main|__wasm_call_ctors|__cobra_|__main_void|__main_argc_argv|__cxx_global_var_init|_GLOBAL__sub_I_)/;function ce(e){return e?e==="__original_main"||e==="main"?"main":$(e.replace(/std::__2::/g,"std::").replace(/std::basic_string<char, std::char_traits<char>, std::allocator<char> >/g,"std::string").replace(/, std::allocator<[^<>]*(<[^<>]*>)?[^<>]*> >/g,">")):"?"}function Pt(e,t,o,a){let[r,s]=e?["texto","s"]:["vector","v"],n=m=>e?m===1?"1 caractere":`${m} caracteres`:m===1?"1 elemento":`${m} elementos`,c=m=>o?`${s}.at(${m})`:`${s}[${m}]`;if(a&&Array.isArray(t)){let m=t[0]|0,d=t[1]>>>0;return`O teste leu a posição ${m} de um ${r} do seu código, mas ${d===0?"ele está vazio":`ele só tem ${n(d)}`}. Confira quantos ${e?"caracteres":"itens"} a sua função devolve (ou guarda).`}if(!Array.isArray(t))return`${c("i")} recebeu uma posição que não existe no ${r}. As posições vão de 0 até size() - 1. Num laço, use i < ${s}.size() (e não <=).`;let l=t[0]|0,u=t[1]>>>0;if(l<0)return`${c(l)}: a posição ${l} não existe — as posições começam em 0. Um índice negativo costuma vir de uma conta como i - 1 com i = 0 (ou de size() - 1 com o ${r} vazio).`;if(u===0)return`${c(l)} foi usado com o ${r} vazio: não existe nenhuma posição, nem a 0. Confira antes se há ${e?"caracteres":"elementos"}: if (!${s}.empty()) { ... }`;let f=l===u?` Num laço, use i < ${s}.size() (e não <=).`:"";return`${c(l)} não existe: o ${r} tem ${n(u)}, ${u===1?"só na posição 0":`nas posições 0 a ${u-1}`}.${f}`}function ye(e,t,{arquivo:o="main.cpp"}={}){let a=e.erro||{},r=String(a.mensagem||""),s=(a.pilha||[]).map(b=>({...b,local:t(b)})),n=s.map(b=>(b.nome||"").replace(/std::__2::/g,"std::")),c=b=>n.some(y=>b.test(y)),l=b=>s.some(y=>y.nome&&b.test(ce(y.nome))),u=s.find(b=>b.local&&b.local.arquivo===o),f=u?u.local.linha:null,m=n[0]||"",d="Erro de execução",i="O programa parou com um erro enquanto rodava.",p=()=>{let b={};for(let y of n)b[y]=(b[y]||0)+1;return Object.entries(b).find(([y,C])=>C>=8&&y&&!vo.test(y))};if(/divide by zero|division by zero/i.test(r))d="Divisão por zero",i="Divisão (ou resto %) de inteiros por zero não existe e trava o programa. Confira o divisor antes de dividir.";else if(/integer overflow/i.test(r))d="Estouro de inteiro",i="A conta passou do maior valor que o tipo inteiro guarda.";else if(/call stack|too much recursion|Maximum call stack/i.test(r)||/out of bounds/.test(r)&&p()){let b=p();d="Recursão infinita",i=(b?`A função ${ce(b[0])} chamou a si mesma sem parar. `:"Funções chamaram umas às outras sem parar. ")+"Falta um caso base (um if que devolve sem chamar de novo)? Ou a chamada não se aproxima dele?"}else if(/unreachable/.test(r)){let b=c(/\bsto(i|l|ll|ul|ull|f|d|ld)\(/),y=/::~(\w+)\(/.exec(m);if(c(/^__cobra_erro_indice_(vector|string)$/)){d="Índice fora do limite";let C=!u&&s.some(E=>E.local&&/^teste\d+\.cpp$/.test(E.local.arquivo));i=Pt(c(/^__cobra_erro_indice_string$/),a.detalhe,c(/::at\(/),C)}else if(c(/^__cobra_erro_vazio$/)){let C=s.map(w=>/^std::(vector|string|list|deque)\b.*::(front|back|pop_back|pop_front)\(/.exec(ce(w.nome))).find(Boolean);d="Coleção vazia";let E=C?C[1]==="string"?"numa string vazia":`num ${C[1]} vazio`:"";i=`${C?`${C[2]}() foi usado ${E}`:"front(), back() ou pop_back() foi usado num vector (ou numa string) vazio"}: não há elemento para pegar ou tirar. Confira antes se há elementos: if (!v.empty()) { ... }`}else c(/^__cobra_erro_optional_vazio$/)?(d="optional vazio",i="*opt (ou opt->...) foi usado num std::optional sem valor. Confira antes com has_value() (ou if (opt))."):c(/^__cobra_erro_ponteiro_vazio$/)?(d="Ponteiro inteligente vazio",i="Um unique_ptr (ou shared_ptr) vazio foi usado com * ou ->: ele não aponta para nenhum objeto. Isso acontece quando ele não recebeu um objeto, depois de std::move (a posse foi para outro) ou depois de reset(). Confira antes: if (p) { ... }"):c(/^__cobra_erro_biblioteca$/)?(d="Uso inválido da biblioteca",i="A biblioteca padrão detectou um uso inválido nesta linha (por exemplo, um ponteiro nulo onde se esperava um texto)."):b&&c(/invalid_arg/)?(d="Conversão inválida",i="std::stoi (ou stod) recebeu um texto que não começa com um número."):b&&c(/out_of_range/)?(d="Número grande demais",i="O número do texto não cabe no tipo (std::stoi só aceita até 2147483647; para mais, use std::stoll)."):l(/^std::(unordered_)?map<.*>::at\(/)?(d="Chave inexistente",i="at(chave) recebeu uma chave que não existe no map. Confira antes com count(chave) ou find(chave) — ou use [] quando a ideia for criar a chave."):l(/^std::string::at\(/)?(d="Índice fora do limite",i="at(i) recebeu uma posição que não existe no texto. As posições vão de 0 até size() - 1."):c(/out_of_range|::at\(/)?(d="Índice fora do limite",i="at(i) recebeu uma posição que não existe. As posições vão de 0 até size() - 1."):c(/__throw_length_error/)?(d="Tamanho inválido",i="Um vector ou string ficou com tamanho impossível (grande demais ou negativo convertido para size_t)."):c(/bad_optional_access/)?(d="optional vazio",i="value() foi chamado num std::optional sem valor. Confira com has_value() (ou if (opt)) antes."):c(/bad_variant_access/)?(d="variant com outro tipo",i="std::get pediu um tipo que o variant não está guardando."):c(/bad_function_call/)?(d="function vazia",i="Um std::function sem função guardada foi chamado."):c(/__throw_bad_alloc|operator new/)?(d="Memória esgotada",i="O programa pediu memória demais."):c(/__assert_fail/)?(d="assert falhou",i="Um assert(...) falhou: a condição dele era falsa. A mensagem na saída mostra qual."):c(/random_device/)?(d="random_device indisponível",i="std::random_device não existe aqui (não há fonte de números aleatórios do sistema). Use uma semente: std::mt19937 gerador(42); ou srand(time(0)) com rand()."):c(/std::thread|__thread_/)?(d="Threads indisponíveis",i="std::thread não funciona aqui: o programa roda numa linha de execução só."):c(/std::terminate|__terminate/)?(d="std::terminate",i="O programa foi encerrado por std::terminate()."):c(/__cxa_pure_virtual/)?(d="Método virtual puro",i="Um método virtual puro (= 0) foi chamado — geralmente de dentro de um construtor ou destrutor."):c(/^(free|dlfree|__libc_free)$/)?(d="Memória liberada errado",i="delete (ou free) recebeu um endereço inválido: memória liberada duas vezes, ou um ponteiro que não veio de new."):/^abort$/.test(m)||c(/^abort$/)?(d="abort()",i="O programa foi abortado (abort())."):y?(d="Destrutor não virtual",i=`Um objeto de uma classe filha foi apagado (delete ou unique_ptr) por um ponteiro de ${y[1]}, mas o destrutor de ${y[1]} não é virtual. Na classe base, declare o destrutor como virtual: virtual ~${y[1]}() {} (ou = default).`):u&&s[0]===u&&!/::(\w+)::\1\(|^(\w+)::\2\(/.test(m)?(d="Função sem return",i=`A função ${ce(u.nome)} chegou ao fim sem return. Toda função que não é void precisa devolver um valor em todos os caminhos.`):(d="Erro de execução",i="O programa chegou a um ponto impossível (unreachable).")}else/memory access out of bounds|index out of bounds|out of bounds memory access/.test(r)?(d="Acesso fora da memória",i="O programa leu ou escreveu fora da memória: índice muito além do fim de um array/vector ([ ] não confere), ponteiro inválido ou memória já liberada."):/null function|signature mismatch|indirect call/.test(r)?(d="Chamada inválida",i="Uma função foi chamada por um ponteiro nulo ou inválido — por exemplo, um método virtual chamado por um ponteiro nulo, por um unique_ptr vazio (depois de std::move) ou por um objeto que já foi apagado."):/float unrepresentable|invalid conversion to integer/.test(r)?(d="Conversão impossível",i="Um número decimal gigante (infinito ou NaN, por exemplo depois de dividir por 0.0) foi convertido para inteiro."):/out of memory|Out of memory|could not allocate/i.test(r)&&(d="Memória esgotada",i="O programa usou memória demais.");e.memoria&&e.memoria>=250*1024*1024&&d!=="Recursão infinita"&&(i+=" (O programa chegou ao limite de 256 MB de memória.)");let _=[`${a.nome||"RuntimeError"}: ${r}`],h=0,v=null,g=0;for(let b of s){if(!b.nome||vo.test(b.nome)&&b.nome!=="__original_main"||b.nome==="main"&&!b.local||/^(abort|__assert_fail|__cxa_pure_virtual)$|^std::__2::__|\(anonymous namespace\)|__throw_|throw_helper/.test(b.nome))continue;let y=b.local&&K(b.local.arquivo)?` (${b.local.arquivo}:${b.local.linha})`:"",C=` em ${ce(b.nome)}${y}`;if(C===v){g++;continue}if(g&&(_.push(` ... (+${g} vezes)`),g=0),_.push(C),v=C,++h>=8)break}return g&&_.push(` ... (+${g} vezes)`),{tipo:d,texto:_.join(`
`),linha:f,dica:i}}function Po(e){let t=e.msg,o,a=`
(${$(e.linhas[0].replace(/^[^:]+:\d+:\d+: /,""))})`,r=[e.msg,...e.notas.map(n=>n.msg)].join(`
`);if(/^no matching function for call to '(confere\w*|texto|iguais|capturar|com_saida|chamada|juntar_args)'/.test(t))return/'void'/.test(r)?"A função do seu código não devolve nada (é void), mas o teste precisa do valor que ela devolve. Confira o tipo de retorno pedido na tarefa.":"O valor que o seu código devolve tem um tipo diferente do que o teste espera. Confira o tipo de retorno pedido na tarefa.";if(o=/^use of undeclared identifier '(\w+)'(?:; did you mean '(.+?)'\?)?/.exec(t))return`Não achei ${o[1]} no seu código. Confira se você criou a função (ou variável) com exatamente esse nome — maiúsculas contam${o[2]?` (existe ${o[2]}; era esse o nome pedido?)`:""}.`;if(o=/^no matching constructor for initialization of '([^']+)'/.exec(t))return So(o[1],e,{teste:!0});if(o=/^no matching function for call to '([^']+)'/.exec(t)){let n=Ve(e,o[1]);return`${$(o[1])} existe no seu código, mas não aceita os argumentos que o teste usa. `+(n||"Confira a quantidade e os tipos dos parâmetros pedidos na tarefa.")+a}if(o=/^too (many|few) arguments to function call, expected (?:at (?:least|most) )?(\d+), have (\d+)/.exec(t))return`A função do seu código tem ${o[2]} parâmetro(s), mas o teste a chama com ${o[3]}. Confira os parâmetros pedidos na tarefa.`;if(o=/^(?:unknown type name|no template named) '(\w+)'/.exec(t))return`Não achei o tipo ${o[1]} (struct ou classe) no seu código. Confira o nome pedido na tarefa.`;if(o=/^no member named '(\w+)' in '(.+?)'/.exec(t))return`${$(o[2])} não tem o membro ${o[1]}. Confira o nome (e se é um atributo ou um método) pedido na tarefa.`;if(o=/^'(\w+)' is a (private|protected) member of '(.+?)'/.exec(t))return e.notas.some(n=>/private inheritance/.test(n.msg))?To(o,e):`${o[1]} é ${o[2]==="private"?"privado":"protegido"} em ${$(o[3])}, mas o teste precisa usá-lo. Confira o que a tarefa pede que seja público.`;if(o=/^'this' argument to member function '(\w+)' has type 'const (.+?)', but function is not marked const/.exec(t))return zo(o[1],o[2],e,{teste:!0});if(/^cannot cast .* to its private base class|abstract class|^call to (?:implicitly-)?deleted|marked 'override'/.test(t))return le(e)+a;if(/with an [lr]value of type 'void'|'void' is not|variable has incomplete type 'void'|of incompatible type 'void'|'void'\)/.test(t)&&!/^invalid operands to binary expression \('void'/.test(t))return"A função do seu código não devolve nada (é void), mas o teste precisa do valor que ela devolve. Confira o tipo de retorno pedido na tarefa.";if(/^reference to non-static member function must be called/.test(t))return"O teste esperava um atributo, mas no seu código esse nome é um método (ou o contrário). Confira a tarefa.";if(o=R(`^invalid operands to binary expression \\(${O} and ${O}\\)`).exec(t)){let n=P(o,1),c=P(o,3),l=wo(e)||"?";if(n==="void"&&l==="<<")return"O seu operator<< devolve void, então o teste não consegue encadear (os << a << ...). Ele precisa devolver o stream: ostream& operator<<(ostream& os, const T& x) { ...; return os; }"+a;if(Co(n)&&l==="<<"&&F(c))return`O teste mostra um ${c.replace(/^const /,"")} com <<, mas o seu código ainda não tem ostream& operator<<(ostream& os, const ${c.replace(/^const /,"")}& obj). Crie essa função, fora da classe, como a tarefa pede.`+a;if(F(n)||F(c)){let u=(F(n)?n:c).replace(/^const /,"");return`O teste usa ${l} com objetos ${u}, mas o seu código ainda não tem o operador ${l} para ${u}. Crie o operator${l} pedido na tarefa.`+a}}if(/^invalid operands to binary expression|^no viable conversion|^cannot initialize|^assigning to/.test(t))return"O valor que o seu código devolve tem um tipo diferente do que o teste espera. Confira o tipo de retorno pedido na tarefa."+a;if(o=/^call to '(\w+)' is ambiguous/.exec(t))return`Há mais de uma versão de ${o[1]} que serve para a chamada do teste. Confira os tipos dos parâmetros.`+a;if(o=/^no matching member function for call to '(\w+)'/.exec(t))return Oo(o[1],e)+a;let s=le(e);return s?s+a:"O teste não compilou junto com o seu código. Confira nomes, parâmetros e tipos pedidos na tarefa."+a}function we(e){let t=String(e).replace(/\r\n/g,`
`).split(`
`).map(o=>o.replace(/\s+$/,""));for(;t.length&&t[t.length-1]==="";)t.pop();return t}function S(e,t=120){let o='"'+String(e).replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\t/g,"\\t")+'"';return o.length<=t?o:o.slice(0,t-4)+'..."'}var W=e=>e.normalize("NFD").replace(/[̀-ͯ]/g,""),oe=e=>[...e].filter(t=>/[\p{L}\p{N}]/u.test(t)).join("");function de(e,t){if(e.toLowerCase()===t.toLowerCase())return"A diferença está nas letras maiúsculas/minúsculas.";if(e.replace(/ /g,"")===t.replace(/ /g,""))return"A diferença está nos espaços.";if(W(e)===W(t))return"A diferença está nos acentos.";if(oe(e)&&e.replace(/-/g,"")===t.replace(/-/g,""))return"A diferença está no sinal de menos (-).";if(oe(e)&&oe(e)===oe(t))return"A diferença está na pontuação ou nos símbolos (vírgulas, pontos, dois-pontos, exclamação...).";let o=oe(W(e)).toLowerCase(),a=oe(W(t)).toLowerCase();return o&&o===a?"Está quase: confira maiúsculas, acentos e pontuação.":null}var Mo=/-?\d+(?:\.\d+)?/g;function Do(e,t){let o=W(String(e)),a=o.match(Mo)||[],r=(o.replace(Mo," ").match(/\p{L}+/gu)||[]).join("");return{nums:a,letras:t?r:r.toLowerCase()}}function Dt(e,t,o){if(Math.abs(e.length-t.length)>o)return o+1;let a=Array.from({length:t.length+1},(r,s)=>s);for(let r=1;r<=e.length;r++){let s=[r],n=r;for(let c=1;c<=t.length;c++)s[c]=Math.min(a[c]+1,s[c-1]+1,a[c-1]+(e[r-1]===t[c-1]?0:1)),s[c]<n&&(n=s[c]);if(n>o)return o+1;a=s}return a[t.length]}function Ae(e,t,o={}){if(o.espacos){let n=W(String(e)),c=W(String(t));return o.caixa?n===c:n.toLowerCase()===c.toLowerCase()}let a=Do(e,o.caixa),r=Do(t,o.caixa);if(a.nums.length!==r.nums.length||a.nums.some((n,c)=>n!==r.nums[c]))return!1;if(a.letras===r.letras)return!0;let s=Math.min(Math.floor(Math.max(a.letras.length,r.letras.length)/8),3);return Dt(a.letras,r.letras,s)<=s}function Rt(e,t,o={}){let a=e.filter(s=>s.trim()),r=t.filter(s=>s.trim());return r.length?a.length===r.length&&a.every((s,n)=>Ae(s,r[n],o))?!0:!o.espacos&&Ae(a.join(" "),r.join(" "),o):!1}function It(e,t){let o=e.filter(r=>r.trim()),a=t.filter(r=>r.trim());for(let r=0;r<Math.min(o.length,a.length);r++)if(o[r]!==a[r]){let s=de(o[r],a[r]);return`Passou! Só um detalhe: o esperado era ${S(o[r])} e saiu ${S(a[r])}.${s?" "+s:""}`}return"Passou! Só um detalhe: as linhas em branco (ou as quebras de linha) ficaram um pouco diferentes do esperado."}var Ro=(e,t)=>{let a=W(String(e)).match(/-?\d+(?:\.\d+)?|\p{L}+/gu)||[];return" "+(t?a:a.map(r=>r.toLowerCase())).join(" ")+" "};function Nt(e,t,o={}){let a=Ro(t,o.caixa);return a.trim()!==""&&Ro(e,o.caixa).includes(a)}function Q(e){let t=/^[A-Za-z_À-ÿ][\wÀ-ÿ]*/.exec(e);if(!t||!/^[a-zà-ÿ]/.test(e))return e;let o=e.slice(t[0].length,t[0].length+1);return t[0].includes("_")||"(.[_:".includes(o)&&o?e:e[0].toUpperCase()+e.slice(1)}var B=e=>e?e+": ":"";function Xe(e){return!e||!e.length?"":e.length===1?"Com a entrada "+S(e[0]):"Com as entradas "+e.map(t=>S(t)).join(", ")}function Bt(e,t,o="",{entradas:a=[],leniente:r=null}={}){let s=Array.isArray(t)?t.map(String):we(t),n=we(e);if(s.length===n.length&&s.every((d,i)=>d===n[i]))return null;if(r&&Rt(s,n,r))return{quase:!0,msg:It(s,n)};let c=s.join(`
`),l=n.join(`
`),u=d=>({msg:Q(d),esperado:c,recebido:l});if(!n.length)return u(`${B(o)}seu programa não mostrou nada. Faltou um cout?`);if(!s.length){let d=n.length>1?` (e mais ${n.length-1} linha${n.length>2?"s":""})`:"";return u(`${B(o)}nada deveria aparecer na tela, mas apareceu ${S(n[0])}${d}.`)}let f=r?s.filter(d=>d.trim()):s,m=n.map((d,i)=>[d,i]).filter(([d])=>!r||d.trim());for(let d=0;d<Math.min(f.length,m.length);d++){let i=f[d],[p,_]=m[d];if(i===p||r&&Ae(i,p,r))continue;let h=`${B(o)}a linha ${_+1} da saída está diferente.
esperado: ${S(i)}
recebido: ${S(p)}`,v=de(i,p);return!v&&n[_+1]!==void 0&&a.includes(n[_+1].trim())&&i.startsWith(p.replace(/\s+$/,""))&&i.trim().endsWith(n[_+1].trim())&&(v="A resposta digitada deveria ficar na mesma linha da pergunta: não use endl (nem \\n) depois da pergunta."),!v&&a.some(g=>i.includes(g))&&!a.some(g=>p.includes(g))&&i.startsWith(p)&&(v="Na saída comparada, o que foi digitado aparece logo depois da pergunta (como no terminal)."),v&&(h+=`
`+v),u(h)}if(m.length<f.length){let d=f.length-m.length;return u(`${B(o)}faltou ${d===1?"uma linha":d+" linhas"} na saída. A próxima esperada era: ${S(f[m.length])}`)}return u(`${B(o)}sua saída tem linhas a mais. A primeira que sobrou foi: ${S(m[f.length][0])}`)}function Lt(e){let t=String(e),o="",a=[],r=0,s=t.length;for(;r<s;){let n=t[r],c=t[r+1];if(n==="/"&&c==="/"){let l=t.indexOf(`
`,r);l<0&&(l=s),a.push(t.slice(r+2,l)),o+=" ",r=l}else if(n==="/"&&c==="*"){let l=t.indexOf("*/",r+2);l<0&&(l=s-2);let u=t.slice(r+2,l);a.push(u),o+=" "+`
`.repeat((u.match(/\n/g)||[]).length),r=l+2}else if(n==="R"&&c==='"'&&!/[\w]/.test(t[r-1]||"")){let l=/^R"([^()\\\s]{0,16})\(/.exec(t.slice(r,r+20));if(l){let u=t.indexOf(")"+l[1]+'"',r+l[0].length),f=u<0?s:u+l[1].length+2;o+='""'+`
`.repeat((t.slice(r,f).match(/\n/g)||[]).length),r=f}else o+=n,r++}else if(n==='"'||n==="'"&&!/[0-9A-Za-z_]/.test(t[r-1]||"")){let l=r+1;for(;l<s&&t[l]!==n&&t[l]!==`
`;)l+=t[l]==="\\"?2:1;o+=n+n,r=l+1}else o+=n,r++}return{codigo:o,comentarios:a}}function kt(e,t){let o=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=new RegExp(`(?<![\\w.>])${o}\\s*\\(`,"g"),r;for(;r=a.exec(e);){let s=r.index+r[0].length,n=1;for(;s<e.length&&n;)e[s]==="("?n++:e[s]===")"&&n--,s++;let c=/^\s*(const\s*)?(noexcept\s*)?(override\s*)?(->\s*[\w:<>,\s*&]+)?\{/.exec(e.slice(s));if(!c)continue;let l=s+c[0].length,u=1,f=l;for(;l<e.length&&u;)e[l]==="{"?u++:e[l]==="}"&&u--,l++;return e.slice(f,l-1)}return null}function Ft(e){let t=String(e).trim();if(!t)return null;let o=t.split(/\s+/),a="";return o.forEach((r,s)=>{if(s>0){let n=o[s-1];a+=/\w$/.test(n)&&/^\w/.test(r)?"\\s+":"\\s*"}a+=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}),/^\w/.test(t)&&(a="(?<![\\w])"+a),/\w$/.test(t)&&(a+="(?![\\w])"),new RegExp(a,"g")}function We(e,t){let o=Ft(t);return o?(e.match(o)||[]).length:0}var te=e=>Array.isArray(e)?e:[e],He=e=>"`"+e+"`";function Io(e,t){let{codigo:o,comentarios:a}=Lt(t);if(e.usa!==void 0){let r=te(e.usa);if(!r.some(s=>We(o,s)>0))return{msg:e.msg||`Este exercício pede que você use ${r.map(He).join(" ou ")}.`}}if(e.nao_usa!==void 0){let r=te(e.nao_usa).find(s=>We(o,s)>0);if(r!==void 0)return{msg:e.msg||`Neste exercício, não use ${He(r)}.`}}if(e.conta!==void 0){let r=te(e.conta).reduce((n,c)=>n+We(o,c),0),s=te(e.conta).map(He).join(" / ");if(e.min!==void 0&&r<e.min)return{msg:e.msg||`Use ${s} pelo menos ${e.min} ${e.min===1?"vez":"vezes"} (encontrei ${r}).`};if(e.max!==void 0&&r>e.max)return{msg:e.msg||`Use ${s} no máximo ${e.max} ${e.max===1?"vez":"vezes"} (encontrei ${r}).`}}if(e.recursiva!==void 0){let r=kt(o,e.recursiva);if(r===null)return{msg:e.msg||`Não achei a função ${e.recursiva} no seu código.`};let s=String(e.recursiva).replace(/[.*+?^${}()|[\]\\]/g,"\\$&");if(!new RegExp(`(?<![\\w])${s}\\s*\\(`).test(r))return{msg:e.msg||`A função ${e.recursiva} precisa ser recursiva: ela deve chamar ${e.recursiva}(...) dentro dela mesma.`}}if(e.regex!==void 0&&!new RegExp(e.regex,"m").test(o))return{msg:e.msg||"O código não tem a estrutura que o exercício pede."};if(e.nao_regex!==void 0&&new RegExp(e.nao_regex,"m").test(o))return{msg:e.msg||"O código usa algo que este exercício não permite."};if(e.codigo_regex!==void 0&&!new RegExp(e.codigo_regex,"m").test(String(t)))return{msg:e.msg||"O código não tem o que o exercício pede."};if(e.comentarios!==void 0&&a.filter(s=>s.trim().length>0).length<e.comentarios)return{msg:e.msg||`Escreva pelo menos ${e.comentarios} comentário${e.comentarios>1?"s":""} (// ...).`};if(e.comentario!==void 0){let r=new RegExp(e.comentario,"m");if(!a.some(s=>r.test(s)))return{msg:e.msg||`Esperava um comentário com ${S(e.comentario)}.`}}return null}var No=["saida","contem","nao_contem","ultima_linha","codigo"],Bo=["usa","nao_usa","regex","nao_regex","conta","comentario","comentarios","codigo_regex","recursiva"],Vt=new Set([...No,...Bo,"cpp","entradas","eof","semente","msg","min","max"]);function Lo(e){let t=typeof e=="string"?[{cpp:e}]:Array.isArray(e)?e:[e];if(!t.length)throw new Error("teste vazio");return t.map(o=>{if(typeof o=="string"&&(o={cpp:o}),!o||typeof o!="object")throw new Error("cada checagem deve ser um dict (ou uma string com código C++)");for(let n of Object.keys(o))if(!Vt.has(n))throw new Error(`chave desconhecida ${JSON.stringify(n)}`);if(o.entradas!==void 0&&!(Array.isArray(o.entradas)&&o.entradas.every(n=>typeof n=="string")))throw new Error('"entradas" deve ser uma lista de strings');let a=No.some(n=>o[n]!==void 0),r=Bo.some(n=>o[n]!==void 0),s=o.cpp!==void 0;if(s+a+r!==1)throw new Error("cada checagem precisa ser de UM tipo: saída (saida/contem/...), C++ (cpp) ou estrutura (usa/regex/...)");if(s){if(typeof o.cpp!="string"||!o.cpp.trim())throw new Error('"cpp" deve ser um texto com código C++');return{tipo:"cpp",...o}}if(a)return{tipo:"saida",...o};for(let n of["entradas","eof","semente"])if(o[n]!==void 0)throw new Error(`"${n}" só vale em checagens de saída ou de C++ (não em usa/regex/...)`);for(let n of["regex","nao_regex","codigo_regex","comentario"])if(o[n]!==void 0)try{new RegExp(o[n])}catch(c){throw new Error(`regex inválida em ${n}: ${c.message}`)}return{tipo:"estrutura",...o}})}function ko(e,t,o,a=null){let r=Xe(e.entradas),s=(l,u={})=>({msg:e.msg&&!u.forcar?e.msg:Q(l),...u}),n=[];if(e.saida!==void 0){let l=Bt(t,e.saida,r,{entradas:e.entradas||[],leniente:a});if(l&&l.quase)n.push(l.msg);else if(l)return e.msg?{...l,msg:e.msg}:l}let c=we(t).join(`
`);for(let l of e.contem===void 0?[]:te(e.contem))if(!c.includes(l)){if(a&&Nt(c,l,a)){n.push(`Passou! Só um detalhe: o esperado era ver exatamente ${S(l)} na saída.`);continue}return s(`${B(r)}esperava ver ${S(l)} na saída, mas não apareceu.`,{esperado:l,recebido:c})}for(let l of e.nao_contem===void 0?[]:te(e.nao_contem))if(c.includes(l))return s(`${B(r)}a saída não deveria ter ${S(l)}.`,{recebido:c});if(e.ultima_linha!==void 0){let l=we(t);if(!l.length)return s(`${B(r)}seu programa não mostrou nada. Faltou um cout?`);let u=l[l.length-1];if(u!==e.ultima_linha&&a&&Ae(e.ultima_linha,u,a))n.push(`Passou! Só um detalhe: a última linha esperada era ${S(e.ultima_linha)} e saiu ${S(u)}.`);else if(u!==e.ultima_linha){let f=`${B(r)}a última linha da saída deveria ser ${S(e.ultima_linha)}, mas foi ${S(u)}.`,m=de(e.ultima_linha,u);return m&&(f+=`
`+m),s(f,{esperado:e.ultima_linha,recebido:u})}}return e.codigo!==void 0&&(o||0)!==e.codigo?s(`${B(r)}o programa deveria terminar com return ${e.codigo}; (código de saída), mas terminou com ${o||0}.`):n.length?{quase:!0,msg:n.join(`
`)}:null}function Fo(e,t,o){let a=`#line 1 "main.cpp"
`+e;a.endsWith(`
`)||(a+=`
`),t.some(r=>/\bRODAR_MAIN\b/.test(r.cpp))&&(a+=`#define COBRA_USA_MAIN 1
`),a+=`#line 1 "cobra_testes.hpp"
`+o+`
`;for(let{id:r,cpp:s}of t)a+=`static void __cobra_teste_${r}() {
#line 1 "teste${r}.cpp"
${s}
#line 1 "cobra_fim.hpp"
}
`;a+=`namespace {
struct __CobraDespachante {
__CobraDespachante() {
`,a+=` const char* t = ::getenv("COBRA_TESTE");
if (!t) return;
const int k = ::atoi(t);
`,a+=` ::__cobra::detalhe::inicio_teste();
switch (k) {
`;for(let{id:r}of t)a+=` case ${r}: __cobra_teste_${r}(); break;
`;return a+=` default: ::__cobra::detalhe::falhar_interno("teste desconhecido");
}
`,a+=` ::__cobra::detalhe::passou();
}
} __cobra_despachante;
}
`,a}var Vo=`// ===== Cobra Code: apoio aos testes (colocado depois do código do aluno; não faz parte do programa dele) =====
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <string_view>
#include <iterator>
#include <sstream>
#include <type_traits>
#include <utility>
#include <initializer_list>
#ifdef COBRA_USA_MAIN
#include <iostream>
#include <stdio_ext.h>
#endif
extern "C" int __cobra_canal(int op, const char* dados, int tamanho);
namespace __cobra {
namespace detalhe {
enum { RELATO = 1, ENTRADAS = 3, CAPTURA_INICIO = 4, CAPTURA_FIM = 5, SAIDA_IGUAL = 6, CAPTURA_COPIA = 7, INICIO_TESTE = 8 };
inline std::string limpo(std::string s) {
for (char& c : s) if (c == '\\x1f' || c == '\\x1e') c = '?';
return s;
}
[[noreturn]] inline void encerrar() {
std::fflush(stdout);
std::_Exit(0);
}
inline void enviar(const std::string& s) { __cobra_canal(RELATO, s.data(), (int)s.size()); }
[[noreturn]] inline void falha(const std::string& msg, const std::string& esperado = "", const std::string& recebido = "",
const std::string& textoA = "", const std::string& textoB = "", bool comPista = false) {
enviar("falha\\x1f" + limpo(msg) + "\\x1f" + limpo(esperado) + "\\x1f" + limpo(recebido) + "\\x1f" + (comPista ? "1" : "0") +
"\\x1f" + limpo(textoA) + "\\x1f" + limpo(textoB));
encerrar();
}
[[noreturn]] inline void falhar_interno(const char* m) { falha(std::string("Erro interno do teste: ") + m); }
[[noreturn]] inline void passou() {
enviar("ok");
encerrar();
}
inline void inicio_teste() { __cobra_canal(INICIO_TESTE, nullptr, 0); }
// --- detecção de tipos ---------------------------------------------------------------------------
template <class T, class = void> struct tem_begin : std::false_type {};
template <class T>
struct tem_begin<T, std::void_t<decltype(std::declval<const T&>().begin()), decltype(std::declval<const T&>().end())>>
: std::true_type {};
template <class T, class = void> struct e_par : std::false_type {};
template <class T>
struct e_par<T, std::void_t<decltype(std::declval<const T&>().first), decltype(std::declval<const T&>().second)>>
: std::true_type {};
template <class T, class = void> struct e_opcional : std::false_type {};
template <class T>
struct e_opcional<T, std::void_t<decltype(std::declval<const T&>().has_value()), decltype(*std::declval<const T&>())>>
: std::true_type {};
template <class T, class = void> struct tem_saida : std::false_type {};
template <class T>
struct tem_saida<T, std::void_t<decltype(std::declval<std::ostream&>() << std::declval<const T&>())>> : std::true_type {};
template <class T> using limpo_t = std::remove_cv_t<std::remove_reference_t<T>>;
template <class T>
constexpr bool e_array_char_v = std::is_array_v<limpo_t<T>> && std::is_same_v<std::remove_cv_t<std::remove_extent_t<limpo_t<T>>>, char>;
template <class T>
constexpr bool e_texto_v = std::is_same_v<limpo_t<T>, std::string> || std::is_same_v<limpo_t<T>, std::string_view> ||
std::is_same_v<std::decay_t<T>, const char*> || std::is_same_v<std::decay_t<T>, char*> ||
e_array_char_v<T>;
inline std::string aspas(std::string_view s) {
std::string r = "\\"";
for (char c : s) {
if (c == '"') r += "\\\\\\"";
else if (c == '\\\\') r += "\\\\\\\\";
else if (c == '\\n') r += "\\\\n";
else if (c == '\\t') r += "\\\\t";
else r += c;
}
return r + "\\"";
}
inline std::string aspas_char(char c) {
if (c == '\\n') return "'\\\\n'";
if (c == '\\t') return "'\\\\t'";
if (c == '\\0') return "'\\\\0'";
if (c == '\\'') return "'\\\\''";
return std::string("'") + c + "'";
}
inline std::string real(double v) {
if (v != v) return "nan";
if (v > 1.7976931348623157e308) return "inf";
if (v < -1.7976931348623157e308) return "-inf";
char buf[64];
for (int p = 1; p <= 17; p++) {
std::snprintf(buf, sizeof buf, "%.*g", p, v);
if (std::strtod(buf, nullptr) == v) break;
}
std::string s = buf;
if (s.find_first_of(".en") == std::string::npos) s += ".0";
return s;
}
inline std::string real_f(float v) {
if (v != v) return "nan";
char buf[64];
for (int p = 1; p <= 9; p++) {
std::snprintf(buf, sizeof buf, "%.*g", p, (double)v);
if (std::strtof(buf, nullptr) == v) break;
}
std::string s = buf;
if (s.find_first_of(".en") == std::string::npos) s += ".0";
return s;
}
} // namespace detalhe
// Representação de um valor como no código C++: 5, 2.5, true, 'a', "Ana", {1, 2, 3}, {"Ana", 7}...
template <class T> std::string texto(const T& v) {
using U = detalhe::limpo_t<T>;
if constexpr (std::is_same_v<U, bool>) return v ? "true" : "false";
else if constexpr (std::is_same_v<U, char>) return detalhe::aspas_char(v);
else if constexpr (std::is_integral_v<U>) return std::to_string(v);
else if constexpr (std::is_same_v<U, float>) return detalhe::real_f(v);
else if constexpr (std::is_floating_point_v<U>) return detalhe::real((double)v);
else if constexpr (std::is_enum_v<U>) return std::to_string((long long)v);
else if constexpr (std::is_array_v<U> && std::is_same_v<std::remove_cv_t<std::remove_extent_t<U>>, char>)
return detalhe::aspas(std::string_view(v));
else if constexpr (std::is_same_v<U, std::string> || std::is_same_v<U, std::string_view>) return detalhe::aspas(v);
else if constexpr (std::is_same_v<std::decay_t<U>, const char*> || std::is_same_v<std::decay_t<U>, char*>)
return v ? detalhe::aspas(v) : std::string("nullptr");
else if constexpr (std::is_null_pointer_v<U>) return "nullptr";
else if constexpr (detalhe::e_opcional<U>::value) return v.has_value() ? __cobra::texto(*v) : std::string("nullopt");
else if constexpr (detalhe::e_par<U>::value) return "{" + __cobra::texto(v.first) + ", " + __cobra::texto(v.second) + "}";
else if constexpr (std::is_array_v<U> || detalhe::tem_begin<U>::value) {
std::string r = "{";
int n = 0;
for (const auto& x : v) {
if (n) r += ", ";
if (++n > 30) { r += "..."; break; }
r += __cobra::texto(x);
}
return r + "}";
} else if constexpr (detalhe::tem_saida<U>::value) {
std::ostringstream o;
o << v;
return o.str();
} else if constexpr (std::is_pointer_v<U>) return v ? std::string("(ponteiro)") : std::string("nullptr");
else return "(valor)";
}
inline std::string juntar_args() { return ""; }
template <class A, class... R> std::string juntar_args(const A& a, const R&... r) {
std::string s = __cobra::texto(a);
if constexpr (sizeof...(r) > 0) s += ", " + __cobra::juntar_args(r...);
return s;
}
// "soma(2, 3)" — para descrever uma chamada nas mensagens (CHAMADA("soma", a, b)).
template <class... A> std::string chamada(const char* nome, const A&... args) {
return std::string(nome) + "(" + __cobra::juntar_args(args...) + ")";
}
// --- comparação ----------------------------------------------------------------------------------
template <class A, class B> bool iguais(const A& a, const B& b) {
using UA = detalhe::limpo_t<A>;
using UB = detalhe::limpo_t<B>;
if constexpr (std::is_arithmetic_v<UA> && std::is_arithmetic_v<UB>) {
if constexpr (std::is_floating_point_v<UA> || std::is_floating_point_v<UB>) {
const long double x = a, y = b;
if (x != x || y != y) return x != x && y != y;
if (x == y) return true;
const long double d = x > y ? x - y : y - x;
long double escala = x < 0 ? -x : x;
const long double ay = y < 0 ? -y : y;
if (ay > escala) escala = ay;
if (escala < 1) escala = 1;
// float tem só ~7 dígitos: a tolerância acompanha o tipo menos preciso
constexpr long double tol = (std::is_same_v<UA, float> || std::is_same_v<UB, float>) ? 1e-6L : 1e-9L;
return d <= tol * escala;
} else if constexpr (std::is_same_v<UA, bool> || std::is_same_v<UB, bool>) {
return static_cast<bool>(a) == static_cast<bool>(b);
} else if constexpr (std::is_signed_v<UA> != std::is_signed_v<UB>) {
if constexpr (std::is_signed_v<UA>) { if (a < 0) return false; } else { if (b < 0) return false; }
return static_cast<unsigned long long>(a) == static_cast<unsigned long long>(b);
} else {
return a == b;
}
} else if constexpr (detalhe::e_texto_v<UA> && detalhe::e_texto_v<UB>) {
return std::string_view(a) == std::string_view(b);
} else if constexpr (detalhe::e_opcional<UA>::value && detalhe::e_opcional<UB>::value) {
if (a.has_value() != b.has_value()) return false;
return !a.has_value() || __cobra::iguais(*a, *b);
} else if constexpr (detalhe::e_par<UA>::value && detalhe::e_par<UB>::value) {
return __cobra::iguais(a.first, b.first) && __cobra::iguais(a.second, b.second);
} else if constexpr ((std::is_array_v<UA> || detalhe::tem_begin<UA>::value) && (std::is_array_v<UB> || detalhe::tem_begin<UB>::value)) {
auto ia = std::begin(a), fa = std::end(a);
auto ib = std::begin(b), fb = std::end(b);
for (; ia != fa && ib != fb; ++ia, ++ib) if (!__cobra::iguais(*ia, *ib)) return false;
return ia == fa && ib == fb;
} else {
return a == b;
}
}
namespace detalhe {
template <class T> long long tamanho(const T& v) {
long long n = 0;
for (const auto& x : v) { (void)x; n++; }
return n;
}
// Explica ONDE está a diferença (coleções) ou dá uma pista (divisão inteira).
template <class A, class B> std::string onde_difere(const A& obtido, const B& esperado) {
using UA = limpo_t<A>;
using UB = limpo_t<B>;
if constexpr (std::is_integral_v<UA> && !std::is_same_v<UA, bool> && std::is_floating_point_v<UB>) {
const double e = esperado;
if (e != (double)(long long)e && (long long)e == (long long)obtido) {
return "\\nVeio um número inteiro: parece uma divisão inteira (em C++, 7 / 2 dá 3). Use um double: 7.0 / 2 ou "
"static_cast<double>(x) / y — e confira se a função devolve double.";
}
return "";
} else if constexpr (!e_texto_v<UA> && !e_texto_v<UB> && (std::is_array_v<UA> || tem_begin<UA>::value) &&
(std::is_array_v<UB> || tem_begin<UB>::value)) {
const long long na = tamanho(obtido), nb = tamanho(esperado);
if (na != nb) {
return "\\nTamanho esperado: " + std::to_string(nb) + (nb == 1 ? " item" : " itens") + "; veio com " + std::to_string(na) + ".";
}
auto ia = std::begin(obtido);
auto ib = std::begin(esperado);
for (long long i = 0; i < na; ++i, ++ia, ++ib) {
if (!__cobra::iguais(*ia, *ib)) {
return "\\nPrimeira diferença na posição [" + std::to_string(i) + "]: esperado " + __cobra::texto(*ib) + ", veio " +
__cobra::texto(*ia) + ".";
}
}
return "";
} else {
return "";
}
}
template <class A, class B> void confere_igual_impl(const std::string& desc, const A& obtido, const B& esperado) {
if (__cobra::iguais(obtido, esperado)) return;
std::string e = __cobra::texto(esperado), o = __cobra::texto(obtido);
if constexpr (std::is_floating_point_v<limpo_t<A>> || std::is_floating_point_v<limpo_t<B>>) {
if (e == o && std::is_arithmetic_v<limpo_t<A>> && std::is_arithmetic_v<limpo_t<B>>) { // mesma aparência: mostra mais casas
char be[40], bo[40];
std::snprintf(be, sizeof be, "%.17g", (double)esperado);
std::snprintf(bo, sizeof bo, "%.17g", (double)obtido);
e = be;
o = bo;
}
}
std::string msg = desc + " deveria ser " + e + ", mas foi " + o + "." + onde_difere(obtido, esperado);
using UA = limpo_t<A>;
using UB = limpo_t<B>;
constexpr bool textos = e_texto_v<UA> && e_texto_v<UB>;
if constexpr (textos) falha(msg, e, o, std::string(std::string_view(esperado)), std::string(std::string_view(obtido)), true);
else falha(msg, e, o);
}
} // namespace detalhe
inline void confere(bool ok, const char* expr, int) {
if (!ok) detalhe::falha(std::string("A condição ") + expr + " deveria ser verdadeira, mas foi falsa.");
}
inline void confere(bool ok, const char*, int, const std::string& msg) {
if (!ok) detalhe::falha(msg);
}
template <class A, class B> void confere_igual(const char* expr, int, const A& obtido, const B& esperado) {
detalhe::confere_igual_impl(expr, obtido, esperado);
}
template <class A, class E> void confere_igual(const char* expr, int, const A& obtido, std::initializer_list<E> esperado) {
detalhe::confere_igual_impl(expr, obtido, esperado);
}
template <class A, class B> void confere_igual_desc(const std::string& desc, int, const A& obtido, const B& esperado) {
detalhe::confere_igual_impl(desc, obtido, esperado);
}
template <class A, class E> void confere_igual_desc(const std::string& desc, int, const A& obtido, std::initializer_list<E> esperado) {
detalhe::confere_igual_impl(desc, obtido, esperado);
}
template <class A, class B, class C> void confere_perto(const char* expr, int, const A& obtido, const B& esperado, const C& tol) {
const long double x = obtido, y = esperado, t = tol;
const long double d = x > y ? x - y : y - x;
if (d <= t) return;
detalhe::falha(std::string(expr) + " deveria ser " + __cobra::texto(esperado) + " (com tolerância " + __cobra::texto(tol) +
"), mas foi " + __cobra::texto(obtido) + "." + detalhe::onde_difere(obtido, esperado),
__cobra::texto(esperado), __cobra::texto(obtido));
}
[[noreturn]] inline void falhar(const std::string& msg) { detalhe::falha(msg); }
// --- saída e entradas ----------------------------------------------------------------------------
namespace detalhe {
inline void captura_inicio() {
std::fflush(stdout);
std::fflush(stderr);
__cobra_canal(CAPTURA_INICIO, nullptr, 0);
}
inline std::string captura_fim() {
std::fflush(stdout);
std::fflush(stderr);
const int n = __cobra_canal(CAPTURA_FIM, nullptr, 0);
std::string s((size_t)(n > 0 ? n : 0), '\\0');
if (n > 0) __cobra_canal(CAPTURA_COPIA, &s[0], n);
return s;
}
} // namespace detalhe
template <class F> std::string capturar(F f) {
detalhe::captura_inicio();
f();
return detalhe::captura_fim();
}
template <class F> auto com_saida(std::string& saida, F f) -> decltype(f()) {
detalhe::captura_inicio();
if constexpr (std::is_void_v<decltype(f())>) {
f();
saida = detalhe::captura_fim();
} else {
auto v = f();
saida = detalhe::captura_fim();
return v;
}
}
inline void definir_entradas(std::initializer_list<const char*> entradas) {
std::string s;
bool primeiro = true;
for (const char* e : entradas) {
if (!primeiro) s += '\\x1f';
s += e;
primeiro = false;
}
__cobra_canal(detalhe::ENTRADAS, s.data(), entradas.size() ? (int)s.size() : -1);
}
inline void confere_saida(const std::string& obtido, const std::string& esperado, const std::string& desc) {
const std::string pacote = obtido + '\\x1f' + esperado + '\\x1f' + desc;
if (!__cobra_canal(detalhe::SAIDA_IGUAL, pacote.data(), (int)pacote.size())) detalhe::encerrar();
}
#ifdef COBRA_USA_MAIN
inline int chamar_main(int (*f)()) { return f(); }
inline int chamar_main(int (*f)(int, char**)) {
static char nome[] = "main";
static char* argv[] = {nome, nullptr};
return f(1, argv);
}
template <class F> std::string rodar_main(F f, std::initializer_list<const char*> entradas = {}) {
__cobra::definir_entradas(entradas);
std::cin.clear();
__fpurge(stdin);
detalhe::captura_inicio();
__cobra::chamar_main(f);
std::string s = detalhe::captura_fim();
std::cin.clear();
__fpurge(stdin);
return s;
}
#endif
} // namespace __cobra
#define CONFERE(cond, ...) ::__cobra::confere(static_cast<bool>(cond), #cond, __LINE__, ##__VA_ARGS__)
#define CONFERE_IGUAL(obtido, ...) ::__cobra::confere_igual(#obtido, __LINE__, (obtido), __VA_ARGS__)
#define CONFERE_IGUAL_DESC(desc, obtido, ...) ::__cobra::confere_igual_desc((desc), __LINE__, (obtido), __VA_ARGS__)
#define CONFERE_PERTO(obtido, esperado, tol) ::__cobra::confere_perto(#obtido, __LINE__, (obtido), (esperado), (tol))
#define CONFERE_SAIDA(obtido, esperado, ...) ::__cobra::confere_saida((obtido), (esperado), std::string("" __VA_ARGS__))
#define FALHAR(msg) ::__cobra::falhar(msg)
#define CAPTURAR(...) ::__cobra::capturar([&]() { __VA_ARGS__; })
#define COM_SAIDA(saida, ...) ::__cobra::com_saida((saida), [&]() { return (__VA_ARGS__); })
#define DEFINIR_ENTRADAS(...) ::__cobra::definir_entradas(__VA_ARGS__)
#define RODAR_MAIN(...) ::__cobra::rodar_main(main, ##__VA_ARGS__)
#define CHAMADA(nome, ...) ::__cobra::chamada(nome, ##__VA_ARGS__)
#define TEXTO(...) ::__cobra::texto(__VA_ARGS__)
`;var Ht=5,Xt=8,Zt=4e3,Ze=6e4;function Je(e){let t=3735928559,o=1103547991;for(let a=0;a<e.length;a++){let r=e.charCodeAt(a);t=Math.imul(t^r,2654435761),o=Math.imul(o^r,1597334677)}return t=Math.imul(t^t>>>16,2246822507)^Math.imul(o^o>>>13,3266489909),o=Math.imul(o^o>>>16,2246822507)^Math.imul(t^t>>>13,3266489909),(4294967296*(2097151&o)+(t>>>0)).toString(36)}var H=()=>performance.now(),Go=e=>e.slice(e.lastIndexOf(`
`)+1).replace(/[\x01\x02]/g,""),qe=e=>e?e+": ":"",Jt={tipo:"Sem main",texto:"O programa não tem a função main.",linha:null,dica:"Todo programa em C++ começa pela função main: int main() { ... }. Escreva a main (ou não apague a do código inicial)."},Kt=/end of non-void function|uninitialized|assignment as a condition|has empty body|does not append to the string|changes value from|past the end of the array|comparison result unused/,Ce=class{constructor(t,o,{progresso:a=()=>{}}={}){this.c=t,this.exec=o,this.progresso=a,this.cache=new Map}info(){return{motor:"cpp",versao:`Clang ${lo}`,padrao:"C++17",linguagem:"C++"}}_guardar(t,o){for(this.cache.delete(t),this.cache.set(t,o);this.cache.size>16;)this.cache.delete(this.cache.keys().next().value);return o}_pegar(t){let o=this.cache.get(t);return o&&(this.cache.delete(t),this.cache.set(t,o)),o}_montar(t,o,a){let r=this.c.ligar([t],{saida:o,iostream:Qt(a)});if(!r.ok)return{ok:!1,fase:"ligar",texto:r.texto};let s=ho(r.wasm),n=r.wasm,c=null;try{let l=fo(r.wasm);l&&(n=l.bytes,c=l.mapa)}catch{}return{ok:!0,modulo:new WebAssembly.Module(n),mapa:c,linhas:s,tamanho:n.length}}binarioAluno(t){let o="a"+Je(t),a=this._pegar(o);if(a)return a;this.progresso({fase:"compilar",texto:"Compilando…"});let r=H(),s=this.c.compilar(t),n;if(!s.ok)n={ok:!1,erro:jo(s.texto,{fonte:t}),avisos:ue(s.texto)};else{let c=this._montar(s.objeto,"/cobra/prog.wasm",t);n=c.ok?{...c,avisos:ue(s.texto)}:{ok:!1,erro:Ge(c.texto),avisos:ue(s.texto)}}return n.msCompilar=Math.round(H()-r),n.pch=s.pch,this._guardar(o,n)}binarioTestes(t,o){let a="t"+Je(t+"\0"+JSON.stringify(o)),r=this._pegar(a);if(r)return r;let s=this.cache.get("a"+Je(t));if(s&&!s.ok)return{sintaxe:s.erro};this.progresso({fase:"compilar",texto:"Compilando os testes…"});let n=H(),c=new Map,l=o.slice(),u=()=>this.binarioAluno(t);for(let m=0;m<6&&l.length;m++){let d=Fo(t,l,Vo),i=this.c.compilar(d,{pchDe:t,arquivo:"/cobra/testes.cpp",objeto:"/cobra/testes.o"});if(i.ok){let v=this._montar(i.objeto,"/cobra/testes.wasm",d);if(v.ok){let E={...v,avisos:ue(i.texto)};return this._guardar(a,{bin:E,falhas:c,msCompilar:Math.round(H()-n),pch:i.pch})}let g=u();if(!g.ok)return{sintaxe:g.erro};let b=[...v.texto.matchAll(/undefined symbol: ([^\n]+)/g)].map(E=>E[1].trim().replace(/\(.*$/,"").split("::").pop()),y=l.filter(E=>b.some(w=>w&&new RegExp("\\b"+w.replace(/\W/g,"")+"\\b").test(E.cpp)));y.length||(y=l.slice());let C=Ge(v.texto);for(let E of y)c.set(E.id,`O teste não conseguiu montar o programa junto com o seu código: ${C.dica}
(${v.texto.split(`
`)[0]})`);l=l.filter(E=>!y.includes(E));continue}let p=Fe($e(i.texto)),_=new Map,h=!1;for(let v of p){let g=Yt(v);g&&l.some(b=>b.id===g)?_.has(g)||_.set(g,v):h=!0}if(h){let v=u();if(!v.ok)return{sintaxe:v.erro};if(!_.size){let g=p[0]?p[0].linhas[0]:i.texto.split(`
`)[0];for(let b of l)c.set(b.id,`O teste não conseguiu compilar junto com o seu código:
${g}`);l=[];break}}for(let[v,g]of _)c.set(v,Po(g));l=l.filter(v=>!_.has(v.id))}let f=u();if(!f.ok)return{sintaxe:f.erro};for(let m of l)c.has(m.id)||c.set(m.id,"O teste não conseguiu compilar junto com o seu código.");return this._guardar(a,{bin:f,falhas:c,msCompilar:Math.round(H()-n)})}_onde(t){return o=>{if(!t||!t.linhas||t.linhas.vazia)return null;let a=t.mapa?t.mapa.original(o.offset):o.offset;return t.linhas.procurar(a)}}_linhaDoTempo(t,o,a="main.cpp"){let r=this._onde(o);for(let s of t.pilha||[]){let n=r(s);if(n&&n.arquivo===a)return n.linha}return null}async run(t={}){let o=String(t.code??""),a=Math.max(.5,Math.min(Number(t.tempo)||Ht,60))*1e3,r=this.binarioAluno(o);if(!r.ok){let l={saida:"",fim:"erro",erro:r.erro};return r.avisos&&r.avisos.length&&(l.avisos=Ke(r.avisos)),l}this.progresso({fase:"executar",texto:"Executando…"});let s=t.seed!=null&&t.seed!==""?Number(t.seed)|0:Math.floor(Math.random()*2**30),n=await this.exec.executar(r.modulo,{entradas:(t.inputs||[]).map(String),eof:!!t.eof,eco:!0,semente:s,limiteSaida:Ze,tempoMs:a},a),c={saida:n.saida,fim:n.fim};if(n.fim==="entrada")c.prompt=Go(n.saida);else if(n.fim==="erro")c.erro=ye(n,this._onde(r));else if(n.fim==="tempo"){let l=this._linhaDoTempo(n,r);l&&(c.linha=l)}return n.semMain&&(c.fim="erro",c.erro=Jt),n.codigo&&(c.codigo=n.codigo),r.avisos&&r.avisos.length&&(c.avisos=Ke(r.avisos)),c}async test(t={}){let o=String(t.code??""),a={ok:!1,sintaxe:null,testes:[]},r=[],s=[];for(let[i,p]of t.tests||[]){let _={nome:String(i),checks:null,erro:null};try{_.checks=Lo(p);for(let h of _.checks)h.tipo==="cpp"&&(h.id=s.length+1,s.push({id:h.id,cpp:h.cpp}))}catch(h){_.erro="Teste mal formado: "+h.message}r.push(_)}let n,c=new Map;if(s.length){let i=this.binarioTestes(o,s);if(i.sintaxe)return a.sintaxe=i.sintaxe,a;n=i.bin,c=i.falhas}else if(n=this.binarioAluno(o),!n.ok)return a.sintaxe=n.erro,a;this.progresso({fase:"testar",texto:"Rodando os testes…"});let l=H()+Math.max(1,Math.min(Number(t.tempo)||Xt,60))*1e3,u=t.leniente&&typeof t.leniente=="object"?t.leniente:null,f=!0,m=!1,d=0;for(let i of r){let p={nome:i.nome,ok:!0};if(i.erro)Object.assign(p,{ok:!1,msg:i.erro});else if(m)Object.assign(p,{ok:!1,msg:"Não rodou: um teste anterior estourou o tempo."});else for(let _ of i.checks){let h=await this._checar(_,o,n,c,l,u);if(_.tipo!=="estrutura"&&d++,h&&h.quase){(p.dicas||(p.dicas=[])).push(h.msg);continue}if(h&&u&&_.tipo==="estrutura"){(p.estrutura||(p.estrutura=[])).push(h.msg);continue}if(h){p.ok=!1,p.msg=h.msg,h.esperado!==void 0&&h.esperado!==""&&(p.esperado=h.esperado),h.recebido!==void 0&&(h.recebido!==""||h.esperado)&&(p.recebido=h.recebido),h.tempo&&H()>l&&(m=!0),_.tipo!=="estrutura"&&(p.msg+=ea(n));break}}a.testes.push(p)}for(let i of a.testes)i.estrutura&&(!d&&i.ok?Object.assign(i,{ok:!1,msg:i.estrutura[0]}):i.ok&&(i.dicas||(i.dicas=[])).push(...i.estrutura.map(p=>`Sugestão da aula: ${p}`)),delete i.estrutura),i.ok||delete i.dicas,f=f&&i.ok;return a.ok=f,n.avisos&&n.avisos.length&&(a.avisos=Ke(n.avisos)),a}async _checar(t,o,a,r,s,n=null){if(t.tipo==="estrutura")return Io(t,o);let c=s-H();if(c<=50)return{msg:"Não rodou: o tempo da bateria de testes acabou.",tempo:!0};let l=Math.min(Zt,c),u=(t.entradas||[]).map(String),f=t.semente!=null?t.semente|0:1,m=Xe(u);if(t.tipo==="cpp"){if(r.has(t.id))return{msg:r.get(t.id)};let i=await this.exec.executar(a.modulo,{entradas:u,eof:!!t.eof,eco:!1,semente:f,env:{COBRA_TESTE:String(t.id)},limiteSaida:Ze,tempoMs:l},l);return this._interpretarCpp(i,a,l)}let d=await this.exec.executar(a.modulo,{entradas:u,eof:!!t.eof,eco:!1,semente:f,limiteSaida:Ze,tempoMs:l},l);if(d.semMain)return{msg:"Seu programa não tem a função main — é por ela que todo programa em C++ começa: int main() { ... }"};if(d.fim==="entrada"){let i=Go(d.saida),p=i.trim()?` (pergunta: ${S(i)})`:"";return u.length?{msg:Q(`${qe(m)}seu programa pediu mais uma entrada${p}, mas o teste só tinha ${u.length} entrada(s). Ele lê mais vezes do que devia?`)}:{msg:`Seu programa pediu uma entrada com cin${p}, mas neste exercício ele não deveria ler nada do teclado.`}}if(d.fim==="limite")return{msg:Q(`${qe(m)}seu programa mostrou texto demais — parece um laço infinito.`)};if(d.fim==="tempo"){let i=this._linhaDoTempo(d,a);return{msg:Q(`${qe(m)}seu programa demorou demais e foi interrompido${i?` na linha ${i}`:""}. Parece um laço infinito: a condição do laço muda em algum momento?`),tempo:!0}}if(d.fim==="erro"){let i=ye(d,this._onde(a));return{msg:Q(`${qe(m)}seu programa deu erro${i.linha?` na linha ${i.linha}`:""}:
${i.texto}
→ ${i.dica}`)}}return ko(t,d.saida,d.codigo,n)}_interpretarCpp(t,o){let a=t.relatos.find(r=>r.tipo==="falha");if(a){let r=a.msg;if(a.pista){let s=de(a.textoA,a.textoB);s&&(r+=`
`+s)}return{msg:r,esperado:a.esperado||void 0,recebido:a.recebido||void 0}}if(t.relatos.some(r=>r.tipo==="ok"))return null;if(t.fim==="erro"){let r=ye(t,this._onde(o));return{msg:`${!t.inicioTeste?"Seu programa deu erro antes de o teste começar (ao criar as variáveis globais)":r.linha?`Ao rodar o teste, seu código deu erro na linha ${r.linha}`:"Ao rodar o teste, aconteceu um erro"}:
${r.texto}
→ ${r.dica}`}}if(t.fim==="tempo"){let r=this._linhaDoTempo(t,o);return{msg:`O teste demorou demais e foi interrompido${r?` (seu código estava na linha ${r})`:""}. Parece um laço infinito — ou uma solução lenta demais.`,tempo:!0}}return t.fim==="entrada"?{msg:"Durante o teste, seu código pediu uma entrada (cin), mas o teste não tinha o que digitar. Aqui a função deve usar só os parâmetros que recebe."}:t.fim==="limite"?{msg:"Durante o teste, seu código mostrou texto demais — parece um laço infinito."}:{msg:"O teste terminou antes da hora: seu código encerrou o programa (exit ou return na main) durante o teste."}}};function Qt(e){return/#\s*include\s*<iostream>/.test(e||"")}function Yt(e){let t=/^teste(\d+)\.cpp$/.exec(e.arquivo||"");if(t)return+t[1];for(let o of e.notas||[]){let a=/^teste(\d+)\.cpp$/.exec(o.arquivo||"");if(a)return+a[1]}return null}function Ke(e){return e.map(({linha:t,texto:o,dica:a})=>({linha:t,texto:o,dica:a}))}function ea(e){let t=(e.avisos||[]).find(o=>Kt.test(o.msg||"")&&o.dica);return t?`
O compilador avisou (linha ${t.linha}): ${t.dica}`:""}var Ee=class{constructor(t){this.criar=t,this.w=null,this.seq=0,this.pend=new Map,this.fila=Promise.resolve(),this._novo()}_novo(){let t=this.criar();t.aoReceber(o=>{let a=this.pend.get(o&&o.id);a&&(this.pend.delete(o.id),a(o.r))}),t.aoErro(o=>{for(let[a,r]of this.pend)this.pend.delete(a),r({fim:"erro",saida:"",relatos:[],codigo:0,erro:{nome:"Erro",mensagem:"o executor parou: "+String(o&&o.message||o),pilha:[]}});if(this.w===t){try{t.encerrar()}catch{}this.w=null}}),this.w=t}executar(t,o,a){let r=this.fila.then(()=>new Promise(s=>{this.w||this._novo();let n=++this.seq,c=setTimeout(()=>{this.pend.delete(n);try{this.w.encerrar()}catch{}this.w=null,this._novo(),s({fim:"tempo",saida:"",relatos:[],pilha:[],codigo:0,forcado:!0})},a+2500);this.pend.set(n,l=>{clearTimeout(c),s(l)}),this.w.enviar({id:n,modulo:t,opcoes:o})}));return this.fila=r.catch(()=>{}),r}fechar(){if(this.w)try{this.w.encerrar()}catch{}this.w=null}};var ae=G,Oe=new URL("./",self.location.href),Wo=e=>(e/1048576).toFixed(e<10485760?1:0).replace(".",","),pe=null,Ho="rede";function Ue(e){try{postMessage({type:"progresso",...e})}catch{}}function oa(e){if(typeof Uint8Array.fromBase64=="function")return Uint8Array.fromBase64(e);let t=atob(e),o=new Uint8Array(t.length);for(let a=0;a<t.length;a++)o[a]=t.charCodeAt(a);return o}async function ta(e){let t=new Blob([e]).stream().pipeThrough(new DecompressionStream("gzip"));return new Uint8Array(await new Response(t).arrayBuffer())}function Xo(e){let t=e.reduce((r,s)=>r+s.length,0),o=new Uint8Array(t),a=0;for(let r of e)o.set(r,a),a+=r.length;return o}async function aa(){let e=ae.versao;try{if(self.caches){let t=await caches.open("cobra-cpp"),o=a=>new URL(`cpp-cache/${e}/${a}`,Oe).href;try{for(let a of await t.keys())a.url.includes(`/cpp-cache/${e}/`)||await t.delete(a)}catch{}return{tipo:"cache",async pegar(a){return await t.match(o(a))||null},async guardar(a,r){await t.put(o(a),new Response(r,{headers:{"Content-Type":a==="sysroot"?"application/octet-stream":"application/wasm"}}))}}}}catch{}try{let t=await new Promise((a,r)=>{let s=indexedDB.open("cobra-cpp",1);s.onupgradeneeded=()=>s.result.createObjectStore("arquivos"),s.onsuccess=()=>a(s.result),s.onerror=()=>r(s.error)}),o=(a,r)=>new Promise((s,n)=>{let c=t.transaction("arquivos",a),l=r(c.objectStore("arquivos"));c.oncomplete=()=>s(l&&l.result),c.onerror=()=>n(c.error),c.onabort=()=>n(c.error)});try{let a=await o("readonly",r=>r.getAllKeys());for(let r of a||[])String(r).startsWith(e+"/")||await o("readwrite",s=>s.delete(r))}catch{}return{tipo:"indexeddb",async pegar(a){let r=await o("readonly",s=>s.get(`${e}/${a}`));return r?new Response(r):null},async guardar(a,r){await o("readwrite",s=>s.put(r,`${e}/${a}`))}}}catch{return null}}async function ra(e,t){let o=await fetch(e);if(!o.ok)throw new Error(`não consegui baixar ${e} (HTTP ${o.status})`);let a;if(o.body&&o.body.getReader){let n=o.body.getReader(),c=[];for(;;){let{done:l,value:u}=await n.read();if(l)break;c.push(u),t(u.length)}a=new TextDecoder().decode(Xo(c))}else a=await o.text(),t(a.length);let r=a.indexOf('"b64"'),s=a.indexOf('"',a.indexOf(":",r)+1)+1;return oa(a.slice(s,a.indexOf('"',s)))}async function sa(){let e=await aa();me=e;let t=["clang","lld","sysroot"],o={};if(e)for(let h of t)try{o[h]=await e.pegar(h)}catch{o[h]=null}let a=t.filter(h=>!o[h]);Ho=a.length?a.length===t.length?"rede":"rede+cache":e.tipo;let r=a.reduce((h,v)=>h+ae.arquivos[v].partes.reduce((g,b)=>g+b.bytes,0),0)+ae.memfs.bytes,s=0,n=0,c=(h=!1)=>{let v=performance.now();!h&&v-n<120||(n=v,Ue({fase:"baixar",feito:s,total:r,texto:`Baixando o compilador de C++ — ${Wo(s)} de ${Wo(r)} MB`}))},l=h=>{s+=h,c()};a.length?c(!0):Ue({fase:"preparar",texto:"Preparando o compilador de C++…"});let u=fetch(new URL(ae.memfs.url,Oe)).then(async h=>{if(!h.ok)throw new Error(`não consegui baixar ${ae.memfs.url} (HTTP ${h.status})`);let v=new Uint8Array(await h.arrayBuffer());return l(v.length),WebAssembly.compile(v)}),f={};await Promise.all(a.map(async h=>{let v=await Promise.all(ae.arquivos[h].partes.map(g=>ra(new URL(g.url,Oe),l)));f[h]=await ta(Xo(v))})),a.length&&(c(!0),Ue({fase:"preparar",texto:"Preparando o compilador de C++…"}));let m=async h=>{if(f[h]){let g=f[h];return e&&e.guardar(h,g).catch(()=>{}),WebAssembly.compile(g)}let v=o[h];if(WebAssembly.compileStreaming&&(v.headers.get("Content-Type")||"").includes("wasm"))try{return await WebAssembly.compileStreaming(v.clone())}catch{}return WebAssembly.compile(new Uint8Array(await v.arrayBuffer()))},d=f.sysroot||new Uint8Array(await o.sysroot.arrayBuffer());f.sysroot&&e&&e.guardar("sysroot",f.sysroot).catch(()=>{});let[i,p,_]=await Promise.all([m("clang"),m("lld"),u]);return{clang:i,lld:p,memfs:_,sysroot:d}}function na(){let e=new Worker(new URL("cpp-runner.js",Oe));return{enviar:t=>e.postMessage(t),aoReceber:t=>{e.onmessage=o=>t(o.data)},aoErro:t=>{e.onerror=o=>{o.preventDefault&&o.preventDefault(),t(o.message||"erro no executor")}},encerrar:()=>e.terminate()}}var me=null,Se=Promise.resolve(),ia=(async()=>{let e=performance.now(),t=await sa(),o=new xe(t);o.iniciar();let a=`pch-iostream-${uo}`,r=null;try{r=me&&await me.pegar(a)}catch{}if(r)try{o.carregarPch("iostream",new Uint8Array(await r.arrayBuffer()))}catch{}pe=new Ce(o,new Ee(na),{progresso:Ue}),postMessage({type:"ready",info:{...pe.info(),origem:Ho,ms:Math.round(performance.now()-e)}});let s=`#include <iostream>
int main() { std::cout << "ok" << std::endl; return 0; }
`;setTimeout(()=>{Se=Se.then(async()=>{try{!r&&o.prepararPch("iostream")&&me&&await me.guardar(a,o.bytesPch("iostream")).catch(()=>{});let n=o.compilar(s,{arquivo:"/cobra/aquecer.cpp",objeto:"/cobra/aquecer.o"});n.ok&&o.ligar([n.objeto],{saida:"/cobra/aquecer.wasm",iostream:!0})}catch{}})},0)})().catch(e=>{throw postMessage({type:"fatal",error:String(e&&(e.stack||e.message)||e)}),e});self.onmessage=e=>{let{id:t,cmd:o,payload:a}=e.data||{};Se=Se.then(async()=>{try{await ia;let r;if(o==="run")r=await pe.run(a||{});else if(o==="test")r=await pe.test(a||{});else if(o==="info")r=pe.info();else throw new Error("comando desconhecido: "+o);postMessage({id:t,ok:!0,result:r})}catch(r){postMessage({id:t,ok:!1,error:String(r&&r.message||r)})}})};})();