<! - * Erzeugt auch automatisch (Python-) Quellcode, um Eingaben zu erhalten->
Diejenigen, die die automatische Generierungsfunktion nutzen möchten, sowie diejenigen, die etwas über die Programmierung wissen möchten, die einen Schritt weiter vom Wettbewerbsprofi entfernt ist Ich denke, dieser Inhalt kann von denen gelesen werden, die sich mit Objektorientierung befassen. Den gesamten Quellcode finden Sie unter [hier] 1.
Wenn Sie ein solches Eingabemakro vorbereiten →
Int(N,2,5)
Float(a,1,100,5) Perm(1,N+4)
Str([a-z]{3,2*N})
*N(2)
Der Eingang wird ausgegeben →
output:
4
54.81887 3 2 4 7 1 8 5 6
yyl
4.32497 4 1 6 5 3 8 7 2
yziuqiac
42.84603 3 2 4 7 8 6 5 1
vsjajs
65.07176 7 5 8 3 4 6 1 2
rbq
Verschiedene andere Dinge
Gewichtete Grafik:
Int(N,3,5) Int(M,N-1,N*(N-1)//2)
Graph1(N,M,0,1000)
↓
output:
4 5
1 2 392
1 3 328
1 4 891
2 3 264
3 4 227
String:
Int(N,4,6) Int(M,4,6)
Str([.#]{M})
*N(1)
↓
output:
4 5
###.#
#.#.#
#..##
.###.
etc.
Wenn Sie an der Funktion selbst interessiert sind, finden Sie eine Liste in [hier] 1.
<! - ## Was Sie tun können: Generieren Sie automatisch Quellcode, um Eingaben zu erhalten
Anstatt Eingaben zu spucken, können Sie auch die Funktion input () von Python verwenden, um Quellcode zu generieren, der Eingaben empfängt:
``` -->
* Da wir bisher nur die innere Klasse definiert haben, müssen Sie Python mit dieser Klasse codieren, wenn Sie viele Testfälle gleichzeitig generieren oder in eine Datei schreiben möchten.
## Realisierungsmethode
Es hat eine objektorientierte Implementierung.
Grob
1. Klasse, die für das Laden des gesamten Makros verantwortlich ist (LineCollection)
1. Klasse (Zeile), die für das zeilenweise Lesen des Makros verantwortlich ist
1. Die Klasse (Item und seine Unterklassen), die für das Leerzeichen in einer Zeile des Makros verantwortlich ist
Es ist unterteilt in. Es ist ein Bild, das ich i + 1 verwalte und die notwendige Arbeit (i = 1,2) wirft.
Allen Klassen sind folgende Methoden gemeinsam:
1. from_str (): Analysiert die Eingabemakrozeichenfolge und initialisiert die Klasse.
1. generate (): Erzeugt einen Testfall mit zufälliger Eingabe für den von ihm verwalteten Bereich.
Zusammenfassend sieht es wie in der folgenden Tabelle aus:
||LineCollection|Line|Item|
|---|---|---|---|
|from_str()|Laden des gesamten Makros|Lesen Sie eine Zeile|Ein Wort lesen|
|generate()|Ausgabegenerierung für das gesamte Makro|Ausgabeerzeugung für eine Zeile|Ausgabeerzeugung für ein Wort|
<!-- |generate()/generate_source()|Ausgabegenerierung für das gesamte Makro|Ausgabeerzeugung für eine Zeile|Ausgabeerzeugung für ein Wort| -->
Der Punkt ist
* Um das Ganze zu nutzen, LineCollection.from_str (Eingabemakro) → generate ()
<! - * Um das Ganze zu verwenden, LineCollection.from_str (Eingabemakro) → generate () / generate_source () ->
* Wenn Sie die Anzahl neuer Makrotypen erhöhen möchten, definieren Sie einfach eine Unterklasse der Item-Klasse mit den oben genannten drei Methoden (Line oder LineCollection müssen nicht geändert werden).
Was für ein Ort wie.
## Quellcode
Insbesondere werden wir den Quellcode überprüfen.
LineCollection
||<font color=green> LineCollection|Line|Item|
|---|---|---|---|
|from_str()|<font color=green>Laden des gesamten Makros</font>|Lesen Sie eine Zeile|Ein Wort lesen|
|generate()|<font color=green>Ausgabegenerierung für das gesamte Makro|Ausgabeerzeugung für eine Zeile|Ausgabeerzeugung für ein Wort|
<!-- |generate()/generate_source()|<font color=green>Ausgabegenerierung für das gesamte Makro|Ausgabeerzeugung für eine Zeile|Ausgabeerzeugung für ein Wort| -->
self.ls hat eine Liste von Zeilen für jede Zeile des Makros.
Es ist etwas kompliziert, Makros wie "* N (1)" zu unterstützen, aber wir tun es
* from_str () = Gesamtes Makro laden: Initialisieren Sie die Zeile, die jeder Zeile entspricht, und fügen Sie sie in self.ls ein
* generate () = Ausgabe für das gesamte Makro generieren: Generiert eine Ausgabe für jede Zeile in self.ls und gibt sie mit einem Zeilenvorschubzeichen zurück
nur.
```python
class LineCollection:
def __init__(self, ls, s=None):
"""ls: list of Line
"""
self.ls = ls
self.s = s
@classmethod
def from_str(cls, s):
lines = s.split("\n")
i = 0
ls = []
for i in range(len(lines)):
if lines[i].startswith("*"):
name, num = lines[i][1:].split("(",1)
num = int(num[:-1])
ls.append((name, num))
else:
l = Line.from_str(lines[i])
ls.append(l)
return cls(ls, s)
def generate(self):
i = 0
prv = 0
output = []
while i<len(self.ls):
while i<len(self.ls) and not isinstance(self.ls[i], tuple):
i += 1
if i<len(self.ls) and isinstance(self.ls[i], tuple):
m, num = self.ls[i]
i += 1
else:
m = 0
num = 0
for j in range(prv, i-num-1):
if isinstance(self.ls[j], tuple):
continue
output.append(self.ls[j].generate())
if num!=0:
try:
m = Item.names[m]
except KeyError:
raise ValueError("Undefinierte Anzahl von Testfällen:Ist die Angabe, wie viele Zeilen oben angezeigt werden sollen, nicht falsch?")
for _ in range(m):
for j in range(i-num-1, i-1):
if isinstance(self.ls[j], tuple):
continue
output.append(self.ls[j].generate())
prv = i
return "\n".join(output)
Line
LineCollection | Line | Item | |
---|---|---|---|
from_str() | Laden des gesamten Makros | Lesen Sie eine Zeile | Ein Wort lesen |
generate() | Ausgabegenerierung für das gesamte Makro | Ausgabeerzeugung für eine Zeile | Ausgabeerzeugung für ein Wort |
self.l verwaltet eine Liste von Elementen, die in der angezeigten Zeile vorhanden sind. Ähnlich wie bei der LineCollection,
Ich mache das Wenn wir den Klassennamen lesen und das Element initialisieren, erhalten wir das Klassenobjekt von der in Python integrierten Funktion globals ().
def evaluate_item(ss):
cc, tmp = ss.split("(", 1)
vv = tmp[:-1]
return globals()[cc].from_str(vv)
class Line:
def __init__(self, l, s=None):
"""
correspond to a line of input file
l: list of Item
"""
self.l = l
self.s = s
@classmethod
def from_str(cls, s):
l = []
for ss in s.split():
l.append(evaluate_item(ss))
return cls(l)
def generate(self):
return " ".join([item.generate() for item in self.l])
Item
LineCollection | Line | Item | |
---|---|---|---|
from_str() | Laden des gesamten Makros | Lesen Sie eine Zeile | Ein Wort lesen |
generate() | Ausgabegenerierung für das gesamte Makro | Ausgabeerzeugung für eine Zeile | Ausgabeerzeugung für ein Wort |
Schließlich Item, das für jedes Makro definiert ist, das Sie unterstützen möchten. In einem solchen Fall ist das Erstellen und Erben einer Basisklasse hinsichtlich Lesbarkeit, Wartbarkeit und Codierungseffizienz überlegen. Wir haben die Item-Klasse als Basisklasse wie folgt vorbereitet:
class Item:
names = {}
def __init__(self, s=None, **keys):
self.s = s
@classmethod
def from_str(cls, s):
pass
def evaluate(self, s):
for k in Item.names.keys():
if k in s:
s = s.replace(k, str(Item.names[k]))
return eval(s)
def generate(self):
pass
def __str__(self):
if hasattr(self, "s"):
return self.s
Item ist eine Klasse, die nicht so verwendet werden kann, wie sie ist. Es ist daher besser, einen Zauberspruch zu verwenden, um sie darzustellen. Diesmal wird sie jedoch weggelassen. Selbst wenn Sie nur erklären, dass Sie über diese Methoden verfügen, hat dies große Vorteile, z. B. das Verständnis für andere beim Hinzufügen von Funktionen.
Erstellen Sie darunter eine Klasse für jedes Makro, das Sie realisieren möchten. Zum Beispiel Int
class Int(Item):
def __init__(self, name, low, high, s=None, **keys):
"""
correspond to the input value between two spaces
name: str
name of variable
low/high : str
min / max (inclusive)
"""
self.name = name
self.low = low
self.high = high
self.keys = keys
Item.__init__(self, s)
@classmethod
def from_str(cls, s):
name, low, high = s.split(",")
return cls(name, low, high, s=s)
def generate(self):
low, high = self.evaluate(self.low), self.evaluate(self.high)
value = utils.rng.integers(low, high+1)
Item.names[self.name] = value
return str(value)
Wenn die Reihenfolge 1 ... N ist
class Perm(Item):
"""permutation of [low, low+1, ..., high-1, high]
"""
def __init__(self, low, high, s=None):
self.low = low
self.high = high
self.s = s
@classmethod
def from_str(cls, s):
low, high = s.split(",")
return cls(low, high, s=s)
def generate(self):
low, high = self.evaluate(self.low), self.evaluate(self.high)
return " ".join(map(str, (utils.rng.permutation(high-low+1) + low).tolist()))
Es ist wie geformt. Wenn Zufallszahlen benötigt werden, werden sie in einen extern definierten Zufallsgenerator geworfen:
utils.py
import numpy as np
SEED = 0
rng = np.random.default_rng(SEED)
Bei der Verwendung von Zufallszahlen ist es richtig, die Funktion nicht jedes Mal aufzurufen, sondern Zufallskorrekturen (gegebenenfalls mehrere) vorzubereiten und entsprechend dem Umfang ordnungsgemäß zu verwenden. In diesem Fall hängt es jedoch davon ab, ob es wünschenswert ist, die Zufallszahl festzulegen (um die Reproduzierbarkeit zu erhalten) oder das Ergebnis für jede Ausführung zu ändern, sodass es je nach Anwendungsfall erforderlich sein kann, es neu zu schreiben. ..
Andere Makros werden nacheinander auf die gleiche Weise unterstützt. Wenn es sich beispielsweise um ein Diagramm handelt, wird es mithilfe von Funktionen wie der Erzeugung eines zufälligen Networkx-Diagramms realisiert. Wenn es sich um eine Zeichenfolge handelt, wird dies mithilfe von Funktionen wie der zufälligen Generierung einer Zeichenfolge realisiert, die mit dem Muster des regulären Ausdrucks durch rstr übereinstimmt. Was tun?
Es ist nur eine Frage der Implementierung, sodass der Aufwand für das Hinzufügen von Funktionen reduziert wird!
<! - * Erzeugt auch automatisch (Python-) Quellcode, um Eingaben zu erhalten->
TODO