Init. import
This commit is contained in:
8
Marathon-PPC/README.md
Normal file
8
Marathon-PPC/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Информация для участников
|
||||
> Каждый уважающий себя CTFер обязан решать 150 примеров за 10 секунд
|
||||
|
||||
## Решение
|
||||
Готовый скрипт: [solve/solve.py](solve/solver.py).
|
||||
|
||||
## Флаг
|
||||
`caplag{There_1s_n0thing_m0re_1mp0rtant_f0r_pract1ce_than_g00d_the0ry}`
|
||||
162
Marathon-PPC/solve/solver.py
Normal file
162
Marathon-PPC/solve/solver.py
Normal file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import math
|
||||
import socket
|
||||
from typing import List, Tuple
|
||||
|
||||
|
||||
def fib_fast(n: int) -> int:
|
||||
def f(k: int) -> Tuple[int, int]:
|
||||
if k == 0:
|
||||
return (0, 1)
|
||||
a, b = f(k >> 1)
|
||||
c = a * (2 * b - a)
|
||||
d = a * a + b * b
|
||||
if k & 1:
|
||||
return (d, c + d)
|
||||
else:
|
||||
return (c, d)
|
||||
return f(n)[0]
|
||||
|
||||
|
||||
def arith_sum(a: int, b: int, s: int) -> int:
|
||||
|
||||
n = (b - a) // s + 1
|
||||
return n * (a + b) // 2
|
||||
|
||||
|
||||
def integral_poly(a: int, b: int, coeff: List[int]) -> int:
|
||||
|
||||
res = 0
|
||||
for k, c in enumerate(coeff):
|
||||
e = k + 1
|
||||
if c % e != 0:
|
||||
raise ValueError("Non-integer term encountered; protocol assumption violated")
|
||||
ce = c // e
|
||||
res += ce * (pow(b, e) - pow(a, e))
|
||||
return res
|
||||
|
||||
|
||||
def eval_expr(expr: str) -> int:
|
||||
t = expr.strip().split()
|
||||
if not t:
|
||||
raise ValueError("Empty expression")
|
||||
op = t[0]
|
||||
|
||||
def i(x: str) -> int:
|
||||
return int(x)
|
||||
|
||||
if op == "plus":
|
||||
return i(t[1]) + i(t[2])
|
||||
if op == "minus":
|
||||
return i(t[1]) - i(t[2])
|
||||
if op == "times":
|
||||
return i(t[1]) * i(t[2])
|
||||
if op == "div":
|
||||
a, b = i(t[1]), i(t[2])
|
||||
return a // b
|
||||
if op == "mod":
|
||||
a, b = i(t[1]), i(t[2])
|
||||
return a % b
|
||||
if op == "pow":
|
||||
a, b = i(t[1]), i(t[2])
|
||||
return pow(a, b)
|
||||
if op == "sqrt":
|
||||
a = i(t[1])
|
||||
r = math.isqrt(a)
|
||||
return r
|
||||
if op == "abs":
|
||||
return abs(i(t[1]))
|
||||
if op == "fact":
|
||||
return math.factorial(i(t[1]))
|
||||
if op == "gcd":
|
||||
return math.gcd(i(t[1]), i(t[2]))
|
||||
if op == "lcm":
|
||||
a, b = i(t[1]), i(t[2])
|
||||
g = math.gcd(a, b)
|
||||
return a // g * b
|
||||
if op == "det2":
|
||||
a, b, c, d = i(t[1]), i(t[2]), i(t[3]), i(t[4])
|
||||
return a * d - b * c
|
||||
if op == "det3":
|
||||
a, b, c = i(t[1]), i(t[2]), i(t[3])
|
||||
d, e, f = i(t[4]), i(t[5]), i(t[6])
|
||||
g, h, j = i(t[7]), i(t[8]), i(t[9])
|
||||
return a * (e * j - f * h) - b * (d * j - f * g) + c * (d * h - e * g)
|
||||
if op == "sum":
|
||||
if t[3] != "step":
|
||||
raise ValueError("Expected 'step' in sum expression")
|
||||
a, b, s = i(t[1]), i(t[2]), i(t[4])
|
||||
return arith_sum(a, b, s)
|
||||
if op == "fib":
|
||||
return fib_fast(i(t[1]))
|
||||
if op == "lin1":
|
||||
a, b, c = i(t[1]), i(t[2]), i(t[3])
|
||||
return (c - b) // a
|
||||
if op == "lin2x":
|
||||
a1, b1, c1, a2, b2, c2 = i(t[1]), i(t[2]), i(t[3]), i(t[4]), i(t[5]), i(t[6])
|
||||
D = a1 * b2 - a2 * b1
|
||||
return (c1 * b2 - c2 * b1) // D
|
||||
if op == "lin2y":
|
||||
a1, b1, c1, a2, b2, c2 = i(t[1]), i(t[2]), i(t[3]), i(t[4]), i(t[5]), i(t[6])
|
||||
D = a1 * b2 - a2 * b1
|
||||
return (a1 * c2 - a2 * c1) // D
|
||||
if op == "integral":
|
||||
a, b = i(t[1]), i(t[2])
|
||||
if t[3] != "poly":
|
||||
raise ValueError("Expected 'poly' in integral expression")
|
||||
coeff = list(map(int, t[4:]))
|
||||
return integral_poly(a, b, coeff)
|
||||
|
||||
raise ValueError(f"Unknown operator: {op}")
|
||||
|
||||
|
||||
def run(host: str, port: int):
|
||||
with socket.create_connection((host, port)) as sock:
|
||||
sock_file = sock.makefile("rwb", buffering=0)
|
||||
pending = None # (expr_str, answer)
|
||||
while True:
|
||||
line = sock_file.readline()
|
||||
if not line:
|
||||
break
|
||||
try:
|
||||
s = line.decode().rstrip("\r\n")
|
||||
except Exception:
|
||||
continue
|
||||
print(f"[SRV] {s}")
|
||||
|
||||
if s.startswith("Task ") and ":" in s:
|
||||
try:
|
||||
expr = s.split(":", 1)[1].strip()
|
||||
except Exception:
|
||||
expr = ""
|
||||
ans = eval_expr(expr)
|
||||
pending = (expr, ans)
|
||||
print(f"[SOLVE] {expr} => {ans}")
|
||||
continue
|
||||
|
||||
if s.strip().startswith(">") and pending is not None:
|
||||
print(f"[SEND] {pending[1]}")
|
||||
ans_bytes = str(pending[1]).encode() + b"\n"
|
||||
sock_file.write(ans_bytes)
|
||||
sock_file.flush()
|
||||
pending = None
|
||||
continue
|
||||
|
||||
if "Here is your flag:" in s or s.endswith("Bye."):
|
||||
print(s)
|
||||
continue
|
||||
|
||||
|
||||
def main():
|
||||
host = sys.argv[1] if len(sys.argv) >= 2 else os.getenv("HOST", "127.0.0.1")
|
||||
port = int(sys.argv[2]) if len(sys.argv) >= 3 else int(os.getenv("PORT", "5000"))
|
||||
run(host, port)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user