Skip to content
Snippets Groups Projects
Commit fd71d402 authored by Peter Gerwinski's avatar Peter Gerwinski
Browse files

Vorbereitung 7.12.2023

parent e5a55ae5
No related branches found
No related tags found
No related merge requests found
Showing
with 1243 additions and 1 deletion
...@@ -164,7 +164,7 @@ ...@@ -164,7 +164,7 @@
um die Teilaufgaben (e), (f) und (g). Für den "`Klausur-Modus"' können 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. Sie die Teilaufgaben (a) bis (d) als "`bereits gelöst"' voraussetzen.
Wir betrachten das folgende Programm (\gitfile{hp}{2023ws/20231130}{aufgabe-1.c}): Wir betrachten das folgende Programm (\gitfile{hp}{2023ws/20231130}{aufgabe-3.c}):
% \begin{lstlisting}[style=numbered] % \begin{lstlisting}[style=numbered]
\begin{lstlisting} \begin{lstlisting}
#include <stdio.h> #include <stdio.h>
......
../common/Tower_of_Hanoi.jpeg
\ No newline at end of file
#include <string.h>
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
#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;
}
File added
% hp-20231207.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: 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{7.\ Dezember 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}
\item[\textbf{5}] \textbf{Algorithmen}
\begin{itemize}
\color{medgreen}
\item[5.1] Differentialgleichungen
\item[5.2] Rekursion
\color{red}
\item[5.3] Aufwandsabschätzungen
\end{itemize}
\item[\textbf{6}] \textbf{Objektorientierte Programmierung}
\item[\textbf{7}] \textbf{Datenstrukturen}
\end{itemize}
\end{frame}
\setcounter{section}{4}
\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<1>{\hfill$\Rightarrow$\hfill}%
\begin{onlyenv}<1>
\begin{minipage}{8.3cm}
\begin{align*}
x(t) &= \int v_x(t)\,dt
\visible<1->{= \int v_{0x}\,dt}
\visible<1->{= x_0 + v_{0x}\cdot t}\\[\medskipamount]
y(t) &= \int v_y(t)\,dt
\visible<1->{= \int v_{0y} - g\cdot t\,dt}
\visible<1->{= y_0 + v_{0y}\cdot t
- {\textstyle\frac12}gt^2}\\[\bigskipamount]
v_x(t) &= \int 0\,dt
\visible<1->{= v_{0x}} \\[\medskipamount]
v_y(t) &= \int -g\,dt
\visible<1->{= v_{0y} - g\cdot t}
\end{align*}
\end{minipage}%
\end{onlyenv}%
\begin{onlyenv}<2>
\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}
File added
% hp-musterloesung-20231207.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: Länge von Strings, Einfügen in Strings (Ergänzung)
\documentclass[a4paper]{article}
\usepackage{pgscript}
\usepackage{gnuplot-lua-tikz}
\begin{document}
\section*{Hardwarenahe Programmierung\\
Musterlösung zu den Übungsaufgaben -- 7.\ Dezember 2023}
\exercise{Länge von Strings}
Strings werden in der Programmiersprache C durch Zeiger auf \lstinline{char}-Variable realisiert.
Beispiel: \lstinline{char *hello_world = "Hello, world!\n"}
Die Systembibliothek stellt eine Funktion \lstinline{strlen()} zur Ermittlung der Länge von Strings\\
zur Verfügung (\lstinline{#include <string.h>}).
\begin{enumerate}[\quad(a)]
\item
Auf welche Weise ist die Länge eines Strings gekennzeichnet?
\points{1}
\item
Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"},
und wieviel Speicherplatz belegt sie?\\
\points{2}
\item
Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)},
die die Länge eines Strings zurückgibt.\\
\points{3}
\end{enumerate}
\goodbreak
Wir betrachten nun die folgenden Funktionen (Datei: \gitfile{hp}{2023ws/20231207}{aufgabe-1.c}):
\begin{center}
\begin{minipage}{8cm}
\begin{lstlisting}[gobble=8]
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
\end{lstlisting}
\end{minipage}%
\begin{minipage}{6cm}
\vspace*{-1cm}
\begin{lstlisting}[gobble=8]
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
\end{lstlisting}
\vspace*{-1cm}
\end{minipage}
\end{center}
\begin{enumerate}[\quad(a)]\setcounter{enumi}{3}
\item
Was bewirken die beiden Funktionen?
\points{2}
\item
Schreiben Sie eine eigene Funktion,
die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},\\
nur effizienter.
\points{4}
\item
Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen
hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String?
Begründen Sie Ihre Antwort.
Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen.
\points{3}
\item
Von welcher Ordnung (Landau-Symbol) ist Ihre effizientere Funktion?\\
Begründen Sie Ihre Antwort.
\points{1}
\end{enumerate}
\solution
\begin{itemize}
\item[(a)]
\textbf{Auf welche Weise ist die Länge eines Strings gekennzeichnet?}
Ein String ist ein Array von \lstinline{char}s.
Nach den eigentlichen Zeichen des Strings enthält das Array
\textbf{ein Null-Symbol} (Zeichen mit Zahlenwert 0,
nicht zu verwechseln mit der Ziffer \lstinline{'0'}) als Ende-Markierung.
Die Länge eines Strings ist die Anzahl der Zeichen
\emph{vor\/} diesem Symbol.
\item[(b)]
{\bf Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"},
und wieviel Speicherplatz belegt sie?}
Sie ist 14 Zeichen lang (\lstinline{'\n'} ist nur 1 Zeichen;
das Null-Symbol, das das Ende markiert, zählt hier nicht mit)
und belegt Speicherplatz für 15 Zeichen
(15 Bytes -- einschließlich Null-Symbol / Ende-Markierung).
\item[(c)]
\textbf{Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)},
die die Länge eines Strings zurückgibt.}
Siehe die Dateien \gitfile{hp}{2023ws/20231207}{loesung-1c-1.c} (mit Array-Index)
und \gitfile{hp}{2023ws/20231207}{loesung-1c-2.c} (mit Zeiger-Arithmetik).
Beide Lösungen sind korrekt und arbeiten gleich schnell.
Die Warnung \lstinline[style=terminal]{conflicting types for built-in function "strlen"}
kann normalerweise ignoriert werden;
auf manchen Systemen (z.\,B.\ MinGW) hat jedoch die eingebaute Funktion \lstinline{strlen()}
beim Linken Vorrang vor der selbstgeschriebenen,
so daß die selbstgeschriebene Funktion nie aufgerufen wird.
In solchen Fällen ist es zulässig, die selbstgeschriebene Funktion
anders zu nennen (z.\,B.\ \lstinline{my_strlen()}).
\item[(d)]
\textbf{Was bewirken die beiden Funktionen?}
Beide addieren die Zahlenwerte der im String enthaltenen Zeichen
und geben die Summe als Funktionsergebnis zurück.
Im Falle des Test-Strings \lstinline{"Hello, world!\n"}
lautet der Rückgabewert 1171 (siehe \gitfile{hp}{2023ws/20231207}{loesung-1d-1.c} und \gitfile{hp}{2023ws/20231207}{loesung-1d-2.c}).
\item[(e)]
\textbf{Schreiben Sie eine eigene Funktion,
die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},
nur effizienter.}
Die Funktion wird effizienter,
wenn man auf den Aufruf von \lstinline{strlen()} verzichtet
und stattdessen die Ende-Prüfung in derselben Schleife vornimmt,
in der man auch die Zahlenwerte der Zeichen des Strings aufsummiert.
Die Funktion \lstinline{fun_3()} in der Datei \gitfile{hp}{2023ws/20231207}{loesung-1e-1.c}
realisiert dies mit einem Array-Index,
Die Funktion \lstinline{fun_4()} in der Datei \gitfile{hp}{2023ws/20231207}{loesung-1e-2.c}
mit Zeiger-Arithmetik.
Beide Lösungen sind korrekt und arbeiten gleich schnell.
\textbf{Bemerkung:} Die effizientere Version der Funktion
arbeitet doppelt so schnell wie die ursprüngliche,
hat aber ebenfalls die Ordnung $\mathcal{O}(n)$ -- siehe unten.
\item[(f)]
\textbf{Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen
hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String?
Begründen Sie Ihre Antwort.
Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen.}
Vorüberlegung: \lstinline{strlen()} greift in einer Schleife
auf alle Zeichen des Strings der Länge $n$ zu,
hat also $\mathcal{O}(n)$.
\lstinline{fun_1()} ruft in jedem Schleifendurchlauf
(zum Prüfen der \lstinline{while}-Bedingung) einmal \lstinline{strlen()} auf
und greift anschließend auf ein Zeichen des Strings zu,
hat also $\mathcal{O}\bigl(n\cdot(n+1)\bigr) = \mathcal{O}(n^2)$.
\lstinline{fun_2()} ruft einmalig \lstinline{strlen()} auf
und greift anschließend in einer Schleife auf alle Zeichen des Strings zu,
hat also $\mathcal{O}(n+n) = \mathcal{O}(n)$.
\item[(g)]
\textbf{Von welcher Ordnung (Landau-Symbol) ist Ihre effizientere Funktion?\\
Begründen Sie Ihre Antwort.}
In beiden o.\,a.\ Lösungsvarianten
-- \gitfile{hp}{2023ws/20231207}{loesung-1e-1.c}
und \gitfile{hp}{2023ws/20231207}{loesung-1e-2.c} --
arbeitet die Funktion mit einer einzigen Schleife,
die gleichzeitig die Zahlenwerte addiert und das Ende des Strings sucht.
Mit jeweils einer einzigen Schleife
haben beide Funktionen die Ordnung $\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/20231207}{aufgabe-2.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/20231207}{loesung-2e.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/20231207}{loesung-2g.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}
File added
% hp-uebung-20231207.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: Länge von Strings, Einfügen in Strings (Ergänzung)
\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 -- 7.\ Dezember 2023}
Diese Übung enthält Punkteangaben wie in einer Klausur.
Um zu "`bestehen"', müssen Sie innerhalb von 70 Minuten
unter Verwendung ausschließlich zugelassener Hilfsmittel
12 Punkte (von insgesamt \totalpoints) erreichen.
\exercise{Länge von Strings}
Strings werden in der Programmiersprache C durch Zeiger auf \lstinline{char}-Variable realisiert.
Beispiel: \lstinline{char *hello_world = "Hello, world!\n"}
Die Systembibliothek stellt eine Funktion \lstinline{strlen()} zur Ermittlung der Länge von Strings\\
zur Verfügung (\lstinline{#include <string.h>}).
\begin{enumerate}[\quad(a)]
\item
Auf welche Weise ist die Länge eines Strings gekennzeichnet?
\points{1}
\item
Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"},
und wieviel Speicherplatz belegt sie?\\
\points{2}
\item
Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)},
die die Länge eines Strings zurückgibt.\\
\points{3}
\end{enumerate}
\goodbreak
Wir betrachten nun die folgenden Funktionen (Datei: \gitfile{hp}{2023ws/20231207}{aufgabe-1.c}):
\begin{center}
\begin{minipage}{8cm}
\begin{lstlisting}[gobble=8]
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
\end{lstlisting}
\end{minipage}%
\begin{minipage}{6cm}
\vspace*{-1cm}
\begin{lstlisting}[gobble=8]
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
\end{lstlisting}
\vspace*{-1cm}
\end{minipage}
\end{center}
\begin{enumerate}[\quad(a)]\setcounter{enumi}{3}
\item
Was bewirken die beiden Funktionen?
\points{2}
\item
Schreiben Sie eine eigene Funktion,
die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},\\
nur effizienter.
\points{4}
\item
Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen
hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String?
Begründen Sie Ihre Antwort.
Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen.
\points{3}
\item
Von welcher Ordnung (Landau-Symbol) ist Ihre effizientere Funktion?\\
Begründen Sie Ihre Antwort.
\points{1}
\end{enumerate}
\clearpage
\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/20231207}{aufgabe-2.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}
../common/landau-symbols-2.pdf
\ No newline at end of file
../common/landau-symbols-3.pdf
\ No newline at end of file
../common/landau-symbols.pdf
\ No newline at end of file
#include <stdio.h>
int strlen (char *s)
{
int l = 0;
while (s[l])
l++;
return l;
}
int main (void)
{
printf ("%d\n", strlen ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int strlen (char *s)
{
char *s0 = s;
while (*s)
s++;
return s - s0;
}
int main (void)
{
printf ("%d\n", strlen ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int strlen (char *s)
{
int l = 0;
while (s[l])
l++;
return l;
}
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
int main (void)
{
printf ("%d\n", fun_1 ("Hello, world!\n"));
printf ("%d\n", fun_2 ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int strlen (char *s)
{
char *s0 = s;
while (*s)
s++;
return s - s0;
}
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
int main (void)
{
printf ("%d\n", fun_1 ("Hello, world!\n"));
printf ("%d\n", fun_2 ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int fun_3 (char *s)
{
int i = 0, x = 0;
while (s[i])
x += s[i++];
return x;
}
int main (void)
{
printf ("%d\n", fun_3 ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int fun_4 (char *s)
{
int x = 0;
while (*s)
x += *s++;
return x;
}
int main (void)
{
printf ("%d\n", fun_4 ("Hello, world!\n"));
return 0;
}
#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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment