diff --git a/20221212/hp-20221212.pdf b/20221219/hp-20221219.pdf
similarity index 100%
rename from 20221212/hp-20221212.pdf
rename to 20221219/hp-20221219.pdf
diff --git a/20221212/hp-20221212.tex b/20221219/hp-20221219.tex
similarity index 100%
rename from 20221212/hp-20221212.tex
rename to 20221219/hp-20221219.tex
diff --git a/20221219/lists-1.c b/20221219/lists-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a04067e1403601ef56dd706d6148c1d386884e82
--- /dev/null
+++ b/20221219/lists-1.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+typedef struct
+{
+  int content;
+  node *next;
+} node;
+
+int main (void)
+{
+  return 0;
+}
diff --git a/20221219/lists-2.c b/20221219/lists-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..f27d1d5af7c0c237f0d0286155380ef9452a497a
--- /dev/null
+++ b/20221219/lists-2.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+typedef struct node
+{
+  int content;
+  struct node *next;
+} node;
+
+int main (void)
+{
+  return 0;
+}
diff --git a/20221219/lists-3.c b/20221219/lists-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c9029724efff25263813c5491add92504779d17
--- /dev/null
+++ b/20221219/lists-3.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+typedef struct node
+{
+  int content;
+  struct node *next;
+} node;
+
+int main (void)
+{
+  node node3 = { 3, NULL };
+  node node7 = { 7, NULL };
+  node node137 = { 137, NULL };
+
+  node *first = &node3;
+
+  for (node *p = first; p; p = p->next)
+    printf ("%d\n", p->content);
+
+  return 0;
+}
diff --git a/20221219/lists-4.c b/20221219/lists-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..e048736b85cc228c35f31644d003e00cdefc5496
--- /dev/null
+++ b/20221219/lists-4.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+typedef struct node
+{
+  int content;
+  struct node *next;
+} node;
+
+int main (void)
+{
+  node node3 = { 3, NULL };
+  node node7 = { 7, NULL };
+  node node137 = { 137, NULL };
+
+  node3.next = &node7;
+  node7.next = &node137;
+  node137.next = NULL;
+
+  node *first = &node3;
+
+  for (node *p = first; p; p = p->next)
+    printf ("%d\n", p->content);
+
+  return 0;
+}
diff --git a/20221219/lists-5.c b/20221219/lists-5.c
new file mode 100644
index 0000000000000000000000000000000000000000..a0cc620a884c133dd89582de726139091bc9c5d0
--- /dev/null
+++ b/20221219/lists-5.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+
+typedef struct node
+{
+  int content;
+  struct node *next;
+} node;
+
+int main (void)
+{
+  node node3 = { 3, NULL };
+  node node7 = { 7, NULL };
+  node node137 = { 137, NULL };
+
+  node3.next = &node7;
+  node7.next = &node137;
+  node137.next = NULL;
+
+  node node5 = { 5, NULL };
+  node5.next = node3.next;
+  node3.next = &node5;
+
+  node *first = &node3;
+
+  for (node *p = first; p; p = p->next)
+    printf ("%d\n", p->content);
+
+  return 0;
+}
diff --git a/20221219/logo-hochschule-bochum-cvh-text-v2.pdf b/20221219/logo-hochschule-bochum-cvh-text-v2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8
--- /dev/null
+++ b/20221219/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/20221219/logo-hochschule-bochum.pdf b/20221219/logo-hochschule-bochum.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1
--- /dev/null
+++ b/20221219/logo-hochschule-bochum.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum.pdf
\ No newline at end of file
diff --git a/20221212/pgslides.sty b/20221219/pgslides.sty
similarity index 100%
rename from 20221212/pgslides.sty
rename to 20221219/pgslides.sty
diff --git a/20221219/tree-01.c b/20221219/tree-01.c
new file mode 100644
index 0000000000000000000000000000000000000000..d347186a019709e416529c1b73c32f268e0fce57
--- /dev/null
+++ b/20221219/tree-01.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+typedef struct
+{
+  int content;
+  node *left, *right;
+} node;
+
+int main (void)
+{
+  node *root = NULL;
+  return 0;
+}
diff --git a/20221219/tree-02.c b/20221219/tree-02.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e591c3282329f0211c479dfa1b8c82f3dc755a3
--- /dev/null
+++ b/20221219/tree-02.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+int main (void)
+{
+  node *root = NULL;
+  return 0;
+}
diff --git a/20221219/tree-03.c b/20221219/tree-03.c
new file mode 100644
index 0000000000000000000000000000000000000000..b88b8671bbda9efe1031d09e3caa60ebeea8ccea
--- /dev/null
+++ b/20221219/tree-03.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+void insert (node *root, int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  root = p;
+}
+
+void output (node *root)
+{
+  if (root)
+    printf ("%d\n", root->content);
+}
+
+int main (void)
+{
+  node *root = NULL;
+  insert (root, 7);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-04.c b/20221219/tree-04.c
new file mode 100644
index 0000000000000000000000000000000000000000..db3b53dde184a82e1f85aa46e1f7e76b38e6b775
--- /dev/null
+++ b/20221219/tree-04.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+}
+
+void output (void)
+{
+  if (root)
+    printf ("%d\n", root->content);
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  output ();
+  return 0;
+}
diff --git a/20221219/tree-05.c b/20221219/tree-05.c
new file mode 100644
index 0000000000000000000000000000000000000000..628d8803131ca8ff163a085ee8ff4cb6ede0bc88
--- /dev/null
+++ b/20221219/tree-05.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      if (content > root->content)
+        root->right = p;
+      else
+        root->left = p;
+    }
+}
+
+void output (void)
+{
+  if (root)
+    printf ("%d\n", root->content);
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  output ();
+  return 0;
+}
diff --git a/20221219/tree-06.c b/20221219/tree-06.c
new file mode 100644
index 0000000000000000000000000000000000000000..f38634d004a020104e65e04cf437c87085dd0d18
--- /dev/null
+++ b/20221219/tree-06.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      if (content > root->content)
+        root->right = p;
+      else
+        root->left = p;
+    }
+}
+
+void output (void)
+{
+  if (root)
+    {
+      if (root->left)
+        printf ("%d\n", root->left->content);
+      printf ("%d\n", root->content);
+      if (root->right)
+        printf ("%d\n", root->right->content);
+    }
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  output ();
+  return 0;
+}
diff --git a/20221219/tree-07.c b/20221219/tree-07.c
new file mode 100644
index 0000000000000000000000000000000000000000..df1dd66b3e1a5892235bcaa894888f8becb4de85
--- /dev/null
+++ b/20221219/tree-07.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      node *save_root = root;
+      if (content > root->content)
+        {
+          root = root->left;
+          insert (content);
+        }
+      else
+        {
+          root = root->right;
+          insert (content);
+        }
+      root = save_root;
+    }
+}
+
+void output (void)
+{
+  if (root)
+    {
+      if (root->left)
+        {
+          node *save_root = root;
+          root = root->left;
+          output ();
+          root = save_root;
+        }
+      printf ("%d\n", root->content);
+      if (root->right)
+        {
+          node *save_root = root;
+          root = root->right;
+          output ();
+          root = save_root;
+        }
+    }
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  insert (1117);
+  insert (42);
+  insert (13);
+  output ();
+  return 0;
+}
diff --git a/20221219/tree-08.c b/20221219/tree-08.c
new file mode 100644
index 0000000000000000000000000000000000000000..fd3cafcad82fb4b9bbc6d7c905c1005d7c202f6e
--- /dev/null
+++ b/20221219/tree-08.c
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      node *save_root = root;
+      if (content > root->content)
+        {
+          root = root->left;
+          insert (content);
+          save_root->left = root;
+        }
+      else
+        {
+          root = root->right;
+          insert (content);
+          save_root->right = root;
+        }
+      root = save_root;
+    }
+}
+
+void output (void)
+{
+  if (root)
+    {
+      if (root->left)
+        {
+          node *save_root = root;
+          root = root->left;
+          output ();
+          root = save_root;
+        }
+      printf ("%d\n", root->content);
+      if (root->right)
+        {
+          node *save_root = root;
+          root = root->right;
+          output ();
+          root = save_root;
+        }
+    }
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  insert (1117);
+  insert (42);
+  insert (13);
+  output ();
+  return 0;
+}
diff --git a/20221219/tree-09.c b/20221219/tree-09.c
new file mode 100644
index 0000000000000000000000000000000000000000..6b44c1108c747f4e6021ddf92d771d77288af18d
--- /dev/null
+++ b/20221219/tree-09.c
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      node *save_root = root;
+      if (content < root->content)
+        {
+          root = root->left;
+          insert (content);
+          save_root->left = root;
+        }
+      else
+        {
+          root = root->right;
+          insert (content);
+          save_root->right = root;
+        }
+      root = save_root;
+    }
+}
+
+void output (void)
+{
+  if (root)
+    {
+      if (root->left)
+        {
+          node *save_root = root;
+          root = root->left;
+          output ();
+          root = save_root;
+        }
+      printf ("%d\n", root->content);
+      if (root->right)
+        {
+          node *save_root = root;
+          root = root->right;
+          output ();
+          root = save_root;
+        }
+    }
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  insert (1117);
+  insert (42);
+  insert (13);
+  output ();
+  return 0;
+}
diff --git a/20221219/tree-10.c b/20221219/tree-10.c
new file mode 100644
index 0000000000000000000000000000000000000000..26a5575d8c0dbd139b08ca9365ad0a667223841b
--- /dev/null
+++ b/20221219/tree-10.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      node *save_root = root;
+      if (content < root->content)
+        {
+          root = root->left;
+          insert (content);
+          save_root->left = root;
+        }
+      else
+        {
+          root = root->right;
+          insert (content);
+          save_root->right = root;
+        }
+      root = save_root;
+    }
+}
+
+void output (node *root)
+{
+  if (root)
+    {
+      if (root->left)
+        output (root->left);
+      printf ("%d\n", root->content);
+      if (root->right)
+        output (root->right);
+    }
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  insert (1117);
+  insert (42);
+  insert (13);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-11.c b/20221219/tree-11.c
new file mode 100644
index 0000000000000000000000000000000000000000..508b24316bf6696abc9225fac3fe7ef398a7e094
--- /dev/null
+++ b/20221219/tree-11.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      node *save_root = root;
+      if (content < root->content)
+        {
+          root = root->left;
+          insert (content);
+          save_root->left = root;
+        }
+      else
+        {
+          root = root->right;
+          insert (content);
+          save_root->right = root;
+        }
+      root = save_root;
+    }
+}
+
+void output (node *root)
+{
+  if (root)
+    {
+      output (root->left);
+      printf ("%d\n", root->content);
+      output (root->right);
+    }
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  insert (1117);
+  insert (42);
+  insert (13);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-12.c b/20221219/tree-12.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff07e64e6dceb10266dc6d376d68fd15bc59e68b
--- /dev/null
+++ b/20221219/tree-12.c
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      node *save_root = root;
+      if (content < root->content)
+        {
+          root = root->left;
+          insert (content);
+          save_root->left = root;
+        }
+      else
+        {
+          root = root->right;
+          insert (content);
+          save_root->right = root;
+        }
+      root = save_root;
+    }
+}
+
+void output (node *root)
+{
+  if (root)
+    {
+      output (root->left);
+      printf ("%d\n", root->content);
+      output (root->right);
+    }
+}
+
+int main (void)
+{
+  insert (7);
+  insert (137);
+  insert (3);
+  insert (1117);
+  insert (42);
+  insert (13);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-13.c b/20221219/tree-13.c
new file mode 100644
index 0000000000000000000000000000000000000000..236930ed75a80984bfe343a582320470180db3ad
--- /dev/null
+++ b/20221219/tree-13.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+node *insert (node *root, int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    return p;
+  else
+    {
+      if (content < root->content)
+        {
+          root->left = insert (root->left, content);
+          return root;
+        }
+      else
+        {
+          root->right = insert (root->right, content);
+          return root;
+        }
+    }
+}
+
+void output (node *root)
+{
+  if (root)
+    {
+      output (root->left);
+      printf ("%d\n", root->content);
+      output (root->right);
+    }
+}
+
+int main (void)
+{
+  root = insert (root, 7);
+  root = insert (root, 137);
+  root = insert (root, 3);
+  root = insert (root, 1117);
+  root = insert (root, 42);
+  root = insert (root, 13);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-14.c b/20221219/tree-14.c
new file mode 100644
index 0000000000000000000000000000000000000000..a95a1fc5acec20d7fa0fcf714af2d5d746899c1c
--- /dev/null
+++ b/20221219/tree-14.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+node *insert (node *root, int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    return p;
+  else
+    {
+      if (content < root->content)
+        {
+          root->left = insert (root->left, content);
+          return root;
+        }
+      else
+        {
+          root->right = insert (root->right, content);
+          return root;
+        }
+    }
+}
+
+void output (node *root)
+{
+  if (root)
+    {
+      output (root->left);
+      printf ("%d\n", root->content);
+      output (root->right);
+    }
+}
+
+int main (void)
+{
+  insert (root, 7);
+  insert (root, 137);
+  insert (root, 3);
+  insert (root, 1117);
+  insert (root, 42);
+  insert (root, 13);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-15.c b/20221219/tree-15.c
new file mode 100644
index 0000000000000000000000000000000000000000..929d253f77de0cc15a6707dd499420965eb9daca
--- /dev/null
+++ b/20221219/tree-15.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+void insert (node **root, int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (*root == NULL)
+    *root = p;
+  else
+    {
+      if (content < root->content)
+        insert (&root->left, content);
+      else
+        insert (&root->right, content);
+    }
+}
+
+void output (node *root)
+{
+  if (root)
+    {
+      output (root->left);
+      printf ("%d\n", root->content);
+      output (root->right);
+    }
+}
+
+int main (void)
+{
+  node *root = NULL;
+  insert (&root, 7);
+  insert (&root, 137);
+  insert (&root, 3);
+  insert (&root, 1117);
+  insert (&root, 42);
+  insert (&root, 13);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-16.c b/20221219/tree-16.c
new file mode 100644
index 0000000000000000000000000000000000000000..be7163d4fdf57b897887bb861418e342e5061961
--- /dev/null
+++ b/20221219/tree-16.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+void insert (node **root, int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (*root == NULL)
+    *root = p;
+  else
+    {
+      if (content < (*root)->content)
+        insert (&(*root)->left, content);
+      else
+        insert (&(*root)->right, content);
+    }
+}
+
+void output (node *root)
+{
+  if (root)
+    {
+      output (root->left);
+      printf ("%d\n", root->content);
+      output (root->right);
+    }
+}
+
+int main (void)
+{
+  node *root = NULL;
+  insert (&root, 7);
+  insert (&root, 137);
+  insert (&root, 3);
+  insert (&root, 1117);
+  insert (&root, 42);
+  insert (&root, 13);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-16a.cpp b/20221219/tree-16a.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e11b48316a1ecae2c3263f85ee7e2c3616b3e912
--- /dev/null
+++ b/20221219/tree-16a.cpp
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+void insert (node *&root, int content)
+{
+  node *p = (node *) malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  if (root == NULL)
+    root = p;
+  else
+    {
+      if (content < root->content)
+        insert (root->left, content);
+      else
+        insert (root->right, content);
+    }
+}
+
+void output (node *root)
+{
+  if (root)
+    {
+      output (root->left);
+      printf ("%d\n", root->content);
+      output (root->right);
+    }
+}
+
+int main (void)
+{
+  node *root = NULL;
+  insert (root, 7);
+  insert (root, 137);
+  insert (root, 3);
+  insert (root, 1117);
+  insert (root, 42);
+  insert (root, 13);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-3a.c b/20221219/tree-3a.c
new file mode 100644
index 0000000000000000000000000000000000000000..8031ec72af9bcb97b83c46b296ab5f2464832fcd
--- /dev/null
+++ b/20221219/tree-3a.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+void insert (node *root, int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  root = p;
+}
+
+void output (node *root)
+{
+  if (root)
+    printf ("%d\n", root->content);
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  node *root = NULL;
+  insert (root, 7);
+  output (root);
+  return 0;
+}
diff --git a/20221219/tree-3b.c b/20221219/tree-3b.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b47c41b61d5a76380bccefc98f2fd3057ad645b
--- /dev/null
+++ b/20221219/tree-3b.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *root = NULL;
+
+void insert (int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  root = p;
+}
+
+void output (void)
+{
+  if (root)
+    printf ("%d\n", root->content);
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  insert (7);
+  output ();
+  return 0;
+}
diff --git a/20221219/tree-3c.c b/20221219/tree-3c.c
new file mode 100644
index 0000000000000000000000000000000000000000..63ffbaa792e5bc4d122f96e5cfd32e7579c2077c
--- /dev/null
+++ b/20221219/tree-3c.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *left, *right;
+} node;
+
+node *insert (node *root, int content)
+{
+  node *p = malloc (sizeof (node));
+  p->content = content;
+  p->left = NULL;
+  p->right = NULL;
+  return p;
+}
+
+void output (node *root)
+{
+  if (root)
+    printf ("%d\n", root->content);
+  else
+    printf ("root is NULL\n");
+}
+
+int main (void)
+{
+  node *root = NULL;
+  root = insert (root, 7);
+  output (root);
+  return 0;
+}
diff --git a/20230109/aufgabe-1.c b/20230109/aufgabe-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..f26ce5d665012e2cdbaac8b0f43f01d40f338254
--- /dev/null
+++ b/20230109/aufgabe-1.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *next;
+} node;
+
+void output_list (node *first)
+{
+  for (node *p = first; p; p = p->next)
+    printf ("%d ", p->content);
+  printf ("\n");
+}
+
+void insert_into_list (node *what, node *where)
+{
+  what->next = where->next;
+  where->next = what;
+}
+
+int main (void)
+{
+  node *element3 = malloc (sizeof (node));
+  node *element7 = malloc (sizeof (node));
+  node *element137 = malloc (sizeof (node));
+
+  element3->content = 3;
+  element7->content = 7;
+  element137->content = 137;
+
+  node *first = element3;
+  element3->next = element7;
+  element7->next = element137;
+  element137->next = NULL;
+
+  output_list (first);
+
+  node *element5 = malloc (sizeof (node));
+  element5->content = 5;
+  insert_into_list (element5, element3);
+
+  output_list (first);
+
+  return 0;
+}
diff --git a/20230109/aufgabe-3.c b/20230109/aufgabe-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b0cb23fdd5ee15a4403808c18d2104ed49caf3f
--- /dev/null
+++ b/20230109/aufgabe-3.c
@@ -0,0 +1,62 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 320
+#define HEIGHT 240
+
+double t = 0.0;
+double dt = 0.2;
+
+int r = 5;
+
+double x = 10;
+double y = 200;
+double vx = 20;
+double vy = -60;
+double g = 9.81;
+
+gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
+{
+  GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
+
+  gdk_cairo_set_source_rgba (c, &blue);
+  cairo_arc (c, x, y, r, 0, 2 * G_PI);
+  cairo_fill (c);
+
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  t += dt;
+  x += vx * dt;
+  y += vy * dt;
+  vx = vx;
+  vy = 0.5 * g * (t * t);
+  if (y + r >= HEIGHT)
+    vy = -vy * 0.9;
+  if (x + r >= WIDTH)
+    vx = -vx * 0.9;
+  if (x - r <= 0)
+    vx = -vx * 0.9;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (50, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_widget_show (window);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_widget_show (drawing_area);
+  gtk_container_add (GTK_CONTAINER (window), drawing_area);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  gtk_main ();
+  return 0;
+}
diff --git a/20230109/aufgabe-4.c b/20230109/aufgabe-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..2bcd5e63a71f212b7243d1f7d9c92406d1e41e77
--- /dev/null
+++ b/20230109/aufgabe-4.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+int main (void)
+{
+  char buffer[100];
+  fgets (buffer, 100, stdin);
+  for (char *p = buffer; *p; p++)
+    printf ("%02x", *p);
+  printf ("\n");
+}
diff --git a/20230109/hp-musterloesung-20230109.pdf b/20230109/hp-musterloesung-20230109.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..fecb1322d2d38ae43542bdc5fe222115f6503eba
Binary files /dev/null and b/20230109/hp-musterloesung-20230109.pdf differ
diff --git a/20230109/hp-musterloesung-20230109.tex b/20230109/hp-musterloesung-20230109.tex
new file mode 100644
index 0000000000000000000000000000000000000000..a10d64ce3bff36aae2a0a9c59bc18a3beacd64c3
--- /dev/null
+++ b/20230109/hp-musterloesung-20230109.tex
@@ -0,0 +1,636 @@
+% hp-musterloesung-20230109.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: Einfach und doppelt verkettete Listen, ternärer Baum, hüpfender Ball, Hexdumps
+
+% ! Hüpfender Ball (20211206-3)
+% ! Hexdumps (20220110-3)
+% ! einfach und doppelt verkettete Listen (20220117-2)
+% ! ternärer Baum (20220117-3)
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+\usepackage{tikz}
+
+\begin{document}
+
+  \section*{Hardwarenahe Programmierung\\
+            Musterlösung zu den Übungsaufgaben -- 9.\ Januar 2023}
+
+  \exercise{Einfach und doppelt verkettete Listen}
+
+  Das Beispiel-Programm \gitfile{hp}{2022ws/20230109}{aufgabe-1.c}
+  demonstriert zwei Funktionen zur Verwaltung einfach verketteter Listen:
+  \lstinline{output_list()} zum Ausgeben der Liste auf den Bildschirm und
+  \lstinline{insert_into_list()} zum Einfügen in die Liste.
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Ergänzen Sie eine Funktion \lstinline{delete_from_list()}
+      zum Löschen eines Elements aus der Liste
+      mit Freigabe des Speicherplatzes.
+      \points{5}
+    \item
+      Ergänzen Sie eine Funktion \lstinline{reverse_list()}
+      die die Reihenfolge der Elemente in der Liste umdreht.\\
+      \points{3}
+  \end{enumerate}
+
+  Eine doppelt verkettete Liste hat in jedem Knotenpunkt (\lstinline{node})
+  \emph{zwei\/} Zeiger -- einen auf das nächste Element (\lstinline{next})
+  und einen auf das vorherige Element (z.\,B.\ \lstinline{prev} für "`previous"').
+  Dadurch ist es leichter als bei einer einfach verketteten Liste,
+  die Liste in umgekehrter Reihenfolge durchzugehen.
+
+  \begin{quote}
+    \begin{tikzpicture}
+      \color{blendedblue}
+      \node(first) at (0,3.5) {first};
+      \node(NULL1) at (-1,1.25) {NULL};
+      \node[shape=rectangle,draw,line width=1pt](3) at (1,2) {3};
+      \node[shape=rectangle,draw,line width=1pt](7) at (3,2) {7};
+      \node[shape=rectangle,draw,line width=1pt](137) at (5,2) {137};
+      \node(NULL2) at (7,2.75) {NULL};
+      \draw[-latex](first)--(3);
+      \draw[-latex](3) to[out=45,in=135] (7);
+      \draw[-latex](3) to[out=-135,in=0] (NULL1);
+      \draw[-latex](7) to[out=-135,in=-45] (3);
+      \draw[-latex](7) to[out=45,in=135] (137);
+      \draw[-latex](137) to[out=-135,in=-45] (7);
+      \draw[-latex](137) to[out=45,in=180] (NULL2);
+    \end{tikzpicture}
+  \end{quote}
+
+  Der Rückwärts-Zeiger (\lstinline{prev}) des ersten Elements zeigt,
+  genau wie der Vorwärts-Zeiger (\lstinline{next}) des letzten Elements,
+  auf \emph{nichts}, hat also den Wert \lstinline{NULL}.
+
+  \begin{enumerate}[\quad(a)]\setcounter{enumi}{2}
+    \item
+      Schreiben Sie das Programm um für doppelt verkettete Listen.
+      \points{5}
+  \end{enumerate}
+
+  \solution
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      \textbf{Ergänzen Sie eine Funktion \lstinline{delete_from_list()}
+      zum Löschen eines Elements aus der Liste
+      mit Freigabe des Speicherplatzes.}
+
+      Siehe: \gitfile{hp}{2022ws/20230109}{loesung-1a.c}
+
+      Um ein Element aus einer verketteten Liste zu löschen,
+      müssen zuerst die Zeiger umgestellt werden,
+      um das Element von der Liste auszuschließen.
+      Erst danach darf der Speicherplatz für das Element freigegeben werden.
+
+%      Da das Beispielprogramm (\gitfile{hp}{2021ws/20220117}{lists-5.c})
+%      nicht mit dynamischem Speicher arbeitet,
+%      stellen wir dieses zunächst auf dynamischen Speicher um, z.\,B.:
+%      \begin{lstlisting}[gobble=8]
+%        node *element5 = malloc (sizeof (node));
+%      \end{lstlisting}
+%      Danach bezeichnet \lstinline{element5}
+%      die Adresse der \lstinline{struct}-Variablen;
+%      es wird also \lstinline{element5} an die Funktionen übergeben
+%      und nicht \lstinline{&element5} (die Adresse des Zeigers).
+
+%      Um nun ein Element aus der Liste zu entfernen,
+%      benötigt man
+      Man benötigt also
+      \emph{das vorherige Element},
+      dessen \lstinline{next}-Zeiger man dann auf
+      das übernächste Element \lstinline{next->next} weitersetzt.
+
+      Bei jedem Zeiger muß man vor dem Zugriff prüfen,
+      daß dieser nicht auf \lstinline{NULL} zeigt.
+      (Die Musterlösung ist in dieser Hinsicht nicht konsequent.
+      Für den Produktiveinsatz müßte z.\,B.\ \lstinline{delete_from_list()}
+      auch den übergebenen Zeiger \lstinline{what} auf \lstinline{NULL} prüfen.)
+
+      Ein Spezialfall tritt ein, wenn das erste Element einer Liste
+      entfernt werden soll. In diesem Fall tritt \lstinline{first}
+      an die Stelle des \lstinline{next}-Zeigers
+      des (nicht vorhandenen) vorherigen Elements.
+      Da \lstinline{delete_from_list()} \emph{schreibend\/} auf \lstinline{first}
+      zugreift, muß \lstinline{first} \emph{als Zeiger\/} übergeben werden
+      (\lstinline{node **first}).
+
+      Um alle Spezialfälle zu testen (am Anfang, am Ende und in der Mitte der Liste),
+      wurden die Testfälle im Hauptprogramm erweitert.
+
+    \item
+      \textbf{Schreiben Sie das Programm um für doppelt verkettete Listen.}
+
+      Siehe: \gitfile{hp}{2022ws/20230109}{loesung-1b.c}
+
+      Bei allen Einfüge- und Löschaktionen müssen \emph{jeweils zwei\/}
+      \lstinline{next}- und \lstinline{prev}-Zeiger neu gesetzt werden.
+
+      Zum Debuggen empfiehlt es sich sehr,
+      eine Funktion zu schreiben, die die Liste auf Konsistenz prüft
+      (hier: \lstinline{check_list()}).
+
+      Das Testprogramm macht von der Eigenschaft der doppelt verketteten Liste,
+      daß man sie auch rückwärts effizient durchgehen kann, keinen Gebrauch.
+      Um diese Eigenschaft als Vorteil nutzen zu können, empfiehlt es sich,
+      zusätzlich zu \lstinline{first}
+      auch einen Zeiger auf das letzte Element (z.\,B.\ \lstinline{last})
+      einzuführen. Dieser muß dann natürlich bei allen Operationen
+      (Einfügen, Löschen, \dots) auf dem aktuellen Stand gehalten werden.
+
+  \end{enumerate}
+
+  \exercise{Ternärer Baum}
+
+  Der in der Vorlesung vorgestellte \newterm{binäre Baum\/}
+  ist nur ein Spezialfall;
+  im allgemeinen können Bäume auch mehr als zwei Verzweigungen
+  pro Knotenpunkt haben.
+  Dies ist nützlich bei der Konstruktion \emph{balancierter Bäume},
+  also solcher, die auch im \emph{Worst Case\/}
+  nicht zu einer linearen Liste entarten,
+  sondern stets eine -- möglichst flache -- Baumstruktur behalten.
+
+  Wir betrachten einen Baum mit bis zu drei Verzweigungen pro Knotenpunkt,
+  einen sog.\ \newterm{ternären Baum}.
+  Jeder Knoten enthält dann nicht nur einen,
+  sondern \emph{zwei\/} Werte als Inhalt:
+  \begin{lstlisting}
+    typedef struct node
+    {
+      int content_left, content_right;
+      struct node *left, *middle, *right;
+    } node;
+  \end{lstlisting}
+
+  Wir konstruieren nun einen Baum nach folgenden Regeln:
+  \vspace{-\medskipamount}
+  \begin{itemize}\itemsep0pt
+    \item
+      Innerhalb eines Knotens sind die Werte sortiert:
+      \lstinline{content_left} muß stets kleiner sein als \lstinline{content_right}.
+    \item
+      Der Zeiger \lstinline{left} zeigt auf Knoten,
+      deren enthaltene Werte durchweg kleiner sind als \lstinline{content_left}.
+    \item
+      Der Zeiger \lstinline{right} zeigt auf Knoten,
+      deren enthaltene Werte durchweg größer sind als \lstinline{content_right}.
+    \item
+      Der Zeiger \lstinline{middle} zeigt auf Knoten,
+      deren enthaltene Werte durchweg größer sind als \lstinline{content_left},
+      aber kleiner als \lstinline{content_right}.
+    \item
+      Ein Knoten muß nicht immer mit zwei Werten voll besetzt sein;
+      er darf auch \emph{nur einen\/} gültigen Wert enthalten.
+
+      Der Einfachheit halber lassen wir in diesem Beispiel
+      nur positive Zahlen als Werte zu.
+      Wenn ein Knoten nur einen Wert enthält,
+      setzen wir \lstinline{content_right = -1},
+      und der Zeiger \lstinline{middle} wird nicht verwendet.
+    \item
+      Wenn wir neue Werte in den Baum einfügen,
+      werden \emph{zuerst\/} die nicht voll besetzten Knoten aufgefüllt
+      und \emph{danach erst\/} neue Knoten angelegt und Zeiger gesetzt.
+    \item
+      Beim Auffüllen eines Knotens darf nötigenfalls \lstinline{content_left}
+      nach \lstinline{content_right} verschoben werden.
+      Ansonsten werden einmal angelegte Knoten nicht mehr verändert.
+  \end{itemize}
+  \vspace*{-\medskipamount}
+  (In der Praxis dürfen Knoten gemäß speziellen Regeln
+  nachträglich verändert werden,
+  um Entartungen gar nicht erst entstehen zu lassen --
+  siehe z.\,B.\ \url{https://en.wikipedia.org/wiki/2-3_tree}.)
+  \begin{enumerate}[\quad(a)]
+    \item
+      Zeichnen Sie ein Schaubild, das veranschaulicht,
+      wie die Zahlen 7, 137, 3, 5, 6, 42, 1, 2 und 12
+      nacheinander und in dieser Reihenfolge
+      in den oben beschriebenen Baum eingefügt werden
+      -- analog zu den Vortragsfolien (\gitfile{hp}{2022ws/20221219}{hp-20221219.pdf}),
+      Seite 33.
+      \points{3}
+      %
+      % Lösung:
+      %
+      %           7 137
+      %         /   |
+      %      3 5  12 42
+      %     /   \
+      %   1 2    6
+      %
+      % (NULL-Zeiger sind hier nicht dargestellt,
+      % gehören aber dazu.)
+      %
+    \item
+      Dasselbe, aber in der Reihenfolge 
+      2, 7, 42, 12, 1, 137, 5, 6, 3.
+      \points{3}
+      %
+      % Lösung:
+      %
+      %           2 7
+      %         /  |  \
+      %       1   5 6  12 42
+      %         /           \
+      %        3             137
+      %
+      % (NULL-Zeiger sind hier wieder nicht dargestellt,
+      % gehören aber dazu.)
+      %
+    \item
+      Beschreiben Sie in Worten und/oder als C-Quelltext-Fragment,
+      wie eine Funktion aussehen müßte, um den auf diese Weise entstandenen Baum
+      sortiert auszugeben.
+      \points{4}
+  \end{enumerate}
+
+  \solution
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      \textbf{Zeichnen Sie ein Schaubild, das veranschaulicht,
+      wie die Zahlen 7, 137, 3, 5, 6, 42, 1, 2 und 12
+      nacheinander und in dieser Reihenfolge
+      in den oben beschriebenen Baum eingefügt werden
+      -- analog zu den Vortragsfolien (\gitfile{hp}{2022ws/20221219}{hp-20221219.pdf}),
+      Seite 21.}
+      %
+      % Lösung:
+      %
+      %           7 137
+      %         /   |
+      %      3 5  12 42
+      %     /   \
+      %   1 2    6
+      %
+      % (NULL-Zeiger sind hier nicht dargestellt,
+      % gehören aber dazu.)
+      %
+      \begin{center}
+        \newcommand{\x}{~\makebox(0,0){\raisebox{0.7em}{\rule{1pt}{1.4em}}}~}
+        \begin{tikzpicture}
+          \color{blendedblue}
+          \node(root) at (0,0) {\lstinline{node *root;}};
+          \node[shape=rectangle,draw,line width=1pt](7-137) at (0,-1.5) {7\x 137};
+          \draw[-latex](root)--(7-137);
+          \node[shape=rectangle,draw,line width=1pt](3-5) at (-2,-3) {3\x 5};
+          \draw[-latex](7-137)--(3-5);
+          \node[shape=rectangle,draw,line width=1pt](12-42) at (0,-3) {12\x 42};
+          \draw[-latex](7-137)--(12-42);
+          \node[shape=rectangle,draw,line width=1pt](1-2) at (-4,-4.5) {1\x 2};
+          \draw[-latex](3-5)--(1-2);
+          \node[shape=rectangle,draw,line width=1pt](6) at (0,-4.5) {6};
+          \draw[-latex](3-5)--(6);
+        \end{tikzpicture}
+      \end{center}
+      Bemerkungen:
+      \begin{itemize}
+        \item
+          Zeiger mit dem Wert \lstinline{NULL} sind nicht dargestellt:
+          \lstinline{right}-Zeiger von 7/137,
+          \lstinline{middle}-Zeiger von 3/5,
+          sämtliche Zeiger von 1/2, 12/42 und 6.
+        \item
+          Beim Einfügen der 12 wird die sich bereits vorher in diesem
+          \lstinline{node} befindliche 42 zu \lstinline{content_right},
+          und die 12 wird das neue \lstinline{content_left}.
+        \item
+          Dieser Baum hat sehr einfache Regeln und ist daher \emph{nicht\/}
+          balanciert. Insbesondere unsere Regel, daß einmal angelegte Knoten
+          nicht mehr verändert werden dürfen, steht dem im Wege.
+          Ein einfaches Beispiel für einen \emph{balancierten\/} ternären
+          Baum ist der 2-3-Baum -- siehe z.\,B.\ \url{https://en.wikipedia.org/wiki/2-3_tree}.
+      \end{itemize}
+    \goodbreak
+    \item
+      \textbf{Dasselbe, aber in der Reihenfolge 
+      2, 7, 42, 12, 1, 137, 5, 6, 3.}
+      %
+      % Lösung:
+      %
+      %           2 7
+      %         /  |  \
+      %       1   5 6  12 42
+      %         /           \
+      %        3             137
+      %
+      % (NULL-Zeiger sind hier wieder nicht dargestellt,
+      % gehören aber dazu.)
+      %
+      \begin{center}
+        \newcommand{\x}{~\makebox(0,0){\raisebox{0.7em}{\rule{1pt}{1.4em}}}~}
+        \begin{tikzpicture}
+          \color{blendedblue}
+          \node(root) at (0,0) {\lstinline{node *root;}};
+          \node[shape=rectangle,draw,line width=1pt](2-7) at (0,-1.5) {2\x 7};
+          \draw[-latex](root)--(7-137);
+          \node[shape=rectangle,draw,line width=1pt](1) at (-2,-3) {1};
+          \draw[-latex](2-7)--(1);
+          \node[shape=rectangle,draw,line width=1pt](5-6) at (0,-3) {5\x 6};
+          \draw[-latex](2-7)--(5-6);
+          \node[shape=rectangle,draw,line width=1pt](3) at (-2,-4.5) {3};
+          \draw[-latex](5-6)--(3);
+          \node[shape=rectangle,draw,line width=1pt](12-42) at (2,-3) {12\x 42};
+          \draw[-latex](2-7)--(12-42);
+          \node[shape=rectangle,draw,line width=1pt](137) at (4,-4.5) {137};
+          \draw[-latex](12-42)--(137);
+        \end{tikzpicture}
+      \end{center}
+      Bemerkungen:
+      \begin{itemize}
+        \item
+          Wieder sind Zeiger mit dem Wert \lstinline{NULL} nicht dargestellt:
+          \lstinline{middle}- und \lstinline{right}-Zeiger von 5/6,
+          \lstinline{left}- und \lstinline{middle}-Zeiger von 12/42,
+          sämtliche Zeiger von 1, 3 und 137.
+        \item
+          Beim Einfügen der 12 wird wieder die sich bereits vorher in diesem
+          \lstinline{node} befindliche 42 zu \lstinline{content_right},
+          und die 12 wird das neue \lstinline{content_left}.
+      \end{itemize}
+    \item
+      \textbf{Beschreiben Sie in Worten und/oder als C-Quelltext-Fragment,
+      wie eine Funktion aussehen müßte, um den auf diese Weise entstandenen Baum
+      sortiert auszugeben.}
+
+      Die entscheidende Idee ist \textbf{Rekursion}.
+
+      Eine Funktion, die den gesamten Baum ausgibt,
+      müßte einmalig für den Zeiger \lstinline{root} aufgerufen werden
+      und folgendes tun:
+      \begin{enumerate}[\quad 1.]
+        \item
+          falls der übergebene Zeiger den Wert \lstinline{NULL} hat,
+          nichts ausgeben, sondern die Funktion direkt beenden,
+        \item
+          sich selbst für den \lstinline{left}-Zeiger aufrufen,
+        \item
+          den Wert von \lstinline{content_left} ausgeben,
+        \item
+          sich selbst für den \lstinline{middle}-Zeiger aufrufen,
+        \item
+          sofern vorhanden (also ungleich \lstinline{-1}),
+          den Wert von \lstinline{content_right} ausgeben,
+        \item
+          sich selbst für den \lstinline{right}-Zeiger aufrufen.
+      \end{enumerate}
+      Als C-Fragment:
+      \begin{lstlisting}[gobble=8]
+        void output_tree (node *root)
+        {
+          if (root)
+            {
+              output_tree (root->left);
+              printf ("%d\n", root->content_left);
+              output_tree (root->middle);
+              if (root->content_right >= 0)
+                printf ("%d\n", root->content_right);
+              output_tree (root->right);
+            }
+        }
+      \end{lstlisting}
+      Die Datei \gitfile{hp}{2022ws/20230109}{loesung-2c.c} erweitert dieses Fragment
+      zu einem vollständigen C-Programm zum Erstellen und sortierten Ausgeben
+      eines ternären Baums mit den Zahlenwerten von Aufgabenteil (a).
+  \end{enumerate}
+
+  \exercise{Fehlerhaftes Programm: Hüpfender Ball}
+
+  Das auf der nächsten Seite abgedruckte GTK+-Programm
+  (Datei: \gitfile{hp}{2022ws/20230109}{aufgabe-3.c}) soll einen
+  hüpfenden Ball darstellen, ist jedoch fehlerhaft.
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Warum sieht man lediglich ein leeres Fenster?
+      Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben?
+      \points{3}
+    \item
+      Nach der Fehlerbehebung in Aufgabenteil (a)
+      zeigt das Programm einen unbeweglichen Ball.
+      Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben, und warum?
+      \points{2}
+    \item
+      Erklären Sie das merkwürdige Hüpfverhalten des Balls.
+      Wie kommt es zustande?
+      Was an diesem Verhalten ist korrekt, und was ist fehlerhaft? \points{5}
+    \item
+      Welche Befehle muß man in welcher Weise ändern,
+      um ein realistischeres Hüpf-Verhalten zu bekommen? \points{2}
+  \end{enumerate}
+
+  Hinweis: Das Hinzuziehen von Beispiel-Programmen aus der Vorlesung
+  ist ausdrücklich erlaubt -- auch in der Klausur.
+
+  Allgemeiner Hinweis:
+  Wenn Sie die Übungsaufgaben zu dieser Lehrveranstaltung
+  als PDF-Datei betrachten und darin auf die Dateinamen klicken,
+  können Sie die Beispiel-Programme direkt herunterladen.
+  Dadurch vermeiden Sie Übertragungsfehler.
+
+  \solution
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      \textbf{Warum sieht man lediglich ein leeres Fenster?
+      Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben?}
+
+      Die für das Zeichnen zuständige Callback-Funktion wurde zwar geschrieben,
+      aber nicht installiert.
+      Um dies zu beheben, ergänze man den folgenden Befehl im Hauptprogramm:
+
+      \lstinline{g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);}
+
+      Dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
+      \gitfile{hp}{2022ws/20221114}{gtk-13.c}.
+
+    \item
+      \textbf{Nach der Fehlerbehebung in Aufgabenteil (a)
+      zeigt das Programm einen unbeweglichen Ball.
+      Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben, und warum?}
+
+      Die Timer-Callback-Funktion wurde zwar geschrieben, aber nicht installiert.
+      Um dies zu beheben, ergänze man den folgenden Befehl im Hauptprogramm:
+
+      \lstinline{g_timeout_add (50, (GSourceFunc) timer, drawing_area);}
+
+      Auch dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
+      \gitfile{hp}{2022ws/20221114}{gtk-13.c}.
+
+    \item
+      \textbf{Erklären Sie das merkwürdige Hüpfverhalten des Balls.
+      Wie kommt es zustande?
+      Was an diesem Verhalten ist korrekt, und was ist fehlerhaft?}
+
+      Die Geschwindigkeit in $y$-Richtung wächst immer weiter.
+      Der Grund dafür ist, daß die $y$-Komponente der Geschwindigkeit
+      nicht auf physikalisch sinnvolle Weise berechnet wird.
+      In der dafür zuständigen Zeile
+      \lstinline{vy = 0.5 * g * (t * t);}
+      wird stattdessen der Weg in $y$-Richtung bei einer gleichmäßig
+      beschleunigten Bewegung berechnet und als Geschwindigkeit verwendet.
+
+    \item
+      \textbf{Welche Befehle muß man in welcher Weise ändern,
+      um ein realistischeres Hüpf-Verhalten zu bekommen?}
+
+      Da der Ball am Boden abprallen soll, ist es \emph{nicht\/} sinnvoll,
+      die $y$-Komponente der Geschwindigkeit über die bekannte physikalische
+      Formel $v_y = -g\cdot t$ für die Geschwindigkeit in einer
+      gleichmäßig beschleunigten Bewegung zu berechnen.
+
+      Stattdessen ist es sinnvoll, die \emph{Geschwindigkeitsänderung\/}
+      innerhalb des Zeitintervalls \lstinline{dt}
+      zur Geschwindigkeitskomponente zu addieren:
+      \lstinline{vy += g * dt;}
+
+      Auch dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
+      \gitfile{hp}{2022ws/20221114}{gtk-13.c}.
+  \end{enumerate}
+
+  \clearpage
+
+  \vbox to \textheight{\vspace*{-0.5cm}\begin{lstlisting}
+    #include <gtk/gtk.h>
+
+    #define WIDTH 320
+    #define HEIGHT 240
+
+    double t = 0.0;
+    double dt = 0.2;
+
+    int r = 5;
+
+    double x = 10;
+    double y = 200;
+    double vx = 20;
+    double vy = -60;
+    double g = 9.81;
+
+    gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
+    {
+      GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
+
+      gdk_cairo_set_source_rgba (c, &blue);
+      cairo_arc (c, x, y, r, 0, 2 * G_PI);
+      cairo_fill (c);
+
+      return FALSE;
+    }
+
+    gboolean timer (GtkWidget *widget)
+    {
+      t += dt;
+      x += vx * dt;
+      y += vy * dt;
+      vx = vx;
+      vy = 0.5 * g * (t * t);
+      if (y + r >= HEIGHT)
+        vy = -vy * 0.9;
+      if (x + r >= WIDTH)
+        vx = -vx * 0.9;
+      if (x - r <= 0)
+        vx = -vx * 0.9;
+      gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+      g_timeout_add (50, (GSourceFunc) timer, widget);
+      return FALSE;
+    }
+
+    int main (int argc, char **argv)
+    {
+      gtk_init (&argc, &argv);
+
+      GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+      gtk_widget_show (window);
+      gtk_window_set_title (GTK_WINDOW (window), "Hello");
+      g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+      GtkWidget *drawing_area = gtk_drawing_area_new ();
+      gtk_widget_show (drawing_area);
+      gtk_container_add (GTK_CONTAINER (window), drawing_area);
+      gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+      gtk_main ();
+      return 0;
+    }
+  \end{lstlisting}\vss}
+
+  \clearpage
+
+  \exercise{Hexdumps}
+
+  Das folgende Programm (\gitfile{hp}{2022ws/20230109}{aufgabe-4.c}) liest
+  einen String ein und gibt die ASCII-Werte der Buchstaben hexadezimal aus.
+  (Anders als z.\,B.\ \lstinline{scanf()}
+  akzeptiert die Funktion \lstinline{fgets()} zum Lesen von Strings auch Leerzeichen,
+  und sie vermeidet Pufferüberläufe.)
+  \begin{lstlisting}[style=numbered]
+    #include <stdio.h>
+
+    int main (void)
+    {
+      char buffer[100];
+      fgets (buffer, 100, stdin);
+      for (char *p = buffer; *p; p++)
+        printf ("%02x", *p);
+      printf ("\n");
+    }
+  \end{lstlisting}
+  Beispiel: Bei der Eingabe von \lstinline[style=cmd]{Dies ist ein Test.}
+  erscheint die Ausgabe\\
+  \lstinline[style=terminal]{44696573206973742065696e20546573742e0a}.
+
+  Schreiben Sie ein Programm, das diese Umwandlung in umgekehrter Richtung vornimmt,
+  also z.\,B.\ bei Eingabe von \lstinline[style=cmd]{44696573206973742065696e20546573742e0a}
+  wieder \lstinline[style=terminal]{Dies ist ein Test.} ausgibt.
+
+  \points{6}
+
+  Hinweis für die Klausur:
+  Abgabe in digitaler Form ist erwünscht, aber nicht zwingend.
+
+  \solution
+
+  Siehe \gitfile{hp}{2022ws/20230109}{loesung-4.c}.
+
+  Das Programm macht mehrfach davon Gebrauch,
+  daß in C Zeichen und Zahlen äquivalent sind.
+  Wenn z.\,B.\ die \lstinline{char}-Variable \lstinline{c}
+  den Wert \lstinline{'3'} (Ziffer 3) enthält,
+  dann hat der Ausdruck \lstinline{c - '0'} den Wert \lstinline{3} (Zahlenwert 3).
+  Hierfür ist es insbesondere nicht nötig, vorauszusetzen,
+  daß wir den ASCII-Zeichensatz verwenden und \lstinline{'0'}
+  den Wert \lstinline{48} hat.
+
+  Bei Eingabe von \lstinline[style=cmd]{44696573206973742065696e20546573742e0a}
+  gibt das Programm zusätzlich eine Leerzeile aus.
+  Die liegt daran, daß das \lstinline[style=cmd]{0a} am Ende
+  bereits eine Zeilenschaltung enthält und das Programm mit
+  \lstinline{printf ("\n")} eine zusätzliche Zeilenschaltung ausgibt.
+
+\end{document}
diff --git a/20230109/hp-uebung-20230109.pdf b/20230109/hp-uebung-20230109.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..fa3d56e5adb15c9eca45f503587d85415b4cd073
Binary files /dev/null and b/20230109/hp-uebung-20230109.pdf differ
diff --git a/20230109/hp-uebung-20230109.tex b/20230109/hp-uebung-20230109.tex
new file mode 100644
index 0000000000000000000000000000000000000000..e74dbe9a04de7ba9eb0de465392b0d840323d5cd
--- /dev/null
+++ b/20230109/hp-uebung-20230109.tex
@@ -0,0 +1,350 @@
+% hp-uebung-20230109.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: Einfach und doppelt verkettete Listen, ternärer Baum, hüpfender Ball, Hexdumps
+
+% ! Hüpfender Ball (20211206-3)
+% ! Hexdumps (20220110-3)
+% ! einfach und doppelt verkettete Listen (20220117-2)
+% ! ternärer Baum (20220117-3)
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+\usepackage{tikz}
+
+\begin{document}
+
+  \section*{Hardwarenahe Programmierung\\
+            Übungsaufgaben -- 9.\ Januar 2023}
+
+  Diese Übung enthält Punkteangaben wie in einer Klausur.
+  Um zu "`bestehen"', müssen Sie innerhalb von 120 Minuten
+  unter Verwendung ausschließlich zugelassener Hilfsmittel
+  20 Punkte (von insgesamt \totalpoints) erreichen.
+
+  \exercise{Einfach und doppelt verkettete Listen}
+
+  Das Beispiel-Programm \gitfile{hp}{2022ws/20230109}{aufgabe-1.c}
+  demonstriert zwei Funktionen zur Verwaltung einfach verketteter Listen:
+  \lstinline{output_list()} zum Ausgeben der Liste auf den Bildschirm und
+  \lstinline{insert_into_list()} zum Einfügen in die Liste.
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Ergänzen Sie eine Funktion \lstinline{delete_from_list()}
+      zum Löschen eines Elements aus der Liste
+      mit Freigabe des Speicherplatzes.
+      \points{5}
+    \item
+      Ergänzen Sie eine Funktion \lstinline{reverse_list()}
+      die die Reihenfolge der Elemente in der Liste umdreht.\\
+      \points{3}
+  \end{enumerate}
+
+  Eine doppelt verkettete Liste hat in jedem Knotenpunkt (\lstinline{node})
+  \emph{zwei\/} Zeiger -- einen auf das nächste Element (\lstinline{next})
+  und einen auf das vorherige Element (z.\,B.\ \lstinline{prev} für "`previous"').
+  Dadurch ist es leichter als bei einer einfach verketteten Liste,
+  die Liste in umgekehrter Reihenfolge durchzugehen.
+
+  \begin{quote}
+    \begin{tikzpicture}
+      \color{blendedblue}
+      \node(first) at (0,3.5) {first};
+      \node(NULL1) at (-1,1.25) {NULL};
+      \node[shape=rectangle,draw,line width=1pt](3) at (1,2) {3};
+      \node[shape=rectangle,draw,line width=1pt](7) at (3,2) {7};
+      \node[shape=rectangle,draw,line width=1pt](137) at (5,2) {137};
+      \node(NULL2) at (7,2.75) {NULL};
+      \draw[-latex](first)--(3);
+      \draw[-latex](3) to[out=45,in=135] (7);
+      \draw[-latex](3) to[out=-135,in=0] (NULL1);
+      \draw[-latex](7) to[out=-135,in=-45] (3);
+      \draw[-latex](7) to[out=45,in=135] (137);
+      \draw[-latex](137) to[out=-135,in=-45] (7);
+      \draw[-latex](137) to[out=45,in=180] (NULL2);
+    \end{tikzpicture}
+  \end{quote}
+
+  Der Rückwärts-Zeiger (\lstinline{prev}) des ersten Elements zeigt,
+  genau wie der Vorwärts-Zeiger (\lstinline{next}) des letzten Elements,
+  auf \emph{nichts}, hat also den Wert \lstinline{NULL}.
+
+  \begin{enumerate}[\quad(a)]\setcounter{enumi}{2}
+    \item
+      Schreiben Sie das Programm um für doppelt verkettete Listen.
+      \points{5}
+  \end{enumerate}
+
+  \vspace{3cm}
+
+  \exercise{Ternärer Baum}
+
+  Der in der Vorlesung vorgestellte \newterm{binäre Baum\/}
+  ist nur ein Spezialfall;
+  im allgemeinen können Bäume auch mehr als zwei Verzweigungen
+  pro Knotenpunkt haben.
+  Dies ist nützlich bei der Konstruktion \emph{balancierter Bäume},
+  also solcher, die auch im \emph{Worst Case\/}
+  nicht zu einer linearen Liste entarten,
+  sondern stets eine -- möglichst flache -- Baumstruktur behalten.
+
+  Wir betrachten einen Baum mit bis zu drei Verzweigungen pro Knotenpunkt,
+  einen sog.\ \newterm{ternären Baum}.
+  Jeder Knoten enthält dann nicht nur einen,
+  sondern \emph{zwei\/} Werte als Inhalt:
+  \begin{lstlisting}
+    typedef struct node
+    {
+      int content_left, content_right;
+      struct node *left, *middle, *right;
+    } node;
+  \end{lstlisting}
+
+  Wir konstruieren nun einen Baum nach folgenden Regeln:
+  \vspace{-\medskipamount}
+  \begin{itemize}\itemsep0pt
+    \item
+      Innerhalb eines Knotens sind die Werte sortiert:
+      \lstinline{content_left} muß stets kleiner sein als \lstinline{content_right}.
+    \item
+      Der Zeiger \lstinline{left} zeigt auf Knoten,
+      deren enthaltene Werte durchweg kleiner sind als \lstinline{content_left}.
+    \item
+      Der Zeiger \lstinline{right} zeigt auf Knoten,
+      deren enthaltene Werte durchweg größer sind als \lstinline{content_right}.
+    \item
+      Der Zeiger \lstinline{middle} zeigt auf Knoten,
+      deren enthaltene Werte durchweg größer sind als \lstinline{content_left},
+      aber kleiner als \lstinline{content_right}.
+    \item
+      Ein Knoten muß nicht immer mit zwei Werten voll besetzt sein;
+      er darf auch \emph{nur einen\/} gültigen Wert enthalten.
+
+      Der Einfachheit halber lassen wir in diesem Beispiel
+      nur positive Zahlen als Werte zu.
+      Wenn ein Knoten nur einen Wert enthält,
+      setzen wir \lstinline{content_right = -1},
+      und der Zeiger \lstinline{middle} wird nicht verwendet.
+    \item
+      Wenn wir neue Werte in den Baum einfügen,
+      werden \emph{zuerst\/} die nicht voll besetzten Knoten aufgefüllt
+      und \emph{danach erst\/} neue Knoten angelegt und Zeiger gesetzt.
+    \item
+      Beim Auffüllen eines Knotens darf nötigenfalls \lstinline{content_left}
+      nach \lstinline{content_right} verschoben werden.
+      Ansonsten werden einmal angelegte Knoten nicht mehr verändert.
+  \end{itemize}
+  \vspace*{-\medskipamount}
+  (In der Praxis dürfen Knoten gemäß speziellen Regeln
+  nachträglich verändert werden,
+  um Entartungen gar nicht erst entstehen zu lassen --
+  siehe z.\,B.\ \url{https://en.wikipedia.org/wiki/2-3_tree}.)
+  \begin{enumerate}[\quad(a)]
+    \item
+      Zeichnen Sie ein Schaubild, das veranschaulicht,
+      wie die Zahlen 7, 137, 3, 5, 6, 42, 1, 2 und 12
+      nacheinander und in dieser Reihenfolge
+      in den oben beschriebenen Baum eingefügt werden
+      -- analog zu den Vortragsfolien (\gitfile{hp}{2022ws/20221219}{hp-20221219.pdf}),
+      Seite 33.
+      \points{3}
+      %
+      % Lösung:
+      %
+      %           7 137
+      %         /   |
+      %      3 5  12 42
+      %     /   \
+      %   1 2    6
+      %
+      % (NULL-Zeiger sind hier nicht dargestellt,
+      % gehören aber dazu.)
+      %
+    \item
+      Dasselbe, aber in der Reihenfolge 
+      2, 7, 42, 12, 1, 137, 5, 6, 3.
+      \points{3}
+      %
+      % Lösung:
+      %
+      %           2 7
+      %         /  |  \
+      %       1   5 6  12 42
+      %         /           \
+      %        3             137
+      %
+      % (NULL-Zeiger sind hier wieder nicht dargestellt,
+      % gehören aber dazu.)
+      %
+    \item
+      Beschreiben Sie in Worten und/oder als C-Quelltext-Fragment,
+      wie eine Funktion aussehen müßte, um den auf diese Weise entstandenen Baum
+      sortiert auszugeben.
+      \points{4}
+  \end{enumerate}
+
+  \vspace{3cm}
+
+  \exercise{Fehlerhaftes Programm: Hüpfender Ball}
+
+  Das auf der nächsten Seite abgedruckte GTK+-Programm
+  (Datei: \gitfile{hp}{2022ws/20230109}{aufgabe-3.c}) soll einen
+  hüpfenden Ball darstellen, ist jedoch fehlerhaft.
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Warum sieht man lediglich ein leeres Fenster?
+      Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben?
+      \points{3}
+    \item
+      Nach der Fehlerbehebung in Aufgabenteil (a)
+      zeigt das Programm einen unbeweglichen Ball.
+      Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben, und warum?
+      \points{2}
+    \item
+      Erklären Sie das merkwürdige Hüpfverhalten des Balls.
+      Wie kommt es zustande?
+      Was an diesem Verhalten ist korrekt, und was ist fehlerhaft? \points{5}
+    \item
+      Welche Befehle muß man in welcher Weise ändern,
+      um ein realistischeres Hüpf-Verhalten zu bekommen? \points{2}
+  \end{enumerate}
+
+  Hinweis: Das Hinzuziehen von Beispiel-Programmen aus der Vorlesung
+  ist ausdrücklich erlaubt -- auch in der Klausur.
+
+  Allgemeiner Hinweis:
+  Wenn Sie die Übungsaufgaben zu dieser Lehrveranstaltung
+  als PDF-Datei betrachten und darin auf die Dateinamen klicken,
+  können Sie die Beispiel-Programme direkt herunterladen.
+  Dadurch vermeiden Sie Übertragungsfehler.
+
+  \clearpage
+
+  \vbox to \textheight{\vspace*{-0.5cm}\begin{lstlisting}
+    #include <gtk/gtk.h>
+
+    #define WIDTH 320
+    #define HEIGHT 240
+
+    double t = 0.0;
+    double dt = 0.2;
+
+    int r = 5;
+
+    double x = 10;
+    double y = 200;
+    double vx = 20;
+    double vy = -60;
+    double g = 9.81;
+
+    gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
+    {
+      GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
+
+      gdk_cairo_set_source_rgba (c, &blue);
+      cairo_arc (c, x, y, r, 0, 2 * G_PI);
+      cairo_fill (c);
+
+      return FALSE;
+    }
+
+    gboolean timer (GtkWidget *widget)
+    {
+      t += dt;
+      x += vx * dt;
+      y += vy * dt;
+      vx = vx;
+      vy = 0.5 * g * (t * t);
+      if (y + r >= HEIGHT)
+        vy = -vy * 0.9;
+      if (x + r >= WIDTH)
+        vx = -vx * 0.9;
+      if (x - r <= 0)
+        vx = -vx * 0.9;
+      gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+      g_timeout_add (50, (GSourceFunc) timer, widget);
+      return FALSE;
+    }
+
+    int main (int argc, char **argv)
+    {
+      gtk_init (&argc, &argv);
+
+      GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+      gtk_widget_show (window);
+      gtk_window_set_title (GTK_WINDOW (window), "Hello");
+      g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+      GtkWidget *drawing_area = gtk_drawing_area_new ();
+      gtk_widget_show (drawing_area);
+      gtk_container_add (GTK_CONTAINER (window), drawing_area);
+      gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+      gtk_main ();
+      return 0;
+    }
+  \end{lstlisting}\vss}
+
+  \exercise{Hexdumps}
+
+  Das folgende Programm (\gitfile{hp}{2022ws/20230109}{aufgabe-4.c}) liest
+  einen String ein und gibt die ASCII-Werte der Buchstaben hexadezimal aus.
+  (Anders als z.\,B.\ \lstinline{scanf()}
+  akzeptiert die Funktion \lstinline{fgets()} zum Lesen von Strings auch Leerzeichen,
+  und sie vermeidet Pufferüberläufe.)
+  \begin{lstlisting}[style=numbered]
+    #include <stdio.h>
+
+    int main (void)
+    {
+      char buffer[100];
+      fgets (buffer, 100, stdin);
+      for (char *p = buffer; *p; p++)
+        printf ("%02x", *p);
+      printf ("\n");
+    }
+  \end{lstlisting}
+  Beispiel: Bei der Eingabe von \lstinline[style=cmd]{Dies ist ein Test.}
+  erscheint die Ausgabe\\
+  \lstinline[style=terminal]{44696573206973742065696e20546573742e0a}.
+
+  Schreiben Sie ein Programm, das diese Umwandlung in umgekehrter Richtung vornimmt,
+  also z.\,B.\ bei Eingabe von \lstinline[style=cmd]{44696573206973742065696e20546573742e0a}
+  wieder \lstinline[style=terminal]{Dies ist ein Test.} ausgibt.
+
+  \points{6}
+
+  Hinweis für die Klausur:
+  Abgabe in digitaler Form ist erwünscht, aber nicht zwingend.
+
+  \begin{flushright}
+    \textit{Viel Erfolg -- auch in den Prüfungen!}
+  \end{flushright}
+
+  \makeatletter
+    \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}}
+  \makeatother
+
+\end{document}
diff --git a/20230109/loesung-1a.c b/20230109/loesung-1a.c
new file mode 100644
index 0000000000000000000000000000000000000000..93f5e5629a98d13d6292c56d1a3f855b4f5bd8fd
--- /dev/null
+++ b/20230109/loesung-1a.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *next;
+} node;
+
+void output_list (node *first)
+{
+  for (node *p = first; p; p = p->next)
+    printf ("%d ", p->content);
+  printf ("\n");
+}
+
+void insert_into_list (node *what, node *where)
+{
+  what->next = where->next;
+  where->next = what;
+}
+
+void delete_from_list (node *what, node **first)
+{
+  if (what == *first)
+    *first = what->next;
+  else
+    {
+      node *p = *first;
+      while (p && p->next != what)
+        p = p->next;
+      if (p)
+        p->next = what->next;
+    }
+  free (what);
+}
+
+int main (void)
+{
+  node *element3 = malloc (sizeof (node));
+  node *element7 = malloc (sizeof (node));
+  node *element137 = malloc (sizeof (node));
+
+  element3->content = 3;
+  element7->content = 7;
+  element137->content = 137;
+
+  node *first = element3;
+  element3->next = element7;
+  element7->next = element137;
+  element137->next = NULL;
+
+  output_list (first);
+
+  node *element5 = malloc (sizeof (node));
+  element5->content = 5;
+  insert_into_list (element5, element3);
+
+  output_list (first);
+
+  delete_from_list (element5, &first);
+  output_list (first);
+  delete_from_list (element3, &first);
+  output_list (first);
+  delete_from_list (element137, &first);
+  output_list (first);
+
+  return 0;
+}
diff --git a/20230109/loesung-1b.c b/20230109/loesung-1b.c
new file mode 100644
index 0000000000000000000000000000000000000000..811b99b1fc9697ca0302eea8950c9bc6e7ab6042
--- /dev/null
+++ b/20230109/loesung-1b.c
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content;
+  struct node *next, *prev;
+} node;
+
+void check_list (node *first)
+{
+  for (node *p = first; p; p = p->next)
+    {
+      if (p->next && p->next->prev != p)
+        fprintf (stderr, "List inconsistency!\n");
+      if (p->prev && p->prev->next != p)
+        fprintf (stderr, "List inconsistency!\n");
+    }
+}
+
+void output_list (node *first)
+{
+  for (node *p = first; p; p = p->next)
+    printf ("%d ", p->content);
+  printf ("\n");
+}
+
+void insert_into_list (node *what, node *where)
+{
+  what->next = where->next;
+  if (where->next)
+    where->next->prev = what;
+  what->prev = where;
+  where->next = what;
+}
+
+void delete_from_list (node *what, node **first)
+{
+  if (what == *first)
+    {
+      *first = what->next;
+      if (*first)
+        (*first)->prev = NULL;
+    }
+  else
+    {
+      node *p = *first;
+      while (p && p->next != what)
+        p = p->next;
+      if (p)
+        p->next = what->next;
+      if (what->next)
+        what->next->prev = p;
+    }
+  free (what);
+}
+
+int main (void)
+{
+  node *element3 = malloc (sizeof (node));
+  node *element7 = malloc (sizeof (node));
+  node *element137 = malloc (sizeof (node));
+
+  element3->content = 3;
+  element7->content = 7;
+  element137->content = 137;
+
+  node *first = element3;
+  element3->prev = NULL;
+  element3->next = element7;
+  element7->prev = element3;
+  element7->next = element137;
+  element137->prev = element7;
+  element137->next = NULL;
+
+  output_list (first);
+  check_list (first);
+
+  node *element5 = malloc (sizeof (node));
+  element5->content = 5;
+  insert_into_list (element5, element3);
+
+  output_list (first);
+  check_list (first);
+
+  delete_from_list (element5, &first);
+  output_list (first);
+  check_list (first);
+  delete_from_list (element3, &first);
+  output_list (first);
+  check_list (first);
+  delete_from_list (element137, &first);
+  output_list (first);
+  check_list (first);
+
+  return 0;
+}
diff --git a/20230109/loesung-2c.c b/20230109/loesung-2c.c
new file mode 100644
index 0000000000000000000000000000000000000000..a6dea990b25895475e343f07895c6a946426d2d8
--- /dev/null
+++ b/20230109/loesung-2c.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct node
+{
+  int content_left, content_right;
+  struct node *left, *middle, *right;
+} node;
+
+void insert_into_tree (node **root, int value)
+{
+  if (*root)
+    {
+      if ((*root)->content_right >= 0)
+        if (value < (*root)->content_left)
+          insert_into_tree (&(*root)->left, value);
+        else if (value < (*root)->content_right)
+          insert_into_tree (&(*root)->middle, value);
+        else
+          insert_into_tree (&(*root)->right, value);
+      else
+        if (value < (*root)->content_left)
+          {
+            (*root)->content_right = (*root)->content_left;
+            (*root)->content_left = value;
+          }
+        else
+          (*root)->content_right = value;
+    }
+  else
+    {
+      *root = malloc (sizeof (node));
+      (*root)->left = NULL;
+      (*root)->content_left = value;
+      (*root)->middle = NULL;
+      (*root)->content_right = -1;
+      (*root)->right = NULL;
+    }
+}
+
+void output_tree (node *root)
+{
+  if (root)
+    {
+      output_tree (root->left);
+      printf ("%d\n", root->content_left);
+      output_tree (root->middle);
+      if (root->content_right >= 0)
+        printf ("%d\n", root->content_right);
+      output_tree (root->right);
+    }
+}
+
+int main (void)
+{
+  node *root = NULL;
+  insert_into_tree (&root, 7);
+  insert_into_tree (&root, 137);
+  insert_into_tree (&root, 3);
+  insert_into_tree (&root, 5);
+  insert_into_tree (&root, 6);
+  insert_into_tree (&root, 42);
+  insert_into_tree (&root, 1);
+  insert_into_tree (&root, 2);
+  insert_into_tree (&root, 12);
+  output_tree (root);
+  return 0;
+}
diff --git a/20230109/loesung-4.c b/20230109/loesung-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..872058ac9fecdcb59ac1104ca67841cb3dc974a9
--- /dev/null
+++ b/20230109/loesung-4.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+
+int read_hex (char c)
+{
+  if (c >= '0' && c <= '9')
+    return c - '0';
+  else if (c >= 'A' && c <= 'F')
+    return c - 'A' + 10;
+  else if (c >= 'a' && c <= 'f')
+    return c - 'a' + 10;
+  else
+    {
+      fprintf (stderr, "invalid hex digit '%c'\n", c);
+      return 0;
+    }
+}
+
+int main (void)
+{
+  char buffer[100];
+  fgets (buffer, 100, stdin);
+  for (char *p = buffer; p[0] && p[1]; p += 2)
+    {
+      char c = 16 * read_hex (p[0]) + read_hex (p[1]);
+      printf ("%c", c);
+    }
+  printf ("\n");
+}
diff --git a/20230109/logo-hochschule-bochum-cvh-text-v2.pdf b/20230109/logo-hochschule-bochum-cvh-text-v2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8
--- /dev/null
+++ b/20230109/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/20230109/logo-hochschule-bochum.pdf b/20230109/logo-hochschule-bochum.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1
--- /dev/null
+++ b/20230109/logo-hochschule-bochum.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum.pdf
\ No newline at end of file
diff --git a/20230109/pgscript.sty b/20230109/pgscript.sty
new file mode 120000
index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b
--- /dev/null
+++ b/20230109/pgscript.sty
@@ -0,0 +1 @@
+../common/pgscript.sty
\ No newline at end of file
diff --git a/README.md b/README.md
index 3ddb14b19a44834df18d846b5b47432b73996be5..583ac081047ac170412f57d62da3988669520b2c 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ Vortragsfolien und Beispiele:
  * [21.11.2022: Aufwandsabschätzungen, Objektorientierte Programmierung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221121/hp-20221121.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2022ws/20221121/)
  * [28.11.2022: Objektorientierte Programmierung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221128/hp-20221128.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2022ws/20221128/)
  * [05.12.2022: Objektorientierte Programmierung, Datenstrukturen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221205/hp-20221205.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2022ws/20221205/)
- * [12.12.2022: Objektorientierte Programmierung, Datenstrukturen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221212/hp-20221212.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2022ws/20221212/)
+ * [19.12.2022: Objektorientierte Programmierung, Datenstrukturen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221219/hp-20221219.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2022ws/20221219/)
  * [alle in 1 Datei](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/hp-slides-2022ws.pdf)
 
 Übungsaufgaben:
@@ -43,6 +43,7 @@ Vortragsfolien und Beispiele:
  * [28.11.2022: Einfügen in Strings (Ergänzung), dynamisches Bit-Array, objektorientierte Tier-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221128/hp-uebung-20221128.pdf)
  * [05.12.2022: Objektorientierte Tier-Datenbank (Ergänzung), Iterationsfunktionen, Stack-Operationen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221205/hp-uebung-20221205.pdf)
  * [12.12.2022: Länge von Strings (Neuauflage), Text-Grafik-Bibliothek, PBM-Grafik](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221212/hp-uebung-20221212.pdf)
+ * [09.01.2023: Einfach und doppelt verkettete Listen, ternärer Baum, hüpfender Ball, Hexdumps](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20230109/hp-uebung-20230109.pdf)
 
 Musterlösungen:
 ---------------
@@ -56,6 +57,7 @@ Musterlösungen:
  * [28.11.2022: Einfügen in Strings (Ergänzung), dynamisches Bit-Array, objektorientierte Tier-Datenbank](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221128/hp-musterloesung-20221128.pdf)
  * [05.12.2022: Objektorientierte Tier-Datenbank (Ergänzung), Iterationsfunktionen, Stack-Operationen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221205/hp-musterloesung-20221205.pdf)
  * [12.12.2022: Länge von Strings (Neuauflage), Text-Grafik-Bibliothek, PBM-Grafik](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20221212/hp-musterloesung-20221212.pdf)
+ * [09.01.2023: Einfach und doppelt verkettete Listen, ternärer Baum, hüpfender Ball, Hexdumps](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2022ws/20230109/hp-musterloesung-20230109.pdf)
 
 Praktikumsunterlagen:
 ---------------------