diff --git a/20201217/Makefile b/20201217/Makefile
new file mode 120000
index 0000000000000000000000000000000000000000..d5f315bb0af8681b0b80a89de423cdc968cac0ba
--- /dev/null
+++ b/20201217/Makefile
@@ -0,0 +1 @@
+Makefile-3
\ No newline at end of file
diff --git a/20201217/Makefile-1 b/20201217/Makefile-1
new file mode 100644
index 0000000000000000000000000000000000000000..bfc1b10a929f22a8c2f4f0cf0368c78db14ad0b0
--- /dev/null
+++ b/20201217/Makefile-1
@@ -0,0 +1,8 @@
+philosophy: philosophy.o answer.o
+	gcc philosophy.o answer.o -o philosophy
+
+answer.o: answer.c answer.h
+	gcc -Wall -O answer.c -c
+
+philosophy.o: philosophy.c answer.h
+	gcc -Wall -O philosophy.c -c
diff --git a/20201217/Makefile-2 b/20201217/Makefile-2
new file mode 100644
index 0000000000000000000000000000000000000000..60aab7c7d51b28879c41e8590ab422e9edfadee5
--- /dev/null
+++ b/20201217/Makefile-2
@@ -0,0 +1,16 @@
+TARGET = philosophy
+OBJECTS = philosophy.o answer.o
+HEADERS = answer.h
+CFLAGS = -Wall -O
+
+$(TARGET): $(OBJECTS)
+	gcc $(OBJECTS) -o $(TARGET)
+
+answer.o: answer.c $(HEADERS)
+	gcc $(CFLAGS) answer.c -c
+
+philosophy.o: philosophy.c $(HEADERS)
+	gcc $(CFLAGS) philosophy.c -c
+
+clean:
+	rm -f $(OBJECTS) $(TARGET)
diff --git a/20201217/Makefile-3 b/20201217/Makefile-3
new file mode 100644
index 0000000000000000000000000000000000000000..0ac355bfddfd237fe0f1b5062c5a242ab0d3e97e
--- /dev/null
+++ b/20201217/Makefile-3
@@ -0,0 +1,13 @@
+TARGET = philosophy
+OBJECTS = philosophy.o answer.o
+HEADERS = answer.h
+CFLAGS = -Wall -O
+
+$(TARGET): $(OBJECTS)
+	gcc $(OBJECTS) -o $(TARGET)
+
+%.o: %.c $(HEADERS)
+	gcc $(CFLAGS) $< -c
+
+clean:
+	rm -f $(OBJECTS) $(TARGET)
diff --git a/20201217/answer.c b/20201217/answer.c
new file mode 100644
index 0000000000000000000000000000000000000000..65a1dc248becb3157f2a226fc7b30df2ffb82e00
--- /dev/null
+++ b/20201217/answer.c
@@ -0,0 +1,6 @@
+#include "answer.h"
+
+int answer (void)
+{
+  return 23;
+}
diff --git a/20201217/answer.h b/20201217/answer.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6777e8210983d315b3ac3424a61bd9c9f0437b1
--- /dev/null
+++ b/20201217/answer.h
@@ -0,0 +1 @@
+extern int answer (void);
diff --git a/20201217/gtk-14.c b/20201217/gtk-14.c
new file mode 100644
index 0000000000000000000000000000000000000000..75956a60c799d463b13ab45db1a6a62db96f7a20
--- /dev/null
+++ b/20201217/gtk-14.c
@@ -0,0 +1,60 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 50.0;
+double dt = 0.05;
+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, HEIGHT - y, 5, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  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_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (5000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/gtk-15.c b/20201217/gtk-15.c
new file mode 100644
index 0000000000000000000000000000000000000000..abedb4d4988920c9a48cf4db12caf48a1d30d720
--- /dev/null
+++ b/20201217/gtk-15.c
@@ -0,0 +1,60 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 50.0;
+double dt = 0.2;
+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, HEIGHT - y, 5, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (200, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/gtk-16.c b/20201217/gtk-16.c
index 0901dd7f491ca219cceb6c1f344291de0c154f38..ccd1697d780457103a2c46d2be8572ac6f6d6d9e 100644
--- a/20201217/gtk-16.c
+++ b/20201217/gtk-16.c
@@ -8,7 +8,7 @@ double x = 5;
 double y = 95;
 double vx = 50.0;
 double vy = 70.0;
-double dt = 0.05;
+double dt = 0.2;
 double g = 9.81;
 
 gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
@@ -29,7 +29,7 @@ gboolean timer (GtkWidget *widget)
   if (x + RADIUS >= WIDTH)
     vx = -vx;
   gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
-  g_timeout_add (50, (GSourceFunc) timer, widget);
+  g_timeout_add (200, (GSourceFunc) timer, widget);
   return FALSE;
 }
 
@@ -52,7 +52,7 @@ int main (int argc, char **argv)
   g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
   gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
 
-  g_timeout_add (50, (GSourceFunc) timer, drawing_area);
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
 
   gtk_widget_show (drawing_area);
   gtk_widget_show (button);
diff --git a/20201217/gtk-17.c b/20201217/gtk-17.c
new file mode 100644
index 0000000000000000000000000000000000000000..21786c759abcb452650aaa2358d3117acc15da52
--- /dev/null
+++ b/20201217/gtk-17.c
@@ -0,0 +1,65 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+#define RADIUS 5
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 70.0;
+double dt = 0.2;
+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, HEIGHT - y, RADIUS, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  if (x + RADIUS >= WIDTH)
+    vx = -vx;
+  if (y + RADIUS >= HEIGHT)
+    vy = -vy;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (200, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/gtk-18.c b/20201217/gtk-18.c
new file mode 100644
index 0000000000000000000000000000000000000000..84f6081519114dbbd32e58ae495c60dbad83e279
--- /dev/null
+++ b/20201217/gtk-18.c
@@ -0,0 +1,65 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+#define RADIUS 5
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 70.0;
+double dt = 0.2;
+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, HEIGHT - y, RADIUS, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  if (x + RADIUS >= WIDTH)
+    vx = -vx;
+  if (y + RADIUS <= 0)
+    vy = -vy;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (200, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/gtk-19.c b/20201217/gtk-19.c
new file mode 100644
index 0000000000000000000000000000000000000000..488ecb2f7e2e89c00119acc9c2a7a336129b0236
--- /dev/null
+++ b/20201217/gtk-19.c
@@ -0,0 +1,65 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+#define RADIUS 5
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 70.0;
+double dt = 0.2;
+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, HEIGHT - y, RADIUS, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  if (x + RADIUS >= WIDTH)
+    vx = -vx;
+  if (y - RADIUS <= 0)
+    vy = -vy;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (200, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/gtk-20.c b/20201217/gtk-20.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf4c99aadff3cc1856b63176eebc1b66bb64acfb
--- /dev/null
+++ b/20201217/gtk-20.c
@@ -0,0 +1,65 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+#define RADIUS 5
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 70.0;
+double dt = 0.1;
+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, HEIGHT - y, RADIUS, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  if (x + RADIUS >= WIDTH)
+    vx = -vx;
+  if (y - RADIUS <= 0)
+    vy = -vy;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (100, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/gtk-21.c b/20201217/gtk-21.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5227416e36dd16cb647142a2574bf2229f88456
--- /dev/null
+++ b/20201217/gtk-21.c
@@ -0,0 +1,67 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+#define RADIUS 5
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 70.0;
+double dt = 0.1;
+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, HEIGHT - y, RADIUS, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  if (x + RADIUS >= WIDTH)
+    vx = -vx;
+  if (x - RADIUS <= 0)
+    vx = -vx;
+  if (y - RADIUS <= 0)
+    vy = -vy;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (100, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/gtk-22.c b/20201217/gtk-22.c
new file mode 100644
index 0000000000000000000000000000000000000000..5a141e5773fe36fc51adce4a69e71d76c898b8f6
--- /dev/null
+++ b/20201217/gtk-22.c
@@ -0,0 +1,67 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+#define RADIUS 5
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 70.0;
+double dt = 0.1;
+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, HEIGHT - y, RADIUS, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  if (x + RADIUS >= WIDTH)
+    vx = -0.9 * vx;
+  if (x - RADIUS <= 0)
+    vx = -0.9 * vx;
+  if (y - RADIUS <= 0)
+    vy = -0.9 * vy;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (100, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/gtk-23.c b/20201217/gtk-23.c
new file mode 100644
index 0000000000000000000000000000000000000000..0a92ba411bab337fc882130556f463b81d919cfa
--- /dev/null
+++ b/20201217/gtk-23.c
@@ -0,0 +1,67 @@
+#include <gtk/gtk.h>
+
+#define WIDTH 640
+#define HEIGHT 480
+#define RADIUS 5
+
+double x = 5;
+double y = 95;
+double vx = 50.0;
+double vy = 70.0;
+double dt = 0.1;
+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, HEIGHT - y, RADIUS, 0, 2 * G_PI);
+  cairo_fill (c);
+  return FALSE;
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  x += vx * dt;
+  y += vy * dt;
+  vx += 0.0 * dt;
+  vy += (-g) * dt;
+  if (x + RADIUS >= WIDTH && vx > 0)
+    vx = -0.9 * vx;
+  if (x - RADIUS <= 0 && vx < 0)
+    vx = -0.9 * vx;
+  if (y - RADIUS <= 0 && vy < 0)
+    vy = -0.9 * vy;
+  gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
+  g_timeout_add (100, (GSourceFunc) timer, widget);
+  return FALSE;
+}
+
+int main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+  GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "Hello");
+  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+  GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  GtkWidget *button = gtk_button_new_with_label ("Quit");
+  g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_container_add (GTK_CONTAINER (vbox), button);
+
+  GtkWidget *drawing_area = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+  gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
+
+  g_timeout_add (1000, (GSourceFunc) timer, drawing_area);
+
+  gtk_widget_show (drawing_area);
+  gtk_widget_show (button);
+  gtk_widget_show (vbox);
+  gtk_widget_show (window);
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/hp-20201217.pdf b/20201217/hp-20201217.pdf
index 173a2277de52dffc99c4e949574ebe3797c9d641..440d46e10981db443b7be234834f08ba026b94fc 100644
Binary files a/20201217/hp-20201217.pdf and b/20201217/hp-20201217.pdf differ
diff --git a/20201217/hp-20201217.tex b/20201217/hp-20201217.tex
index be44ed7ba94b35fb895021d5cd18d64683abaaaa..b64061a30d02b25cffbee5d64fc763758018f863 100644
--- a/20201217/hp-20201217.tex
+++ b/20201217/hp-20201217.tex
@@ -208,7 +208,7 @@
       \begin{onlyenv}<3->
         \begin{lstlisting}[style=terminal,gobble=10]
           $ ¡gcc -Wall -O hello-gtk.c $(pkg-config --cflags --libs
-                 gtk+-3.0 -o hello-gtk¿
+                 gtk+-3.0) -o hello-gtk¿
         \end{lstlisting}
       \end{onlyenv}
       \begin{onlyenv}<3>
diff --git a/20201217/make-1.txt b/20201217/make-1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a04a551c7c38556c87ae7c3644357cbf51d13df3
--- /dev/null
+++ b/20201217/make-1.txt
@@ -0,0 +1,27 @@
+cassini/home/peter/bo/2020ws/hp/20201217> cat philosophy.c
+#include <stdio.h>
+#include "answer.h"
+
+int main (void)
+{
+  printf ("The answer is %d.\n", answer ());
+  return 0;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> cat answer.h
+extern int answer (void);
+cassini/home/peter/bo/2020ws/hp/20201217> cat answer.c
+#include "answer.h"
+
+int answer (void)
+{
+  return 42;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O philosophy.c -o philosophy
+/usr/bin/ld: /tmp/ccCbFdy5.o: in function `main':
+philosophy.c:(.text+0x5): undefined reference to `answer'
+collect2: error: ld returned 1 exit status
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O answer.c -c
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O philosophy.c answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 42.
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-10.txt b/20201217/make-10.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5a731bbb980ec0a63c1caf3152fd690e81631e26
--- /dev/null
+++ b/20201217/make-10.txt
@@ -0,0 +1,30 @@
+TARGET = philosophy
+OBJECTS = philosophy.o answer.o
+HEADERS = answer.h
+CFLAGS = -Wall -O
+
+$(TARGET): $(OBJECTS)
+        gcc $(OBJECTS) -o $(TARGET)
+
+answer.o: answer.c $(HEADERS)
+        gcc $(CFLAGS) answer.c -c
+
+philosophy.o: philosophy.c $(HEADERS)
+        gcc $(CFLAGS) philosophy.c -c
+
+clean:
+        rm -f $(OBJECTS) $(TARGET)
+cassini/home/peter/bo/2020ws/hp/20201217> make -f Makefile-2
+make: „philosophy“ ist bereits aktuell.
+cassini/home/peter/bo/2020ws/hp/20201217> make answer.o -f Makefile-2
+make: „answer.o“ ist bereits aktuell.
+cassini/home/peter/bo/2020ws/hp/20201217> make clean -f Makefile-2
+rm -f philosophy.o answer.o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> make answer.o -f Makefile-2
+gcc -Wall -O answer.c -c
+cassini/home/peter/bo/2020ws/hp/20201217> make -f Makefile-2
+gcc -Wall -O philosophy.c -c
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 23.
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-11.txt b/20201217/make-11.txt
new file mode 100644
index 0000000000000000000000000000000000000000..972907b4742b95090fa2ab16b416c01f234894a3
--- /dev/null
+++ b/20201217/make-11.txt
@@ -0,0 +1,32 @@
+cassini/home/peter/bo/2020ws/hp/20201217> cat Makefile-3
+TARGET = philosophy
+OBJECTS = philosophy.o answer.o
+HEADERS = answer.h
+CFLAGS = -Wall -O
+
+$(TARGET): $(OBJECTS)
+        gcc $(OBJECTS) -o $(TARGET)
+
+%.o: %.c $(HEADERS)
+        gcc $(CFLAGS) $< -c
+
+clean:
+        rm -f $(OBJECTS) $(TARGET)
+cassini/home/peter/bo/2020ws/hp/20201217> make clean
+make: *** Keine Regel, um „clean“ zu erstellen.  Schluss.
+cassini/home/peter/bo/2020ws/hp/20201217> make
+make: *** Es wurden keine Ziele angegeben und keine „make“-Steuerdatei gefunden.  Schluss.
+cassini/home/peter/bo/2020ws/hp/20201217> make -f Makefile-3 clean
+rm -f philosophy.o answer.o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> make -f Makefile-3
+gcc -Wall -O philosophy.c -c
+gcc -Wall -O answer.c -c
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ln -s Makefile-3 Makefile
+cassini/home/peter/bo/2020ws/hp/20201217> make clean
+rm -f philosophy.o answer.o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> make
+gcc -Wall -O philosophy.c -c
+gcc -Wall -O answer.c -c
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-2.txt b/20201217/make-2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4143a77a2e45b57b3efe005456c99b173ca92b99
--- /dev/null
+++ b/20201217/make-2.txt
@@ -0,0 +1,10 @@
+#include "answer.h"
+
+int answer (void)
+{
+  return 137;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O philosophy.c answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 42.
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-3.txt b/20201217/make-3.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ac0a49ddec4c3f6fcb3229abbe35640a7816e8d9
--- /dev/null
+++ b/20201217/make-3.txt
@@ -0,0 +1,25 @@
+#include "answer.h"
+
+int answer (void)
+{
+  return 137;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O philosophy.c answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 42.
+cassini/home/peter/bo/2020ws/hp/20201217> cat >> make-2.txt
+#include "answer.h"
+
+int answer (void)
+{
+  return 137;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O philosophy.c answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 42.
+cassini/home/peter/bo/2020ws/hp/20201217>
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O answer.c -c
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O philosophy.c answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 137.
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-4.txt b/20201217/make-4.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d07bb9f28f390a394f55dbb9bf1a85a8a00419cf
--- /dev/null
+++ b/20201217/make-4.txt
@@ -0,0 +1,24 @@
+cassini/home/peter/bo/2020ws/hp/20201217> cat philosophy.c
+#include <stdio.h>
+#include "answer.h"
+
+int main (void)
+{
+  printf ("The answer is %d.\n", answer ());
+  return 0;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> cat answer.h
+extern int answer (void);
+cassini/home/peter/bo/2020ws/hp/20201217> cat answer.c
+#include "answer.h"
+
+int answer (void)
+{
+  return 137;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O philosophy.c -c
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O answer.c -c
+cassini/home/peter/bo/2020ws/hp/20201217> gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 137.
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-5.txt b/20201217/make-5.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7033a7ff15ef20da449058e5955084573bec74c3
--- /dev/null
+++ b/20201217/make-5.txt
@@ -0,0 +1,25 @@
+cassini/home/peter/bo/2020ws/hp/20201217> cat philosophy.c
+#include <stdio.h>
+#include "answer.h"
+
+int main (void)
+{
+  printf ("The answer is %d.\n", answer ());
+  return 0;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> cat answer.h
+extern int answer (void);
+cassini/home/peter/bo/2020ws/hp/20201217> cat answer.c
+#include "answer.h"
+
+int answer (void)
+{
+  return 137;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> for x in philsophy.c answer.c; do gcc -Wall -O $x -c; done
+gcc: error: philsophy.c: Datei oder Verzeichnis nicht gefunden
+gcc: fatal error: no input files
+compilation terminated.
+cassini/home/peter/bo/2020ws/hp/20201217> for x in philosophy.c answer.c; do gcc -Wall -O $x -c; done
+cassini/home/peter/bo/2020ws/hp/20201217> gcc -Wall -O philosophy.c answer.c -c
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-6.txt b/20201217/make-6.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8b369c1e14c49675d968324c8406a311eb3bbd66
--- /dev/null
+++ b/20201217/make-6.txt
@@ -0,0 +1,14 @@
+cassini/home/peter/bo/2020ws/hp/20201217> cat Makefile
+philosophy: philosophy.o answer.o
+        gcc philosophy.o answer.o -o philosophy
+
+answer.o: answer.c answer.h
+        gcc -Wall -O answer.c -c
+
+philosophy.o: philosophy.c answer.h
+        gcc -Wall -O philosophy.c -c
+cassini/home/peter/bo/2020ws/hp/20201217> make
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 137.
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-7.txt b/20201217/make-7.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2237b1b84043ee3844d8d73c212a3321436b2e4d
--- /dev/null
+++ b/20201217/make-7.txt
@@ -0,0 +1,40 @@
+cassini/home/peter/bo/2020ws/hp/20201217> cat Makefile
+philosophy: philosophy.o answer.o
+        gcc philosophy.o answer.o -o philosophy
+
+answer.o: answer.c answer.h
+        gcc -Wall -O answer.c -c
+
+philosophy.o: philosophy.c answer.h
+        gcc -Wall -O philosophy.c -c
+cassini/home/peter/bo/2020ws/hp/20201217> make
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 137.
+cassini/home/peter/bo/2020ws/hp/20201217> cat >> make-6.txt
+cassini/home/peter/bo/2020ws/hp/20201217> cat Makefile
+philosophy: philosophy.o answer.o
+        gcc philosophy.o answer.o -o philosophy
+
+answer.o: answer.c answer.h
+        gcc -Wall -O answer.c -c
+
+philosophy.o: philosophy.c answer.h
+        gcc -Wall -O philosophy.c -c
+cassini/home/peter/bo/2020ws/hp/20201217> make
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> ./philosophy
+The answer is 137.
+cassini/home/peter/bo/2020ws/hp/20201217>
+cassini/home/peter/bo/2020ws/hp/20201217> sed -i answer.c -e 's/137/23/'
+cassini/home/peter/bo/2020ws/hp/20201217> cat answer.c
+#include "answer.h"
+
+int answer (void)
+{
+  return 23;
+}
+cassini/home/peter/bo/2020ws/hp/20201217> make
+gcc -Wall -O answer.c -c
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-8.txt b/20201217/make-8.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f2d502f113a0c393496efea008247677f643092b
--- /dev/null
+++ b/20201217/make-8.txt
@@ -0,0 +1,5 @@
+cassini/home/peter/bo/2020ws/hp/20201217> touch philosophy.c
+cassini/home/peter/bo/2020ws/hp/20201217> make
+gcc -Wall -O philosophy.c -c
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/make-9.txt b/20201217/make-9.txt
new file mode 100644
index 0000000000000000000000000000000000000000..13617e5285cbb625b8f27f070279508d80705c0a
--- /dev/null
+++ b/20201217/make-9.txt
@@ -0,0 +1,13 @@
+cassini/home/peter/bo/2020ws/hp/20201217> touch philosophy.c
+cassini/home/peter/bo/2020ws/hp/20201217> make
+gcc -Wall -O philosophy.c -c
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217> cat >> make-8.txt
+cassini/home/peter/bo/2020ws/hp/20201217> touch philosophy.c
+cassini/home/peter/bo/2020ws/hp/20201217> make
+gcc -Wall -O philosophy.c -c
+gcc philosophy.o answer.o -o philosophy
+cassini/home/peter/bo/2020ws/hp/20201217>
+cassini/home/peter/bo/2020ws/hp/20201217> make -f Makefile-1
+make: „philosophy“ ist bereits aktuell.
+cassini/home/peter/bo/2020ws/hp/20201217>
diff --git a/20201217/pendulum-0.c b/20201217/pendulum-0.c
new file mode 100644
index 0000000000000000000000000000000000000000..6faebdc7ad779d89ab8e2eacd189240ace1fb406
--- /dev/null
+++ b/20201217/pendulum-0.c
@@ -0,0 +1,69 @@
+#include <gtk/gtk.h>
+#include <math.h>
+
+int width = 320;
+int height = 240;
+int gap = height / 20;
+int r = gap;
+double visual_length = height - 2 * gap - r;
+
+double phi0 = -0.5;
+double omega0 = 0.0;
+double t0 = 0.0;
+double g = 9.81;
+double l = 1.0;
+double dt = 0.02;
+
+double t = t0;
+double phi = phi0;
+double omega = omega0;
+
+gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
+{
+  GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
+
+  int x = width / 2 + visual_length * sin (phi);
+  int y = gap + visual_length * cos (phi);
+
+  gdk_cairo_set_source_rgba (c, &blue);
+  cairo_move_to (c, width / 2, gap);
+  cairo_line_to (c, x, y);
+  cairo_stroke (c);
+  cairo_arc (c, x, y, r, 0, 2 * G_PI);
+  cairo_fill (c);
+
+  return FALSE;  /* TRUE to stop other handlers from being invoked for the event.
+                    FALSE to propagate the event further. */
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  t += dt;
+  phi += omega * dt;
+  omega += - dt * g / l * sin (phi);
+
+  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);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+
+  g_timeout_add (50, (GSourceFunc) timer, drawing_area);
+
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/pendulum-1.c b/20201217/pendulum-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..44f4c4fde79d96ed604882b0d5ce22a9035e1400
--- /dev/null
+++ b/20201217/pendulum-1.c
@@ -0,0 +1,69 @@
+#include <gtk/gtk.h>
+#include <math.h>
+
+#define WIDTH 320
+#define HEIGHT 240
+#define GAP (HEIGHT / 20)
+#define r GAP
+#define visual_length (HEIGHT - 2 * GAP - r)
+
+#define phi0 (-0.5)
+#define omega0 0.0
+#define t0 0.0
+#define g 9.81
+#define l 1.0
+#define dt 0.02
+
+double t = t0;
+double phi = phi0;
+double omega = omega0;
+
+gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
+{
+  GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
+
+  int x = WIDTH / 2 + visual_length * sin (phi);
+  int y = GAP + visual_length * cos (phi);
+
+  gdk_cairo_set_source_rgba (c, &blue);
+  cairo_move_to (c, WIDTH / 2, 10);
+  cairo_line_to (c, x, y);
+  cairo_stroke (c);
+  cairo_arc (c, x, y, r, 0, 2 * G_PI);
+  cairo_fill (c);
+
+  return FALSE;  /* TRUE to stop other handlers from being invoked for the event.
+                    FALSE to propagate the event further. */
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  t += dt;
+  phi += omega * dt;
+  omega += - dt * g / l * sin (phi);
+
+  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);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+
+  g_timeout_add (50, (GSourceFunc) timer, drawing_area);
+
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/pendulum-2.c b/20201217/pendulum-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..4fbad9a50cc595e92fbb1075dd01405a08e84001
--- /dev/null
+++ b/20201217/pendulum-2.c
@@ -0,0 +1,69 @@
+#include <gtk/gtk.h>
+#include <math.h>
+
+#define WIDTH 320
+#define HEIGHT 240
+#define GAP (HEIGHT / 20)
+#define r GAP
+#define visual_length (HEIGHT - 2 * GAP - r)
+
+#define phi0 (-0.5)
+#define omega0 0.0
+#define t0 0.0
+#define g 9.81
+#define l 1.0
+#define dt 0.02
+
+double t = t0;
+double phi = phi0;
+double omega = omega0;
+
+gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
+{
+  GdkRGBA orange = { 1.0, 0.5, 0.0, 1.0 };
+
+  int x = WIDTH / 2 + visual_length * sin (phi);
+  int y = GAP + visual_length * cos (phi);
+
+  gdk_cairo_set_source_rgba (c, &orange);
+  cairo_move_to (c, WIDTH / 2, 10);
+  cairo_line_to (c, x, y);
+  cairo_stroke (c);
+  cairo_arc (c, x, y, r, 0, 2 * G_PI);
+  cairo_fill (c);
+
+  return FALSE;  /* TRUE to stop other handlers from being invoked for the event.
+                    FALSE to propagate the event further. */
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  t += dt;
+  phi += omega * dt;
+  omega += - dt * g / l * phi;
+
+  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);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+
+  g_timeout_add (50, (GSourceFunc) timer, drawing_area);
+
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/pendulum-3.c b/20201217/pendulum-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..35b0b67aeb0d11aa2a81aba204c97ca96504ad89
--- /dev/null
+++ b/20201217/pendulum-3.c
@@ -0,0 +1,86 @@
+#include <gtk/gtk.h>
+#include <math.h>
+
+#define WIDTH 320
+#define HEIGHT 240
+#define GAP (HEIGHT / 20)
+#define r GAP
+#define visual_length (HEIGHT - 2 * GAP - r)
+
+#define phi0 (-0.5)
+#define omega0 0.0
+#define t0 0.0
+#define g 9.81
+#define l 1.0
+#define dt 0.02
+
+double t = t0;
+double phi_with_sin = phi0;
+double omega_with_sin= omega0;
+double phi_without_sin = phi0;
+double omega_without_sin= omega0;
+
+void draw_pendulum (cairo_t *c, double phi, GdkRGBA *colour)
+{
+  int x = WIDTH / 2 + visual_length * sin (phi);
+  int y = GAP + visual_length * cos (phi);
+
+  gdk_cairo_set_source_rgba (c, colour);
+  cairo_move_to (c, WIDTH / 2, 10);
+  cairo_line_to (c, x, y);
+  cairo_stroke (c);
+  cairo_arc (c, x, y, r, 0, 2 * G_PI);
+  cairo_fill (c);
+}
+
+gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
+{
+  GdkRGBA blue   = { 0.0, 0.5, 1.0, 1.0 };
+  GdkRGBA orange = { 1.0, 0.5, 0.0, 1.0 };
+  GdkRGBA green  = { 0.0, 0.5, 0.0, 1.0 };
+
+  double A = phi0;
+  double B = 0.5 * M_PI;  /* 90° */
+  double phi_analytic = A * sin (sqrt (g / l) * t + B);
+
+  draw_pendulum (c, phi_with_sin, &blue);
+  draw_pendulum (c, phi_without_sin, &orange);
+  draw_pendulum (c, phi_analytic, &green);
+
+  return FALSE;  /* TRUE to stop other handlers from being invoked for the event.
+                    FALSE to propagate the event further. */
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  t += dt;
+  phi_with_sin += omega_with_sin * dt;
+  omega_with_sin += - dt * g / l * sin (phi_with_sin);
+  phi_without_sin += omega_without_sin * dt;
+  omega_without_sin += - dt * g / l * phi_without_sin;
+
+  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);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+
+  g_timeout_add (50, (GSourceFunc) timer, drawing_area);
+
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/pendulum-4.c b/20201217/pendulum-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a08e32735336064af72ce6f332299d14ff66218
--- /dev/null
+++ b/20201217/pendulum-4.c
@@ -0,0 +1,86 @@
+#include <gtk/gtk.h>
+#include <math.h>
+
+#define WIDTH 320
+#define HEIGHT 240
+#define GAP (HEIGHT / 20)
+#define r GAP
+#define visual_length (HEIGHT - 2 * GAP - r)
+
+#define phi0 (-5.0 / 180.0 * M_PI)
+#define omega0 0.0
+#define t0 0.0
+#define g 9.81
+#define l 1.0
+#define dt 0.02
+
+double t = t0;
+double phi_with_sin = phi0;
+double omega_with_sin= omega0;
+double phi_without_sin = phi0;
+double omega_without_sin= omega0;
+
+void draw_pendulum (cairo_t *c, double phi, GdkRGBA *colour)
+{
+  int x = WIDTH / 2 + visual_length * sin (phi);
+  int y = GAP + visual_length * cos (phi);
+
+  gdk_cairo_set_source_rgba (c, colour);
+  cairo_move_to (c, WIDTH / 2, 10);
+  cairo_line_to (c, x, y);
+  cairo_stroke (c);
+  cairo_arc (c, x, y, r, 0, 2 * G_PI);
+  cairo_fill (c);
+}
+
+gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
+{
+  GdkRGBA blue   = { 0.0, 0.5, 1.0, 1.0 };
+  GdkRGBA orange = { 1.0, 0.5, 0.0, 1.0 };
+  GdkRGBA green  = { 0.0, 0.5, 0.0, 1.0 };
+
+  double A = phi0;
+  double B = 0.5 * M_PI;  /* 90° */
+  double phi_analytic = A * sin (sqrt (g / l) * t + B);
+
+  draw_pendulum (c, phi_with_sin, &blue);
+  draw_pendulum (c, phi_without_sin, &orange);
+  draw_pendulum (c, phi_analytic, &green);
+
+  return FALSE;  /* TRUE to stop other handlers from being invoked for the event.
+                    FALSE to propagate the event further. */
+}
+
+gboolean timer (GtkWidget *widget)
+{
+  t += dt;
+  phi_with_sin += omega_with_sin * dt;
+  omega_with_sin += - dt * g / l * sin (phi_with_sin);
+  phi_without_sin += omega_without_sin * dt;
+  omega_without_sin += - dt * g / l * phi_without_sin;
+
+  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);
+  g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
+
+  g_timeout_add (50, (GSourceFunc) timer, drawing_area);
+
+  gtk_main ();
+  return 0;
+}
diff --git a/20201217/philosophy.c b/20201217/philosophy.c
new file mode 100644
index 0000000000000000000000000000000000000000..e9f508a501d9ec66d02e0636a9f6c71f2c7a8594
--- /dev/null
+++ b/20201217/philosophy.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include "answer.h"
+
+int main (void)
+{
+  printf ("The answer is %d.\n", answer ());
+  return 0;
+}