WeChall - Flow Over Astronomy

Flow Over Astronomy (Coding, Math) by anto 自定义进制大整数计算,必须在 3.1416 秒内提交结果

Challenge

页面给出一个 charset、input base、solution base,以及一串用 input base 表示的等式。计算结果并以 solution base 表示提交。限时 3.1416 秒。

典型输入:

1
2
3
4
5
Charset: hpQiNnoSt2E_guqOHd5j]P3v01wKZFk}{c8L6fmbDsMlVU7T[IzRYeWxGaB4#@JC9yrAX
Input Base: 52
Solution Base: 25

js6Q * zQwi * 0_Qm * pOZTc * RS_m * QthQf * ... + HjRq
  • Base N 使用 charset 的前 N 个字符做编码表
  • 等式结构:一长串乘法,末尾 + 一个数(全部是 input base 编码)

Solution

两个转换函数搞定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def from_base(s, charset, base):
value = 0
table = {ch: i for i, ch in enumerate(charset[:base])}
for ch in s:
value = value * base + table[ch]
return value

def to_base(n, charset, base):
if n == 0:
return charset[0]
out = []
while n:
n, r = divmod(n, base)
out.append(charset[r])
return ''.join(reversed(out))

完整解法(抓题、计算、提交):

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
import re, sys
from urllib.request import Request, urlopen

CHALL_URL = 'http://www.wechall.net/en/challenge/anto/FlowOverAstronomy/index.php'
COOKIE = 'WC=...'

def fetch():
req = Request(CHALL_URL, headers={'Cookie': COOKIE})
return urlopen(req, timeout=10).read().decode()

def from_base(s, charset, base):
table = {ch: i for i, ch in enumerate(charset[:base])}
v = 0
for ch in s: v = v * base + table[ch]
return v

def to_base(n, charset, base):
if n == 0: return charset[0]
out = []
while n: n, r = divmod(n, base); out.append(charset[r])
return ''.join(reversed(out))

html = fetch()
# Parse parameters
charset = re.search(r'Charset:\s*(\S+)', html).group(1)
in_base = int(re.search(r'Input Base:\s*(\d+)', html).group(1))
out_base = int(re.search(r'Solution Base:\s*(\d+)', html).group(1))
# Parse equation — split on operators, handle multi-line
eq_match = re.search(r'Equation\s*\n(.*?)(?=\n©)', html, re.DOTALL)
eq = eq_match.group(1).replace('\n', '').strip()

# Evaluate: split by + first, then *
terms = eq.split('+')
product_terms = terms[0].split('*')
add_term = terms[1].strip()

result = 1
for t in product_terms:
result *= from_base(t.strip(), charset, in_base)
result += from_base(add_term, charset, in_base)

answer = to_base(result, charset, out_base)
print(answer) # 提交这个值

关键陷阱:

  • 不用 float — 数值巨大,全部用 Python big int
  • 单 session 完成 — charset 和 equation 每次请求随机生成,不能手动分批
  • 解析等式 — 注意多行;末尾的 + HjRq 是加法项,前面的 * 是乘法
  • HTML 解析 — 不要用 .find() 切片,论坛反馈有人因此只错最后几位数字
  • 限时 3.1416s — 自动化脚本必须在同一 HTTP session 内完成抓题→计算→提交

答案 session-bound,每次不同,无法复用固定值。