rbx.cp 0.7.0__py3-none-any.whl → 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. rbx/box/cd.py +2 -2
  2. rbx/box/cli.py +87 -33
  3. rbx/box/code.py +133 -84
  4. rbx/box/contest/build_contest_statements.py +2 -2
  5. rbx/box/contest/contest_package.py +1 -1
  6. rbx/box/contest/main.py +29 -2
  7. rbx/box/environment.py +140 -80
  8. rbx/box/formatting.py +2 -1
  9. rbx/box/global_package.py +74 -0
  10. rbx/box/package.py +11 -24
  11. rbx/box/packaging/__init__.py +0 -0
  12. rbx/box/packaging/boca/__init__.py +0 -0
  13. rbx/box/packaging/polygon/packager.py +3 -3
  14. rbx/box/presets/__init__.py +369 -53
  15. rbx/box/presets/lock_schema.py +42 -2
  16. rbx/box/presets/schema.py +4 -0
  17. rbx/box/remote.py +21 -2
  18. rbx/box/retries.py +3 -2
  19. rbx/box/sanitizers/warning_stack.py +5 -5
  20. rbx/box/solutions.py +37 -25
  21. rbx/box/statements/build_statements.py +6 -6
  22. rbx/box/statements/builders.py +1 -1
  23. rbx/box/stats.py +10 -0
  24. rbx/box/stresses.py +47 -66
  25. rbx/box/stressing/finder_parser.py +11 -16
  26. rbx/box/tasks.py +33 -22
  27. rbx/box/testcase_utils.py +3 -3
  28. rbx/box/tooling/boca/scraper.py +1 -1
  29. rbx/grading/caching.py +98 -47
  30. rbx/grading/debug_context.py +31 -0
  31. rbx/grading/grading_context.py +96 -0
  32. rbx/grading/judge/cacher.py +93 -21
  33. rbx/grading/judge/sandbox.py +8 -4
  34. rbx/grading/judge/sandboxes/isolate.py +3 -2
  35. rbx/grading/judge/sandboxes/stupid_sandbox.py +3 -2
  36. rbx/grading/judge/sandboxes/timeit.py +1 -1
  37. rbx/grading/judge/storage.py +170 -35
  38. rbx/grading/profiling.py +126 -0
  39. rbx/grading/steps.py +46 -17
  40. rbx/grading/steps_with_caching.py +52 -26
  41. rbx/resources/envs/default.rbx.yml +2 -3
  42. rbx/resources/envs/isolate.rbx.yml +2 -3
  43. rbx/resources/presets/default/contest/.gitignore +6 -0
  44. rbx/resources/presets/default/contest/contest.rbx.yml +14 -1
  45. rbx/resources/presets/default/contest/statement/contest.rbx.tex +24 -86
  46. rbx/resources/presets/default/contest/statement/instructions.tex +40 -0
  47. rbx/resources/presets/default/contest/statement/logo.png +0 -0
  48. rbx/resources/presets/default/env.rbx.yml +67 -0
  49. rbx/resources/presets/default/preset.rbx.yml +6 -2
  50. rbx/resources/presets/default/problem/.gitignore +1 -1
  51. rbx/resources/presets/default/problem/problem.rbx.yml +12 -8
  52. rbx/resources/presets/default/shared/contest_template.rbx.tex +57 -0
  53. rbx/resources/presets/default/shared/icpc.sty +322 -0
  54. rbx/resources/presets/default/shared/problem_template.rbx.tex +57 -0
  55. rbx/submitors/codeforces.py +3 -2
  56. rbx/test.py +1 -1
  57. rbx/utils.py +6 -1
  58. {rbx_cp-0.7.0.dist-info → rbx_cp-0.9.0.dist-info}/METADATA +4 -1
  59. {rbx_cp-0.7.0.dist-info → rbx_cp-0.9.0.dist-info}/RECORD +67 -58
  60. rbx/resources/presets/default/contest/statement/olymp.sty +0 -250
  61. rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -42
  62. rbx/resources/presets/default/problem/statement/olymp.sty +0 -250
  63. rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -89
  64. /rbx/resources/presets/default/problem/{gen.cpp → gens/gen.cpp} +0 -0
  65. /rbx/resources/presets/default/problem/{tests → manual_tests}/samples/000.in +0 -0
  66. /rbx/resources/presets/default/problem/{tests → manual_tests}/samples/001.in +0 -0
  67. /rbx/resources/presets/default/problem/{random.py → testplan/random.py} +0 -0
  68. /rbx/resources/presets/default/problem/{random.txt → testplan/random.txt} +0 -0
  69. {rbx_cp-0.7.0.dist-info → rbx_cp-0.9.0.dist-info}/LICENSE +0 -0
  70. {rbx_cp-0.7.0.dist-info → rbx_cp-0.9.0.dist-info}/WHEEL +0 -0
  71. {rbx_cp-0.7.0.dist-info → rbx_cp-0.9.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,126 @@
1
+ import contextvars
2
+ import functools
3
+ import math
4
+ import threading
5
+ import time
6
+
7
+ ALL_CONTEXTS_BY_NAME = {}
8
+ _ALL_CONTEXTS_BY_NAME_LOCK = threading.Lock()
9
+
10
+
11
+ @functools.cache
12
+ def _get_threadsafe_context(name: str) -> 'Context':
13
+ with _ALL_CONTEXTS_BY_NAME_LOCK:
14
+ if name not in ALL_CONTEXTS_BY_NAME:
15
+ ALL_CONTEXTS_BY_NAME[name] = Context(name)
16
+ return ALL_CONTEXTS_BY_NAME[name]
17
+
18
+
19
+ class Distribution:
20
+ def __init__(self):
21
+ self.values = []
22
+
23
+ def add(self, value: float):
24
+ self.values.append(value)
25
+
26
+ def mean(self) -> float:
27
+ return sum(self.values) / len(self.values)
28
+
29
+ def median(self) -> float:
30
+ return sorted(self.values)[len(self.values) // 2]
31
+
32
+ def stddev(self) -> float:
33
+ mean = self.mean()
34
+ return math.sqrt(sum((x - mean) ** 2 for x in self.values) / len(self.values))
35
+
36
+
37
+ class Context:
38
+ def __init__(self, name: str):
39
+ self.name = name
40
+ self._lock = threading.Lock()
41
+ self.distributions = {}
42
+ self.counters = {}
43
+
44
+ def add_to_distribution(self, name: str, value: float):
45
+ with self._lock:
46
+ if name not in self.distributions:
47
+ self.distributions[name] = Distribution()
48
+ self.distributions[name].add(value)
49
+
50
+ def add_to_counter(self, name: str):
51
+ with self._lock:
52
+ if name not in self.counters:
53
+ self.counters[name] = 0
54
+ self.counters[name] += 1
55
+
56
+ def print_summary(self):
57
+ with self._lock:
58
+ print(f'{self.name}:')
59
+ for name, distribution in sorted(self.distributions.items()):
60
+ print(f' ~ {name}: {distribution.mean():.2f}')
61
+ for name, count in sorted(self.counters.items()):
62
+ print(f' + {name}: {count}')
63
+
64
+
65
+ profiling_stack_var = contextvars.ContextVar(
66
+ 'profiling_stack', default=[_get_threadsafe_context('root')]
67
+ )
68
+
69
+
70
+ def _push_profiling_stack(name: str):
71
+ return profiling_stack_var.set(
72
+ profiling_stack_var.get() + [_get_threadsafe_context(name)]
73
+ )
74
+
75
+
76
+ class PushContext:
77
+ def __init__(self, name: str):
78
+ self.name = name
79
+ self.token = None
80
+
81
+ def __enter__(self):
82
+ self.token = _push_profiling_stack(self.name)
83
+ return profiling_stack_var.get()[-1]
84
+
85
+ def __exit__(self, exc_type, exc_value, traceback):
86
+ if self.token is not None:
87
+ profiling_stack_var.reset(self.token)
88
+
89
+
90
+ def print_summary():
91
+ print('\n' + ('-') * 3 + '\n')
92
+ with _ALL_CONTEXTS_BY_NAME_LOCK:
93
+ for context in ALL_CONTEXTS_BY_NAME.values():
94
+ context.print_summary()
95
+
96
+
97
+ ### Public API
98
+
99
+
100
+ class Profiler:
101
+ def __init__(self, name: str, start: bool = False):
102
+ self.name = name
103
+ self.start_time = 0
104
+ if start:
105
+ self.start()
106
+
107
+ def start(self):
108
+ self.start_time = time.monotonic()
109
+ return self
110
+
111
+ def stop(self):
112
+ self.end_time = time.monotonic()
113
+ self.duration = self.end_time - self.start_time
114
+ for context in profiling_stack_var.get():
115
+ context.add_to_distribution(self.name, self.duration)
116
+
117
+ def __enter__(self):
118
+ return self.start()
119
+
120
+ def __exit__(self, exc_type, exc_value, traceback):
121
+ self.stop()
122
+
123
+
124
+ def add_to_counter(name: str):
125
+ for context in profiling_stack_var.get():
126
+ context.add_to_counter(name)
rbx/grading/steps.py CHANGED
@@ -20,9 +20,10 @@ from rich.text import Text
20
20
  from rbx import utils
21
21
  from rbx.config import get_bits_stdcpp, get_jngen, get_testlib
22
22
  from rbx.console import console
23
- from rbx.grading import processing_context
23
+ from rbx.grading import grading_context, processing_context
24
+ from rbx.grading.judge.cacher import FileCacher
24
25
  from rbx.grading.judge.sandbox import SandboxBase, SandboxParams
25
- from rbx.grading.judge.storage import Storage, copyfileobj
26
+ from rbx.grading.judge.storage import copyfileobj
26
27
  from rbx.grading.limits import Limits
27
28
 
28
29
  MAX_STDOUT_LEN = 1024 * 1024 * 128 # 128 MB
@@ -139,6 +140,8 @@ class GradingFileInput(BaseModel):
139
140
  digest: Optional[DigestHolder] = None
140
141
  # Whether the destination file should be marked as an executable.
141
142
  executable: bool = False
143
+ # Whether to track file through its hash (disable for optimization).
144
+ hash: bool = True
142
145
 
143
146
 
144
147
  class GradingFileOutput(BaseModel):
@@ -161,15 +164,15 @@ class GradingFileOutput(BaseModel):
161
164
  # Whether to touch the file before the command runs.
162
165
  touch: bool = False
163
166
 
164
- def get_file(self, storage: Storage) -> Optional[IO[bytes]]:
167
+ def get_file(self, cacher: FileCacher) -> Optional[IO[bytes]]:
165
168
  if self.dest is not None:
166
169
  if self.optional and not self.dest.exists():
167
170
  return None
168
171
  return self.dest.open('rb')
169
172
  if self.digest is not None and self.digest.value is not None:
170
- if self.optional and not storage.exists(self.digest.value):
173
+ if self.optional and not cacher.exists(self.digest.value):
171
174
  return None
172
- return storage.get_file(self.digest.value)
175
+ return cacher.get_file(self.digest.value)
173
176
  raise ValueError('No file to get')
174
177
 
175
178
 
@@ -308,11 +311,14 @@ def _process_input_artifacts(artifacts: GradingArtifacts, sandbox: SandboxBase):
308
311
 
309
312
 
310
313
  def _process_output_artifacts(
311
- artifacts: GradingArtifacts, sandbox: SandboxBase
314
+ artifacts: GradingArtifacts,
315
+ sandbox: SandboxBase,
312
316
  ) -> bool:
313
317
  for output_artifact in artifacts.outputs:
314
318
  if output_artifact.hash and output_artifact.digest is None:
315
- output_artifact.digest = DigestHolder()
319
+ if not grading_context.is_no_cache():
320
+ # If cache is enabled, track this file in cache.
321
+ output_artifact.digest = DigestHolder()
316
322
  if not sandbox.file_exists(output_artifact.src):
317
323
  if output_artifact.optional:
318
324
  continue
@@ -322,21 +328,43 @@ def _process_output_artifacts(
322
328
  return False
323
329
 
324
330
  if output_artifact.digest is not None:
325
- output_artifact.digest.value = sandbox.get_file_to_storage(
326
- output_artifact.src, trunc_len=output_artifact.maxlen
327
- )
331
+ # Put it in the cache, possibly compressing it if it's an executable.
332
+ with grading_context.compression(
333
+ use_compression=True,
334
+ when=output_artifact.executable,
335
+ ):
336
+ output_artifact.digest.value = sandbox.get_file_to_storage(
337
+ output_artifact.src, trunc_len=output_artifact.maxlen
338
+ )
328
339
  if output_artifact.dest is None:
329
340
  continue
330
341
  dst: pathlib.Path = artifacts.root / output_artifact.dest
331
342
  # Ensure dst directory exists.
343
+
332
344
  dst.parent.mkdir(parents=True, exist_ok=True)
333
- with dst.open('wb') as f:
334
- with sandbox.get_file(output_artifact.src) as sb_f:
335
- copyfileobj(
336
- sb_f,
337
- f,
338
- maxlen=output_artifact.maxlen,
345
+
346
+ if (
347
+ output_artifact.digest is not None
348
+ and output_artifact.digest.value is not None
349
+ and (
350
+ path_to_symlink := sandbox.file_cacher.path_for_symlink(
351
+ output_artifact.digest.value
339
352
  )
353
+ )
354
+ is not None
355
+ ):
356
+ # File is in the persistent cache, store a symlink to it.
357
+ dst.unlink(missing_ok=True)
358
+ dst.symlink_to(path_to_symlink)
359
+ else:
360
+ # File is not in the persistent cache, copy it.
361
+ with dst.open('wb') as f:
362
+ with sandbox.get_file(output_artifact.src) as sb_f:
363
+ copyfileobj(
364
+ sb_f,
365
+ f,
366
+ maxlen=output_artifact.maxlen,
367
+ )
340
368
  if output_artifact.executable:
341
369
  dst.chmod(0o755)
342
370
  return True
@@ -495,7 +523,8 @@ def _get_system_bits_stdcpp(command: str) -> Optional[GradingFileInput]:
495
523
  if not bits_candidate.is_file():
496
524
  continue
497
525
  return GradingFileInput(
498
- src=bits_candidate.resolve().absolute(), dest=pathlib.Path('bits/stdc++.h')
526
+ src=utils.abspath(bits_candidate),
527
+ dest=pathlib.Path('bits/stdc++.h'),
499
528
  )
500
529
  return None
501
530
 
@@ -1,6 +1,6 @@
1
1
  from typing import Any, Dict, List, Optional, Tuple
2
2
 
3
- from rbx.grading import steps
3
+ from rbx.grading import grading_context, profiling, steps
4
4
  from rbx.grading.caching import DependencyCache, NoCacheException
5
5
  from rbx.grading.judge.sandbox import SandboxBase, SandboxParams
6
6
  from rbx.grading.steps import (
@@ -27,17 +27,24 @@ def compile(
27
27
  artifacts.logs = GradingLogsHolder()
28
28
 
29
29
  ok = True
30
+ cached_profile = profiling.Profiler('steps.compile[cached]', start=True)
30
31
  with dependency_cache(
31
32
  commands, [artifacts], params.get_cacheable_params()
32
33
  ) as is_cached:
33
- if not is_cached and not steps.compile(
34
- commands=commands,
35
- params=params,
36
- artifacts=artifacts,
37
- sandbox=sandbox,
38
- ):
39
- ok = False
40
- raise NoCacheException()
34
+ if not is_cached:
35
+ with profiling.Profiler('steps.compile'):
36
+ profiling.add_to_counter('steps.compile')
37
+ ok = steps.compile(
38
+ commands=commands,
39
+ params=params,
40
+ artifacts=artifacts,
41
+ sandbox=sandbox,
42
+ )
43
+ if not ok:
44
+ raise NoCacheException()
45
+ else:
46
+ cached_profile.stop()
47
+ profiling.add_to_counter('steps.compile[cached]')
41
48
 
42
49
  return ok
43
50
 
@@ -56,16 +63,25 @@ async def run(
56
63
  if metadata is not None and metadata.retryIndex is not None:
57
64
  cacheable_params['__retry_index__'] = metadata.retryIndex
58
65
 
59
- with dependency_cache([command], [artifacts], cacheable_params) as is_cached:
60
- if not is_cached:
61
- await steps.run(
62
- command=command,
63
- params=params,
64
- artifacts=artifacts,
65
- sandbox=sandbox,
66
- metadata=metadata,
67
- )
68
-
66
+ with grading_context.cache_level(
67
+ grading_context.CacheLevel.NO_CACHE,
68
+ when=grading_context.is_compilation_only,
69
+ ):
70
+ cached_profile = profiling.Profiler('steps.run[cached]', start=True)
71
+ with dependency_cache([command], [artifacts], cacheable_params) as is_cached:
72
+ if not is_cached:
73
+ with profiling.Profiler('steps.run'):
74
+ profiling.add_to_counter('steps.run')
75
+ await steps.run(
76
+ command=command,
77
+ params=params,
78
+ artifacts=artifacts,
79
+ sandbox=sandbox,
80
+ metadata=metadata,
81
+ )
82
+ else:
83
+ cached_profile.stop()
84
+ profiling.add_to_counter('steps.run[cached]')
69
85
  return artifacts.logs.run
70
86
 
71
87
 
@@ -91,13 +107,23 @@ async def run_coordinated(
91
107
  if solution.metadata is not None and solution.metadata.retryIndex is not None:
92
108
  cacheable_params['solution.__retry_index__'] = solution.metadata.retryIndex
93
109
 
94
- with dependency_cache(
95
- [interactor.command, solution.command],
96
- [interactor.artifacts, solution.artifacts],
97
- cacheable_params,
98
- ) as is_cached:
99
- if not is_cached:
100
- await steps.run_coordinated(interactor, solution)
110
+ with grading_context.cache_level(
111
+ grading_context.CacheLevel.NO_CACHE,
112
+ when=grading_context.is_compilation_only,
113
+ ):
114
+ cached_profile = profiling.Profiler('steps.run_coordinated[cached]', start=True)
115
+ with dependency_cache(
116
+ [interactor.command, solution.command],
117
+ [interactor.artifacts, solution.artifacts],
118
+ cacheable_params,
119
+ ) as is_cached:
120
+ if not is_cached:
121
+ with profiling.Profiler('steps.run_coordinated'):
122
+ profiling.add_to_counter('steps.run_coordinated')
123
+ await steps.run_coordinated(interactor, solution)
124
+ else:
125
+ cached_profile.stop()
126
+ profiling.add_to_counter('steps.run_coordinated[cached]')
101
127
 
102
128
  return (
103
129
  interactor.artifacts.logs.run,
@@ -18,7 +18,7 @@ defaultExecution:
18
18
  memoryLimit: 1024 # 1gb
19
19
  languages:
20
20
  - name: "cpp"
21
- readable_name: "C++17"
21
+ readableName: "C++17"
22
22
  extension: "cpp"
23
23
  compilation:
24
24
  commands:
@@ -28,10 +28,9 @@ languages:
28
28
  fileMapping:
29
29
  compilable: "compilable.cpp"
30
30
  - name: "py"
31
- readable_name: "Python3"
31
+ readableName: "Python3"
32
32
  extension: "py"
33
33
  execution:
34
34
  command: "python3 {executable}"
35
35
  fileMapping:
36
36
  executable: "executable.py"
37
-
@@ -18,7 +18,7 @@ defaultExecution:
18
18
  memoryLimit: 1024 # 1gb
19
19
  languages:
20
20
  - name: "cpp"
21
- readable_name: "C++17"
21
+ readableName: "C++17"
22
22
  extension: "cpp"
23
23
  compilation:
24
24
  commands:
@@ -28,10 +28,9 @@ languages:
28
28
  fileMapping:
29
29
  compilable: "compilable.cpp"
30
30
  - name: "py"
31
- readable_name: "Python3"
31
+ readableName: "Python3"
32
32
  extension: "py"
33
33
  execution:
34
34
  command: "/usr/bin/python3 {executable}"
35
35
  fileMapping:
36
36
  executable: "executable.py"
37
-
@@ -0,0 +1,6 @@
1
+ .box/
2
+ build/
3
+
4
+ *.o
5
+ *.aux
6
+ *.log
@@ -8,9 +8,22 @@ statements:
8
8
  language: "en"
9
9
  path: "statement/contest.rbx.tex"
10
10
  type: "jinja-tex"
11
- assets: ["statement/olymp.sty", "statement/*.png"]
11
+ assets:
12
+ - "statement/icpc.sty"
13
+ - "statement/*.png"
14
+ - "statement/instructions.tex"
12
15
  joiner: {type: "tex2pdf"}
13
16
  override:
14
17
  configure:
15
18
  - type: "rbx-tex" # Convert rbxTeX to TeX
16
19
  template: "statement/template.rbx.tex"
20
+ - name: "editorial-en"
21
+ extends: "statement-en"
22
+ vars:
23
+ editorial: true
24
+ watermark: true
25
+ # Whether to show the problem statement in the editorial.
26
+ show_problem: false
27
+ vars:
28
+ year: 2025
29
+ date: "2025-06-21"
@@ -1,97 +1,35 @@
1
-
2
- \documentclass[titlepage, oneside, a4paper]{article}
3
-
4
- \usepackage {import}
5
- \usepackage[margin=25mm, left=17mm, right=17mm]{geometry}
6
- \usepackage[utf8]{inputenc}
7
- \usepackage[english]{babel}
8
- \usepackage{amsmath}
9
- \usepackage{amssymb}
10
- \usepackage{fancyhdr}
11
- \usepackage{comment}
12
- \usepackage{olymp}
13
- \usepackage{epigraph}
14
- \usepackage{expdlist}
15
- \usepackage{graphicx}
16
- \usepackage{ulem}
17
- \usepackage{lastpage}
18
-
19
- %- for problem in problems
20
- %- if problem.blocks.preamble is defined
21
- \VAR{problem.blocks.preamble}
1
+ \documentclass[a4paper,11pt]{article}
2
+
3
+ \def\lang{\VAR{lang}}
4
+ \usepackage{icpc}
5
+ \usepackage{import}
6
+
7
+ \def\Year{\VAR{vars.year}}
8
+ \def\Title{\VAR{contest.title}}
9
+ \def\Date{\VAR{vars.date}}
10
+
11
+ %- if vars.editorial is truthy and vars.watermark is truthy
12
+ \AddToHook{shipout/foreground}{
13
+ \begin{tikzpicture}[overlay, remember picture]
14
+ \node[text=gray, rotate=45, scale=8, opacity=0.3]
15
+ at (0.5\paperwidth,-0.6\paperheight) {EDITORIAL};
16
+ \end{tikzpicture}
17
+ }
22
18
  %- endif
23
- %- endfor
24
-
25
- \def\showSourceFileName{1}
26
- \newif\ifintentionallyblankpages % comment this out to add blank pages
27
-
28
- \pagestyle{fancy}
29
- \fancyhf{}
30
- \renewcommand{\footrulewidth}{0.4pt}
31
-
32
- %- if contest is defined
33
- \title{\VAR{contest.title or ""}}
34
- \author{\VAR{contest.location if contest.location is defined else ""}}
35
- \date{\VAR{contest.date if contest.date is defined else ""}}
36
- %- else
37
- \title{}
38
- \author{}
39
- \date{}
40
- %- endif
41
-
42
- \makeatletter
43
- \let\newtitle\@title
44
- \let\newauthor\@author
45
- \let\newdate\@date
46
- \makeatother
47
-
48
- \rhead{\newtitle}
49
- \lhead{\newauthor}
50
- \lfoot{\newdate}
51
- \rfoot{\thepage}
52
19
 
53
20
  \begin{document}
54
21
 
55
- %- if contest is defined
56
- \begin{frontpage}{\newtitle}{\newauthor}{\newdate}
57
- \begin{itemize}
58
- \item Sobre a prova:
59
- \begin{enumerate}
60
- \item A prova tem duração de 5 horas;
61
- \end{enumerate}
62
- \item Sobre a entrada:
63
- \begin{enumerate}
64
- \item A entrada do seu programa deve ser lida da entrada padrão (standard input);
65
- \item Quando uma linha da entrada contém vários valores, estes são separados por um único espaço em branco, a menos que explicitado o contrário no enunciado do problema;
66
- \item Toda linha da entrada terminará com um caractere final-de-linha.
67
- \end{enumerate}
68
-
69
- \item Sobre a saída:
70
- \begin{enumerate}
71
- \item A saída de seu programa deve ser escrita na saída padrão;
72
- \item Quando uma linha da saída contém vários valores, estes devem ser separados por um único espaço em branco, a menos que explicitado o contrário no enunciado do problema;
73
- \item Toda linha da saída deve terminar com um caractere final-de-linha.
74
- \end{enumerate}
75
-
76
- \item Sobre as submissões:
77
- \begin{enumerate}
78
- \item Você deve submeter o código fonte das suas soluções;
79
- \item Os comandos utilizados para compilação serão:
80
- \begin{enumerate}
81
- %- for language in languages:
82
- \item \VAR{language.name | escape}: \VAR{language.command | escape}
83
- %- endfor
84
- \end{enumerate}
85
- \item Para linguagem Java, o nome da classe principal do arquivo deve ser \textbf{Main}. A classe deve ser pública.
86
- \end{enumerate}
87
- \centering\vspace*{\fill}\textbf{Este caderno contém \VAR{problems | length} problema(s) e \pageref{LastPage} página(s)} \\
88
- \vspace*{\fill}
89
- \end{itemize}
90
- \end{frontpage}
22
+ %- if vars.editorial is truthy
23
+ \InsertEditorialTitlePage
24
+ %- else
25
+ \InsertTitlePage
26
+ \input{instructions.tex}
91
27
  %- endif
92
28
 
93
29
  %- for problem in problems
30
+ \stepcounter{problemcounter}
94
31
  \subimport{\VAR{problem.path | parent}/}{\VAR{problem.path | stem}}
95
32
  %- endfor
96
33
 
34
+ \label{lastpage}
97
35
  \end{document}
@@ -0,0 +1,40 @@
1
+ \section*{General Information}
2
+
3
+ This task sheet consists of \pageref*{lastpage} pages (not counting the cover), numbered from 1 to \pageref*{lastpage}. Check if the sheet is complete.
4
+
5
+ \subsection*{Input}
6
+
7
+ \begin{itemize}
8
+ \item The input must be read from standard input.
9
+
10
+ \item All lines in the input, including the last one, end with a line break character (\texttt{\textbackslash n}).
11
+
12
+ \item When the input contains multiple space-separated values, there is exactly one whitespace character between two consecutive values on the same line.
13
+ \end{itemize}
14
+
15
+ \subsection*{Output}
16
+
17
+ \begin{itemize}
18
+ \item The output must be written to standard output.
19
+
20
+ \item The output must follow the format specified in the problem statement. The output must not contain any extra data.
21
+
22
+ \item All lines in the output, including the last one, must end with a line break character (\texttt{\textbackslash n}).
23
+
24
+ \item When a line in the output displays multiple space-separated values, there must be exactly one whitespace character between two consecutive values.
25
+
26
+ \item When an output value is a real number, use at least the number of decimal places corresponding to the precision required in the problem statement.
27
+ \end{itemize}
28
+
29
+ % \subsection*{Interactive Problems}
30
+
31
+ % The contest may contain interactive problems. In this type of problem, the input data provided to your program may not be predetermined but is instead specifically constructed for your solution. The judge writes a special program (the interactor), whose output is transferred to your solution's input, and your program's output is sent to the interactor's input. In other words, your solution and the interactor exchange data and may decide what to print based on the communication history.
32
+
33
+ % When writing a solution for an interactive problem, it is important to remember that if you print any data, it may first be stored in an internal \textit{buffer} and not immediately transferred to the interactor. To avoid this situation, you must use a special \textit{flush} operation every time you print data. These flush operations are available in the standard libraries of almost all programming languages:
34
+
35
+ % \begin{itemize}
36
+ % \item \texttt{fflush(stdout)} in \texttt{C}.
37
+ % \item \texttt{cout.flush()} in \texttt{C++}.
38
+ % \item \texttt{sys.stdout.flush()} in \texttt{Python}.
39
+ % \item \texttt{System.out.flush()} in \texttt{Java}.
40
+ % \end{itemize}
@@ -0,0 +1,67 @@
1
+ ---
2
+ sandbox: "stupid"
3
+ defaultCompilation:
4
+ sandbox:
5
+ maxProcesses: 1000
6
+ timeLimit: 50000 # 50 seconds
7
+ wallTimeLimit: 50000 # 50 seconds
8
+ memoryLimit: 1024 # 1gb
9
+ defaultExecution:
10
+ sandbox:
11
+ # Useful for checkers, validators, etc.
12
+ timeLimit: 50000 # 50 seconds
13
+ wallTimeLimit: 50000 # 50 seconds
14
+ memoryLimit: 1024 # 1gb
15
+ languages:
16
+ - name: "cpp"
17
+ readableName: "C++20"
18
+ extension: "cpp"
19
+ compilation:
20
+ commands: ["g++ -std=c++20 -O2 -o {executable} {compilable}"]
21
+ execution:
22
+ command: "./{executable}"
23
+ fileMapping:
24
+ compilable: "compilable.cpp"
25
+ extensions:
26
+ boca:
27
+ bocaLanguage: "cc"
28
+ - name: "c"
29
+ readableName: "C"
30
+ extension: "c"
31
+ compilation:
32
+ commands: ["gcc -std=gnu11 -O2 -lm -o {executable} {compilable}"]
33
+ execution:
34
+ command: "./{executable}"
35
+ fileMapping:
36
+ compilable: "compilable.c"
37
+ - name: "py"
38
+ readableName: "Python3"
39
+ extension: "py"
40
+ execution:
41
+ command: "python3 {executable}"
42
+ fileMapping:
43
+ executable: "executable.py"
44
+ extensions:
45
+ boca:
46
+ bocaLanguage: "py3"
47
+ - name: "java"
48
+ readableName: "Java"
49
+ extension: "java"
50
+ compilation:
51
+ commands:
52
+ - "javac -Xlint -encoding UTF-8 {compilable}"
53
+ - "jar cvf {executable} @glob:*.class"
54
+ execution:
55
+ command:
56
+ "java -Xss100m -Xmx{{memory}}m -Xms{{initialMemory}}m -cp {executable}
57
+ Main"
58
+ fileMapping:
59
+ compilable: "Main.java"
60
+ executable: "Main.jar"
61
+ extensions:
62
+ boca:
63
+ languages: ["c", "cc", "java", "py3"]
64
+ flags:
65
+ c: "-O2 -lm -static"
66
+ cc: "-std=c++20 -O2 -lm -static"
67
+ preferContestLetter: true
@@ -4,11 +4,15 @@ name: "default"
4
4
  uri: "rsalesc/rbx/rbx/resources/presets/default"
5
5
  problem: "problem"
6
6
  contest: "contest"
7
+ env: "env.rbx.yml"
7
8
  tracking:
8
9
  problem:
10
+ - path: ".gitignore"
11
+ - path: "statement/icpc.sty"
9
12
  - path: "statement/template.rbx.tex"
10
- - path: "statement/olymp.sty"
11
13
  contest:
14
+ - path: ".gitignore"
15
+ - path: "statement/icpc.sty"
12
16
  - path: "statement/template.rbx.tex"
13
- - path: "statement/olymp.sty"
14
17
  - path: "statement/contest.rbx.tex"
18
+ symlink: true