From 3ca73937590a4415b555a7365f3949025d770905 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 8 Jan 2023 09:10:54 -0800 Subject: [PATCH 01/11] Applied edits to network flow handout --- Advanced/Graph Algorithms/parts/00 review.tex | 36 +++---------------- Advanced/Graph Algorithms/parts/01 flow.tex | 29 +++++++-------- .../Graph Algorithms/parts/02 residual.tex | 9 +++-- .../Graph Algorithms/parts/03 fulkerson.tex | 2 +- .../parts/04 applications.tex | 9 ++--- .../Graph Algorithms/parts/05 reductions.tex | 12 ++----- Advanced/Graph Algorithms/parts/06 bonus.tex | 4 +-- Advanced/Graph Algorithms/tikxset.tex | 4 +++ 8 files changed, 35 insertions(+), 70 deletions(-) diff --git a/Advanced/Graph Algorithms/parts/00 review.tex b/Advanced/Graph Algorithms/parts/00 review.tex index 3781dae..db4e0f4 100755 --- a/Advanced/Graph Algorithms/parts/00 review.tex +++ b/Advanced/Graph Algorithms/parts/00 review.tex @@ -2,7 +2,7 @@ \definition{} A \textit{graph} consists of a set of \textit{nodes} $\{A, B, ...\}$ and a set of edges $\{ (A,B), (A,C), ...\}$ connecting them. -A \textit{directed graph} is a graph where edges have direction. In such a graph, $(A, B)$ and $(B, A)$ are distinct edges. +A \textit{directed graph} is a graph where edges have direction. In such a graph, edges $(A, B)$ and $(B, A)$ are distinct. A \textit{weighted graph} is a graph that features weights on its edges. \\ A weighted directed graph is shown below. @@ -28,8 +28,7 @@ A weighted directed graph is shown below. \vfill \definition{} -We say a graph is \textit{bipartite} if its nodes can be split into two groups $L$ and $R$ so that no two nodes in the same group are connected by an edge. \\ -The following graph is bipartite: +We say a graph is \textit{bipartite} if its nodes can be split into two groups $L$ and $R$, where no two nodes in the same group are connected by an edge: \\ \begin{center} \begin{tikzpicture} @@ -39,9 +38,9 @@ The following graph is bipartite: \node[main] (B) at (0mm, -10mm) {$B$}; \node[main] (C) at (0mm, -20mm) {$C$}; - \node[main] (D) at (20mm, 0mm) {$D$}; - \node[main] (E) at (20mm, -10mm) {$E$}; - \node[main] (F) at (20mm, -20mm) {$F$}; + \node[main, hatch] (D) at (20mm, 0mm) {$D$}; + \node[main, hatch] (E) at (20mm, -10mm) {$E$}; + \node[main, hatch] (F) at (20mm, -20mm) {$F$}; \end{scope} % Edges @@ -55,30 +54,5 @@ The following graph is bipartite: \end{tikzpicture} \end{center} -\vfill - -\definition{} -We say two nodes $A$ ane $B$ are \textit{connected} if we can reach $A$ from $B$ and $B$ from $A$ by walking along (possibly directed) edges. We say a graph is connected if all its nodes are connected to each other.\\ - -The bipartite graph above and the directed graph below are not connected. - -\begin{center} - \begin{tikzpicture}[node distance = 20mm] - % Nodes - \begin{scope} - \node[main] (A) {$A$}; - \node[main] (B) [below right of = A] {$B$}; - \node[main] (C) [below left of = A] {$C$}; - \end{scope} - - % Edges - \draw[->] - (A) edge[bend right] (B) - (B) edge[bend right] (A) - (B) edge (C) - ; - \end{tikzpicture} -\end{center} - \vfill \pagebreak \ No newline at end of file diff --git a/Advanced/Graph Algorithms/parts/01 flow.tex b/Advanced/Graph Algorithms/parts/01 flow.tex index 07b1361..538f83b 100755 --- a/Advanced/Graph Algorithms/parts/01 flow.tex +++ b/Advanced/Graph Algorithms/parts/01 flow.tex @@ -1,23 +1,23 @@ \section{Network Flow} \generic{Networks} -Say have a network: a sequence of pipes, a set of cities and highways, an electrical circuit, server infrastructure, etc. +Say have a network: a sequence of pipes, a set of cities and highways, an electrical circuit, etc. \vspace{1ex} -We'll represent our network with a connected directed weighted graph. If we take a city, edges will be highways and cities will be nodes. There are a few conditions for a valid network graph: +We can draw this network as a directed weighted graph. If we take a transporation network, for example, edges will represent highways and nodes will be cities. There are a few conditions for a valid network graph: \begin{itemize} - \item The weight of each edge represents its capacity, the number of lanes in the highway. + \item The weight of each edge represents its capacity, e.g, the number of lanes in the highway. \item Edge capacities are always positive integers.\hspace{-0.5ex}\footnotemark{} \item Node $S$ is a \textit{source}: it produces flow. \item Node $T$ is a \textit{sink}: it consumes flow. - \item All other nodes \textit{conserve} flow. In other words, the sum of flow coming in must equal the sum of flow going out. + \item All other nodes \textit{conserve} flow. The sum of flow coming in must equal the sum of flow going out. \end{itemize} \footnotetext{An edge with capacity zero is equivalent to an edge that does not exist; An edge with negative capacity is equivalent to an edge in the opposite direction.} -Here is an example of a such a graph: +Here is an example of such a graph: \begin{center} \begin{tikzpicture} @@ -43,7 +43,7 @@ Here is an example of a such a graph: \hrule{} \generic{Flow} -In our city example, cars represent \textit{flow}. Let's send one unit of cars along the topmost highway: +In our city example, traffic represents \textit{flow}. Let's send one unit of traffic along the topmost highway: \vspace{2ex} @@ -89,11 +89,9 @@ In our city example, cars represent \textit{flow}. Let's send one unit of cars a \vspace{1ex} -The \textit{magnitude} of a flow\footnotemark{} is the number of \say{flow-units} that go from $S$ to $T$. \\ +The \textit{magnitude} of a flow is the number of \say{flow-units} that go from $S$ to $T$. \\ -We are interested in the \textit{maximum flow} through this network: what is the greatest amount of flow we can push from $S$ to $T$? - -\footnotetext{you could also think of \say{flow} as a directed weighted graph on top of our network.} +We are interested in the \textit{maximum flow} through this network: what is the greatest amount of flow we can get from $S$ to $T$? \problem{} What is the magnitude of the flow above? @@ -156,7 +154,8 @@ Find a maximal flow on the graph below. \\ \pagebreak \section{Combining Flows} -It is fairly easy to combine two flows on a graph. All we need to do is add the flows along each edge. For example, consider the following flows: +It is fairly easy to combine two flows on a graph. All we need to do is add the flows along each edge. \\ +Consider the following flows: \vspace{2ex} @@ -266,11 +265,7 @@ It is fairly easy to combine two flows on a graph. All we need to do is add the \vspace{1ex} - For example, we could not add these graphs if the magnitude of flow in the right graph above was 2. - - \vspace{1ex} - - This is because the capacity of the top-right edge is 2, and $2 + 1 > 2$. + For example, we could not add these graphs if the magnitude of flow in the right graph above was 2, since the capacity of the top-right edge is 2, and $2 + 1 > 2$. \end{minipage} \vspace{2ex} @@ -278,7 +273,7 @@ It is fairly easy to combine two flows on a graph. All we need to do is add the \vspace{2ex} \problem{} -Combine the following flows and ensure that the flow along all edges remains within capacity. +Combine the flows below, ensuring that the flow along each edge remains within capacity. \vspace{2ex} diff --git a/Advanced/Graph Algorithms/parts/02 residual.tex b/Advanced/Graph Algorithms/parts/02 residual.tex index f8ff5c6..f37e946 100755 --- a/Advanced/Graph Algorithms/parts/02 residual.tex +++ b/Advanced/Graph Algorithms/parts/02 residual.tex @@ -1,9 +1,10 @@ \section{Residual Graphs} -As our network gets bigger, finding a maximum flow by hand becomes much more difficult. It will be convenient to have an algorithm that finds a maximal flow in any network. +It is hard to find a maximum flow for a large network by hand. \\ +We need to create an algorithm to accomplish this task. \vspace{1ex} -The first thing we'll need to construct such an algorithm is a \textit{residual graph}. +The first thing we'll is the notion of a \textit{residual graph}. \vspace{2ex} \hrule @@ -202,11 +203,9 @@ If it isn't, find a maximal flow. \\ \problem{} Show that... \begin{enumerate} - \item A maximal flow exists in every network with integral\footnotemark{} edge weights. + \item A maximal flow exists in every network with integral edge weights. \item Every edge in this flow carries an integral amount of flow \end{enumerate} -\footnotetext{Integral = \say{integer} as an adjective.} - \vfill \pagebreak \ No newline at end of file diff --git a/Advanced/Graph Algorithms/parts/03 fulkerson.tex b/Advanced/Graph Algorithms/parts/03 fulkerson.tex index f1524c1..cf837bc 100755 --- a/Advanced/Graph Algorithms/parts/03 fulkerson.tex +++ b/Advanced/Graph Algorithms/parts/03 fulkerson.tex @@ -108,7 +108,7 @@ There is extra space on the next page. \pagebreak \problem{} -You are given a large network. How would you quickly find an upper bound for the number of iterations the Ford-Fulkerson algorithm will need to find a maximum flow? +You are given a large network. How can you quickly find an upper bound for the number of iterations the Ford-Fulkerson algorithm will need to find a maximum flow? \begin{solution} Each iteration adds at least one unit of flow. So, we will find a maximum flow in at most $\min(\text{flow out of } S,~\text{flow into } T)$ iterations. diff --git a/Advanced/Graph Algorithms/parts/04 applications.tex b/Advanced/Graph Algorithms/parts/04 applications.tex index 883db36..e648a24 100755 --- a/Advanced/Graph Algorithms/parts/04 applications.tex +++ b/Advanced/Graph Algorithms/parts/04 applications.tex @@ -86,8 +86,9 @@ A matching is \textit{maximal} if it has more edges than any other matching. \vspace{5mm} -Devise an algorithm to find a maximal matching in any bipartite graph. \\ -Find an upper bound for its runtime. +Create an algorithm that finds a maximal matching in any bipartite graph. \\ +Find an upper bound for its runtime. \\ +\hint{Can you modify an algorithm we already know?} \begin{solution} Turn this into a maximum flow problem and use FF. \\ @@ -101,7 +102,7 @@ Find an upper bound for its runtime. \vfill \pagebreak -\problem{Circulations with Demand} +\problem{Supply and Demand} Say we have a network of cities and power stations. Stations produce power; cities consume it. @@ -146,7 +147,7 @@ We'll represent station capacity with a negative number, since they \textit{cons \end{tikzpicture} \end{center} -We'd like to know if there exists a \textit{feasible circulation} in this network---that is, can we supply our cities with the energy they need without exceeding the capacity of power plants or transmission lines? +We'd like to know if there exists a \textit{feasible circulation} in this network---that is, can we supply our cities with the energy they need without exceeding the capacity of our power plants and transmission lines? \vspace{2ex} diff --git a/Advanced/Graph Algorithms/parts/05 reductions.tex b/Advanced/Graph Algorithms/parts/05 reductions.tex index 9376b27..0ad1859 100755 --- a/Advanced/Graph Algorithms/parts/05 reductions.tex +++ b/Advanced/Graph Algorithms/parts/05 reductions.tex @@ -8,11 +8,7 @@ An \textit{independent set} is a set of vertices\footnotemark{} in which no two \begin{center} \begin{tikzpicture}[ - node distance = 12mm, - hatch/.style = { - pattern=north west lines, - pattern color=gray - } + node distance = 12mm ] % Nodes \begin{scope}[layer = nodes] @@ -48,11 +44,7 @@ A \textit{vertex cover} is a set of vertices that includes at least one endpoint \begin{center} \begin{tikzpicture}[ - node distance = 12mm, - hatch/.style = { - pattern=north west lines, - pattern color=gray - } + node distance = 12mm ] % Nodes \begin{scope}[layer = nodes] diff --git a/Advanced/Graph Algorithms/parts/06 bonus.tex b/Advanced/Graph Algorithms/parts/06 bonus.tex index 83d5438..be94bae 100644 --- a/Advanced/Graph Algorithms/parts/06 bonus.tex +++ b/Advanced/Graph Algorithms/parts/06 bonus.tex @@ -1,6 +1,6 @@ -\section{Crosses (Bonus Problem)} +\section{Crosses} -You are given an $n \times n$ grid. Some of its squares are white, and some are gray. Your goal is to place $n$ crosses on white cells so that each row and each column contains exactly one cross. +You are given an $n \times n$ grid. Some of its squares are white, some are gray. Your goal is to place $n$ crosses on white cells so that each row and each column contains exactly one cross. \vspace{2ex} diff --git a/Advanced/Graph Algorithms/tikxset.tex b/Advanced/Graph Algorithms/tikxset.tex index 9c0d794..4991f1d 100644 --- a/Advanced/Graph Algorithms/tikxset.tex +++ b/Advanced/Graph Algorithms/tikxset.tex @@ -49,5 +49,9 @@ % completely under nodes. line cap = rect, opacity = 0.3 + }, + hatch/.style = { + pattern=north west lines, + pattern color=gray } } \ No newline at end of file From 81ba94739c39703a293d8e72946e1ad5a2a1736d Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 8 Jan 2023 10:34:53 -0800 Subject: [PATCH 02/11] Added electrician's warm-up --- Misc/Warm-Ups/electician.tex | 160 +++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100755 Misc/Warm-Ups/electician.tex diff --git a/Misc/Warm-Ups/electician.tex b/Misc/Warm-Ups/electician.tex new file mode 100755 index 0000000..f360d40 --- /dev/null +++ b/Misc/Warm-Ups/electician.tex @@ -0,0 +1,160 @@ +% https://git.betalupi.com/Mark/latex-packages +% use [nosolutions] flag to hide solutions. +% use [solutions] flag to show solutions. +% Last built with version 1.1.0 +\documentclass[ + nosolutions, + singlenumbering +]{ormc_handout} + +% We put nodes in a separate layer, so we can +% slightly overlap with paths for a perfect fit +\pgfdeclarelayer{nodes} +\pgfsetlayers{main,nodes} + +% Layer settings +\tikzset{ + % Layer hack, lets us write + % later = * in scopes. + layer/.style = { + execute at begin scope={\pgfonlayer{#1}}, + execute at end scope={\endpgfonlayer} + } +} + +\begin{document} + + \maketitle + {The Electrician's Warm-Up} + {Prepared by Mark on \today} + + Ivan the electician is working in an apartment. He has a box of switches, which come in three types: + \begin{center} + \begin{minipage}[t]{0.3\textwidth} + \begin{center} + Plain switch + \end{center} + \begin{center} + \begin{tikzpicture} + % A state + \node at (0.375, -1.25) {A}; + \draw[line width=1mm] (0, 0) -- (0.75, 0); + + \draw[fill=white] (0, 0) circle (1mm); + \draw[fill=white] (0.75, 0) circle (1mm); + + % B state + \node at (2.375, -1.25) {B}; + \draw[line width=1mm,cap=round] (2, 0) -- (2.6, 0.4); + + \draw[fill=white] (2, 0) circle (1mm); + \draw[fill=white] (2.75, 0) circle (1mm); + \end{tikzpicture} + \end{center} + \end{minipage} + \begin{minipage}[t]{0.3\textwidth} + \begin{center} + Three-way switch + \end{center} + \begin{center} + \begin{tikzpicture} + % A state + \node at (0.375, -1) {A}; + \draw[line width=1mm] (0, 0) -- (0.75, 0.5); + + \draw[fill=white] (0, 0) circle (1mm); + \draw[fill=white] (0.75, 0.5) circle (1mm); + \draw[fill=white] (0.75, -0.5) circle (1mm); + + % B state + \node at (2.375, -1) {B}; + \draw[line width=1mm] (2, 0) -- (2.75, -0.5); + + \draw[fill=white] (2, 0) circle (1mm); + \draw[fill=white] (2.75, 0.5) circle (1mm); + \draw[fill=white] (2.75, -0.5) circle (1mm); + \end{tikzpicture} + \end{center} + \end{minipage} + \hfill + \begin{minipage}[t]{0.3\textwidth} + \begin{center} + Four-way switch + \end{center} + \begin{center} + \begin{tikzpicture} + % A state + \node at (0.375, -0.5) {A}; + \draw[line width=1mm] (0, 0) -- (0.75, 1); + \draw[line width=1mm] (0, 1) -- (0.75, 0); + + \draw[fill=white] (0, 0) circle (1mm); + \draw[fill=white] (0.75, 0) circle (1mm); + \draw[fill=white] (0, 1) circle (1mm); + \draw[fill=white] (0.75, 1) circle (1mm); + + % B state + \node at (2.375, -0.5) {B}; + \draw[line width=1mm] (2, 0) -- (2.75, 0); + \draw[line width=1mm] (2, 1) -- (2.75, 1); + + \draw[fill=white] (2, 0) circle (1mm); + \draw[fill=white] (2.75, 0) circle (1mm); + \draw[fill=white] (2, 1) circle (1mm); + \draw[fill=white] (2.75, 1) circle (1mm); + \end{tikzpicture} + \end{center} + \end{minipage} + \end{center} + + When a switch is pointing up, it is in the \say{A} state. When it is pointing down, it is in the \say{B} state. Each circle represents a terminal on the switch, and lines represent electrical connections. + + \example{} + First, Ivan wires a simple light in the kitchen: one switch, one lamp. The result is the following circuit: + + \begin{center} + \begin{tikzpicture} + + \begin{scope}[layer = nodes] + + \draw[fill=white] (-1.5, 0) circle (1mm); + + \node (h) at (-2, 0) {\texttt{Hot}}; + + \draw[fill=white] (0, 0) circle (1mm); + \draw[fill=white] (0.75, 0) circle (1mm); + + \node[ + circle, + draw = black, + fill = white, + label = below:\texttt{Lamp} + ] (l) at (2,0) {$\circledast$}; + + \draw[fill=white] (3.5, 0) circle (1mm); + + \node (n) at (4.5, 0) {\texttt{Neutral}}; + + \end{scope} + + \draw[line width=1mm,cap=round] (-1.5, 0) -- (0, 0); + \draw[line width=1mm,cap=round] (0, 0) -- (0.6, 0.4); + \draw[line width=1mm,cap=round] (0.75, 0) -- (l); + \draw[line width=1mm,cap=round] (l) -- (3.5,0); + \end{tikzpicture} + \end{center} + + \problem{} + Ivan now needs to wire a hallway. It has two switches, one at each end. Toggling either switch should toggle the single lamp in the middle. Which switches should Ivan use, and how should he connect their terminals? + + \vfill + + + \problem{} + Next, Ivan goes to the bedroom. There is one switch by the door and one on each side of the bed. How can he make these three switches control one lamp? + + \vfill + + \problem{Bonus} + Is it possible to do the same with four or more switches? If so, how? +\end{document} \ No newline at end of file From 2342ef994d8b7fa3bc5ac8d0f3093aad25b65c17 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 8 Jan 2023 19:29:05 -0800 Subject: [PATCH 03/11] Typo --- Advanced/Graph Algorithms/parts/02 residual.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Advanced/Graph Algorithms/parts/02 residual.tex b/Advanced/Graph Algorithms/parts/02 residual.tex index f37e946..a33611a 100755 --- a/Advanced/Graph Algorithms/parts/02 residual.tex +++ b/Advanced/Graph Algorithms/parts/02 residual.tex @@ -4,7 +4,7 @@ We need to create an algorithm to accomplish this task. \vspace{1ex} -The first thing we'll is the notion of a \textit{residual graph}. +The first thing we'll need is the notion of a \textit{residual graph}. \vspace{2ex} \hrule From 7324adf7c115e5a26f64a8cb306e479bfdf2374e Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 9 Jan 2023 22:00:41 -0800 Subject: [PATCH 04/11] Added RAID warm-up --- Misc/Warm-Ups/raid.tex | 99 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100755 Misc/Warm-Ups/raid.tex diff --git a/Misc/Warm-Ups/raid.tex b/Misc/Warm-Ups/raid.tex new file mode 100755 index 0000000..7e03189 --- /dev/null +++ b/Misc/Warm-Ups/raid.tex @@ -0,0 +1,99 @@ +% https://git.betalupi.com/Mark/latex-packages +% use [nosolutions] flag to hide solutions. +% use [solutions] flag to show solutions. +% Last built with version 1.1.0 +\documentclass[ + nosolutions, + singlenumbering, + nopagenumber +]{ormc_handout} + +\usepackage{tikz} + +\begin{document} + + \maketitle + {The Sysadmin's Warm-Up} + {Prepared by Mark on \today} + + + Most of you have seen a hard drive. Many have touched one, and a lucky few have poked around inside one. These devices have two interesting properties: + + \begin{enumerate} + \item They hold valuable data + \item They eventually fail + \end{enumerate} + + Needless to say, this is a problem. \\ + We need to design a system that allows hard drives to fail without data loss. + + \definition{} + You can think of a hard drive as a long string of bits. \\ + Assume all hard drives can store 1 TiB of data. + + \begin{center} + \begin{tikzpicture} + + \node[above] at (1/2, 0) {Drive A}; + \draw (0cm, 0cm) -- (0cm, -3cm); + \draw (1cm, 0cm) -- (1cm, -3cm); + \foreach \i in {0,...,-6} { + \draw (0cm,\i cm / 2) -- (1cm ,\i cm / 2); + } + + \node at (1/2, - 1 / 4) {1}; + \node at (1/2, - 3 / 4) {1}; + \node at (1/2, - 5 / 4) {0}; + \node at (1/2, - 7 / 4) {...}; + \node at (1/2, - 9 / 4) {1}; + \node at (1/2, -11 / 4) {0}; + + + \node[above] at (5/2, 0) {Drive B}; + \draw (2cm, 0cm) -- (2cm, -3cm); + \draw (3cm, 0cm) -- (3cm, -3cm); + \foreach \i in {0,...,-6} { + \draw (2cm,\i cm / 2) -- (3cm ,\i cm / 2); + } + + \node at (5/2, - 1 / 4) {0}; + \node at (5/2, - 3 / 4) {1}; + \node at (5/2, - 5 / 4) {0}; + \node at (5/2, - 7 / 4) {...}; + \node at (5/2, - 9 / 4) {0}; + \node at (5/2, -11 / 4) {1}; + \end{tikzpicture} + \end{center} + + \problem{} + Suppose we have two hard drives. How can we arrange our data so that... + \begin{enumerate} + \item We can store 1 TiB of data + \item We lose no data when any one drive fails + \end{enumerate} + + \vfill + + \problem{} + Suppose we have three hard drives. How can we arrange our data so that... + \begin{enumerate} + \item We can store 2 TiB of data + \item We lose no data when any one drive fails + \end{enumerate} + + \vfill + + \problem{} + Suppose we have five hard drives. How can we arrange our data so that... + \begin{enumerate} + \item We can store 3 TiB of data + \item We lose no data when any two drives fail + \end{enumerate} + + \vfill + + \problem{} + Can you write a general solution to this problem? + + \vfill +\end{document} \ No newline at end of file From 46d7d99cc61e7ed8055b7c9d3efecc65a3b9c194 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 10 Jan 2023 08:09:57 -0800 Subject: [PATCH 05/11] Warm-Up cleanup --- Misc/Warm-Ups/electician.tex | 3 ++- Misc/Warm-Ups/raid.tex | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Misc/Warm-Ups/electician.tex b/Misc/Warm-Ups/electician.tex index f360d40..b2dcb8a 100755 --- a/Misc/Warm-Ups/electician.tex +++ b/Misc/Warm-Ups/electician.tex @@ -4,7 +4,8 @@ % Last built with version 1.1.0 \documentclass[ nosolutions, - singlenumbering + singlenumbering, + nopagenumber ]{ormc_handout} % We put nodes in a separate layer, so we can diff --git a/Misc/Warm-Ups/raid.tex b/Misc/Warm-Ups/raid.tex index 7e03189..c884f59 100755 --- a/Misc/Warm-Ups/raid.tex +++ b/Misc/Warm-Ups/raid.tex @@ -69,7 +69,7 @@ Suppose we have two hard drives. How can we arrange our data so that... \begin{enumerate} \item We can store 1 TiB of data - \item We lose no data when any one drive fails + \item We lose no data if any one drive fails \end{enumerate} \vfill @@ -78,7 +78,7 @@ Suppose we have three hard drives. How can we arrange our data so that... \begin{enumerate} \item We can store 2 TiB of data - \item We lose no data when any one drive fails + \item We lose no data if any one drive fails \end{enumerate} \vfill @@ -87,7 +87,7 @@ Suppose we have five hard drives. How can we arrange our data so that... \begin{enumerate} \item We can store 3 TiB of data - \item We lose no data when any two drives fail + \item We lose no data if any two drives fail \end{enumerate} \vfill From 9e99560b387509629efb08342bba0bd666d5c189 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 12 Jan 2023 08:31:10 -0800 Subject: [PATCH 06/11] Added ECC handout --- Advanced/Error-Correcting Codes/main.tex | 28 +++ .../parts/00 detection.tex | 164 ++++++++++++++++++ .../parts/01 correction.tex | 122 +++++++++++++ .../parts/02 distance.tex | 41 +++++ .../Error-Correcting Codes/parts/03 bonus.tex | 94 ++++++++++ Advanced/Error-Correcting Codes/qr.png | Bin 0 -> 90906 bytes 6 files changed, 449 insertions(+) create mode 100755 Advanced/Error-Correcting Codes/main.tex create mode 100755 Advanced/Error-Correcting Codes/parts/00 detection.tex create mode 100644 Advanced/Error-Correcting Codes/parts/01 correction.tex create mode 100644 Advanced/Error-Correcting Codes/parts/02 distance.tex create mode 100644 Advanced/Error-Correcting Codes/parts/03 bonus.tex create mode 100644 Advanced/Error-Correcting Codes/qr.png diff --git a/Advanced/Error-Correcting Codes/main.tex b/Advanced/Error-Correcting Codes/main.tex new file mode 100755 index 0000000..8960bf5 --- /dev/null +++ b/Advanced/Error-Correcting Codes/main.tex @@ -0,0 +1,28 @@ +% https://git.betalupi.com/Mark/latex-packages +% use [nosolutions] flag to hide solutions. +% use [solutions] flag to show solutions. +% Last built with version 1.1.0 +\documentclass[ + solutions +]{ormc_handout} + +\usepackage{tikz} + +\begin{document} + + \maketitle + + + {Error-Correcting Codes} + { + Based on a handout by Yingkun Li \\ + Revised by Mark on \today + } + + + \input{parts/00 detection} + \input{parts/01 correction} + \input{parts/02 distance} + \input{parts/03 bonus} + +\end{document} \ No newline at end of file diff --git a/Advanced/Error-Correcting Codes/parts/00 detection.tex b/Advanced/Error-Correcting Codes/parts/00 detection.tex new file mode 100755 index 0000000..6b25436 --- /dev/null +++ b/Advanced/Error-Correcting Codes/parts/00 detection.tex @@ -0,0 +1,164 @@ +\section{Error Detection} + +An ISBN\footnote{International Standard Book Number} is a unique numeric book identifier. It comes in two forms: ISBN-10 and ISBN-13. Naturally, ISBN-10s have ten digits, and ISBN-13s have thirteen. The final digit in both versions is a \textit{check digit}. + +\vspace{3mm} + +Say we have a sequence of nine digits, forming a partial ISBN-10: $n_1 n_2 ... n_9$. \\ +The final digit, $n_{10}$, is calculated as follows: + +$$ + \Biggr( \sum_{i = 1}^{9} i \times n_i \Biggl) \text{ mod } 11 +$$ + +If $n_{10}$ is equal to 10, it is written as \texttt{X}. + + +\problem{} +Which of the following could be valid ISBNs? + +\begin{itemize} + \item \texttt{0-134-54896-2} + \item \texttt{0-307-29206-3} + \item \texttt{0-316-00395-6} +\end{itemize} + +\begin{solution} + Only the first has an inconsistent check digit. +\end{solution} + +\vfill +\pagebreak + +\problem{} +Show that the following sum is divisible by 11 iff $n_1n_2...n_{10}$ is a valid ISBN-10. +$$ + \sum_{i = 1}^{10} (11 - i)n_i +$$ + +\begin{solution} + Proof that valid $\implies$ divisible, working in mod 11: + + \vspace{2mm} + + $10n_1 + 9n_2 + ... + 2n_9 + n_{10} \equiv$ \\ + $(-n_1) + (-2n_2) + ... + (-9n_9) + n_{10} =$ \\ + $-n_{10} + n_{10} \equiv 0$ + + \vspace{2mm} + + Having done this, the rest is easy. Work in reverse, or note that each step above is an iff. + +\end{solution} + +\vfill + +\problem{} +Take a valid ISBN-10 and change one digit. Is it possible that you get another valid ISBN-10? \\ +Provide an example or a proof. + +\begin{solution} + Let $S$ be the sum $10n_1 + 9n_2 + ... + 2n_9 + n_{10}$, before any digits are changed. + + \vspace{3mm} + + If you change one digit of the ISBN, $S$ changes by $km$, where $k \in \{1,2,...,10\}$ and $|m| \leq 10$. \\ + $k$ and $m$ cannot be divisible by 11, thus $km$ cannot be divisible by 11. + + \vspace{3mm} + + We know that $S \equiv 0 \text{ (mod 11)}$. \\ + After the change, the checksum is $S + km \equiv km \not\equiv 0 \text{ (mod 11)}$. +\end{solution} + +\vfill + +\problem{} +Take a valid ISBN-10 and swap two adjacent digits. When will the result be a valid ISBN-10? \\ +This is called a \textit{transposition error}. + + +\begin{solution} + Let $n_1n_2...n_{10}$ be a valid ISBN-10. \\ + When we swap $n_i$ and $n_{i+1}$, we subtract $n_i$ and add $n_{i+1}$ to the checksum. + + \vspace{3mm} + + If the new ISBN is to be valid, we must have that $n_{i+1} - n_i \equiv 0 \text{ (mod 11)}$. \\ + This is impossible unless $n_i = n_{i+1}$. Figure out why yourself. +\end{solution} + +\vfill +\pagebreak + +\problem{} +ISBN-13 error checking is slightly different. Given a partial ISBN-13 $n_1 n_2 n_3 ... n_{12}$, the final digit is given by + +$$ + n_{13} = \Biggr[ \sum_{i=1}^{12} n_i \times (2 + (-1)^i) \Biggl] \text{ mod } 10 +$$ + +What is the last digit of the following ISBN-13? \\ +\texttt{978-0-380-97726-?} + +\begin{solution} + The final digit is 0. +\end{solution} + +\vfill + +\problem{} +Take a valid ISBN-13 and change one digit. Is it possible that you get another valid ISBN-13? \\ +Provide an example or a proof. + +\begin{solution} + Let $n_1n_2...n_{13}$ be a valid ISBN-13. Choose some $n_i$ and change it to $m_i$. \\ + + \vspace{3mm} + + Since $n_i$, $m_i$ $\in \{0, 1, 2, ..., 9\}$, $-9 \leq n_i - m_i \leq 9$. \\ + + \vspace{2mm} + + Case 0: $i$ is 13 \\ + This is trivial. + + \vspace{2mm} + + Case 1: $i$ is odd \\ + For the new ISBN to be valid, we need $n_i - m_i \equiv 0 \text{ (mod 10)}$. \\ + This cannot happen if $n_i \neq m_i$. + + \vspace{2mm} + + Case 2: $i$ is even \\ + For the new ISBN to be valid, we need $3(n_i - m_i) \equiv 0 \text{ (mod 10)}$ \\ + This cannot happen, 10 and 3 are coprime. +\end{solution} + +\vfill + +\problem{} +Take a valid ISBN-13 and swap two adjacent digits. When will the result be a valid ISBN-13? \\ +\hint{The answer here is more interesting than it was last time.} + +\begin{solution} + Say we swap $n_i$ and $n_{i+1}$, where $i \in \{1, 2, ..., 11\}$. \\ + The checksum changes by $2(n_{i+1} - n_i)$, and will \\ + remain the same if this value is $\equiv 0 \text{ (mod 10)}$. +\end{solution} + +\vfill + +\problem{} +\texttt{978-0-08-2066-46-6} was a valid ISBN until I changed a single digit. \\ +Can you tell me which digit I changed? + +\begin{solution} + Nope, unless you look at the meaning of each digit in the spec. \\ + If you're unlucky, maybe not even then. +\end{solution} + + +\vfill +\pagebreak diff --git a/Advanced/Error-Correcting Codes/parts/01 correction.tex b/Advanced/Error-Correcting Codes/parts/01 correction.tex new file mode 100644 index 0000000..883c85a --- /dev/null +++ b/Advanced/Error-Correcting Codes/parts/01 correction.tex @@ -0,0 +1,122 @@ +\section{Error Correction} + +Error detection is helpful, but we'd also like to fix errors when we find them. One example of such a system is the QR code, which remains readable even if a significant amount of it is removed. QR codes with icons inside aren't special--they're just missing their central elements. The error-correcting codes in the QR specification allow us to recover the lost data. +\begin{figure}[h] + \centering + \includegraphics[width = 3cm]{qr} +\end{figure} + +\definition{Repeating codes} +The simplest possible error-correcting code is a \say{repeating code}. It works just as you'd expect: \\ +Instead of sending data once, it sends multiple copies. If a few bits are damaged, they can be both detected and repaired. \\ + +For example, consider the following three-repeat code encoding the binary string $101$: + +$$ + 111~000~111 +$$ + +If we flip any one bit, we can easily find and fix the error. + +\definition{Code Efficiency} +The efficiency of an error-correcting code is calculated as follows: +$$ +\frac{\text{number of data bits}}{\text{total bits sent}} +$$ + +For example, the efficiency of the three-repeat code above is $\frac{3}{9} = \frac{1}{3} \approx 0.33$ + +\problem{} +What is the efficiency of an $k$-repeat code? + +\vfill + +\problem{} +How many repeated digits do you need to... +\begin{itemize} + \item[-] detect a transposition error? + \item[-] correct a transposition error? +\end{itemize} + +\vfill +\pagebreak + +\definition{Hamming's Square Code} + +A more effective coding scheme comes in the form of Hamming's square code. +Take a four-bit message and arrange it in a $2 \times 2$ square. \\ + +Compute the pairity of each row and write it at the right. \\ +Compute the pairity of each column and write it at the bottom. \\ +Finally, compute the pairity of the entire message write it in the lower right corner. + +\vspace{3mm} + +Reading the result row by row to get the encoded message. \\ +For example, the message 1011 generates the sequence 101110011: + +$$ +1011 +\longrightarrow +\begin{array}{cc|} + 1 & 0 \\ + 1 & 1 \\ + \hline +\end{array} +\longrightarrow +\begin{array}{cc|c} + 1 & 0 & 1 \\ + 1 & 1 & 0 \\ \hline + 0 & 1 & +\end{array} +\longrightarrow +\begin{array}{cc|c} + 1 & 0 & 1 \\ + 1 & 1 & 0 \\ \hline + 0 & 1 & 1 +\end{array} +\longrightarrow +101110011 +$$ + +\problem{} +The following message are encoded using the method above. +Find and correct any single-digit or transposition errors. +\begin{enumerate} + \item \texttt{110 110 011} %101110011 + \item \texttt{100 101 011} %110101011 + \item \texttt{001 010 110} %000110110 +\end{enumerate} + +\begin{solution} + \begin{enumerate} + \item \texttt{101 110 011} or \texttt{110 101 011} + \item \texttt{110 101 011} + \item \texttt{000 110 110} + \end{enumerate} +\end{solution} + +\vfill + +\problem{} +What is the efficiency of this coding scheme? + +\vfill + +\problem{} +Can we correct a single-digit error in the encoded message? \\ +Can we correct a transposition error in the encoded message? + +\vfill + +\problem{} +Let's generalize this coding scheme to a non-square table: \\ +Given a message of length $ab$, construct a rectangle with dimensions $a \times b$ as described above. +\begin{itemize} + \item What is the efficiency of a $a \times b$ rectangle code? + \item Can the $a \times b$ rectangle code detect and fix single-bit errors? + \item Can the $a \times b$ rectangle code detect and fix two-bit errors? +\end{itemize} + +\vfill +\pagebreak diff --git a/Advanced/Error-Correcting Codes/parts/02 distance.tex b/Advanced/Error-Correcting Codes/parts/02 distance.tex new file mode 100644 index 0000000..a7ec4f4 --- /dev/null +++ b/Advanced/Error-Correcting Codes/parts/02 distance.tex @@ -0,0 +1,41 @@ +\section{Hamming Distance} + +\definition{} +The \textit{Hamming distance} between two strings $x = x_1x_2...x_n$ and $y = y_1y_2...y_n$ is the number of positions at which the digits of $x$ and $y$ are different. + +\problem{} +Compute the Hamming distance between \texttt{1010} and \texttt{0001}. + +\vfill + +\problem{} +Read $d_H(x, y)$ as \say{the hamming distance between $x$ and $y$.} \\ +Prove the following statements: +\begin{enumerate} +\item $d_H(x, y) \ge 0$ with equality if and only if $x = y$, +\item $d_H(x, y) = d_H(y, x)$, +\item $d_H(x, z) \le d_H(x, y) + d_H(y, z)$. +\end{enumerate} + +\vfill + +\problem{} +Say we encode and send a message with the 3-repeat code. A few bits are damaged in transit. \\ +When the transmission is decoded, a different message is read. + +\vspace{2mm} + +What is the minimum possible hamming distance between the undamaged encoded message and the damaged encoded message? + +\vfill + +\problem{} +Say we encode and send a message with Hamming's square code. A few bits are damaged in transit. \\ +When the transmission is decoded, no uncorrectable errors are detected and a different message is read. + +\vspace{2mm} + +What is the minimum possible hamming distance between the undamaged encoded message and the damaged encoded message? + +\vfill +\pagebreak \ No newline at end of file diff --git a/Advanced/Error-Correcting Codes/parts/03 bonus.tex b/Advanced/Error-Correcting Codes/parts/03 bonus.tex new file mode 100644 index 0000000..f58ecd7 --- /dev/null +++ b/Advanced/Error-Correcting Codes/parts/03 bonus.tex @@ -0,0 +1,94 @@ +\section{Hat Puzzles: The Revenge} + +\problem{} +Three people are sitting in a circle. A black or a white hat will be placed on each person's head, with equal probability. Each person can see everyone's hat color except their own. \\ + +\vspace{1mm} + +The participants are asked to simultaneously write down \say{Black}, \say{White}, or \say{Pass}. \\ +They win if at least one person guesses their hat correctly. \\ +They lose if anyone guesses incorrectly, or if everyone passes. + +\vspace{1mm} + +How can they maximize their chance of winning? + +\vfill + + +\problem{} +Consider the same game with $2^n-1$ people. How can they achieve a win rate of $\frac{2^n-1}{2^n}$? + +\vfill +\pagebreak + +% A copy of the post these problems are based on. Contains the solution. +% https://cornellmath.wordpress.com/2007/09/20/hat-guessing-puzzles-the-revenge +% +% I guess since my previous hat color guessing problem was so popular, I might as well talk about the other one I know. However, this one isn't meant to attack the foundations of mathematics. The problem is as follows: +% +% Three people are sitting in a circle. Black or white hats (50% chance of each) will all be placed on their heads, and they will be able to see everyone's hat color but their own. They will all simultaneously write down on a piece of paper either "Black", "White", or "Pass", trying to guess their own hat color. All the people collectively win (whatever that means) if at least someone guesses their hat correctly and no one guesses incorrectly. They lose if anyone guesses incorrectly, or everyone passes. If they can agree on a strategy beforehand, what is their best chance of winning? +% +% Again, there is the problem that no information can be conveyed to someone about their own hat color, so they would seem to be guessing blindly (talking and facial expressions are prohibited). However, they can still win 75% of the time. Figure it out! +% +% Once you solve the easy version of this puzzle, the harder version is with larger numbers of people. As a partial spoiler, stick to 2^n-1, where the best win rate is 2^n-1 out of 2^n. How is this possible? (Answer below the fold) +% +% The trick to the puzzle is realizing that, even though any specific person who elects not to pass has only a 50% chance of being right, the strategy can be chosen so that the wrong guesses are all concentrated into a small number of possibilities. That is, because you only need % one right guess to win and multiple wrong guesses don't make a loss worse, the strategy should attempt to make as many people wrong simultaneously if anyone is going to guess wrong. +% +% The three-person case makes a good example. Consider the following strategy: +% +% If you see two hats of the same color: Guess the opposite color. +% +% If you see two different hat colors: Pass. +% +% What happens? It's not hard to write down all the possibilities: +% +% 3 black hats: Everyone sees two black hats, and guesses White. Everyone is wrong. +% +% 2 black hats, 1 white hat: The people in black hats see both colors and Pass; the person in the white hat sees two black hats and says White. One person is correct and everyone else passed. +% +% 1 black hat, 2 white hats: This is identical to the previous case, with colors reversed. Its a win. +% +% 3 white hats: This is identical to the first case, with colors reversed. Its a loss. +% +% So unless all three hats were the same color, everyone won. However, the chances of all three hats being the same color is only 1 in 4, so its a win 75% of the time. Notice that the key was getting everyone to be wrong at the same time, but only having one correct guess in winning situations. +% +% Ok, what about more people, say, n of them? Well, we need a strategy where the wrong guesses are concentrated and the right guesses are spread out. Let's make this a little bit more mathematical, by turning white hats into 1s and black hats into 0s. Now, a possible hat scenario is a sequence of n binary digits, and every sequence is equally likely. +% +% Since the optimal strategy seems to be when all the wrong guesses happen simultaneously, we need to agree on some sequences that will be the wrong sequences, that is, the scenarios where everyone will guess incorrectly. How does this work? Say 0000000 is one of the agreed upon wrong sequences (this is for n=7). Then, if someone looks around and sees all zeros/black hats, they will guess white. That way, everyone will be wrong if it is all black hats; but if there is exactly one white hat, everyone wins! Since it is n times more likely for there to be exactly one white hat than no white hats, this seems to work pretty well. +% +% The general strategy if you have a whole bunch of wrong sequences is for everyone to look around, and: +% +% If it looks like you might be in a wrong sequence, guess the opposite possibility. +% +% If you are definitely not in a wrong sequence, pass. +% +% (Note that we are assuming that no two wrong sequences differ by a single digit, so that there is always an 'opposite possiblity') How well does this strategy work? +% +% It loses every wrong sequence. +% +% It wins every sequence that differs from a wrong sequences by exactly one digit. +% +% It loses every sequence that differs from every wrong sequence by at least two digits (since everyone passes). +% +% So what we want is a collection of wrong sequences that are evenly spread out amongst the possibilities, ie, we want to 'cover' as many possibilites as possible with the fewest number of wrong sequences. +% +% This is actually a problem that real people care about, even some who don't wear hats. This is (roughly) the problem of finding an error correcting code. Sometimes, one computer will be sending another computer information in the form of a sequence of 1s and 0s, and by some fluke % a single digit will get flipped. The goal of error correcting codes is to turn the sequence of 1s and 0s you want to send into a longer sequence, which has the property that the receiving computer can tell if a digit got flipped and repair it. +% +% A silly example is the Tripling Code, where if what I want to do is send you 011, I instead send you 011011011 (we always agree on what code we are using ahead of time). Now, if one digit gets flipped, you will see two of the three copies of the sequence agreeing and one differing, and you will know what I was trying to say. However, this is a wildly inefficient code, since it takes three times as long to say anything. +% +% What does an error-correcting code look like? Well, we agree ahead of time upon which possible sequences are the codewords (ie, the ones that are correct), and how to turn them into the messages we really wanted to send. Then, if you get something that differs from a codeword by % exactly one digit, you know how to correct it (this is assuming that the codewords are far enough apart that there is only one close one). So the goal for making an efficient code is to pick codewords spread apart evenly enough that as many possible sequences are exactly one away % from a codeword. This is exactly what we were looking for with our 'wrong sequences', even though the names were different. +% +% Therefore, we can invoke some fancy error-correcting codes to find the optimal hat guessing strategy. In particular, if the number of people/length of sequence is 2^n-1, there is a 'perfect code' called the Hamming code, which will give us a choice of wrong sequences such that every possibility is either 1) a wrong sequence, or 2) exactly 1 digit away from a wrong sequence. Hence, this is best possible strategy for hat guessing. I am not going into the details of the Hamming codes, since the important thing here is that they exist. +% +% However, this only solves the problem for a very specific number of people. What about other numbers? Theres a complication in these cases, in that its impossible to have a perfect code. That is, it is impossible to choose wrong sequences so that every possible sequence is either wrong, or one digit away from exactly one wrong sequence. +% +% We can ask what the nearest possibility to a perfect code is, but its not clear which way to be less than perfect is optimal: +% +% 1) Having some of the correct guesses overlap, that is, having some wrong sequences differ by 2 digits. +% +% 2) Having some sequences which are lost because everyone passes. +% +% 3) Most significantly, moving away from the 'wrong sequence' strategy. +% +% The last one, which I would guess is the correct way to proceed, is bad because the tools from computer science become useless rapidly. I really have no idea what the optimal solution looks like here. \ No newline at end of file diff --git a/Advanced/Error-Correcting Codes/qr.png b/Advanced/Error-Correcting Codes/qr.png new file mode 100644 index 0000000000000000000000000000000000000000..195d3e3e0e58749bba346ac71ab189b24c57fc78 GIT binary patch literal 90906 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 b}d~V{>!TX9P=Evgz*di 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 Date: Thu, 12 Jan 2023 09:41:51 -0800 Subject: [PATCH 07/11] Fixed old boxlinehack command --- Advanced/Euler's Number/main.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Advanced/Euler's Number/main.tex b/Advanced/Euler's Number/main.tex index d2bb369..bdc0266 100755 --- a/Advanced/Euler's Number/main.tex +++ b/Advanced/Euler's Number/main.tex @@ -115,7 +115,7 @@ We know that for any $\epsilon$, $\exists p$ so that $\frac{1}{p} = \epsilon$. This is the \textit{Archemedian Property}. \\ It is now clear that $\lim_{n\to\infty}a_n = 0$ - \boxlinehack + \linehack{} $\lim_{n\to\infty}a_n = \pi$ means that $\forall \epsilon > 0$, $\exists N \in \mathbb{N}$ so that $|a_n - \pi| < \epsilon\ \forall n < N$. \\ @@ -149,7 +149,7 @@ Therefore, if both $A$ and $B$ are limits of $[a_n]$, $A$ and $B$ must be equal. - \boxlinehack + \linehack{} \textsuperscript{*}Note that we can also set $\epsilon = \frac{|B-A|}{2}$, which gives $|B-A| < |B-A|$. This is also false, and the proof still works. However, the extra $\frac{\hspace{2em}}{2}$ gives a clearer explanation. From 3ff9ea3c508562cc78825c2fed5a855cf3d4ecaf Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 12 Jan 2023 10:23:48 -0800 Subject: [PATCH 08/11] Metafile cleanup --- .gitignore | 4 ++++ .vscode/settings.json | 17 +---------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 635eeee..aece2e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ # Output files main.pdf +# CI files +/build +/output + # TeX build files *.synctex.gz* *.latexmk diff --git a/.vscode/settings.json b/.vscode/settings.json index 9c49db7..d92fcb1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,18 +1,3 @@ { - "latex-workshop.latex.recipe.default": "latexmk (lualatex)", - "cSpell.words": [ - "Eulerian", - "Gleizer", - "nosolutions", - "Oleg", - "ORMC", - "Pidgeonhole", - "Radko", - "Combinators", - "coprime", - "cryptosystem", - "Fulkerson", - "multivariable", - "pathgroup" - ] + "latex-workshop.latex.recipe.default": "latexmk (lualatex)" } \ No newline at end of file From 5ef1d0f461742779e06d395eeb2300f1a9172fe8 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 12 Jan 2023 10:30:53 -0800 Subject: [PATCH 09/11] Moved tex packages into this repo --- Advanced/Cryptography/main.tex | 4 +- Advanced/Error-Correcting Codes/main.tex | 4 +- Advanced/Euler's Number/main.tex | 4 +- Advanced/Graph Algorithms/main.tex | 4 +- Advanced/Lambda Calculus/main.tex | 5 +- Advanced/Pidgeonhole Problems/main.tex | 4 +- .../An Introduction to Graph Theory/main.tex | 7 +- Intermediate/Combinatorics/main.tex | 4 +- Intermediate/Instant Insanity/main.tex | 4 +- Intermediate/Newton's Laws/main.tex | 6 +- Intermediate/Probability/main.tex | 4 +- Intermediate/Slide Rules/main.tex | 4 +- Intermediate/Slide Rules/sliderule.sty | 534 ++++++++++++++++++ Intermediate/Vectors 1/main.tex | 4 +- Intermediate/Vectors 2/main.tex | 4 +- Misc/Moscow Puzzles/main.tex | 4 +- Misc/Warm-Ups/electician.tex | 4 +- Misc/Warm-Ups/raid.tex | 4 +- README.md | 30 +- resources/ormc_handout.cls | 441 +++++++++++++++ 20 files changed, 1022 insertions(+), 57 deletions(-) create mode 100755 Intermediate/Slide Rules/sliderule.sty create mode 100644 resources/ormc_handout.cls diff --git a/Advanced/Cryptography/main.tex b/Advanced/Cryptography/main.tex index 6f3652c..8e9f7d6 100755 --- a/Advanced/Cryptography/main.tex +++ b/Advanced/Cryptography/main.tex @@ -1,11 +1,9 @@ -% https://git.betalupi.com/Mark/latex % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ solutions, singlenumbering -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{amsmath} \usepackage{amssymb} diff --git a/Advanced/Error-Correcting Codes/main.tex b/Advanced/Error-Correcting Codes/main.tex index 8960bf5..ad0e8c7 100755 --- a/Advanced/Error-Correcting Codes/main.tex +++ b/Advanced/Error-Correcting Codes/main.tex @@ -1,10 +1,8 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ solutions -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{tikz} diff --git a/Advanced/Euler's Number/main.tex b/Advanced/Euler's Number/main.tex index bdc0266..e42de35 100755 --- a/Advanced/Euler's Number/main.tex +++ b/Advanced/Euler's Number/main.tex @@ -1,11 +1,9 @@ -% https://git.betalupi.com/Mark/latex % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ singlenumbering, nosolutions -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{amsmath} \usepackage{amssymb} diff --git a/Advanced/Graph Algorithms/main.tex b/Advanced/Graph Algorithms/main.tex index bdf9a5b..bd47eb0 100755 --- a/Advanced/Graph Algorithms/main.tex +++ b/Advanced/Graph Algorithms/main.tex @@ -1,10 +1,8 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ solutions -]{ormc_handout} +]{../../resources/ormc_handout} \input{tikxset} diff --git a/Advanced/Lambda Calculus/main.tex b/Advanced/Lambda Calculus/main.tex index 7346b39..5f5ed22 100755 --- a/Advanced/Lambda Calculus/main.tex +++ b/Advanced/Lambda Calculus/main.tex @@ -1,12 +1,9 @@ -% https://git.betalupi.com/Mark/latex % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 - \documentclass[ solutions, singlenumbering -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{url} \usepackage{mathtools} % for \coloneqq diff --git a/Advanced/Pidgeonhole Problems/main.tex b/Advanced/Pidgeonhole Problems/main.tex index 2d2eef6..0a2edfe 100755 --- a/Advanced/Pidgeonhole Problems/main.tex +++ b/Advanced/Pidgeonhole Problems/main.tex @@ -1,10 +1,8 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ solutions -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{amsmath} \usepackage{amssymb} diff --git a/Intermediate/An Introduction to Graph Theory/main.tex b/Intermediate/An Introduction to Graph Theory/main.tex index 4bb689f..2926de6 100755 --- a/Intermediate/An Introduction to Graph Theory/main.tex +++ b/Intermediate/An Introduction to Graph Theory/main.tex @@ -1,11 +1,8 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.0.6 \documentclass[ - solutions, - simplefooter -]{ormc_handout} + solutions +]{../../resources/ormc_handout} \usepackage{tkz-graph} diff --git a/Intermediate/Combinatorics/main.tex b/Intermediate/Combinatorics/main.tex index 41df0fd..06ba540 100755 --- a/Intermediate/Combinatorics/main.tex +++ b/Intermediate/Combinatorics/main.tex @@ -1,8 +1,6 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 -\documentclass[solutions]{ormc_handout} +\documentclass[solutions]{../../resources/ormc_handout} \newcommand{\nck}[2] { \ensuremath{ diff --git a/Intermediate/Instant Insanity/main.tex b/Intermediate/Instant Insanity/main.tex index 716d0db..d74a262 100755 --- a/Intermediate/Instant Insanity/main.tex +++ b/Intermediate/Instant Insanity/main.tex @@ -1,10 +1,8 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ solutions -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{tkz-graph} diff --git a/Intermediate/Newton's Laws/main.tex b/Intermediate/Newton's Laws/main.tex index 0d8c59f..18de8a0 100755 --- a/Intermediate/Newton's Laws/main.tex +++ b/Intermediate/Newton's Laws/main.tex @@ -1,8 +1,8 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.0.6 -\documentclass[solutions, simplefooter]{ormc_handout} +\documentclass[ + solutions +]{../../resources/ormc_handout} \begin{document} diff --git a/Intermediate/Probability/main.tex b/Intermediate/Probability/main.tex index b0702c8..91e594c 100755 --- a/Intermediate/Probability/main.tex +++ b/Intermediate/Probability/main.tex @@ -1,8 +1,6 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 -\documentclass[solutions]{ormc_handout} +\documentclass[solutions]{../../resources/ormc_handout} % Quick P() macro. diff --git a/Intermediate/Slide Rules/main.tex b/Intermediate/Slide Rules/main.tex index 60a1016..8838305 100755 --- a/Intermediate/Slide Rules/main.tex +++ b/Intermediate/Slide Rules/main.tex @@ -1,10 +1,8 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ solutions -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{pdfpages} \usepackage{sliderule} diff --git a/Intermediate/Slide Rules/sliderule.sty b/Intermediate/Slide Rules/sliderule.sty new file mode 100755 index 0000000..13e3995 --- /dev/null +++ b/Intermediate/Slide Rules/sliderule.sty @@ -0,0 +1,534 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{sliderule}[2022/08/22 Slide rule tools] + +\RequirePackage{tikz} +\RequirePackage{ifthen} + + +% Scale functions: +% See https://sliderulemuseum.com/SR_Scales.htm +% +% l: length of the rule +% n: the number on the rule +% +% A/B: (l/2) * log(n) +% C/D: l / log(n) +% CI: abs(l * log(10 / n) - l) +% K: (l/3) * log(n) +% +% L: n * l +% T: l * log(10 * tan(n)) +% S: l * log(10 * sin(n)) + +\def\sliderulewidth{10} + +\def\abscalefn(#1){(\sliderulewidth/2) * log10(#1)} +\def\cdscalefn(#1){(\sliderulewidth * log10(#1))} +\def\ciscalefn(#1){(\sliderulewidth - \cdscalefn(#1))} +\def\kscalefn(#1){(\sliderulewidth/3) * log10(#1)} +\def\lscalefn(#1){(\sliderulewidth * #1)} +\def\tscalefn(#1){(\sliderulewidth * log10(10 * tan(#1)))} +\def\sscalefn(#1){(\sliderulewidth * log10(10 * sin(#1)))} + + +% Arguments: +% Label +% x of start +% y of start +\newcommand{\linearscale}[3]{ + \draw[black] ({#1}, #2) -- ({#1 + \sliderulewidth}, #2); + \draw[black] ({#1}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.9); + \draw[black] ({#1}, #2 + 0.9) -- ({#1}, #2 + 0.7); + \draw[black] ({#1 + \sliderulewidth}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.7); + + \draw ({#1 - 0.1}, #2 + 0.5) node[left] {#3}; + + % Numbers and marks + \foreach \i in {0,..., 10}{ + \draw[black] + ({#1 + (\sliderulewidth / 10) * \i}, #2) -- + ({#1 + (\sliderulewidth / 10) * \i}, #2 + 0.3) + node[above] {\i}; + } + + % Submarks + \foreach \n in {0, ..., 9} { + \foreach \i in {1,..., 9} { + \ifthenelse{\i=5}{ + \draw[black] + ({#1 + (\sliderulewidth / 10) * (\n + \i / 10)}, #2) -- + ({#1 + (\sliderulewidth / 10) * (\n + \i / 10)}, #2 + 0.2); + } { + \draw[black] + ({#1 + (\sliderulewidth / 10) * (\n + \i / 10)}, #2) -- + ({#1 + (\sliderulewidth / 10) * (\n + \i / 10)}, #2 + 0.1); + } + } + } +} + + +% Arguments: +% Label +% x of start +% y of start +\newcommand{\abscale}[3]{ + \draw[black] ({#1}, #2) -- ({#1 + \sliderulewidth}, #2); + \draw[black] ({#1}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.9); + \draw[black] ({#1}, #2 + 0.9) -- ({#1}, #2 + 0.7); + \draw[black] ({#1 + \sliderulewidth}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.7); + + + \draw ({#1 - 0.1}, #2 + 0.5) node[left] {#3}; + + % Numbers and marks 1 - 9 + \foreach \i in {1,..., 9}{ + \draw[black] + ({#1 + \abscalefn(\i)}, #2) -- + ({#1 + \abscalefn(\i)}, #2 + 0.3) + node[above] {\i}; + } + % Numbers and marks 10 - 100 + \foreach \i in {1,..., 10}{ + \draw[black] + ({#1 + \abscalefn(10 * \i)}, #2) -- + ({#1 + \abscalefn(10 * \i)}, #2 + 0.3) + node[above] {\ifthenelse{\i=10}{1}{\i}}; + } + + % Submarks 1 - 9 + \foreach \n in {1, ..., 9} { + \ifthenelse{\n<5}{ + \foreach \i in {1,..., 9} + } { + \foreach \i in {2,4,6,8} + } + { + \ifthenelse{\i=5}{ + \draw[black] + ({#1 + \abscalefn(\n + \i / 10)}, #2) -- + ({#1 + \abscalefn(\n + \i / 10)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \abscalefn(\n + \i / 10)}, #2) -- + ({#1 + \abscalefn(\n + \i / 10)}, #2 + 0.1); + } + } + } + + % Submarks 10 - 100 + \foreach \n in {10,20,...,90} { + \ifthenelse{\n<50}{ + \foreach \i in {1,..., 9} + } { + \foreach \i in {2,4,6,8} + } + { + \ifthenelse{\i=5}{ + \draw[black] + ({#1 + \abscalefn(\n + \i)}, #2) -- + ({#1 + \abscalefn(\n + \i)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \abscalefn(\n + \i)}, #2) -- + ({#1 + \abscalefn(\n + \i)}, #2 + 0.1); + } + } + } +} + +\newcommand{\cdscale}[3]{ + \draw[black] ({#1}, #2) -- ({#1 + \sliderulewidth}, #2); + \draw[black] ({#1}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.9); + \draw[black] ({#1}, #2 + 0.9) -- ({#1}, #2 + 0.7); + \draw[black] ({#1 + \sliderulewidth}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.7); + + + \draw ({#1 - 0.1}, #2 + 0.5) node[left] {#3}; + + % Numbers and marks 1 - 10 + \foreach \i in {1,..., 10}{ + \draw[black] + ({#1 + \cdscalefn(\i)}, #2) -- + ({#1 + \cdscalefn(\i)}, #2 + 0.3) + node[above] {\ifthenelse{\i=10}{1}{\i}}; + } + + % Submarks 1 - 9 + \foreach \n in {1, ..., 9} { + \ifthenelse{\n<3}{ + \foreach \i in {5,10,...,95} + } { + \foreach \i in {10,20,...,90} + } + { + \ifthenelse{\i=50}{ + \draw[black] + ({#1 + \cdscalefn(\n + \i / 100)}, #2) -- + ({#1 + \cdscalefn(\n + \i / 100)}, #2 + 0.2); + \ifthenelse{\n=1}{ + \draw + ({#1 + \cdscalefn(\n + \i / 100)}, #2 + 0.2) + node [above] {1.5}; + }{} + } { + \ifthenelse{ + \i=10 \OR \i=20 \OR \i=30 \OR \i=40 \OR + \i=60 \OR \i=70 \OR \i=80 \OR \i=90 + }{ + \draw[black] + ({#1 + \cdscalefn(\n + \i / 100)}, #2) -- + ({#1 + \cdscalefn(\n + \i / 100)}, #2 + 0.15); + } { + \draw[black] + ({#1 + \cdscalefn(\n + \i / 100)}, #2) -- + ({#1 + \cdscalefn(\n + \i / 100)}, #2 + 0.1); + } + } + } + } +} + +\newcommand{\ciscale}[3]{ + \draw[black] ({#1}, #2) -- ({#1 + \sliderulewidth}, #2); + \draw[black] ({#1}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.9); + \draw[black] ({#1}, #2 + 0.9) -- ({#1}, #2 + 0.7); + \draw[black] ({#1 + \sliderulewidth}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.7); + + + \draw ({#1 - 0.1}, #2 + 0.5) node[left] {#3}; + + % Numbers and marks + \foreach \i in {1,...,10}{ + \draw[black] + ({#1 + \ciscalefn(\i)}, #2) -- + ({#1 + \ciscalefn(\i)}, #2 + 0.3) + node[above] {\ifthenelse{\i=10}{1}{\ifthenelse{\i=0}{0}{.\i}}}; + } + + % Submarks 1 - 9 + \foreach \n in {1, ..., 9} { + \ifthenelse{\n<3}{ + \foreach \i in {5,10,...,95} + } { + \foreach \i in {10,20,...,90} + } + { + \ifthenelse{\i=50}{ + \draw[black] + ({#1 + \ciscalefn(\n + \i / 100)}, #2) -- + ({#1 + \ciscalefn(\n + \i / 100)}, #2 + 0.2); + \ifthenelse{\n=1}{ + \draw + ({#1 + \ciscalefn(\n + \i / 100)}, #2 + 0.2) + node [above] {1.5}; + }{} + } { + \ifthenelse{ + \i=10 \OR \i=20 \OR \i=30 \OR \i=40 \OR + \i=60 \OR \i=70 \OR \i=80 \OR \i=90 + }{ + \draw[black] + ({#1 + \ciscalefn(\n + \i / 100)}, #2) -- + ({#1 + \ciscalefn(\n + \i / 100)}, #2 + 0.15); + } { + \draw[black] + ({#1 + \ciscalefn(\n + \i / 100)}, #2) -- + ({#1 + \ciscalefn(\n + \i / 100)}, #2 + 0.1); + } + } + } + } +} + +\newcommand{\kscale}[3]{ + \draw[black] ({#1}, #2) -- ({#1 + \sliderulewidth}, #2); + \draw[black] ({#1}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.9); + \draw[black] ({#1}, #2 + 0.9) -- ({#1}, #2 + 0.7); + \draw[black] ({#1 + \sliderulewidth}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.7); + + + \draw ({#1 - 0.1}, #2 + 0.5) node[left] {#3}; + + % Numbers and marks 1 - 9 + \foreach \i in {1,...,9}{ + \draw[black] + ({#1 + \kscalefn(\i)}, #2) -- + ({#1 + \kscalefn(\i)}, #2 + 0.3) + node[above] {\i}; + } + % Numbers and marks 10 - 90 + \foreach \i in {1,..., 9}{ + \draw[black] + ({#1 + \kscalefn(10 * \i)}, #2) -- + ({#1 + \kscalefn(10 * \i)}, #2 + 0.3) + node[above] {\ifthenelse{\i=10}{1}{\i}}; + } + % Numbers and marks 100 - 1000 + \foreach \i in {1,..., 10}{ + \draw[black] + ({#1 + \kscalefn(100 * \i)}, #2) -- + ({#1 + \kscalefn(100 * \i)}, #2 + 0.3) + node[above] {\ifthenelse{\i=10}{1}{\i}}; + } + + % Submarks 1 - 9 + \foreach \n in {1, ..., 9} { + \ifthenelse{\n<4}{ + \foreach \i in {1,..., 9} + } { + \foreach \i in {2,4,6,8} + } + { + \ifthenelse{\i=5}{ + \draw[black] + ({#1 + \kscalefn(\n + \i / 10)}, #2) -- + ({#1 + \kscalefn(\n + \i / 10)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \kscalefn(\n + \i / 10)}, #2) -- + ({#1 + \kscalefn(\n + \i / 10)}, #2 + 0.1); + } + } + } + + % Submarks 10 - 90 + \foreach \n in {10,20,...,90} { + \ifthenelse{\n<40}{ + \foreach \i in {1,..., 9} + } { + \foreach \i in {2,4,6,8} + } + { + \ifthenelse{\i=5}{ + \draw[black] + ({#1 + \kscalefn(\n + \i)}, #2) -- + ({#1 + \kscalefn(\n + \i)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \kscalefn(\n + \i)}, #2) -- + ({#1 + \kscalefn(\n + \i)}, #2 + 0.1); + } + } + } + + % Submarks 100 - 1000 + \foreach \n in {100,200,...,900} { + \ifthenelse{\n<400}{ + \foreach \i in {10,20,...,90} + } { + \foreach \i in {20,40,60,80} + } + { + \ifthenelse{\i=50}{ + \draw[black] + ({#1 + \kscalefn(\n + \i)}, #2) -- + ({#1 + \kscalefn(\n + \i)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \kscalefn(\n + \i)}, #2) -- + ({#1 + \kscalefn(\n + \i)}, #2 + 0.1); + } + } + } +} + +\newcommand{\lscale}[3]{ + \draw[black] ({#1}, #2) -- ({#1 + \sliderulewidth}, #2); + \draw[black] ({#1}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.9); + \draw[black] ({#1}, #2 + 0.9) -- ({#1}, #2 + 0.7); + \draw[black] ({#1 + \sliderulewidth}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.7); + + + \draw ({#1 - 0.1}, #2 + 0.5) node[left] {#3}; + + % Numbers and marks + \foreach \i in {0,..., 10}{ + \draw[black] + ({#1 + \lscalefn(\i / 10)}, #2) -- + ({#1 + \lscalefn(\i / 10)}, #2 + 0.3) + node[above] {\ifthenelse{\i=10}{1}{\ifthenelse{\i=0}{0}{.\i}}}; + } + + % Submarks + \foreach \n in {0, ..., 9} { + \foreach \i in {1,...,19} { + \ifthenelse{\i=10}{ + \draw[black] + ({#1 + \lscalefn((\n + (\i / 20))/10)}, #2) -- + ({#1 + \lscalefn((\n + (\i / 20))/10)}, #2 + 0.2); + } { + \ifthenelse{ + \i=1 \OR \i=3 \OR \i=5 \OR \i=7 \OR + \i=9 \OR \i=11 \OR \i=13 \OR \i=15 \OR + \i=17 \OR \i=19 + }{ + \draw[black] + ({#1 + \lscalefn((\n + (\i / 20))/10)}, #2) -- + ({#1 + \lscalefn((\n + (\i / 20))/10)}, #2 + 0.1); + } { + \draw[black] + ({#1 + \lscalefn((\n + (\i / 20))/10)}, #2) -- + ({#1 + \lscalefn((\n + (\i / 20))/10)}, #2 + 0.15); + } + } + } + } +} + +\newcommand{\tscale}[3]{ + \draw[black] ({#1}, #2) -- ({#1 + \sliderulewidth}, #2); + \draw[black] ({#1}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.9); + \draw[black] ({#1}, #2 + 0.9) -- ({#1}, #2 + 0.7); + \draw[black] ({#1 + \sliderulewidth}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.7); + + % First line + \draw[black] ({#1}, #2) -- ({#1}, #2 + 0.2); + + + \draw ({#1 - 0.1}, #2 + 0.5) node[left] {#3}; + + % Numbers and marks 6 - 10 + \foreach \i in {6,...,9,10,15,...,45}{ + \draw[black] + ({#1 + \tscalefn(\i)}, #2) -- + ({#1 + \tscalefn(\i)}, #2 + 0.3) + node[above] {\i}; + } + + % Submarks 6 - 10 + \foreach \n in {6, ..., 9} { + \foreach \i in {1,...,9}{ + \ifthenelse{\i=5}{ + \draw[black] + ({#1 + \tscalefn(\n + \i / 10)}, #2) -- + ({#1 + \tscalefn(\n + \i / 10)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \tscalefn(\n + \i / 10)}, #2) -- + ({#1 + \tscalefn(\n + \i / 10)}, #2 + 0.1); + } + } + } + + % Submarks 15 - 45 + \foreach \n in {10, 15, ..., 40} { + \foreach \i in {1,...,24}{ + \ifthenelse{ + \i=5 \OR \i=10 \OR \i=15 \OR \i=20 + } { + \draw[black] + ({#1 + \tscalefn(\n + \i / 5)}, #2) -- + ({#1 + \tscalefn(\n + \i / 5)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \tscalefn(\n + \i / 5)}, #2) -- + ({#1 + \tscalefn(\n + \i / 5)}, #2 + 0.1); + } + } + } +} + +\newcommand{\sscale}[3]{ + \draw[black] ({#1}, #2) -- ({#1 + \sliderulewidth}, #2); + \draw[black] ({#1}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.9); + \draw[black] ({#1}, #2 + 0.9) -- ({#1}, #2 + 0.7); + \draw[black] ({#1 + \sliderulewidth}, #2 + 0.9) -- ({#1 + \sliderulewidth}, #2 + 0.7); + + % First line + \draw[black] ({#1}, #2) -- ({#1}, #2 + 0.2); + + + \draw ({#1 - 0.1}, #2 + 0.5) node[left] {#3}; + + % Numbers and marks + \foreach \i in {6,...,9,10,15,...,30,40,50,...,60,90}{ + \draw[black] + ({#1 + \sscalefn(\i)}, #2) -- + ({#1 + \sscalefn(\i)}, #2 + 0.3) + node[above] {\i}; + } + + % Submarks 6 - 10 + \foreach \n in {6, ..., 9} { + \foreach \i in {1,...,9}{ + \ifthenelse{\i=5}{ + \draw[black] + ({#1 + \sscalefn(\n + \i / 10)}, #2) -- + ({#1 + \sscalefn(\n + \i / 10)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \sscalefn(\n + \i / 10)}, #2) -- + ({#1 + \sscalefn(\n + \i / 10)}, #2 + 0.1); + } + } + } + + % Submarks 15 - 30 + \foreach \n in {10, 15, ..., 25} { + \foreach \i in {1,...,24}{ + \ifthenelse{ + \i=5 \OR \i=10 \OR \i=15 \OR \i=20 + } { + \draw[black] + ({#1 + \sscalefn(\n + \i / 5)}, #2) -- + ({#1 + \sscalefn(\n + \i / 5)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \sscalefn(\n + \i / 5)}, #2) -- + ({#1 + \sscalefn(\n + \i / 5)}, #2 + 0.1); + } + } + } + + % Submarks 30 + \foreach \n in {30} { + \foreach \i in {1,...,19}{ + \ifthenelse{ + \i=2 \OR \i=4 \OR \i=6 \OR \i=8 \OR + \i=10 \OR \i=12 \OR \i=14 \OR \i=16 \OR + \i=18 + } { + \draw[black] + ({#1 + \sscalefn(\n + \i / 2)}, #2) -- + ({#1 + \sscalefn(\n + \i / 2)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \sscalefn(\n + \i / 2)}, #2) -- + ({#1 + \sscalefn(\n + \i / 2)}, #2 + 0.1); + } + } + } + + % Submarks 40 - 50 + \foreach \n in {40, 50} { + \foreach \i in {1,...,9}{ + \ifthenelse{ + \i=5 \OR \i=10 \OR \i=15 \OR \i=20 + } { + \draw[black] + ({#1 + \sscalefn(\n + \i)}, #2) -- + ({#1 + \sscalefn(\n + \i)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \sscalefn(\n + \i)}, #2) -- + ({#1 + \sscalefn(\n + \i)}, #2 + 0.1); + } + } + } + + % Submarks 60 + \foreach \i in {1,...,10}{ + \ifthenelse{ + \i=5 \OR \i=10 + } { + \draw[black] + ({#1 + \sscalefn(60 + \i * 2)}, #2) -- + ({#1 + \sscalefn(60 + \i * 2)}, #2 + 0.2); + } { + \draw[black] + ({#1 + \sscalefn(60 + \i * 2)}, #2) -- + ({#1 + \sscalefn(60 + \i * 2)}, #2 + 0.1); + } + } +} diff --git a/Intermediate/Vectors 1/main.tex b/Intermediate/Vectors 1/main.tex index 9da6e22..0e0eb70 100755 --- a/Intermediate/Vectors 1/main.tex +++ b/Intermediate/Vectors 1/main.tex @@ -1,8 +1,6 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.0.4 -\documentclass[solutions]{ormc_handout} +\documentclass[solutions]{../../resources/ormc_handout} \usepackage{adjustbox} \begin{document} diff --git a/Intermediate/Vectors 2/main.tex b/Intermediate/Vectors 2/main.tex index f71a28c..be80758 100755 --- a/Intermediate/Vectors 2/main.tex +++ b/Intermediate/Vectors 2/main.tex @@ -1,8 +1,6 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.0.6 -\documentclass[solutions]{ormc_handout} +\documentclass[solutions]{../../resources/ormc_handout} \begin{document} diff --git a/Misc/Moscow Puzzles/main.tex b/Misc/Moscow Puzzles/main.tex index 9587847..1e9911a 100755 --- a/Misc/Moscow Puzzles/main.tex +++ b/Misc/Moscow Puzzles/main.tex @@ -1,10 +1,8 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ solutions -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{subfiles} \usepackage{graphicx} diff --git a/Misc/Warm-Ups/electician.tex b/Misc/Warm-Ups/electician.tex index b2dcb8a..2728546 100755 --- a/Misc/Warm-Ups/electician.tex +++ b/Misc/Warm-Ups/electician.tex @@ -1,12 +1,10 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ nosolutions, singlenumbering, nopagenumber -]{ormc_handout} +]{../../resources/ormc_handout} % We put nodes in a separate layer, so we can % slightly overlap with paths for a perfect fit diff --git a/Misc/Warm-Ups/raid.tex b/Misc/Warm-Ups/raid.tex index c884f59..28187ab 100755 --- a/Misc/Warm-Ups/raid.tex +++ b/Misc/Warm-Ups/raid.tex @@ -1,12 +1,10 @@ -% https://git.betalupi.com/Mark/latex-packages % use [nosolutions] flag to hide solutions. % use [solutions] flag to show solutions. -% Last built with version 1.1.0 \documentclass[ nosolutions, singlenumbering, nopagenumber -]{ormc_handout} +]{../../resources/ormc_handout} \usepackage{tikz} diff --git a/README.md b/README.md index c6ba54e..1c6b9d6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # ORMC Handouts -This repository contains all the handouts I've written for the [ORMC](https://circles.math.ucla.edu/circles/). Most of them are built using [these](https://git.betalupi.com/Mark/latex) packages. - +This repository contains all the handouts I've written for the [ORMC](https://circles.math.ucla.edu/circles/). If you are not affiliated with the ORMC, ask for permission before using these. @@ -11,4 +10,29 @@ Handouts are sorted by the class they're for: - [`./Intermediate`](./Intermediate/): Grades 5 - 9 - [`./Advanced`](./Advanced): Grades 9 - 12 -These grade levels are estimates. \ No newline at end of file +Grade levels are estimates. + +## Usage + +Most handouts use a custom document class. If you move any files out of this repository, you'll need to change a few things for the handout to compile: + 1. Download [`./resources/ormc_handout.cls`](./resources/ormc_handout.cls). + 2. Put it in the same directory as the handout. + 3. Fix the include path at the top of the handout. + + Usually, you'll need to replace + + ```latex + \documentclass[ + solutions + ]{../../resources/ormc_handout} + ``` + + with + + ```latex + \documentclass[ + solutions + ]{ormc_handout} + ``` + +**Warning:** As of now, `ormc_handout.cls` does not work with hyperref. \ No newline at end of file diff --git a/resources/ormc_handout.cls b/resources/ormc_handout.cls new file mode 100644 index 0000000..d630a79 --- /dev/null +++ b/resources/ormc_handout.cls @@ -0,0 +1,441 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{ormc_handout}[2022/05/07 1.1.0 ORMC Handout] + + +% Boolean that determines solution behavior. +% If false, solutions and instructor notes are hidden. +\newif{\ifsolutions} +\solutionstrue + +% Boolean that determines object numbering +% If true, the same counter is used for all objects. +\newif{\ifsinglenumbering} +\singlenumberingfalse + +% Boolean. If true, don't number pages. +\newif{\ifnopagenumber} +\nopagenumberfalse + +% Declare and parse arguments +\DeclareOption{solutions}{\solutionstrue} +\DeclareOption{nosolutions}{\solutionsfalse} +\DeclareOption{singlenumbering}{\singlenumberingtrue} +\DeclareOption{nopagenumber}{\nopagenumbertrue} +\DeclareOption*{\ClassWarning{ormc_handout}{\CurrentOption ignored}} +\ProcessOptions\relax + +% Based on article class +\LoadClass{article} +\makeatletter % Allow commands with @ (\makeatother is at end of this file) + +\newcommand\sbullet[1][.5]{\mathbin{\vcenter{\hbox{\scalebox{#1}{$\bullet$}}}}} + +\renewcommand{\labelitemi}{$\sbullet$} +\renewcommand{\labelitemii}{$\cdot$} + + +% Hack for command-line arguments. +% To force a build with solutions, run +% latexmk +% -synctex=1 +% -interaction=nonstopmode +% -file-line-error +% -outdir=%OUTDIR% +% -xelatex +% -jobname=%DOCFILE%.sol +% -pdfxelatex="xelatex %O \"\\def\\argYesSolutions{1}\\input{%S}\"" +% %DOC% +% +% Or, make a new file with the contents +% \def\argYesSolutions{1}\input{} +% and build that with latex. +\ifdefined\argYesSolutions + \solutionstrue +\else + \ifdefined\argNoSolutions + \solutionsfalse + \fi +\fi + + + + +%%% PACKAGES %%% + + +% Set up page geometry. +% MUST BE DONE FIRST! +\RequirePackage{geometry} +\geometry{ + paper = letterpaper, + top = 25mm, + bottom = 30mm, + left = 30mm, + right = 30mm, + headheight = 75mm, + footskip = 15mm, + headsep = 75mm, +} + +\RequirePackage{enumitem} % list customization +\RequirePackage{xparse} % Provides powerful macros via \NewDocumentCommand +\RequirePackage{xcolor} % For colored text +\RequirePackage{tcolorbox} % For solution boxes +\RequirePackage{tikz} % Used by \boxlinehack +\RequirePackage{comment} % Used to hide solutions +\RequirePackage{fancyhdr} % Header/Footer customization +\RequirePackage{adjustbox} % Used for title + +\RequirePackage[ + left = ``, + right = '', + leftsub = `, + rightsub = ' +]{dirtytalk} + +% Not used by this class, but likely to be used in documents +\RequirePackage{amsmath} +\RequirePackage{amssymb} +\RequirePackage{multicol} +\RequirePackage{subfiles} + + + + + +%%% CONFIG %%% + + +% No paragraph indentation, no list item spacing, +% raggedright layout (hyphenation is excessive). +\setlength{\parindent}{0mm} +\setlist{noitemsep, topsep=0mm} +\raggedright + +% Use symbols instead of numbers for footnotes +\renewcommand*{\thefootnote}{\arabic{footnote}} + +% One space after a period. +\frenchspacing + + +% Fancyhdr setup +\pagestyle{fancy} +\fancyhf{} +\renewcommand{\headrulewidth}{0mm} + +\ifnopagenumber +\else + \fancyfoot[C]{\thepage} +\fi + + + + +%%% COMMANDS %%% + + +% Make a heading. +% Arguments: +% +% First: Top-left text +% Second: Top-right text +% Both are optional, but should only be provided TOGETHER. +% +% Third: Title +% Forth: author +\RenewDocumentCommand{\maketitle}{ d<> d<> m m } { + \begin{adjustbox}{minipage=0.7\textwidth, margin=0pt \smallskipamount,center} + \begin{center} + + \IfNoValueF{#1}{\textsc{#1}} \hfill \IfNoValueF{#2}{\textsc{#2}} \\ + \rule{\linewidth}{0.2mm}\\ + + \huge + #3 \\ + \normalsize + \vspace{1ex} + #4 + \rule{\linewidth}{0.2mm} \\ + + % Instructor's handout warning + \ifsolutions + \begin{tcolorbox}[ + colback=white, + colframe=red + ] + \begin{center} + \large + \textcolor{red}{ + \textbf{Instructor's Handout} + } \\ + \normalsize + \end{center} + + \vspace{1ex} + + \textcolor{red}{This file contains solutions and notes.} + + \textcolor{red}{Compile with the ``nosolutions'' flag before distributing.} + \end{tcolorbox} + \fi + + \end{center} + \end{adjustbox} +} + + +% Helper command that creates a label with custom text. +% First arg: label name +% Second arg: custom text +\newcommand{\customlabel}[2]{% + \protected@write \@auxout {}{ + \string \newlabel {#1}{{#2}{}} + } +} + + +% Commands for problems, theorems, and definitions +% +% Each of these take two arguments. For example: +% +% \problem{} makes an unnamed problem +% \problem{Division} makes a named problem +% \problem{} +% makes a problem and a label "problem:gcd" +% that gives text "Problem X" when referenced. + +\newcounter{section_counter} +\newcounter{problempartcounter} + +\ifsinglenumbering + \newcounter{object_counter} + + \def\problemcounter{object_counter} + \def\theoremcounter{object_counter} + \def\definitioncounter{object_counter} + \def\examplecounter{object_counter} + \def\propositioncounter{object_counter} +\else + \newcounter{problem_counter} + \newcounter{theorem_counter} + \newcounter{definition_counter} + \newcounter{example_counter} + \newcounter{proposition_counter} + + \def\problemcounter{problem_counter} + \def\theoremcounter{theorem_counter} + \def\definitioncounter{definition_counter} + \def\examplecounter{example_counter} + \def\propositioncounter{proposition_counter} +\fi + + +% Generic object command. +% First arg: counter name (mandatory) +% Second arg: object type (optional) +% Third arg: object title (mandatory, can be empty) +% +% If the second argument is ommited, the counter is hidden +% and only the object title is shown. For example: +% \@object{counter}[Problem]{Example Problem} -> Problem 1: Example Problem +% \@object{counter}{Example Problem} -> Example Problem +% +% Only used internally (See following definitions) +\NewDocumentCommand{\@object}{ m d[] m}{ + \stepcounter{#1} + \vspace{3mm} + \IfNoValueTF{#2} { + {\bf\normalsize #3} + } { + {\bf\normalsize #2 \arabic{#1}:\IfNoValueF{#3}{ #3}} + } +} + +% Generic object. +% Does the same thing as \problem, \theorem, etc, but with no counter. +\NewDocumentCommand{\generic}{ m d<> }{ + \vspace{3mm} + {\bf\normalsize #1} \\* + + \IfNoValueF{#2}{ + \customlabel{#2}{#1} + } +} + +% If not starred, text is "Part X: " +% If starred, text is "<title>" +\RenewDocumentCommand{\section}{ s m d<> }{ + \stepcounter{section_counter} + \vspace{8mm} + \IfBooleanTF{#1}{ + {\bf\Large \hfill #2 \hfill} + \IfNoValueF{#3}{\customlabel{#3}#2} \\* + } { + {\bf\Large \hfill Part \arabic{section_counter}\IfNoValueF{#2}{: #2} \hfill} + \IfNoValueF{#3}{\customlabel{#3}Part \arabic{section_counter}} \\* + } + \vspace{2mm} +} + + +\RenewDocumentCommand{\paragraph}{}{ + \hspace{1cm} +} + +\NewDocumentCommand{\problem}{ m d<> }{ + \setcounter{problempartcounter}{0} + + \@object{\problemcounter}[Problem]{#1} + \IfNoValueF{#2}{ + \customlabel{#2}{Problem \arabic{\problemcounter}} + \customlabel{NUM:#2}{\arabic{\problemcounter}} + } \\* +} + +\NewDocumentCommand{\problempart}{ m d<> }{ + \@object{problempartcounter}[Part]{#1} + \IfNoValueF{#2}{ + \customlabel + {#2} + {Problem \arabic{\problemcounter}\alph{problempartcounter}} + \customlabel{NUM:#2}{\arabic{\problemcounter}\alph{problempartcounter}} + } \\* +} + +\NewDocumentCommand{\definition}{ m d<> }{ + \@object{\definitioncounter}[Definition]{#1} + \IfNoValueF{#2}{ + \customlabel{#2}{Definition \arabic{\definitioncounter}} + \customlabel{NUM:#2}{\arabic{\definitioncounter}} + } \\* +} + +\NewDocumentCommand{\theorem}{ m d<> }{ + \@object{\theoremcounter}[Theorem]{#1} + \IfNoValueF{#2}{ + \customlabel{#2}{Theorem \arabic{\theoremcounter}} + \customlabel{NUM:#2}{\arabic{\theoremcounter}} + } \\* +} + +\NewDocumentCommand{\proposition}{ m d<> }{ + \@object{\propositioncounter}[Proposition]{#1} + \IfNoValueF{#2}{ + \customlabel{#2}{Proposition \arabic{\propositioncounter}} + \customlabel{NUM:#2}{\arabic{\propositioncounter}} + } \\* +} + +\NewDocumentCommand{\example}{ m d<> }{ + \@object{\examplecounter}[Example]{#1} + \IfNoValueF{#2}{ + \customlabel{#2}{Example \arabic{\examplecounter}} + \customlabel{NUM:#2}{\arabic{\examplecounter}} + } \\* +} + + +% Solution environment. +% examplesolution environment is always shown (useful for example problems) +% solution environments do the same thing, but are hidden when the [nosolutions] flag is passed. +\newenvironment{examplesolution} { + \begin{tcolorbox}[ + colback=white, + colframe=gray!75!black, + title={\textbf{Example Solution}} + ] +}{ + \end{tcolorbox} +} + +\def\ORMCbgcolor{white} + +% \if isn't parsed inside of LaTeX environents, +% so we have to use the comment package. +\newenvironment{@shown_solution} { + \def\ORMCbgcolor{red!5!white} + \begin{tcolorbox}[ + colback=red!5!white, + colframe=red!75!black, + title={\textbf{Solution}} + ] + \raggedright +}{ + \end{tcolorbox} +} + +\newenvironment{@shown_note} { + \def\ORMCbgcolor{cyan!5!white} + \begin{tcolorbox}[ + colback=cyan!5!white, + colframe=cyan!75!black, + title={\textbf{Note for Instructors}} + ] + \raggedright +}{ + \end{tcolorbox} +} + +% tcolorbox only give us two sections. +% This macro makes a macro \linehack that draws +% lines across a tcolorbox. +% +% Inside every environment that needs a +% \linehack macro, put \@makelinehack{color}. +\newcommand{\@makelinehack}[1]{ + \newcommand{\linehack}{ + \begin{tikzpicture} + \path[use as bounding box] + (0, 0) + -- + (\linewidth, 0); + + \draw[ + color=#1, + dashed, + dash phase=1mm + ] + ( + 0 - \kvtcb@leftlower-\kvtcb@boxsep, + 0 + ) -- ( + \linewidth + \kvtcb@rightlower + \kvtcb@boxsep, + 0 + ); + \end{tikzpicture} \\ + } +} + +\ifsolutions + \newenvironment{solution}{ + \@makelinehack{red!75!black} + \begin{@shown_solution} + } { + \end{@shown_solution} + } + \newenvironment{instructornote}{ + \@makelinehack{cyan!75!black} + \begin{@shown_note} + } { + \end{@shown_note} + } +\else + \excludecomment{solution} + \excludecomment{instructornote} +\fi + + +\NewDocumentCommand{\note}{ d<> m }{ + \IfNoValueTF{#1} { + \textcolor{gray}{#2} \\ + } { + \textcolor{gray}{\textit{#1:} #2} \\ + } +} + +\NewDocumentCommand{\hint}{ m }{ + \note<Hint>{#1} +} + +\makeatother From 7e2ebc4fc709c070915558476e296deb5c2b3490 Mon Sep 17 00:00:00 2001 From: Mark <mark@betalupi.com> Date: Thu, 12 Jan 2023 10:50:24 -0800 Subject: [PATCH 10/11] Updated .gitignore --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index aece2e0..473f474 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,8 @@ main.pdf # CI files -/build -/output +/_build +/_output # TeX build files *.synctex.gz* From 513bac6f54399ea19cb8a6edf6bf7d812c90ca26 Mon Sep 17 00:00:00 2001 From: Mark <mark@betalupi.com> Date: Thu, 12 Jan 2023 18:56:54 -0800 Subject: [PATCH 11/11] Cleaned up RAID handout --- Misc/Warm-Ups/raid.tex | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Misc/Warm-Ups/raid.tex b/Misc/Warm-Ups/raid.tex index 28187ab..a555896 100755 --- a/Misc/Warm-Ups/raid.tex +++ b/Misc/Warm-Ups/raid.tex @@ -66,7 +66,7 @@ \problem{} Suppose we have two hard drives. How can we arrange our data so that... \begin{enumerate} - \item We can store 1 TiB of data + \item We get 1 TiB of usable storage \item We lose no data if any one drive fails \end{enumerate} @@ -75,7 +75,7 @@ \problem{} Suppose we have three hard drives. How can we arrange our data so that... \begin{enumerate} - \item We can store 2 TiB of data + \item We get 2 TiB of usable storage \item We lose no data if any one drive fails \end{enumerate} @@ -84,14 +84,15 @@ \problem{} Suppose we have five hard drives. How can we arrange our data so that... \begin{enumerate} - \item We can store 3 TiB of data + \item We get 3 TiB of usable storage \item We lose no data if any two drives fail \end{enumerate} \vfill \problem{} - Can you write a general solution to this problem? + Write a general solution to this problem, using $n$ drives and providing $s$ TiB of storage. \\ + How many failures will such an array be able to tolerate? \vfill \end{document} \ No newline at end of file