1. 程式人生 > >[工具使用]-利用latex管理建立自己的ACM模板

[工具使用]-利用latex管理建立自己的ACM模板

從很早入坑ACM開始,便和各種演算法的模板打著交道,雖然kaungbin的模板已經足夠強大,但是自己在平常做題中也逐漸有著自己的一些模板,也有一些kuangbin模板中沒有的更快的板子,雖然不確定時候以後會用到,但是能夠記錄下來形成自己的模板是最好的,,這樣也對自己所學有個大致的總結,所以在搜尋網路上各種解決思路後,選擇一位博主的解決方法: 利用python管理資料夾形式的模板庫,生成 latex.tex 檔案,然後通過兩次編譯後得到 .pdf 的模板檔案,,這樣的好處是顯而易見的,首先是程式碼的管理十分的方便,只需將整理的板子扔到對應的分類資料夾下,然後在需要列印 .pdf 的板子時執行一下py指令碼就行了,同時用 latex

生成的檔案的樣式也很個性化,可以根據自己的喜好來改變,,我也從中加深了對 latex 語言的瞭解。

準備工作

為了能夠最後能正常的生成板子,,首先要保證一些軟體能夠正常的使用: python3, tex 等等

這個 Tex Live 我很早之前就安裝了,所以也忘記具體的安裝過程了,,只記得這玩意的下載檔案多而大,,安裝也費事,,不過具體的安裝步驟網上有很多教程(注意要保證xecjk使用,,支援中文的包

最後的板子的管理資料夾大致是這樣的:

卷 檔案 的資料夾 PATH 列表
卷序列號為 D0B1-CFE7
G:.
│  1.pdf                //生成的pdf檔案
│  1.tex                //生成的tex檔案
│  logo.jpg             //板子的封面
│  README.md            
│  setting.dat          //儲存的配置,名字啊等等
│  template.py          //我們的指令碼
│  tree.txt             //這個目錄的大致結構
│  
├─dp
│      線性dp.cpp
│      
├─_MyTemplate
│      init.cpp
│      
├─博弈論
│      sg函式.cpp
│      
├─圖論
│  ├─2-sat
│  │      輸出字典序最小的解.cpp
│  │      
│  ├─二分圖
│  │      匈牙利演算法_鄰接矩陣實現.cpp
│  │      
│  ├─割點、橋、連通分支
│  │      基本內容.cpp
│  │      
│  ├─差分約束
│  │      差分約束.cpp
│  │      
│  ├─強連通分量
│  │      Kosaraju.cpp
│  │      Tarjan_kuangbin.cpp
│  │      Tarjan_red_bool.cpp
│  │      
│  ├─拓撲排序
│  │      拓撲排序.cpp
│  │      
│  ├─最短路
│  │  └─spfa
│  │          spfa_1_前向星.cpp
│  │          spfa_2_鄰接表_good.cpp
│  │          spfa_棧優化.cpp
│  │          
│  └─網路流
│      └─最大流
│              dinic.cpp
│              hlpp.cpp
│              
├─字串
│      hash.cpp
│      序列自動機.cpp
│      
├─資料結構
│  └─並查集
│          並查集.cpp
│          
├─數論
│  │  常用數論板子.cpp
│  │  
│  ├─中國剩餘定理
│  │      中國剩餘定理_擴充套件歐幾里得.cpp
│  │      中國剩餘定理_模數不保證互質.cpp
│  │      中國剩餘定理_逆元.cpp
│  │      
│  ├─大整數_java
│  │      java.cpp
│  │      
│  └─快速冪
│          杜教板子.cpp
│          矩陣快速冪.cpp
│          
├─樹
│      線段樹.cpp
│      
└─線性基
        線性基.cpp
        

可以看到我們需要在一個資料夾下放置指令碼程式,板子的封面,以及最重要的就是我們的板子,每一個板子都是 .cpp 檔案,直接將板子扔進去就行了,,

指令碼

總的指令碼是這樣的,直接執行就行了,,原博主 的這個程式貌似只能在 Linux下的python2使用,,所以我做了一些更改,在我的環境下(win10+python3.7)是可以正常使用的,,具體的內容可以看註釋

有一個小bug:目錄貌似不能顯示很多,,,emmmm有時間再改吧,,,

還有編譯中間會有一些warning 得手動按回車才能進行下一步

# coding=utf-8
import os
import sys
import json

# tex的標頭檔案,lstset就是板子的樣式
TexHead = r"""
\documentclass[twocolumn, a4]{article}
\usepackage[colorlinks,linkcolor=black]{hyperref}
\usepackage{xeCJK}
\usepackage{fancyhdr}
\usepackage{amsmath, amsthm}
\usepackage{listings,xcolor}
\usepackage{geometry}
\usepackage{fontspec} 
\usepackage{graphicx}
\setsansfont{Consolas}
\setmonofont[Mapping={}]{Consolas}
\newcommand{\HRule}{\rule{\linewidth}{0.5mm}}
\geometry{left=2.5cm,right=2.5cm,top=1cm,bottom=1cm}
\lstset{
    language    = c++,
    numbers     = left,
    numberstyle = \tiny,
    breaklines  = true,
    captionpos  = b,
    tabsize     = 4,
    frame       = shadowbox,
    columns     = fullflexible,
    commentstyle = \color[RGB]{0,128,0},
    keywordstyle = \color[RGB]{0,0,255},
    basicstyle   = \normalsize\ttfamily,
    stringstyle  = \color[RGB]{148,0,209}\ttfamily,
    rulesepcolor = \color{red!20!green!20!blue!20},
    showstringspaces = true,
}
"""
 
# 初始化設定,主要是板子的名字等等
def InitSetting():
    try:
        SettingFile = open('setting.dat')
        SettingData = json.load(SettingFile)
        print (u'讀取到儲存的設定: ')
        for key in SettingData:
            print ('[%s] %s' % (key, SettingData[key]))
        op = input('是否使用已儲存的設定?[Y/n]')
        if not op in ['n', 'N', 'no', 'No', 'NO']:
            global TITLE, SCHOOL, TEAM, FILE
            for key in ['TITLE', 'SCHOOL', 'TEAM', 'FILE']:
                globals()[key] = SettingData[key]
        else:
            NewSetting()
    except:
        print (u'讀取設定失敗')
        NewSetting()
 
 
# 輸入資訊,儲存到本地
def NewSetting():
    global TITLE, SCHOOL, TEAM, FILE
    TITLE = input('請輸入標題: ')
    SCHOOL = input('請輸入學校: ')
    TEAM = input('請輸入隊名: ')
    FILE = input('請輸入檔名: ')
    Data = dict()
    for key in ['TITLE', 'SCHOOL', 'TEAM', 'FILE']:
        Data[key] = globals()[key]
    json.dump(Data, open('setting.dat', 'w'))
 
# 刪除當前目錄下的所有中間臨時檔案
def Clear():
    for suffix in ['aux', 'log', 'toc', 'out']:
        filename = '%s.%s' % (FILE, suffix)
        if os.path.exists(filename):
            os.remove(filename)
 
# 呼叫兩次生成模板來使 .tex 轉為 .pdf
def Generate():
    Clear()
    os.system('xelatex %s.tex -quiet' % FILE)
    os.system('xelatex %s.tex -quiet' % FILE)           # 兩到三次的生成才能生成目錄https://zhidao.baidu.com/question/1541025230634017307.html
    Clear()
    os.system('open %s.pdf' % FILE)
 
# 對每個板子檔案進行讀取寫入
def ReadCpp(file):
    f = open(file, 'r', encoding='UTF-8')
    print (file + ' 2333333333333333333333333333')
    Tex = 0
    TargetFile.write('\\begin{lstlisting}\n')
    for line in f:
        if line[:-1] == '// ---':
            Tex = not Tex
            ToWrite = '\\%s{lstlisting}\n' % ('begin', 'end')[Tex]
            TargetFile.write(ToWrite)
            continue
        TargetFile.write(line[(0, 3)[Tex]:])
    TargetFile.write('\\end{lstlisting}\n')
    f.close()
 
# 讀入tex檔案
def ReadTex(file):
    f = open(file, 'r')
    for line in f:
        TargetFile.write(line)
    f.close()
 
# 遞迴遍歷當前資料夾下的所有檔案
def Search(level, pwd, folder=''):
    ls = os.popen('dir /b "%s"' % pwd).read().split('\n')[:-1]
    for item in ls:
        print (item)
    if folder:
        print (level)
        TargetFile.write(SECTION[level] % folder[0:])
    for item in ls:
        print (item + '2333' + item[:-3])
        item.replace(' ', '\\ ')
        if '.cpp' in item:
            if not item[:2] == '00':
                TargetFile.write(SECTION[level + 1] % item[:-4])
            ReadCpp(pwd + item)
        elif '.tex' in item:
            continue
            if not item[:2] == '00':
                TargetFile.write(SECTION[level + 1] % item[:-4])
            ReadTex(pwd + item)
        elif 'jpg' in item:
            continue
        elif 'md' in item:
            continue
        elif 'dat' in item:
            continue
        elif 'py' in item:
            continue
        elif 'txt' in item:
            continue
        elif 'pdf' in item:
            continue
        else:
            cd = os.popen('cd "%s%s/"' % (pwd, item)).read()
            if 'Not a directory' in cd or 'No such file or directory' in cd:
                print ('[Unknown File] %s/%s' % (pwd, item))
            else:
                Search(level + 1, pwd + item + '/', item)
 
 
if __name__ == '__main__':
    # 全域性設定
    TITLE, SCHOOL, TEAM, FILE = '', '', '', ''
    SECTION = ['', '\\clearpage\\section{%s}\n',
               '\\subsection{%s}\n', '\\subsubsection{%s}\n', '\\paragraph{%s}\n', '\\subparagraph{%s}\n']
 
    InitSetting()
    Clear()

    TargetFile = open('%s.tex' % FILE, 'w', encoding='utf-8')
 
    # Output Head File
    TargetFile.write(TexHead)
    TargetFile.write('\\title{%s}\n' % TITLE)
    TargetFile.write('\\author{%s}\n' % TEAM)
    TargetFile.write('\\pagestyle{fancy}\n\\fancyhf{}\n\\fancyhead[C]{%s}\n' % (TITLE))
    TargetFile.write('\\begin{document}\\small\n')
    TargetFile.write('\\begin{titlepage}\n\\begin{center}\n\\vspace*{0.5cm}\\includegraphics[width=0.75\\textwidth]{logo.jpg} \\\\ [2cm]\n')
    TargetFile.write('\\HRule \\\\ [1cm]\n')
    TargetFile.write('\\textbf{\\Huge{%s}} \\\\ [0.5cm]\n' % TITLE)
    TargetFile.write('\\HRule \\\\ [4cm]\n')
    TargetFile.write('\\textbf{\\Huge{%s}} \\\\ [1cm]\n\\LARGE{%s}\n' % (SCHOOL, TEAM))
    TargetFile.write('\\vfill\n\\Large{\\today}\n\\end{center}\n')
    TargetFile.write('\\clearpage\n\end{titlepage}\n')
    TargetFile.write('\\tableofcontents\\clearpage\n')
    TargetFile.write('\\pagestyle{fancy}\n\\lfoot{}\n\\cfoot{\\thepage}\\rfoot{}\n')
    TargetFile.write('\\setcounter{section}{-1}\n\\setcounter{page}{1}\n')
 
    # Search Files
    Search(0, './')
 
    # End Output
    TargetFile.write('\n\\end{document}\n')
    TargetFile.close()
 
    # Gen
    Generate()

最後的效果如下;

參考的部落格:

主程式

latex語法的介紹

latex官網

latex的某個大佬的筆記

(應該沒了吧,,,,