InternBootcamp/internbootcamp/bootcamp/enewlanguage/enewlanguage.py
2025-05-23 15:27:15 +08:00

350 lines
12 KiB
Python
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""#
### 谜题描述
Living in Byteland was good enough to begin with, but the good king decided to please his subjects and to introduce a national language. He gathered the best of wise men, and sent an expedition to faraway countries, so that they would find out all about how a language should be designed.
After some time, the wise men returned from the trip even wiser. They locked up for six months in the dining room, after which they said to the king: \"there are a lot of different languages, but almost all of them have letters that are divided into vowels and consonants; in a word, vowels and consonants must be combined correctly.\"
There are very many rules, all of them have exceptions, but our language will be deprived of such defects! We propose to introduce a set of formal rules of combining vowels and consonants, and include in the language all the words that satisfy them.
The rules of composing words are:
* The letters are divided into vowels and consonants in some certain way;
* All words have a length of exactly n;
* There are m rules of the form (pos1, t1, pos2, t2). Each rule is: if the position pos1 has a letter of type t1, then the position pos2 has a letter of type t2.
You are given some string s of length n, it is not necessarily a correct word of the new language. Among all the words of the language that lexicographically not smaller than the string s, find the minimal one in lexicographic order.
Input
The first line contains a single line consisting of letters 'V' (Vowel) and 'C' (Consonant), determining which letters are vowels and which letters are consonants. The length of this string l is the size of the alphabet of the new language (1 ≤ l ≤ 26). The first l letters of the English alphabet are used as the letters of the alphabet of the new language. If the i-th character of the string equals to 'V', then the corresponding letter is a vowel, otherwise it is a consonant.
The second line contains two integers n, m (1 ≤ n ≤ 200, 0 ≤ m ≤ 4n(n - 1)) — the number of letters in a single word and the number of rules, correspondingly.
Next m lines describe m rules of the language in the following format: pos1, t1, pos2, t2 (1 ≤ pos1, pos2 ≤ n, pos1 ≠ pos2, <image> 'V', 'C' }).
The last line contains string s of length n, consisting of the first l small letters of the English alphabet.
It is guaranteed that no two rules are the same.
Output
Print a smallest word of a language that is lexicographically not smaller than s. If such words does not exist (for example, if the language has no words at all), print \"-1\" (without the quotes).
Examples
Input
VC
2 1
1 V 2 C
aa
Output
ab
Input
VC
2 1
1 C 2 V
bb
Output
-1
Input
VCC
4 3
1 C 2 V
2 C 3 V
3 V 4 V
abac
Output
acaa
Note
In the first test word \"aa\" is not a word of the language, but word \"ab\" is.
In the second test out of all four possibilities only word \"bb\" is not a word of a language, but all other words are lexicographically less, so there is no answer.
In the third test, due to the last rule, \"abac\" doesn't belong to the language (\"a\" is a vowel, \"c\" is a consonant). The only word with prefix \"ab\" that meets the given rules is \"abaa\". But it is less than \"abac\", so the answer will be \"acaa\"
Here is a reference code to solve this task. You can use this to help you genereate cases or validate the solution.
```python
#include <bits/stdc++.h>
#pragma comment(linker, \"/STACK:36777216\")
int ddx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
int ddy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
using namespace std;
using namespace std;
string s, v;
pair<int, int> p[200100];
pair<char, char> t[200100];
vector<int> g[200100];
vector<int> gr[200100];
int ord[200100];
int cnt, n, m;
bool used[200100];
int color[200100];
void dfs(int v) {
used[v] = 1;
for (int _n((g[v].size()) - 1), i(0); i <= _n; ++i)
if (!used[g[v][i]]) dfs(g[v][i]);
ord[cnt++] = v;
}
void cmp(int v, int id) {
color[v] = id;
for (int _n((gr[v].size()) - 1), i(0); i <= _n; ++i)
if (color[gr[v][i]] == -1) cmp(gr[v][i], id);
}
bool SAT(string t) {
for (int _n((n)-1), i(0); i <= _n; ++i)
if (t[i] != '#') {
if (v[t[i] - 'a'] == 'C')
g[i].push_back(i + n), gr[i + n].push_back(i);
else
g[i + n].push_back(i), gr[i].push_back(i + n);
}
cnt = 0;
for (int _n((n << 1) - 1), i(0); i <= _n; ++i) used[i] = 0, color[i] = -1;
for (int _n((n << 1) - 1), i(0); i <= _n; ++i)
if (!used[i]) dfs(i);
reverse(ord, ord + cnt);
int id = 0;
for (int _n((n << 1) - 1), i(0); i <= _n; ++i)
if (color[ord[i]] == -1) cmp(ord[i], ++id);
for (int _n((n)-1), i(0); i <= _n; ++i)
if (t[i] != '#') {
if (v[t[i] - 'a'] == 'C')
g[i].pop_back(), gr[i + n].pop_back();
else
g[i + n].pop_back(), gr[i].pop_back();
}
for (int _n((n)-1), i(0); i <= _n; ++i)
if (color[i] == color[i + n]) return 0;
return 1;
}
int main() {
int C, V;
C = V = 0;
cin >> v;
for (int _n((v.size()) - 1), i(0); i <= _n; ++i) (v[i] == 'V' ? V : C)++;
cin >> n >> m;
for (int _n((m)-1), i(0); i <= _n; ++i) {
cin >> p[i].first >> t[i].first;
cin >> p[i].second >> t[i].second;
p[i].first--, p[i].second--;
if (t[i].first == 'C') p[i].first += n;
if (t[i].second == 'C') p[i].second += n;
g[p[i].first].push_back(p[i].second);
gr[p[i].second].push_back(p[i].first);
if (p[i].first < n)
p[i].first += n;
else
p[i].first -= n;
if (p[i].second < n)
p[i].second += n;
else
p[i].second -= n;
g[p[i].second].push_back(p[i].first);
gr[p[i].first].push_back(p[i].second);
}
cin >> s;
if (SAT(s)) {
cout << s << endl;
return 0;
} else if (!C || !V) {
cout << -1 << endl;
return 0;
}
for (int i = (n - 1), _b = (0); i >= _b; --i) {
pair<int, int> f = {0, 0};
for (int _n(v.size() - 1), j(s[i] + 1 - 'a'); j <= _n; ++j) {
if (v[j] == 'C') {
if (f.first) continue;
f.first++;
} else {
if (f.second) continue;
f.second++;
}
string solve = s;
solve[i] = 'a' + j;
for (int _n(n - 1), k(i + 1); k <= _n; ++k) solve[k] = '#';
if (SAT(solve)) {
for (int _n(n - 1), k(i + 1); k <= _n; ++k) {
pair<int, int> g = {0, 0};
for (int _n((v.size()) - 1), l(0); l <= _n; ++l) {
if (v[l] == 'C') {
if (g.first) continue;
g.first++;
} else {
if (g.second) continue;
g.second++;
}
solve[k] = 'a' + l;
if (SAT(solve)) break;
}
}
cout << solve << endl;
return 0;
}
}
}
cout << -1 << endl;
return 0;
}
```
请完成上述谜题的训练场环境类实现,包括所有必要的方法。
"""
from bootcamp import Basebootcamp
import json
import re
from collections import defaultdict
from copy import deepcopy
from bootcamp import Basebootcamp
class Enewlanguagebootcamp(Basebootcamp):
def __init__(self, **params):
# 参数包括字母分类字符串、n单词长度、m规则数量、rules规则列表、s初始字符串
self.vc = params.get('vc', 'VC') # 默认字母分类为V和C
self.n = params.get('n', 2) # 默认单词长度为2
self.m = params.get('m', 1) # 默认规则数量为1
self.rules = params.get('rules', []) # 规则列表,默认为空
self.s = params.get('s', 'aa') # 默认初始字符串为'aa'
def case_generator(self):
# 生成一个谜题实例
# 这里简化处理,生成一个随机实例,实际应确保实例有解
# 生成字母分类字符串例如前l个字母每个是V或C
import random
l = random.randint(1, 26)
self.vc = ''.join([random.choice(['V', 'C']) for _ in range(l)])
# 生成n和m
self.n = random.randint(1, 200)
max_rules = 4 * self.n * (self.n - 1)
self.m = random.randint(0, max_rules)
# 生成m条规则
self.rules = []
for _ in range(self.m):
pos1 = random.randint(1, self.n)
t1 = random.choice(['V', 'C'])
pos2 = random.randint(1, self.n)
while pos2 == pos1:
pos2 = random.randint(1, self.n)
t2 = random.choice(['V', 'C'])
self.rules.append( (pos1, t1, pos2, t2) )
# 生成初始字符串s长度为n使用前l个字母
allowed_letters = [chr(ord('a') + i) for i in range(l)]
self.s = ''.join([random.choice(allowed_letters) for _ in range(self.n)])
# 返回JSON序列化的字典
return {
'vc': self.vc,
'n': self.n,
'm': self.m,
'rules': self.rules,
's': self.s
}
@staticmethod
def prompt_func(question_case):
# 将case转换为问题描述
vc = question_case['vc']
n = question_case['n']
m = question_case['m']
rules = question_case['rules']
s = question_case['s']
rule_desc = []
for rule in rules:
pos1, t1, pos2, t2 = rule
rule_str = f"如果位置 {pos1}{t1},那么位置 {pos2} 必须是 {t2}"
rule_desc.append(rule_str)
prompt = f"""
你是Enewlanguage语言专家需要找出符合以下规则的最小字典序单词且该单词不小于给定的字符串 '{s}'
规则如下:
{chr(10).join(rule_desc)}
字符串的每个位置只能是元音V或辅音C具体分类为
{vc}
你的任务是从 '{s}' 开始,找到最小的符合条件的单词。如果没有这样的单词,输出 '-1'
请将答案放置在 [answer] 标签内,格式如下:
[answer]your_answer[/answer]
"""
return prompt.strip()
@staticmethod
def extract_output(output):
# 提取答案,使用正则表达式查找最后一个[answer]...[/answer]
matches = list(re.finditer(r'\[answer\](.*?)\[\/answer\]', output, re.DOTALL))
if not matches:
return None
# 取最后一个匹配项
last_match = matches[-1]
extracted = last_match.group(1).strip()
return extracted
@classmethod
def _verify_correction(cls, solution, identity):
# 验证solution是否符合所有规则
# 解析identity中的参数
vc = identity['vc']
n = identity['n']
rules = identity['rules']
s = identity['s']
# 如果solution是-1检查是否真的没有解
if solution == '-1':
# 这里需要验证是否存在任何合法单词,这可能很复杂,暂时简化处理
# 实际应实现完整的验证逻辑
return True
# 检查solution的长度是否为n
if len(solution) != n:
return False
# 检查每个字符是否在允许的字母范围内
allowed_letters = list('abcdefghijklmnopqrstuvwxyz')[:len(vc)]
for c in solution:
if c not in allowed_letters:
return False
# 构建每个位置的类型V或C
type_dict = {}
for i, c in enumerate(solution):
idx = ord(c) - ord('a')
type_dict[i+1] = 'V' if vc[idx] == 'V' else 'C'
# 检查所有规则
for rule in rules:
pos1, t1, pos2, t2 = rule
if type_dict.get(pos1, None) == t1:
if type_dict.get(pos2, None) != t2:
return False
return True