Add exam template
This commit is contained in:
parent
94abae2905
commit
629e956af5
4
.gitignore
vendored
4
.gitignore
vendored
@ -8,4 +8,6 @@ _region_.tex
|
||||
*.log
|
||||
*.out
|
||||
*.synctex.gz
|
||||
.projectile
|
||||
.projectile
|
||||
|
||||
__pycache__
|
270
exam_template/.vscode/latex.code-snippets
vendored
Normal file
270
exam_template/.vscode/latex.code-snippets
vendored
Normal file
@ -0,0 +1,270 @@
|
||||
{
|
||||
"exc": {
|
||||
"scope": "latex",
|
||||
"prefix": ["\\exc"],
|
||||
"body":
|
||||
[
|
||||
"\\exc{}",
|
||||
"\\begin{subexcs}",
|
||||
" \\subexc{}",
|
||||
" $0",
|
||||
"\\end{subexcs}"
|
||||
],
|
||||
"description": "Adds new exc with subexcs",
|
||||
},
|
||||
|
||||
"subexc": {
|
||||
"scope": "latex",
|
||||
"prefix": ["\\subexc"],
|
||||
"body":
|
||||
[
|
||||
"\\subexc{}",
|
||||
"\\begin{ssubexcs}",
|
||||
" \\ssubexc{}",
|
||||
" $0",
|
||||
"\\end{ssubexcs}"
|
||||
],
|
||||
"description": "Adds new subexc with ssubexcs",
|
||||
},
|
||||
|
||||
"graph-table": {
|
||||
"scope": "latex",
|
||||
"prefix": ["graph-table"],
|
||||
"body":
|
||||
[
|
||||
"\\begin{figure}[H]",
|
||||
" \\center",
|
||||
" \\begin{tabular}{c|cc}",
|
||||
" $A$ & \\multicolumn{2}{c}{$v$} \\\\",
|
||||
" \\hline",
|
||||
" & $a$ & $b$ \\\\",
|
||||
" \\hline",
|
||||
" $s_0$ & $s_$ & $s_$ \\\\",
|
||||
" $s_1$ & $s_$ & $s_$ \\\\",
|
||||
" $s_2$ & $s_$ & $s_$ \\\\",
|
||||
" \\end{tabular}",
|
||||
"\\end{figure}"
|
||||
],
|
||||
"description": "Adds graph-table",
|
||||
},
|
||||
|
||||
"graph-table-double": {
|
||||
"scope": "latex",
|
||||
"prefix": ["graph-dtable"],
|
||||
"body":
|
||||
[
|
||||
"\\begin{figure}[H]",
|
||||
" \\center",
|
||||
" \\begin{tabular}{c|cc}",
|
||||
" $A$ & \\multicolumn{2}{c}{$v$} \\\\",
|
||||
" \\hline",
|
||||
" & $a$ & $b$ \\\\",
|
||||
" \\hline",
|
||||
" $s_0$ & $s_$ & $s_$ \\\\",
|
||||
" $s_1$ & $s_$ & $s_$ \\\\",
|
||||
" $s_2$ & $s_$ & $s_$ \\\\",
|
||||
" \\end{tabular}",
|
||||
"\\end{figure}"
|
||||
],
|
||||
"description": "Adds graph-table",
|
||||
},
|
||||
|
||||
"graph-table-line": {
|
||||
"scope": "latex",
|
||||
"prefix": ["gtl"],
|
||||
"body": " $s_$ & $s_$ & $s_$ \\\\",
|
||||
"description": "Adds line inside graph-table",
|
||||
},
|
||||
|
||||
"graph-table-double-line": {
|
||||
"scope": "latex",
|
||||
"prefix": ["gtdl"],
|
||||
"body": " $s_$ & $s_$ & $s_$ & $s_$ & $s_$ \\\\",
|
||||
"description": "Adds line inside a double graph-table",
|
||||
},
|
||||
|
||||
"induction-proof": {
|
||||
"scope": "latex",
|
||||
"prefix": ["prove-induction"],
|
||||
"body": [
|
||||
"Base case:",
|
||||
"",
|
||||
"\\begin{align*}",
|
||||
"",
|
||||
"\\end{align*}",
|
||||
"",
|
||||
"Assume that",
|
||||
"",
|
||||
"\\[ $1 \\]",
|
||||
"",
|
||||
"Then",
|
||||
"",
|
||||
"\begin{align*}",
|
||||
" &= $1 + \\\\",
|
||||
" &=",
|
||||
"\\end{align*}",
|
||||
"",
|
||||
"\\qed"
|
||||
],
|
||||
"description": "Template for induction proof",
|
||||
},
|
||||
|
||||
"injective-proof": {
|
||||
"scope": "latex",
|
||||
"prefix": ["prove-injective"],
|
||||
"body": [
|
||||
"In order for $f(x)$ to be injective, it has to hold that",
|
||||
"",
|
||||
"\\[ f(a) = f(b) \\Rightarrow a = b \\]",
|
||||
"",
|
||||
"\\begin{align*}",
|
||||
" f(a) &= f(b) \\\\",
|
||||
" $0",
|
||||
"\\end{align*}",
|
||||
"",
|
||||
"Hence $f(x)$ is injective."
|
||||
],
|
||||
"description": "Template for injective proof",
|
||||
},
|
||||
|
||||
"surjective-proof": {
|
||||
"scope": "latex",
|
||||
"prefix": ["prove-surjective"],
|
||||
"body": [
|
||||
"In order for $f(x)$ to be surjective, it has to hold that",
|
||||
"",
|
||||
"\\[ \\forall x \\in SET \\exists y \\in SET [f(x) = y] \\]",
|
||||
"",
|
||||
"\\begin{align*}",
|
||||
" y &= $1 \\\\",
|
||||
"",
|
||||
" x &= \\\\" ,
|
||||
"\\end{align*}",
|
||||
"",
|
||||
"$ $ makes up all the elements in SET",
|
||||
"",
|
||||
"\\begin{align*}",
|
||||
" f(y) &= \\\\",
|
||||
"",
|
||||
"\\end{align*}",
|
||||
"",
|
||||
"Hence $f(x)$ is surjective"
|
||||
],
|
||||
"description": "Template for surjective proof",
|
||||
},
|
||||
|
||||
"bijective-proof": {
|
||||
"scope": "latex",
|
||||
"prefix": ["prove-bijective"],
|
||||
"body": [
|
||||
"\\textbf{Injective:}",
|
||||
"",
|
||||
"In order for $f(x)$ to be injective, it has to hold that",
|
||||
"",
|
||||
"\\[ f(a) = f(b) \\Rightarrow a = b \\]",
|
||||
"",
|
||||
"\\begin{align*}",
|
||||
" f(a) &= f(b) \\\\",
|
||||
" $0",
|
||||
"\\end{align*}",
|
||||
"",
|
||||
"Hence $f(x)$ is injective.",
|
||||
"",
|
||||
"",
|
||||
"\\textbf{Surjective:}",
|
||||
"",
|
||||
"In order for $f(x)$ to be surjective, it has to hold that",
|
||||
"",
|
||||
"\\[ \\forall x \\in SET \\exists y \\in SET [f(x) = y] \\]",
|
||||
"",
|
||||
"\\begin{align*}",
|
||||
" y &= $1 \\\\",
|
||||
"",
|
||||
" x &= \\\\" ,
|
||||
"\\end{align*}",
|
||||
"",
|
||||
"$ $ makes up all the elements in SET",
|
||||
"",
|
||||
"\\begin{align*}",
|
||||
" f(y) &= \\\\",
|
||||
"",
|
||||
"\\end{align*}",
|
||||
"",
|
||||
"Hence $f(x)$ is surjective",
|
||||
"",
|
||||
"",
|
||||
"\\textbf{Inverse:}",
|
||||
"",
|
||||
"The inverse is the same as the expression which makes up $x$ which we used to prove that $f(x)$ is surjective. Hence",
|
||||
"",
|
||||
"\\[ f^{-1}(x) = \\]",
|
||||
],
|
||||
"description": "Template for bijective proof",
|
||||
},
|
||||
|
||||
"equivalence-relation-proof": {
|
||||
"scope": "latex",
|
||||
"prefix": ["prove-eq-rel"],
|
||||
"body": [
|
||||
"In order for this relation to be an equivalence equation, it has to be reflexive, symmetric and transitive.",
|
||||
"",
|
||||
"\\textbf{Reflexive:}",
|
||||
"",
|
||||
"\\[ \\]",
|
||||
"",
|
||||
"\\textbf{Symmetric:}",
|
||||
"",
|
||||
"\\[ \\]",
|
||||
"",
|
||||
"\\textbf{Transitive:}",
|
||||
"",
|
||||
"\\[ \\]",
|
||||
"",
|
||||
"Hence the relation is an equivalence relation",
|
||||
],
|
||||
"description": "Template for equivalence relation proof",
|
||||
},
|
||||
|
||||
"partial order-proof": {
|
||||
"scope": "latex",
|
||||
"prefix": ["prove-poset"],
|
||||
"body": [
|
||||
"In order for this relation to be a partial order, it has to be reflexive, antisymmetric and transitive.",
|
||||
"",
|
||||
"\\textbf{Reflexive:}",
|
||||
"",
|
||||
"\\[ \\]",
|
||||
"",
|
||||
"\\textbf{Antisymmetric:}",
|
||||
"",
|
||||
"\\[ \\]",
|
||||
"",
|
||||
"\\textbf{Transitive:}",
|
||||
"",
|
||||
"\\[ \\]",
|
||||
"",
|
||||
"Hence the relation is a partial order",
|
||||
],
|
||||
"description": "Template for poset proof",
|
||||
},
|
||||
|
||||
"poset minmax": {
|
||||
"scope": "latex",
|
||||
"prefix": ["minmax-poset"],
|
||||
"body": [
|
||||
"Minimal elements:",
|
||||
" \\[ \\{ $0 \\} \\]",
|
||||
"Maximal elements:",
|
||||
" \\[ \\{ \\} \\]"
|
||||
],
|
||||
"description": "Minimal maximal elements for poset",
|
||||
},
|
||||
|
||||
"Diagram": {
|
||||
"scope": "latex",
|
||||
"prefix": ["dia"],
|
||||
"body": "\\includeDiagram[caption={}, width=1\\linewidth]{graphics/$0.tex}",
|
||||
"description": "Include a diagram",
|
||||
},
|
||||
|
||||
}
|
16
exam_template/.vscode/makefile.code-snippets
vendored
Normal file
16
exam_template/.vscode/makefile.code-snippets
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
{
|
||||
"hasse": {
|
||||
"scope": "makefile",
|
||||
"prefix": ["hasse"],
|
||||
"body": "python ../../python/Hasse.py graphics/src/$1.txt graphics/$1.tex",
|
||||
"description": "Add hasse diagram",
|
||||
},
|
||||
|
||||
"FSA": {
|
||||
"scope": "makefile",
|
||||
"prefix": ["fsa"],
|
||||
"body": "python ../../python/FSA.py graphics/src/$1.txt graphics/$1.tex",
|
||||
"description": "Add FSA diagram",
|
||||
}
|
||||
}
|
9
exam_template/Makefile
Normal file
9
exam_template/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
.DEFAULT_GOAL := default
|
||||
.PHONY: default python
|
||||
|
||||
default: python
|
||||
pdflatex main.tex
|
||||
|
||||
python:
|
||||
python python/Hasse.py graphics/src/example1.txt graphics/example1.tex
|
||||
python python/FSA.py graphics/src/example2.txt graphics/example2.tex
|
16
exam_template/graphics/example1.tex
Normal file
16
exam_template/graphics/example1.tex
Normal file
@ -0,0 +1,16 @@
|
||||
\begin{tikzpicture}
|
||||
\tikzset{every node/.style={shape=circle,draw,inner sep=2pt}}
|
||||
|
||||
\node (a) at (-0.5, 0) {$a$};
|
||||
\node (e) at (-1.0, 1) {$e$};
|
||||
\node (b) at (0.0, 1) {$b$};
|
||||
\node (d) at (-1.0, 2) {$d$};
|
||||
\node (c) at (0.0, 2) {$c$};
|
||||
|
||||
\draw (a) -- (e);
|
||||
\draw (b) -- (c);
|
||||
\draw (e) -- (d);
|
||||
\draw (a) -- (b);
|
||||
\draw (e) -- (c);
|
||||
|
||||
\end{tikzpicture}
|
23
exam_template/graphics/example2.tex
Normal file
23
exam_template/graphics/example2.tex
Normal file
@ -0,0 +1,23 @@
|
||||
\begin{tikzpicture}
|
||||
\tikzset{
|
||||
->, % makes the edges directed
|
||||
>=Stealth, % makes the arrow heads bold
|
||||
node distance=5cm, % specifies the minimum distance between two nodes. Change if necessary.
|
||||
every state/.style={thick, fill=white}, % sets the properties for each ’state’ node
|
||||
initial text=$ $, % sets the text that appears on the start arrow
|
||||
}
|
||||
|
||||
\node[state, initial] (s0) {$s_0$};
|
||||
\node[state, right of=s0] (s1) {$s_1$};
|
||||
\node[state, accepting, right of=s1] (s2) {$s_2$};
|
||||
\node[state, right of=s2] (s3) {$s_3$};
|
||||
|
||||
\draw (s0) edge[above] node{$a$} (s1);
|
||||
\draw (s0) edge[bend left, above] node{$b$} (s3);
|
||||
\draw (s1) edge[loop,below] node{a} (s1);
|
||||
\draw (s1) edge[above] node{$b$} (s2);
|
||||
\draw (s2) edge[loop,below] node{b} (s2);
|
||||
\draw (s2) edge[above] node{$a$} (s3);
|
||||
\draw (s3) edge[loop,above] node{a,b} (s3);
|
||||
|
||||
\end{tikzpicture}
|
1
exam_template/graphics/src/example1.txt
Normal file
1
exam_template/graphics/src/example1.txt
Normal file
@ -0,0 +1 @@
|
||||
ab ac ad ae bc ed ec
|
12
exam_template/graphics/src/example2.txt
Normal file
12
exam_template/graphics/src/example2.txt
Normal file
@ -0,0 +1,12 @@
|
||||
0 s
|
||||
1 r0
|
||||
2 fr1
|
||||
3 r2
|
||||
|
||||
0 a u 1
|
||||
0 b u( 3
|
||||
o a d 1
|
||||
1 b u 2
|
||||
o b d 2
|
||||
2 a u 3
|
||||
o a,b u 3
|
33
exam_template/main.tex
Normal file
33
exam_template/main.tex
Normal file
@ -0,0 +1,33 @@
|
||||
\documentclass[12pt]{article}
|
||||
\usepackage{ntnu}
|
||||
\usepackage{ntnu-math}
|
||||
|
||||
\author{TODO: STUDENTNUMMER}
|
||||
\title{Exam v2021}
|
||||
|
||||
\usetikzlibrary{automata, positioning, arrows.meta}
|
||||
|
||||
\newcommand{\I}{Option 1 is correct}
|
||||
\newcommand{\II}{Option 2 is correct}
|
||||
\newcommand{\III}{Option 3 is correct}
|
||||
|
||||
\renewcommand{\theenumi}{\arabic{enumi}}
|
||||
\renewcommand{\theenumii}{(\arabic{enumii})}
|
||||
\renewcommand{\theenumiii}{\alph{enumiii})}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\ntnuTitle{}
|
||||
\break{}
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\begin{excs}
|
||||
\exc{}
|
||||
\begin{subexcs}
|
||||
\subexc{}
|
||||
|
||||
\end{subexcs}
|
||||
\end{excs}
|
||||
|
||||
\end{document}
|
74
exam_template/python/FSA.py
Normal file
74
exam_template/python/FSA.py
Normal file
@ -0,0 +1,74 @@
|
||||
from sys import argv
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
placementChart = {
|
||||
'a': 'above',
|
||||
'b': 'below',
|
||||
'l': 'left',
|
||||
'r': 'right'
|
||||
}
|
||||
|
||||
def generateEdge(inputLine):
|
||||
s_src, msg, opts, s_dest = inputLine.split(' ')
|
||||
|
||||
out_options = []
|
||||
|
||||
if '(' in opts or ')' in opts:
|
||||
out_options.append('bend left' if '(' in opts else 'bend right')
|
||||
|
||||
if any(x in opts for x in 'udlr'):
|
||||
out_options.append(
|
||||
'above' if 'u' in opts else \
|
||||
'below' if 'd' in opts else \
|
||||
'left' if 'l' in opts else \
|
||||
'right' if 'r' in opts else ''
|
||||
)
|
||||
|
||||
|
||||
if s_src == 'o':
|
||||
return f'\draw (s{s_dest}) edge[loop,{",".join(out_options)}] node{{{msg}}} (s{s_dest});'
|
||||
else:
|
||||
return f'\draw (s{s_src}) edge[{", ".join(out_options)}] node{{${msg}$}} (s{s_dest});'
|
||||
|
||||
def generateNode(inputLine):
|
||||
s_src, opts = inputLine.split(' ')
|
||||
|
||||
out_opts = []
|
||||
if 's' in opts:
|
||||
out_opts.append('initial')
|
||||
if 'f' in opts:
|
||||
out_opts.append('accepting')
|
||||
|
||||
if place := re.search('[udlr]\d+', opts):
|
||||
out_opts.append(placementChart[place.group()[0]] + ' of=s' + place.group()[1])
|
||||
|
||||
return f'\\node[state, {", ".join(out_opts)}] (s{s_src}) {{$s_{s_src}$}};'
|
||||
|
||||
|
||||
def generate_latex(inputLines):
|
||||
|
||||
nodes, edges = inputLines.split('\n\n')
|
||||
|
||||
output=[]
|
||||
|
||||
for node in nodes.split('\n'):
|
||||
output.append(generateNode(node))
|
||||
|
||||
output.append('')
|
||||
|
||||
for edge in edges.split('\n'):
|
||||
output.append(generateEdge(edge))
|
||||
|
||||
return '\n'.join(output)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
filename = argv[1]
|
||||
|
||||
with open(filename) as file:
|
||||
content = generate_latex(file.read())
|
||||
|
||||
with open(str(Path(__file__).parent.absolute()) + '/tex_templates/FSA.tex') as template:
|
||||
with open(argv[2], 'w') as destination_file:
|
||||
destination_file.write(template.read().replace('%CONTENT', content))
|
82
exam_template/python/Hasse.py
Normal file
82
exam_template/python/Hasse.py
Normal file
@ -0,0 +1,82 @@
|
||||
from sys import argv
|
||||
from pathlib import Path
|
||||
|
||||
# Increase if the diagram becomes too clobbered
|
||||
HEIGHT_SEPARATOR = 1
|
||||
|
||||
def printred(text):
|
||||
print(f'\033[31m{text}\033[0m')
|
||||
|
||||
# For manual usage via stdin
|
||||
def getRels(relations=None):
|
||||
if relations == None:
|
||||
relations = input("Write the relations in the following format: ab ac ad bc cd ...\n")
|
||||
relations = (tuple(list(x)) for x in relations.split(' '))
|
||||
return set(relations)
|
||||
|
||||
# Generate divisibility graph by range
|
||||
def divisibility_graph(n):
|
||||
E = set()
|
||||
for dst in range(n):
|
||||
for src in range( 1, dst ):
|
||||
if dst % src == 0:
|
||||
E.add( ( src, dst ) )
|
||||
return E
|
||||
|
||||
def hasse_diagram(E):
|
||||
E2 = set()
|
||||
for e0 in E:
|
||||
for e1 in E:
|
||||
if e0[1] == e1[0]:
|
||||
E2.add( ( e0[0], e1[1] ) )
|
||||
return E - E2
|
||||
|
||||
def latex_hasse(hasse):
|
||||
min_el = set(a for a,b in hasse if a not in list(zip(*hasse))[1])
|
||||
keys = set(item for tup in hasse for item in tup)
|
||||
y_pos = dict.fromkeys(keys, 0)
|
||||
|
||||
i = 0
|
||||
while len(next_row := [val for key,val in hasse if key in [x for x,y in y_pos.items() if y == i] ]) != 0:
|
||||
for item in next_row:
|
||||
y_pos[item] = i + 1
|
||||
i += 1
|
||||
|
||||
inv_ypos = dict()
|
||||
for key in set(y_pos.values()):
|
||||
inv_ypos[key] = [x for x,y in y_pos.items() if y == key]
|
||||
|
||||
output = []
|
||||
|
||||
for y in inv_ypos.keys():
|
||||
for i, n in enumerate(inv_ypos[y]):
|
||||
output.append(f'\\node ({n}) at ({i - len(inv_ypos[y])/2}, {y * HEIGHT_SEPARATOR}) {{${n}$}};')
|
||||
|
||||
output.append('')
|
||||
|
||||
for x,y in hasse:
|
||||
output.append(f'\\draw ({x}) -- ({y});')
|
||||
|
||||
|
||||
printred(f"Minimal elements: $\{{ {', '.join(str(e) for e in min_el)} \}}$ \\\\")
|
||||
|
||||
max_el = set(v for k,v in hasse if v not in (x for x,_ in hasse))
|
||||
printred(f"Maximal elements: $\{{ {', '.join(str(e) for e in max_el)} \}}$" )
|
||||
|
||||
return '\n'.join(output)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
filename = argv[1]
|
||||
|
||||
with open(filename) as file:
|
||||
rels = getRels(file.read())
|
||||
|
||||
# rels = getRels()
|
||||
# rels = divisibility_graph(30)
|
||||
|
||||
content = latex_hasse(hasse_diagram(rels))
|
||||
|
||||
with open(str(Path(__file__).parent.absolute()) + '/tex_templates/Hasse.tex') as template:
|
||||
with open(argv[2], 'w') as destination_file:
|
||||
destination_file.write(template.read().replace('%CONTENT', content))
|
12
exam_template/python/tex_templates/FSA.tex
Normal file
12
exam_template/python/tex_templates/FSA.tex
Normal file
@ -0,0 +1,12 @@
|
||||
\begin{tikzpicture}
|
||||
\tikzset{
|
||||
->, % makes the edges directed
|
||||
>=Stealth, % makes the arrow heads bold
|
||||
node distance=5cm, % specifies the minimum distance between two nodes. Change if necessary.
|
||||
every state/.style={thick, fill=white}, % sets the properties for each ’state’ node
|
||||
initial text=$ $, % sets the text that appears on the start arrow
|
||||
}
|
||||
|
||||
%CONTENT
|
||||
|
||||
\end{tikzpicture}
|
6
exam_template/python/tex_templates/Hasse.tex
Normal file
6
exam_template/python/tex_templates/Hasse.tex
Normal file
@ -0,0 +1,6 @@
|
||||
\begin{tikzpicture}
|
||||
\tikzset{every node/.style={shape=circle,draw,inner sep=2pt}}
|
||||
|
||||
%CONTENT
|
||||
|
||||
\end{tikzpicture}
|
Loading…
Reference in New Issue
Block a user