1. 程式人生 > 其它 >「BUAA OO Unit 1 HW1」面向測試小白的簡易評測機

「BUAA OO Unit 1 HW1」面向測試小白的簡易評測機

「BUAA OO Unit 1 HW1」面向測試小白的簡易評測機

宣告:本評測機所使用資料生成來自郭鴻宇同學,這對本評測機非常重要

目錄

Part 0 前言

筆者的配置與環境

  1. Windows10家庭版
  2. Pycharm 2021.3.2
  3. Anaconda1.9.7,其中用於python專案的python版本為3.6,但是應該是python3就可以
  4. IDEA 2021.3.2

面向人群

所有人,無論是否有python基礎或者評測機搭建經驗。

定位

基於本篇部落格,您可以從零迅速搭建一個適合您的評測機,並且對您的專案路徑沒有要求。得益於資料輸入輸出和資料生成模組的解耦合,您可以快速遷移本評測機的輸入輸出,並更換您需要的資料生成模組,提高了泛用性。

Part 1 準備工作

  1. 若沒有,則安裝Anaconda,並安裝一個python3的環境,這將在Part5附錄部分介紹
  2. 若沒有,則安裝IDEA和Pycharm

Part 2 獲取java jar包

目的

為了避免不同同學的Java專案結構目錄、依賴包等的不同導致的無謂的麻煩,將Java專案打包為jar包,方法可移植性強

過程

  1. 在IDEA中建立專案,並將程式碼置於其中,測試可以執行即可。如果有依賴包,則需要匯入依賴包。

  2. File ->Project Structure->Artifacts->+->JAR->From modules with dependencies...

  1. Main Class中選中程式入口類->OK->Cancel

  2. 修改Name

    (也可以不改)->Apply->OK

  3. Build->Build Artifacts,然後在其中選擇剛才Name的項,然後Build

  1. 在專案目錄/out/artifacts/Name下可以找到生成的jar包

須知

對於本次作業,課程組提供的官方輸入輸出包需要被註釋掉,同時需要自行將原MainClass中的Scanner切換回標準的Scanner SCANNER = new Scanner(System.in)。同時,本評測機暫不支援預解析模式輸入。

Part 2 修改評測機引數

pipline.py

import sympy # 如果報錯顯示沒有這個包,就需要匯入
from xeger import Xeger
import random
import subprocess
from subprocess import STDOUT, PIPE
from gendata import genData


def execute_java(stdin):
    cmd = ['java', '-jar', 'archer.jar']# 更改為自己的.jar包名
    proc = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
    stdout, stderr = proc.communicate(stdin.encode())
    return stdout.decode().strip()


x = sympy.Symbol('x')
X = Xeger(limit=10)
cnt = 1

while True:
    cnt = cnt + 1
    if cnt % 1000 == 0:
        print(cnt)
    poly, ans = genData()
    #print(poly)
    f = sympy.parse_expr(poly)
    strr = execute_java(poly)
    #print(strr)
    g = sympy.parse_expr(strr)
    if sympy.simplify(f).equals(g) :
        print("AC : " + str(cnt))
    else:
        print("!!WA!! with " + "poly : " + poly + " YOURS: " + strr)

上述程式碼中需要改jar包為自己的包名

其他不修改即可正常使用,也可根據需求自行修改。

gendata.py

"""
Auther: GHY
Date: 20222022/3/5
"""

import random
import sympy

intPool = [0,1,2,3,4]   # 常量池
hasWhiteSpace = False   # 是否加入空白字元
hasLeadZeros = False    # 數字是否有前導零,如果傳入sympy的表示式中數字有前導零,sympy將無法識別
maxTerm = 10             # 表示式中的最大項數
maxFactor = 3           # 項中最大因子個數
specialData = ["1","x-x","-1"]  # 可以放一些特殊資料
globalPointer = 0

def rd(a,b) :
    return random.randint(a,b)

def getWhiteSpace():
    if hasWhiteSpace==False:
        return ""
    str = ""
    cnt = rd(0,2)
    for i in range(cnt):
        type = rd(0,1)
        if type==0:
            str = str + " "
        else:
            str = str + "\t"
    return str


def getSymbol():
    if rd(0,1)==1:
        return "+"
    else:
        return "-"

def getNum(positive):
    result = ""
    integer = intPool[rd(0,len(intPool)-1)]
    iszero = rd(0,2)
    for i in range(iszero):
        result = result + "0"
    if hasLeadZeros==False:
        result = ""
    result = result + str(integer)
    if rd(0,1)==1:
        if positive==True:
            result = "+" + result
        else:
            result = getSymbol() + result 
    # print("num:"+result)
    return result


def getExponent():
    result = "**"
    result = result + getWhiteSpace()
    case = rd(0,2)
    if rd(0,1)==1:
        result = result + "+"
    if case==0:
        result = result + "0"
    elif case==1:
        result = result + "1"
    else:
        result = result + "2"    
    # result = result + getNum(True)
    # print("exponent:"+result)
    return result
     
    
def getPower():
    result = "x"
    if rd(0,1)==1:
        result = result + getWhiteSpace() + getExponent()
    # print("Power:"+result)
    return result


def getTerm(genExpr):
    factorNum = rd(1,maxFactor)
    result = ""
    if rd(0,1)==1:
        result = getSymbol()+getWhiteSpace()
    for i in range(factorNum):
        factor = rd(0,2)
        if factor==0:
            result = result + getNum(False)
        elif factor==1:
            result = result + getPower()
        elif factor==2 and genExpr==True:
            result = result + getExpr(True)
        else:
            result = result + "0"    
        if i < factorNum-1:
            result = result + getWhiteSpace() + "*" + getWhiteSpace()   
    # print("term:"+result)        
    return result                 
    

def getExpr(isFactor):
    termNum = rd(1,maxTerm)
    result = getWhiteSpace()    
    genExpr = True
    if isFactor==True:
        genExpr = False
    for i in range(termNum):
        result = result + getSymbol() + getWhiteSpace() + getTerm(genExpr) + getWhiteSpace()
    if isFactor==True:
        result = "(" + result + ")"
        if rd(0,1)==1:
            result = result + getWhiteSpace() + getExponent()   
    # print("Expr:"+result)        
    return result          
               
              
def genData():
    global globalPointer
    if globalPointer<len(specialData):
        expr = specialData[globalPointer]
        globalPointer = globalPointer + 1
    else:
        expr = getExpr(False)
    x = sympy.Symbol('x')
    simplifed = sympy.expand(eval(expr))
    return str(expr),str(simplifed)
               
               
x = sympy.Symbol('x')
fx = "+x**+0*x**0++3++x**+1*+1"
y = sympy.expand(eval(fx))
print(y)

上述程式碼不修改即可正常使用,也可根據需求修改資料生成方式。

Part 3 評測機架構

本評測機需要將jar包、pipline.py和gendata.py放在同一目錄下即可,無其他要求。

對於多個jar包,允許在多個資料夾中分別存放評測機,同時測試執行。

Part 4 有待改進的地方

  1. Part2中要求註釋掉官方包及切換回Scanner的原因是,目前筆者沒有辦法在獲取輸出時跳過第一行,但這應該可以做到。

Part 5 附錄:如何從0配置本評測機可執行的 python+Anaconda 環境

一、下載pycharm:

此步僅執行連線中步驟1.2.3,即不進行後續python安裝即環境變數的配置。僅安裝pycharm。
https://www.runoob.com/w3cnote/pycharm-windows-install.html

二、Anaconda安裝教程

如果沒有特定版本需求,可選擇文中版本安裝,此版本預設安裝python3.7
https://zhuanlan.zhihu.com/p/75717350

三、建立python專案時關聯Anaconda的python.exe

僅參考步驟五即可
https://www.cnblogs.com/yuxuefeng/articles/9235431.html

四、安裝 xeger庫:見連結方法一

https://www.cnblogs.com/ShineLeBlog/p/10893419.html

五、更新sympy庫

同上,在此介面取消Anaconda模式後,找到sympy庫雙擊。

勾選 Spectify version ,選擇1.9版本,點選 Install Package。