diff --git a/20231123/hp-20231123.pdf b/20231123/hp-20231123.pdf
index 44bf8dfc4de090990e3d4061099d2bb3a366ec7f..a9875318c61eedb0a03d50cbe6ec40a21a25e20a 100644
Binary files a/20231123/hp-20231123.pdf and b/20231123/hp-20231123.pdf differ
diff --git a/20231123/hp-20231123.tex b/20231123/hp-20231123.tex
index eda7fca5dcfed48f0854d68b34d6d1fd01c45ed8..abcaac6d80172739a5cba19e311644614a829824 100644
--- a/20231123/hp-20231123.tex
+++ b/20231123/hp-20231123.tex
@@ -551,6 +551,7 @@
 
   \begin{picture}(0,0)
     \put(8,-6.5){\includegraphics{pendulum.pdf}}
+    \put(5,-1.5){\rotatebox{10}{\color{red}\bf\textarrow\ nächste Woche}}
   \end{picture}
 
   \begin{eqnarray*}
diff --git a/20231123/hp-musterloesung-20231123.pdf b/20231123/hp-musterloesung-20231123.pdf
index 1782abc389d59c3de4999c95356c99baf45cd738..5a40d75a038f32e91e57df6c59f75740d7562454 100644
Binary files a/20231123/hp-musterloesung-20231123.pdf and b/20231123/hp-musterloesung-20231123.pdf differ
diff --git a/20231123/hp-musterloesung-20231123.tex b/20231123/hp-musterloesung-20231123.tex
index 810480f0f431e547c1f4cc9f472b1337f2598e0b..08bc1dbcf1f13936a99768deae1f2bec54828b66 100644
--- a/20231123/hp-musterloesung-20231123.tex
+++ b/20231123/hp-musterloesung-20231123.tex
@@ -1,4 +1,4 @@
-% hp-musterloesung-20231116.pdf - Solutions to the Exercises on Low-Level Programming / Applied Computer Sciences
+% hp-musterloesung-20231123.pdf - Solutions to the Exercises on Low-Level Programming / Applied Computer Sciences
 % Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023  Peter Gerwinski
 %
 % This document is free software: you can redistribute it and/or
@@ -30,7 +30,7 @@
 \begin{document}
 
   \section*{Hardwarenahe Programmierung\\
-            Musterlösung zu den Übungsaufgaben -- 16.\ November 2023}
+            Musterlösung zu den Übungsaufgaben -- 23.\ November 2023}
 
   \exercise{Kondensator}
 
diff --git a/20231130/Tower_of_Hanoi.jpeg b/20231130/Tower_of_Hanoi.jpeg
new file mode 120000
index 0000000000000000000000000000000000000000..a1a794afda08596ffa2f46f278db53455de25b6c
--- /dev/null
+++ b/20231130/Tower_of_Hanoi.jpeg
@@ -0,0 +1 @@
+../common/Tower_of_Hanoi.jpeg
\ No newline at end of file
diff --git a/20231130/aufgabe-1.c b/20231130/aufgabe-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..ac63ca250c79fd76c26f4045ece703407024a4ce
--- /dev/null
+++ b/20231130/aufgabe-1.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+/* ... */
+
+int main (void)
+{
+  pbm_open (14, 14, "test.pbm");
+  pbm_line ("              ");
+  pbm_line ("    XXXXXX    ");
+  pbm_line ("   X      X   ");
+  pbm_line ("  X        X  ");
+  pbm_line (" X          X ");
+  pbm_line (" X  XX  XX  X ");
+  pbm_line (" X   X   X  X ");
+  pbm_line (" X          X ");
+  pbm_line (" X X      X X ");
+  pbm_line (" X  X    X  X ");
+  pbm_line ("  X  XXXX  X  ");
+  pbm_line ("   X      X   ");
+  pbm_line ("    XXXXXX    ");
+  pbm_line ("              ");
+  pbm_close ();
+  return 0;
+}
diff --git a/20231130/aufgabe-1.pbm b/20231130/aufgabe-1.pbm
new file mode 100644
index 0000000000000000000000000000000000000000..bc5b70b1ad6f7236ec9469afac311f05fb056946
Binary files /dev/null and b/20231130/aufgabe-1.pbm differ
diff --git a/20231130/aufgabe-1.png b/20231130/aufgabe-1.png
new file mode 100644
index 0000000000000000000000000000000000000000..e655af0096cc6e50da81c8f820395dfaed27277f
Binary files /dev/null and b/20231130/aufgabe-1.png differ
diff --git a/20231130/aufgabe-2.c b/20231130/aufgabe-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..abbf364a3db17611e41d086591826e98a8a3672b
--- /dev/null
+++ b/20231130/aufgabe-2.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+int fak (int n)
+{
+  if (n <= 0)
+    return 1;
+  else
+    return n * fak (n - 1);
+}
+
+int main (void)
+{
+  for (int n = 0; n <= 5; n++)
+    printf ("%d\n", fak (n));
+  return 0;
+}
diff --git a/20231130/aufgabe-3.c b/20231130/aufgabe-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..15c90561b94d5a0c1a136f0e6479d3633dc242b1
--- /dev/null
+++ b/20231130/aufgabe-3.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <string.h>
+
+void insert_into_string (char src, char *target, int pos)
+{
+  int len = strlen (target);
+  for (int i = pos; i < len; i++)
+    target[i + 1] = target[i];
+  target[pos] = src;
+}
+
+int main (void)
+{
+  char test[100] = "Hochshule Bochum";
+  insert_into_string ('c', test, 5);
+  printf ("%s\n", test);
+  return 0;
+}
diff --git a/20231130/hp-20231130.pdf b/20231130/hp-20231130.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..66a0a71f6fe530d0c1e6581494b379a7654070ad
Binary files /dev/null and b/20231130/hp-20231130.pdf differ
diff --git a/20231130/hp-20231130.tex b/20231130/hp-20231130.tex
new file mode 100644
index 0000000000000000000000000000000000000000..c878d5d163e8a26275d773eab12032d163964ddf
--- /dev/null
+++ b/20231130/hp-20231130.tex
@@ -0,0 +1,595 @@
+% hp-20231130.pdf - Lecture Slides on Low-Level Programming
+% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: Algorithmen: Rekursion, Aufwandsabschätzungen
+
+\documentclass[10pt,t]{beamer}
+
+\usepackage{pgslides}
+\usepackage{tikz}
+
+\newcommand{\redurl}[1]{\href{#1}{\color{red}\nolinkurl{#1}}}
+
+\title{Hardwarenahe Programmierung}
+\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski}
+\date{30.\ November 2023}
+
+\begin{document}
+
+\maketitleframe
+
+\title{Hardwarenahe Programmierung}
+
+\nosectionnonumber{\inserttitle}
+
+\begin{frame}
+
+  \shownosectionnonumber
+
+  \begin{itemize}
+    \item[\textbf{1}] \textbf{Einführung}
+      \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
+    \item[\textbf{2}] \textbf{Einführung in C}
+    \item[\textbf{3}] \textbf{Bibliotheken}
+    \item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
+      \begin{itemize}
+        \vspace*{-\smallskipamount}
+        \item[\dots]
+        \color{medgreen}
+        \item[4.7] Binärdarstellung von Gleitkommazahlen
+        \item[4.8] Speicherausrichtung -- Alignment
+      \end{itemize}
+    \item[\textbf{5}] \textbf{Algorithmen}
+      \begin{itemize}
+        \color{orange}
+        \item[5.1] Differentialgleichungen
+        \color{red}
+        \item[5.2] Rekursion
+        \item[5.3] Aufwandsabschätzungen
+      \end{itemize}
+    \item[\textbf{6}] \textbf{Objektorientierte Programmierung}
+    \item[\textbf{7}] \textbf{Datenstrukturen}
+  \end{itemize}
+
+\end{frame}
+
+\setcounter{section}{3}
+\section{Hardwarenahe Programmierung}
+\setcounter{subsection}{6}
+\subsection{Binärdarstellung von Gleitkommazahlen}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+%  (Diese Seite wurde unbewußt leer gelassen.)
+
+  Beispiel für Gleitkommazahl: $2{,}351\cdot10^5$ (oder: $2.351\times10^5$)
+
+  \smallskip
+
+  Bezeichnungen: $\text{Mantisse} \cdot 10^{\text{Exponent}}$
+
+  \smallskip
+
+  C-Schreibweise: \lstinline{2.351e5} (oder: \lstinline{2.351E5})
+
+%  \pause
+  \bigskip
+
+  Wie speichert man Gleitkommazahlen?
+
+  \smallskip
+
+  $m$-Bit-Zahl, davon
+  \begin{itemize}
+    \item
+      $e$ Bits für den Exponenten (einschließlich Vorzeichen),
+    \item
+      $1$ Bit für das Vorzeichen der Mantisse,
+    \item
+      $m - e - 1$ Bits für die Mantisse.
+  \end{itemize}
+
+%  \pause
+  \begin{picture}(0,0)
+    \color{red}
+    \put(1.95,0.65){\makebox(0,0){\tikz{\draw(0,0)--(0.5,0.25);}}}
+    \put(1.95,0.65){\makebox(0,0){\tikz{\draw(0,0.25)--(0.5,0);}}}
+  \end{picture}%
+  {\color{red}Trick: Mantisse als \newterm{normalisierte Zahl\/} abspeichern}
+
+%  \pause
+  \bigskip
+  Vorteil gegenüber ganzen Zahlen:\\
+  größerer Wertebereich bei vergleichbarem Speicherplatzbedarf
+
+  \medskip
+
+  Nachteil gegenüber ganzen Zahlen: Rundungsfehler\\
+  \textcolor{red}{\textarrow\
+  \textbf{ungeeignet} für Anwendungen, bei denen es auf jedes Bit ankommt\\
+  \phantom{\textarrow\ }(z.\,B.\ Verschlüsselung)}
+  \vspace*{-1cm}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Problem beim Arbeiten mit Gleitkommazahlen: Auslöschung von Ziffern
+  \begin{itemize}
+    \item
+      Zahlen aufsummieren:\\
+      vorher sortieren, mit der kleinsten Zahl beginnen
+%    \pause
+    \item
+      Ableitungen bilden:\\
+      Beim Bilden von Differenzquotienten\\
+      verliert man notwendigerweise an Präzision!\\
+      \textarrow\ Die Differenzen sehr sorgfältig auswählen.\\
+      \textarrow\ Am besten gar nicht ableiten, sondern integrieren.\\
+%      \pause
+      (Trick: Ableiten über Fourier-Transformationen)
+  \end{itemize}
+
+\end{frame}
+
+\subsection{Speicherausrichtung -- Alignment}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \begin{lstlisting}
+    #include <stdint.h>
+
+    uint8_t a;
+    uint16_t b;
+    uint8_t c;
+  \end{lstlisting}
+
+%  \pause
+  \bigskip
+
+  Speicheradresse durch 2 teilbar -- "`16-Bit-Alignment"'
+  \begin{itemize}
+    \item
+      2-Byte-Operation: effizienter
+%    \pause
+    \item
+      \dots\ oder sogar nur dann erlaubt
+%    \pause
+    \arrowitem
+      Compiler optimiert Speicherausrichtung
+  \end{itemize}
+
+  \medskip
+
+%  \pause
+  \begin{minipage}{3cm}
+    \begin{lstlisting}[gobble=6]
+      ¡uint8_t a;
+      uint8_t dummy;
+      uint16_t b;
+      uint8_t c;¿
+    \end{lstlisting}
+  \end{minipage}
+%  \pause
+  \begin{minipage}{3cm}
+    \begin{lstlisting}[gobble=6]
+      ¡uint8_t a;
+      uint8_t c;
+      uint16_t b;¿
+    \end{lstlisting}
+  \end{minipage}
+
+%  \pause
+  \vspace{-1.75cm}
+  \strut\hfill
+  \begin{minipage}{6.5cm}
+    Fazit:
+    \begin{itemize}
+      \item
+        \textbf{Adressen von Variablen\\
+        sind systemabhängig}
+      \item
+        Bei Definition von Datenformaten\\
+        Alignment beachten \textarrow\ effizienter
+    \end{itemize}
+  \end{minipage}
+
+\end{frame}
+
+\section{Algorithmen}
+\subsection{Differentialgleichungen}
+
+\begin{frame}[fragile]
+
+  \showsection
+  \showsubsection
+
+  \textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung}
+
+  \strut\hfill
+  \begin{minipage}{2.5cm}
+    \vspace*{0.6cm}
+    \begin{align*}
+      x'(t) &= v_x(t) \\[0.65cm]
+      y'(t) &= v_y(t) \\[0.75cm]
+      v_x'(t) &= 0 \\[0.65cm]
+      v_y'(t) &= -g
+    \end{align*}
+    \vspace*{0.0cm}
+  \end{minipage}%
+  \only<1>{\hspace*{9.49cm}}\strut
+  \only<2->{\hfill$\Rightarrow$\hfill}%
+  \begin{onlyenv}<2-8>
+    \begin{minipage}{8.3cm}
+      \begin{align*}
+        x(t) &= \int v_x(t)\,dt
+          \visible<4->{= \int v_{0x}\,dt}
+          \visible<5->{= x_0 + v_{0x}\cdot t}\\[\medskipamount]
+        y(t) &= \int v_y(t)\,dt
+          \visible<7->{= \int v_{0y} - g\cdot t\,dt}
+          \visible<8->{= y_0 + v_{0y}\cdot t
+                         - {\textstyle\frac12}gt^2}\\[\bigskipamount]
+        v_x(t) &= \int 0\,dt
+          \visible<3->{= v_{0x}} \\[\medskipamount]
+        v_y(t) &= \int -g\,dt
+          \visible<6->{= v_{0y} - g\cdot t}
+      \end{align*}
+    \end{minipage}%
+  \end{onlyenv}%
+  \begin{onlyenv}<9->
+    \begin{minipage}{3.5cm}
+      \vspace*{0.5cm}
+      \begin{lstlisting}[gobble=8,xleftmargin=0.5em]
+        ¡x += vx * dt;¿
+      \end{lstlisting}
+      \vspace{0.75cm}
+      \begin{lstlisting}[gobble=8,xleftmargin=0.5em]
+        ¡y += vy * dt;¿
+      \end{lstlisting}
+      \vspace{0.90cm}
+      \begin{lstlisting}[gobble=8,xleftmargin=0.5em]
+        ¡vx += 0 * dt;¿
+      \end{lstlisting}
+      \vspace{0.75cm}
+      \begin{lstlisting}[gobble=8,xleftmargin=0.5em]
+        ¡vy += -g * dt;¿
+      \end{lstlisting}
+    \end{minipage}%
+    \begin{minipage}{5.13cm}
+%      Siehe: \file{gtk-13.c}
+      \strut
+    \end{minipage}
+  \end{onlyenv}%
+  \hfill\strut
+
+\end{frame}
+
+\begin{frame}[fragile]
+  \showsection
+  \showsubsection
+
+  \textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung}
+
+  \medskip
+
+  \textbf{Beispiel 2: Mathematisches Pendel}
+
+  \vspace*{-2\bigskipamount}
+
+  \begin{picture}(0,0)
+    \put(8,-6.5){\includegraphics{pendulum.pdf}}
+  \end{picture}
+
+  \begin{eqnarray*}
+    \varphi'(t) &=& \omega(t) \\[\smallskipamount]
+    \omega'(t) &=& -\frac{g}{l}\cdot\sin\varphi(t)\hspace*{7.1cm}
+  \end{eqnarray*}
+  \vspace*{-1.5\medskipamount}
+  \begin{itemize}
+    \item
+      Von Hand (analytisch):\\
+      Lösung raten (Ansatz), Parameter berechnen
+    \item
+      Mit Computer (numerisch):\\
+      Eulersches Polygonzugverfahren
+  \end{itemize}
+  \smallskip
+  \begin{lstlisting}[gobble=0]
+    phi += dt * omega;
+    omega += - dt * g / l * sin (phi);
+  \end{lstlisting}
+
+  \pause
+  \bigskip
+
+  \textbf{Beispiel 3: Weltraum-Simulation}
+
+  Praktikumsaufgabe
+  \vspace*{-1cm}
+
+\end{frame}
+
+\subsection{Rekursion}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Vollständige Induktion:
+  \vspace*{-0.725cm}
+  \begin{displaymath}
+    \hspace*{4cm}
+    \left.
+      \begin{array}{r}
+        \mbox{Aussage gilt für $n = 1$}\\[2pt]
+        \mbox{Schluß von $n - 1$ auf $n$}
+      \end{array}
+    \right\}
+    \mbox{Aussage gilt für alle $n\in\mathbb{N}$}
+  \end{displaymath}
+  \vspace*{-0.5cm}
+
+  \pause
+
+  Türme von Hanoi
+
+  \begin{onlyenv}<2>
+    \begin{center}
+      \includegraphics[width=12.2cm]{Tower_of_Hanoi.jpeg}
+    \end{center}
+  \end{onlyenv}
+
+  \begin{onlyenv}<3->
+    \begin{itemize}
+      \item
+        64 Scheiben, 3 Plätze,
+        \only<3-4>{\hfill\makebox(0,0)[rt]{\includegraphics[width=6cm]{Tower_of_Hanoi.jpeg}}}\\
+        immer 1 Scheibe verschieben
+      \item
+        Ziel: Turm verschieben
+      \item
+        Es dürfen nur kleinere Scheiben\\
+        auf größeren liegen.
+      \bigskip
+      \pause
+      \pause
+      \item
+        $n = 1$ Scheibe: fertig
+      \item
+        Wenn $n - 1$ Scheiben verschiebbar:\\
+        schiebe $n - 1$ Scheiben auf Hilfsplatz,\\
+        verschiebe die darunterliegende,\\
+        hole $n - 1$ Scheiben von Hilfsplatz
+    \end{itemize}
+    \begin{onlyenv}<5>
+      \vspace{-4.3cm}
+      \begin{lstlisting}[gobble=8,xleftmargin=6.4cm]
+        void move (int from, int to, int disks)
+        {
+          if (disks == 1)
+            move_one_disk (from, to);
+          else
+            {
+              int help = 0 + 1 + 2 - from - to;
+              move (from, help, disks - 1);
+              move (from, to, 1);
+              move (help, to, disks - 1);
+            }
+        }
+      \end{lstlisting}
+    \end{onlyenv}
+%     \begin{onlyenv}<6->
+%       \vspace{-5.0cm}
+%       \hspace*{7.4cm}\begin{minipage}[t]{5cm}
+%         32 Scheiben:
+%         \begin{lstlisting}[gobble=10,style=terminal]
+%           $ ¡time ./hanoi-9b¿
+%           ...
+%           real    0m30,672s
+%           user    0m30,662s
+%           sys     0m0,008s
+%         \end{lstlisting}
+%         \pause[7]
+%         \begin{itemize}
+%           \arrowitem
+%             etwas über 1 Minute\\
+%             für 64 Scheiben
+%         \end{itemize}
+%         \pause
+%         \vspace*{-0.5cm}
+%         \begin{picture}(0,0)
+%           \color{red}
+%           \put(0,0){\makebox(0,0)[bl]{\tikz[line width=1pt]{\draw(0,0)--(4,0.8);}}}
+%           \put(0,0.8){\makebox(0,0)[tl]{\tikz[line width=1pt]{\draw(0,0)--(4,-0.8);}}}
+%         \end{picture}
+% 
+%         Für jede zusätzliche Scheibe\\verdoppelt sich die Rechenzeit!
+%         % 30.672 * 2^32 / 3600 / 24 / 365.25 = 4174.43775518138261464750
+%         \begin{itemize}
+%           \arrowitem
+%             $\frac{30,672\,\text{s}\,\cdot\,2^{32}}{3600\,\cdot\,24\,\cdot\,365,25} \approx 4174$
+%             Jahre\\[\smallskipamount]
+%             für 64 Scheiben
+%         \end{itemize}
+%       \end{minipage}
+%     \end{onlyenv}
+  \end{onlyenv}
+
+\end{frame}
+
+\subsection{Aufwandsabschätzungen \protect\color{gray}-- Komplexitätsanalyse}
+
+\begin{frame}[fragile]
+
+%  \newcommand{\w}{\hspace*{0.75pt}}
+
+  \showsubsection
+
+  \begin{picture}(0,0)
+    \put(7.6,-0.5){%
+      \begin{minipage}[t]{5.3cm}
+%        \vspace*{-1.0cm}\includegraphics{landau-symbols.pdf}
+        \vspace*{-1.0cm}\alt<16->{\includegraphics{landau-symbols-3.pdf}}%
+                       {\alt<15->{\includegraphics{landau-symbols-2.pdf}}%
+                                 {\includegraphics{landau-symbols.pdf}}}
+        \small
+        \begin{description}\itemsep0pt\leftskip-0.5cm
+          \item[$n$:] Eingabedaten
+          \item[$g(n)$:] Rechenzeit
+        \end{description}
+      \end{minipage}}
+  \end{picture}
+
+  \vspace*{-\bigskipamount}
+
+  Wann ist ein Programm "`schnell"'?
+
+  \medskip
+
+  \begin{onlyenv}<1-2>
+      Türme von Hanoi: $\mathcal{O}(2^n)$
+      \par\medskip
+      Für jede zusätzliche Scheibe\\verdoppelt sich die Rechenzeit!
+      \begin{itemize}
+        \arrowitem
+          $\frac{30,672\,\text{s}\,\cdot\,2^{32}}{3600\,\cdot\,24\,\cdot\,365,25} \approx 4174$
+          Jahre\\[\smallskipamount]
+          für 64 Scheiben
+      \end{itemize}
+
+      \bigskip
+  \end{onlyenv}
+
+  \begin{onlyenv}<2->
+    Faustregel:\\Schachtelung der Schleifen zählen\\
+    $k$ Schleifen ineinander \textarrow\ $\mathcal{O}(n^k)$
+
+    \bigskip
+  \end{onlyenv}
+
+  \begin{onlyenv}<3-13>
+    \textbf{Beispiel: Sortieralgorithmen}
+
+    \smallskip
+
+    Anzahl der Vergleiche bei $n$ Strings
+    \begin{itemize}
+      \item
+        Maximum suchen \pause[4]mit Schummeln\pause: $\mathcal{O}(1)$
+      \pause
+      \item
+        Maximum suchen\pause: $\mathcal{O}(n)$
+      \pause
+      \item
+        Selection-Sort\pause: $\mathcal{O}(n^2)$
+      \pause
+      \item
+        Bubble-Sort\pause: $\mathcal{O}(n)$ bis $\mathcal{O}(n^2)$
+      \pause
+      \item
+        Quicksort\pause: $\mathcal{O}(n\log n)$ bis $\mathcal{O}(n^2)$
+    \end{itemize}
+
+  \end{onlyenv}
+
+  \begin{onlyenv}<14>
+    \textbf{Wie schnell ist RSA-Verschlüsselung?}
+
+    \smallskip
+
+    \begin{math}
+      c = m^e\,\%\,N
+    \end{math}
+    \quad
+    ("`$\%$"' = "`modulo"')
+
+    \medskip
+
+    \begin{lstlisting}[gobble=6,xleftmargin=2em]
+      int c = 1;
+      for (int i = 0; i < e; i++)
+        c = (c * m) % N;
+    \end{lstlisting}
+
+    \smallskip
+
+    \begin{itemize}
+      \item
+        $\mathcal{O}(e)$ Iterationen
+%      \item
+%        wenn $n$ die Anzahl der Binärziffern (Bits) von $e$ ist:
+%        $\mathcal{O}(2^n)$ Iterationen
+      \item
+        mit Trick:
+        $\mathcal{O}(\log e)$ Iterationen ($\log e$ = Anzahl der Ziffern von $e$)
+    \end{itemize}
+
+    \smallskip
+
+    Jede Iteration enthält eine Multiplikation und eine Division.\\
+    Aufwand dafür: $\mathcal{O}(\log e)$\\
+    \textarrow\ Gesamtaufwand: $\mathcal{O}\bigl((\log e)^2\bigr)$
+
+  \end{onlyenv}
+
+  \begin{onlyenv}<15->
+
+    \textbf{Wie schnell ist RSA?}\\
+
+    \smallskip
+
+    ($n$ = typische beteiligte Zahl, z.\,B. $e,p,q$)
+
+    \begin{itemize}
+      \item
+        Ver- und Entschlüsselung (Exponentiation):\\
+        \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\!\left((\log n)^2\right)$\hss}
+        \only<16->{{\color{magenta}$\mathcal{O}(n^2)$}}
+      \item
+        Schlüsselerzeugung (Berechnung von $d$):\\
+        \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\!\left((\log n)^2\right)$\hss}
+        \only<16->{{\color{magenta}$\mathcal{O}(n^2)$}}
+      \item
+        Verschlüsselung brechen (Primfaktorzerlegung):\\
+        \strut\hbox to 3.5cm{\color{red}$\mathcal{O}\bigl(2^{\sqrt{\log n\,\cdot\,\log\log n}}\bigr)$\hss}
+        \only<16->{{\color{magenta}$\mathcal{O}\bigl(2^{\sqrt{n\log n}}\bigr)$}}
+    \end{itemize}
+
+    \vspace{0cm plus 1filll}
+
+    \textbf{Die Sicherheit von RSA beruht darauf,
+    daß das Brechen der Verschlüsselung aufwendiger ist als
+    \boldmath$\mathcal{O}\bigl((\log n)^k\bigr)$ (für beliebiges $k$).}
+
+    \vspace*{0.65cm}
+
+  \end{onlyenv}
+
+\end{frame}
+
+\end{document}
diff --git a/20231130/hp-musterloesung-20231130.pdf b/20231130/hp-musterloesung-20231130.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..1782abc389d59c3de4999c95356c99baf45cd738
Binary files /dev/null and b/20231130/hp-musterloesung-20231130.pdf differ
diff --git a/20231130/hp-musterloesung-20231130.tex b/20231130/hp-musterloesung-20231130.tex
new file mode 100644
index 0000000000000000000000000000000000000000..670f107dfce1e3f1111745f6a32fcb58659b3092
--- /dev/null
+++ b/20231130/hp-musterloesung-20231130.tex
@@ -0,0 +1,375 @@
+% hp-musterloesung-20231130.pdf - Solutions to the Exercises on Low-Level Programming / Applied Computer Sciences
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: PBM-Grafik, Einfügen in Strings (Ergänzung), Fakultät
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+\usepackage{gnuplot-lua-tikz}
+
+\begin{document}
+
+  \section*{Hardwarenahe Programmierung\\
+            Musterlösung zu den Übungsaufgaben -- 30.\ November 2023}
+
+  \exercise{PBM-Grafik}
+
+  Bei einer PBM-Grafikdatei handelt es sich
+  um ein abgespeichertes C-Array von Bytes (\lstinline{uint8_t}),
+  das die Bildinformationen enthält:
+  \begin{itemize}\itemsep0pt
+    \item Die Datei beginnt mit der Kennung \lstinline{P4},
+          danach folgen Breite und Höhe in Pixel als ASCII-Zahlen,
+          danach ein Trennzeichen und die eigentlichen Bilddaten.
+    \item Jedes Bit entspricht einem Pixel.
+    \item Nullen stehen für Weiß, Einsen für Schwarz.
+    \item MSB first.
+    \item Jede Zeile des Bildes wird auf ganze Bytes aufgefüllt.
+  \end{itemize}
+  Viele Grafikprogramme können PBM-Dateien öffnen und bearbeiten.
+  Der Anfang der Datei (Kennung, Breite und Höhe)
+  ist auch in einem Texteditor lesbar.
+
+  Beispiel (\gitfile{hp}{2023ws/20231130}{aufgabe-1.pbm}):\hfill
+  \makebox(0,0)[tr]{\framebox{\includegraphics[scale=3]{aufgabe-1.png}}}
+  \begin{lstlisting}
+    P4
+    14 14
+    <Bilddaten>
+  \end{lstlisting}
+
+  In dem untenstehenden Programmfragment (\gitfile{hp}{2023ws/20231130}{aufgabe-1.c})
+  wird eine Grafik aus Textzeilen zusammengesetzt,
+  so daß man mit einem Texteditor "`malen"' kann:
+  \begin{lstlisting}
+    #include <stdio.h>
+
+    /* ... */
+
+    int main (void)
+    {
+      pbm_open (14, 14, "test.pbm");
+      pbm_line ("              ");
+      pbm_line ("    XXXXXX    ");
+      pbm_line ("   X      X   ");
+      pbm_line ("  X        X  ");
+      pbm_line (" X          X ");
+      pbm_line (" X  XX  XX  X ");
+      pbm_line (" X   X   X  X ");
+      pbm_line (" X          X ");
+      pbm_line (" X X      X X ");
+      pbm_line (" X  X    X  X ");
+      pbm_line ("  X  XXXX  X  ");
+      pbm_line ("   X      X   ");
+      pbm_line ("    XXXXXX    ");
+      pbm_line ("              ");
+      pbm_close ();
+      return 0;
+    }
+  \end{lstlisting}
+  Ergänzen Sie das Programmfragment so,
+  daß es eine Datei \file{test.pbm} erzeugt, die die Grafik enthält.
+
+  Das Programm soll typische Benutzerfehler abfangen
+  (z.\,B.\ weniger Zeilen als in \lstinline{pbm_open} angegeben),
+  keine fehlerhaften Ausgaben produzieren oder abstürzen,
+  sondern stattdessen sinnvolle Fehlermeldungen ausgeben.
+
+  Zum Vergleich liegt eine Datei \gitfile{hp}{2023ws/20231130}{aufgabe-1.pbm}
+  mit dem gewünschten Ergebnis bei,\\
+  und die Datei \gitfile{hp}{2023ws/20231130}{aufgabe-1.png} enthält dasselbe Bild.
+
+  \points{10}
+
+  \solution
+
+  Die Datei \gitfile{hp}{2023ws/20231130}{loesung-1.c} enthält eine richtige Lösung.
+  Man beachte die Aufrufe der Funktion \lstinline{error()} im Falle von
+  falscher Benutzung der Bibliotheksfunktionen.
+  Weitere Erklärungen finden Sie als Kommentare im Quelltext.
+
+  Die Datei \gitfile{hp}{2023ws/20231130}{loesung-1f.c} enthält eine falsche Lösung.
+  (Beide Dateien unterscheiden sich nur in Zeile 46.)
+  Dieses Programm speichert die Bits in den Bytes von rechts nach links (LSB first).
+  Richtig wäre von links nach rechts (MBS first).
+  Das erzeugte Bild ist dementsprechend fehlerhaft.
+
+  \exercise{Fakultät}
+
+  Die Fakultät $n!$ einer ganzen Zahl $n \ge 0$ ist definiert als:
+  \begin{eqnarray*}
+    1 & \mbox{für} & n = 0, \\
+    n \cdot (n-1)! & \mbox{für} & n > 0.
+  \end{eqnarray*}
+
+  Mit anderen Worten: $n! = 1\cdot2\cdot3\cdot\dots\cdot n$.
+
+  Die folgende Funktion \lstinline{fak()} berechnet die Fakultät \emph{rekursiv}
+  (Datei: \gitfile{hp}{2023ws/20231130}{aufgabe-2.c}):
+
+  \begin{lstlisting}
+    int fak (int n)
+    {
+      if (n <= 0)
+        return 1;
+      else
+        return n * fak (n - 1);
+    }
+  \end{lstlisting}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Schreiben Sie eine Funktion, die die Fakultät \emph{iterativ} berechnet,\\
+      d.\,h.\ mit Hilfe einer Schleife anstelle von Rekursion.
+      \points{3}
+    \item
+      Wie viele Multiplikationen (Landau-Symbol)
+      erfordern beide Versionen der Fakultätsfunktion\\
+      in Abhängigkeit von \lstinline$n$?
+      Begründen Sie Ihre Antwort.
+      \points{2}
+    \item
+      Wieviel Speicherplatz (Landau-Symbol)
+      erfordern beide Versionen der Fakultätsfunktion\\
+      in Abhängigkeit von \lstinline$n$?
+      Begründen Sie Ihre Antwort.
+      \points{3}
+  \end{enumerate}
+
+  \solution
+
+  \begin{itemize}
+    \item[(a)]
+      \textbf{Schreiben Sie eine Funktion, die die Fakultät \emph{iterativ} berechnet,\\
+      d.\,h.\ mit Hilfe einer Schleife anstelle von Rekursion.}
+
+      Datei: \gitfile{hp}{2023ws/20231130}{loesung-2.c}
+      \begin{lstlisting}[gobble=8]
+        int fak (int n)
+        {
+          int f = 1;
+          for (int i = 2; i <= n; i++)
+            f *= i;
+          return f;
+        }
+      \end{lstlisting}
+
+    \item[(b)]
+      \textbf{Wie viele Multiplikationen (Landau-Symbol)
+      erfordern beide Versionen der Fakultätsfunktion\\
+      in Abhängigkeit von \lstinline$n$?
+      Begründen Sie Ihre Antwort.}
+
+      In beiden Fällen werden $n$ Zahlen miteinander multipliziert --
+      oder $n - 1$, wenn man Multiplikationen mit 1 ausspart.
+      In jedem Fall hängt die Anzahl der Multiplikationen
+      linear von $n$ ab; es sind $\mathcal{O}(n)$ Multiplikationen.
+      Insbesondere arbeiten also beide Versionen gleich schnell.
+
+    \item[(c)]
+      \textbf{Wieviel Speicherplatz (Landau-Symbol)
+      erfordern beide Versionen der Fakultätsfunktion\\
+      in Abhängigkeit von \lstinline$n$?
+      Begründen Sie Ihre Antwort.}
+
+      Die iterative Version der Funktion benötigt 2 Variable vom Typ \lstinline{int},
+      nämlich \lstinline{n} und \lstinline{f}.
+      Dies ist eine konstante Zahl;
+      der Speicherplatzverbrauch ist daher $\mathcal{O}(1)$.
+
+      Die rekursive Version der Funktion erzeugt
+      jedesmal, wenn sie sich selbst aufruft,
+      eine zusätzliche Variable \lstinline{n}.
+      Es sind $n + 1$ Aufrufe; die Anzahl der Variablen \lstinline{n}
+      hängt linear von $n$ ab; der Speicherplatzverbrauch ist also $\mathcal{O}(n)$.
+  \end{itemize}
+
+  \exercise{Einfügen in Strings (Ergänzung)}
+
+  Diese Aufgabe ist eine Ergänzung von Aufgabe 3 der Übung vom 31.\ Oktober
+  2022 um die Teilaufgaben (e), (f) und (g). Für den "`Klausur-Modus"' können
+  Sie die Teilaufgaben (a) bis (d) als "`bereits gelöst"' voraussetzen.
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{2023ws/20231130}{aufgabe-3.c}):
+%  \begin{lstlisting}[style=numbered]
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    void insert_into_string (char src, char *target, int pos)
+    {
+      int len = strlen (target);
+      for (int i = pos; i < len; i++)
+        target[i+1] = target[i];
+      target[pos] = src;
+    }
+
+    int main (void)
+    {
+      char test[100] = "Hochshule Bochum";
+      insert_into_string ('c', test, 5);
+      printf ("%s\n", test);
+      return 0;
+    }
+  \end{lstlisting}
+  Die Ausgabe des Programms lautet:
+  \lstinline[style=terminal]{Hochschhhhhhhhhhh}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Erklären Sie, wie die Ausgabe zustandekommt.
+%      \points{3}
+%      \workspace{12}
+    \item
+      Schreiben Sie die Funktion \lstinline|insert_into_string()| so um,
+      daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos}
+      in den String \lstinline{target} einfügt.\par
+      Die Ausgabe des Programms müßte dann
+      \lstinline[style=terminal]{Hochschule Bochum} lauten.
+%      \points{2}
+%      \workspace{13}
+    \item
+      Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char test[] = "Hochshule Bochum";} ersetzen?
+      Begründen Sie Ihre Antwort.
+%      \points{2}
+%      \workspace{10}
+    \item
+      Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char *test = "Hochshule Bochum";} ersetzen?
+      Begründen Sie Ihre Antwort.
+%      \points{2}
+%      \workspace{10}
+    \item
+      Schreiben Sie eine Funktion
+      \lstinline{void insert_into_string_sorted (char src, char *target)},
+      die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist
+      und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle
+      einfügt. Diese Funktion darf die bereits vorhandene Funktion
+      \lstinline|insert_into_string()| aufrufen.\\
+      \points{4}\par
+      Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm:
+      \begin{lstlisting}[gobble=8]
+        char test[100] = "";
+        insert_into_string_sorted ('c', test);
+        insert_into_string_sorted ('a', test);
+        insert_into_string_sorted ('d', test);
+        insert_into_string_sorted ('b', test);
+      \end{lstlisting}
+      Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten.
+%      \workspace{14}
+    \goodbreak
+    \item
+      Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings)
+      arbeitet Ihre Funktion
+      \lstinline{void insert_into_string_sorted (char src, char *target)}?
+      Begründen Sie Ihre Antwort.
+      \points{1}
+%      \workspace{10}
+    \item
+      Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\
+      \lstinline{void insert_into_string_sorted (char src, char *target)}
+      so gestalten kann,\\
+      daß sie in $\mathcal{O}(\log n)$ arbeitet.
+      \points{3}
+%      \workspace{35}
+  \end{enumerate}
+
+  \solution
+
+  \textbf{Bemerkung:} Die in dieser Aufgabe und ihrer Musterlösung vorkommenden
+  Funktionen prüfen nicht, ob durch das Einfügen eines Zeichens der für den
+  String reservierte Speicherplatz überläuft. Ein derartiges Verhalten wäre
+  in einem "`echten"' Programm ein \textbf{Fehler}, der katastrophale Folgen
+  haben kann. Wenn dergleichen hier nicht berücksichtigt wird, dann nur, um
+  in einer Klausur nicht den zeitlichen Rahmen zu sprengen.
+
+  \begin{enumerate}[\quad(a)]
+    \setcounter{enumi}{4}
+    \item
+      \textbf{Schreiben Sie eine Funktion
+      \lstinline{void insert_into_string_sorted (char src, char *target)},
+      die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist
+      und den Buchstaben \lstinline{src} an der\break alphabetisch richtigen Stelle
+      einfügt. Diese Funktion darf die bereits vorhandene Funktion\break
+      \lstinline|insert_into_string()| aufrufen.}
+      \begin{lstlisting}{gobble=8}
+        void insert_into_string_sorted (char src, char *target)
+        {
+          int i = 0;
+          while (target[i] && target[i] < src)
+            i++;
+          insert_into_string (src, target, i);
+        }
+      \end{lstlisting}
+
+      Die Datei \gitfile{hp}{2023ws/20231130}{loesung-3e.c} enthält die o.\,a.\ Funktion
+      sowie zusätzliche Tests.
+
+    \item
+      \textbf{Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings)
+      arbeitet Ihre Funktion
+      \lstinline{void insert_into_string_sorted (char src, char *target)}?
+      Begründen Sie Ihre Antwort.}
+
+      Die Funktion sucht im Array \textbf{mittels einer Schleife}
+      nach der korrekten Position zum Einfügen des Zeichens
+      und hat daher von sich aus $\mathcal{O}(n)$.
+
+      Anschließend ruft sie die Funktion \lstinline{insert_into_string()} auf,
+      die ebenfalls eine Schleife verwendet, um im Array Platz zu Einfügen zu schaffen,
+      und daher ebenfalls $\mathcal{O}(n)$ hat.
+
+      Es bleibt daher bei $\mathcal{O}(n)$.
+
+    \item
+      \textbf{Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\
+      \lstinline{void insert_into_string_sorted (char src, char *target)}
+      so gestalten kann,\\
+      daß sie in $\mathcal{O}(\log n)$ arbeitet.}
+
+      In einem alphabetisch sortierten Array kann man die Suche in der Mitte beginnen
+      und sich durch Halbieren der Intervalle an die gesuchte Position herantasten.
+      Wegen des fortwährenden Halbierens geschieht dies in $\mathcal{O}(\log n)$.
+      (Für eine derartige Antwort gäbe es in der Klausur die volle Punktzahl.)
+
+      Wenn wir allerdings anschließend für das eigentliche Einfügen die Funktion
+      \lstinline{insert_into_string()} verwenden, die dafür $\mathcal{O}(n)$ benötigt,
+      kommen wir insgesamt auf $\mathcal{O}(n)$. Ein sortiertes Einfügen in ein Array
+      ist daher in $\mathcal{O}(\log n)$ nicht möglich.
+      (Wer dies bemerkt, kann zum einen während der Klausur nachfragen,
+      wie denn die Aufgabenstellung genau gemeint ist, und sich zum anderen
+      für die besondere Sorgfalt Zusatzpunkte verdienen.)
+
+      Die Datei \gitfile{hp}{2023ws/20231130}{loesung-3g.c} enthält einen C-Quelltext,
+      die den o.\,a.\ Algorithmus als Funktion implementiert.
+      Man beachte die Behandlung des Spezialfalls,
+      daß das einzufügende Zeichen am Ende angehängt werden muß.
+
+  \end{enumerate}
+
+\end{document}
diff --git a/20231130/hp-uebung-20231130.pdf b/20231130/hp-uebung-20231130.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..7a90b036343cf43f9bc7573848921b7c1daccee4
Binary files /dev/null and b/20231130/hp-uebung-20231130.pdf differ
diff --git a/20231130/hp-uebung-20231130.tex b/20231130/hp-uebung-20231130.tex
new file mode 100644
index 0000000000000000000000000000000000000000..40e876f5c678e32eae661f3b04084212153790bc
--- /dev/null
+++ b/20231130/hp-uebung-20231130.tex
@@ -0,0 +1,262 @@
+% hp-uebung-20231130.pdf - Exercises on Low-Level Programming / Applied Computer Sciences
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: PBM-Grafik, Einfügen in Strings (Ergänzung), Fakultät
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+\usepackage{gensymb}
+
+\newcommand{\ItwoC}{I\raisebox{0.5ex}{\footnotesize 2}C}
+\newcommand{\ITWOC}{I\raisebox{0.5ex}{\normalsize 2}C}
+
+\begin{document}
+
+  \thispagestyle{empty}
+
+  \section*{Hardwarenahe Programmierung\\
+            Übungsaufgaben -- 30.\ November 2023}
+
+  Diese Übung enthält Punkteangaben wie in einer Klausur.
+  Um zu "`bestehen"', müssen Sie innerhalb von 75 Minuten
+  unter Verwendung ausschließlich zugelassener Hilfsmittel
+  13 Punkte (von insgesamt \totalpoints) erreichen.
+
+  \exercise{PBM-Grafik}
+
+  Bei einer PBM-Grafikdatei handelt es sich
+  um ein abgespeichertes C-Array von Bytes (\lstinline{uint8_t}),
+  das die Bildinformationen enthält:
+  \begin{itemize}\itemsep0pt
+    \item Die Datei beginnt mit der Kennung \lstinline{P4},
+          danach folgen Breite und Höhe in Pixel als ASCII-Zahlen,
+          danach ein Trennzeichen und die eigentlichen Bilddaten.
+    \item Jedes Bit entspricht einem Pixel.
+    \item Nullen stehen für Weiß, Einsen für Schwarz.
+    \item MSB first.
+    \item Jede Zeile des Bildes wird auf ganze Bytes aufgefüllt.
+  \end{itemize}
+  Viele Grafikprogramme können PBM-Dateien öffnen und bearbeiten.
+  Der Anfang der Datei (Kennung, Breite und Höhe)
+  ist auch in einem Texteditor lesbar.
+
+  Beispiel (\gitfile{hp}{2023ws/20231130}{aufgabe-1.pbm}):\hfill
+  \makebox(0,0)[tr]{\framebox{\includegraphics[scale=3]{aufgabe-1.png}}}
+  \begin{lstlisting}
+    P4
+    14 14
+    <Bilddaten>
+  \end{lstlisting}
+
+  In dem untenstehenden Programmfragment (\gitfile{hp}{2023ws/20231130}{aufgabe-1.c})
+  wird eine Grafik aus Textzeilen zusammengesetzt,
+  so daß man mit einem Texteditor "`malen"' kann:
+  \begin{lstlisting}
+    #include <stdio.h>
+
+    /* ... */
+
+    int main (void)
+    {
+      pbm_open (14, 14, "test.pbm");
+      pbm_line ("              ");
+      pbm_line ("    XXXXXX    ");
+      pbm_line ("   X      X   ");
+      pbm_line ("  X        X  ");
+      pbm_line (" X          X ");
+      pbm_line (" X  XX  XX  X ");
+      pbm_line (" X   X   X  X ");
+      pbm_line (" X          X ");
+      pbm_line (" X X      X X ");
+      pbm_line (" X  X    X  X ");
+      pbm_line ("  X  XXXX  X  ");
+      pbm_line ("   X      X   ");
+      pbm_line ("    XXXXXX    ");
+      pbm_line ("              ");
+      pbm_close ();
+      return 0;
+    }
+  \end{lstlisting}
+  Ergänzen Sie das Programmfragment so,
+  daß es eine Datei \file{test.pbm} erzeugt, die die Grafik enthält.
+
+  Das Programm soll typische Benutzerfehler abfangen
+  (z.\,B.\ weniger Zeilen als in \lstinline{pbm_open} angegeben),
+  keine fehlerhaften Ausgaben produzieren oder abstürzen,
+  sondern stattdessen sinnvolle Fehlermeldungen ausgeben.
+
+  Zum Vergleich liegt eine Datei \gitfile{hp}{2023ws/20231130}{aufgabe-1.pbm}
+  mit dem gewünschten Ergebnis bei,\\
+  und die Datei \gitfile{hp}{2023ws/20231130}{aufgabe-1.png} enthält dasselbe Bild.
+
+  \points{10}
+
+  Hinweis für die Klausur:
+  Abgabe in digitaler Form ist erwünscht, aber nicht zwingend.
+
+  \exercise{Fakultät}
+
+  Die Fakultät $n!$ einer ganzen Zahl $n \ge 0$ ist definiert als:
+  \begin{eqnarray*}
+    1 & \mbox{für} & n = 0, \\
+    n \cdot (n-1)! & \mbox{für} & n > 0.
+  \end{eqnarray*}
+
+  Mit anderen Worten: $n! = 1\cdot2\cdot3\cdot\dots\cdot n$.
+
+  Die folgende Funktion \lstinline{fak()} berechnet die Fakultät \emph{rekursiv}
+  (Datei: \gitfile{hp}{2023ws/20231130}{aufgabe-2.c}):
+
+  \begin{lstlisting}
+    int fak (int n)
+    {
+      if (n <= 0)
+        return 1;
+      else
+        return n * fak (n - 1);
+    }
+  \end{lstlisting}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Schreiben Sie eine Funktion, die die Fakultät \emph{iterativ} berechnet,\\
+      d.\,h.\ mit Hilfe einer Schleife anstelle von Rekursion.
+      \points{3}
+    \item
+      Wie viele Multiplikationen (Landau-Symbol)
+      erfordern beide Versionen der Fakultätsfunktion\\
+      in Abhängigkeit von \lstinline$n$?
+      Begründen Sie Ihre Antwort.
+      \points{2}
+    \item
+      Wieviel Speicherplatz (Landau-Symbol)
+      erfordern beide Versionen der Fakultätsfunktion\\
+      in Abhängigkeit von \lstinline$n$?
+      Begründen Sie Ihre Antwort.
+      \points{3}
+  \end{enumerate}
+
+  \exercise{Einfügen in Strings (Ergänzung)}
+
+  Diese Aufgabe ist eine Ergänzung von Aufgabe 3 der Übung vom 2.\ November 2023
+  um die Teilaufgaben (e), (f) und (g). Für den "`Klausur-Modus"' können
+  Sie die Teilaufgaben (a) bis (d) als "`bereits gelöst"' voraussetzen.
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{2023ws/20231130}{aufgabe-1.c}):
+%  \begin{lstlisting}[style=numbered]
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    void insert_into_string (char src, char *target, int pos)
+    {
+      int len = strlen (target);
+      for (int i = pos; i < len; i++)
+        target[i+1] = target[i];
+      target[pos] = src;
+    }
+
+    int main (void)
+    {
+      char test[100] = "Hochshule Bochum";
+      insert_into_string ('c', test, 5);
+      printf ("%s\n", test);
+      return 0;
+    }
+  \end{lstlisting}
+  Die Ausgabe des Programms lautet:
+  \lstinline[style=terminal]{Hochschhhhhhhhhhh}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Erklären Sie, wie die Ausgabe zustandekommt.
+%      \points{3}
+%      \workspace{12}
+    \item
+      Schreiben Sie die Funktion \lstinline|insert_into_string()| so um,
+      daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos}
+      in den String \lstinline{target} einfügt.\par
+      Die Ausgabe des Programms müßte dann
+      \lstinline[style=terminal]{Hochschule Bochum} lauten.
+%      \points{2}
+%      \workspace{13}
+    \item
+      Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char test[] = "Hochshule Bochum";} ersetzen?
+      Begründen Sie Ihre Antwort.
+%      \points{2}
+%      \workspace{10}
+    \item
+      Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char *test = "Hochshule Bochum";} ersetzen?
+      Begründen Sie Ihre Antwort.
+%      \points{2}
+%      \workspace{10}
+    \item
+      Schreiben Sie eine Funktion
+      \lstinline{void insert_into_string_sorted (char src, char *target)},
+      die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist
+      und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle
+      einfügt. Diese Funktion darf die bereits vorhandene Funktion
+      \lstinline|insert_into_string()| aufrufen.\\
+      \points{4}\par
+      Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm:
+      \begin{lstlisting}[gobble=8]
+        char test[100] = "";
+        insert_into_string_sorted ('c', test);
+        insert_into_string_sorted ('a', test);
+        insert_into_string_sorted ('d', test);
+        insert_into_string_sorted ('b', test);
+      \end{lstlisting}
+      Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten.
+%      \workspace{14}
+    \goodbreak
+    \item
+      Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings)
+      arbeitet Ihre Funktion
+      \lstinline{void insert_into_string_sorted (char src, char *target)}?
+      Begründen Sie Ihre Antwort.
+      \points{1}
+%      \workspace{10}
+    \item
+      Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\
+      \lstinline{void insert_into_string_sorted (char src, char *target)}
+      so gestalten kann,\\
+      daß sie in $\mathcal{O}(\log n)$ arbeitet.
+      \points{3}
+%      \workspace{35}
+  \end{enumerate}
+
+  \begin{flushright}
+    \textit{Viel Erfolg!}
+  \end{flushright}
+
+  \makeatletter
+    \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}}
+  \makeatother
+
+\end{document}
diff --git a/20231130/landau-symbols-2.pdf b/20231130/landau-symbols-2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..6b458b6efd8e274824a6dfcaabc4b9c27d196dc4
--- /dev/null
+++ b/20231130/landau-symbols-2.pdf
@@ -0,0 +1 @@
+../common/landau-symbols-2.pdf
\ No newline at end of file
diff --git a/20231130/landau-symbols-3.pdf b/20231130/landau-symbols-3.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..46efa409b35ff5df763c744a423599cba515d886
--- /dev/null
+++ b/20231130/landau-symbols-3.pdf
@@ -0,0 +1 @@
+../common/landau-symbols-3.pdf
\ No newline at end of file
diff --git a/20231130/landau-symbols.pdf b/20231130/landau-symbols.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..ca145425bf07439c680632aa0663f84be601a565
--- /dev/null
+++ b/20231130/landau-symbols.pdf
@@ -0,0 +1 @@
+../common/landau-symbols.pdf
\ No newline at end of file
diff --git a/20231130/loesung-1.c b/20231130/loesung-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d5733e92e6a1c2d28419adc60321c50f5c18129
--- /dev/null
+++ b/20231130/loesung-1.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <error.h>
+
+/* Die Aufgabe besteht darin, die Funktionen pbm_open(),
+ * pbm_line() und pbm_close() zu schreiben.
+ */
+
+int pbm_width = 0;
+int pbm_height = 0;
+int line_no = 0;
+FILE *pbm_file = NULL;  /* globale Variable für die PBM-Datei */
+
+void pbm_open (int width, int height, char *filename)
+{
+  pbm_file = fopen (filename, "w");
+  if (!pbm_file)
+    error (errno, errno, "pbm_open(): cannot open file %s for writing", filename);
+  pbm_width = width;
+  pbm_height = height;
+  fprintf (pbm_file, "P4\n%d %d\n", pbm_width, pbm_height);
+}
+
+void pbm_line (char *line)
+{
+  if (!pbm_file)
+    error (1, 0, "pbm_line(): PBM file not open");
+  if (!line)
+    error (1, 0, "pbm_line(): line is NULL");
+  if (strlen (line) != pbm_width)
+    error (1, 0, "pbm_line(): line length does not match width");
+  if (line_no >= pbm_height)
+    error (1, 0, "pbm_line(): too many lines");
+  int pbm_bytes = (pbm_width + 7) / 8;   /* benötigte Bytes pro Zeile (immer aufrunden) */
+  uint8_t buffer[pbm_bytes];
+  for (int i = 0; i < pbm_bytes; i++)   /* Puffer auf 0 initialisieren */
+    buffer[i] = 0;
+  line_no++;
+  for (int x = 0; line[x]; x++)
+    {
+      int i = x / 8;  /* In welches Byte des Puffers gehört dieses Pixel? */
+      int b = x % 8;  /* Welches Bit innerhalb des Bytes ist dieses Pixel? */
+      if (line[x] != ' ')   /* Kein Leerzeichen --> Bit auf 1 setzen */
+        buffer[i] |= 0x80 >> b;  /* MSB first. LSB first wäre 1 << b. */
+    }
+  for (int i = 0; i < pbm_bytes; i++)   /* Puffer in Datei ausgeben */
+    fprintf (pbm_file, "%c", buffer[i]);
+}
+
+void pbm_close (void)
+{
+  if (!pbm_file)
+    error (1, 0, "pbm_close(): PBM file not open");
+  if (line_no < pbm_height)
+    error (1, 0, "pbm_close(): too few lines");
+  fclose (pbm_file);
+}
+
+int main (void)
+{
+  pbm_open (14, 14, "test.pbm");
+  pbm_line ("              ");
+  pbm_line ("    XXXXXX    ");
+  pbm_line ("   X      X   ");
+  pbm_line ("  X        X  ");
+  pbm_line (" X          X ");
+  pbm_line (" X  XX  XX  X ");
+  pbm_line (" X   X   X  X ");
+  pbm_line (" X          X ");
+  pbm_line (" X X      X X ");
+  pbm_line (" X  X    X  X ");
+  pbm_line ("  X  XXXX  X  ");
+  pbm_line ("   X      X   ");
+  pbm_line ("    XXXXXX    ");
+  pbm_line ("              ");
+  pbm_close ();
+  return 0;
+}
diff --git a/20231130/loesung-1f.c b/20231130/loesung-1f.c
new file mode 100644
index 0000000000000000000000000000000000000000..d358fa1de54ad08a770dc733d089d3d40342bdde
--- /dev/null
+++ b/20231130/loesung-1f.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <error.h>
+
+/* Die Aufgabe besteht darin, die Funktionen pbm_open(),
+ * pbm_line() und pbm_close() zu schreiben.
+ */
+
+int pbm_width = 0;
+int pbm_height = 0;
+int line_no = 0;
+FILE *pbm_file = NULL;  /* globale Variable für die PBM-Datei */
+
+void pbm_open (int width, int height, char *filename)
+{
+  pbm_file = fopen (filename, "w");
+  if (!pbm_file)
+    error (errno, errno, "pbm_open(): cannot open file %s for writing", filename);
+  pbm_width = width;
+  pbm_height = height;
+  fprintf (pbm_file, "P4\n%d %d\n", pbm_width, pbm_height);
+}
+
+void pbm_line (char *line)
+{
+  if (!pbm_file)
+    error (1, 0, "pbm_line(): PBM file not open");
+  if (!line)
+    error (1, 0, "pbm_line(): line is NULL");
+  if (strlen (line) != pbm_width)
+    error (1, 0, "pbm_line(): line length does not match width");
+  if (line_no >= pbm_height)
+    error (1, 0, "pbm_line(): too many lines");
+  int pbm_bytes = (pbm_width + 7) / 8;   /* benötigte Bytes pro Zeile (immer aufrunden) */
+  uint8_t buffer[pbm_bytes];
+  for (int i = 0; i < pbm_bytes; i++)   /* Puffer auf 0 initialisieren */
+    buffer[i] = 0;
+  line_no++;
+  for (int x = 0; line[x]; x++)
+    {
+      int i = x / 8;  /* In welches Byte des Puffers gehört dieses Pixel? */
+      int b = x % 8;  /* Welches Bit innerhalb des Bytes ist dieses Pixel? */
+      if (line[x] != ' ')   /* Kein Leerzeichen --> Bit auf 1 setzen */
+        buffer[i] |= 1 << b;
+    }
+  for (int i = 0; i < pbm_bytes; i++)   /* Puffer in Datei ausgeben */
+    fprintf (pbm_file, "%c", buffer[i]);
+}
+
+void pbm_close (void)
+{
+  if (!pbm_file)
+    error (1, 0, "pbm_close(): PBM file not open");
+  if (line_no < pbm_height)
+    error (1, 0, "pbm_close(): too few lines");
+  fclose (pbm_file);
+}
+
+int main (void)
+{
+  pbm_open (14, 14, "test.pbm");
+  pbm_line ("              ");
+  pbm_line ("    XXXXXX    ");
+  pbm_line ("   X      X   ");
+  pbm_line ("  X        X  ");
+  pbm_line (" X          X ");
+  pbm_line (" X  XX  XX  X ");
+  pbm_line (" X   X   X  X ");
+  pbm_line (" X          X ");
+  pbm_line (" X X      X X ");
+  pbm_line (" X  X    X  X ");
+  pbm_line ("  X  XXXX  X  ");
+  pbm_line ("   X      X   ");
+  pbm_line ("    XXXXXX    ");
+  pbm_line ("              ");
+  pbm_close ();
+  return 0;
+}
diff --git a/20231130/loesung-2.c b/20231130/loesung-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..c2d6f6003924627ae97831407c191eaac42a09c1
--- /dev/null
+++ b/20231130/loesung-2.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+int fak (int n)
+{
+  int f = 1;
+  for (int i = 2; i <= n; i++)
+    f *= i;
+  return f;
+}
+
+int main (void)
+{
+  for (int n = 0; n <= 5; n++)
+    printf ("%d\n", fak (n));
+  return 0;
+}
diff --git a/20231130/loesung-3e.c b/20231130/loesung-3e.c
new file mode 100644
index 0000000000000000000000000000000000000000..bc41fb0e1f5f826a427038a18798e280fd1a096d
--- /dev/null
+++ b/20231130/loesung-3e.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <string.h>
+
+void insert_into_string (char src, char *target, int pos)
+{
+  int len = strlen (target);
+  for (int i = len; i >= pos; i--)
+    target[i + 1] = target[i];
+  target[pos] = src;
+}
+
+void insert_into_string_sorted (char src, char *target)
+{
+  int i = 0;
+  while (target[i] && target[i] < src)
+    i++;
+  insert_into_string (src, target, i);
+}
+
+int main (void)
+{
+  char test[100] = "";
+  insert_into_string_sorted ('c', test);
+  insert_into_string_sorted ('a', test);
+  insert_into_string_sorted ('d', test);
+  insert_into_string_sorted ('b', test);
+  printf ("test = \"%s\"\n", test);
+  for (char ch = 'e'; ch < 'z'; ch += 2)
+    insert_into_string_sorted (ch, test);
+  insert_into_string_sorted ('n', test);
+  printf ("test = \"%s\"\n", test);
+  return 0;
+}
diff --git a/20231130/loesung-3g.c b/20231130/loesung-3g.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b0c29dfc223fa961cdbf930683e6d79610b002b
--- /dev/null
+++ b/20231130/loesung-3g.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <string.h>
+
+void insert_into_string (char src, char *target, int pos)
+{
+  int len = strlen (target);
+  for (int i = len; i >= pos; i--)
+    target[i + 1] = target[i];
+  target[pos] = src;
+}
+
+void insert_into_string_sorted (char src, char *target)
+{
+  int l = 0;
+  int r = 0;
+  while (target[r])
+    r++;
+  int m = (l + r) / 2;
+  while (m > l)
+    {
+      if (src < target[m])
+        r = m;
+      else
+        l = m;
+      m = (l + r) / 2;
+    }
+  if (target[m] == 0 || src < target[m])
+    insert_into_string (src, target, m);
+  else
+    insert_into_string (src, target, m + 1);
+}
+
+int main (void)
+{
+  char test[100] = "";
+  insert_into_string_sorted ('c', test);
+  insert_into_string_sorted ('a', test);
+  insert_into_string_sorted ('d', test);
+  insert_into_string_sorted ('b', test);
+  printf ("test = \"%s\"\n", test);
+  for (char ch = 'e'; ch < 'z'; ch += 2)
+    insert_into_string_sorted (ch, test);
+  insert_into_string_sorted ('n', test);
+  printf ("test = \"%s\"\n", test);
+  return 0;
+}
diff --git a/20231130/logo-hochschule-bochum-cvh-text-v2.pdf b/20231130/logo-hochschule-bochum-cvh-text-v2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8
--- /dev/null
+++ b/20231130/logo-hochschule-bochum-cvh-text-v2.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum-cvh-text-v2.pdf
\ No newline at end of file
diff --git a/20231130/logo-hochschule-bochum.pdf b/20231130/logo-hochschule-bochum.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1
--- /dev/null
+++ b/20231130/logo-hochschule-bochum.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum.pdf
\ No newline at end of file
diff --git a/20231130/pendulum.pdf b/20231130/pendulum.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..7d1d87305cdb8840a248ff2207538d758464f452
--- /dev/null
+++ b/20231130/pendulum.pdf
@@ -0,0 +1 @@
+../common/pendulum.pdf
\ No newline at end of file
diff --git a/20231130/pgscript.sty b/20231130/pgscript.sty
new file mode 120000
index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b
--- /dev/null
+++ b/20231130/pgscript.sty
@@ -0,0 +1 @@
+../common/pgscript.sty
\ No newline at end of file
diff --git a/20231130/pgslides.sty b/20231130/pgslides.sty
new file mode 120000
index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64
--- /dev/null
+++ b/20231130/pgslides.sty
@@ -0,0 +1 @@
+../common/pgslides.sty
\ No newline at end of file