Skip to content

Commit c2ce2d9

Browse files
mzuennimpsijm
authored andcommitted
use multipass dir
1 parent 1e23309 commit c2ce2d9

File tree

9 files changed

+149
-22
lines changed

9 files changed

+149
-22
lines changed

bin/run.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,9 @@ def _continue_with_tle(self, verdict, timeout_expired):
207207
def _prepare_nextpass(self, nextpass):
208208
if not nextpass or not nextpass.is_file():
209209
return False
210-
# clear all files outside of feedbackdir
210+
# TODO: keep feedback files and concatenate them?
211+
# - judgemessage.txt
212+
# - judgeerror.txt
211213
for f in self.tmpdir.iterdir():
212214
if f == self.feedbackdir:
213215
continue
@@ -216,7 +218,15 @@ def _prepare_nextpass(self, nextpass):
216218
elif f.exists():
217219
shutil.rmtree(f)
218220
# use nextpass.in as next input
219-
shutil.move(nextpass, self.in_path)
221+
nextpass.rename(self.in_path)
222+
# clear all files outside of "feedbackdir / multipass"
223+
for f in self.feedbackdir.iterdir():
224+
if f == self.feedbackdir / "multipass":
225+
continue
226+
if f.is_file():
227+
f.unlink()
228+
elif f.exists():
229+
shutil.rmtree(f)
220230
return True
221231

222232
def _validate_output(self, bar: BAR_TYPE) -> Optional[ExecResult]:
@@ -441,7 +451,7 @@ def process_run(run: Run):
441451
for f in run.feedbackdir.iterdir():
442452
if f.name.startswith("."):
443453
continue # skip "hidden" files
444-
if f.name in ["judgemessage.txt", "judgeerror.txt"]:
454+
if f.name in ["judgemessage.txt", "judgeerror.txt", "multipass"]:
445455
continue
446456
if f.name.startswith("judgeimage.") or f.name.startswith("teamimage."):
447457
data += f"{f.name}: {shorten_path(self.problem, f.parent) / f.name}\n"

bin/validate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ def run(
403403
cwd, constraints_path, arglist = self._run_helper(testcase, constraints, args)
404404
if not isinstance(mode, Mode):
405405
cwd = mode.feedbackdir
406+
if self.problem.multi_pass:
407+
multipassdir = cwd / "multipass"
408+
multipassdir.mkdir(parents=True, exist_ok=True)
406409
invocation = self.run_command + [in_path, ans_path, cwd]
407410

408411
with path.open("rb") as file:

test/problems/alternativeencryption/output_validator/validate.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,30 +1572,30 @@ namespace Multipass {
15721572
void init() {
15731573
judgeAssert<std::logic_error>(::details::initialized(), "validate.h: Multipass::init() was called before init(argc, argv)!");
15741574

1575-
auto path = std::filesystem::path(arguments[3]) / ".pass";
1575+
auto multipassdir = std::filesystem::path(arguments[3]) / "multipass";
1576+
auto passfile = multipassdir / ".pass";
15761577
std::string nextfile = ".state0";
15771578
std::string prevfile = ".state1";
1578-
if (std::filesystem::exists(path)) {
1579-
std::ifstream in(path);
1579+
if (std::filesystem::exists(passfile)) {
1580+
std::ifstream in(passfile);
15801581
in >> pass;
15811582
pass++;
15821583
if ((pass & 1) != 0) {
15831584
std::swap(nextfile, prevfile);
15841585
}
1585-
prevstate = InputStream(std::filesystem::path(arguments[3]) / prevfile, false, true, juryOut, Verdicts::FAIL);
1586+
prevstate = InputStream(multipassdir / prevfile, false, true, juryOut, Verdicts::FAIL);
15861587
} else {
15871588
pass = 0;
15881589
}
1589-
std::filesystem::remove(std::filesystem::path(arguments[3]) / nextfile);
1590-
nextstate = OutputStream(std::filesystem::path(arguments[3]) / nextfile, std::ios::out);
1590+
std::filesystem::remove(multipassdir / nextfile);
1591+
nextstate = OutputStream(multipassdir / nextfile, std::ios::out);
15911592
nextpass = OutputStream(details::nextpassBuffer);
1592-
std::ofstream out(path);
1593-
out << pass;
1593+
std::ofstream(passfile) << pass;
15941594
}
15951595

15961596
[[noreturn]] void NEXT() {
15971597
{
1598-
std::ofstream file(std::filesystem::path(arguments[3]) / "nextpass.in");
1598+
std::ofstream file(std::filesystem::path(arguments[3]) / "nextpass.in"); // this should not be in the multipass subdirectory!
15991599
judgeAssert<std::runtime_error>(file.good(), "NEXT(): Could not open file: nextpass.in");
16001600
file << details::nextpassBuffer.str();
16011601
}
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
problem_format_version: 2023-07-draft
22
type: multi-pass
33
name:
4-
#lang: name
54
en: Alternative Encryption
65
credits:
7-
# Contest name and year
86
authors: Thomas Beuman
97
source:
108
name: NWERC 2024 Test Session
119
url: https://2024.nwerc.eu
1210
uuid: 8ee7605a-95a3-86c2-3995-0a10d365de46
1311
license: cc by-sa
1412
rights_owner: author
15-
limits:
16-
time_limit: 1.0
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
\begin{frame}
2+
\frametitle{\problemtitle}
3+
\begin{block}{Problem}
4+
This is a multi-pass problem, where in each pass, you should:
5+
\vspace{-0.5em}
6+
\begin{enumerate}
7+
\item Encrypt text, such that the length stays the same and every character differs.
8+
\item Decrypt the text that you encrypted, such that you retrieve the original input.
9+
\end{enumerate}
10+
\end{block}
11+
\pause
12+
\begin{block}{Solution}
13+
Some of the many possible solutions (there were some resubmissions):
14+
\begin{itemize}
15+
\addtolength{\leftmargini}{15ex}
16+
\small
17+
\item ($70\times$) Use a Caesar cipher with offset $1 \leq x < 26$ for encrypting, and offset $26 - x$ for decrypting.
18+
\item ($14\times$) Use a Caesar cipher with offset $13$ for both encrypting and decrypting.
19+
\item ($2\times$) Assuming $0$-based \texttt{char} values, XOR the last bit of each value
20+
(`\texttt{a}' $\leftrightarrow$ `\texttt{b}',
21+
`\texttt{c}' $\leftrightarrow$ `\texttt{d}', \dots).
22+
\item ($1\times$) Atbash: Mirror the characters (`\texttt{a}' $\leftrightarrow$ `\texttt{z}',
23+
`\texttt{b}' $\leftrightarrow$ `\texttt{y}', \dots)
24+
for both encrypting and decrypting.
25+
\item ($1\times$) Generate a (seeded) random permutation to encrypt, and use its inverse to decrypt.
26+
\end{itemize}
27+
\end{block}
28+
\pause
29+
\solvestats
30+
\end{frame}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env python3
2+
from pathlib import Path
3+
4+
mode = input()
5+
n = int(input())
6+
7+
8+
def rot(x):
9+
return chr(ord("a") + (ord(x) - ord("a") + 13) % 26)
10+
11+
12+
words = []
13+
14+
for _ in range(n):
15+
word = input()
16+
words.append(word)
17+
print(*(rot(x) for x in word), sep="")
18+
19+
file = Path(".data")
20+
if mode == "encrypt":
21+
file.write_text("\n".join(words))
22+
if mode == "decrypt":
23+
words = file.read_text()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env python3
2+
from pathlib import Path
3+
4+
mode = input()
5+
n = int(input())
6+
7+
8+
def rot(x):
9+
return chr(ord("a") + (ord(x) - ord("a") + 13) % 26)
10+
11+
12+
words = []
13+
14+
for _ in range(n):
15+
word = input()
16+
words.append(word)
17+
print(*(rot(x) for x in word), sep="")
18+
19+
file = Path("data")
20+
if mode == "encrypt":
21+
file.write_text("\n".join(words))
22+
if mode == "decrypt":
23+
words = file.read_text()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env python3
2+
from pathlib import Path
3+
4+
mode = input()
5+
n = int(input())
6+
7+
8+
def rot(x):
9+
return chr(ord("a") + (ord(x) - ord("a") + 13) % 26)
10+
11+
12+
words = []
13+
14+
for _ in range(n):
15+
word = input()
16+
words.append(word)
17+
print(*(rot(x) for x in word), sep="")
18+
19+
file = Path("/tmp/nwerc_alternativeencryption_data")
20+
if mode == "encrypt":
21+
file.write_text("\n".join(words))
22+
if mode == "decrypt":
23+
words = file.read_text()

test/problems/interactivemultipass/output_validator/interctive_multipass_validator.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,38 @@
22
import sys
33
import pathlib
44

5+
6+
def wrong_answer(message: str):
7+
judgemessage = pathlib.Path(sys.argv[3]) / "judgemessage.txt"
8+
judgemessage.write_text(message)
9+
sys.exit(43) # WA
10+
11+
512
test_in = int(pathlib.Path(sys.argv[1]).read_text())
613
print(test_in) # Simulate behaviour of normal multipass problem
7-
team_ans = int(input())
14+
try:
15+
team_ans_string = input()
16+
try:
17+
team_ans = int(team_ans_string)
18+
except ValueError:
19+
wrong_answer(f"team output '{team_ans_string}' is not an integer")
20+
except EOFError:
21+
wrong_answer("no input from team")
22+
823
if test_in < 0:
924
# first pass
1025
if team_ans < 0:
11-
sys.exit(43) # WA
26+
wrong_answer(f"1st pass: team output ({team_ans}) is negative")
1227
nextpass = pathlib.Path(sys.argv[3]) / "nextpass.in"
1328
nextpass.write_text(str(team_ans))
1429
sys.exit(42) # AC + nextpass.in => next run
1530
else:
1631
# second pass
17-
if test_in == team_ans:
18-
sys.exit(42) # AC
19-
else:
20-
sys.exit(43) # WA
32+
if test_in != team_ans:
33+
wrong_answer(f"2nd pass: team output ({team_ans}) is not equal to test input ({test_in})")
34+
35+
try:
36+
more_input = input()
37+
wrong_answer(f'extra input from team, starting with "{more_input}"')
38+
except EOFError:
39+
sys.exit(42) # AC

0 commit comments

Comments
 (0)