From 8084c1e15fbb081948699e0999cbd7d87ba82fc2 Mon Sep 17 00:00:00 2001 From: Martin Puppe Date: Sat, 8 Aug 2020 14:30:21 +0200 Subject: [PATCH] Import old blog posts --- posts/2012-02-22-warum-octopress.markdown | 37 +++ ...-2012-protest-gegen-acta-in-trier.markdown | 11 + ...-kaputte-symbolische-links-finden.markdown | 16 ++ posts/2012-03-29-resumelater-0-dot-1.markdown | 22 ++ posts/2012-05-07-xml-schema.markdown | 37 +++ ...2012-08-03-closures-in-javascript.markdown | 181 ++++++++++++++ ...unter-debian-squeeze-installieren.markdown | 234 ++++++++++++++++++ ...unter-linux-einen-proxy-verwenden.markdown | 41 +++ ...torrent-sync-auf-qnap-nas-geraten.markdown | 36 +++ ...e-root-rechte-hosten-mit-gitolite.markdown | 184 ++++++++++++++ ...y-builds-into-your-home-directory.markdown | 97 ++++++++ ...15-06-28-fundstucke-27-slash-2015.markdown | 53 ++++ ...15-07-05-fundstucke-28-slash-2015.markdown | 44 ++++ ...15-08-03-fundstucke-31-slash-2015.markdown | 39 +++ ...15-08-09-fundstucke-32-slash-2015.markdown | 20 ++ ...15-08-17-fundstucke-33-slash-2015.markdown | 37 +++ ...15-08-25-fundstucke-34-slash-2015.markdown | 34 +++ ...15-08-31-fundstucke-35-slash-2015.markdown | 24 ++ ...15-09-15-fundstucke-37-slash-2015.markdown | 28 +++ ...15-09-20-fundstucke-38-slash-2015.markdown | 18 ++ ...15-09-27-fundstucke-39-slash-2015.markdown | 21 ++ ...15-11-02-fundstucke-44-slash-2015.markdown | 26 ++ posts/2016-04-03-knobeln-mit-clojure.markdown | 144 +++++++++++ 23 files changed, 1384 insertions(+) create mode 100644 posts/2012-02-22-warum-octopress.markdown create mode 100644 posts/2012-02-24-25-dot-02-dot-2012-protest-gegen-acta-in-trier.markdown create mode 100644 posts/2012-02-24-kaputte-symbolische-links-finden.markdown create mode 100644 posts/2012-03-29-resumelater-0-dot-1.markdown create mode 100644 posts/2012-05-07-xml-schema.markdown create mode 100644 posts/2012-08-03-closures-in-javascript.markdown create mode 100644 posts/2013-03-15-hadoop-unter-debian-squeeze-installieren.markdown create mode 100644 posts/2013-04-15-unter-linux-einen-proxy-verwenden.markdown create mode 100644 posts/2013-05-21-bittorrent-sync-auf-qnap-nas-geraten.markdown create mode 100644 posts/2014-05-23-git-repositories-ohne-root-rechte-hosten-mit-gitolite.markdown create mode 100644 posts/2014-11-26-installing-rust-nightly-builds-into-your-home-directory.markdown create mode 100644 posts/2015-06-28-fundstucke-27-slash-2015.markdown create mode 100644 posts/2015-07-05-fundstucke-28-slash-2015.markdown create mode 100644 posts/2015-08-03-fundstucke-31-slash-2015.markdown create mode 100644 posts/2015-08-09-fundstucke-32-slash-2015.markdown create mode 100644 posts/2015-08-17-fundstucke-33-slash-2015.markdown create mode 100644 posts/2015-08-25-fundstucke-34-slash-2015.markdown create mode 100644 posts/2015-08-31-fundstucke-35-slash-2015.markdown create mode 100644 posts/2015-09-15-fundstucke-37-slash-2015.markdown create mode 100644 posts/2015-09-20-fundstucke-38-slash-2015.markdown create mode 100644 posts/2015-09-27-fundstucke-39-slash-2015.markdown create mode 100644 posts/2015-11-02-fundstucke-44-slash-2015.markdown create mode 100644 posts/2016-04-03-knobeln-mit-clojure.markdown diff --git a/posts/2012-02-22-warum-octopress.markdown b/posts/2012-02-22-warum-octopress.markdown new file mode 100644 index 0000000..7e9c280 --- /dev/null +++ b/posts/2012-02-22-warum-octopress.markdown @@ -0,0 +1,37 @@ +--- +layout: post +title: "Warum Octopress?" +date: 2012-02-23 11:16 +comments: true +categories: Octopress +description: "Vor- und Nachteile von Octopress" +keywords: "octopress vorteile, octopress nachteile" +--- + +Die Auswahl an Software zum Hosten eines Weblogs ist groß. Zum einen gibt es die Spezialisten wie bspw. [Wordpress](http://wordpress.org/) oder [Serendipity](http://www.s9y.org/), zum anderen ist fast jedes der [unzähligen Content-Management-Systeme](http://en.wikipedia.org/wiki/Comparison_of_content_management_systems) mehr oder weniger gut für Blogs geeignet. Und nicht zuletzt bieten Dienste wie [Blogger](http://www.blogger.com/) und (wieder) [Wordpress](http://wordpress.com/) schlüsselfertig eine kostenlose Webpräsenz. + +Ich habe mich nach einiger Überlegung für [Octopress](http://octopress.org) entschieden. Octopress ist kein Content-Management-System im eigentlichen Sinne. Man erstellt seine Blogposts lokal in einer simplen Textdatei mit einem beliebigen Editor. Die Formatierung erfolgt mittels [Markdown](http://de.wikipedia.org/wiki/Markdown). Octopress generiert aus diesen Dateien die Website. Das Ergebnis besteht fast ausschließlich aus HTML und Javascript. Und hier wird klar, was Octopress so einzigartig macht: **Es gibt keine serverseitigen Abhängigkeiten.** Datenbanksystem, PHP, Python, Ruby etc., alles nicht notwendig! + +## Vorteile + +Daraus ergeben sich eine Reihe interessanter Vorteile: + +- *Freie Wahl der Plattform*: Da es keine Abhängigkeiten gibt, kann man ein Octopress-Blog quasi überall hosten. Ich nutze beispielsweise im Moment [Github Pages](http://pages.github.com/). Eine interessante Alternative ist sicher auch [Amazon S3](http://www.ianwootten.co.uk/2011/09/09/hosting-an-octopress-blog-on-amazon-s3). Nicht zuletzt macht das Octopress zu einer ziemlich *günstigen* Angelegenheit. Denn ein bisschen Webspace inklusive .de-Domain ist schon für unter zwei Euro monatlich zu haben. +- *Einfache Migration*: Um mit einem Octopress-Blog auf einen anderen Server zu ziehen, reicht einfaches Kopieren der Dateien. +- *Relativ einfach aufzusetzen*: Dazu verweise ich auf die [offizielle Anleitung](http://octopress.org/help/). Mit ein paar einfachen Schritten hat man schnell eine "Entwicklungsumgebung". Für die Grundkonfiguration reicht es Basis-URL, Titel, Untertitel und Autor anzugeben. +- *Einfache Bedienung*: Mit `rake new_post["title"]` wird ein neuer Post erstellt. `rake preview` erzeugt die fertige Website und startet praktischerweise gleich einen Webserver unter http://localhost:4000. Änderungen an den Quelldateien werden umgehend übernommen. Um die Änderungen schließlich ins Netz zu laden, reicht ein einfaches `rake generate && rake deploy`. + +## Nachteile + +Nach all dem Lob, möchte ich die Nachteile aber nicht verschweigen: + +- Da ein Octopress-Blog statisch ist, ist man für eine *Kommentarfunktion* auf [Disqus](http://disqus.com/) angewiesen. Auch die *Suche* muss über einen externen Anbieter laufen. +- Vielleicht hat der Leser es bereits bemerkt: Man sollte sich schon ein wenig wohl fühlen im *Terminal*[^terminal]. Letztlich ist das Ganze aber relativ schmerzlos. Man muss eigentlich nur den Anleitungen folgen. Ist Octopress erst mal aufgesetzt, reichen für das Erstellen neuer Inhalte eine Handvoll Befehle. +- Man sollte sich jeweils eine halbe Stunde mit [Git](http://git-scm.com/) und [RVM](http://beginrescueend.com/) auseinandersetzen, um zu verstehen, was man tut.[^rvm] +- Um sein Blog komplett auf Deutsch zu übersetzen, sind noch einige [manuelle Anpassungen](http://www.uru.ch/blog/2011/09/12/octopress-oberflaeche-im-schnelldurchgang-auf-deutsch-uebersetzen/) notwendig. Hier würde ich mir wünschen, dass eine einzelne Änderung in der Konfigurationsdatei ausreicht. + +[^terminal]: + Übertriebene Angst vor der Kommandozeile ist meiner Meinung nach ohnehin unbegründet. + +[^rvm]: + Das kann in beiden Fällen aber ein echter Gewinn auch für andere Projekte sein. diff --git a/posts/2012-02-24-25-dot-02-dot-2012-protest-gegen-acta-in-trier.markdown b/posts/2012-02-24-25-dot-02-dot-2012-protest-gegen-acta-in-trier.markdown new file mode 100644 index 0000000..2ff2c7d --- /dev/null +++ b/posts/2012-02-24-25-dot-02-dot-2012-protest-gegen-acta-in-trier.markdown @@ -0,0 +1,11 @@ +--- +layout: post +title: "25.02.2012: Protest gegen ACTA in Trier" +date: 2012-02-24 15:44 +comments: true +categories: +keywords: "acta, trier" +--- + +Morgen wird auch in Trier gegen ACTA demonstriert: +[https://www.facebook.com/events/351070788257508/](https://www.facebook.com/events/351070788257508/) diff --git a/posts/2012-02-24-kaputte-symbolische-links-finden.markdown b/posts/2012-02-24-kaputte-symbolische-links-finden.markdown new file mode 100644 index 0000000..7b2f141 --- /dev/null +++ b/posts/2012-02-24-kaputte-symbolische-links-finden.markdown @@ -0,0 +1,16 @@ +--- +layout: post +title: "Kaputte symbolische Links finden" +date: 2012-02-24 11:21 +comments: true +categories: Bash +description: So lassen sich kaputte symbolische Links finden. +--- + +Mit folgendem Terminalbefehl lassen sich kaputte symbolische Links finden: + +``` bash +find / -type l ! -exec test -r {} \; -print +``` + +Quelle: [http://www.linuxforums.org/forum/programming-scripting/94116-how-find-dead-symbolic-links.html#post468681](http://www.linuxforums.org/forum/programming-scripting/94116-how-find-dead-symbolic-links.html#post468681) diff --git a/posts/2012-03-29-resumelater-0-dot-1.markdown b/posts/2012-03-29-resumelater-0-dot-1.markdown new file mode 100644 index 0000000..94f438e --- /dev/null +++ b/posts/2012-03-29-resumelater-0-dot-1.markdown @@ -0,0 +1,22 @@ +--- +layout: post +title: "resumeLater 0.1 veröffentlicht" +date: 2012-03-29 11:53 +comments: true +categories: resumeLater +description: resumeLater 0.1 veröffentlicht +keywords: resumelater, youtube +--- + +{% img right /images/posts/2012-03-29_resumeLater.svg 200 resumeLater %} + +resumeLater ist eine Firefox-Erweiterung. Sie erlaubt es, die aktuelle Position in einem Youtube-Video zu speichern. Später kann die Wiedergabe an exakt der selben Stelle fortgesetzt werden. Das ist vor allem praktisch bei längeren Videos (etwa von Vorträgen), die man nicht an einem Stück schauen möchte. Download bei [addons.mozilla.org](https://addons.mozilla.org/en-US/firefox/addon/resumelater/). + +In Version 0.1 wird die Video-Liste nur lokal im Browser gespeichert. Für Version 1.0 ist die Möglichkeit geplant, die Videos mit Bookmarking-Sites wie [Delicious](http://delicious.com) und [Pinboard](http://pinboard.in) zu synchronisieren. Mittelfristig ist auch eine Android-App denkbar. + +Außerdem vorgesehen: + + * Unterstützung weiterer Video-Seiten ([Vimeo](http://vimeo.com/), [Dailymotion](http://www.dailymotion.com/video/xpqx51) etc.) + * Deaktivieren bei Private Browsing + +Quellcode und Issue-Tracker auf [Github](https://github.com/puppe/resumeLater). \ No newline at end of file diff --git a/posts/2012-05-07-xml-schema.markdown b/posts/2012-05-07-xml-schema.markdown new file mode 100644 index 0000000..594d0e6 --- /dev/null +++ b/posts/2012-05-07-xml-schema.markdown @@ -0,0 +1,37 @@ +--- +layout: post +title: "XML Schema, Keys und Namespaces" +date: 2012-05-07 18:03 +comments: true +categories: XML +description: "Probleme mit XML Schema, Keys und Namespaces" +keywords: "xml schema, keys, namespaces, schlüssel, namensräume" +--- + +Bei der Erstellung von Schemas mit einem Ziel-Namensraum kann man leicht in eine kleine, facepalm-induzierende Falle tappen, die mich heute einiges an Nerven gekostet hat. Um das Problem zu erläutern sehen wir uns am besten ein Beispiel an. + +## Ohne Namensraum + +{% include_code Beispielinstanz ohne Namensraum 2012-05-07/instance.xml %} + +Das Dokument besteht aus einem Wurzelement `foo` und Kindelementen `bar`. Die `bar`-Elemente haben ein Attribut `id`. Nun wollen wir erzwingen, dass `id` ein Schlüssel ist. Die Instanz wäre dann nicht valide. Das entsprechende XML-Schema muss dazu etwa so aussehen: + +{% include_code Schema ohne Ziel-Namensraum 2012-05-07/schema.xsd lang:xml %} + +Man beachte hier vor allem die Zeilen 14 bis 16, in denen festgelegt wird, dass innerhalb des `foo`-Elements die `bar`-Elemente eindeutig durch das Schlüssel-Attribut `id` identifizierbar sein müssen. + +## Mit Namensraum + +Hier folgt eine Beispiel-Instanz, für die `http://foo.bar` als Namensraum festgelegt wurde. + +{% include_code Beispielinstanz mit Namensraum 2012-05-07/instance_namespace.xml %} + +Man könnte nun meinen, dass es ausreicht, den Namensraum entsprechend auch im Schema anzugeben. Das wurde im folgenden Beispiel in Zeile 3 und 4 getan. + +{% include_code Falsches Schema mit Zielnamensraum 2012-05-07/schema_falsch.xsd lang:xml %} + +Das Problem ist aber, dass die Beispiel-Instanz nicht als invalide erkannt wird, sondern klaglos akzeptiert wird. **Warum ist das so?** Das Problem ist der XPath-Ausdruck in Zeile 17. Damit werden alle `bar`-Elemente selektiert und sichergestellt, dass diese eine eindeutige `id` haben. Unser Ziel-Namensraum ist allerdings `http://foo.bar`. Das heißt wir wollen nicht `bar`-Elemente selektieren, sondern `http://foo.bar:bar`-Elemente. Das richtige Schema sieht deshalb so aus: + +{% include_code Richtiges Schema mit Zielnamensraum 2012-05-07/schema_richtig.xsd lang:xml %} + +Zu beachten sind die Zeilen 4 und 18. In Zeile 4 wird definiert, dass das Kürzel `foobar` für den Namensraum `http://foo.bar` steht und in Zeile 18 wird dieses Kürzel verwendet, um den *korrekten* XPath-Ausdruck zu konstruieren. diff --git a/posts/2012-08-03-closures-in-javascript.markdown b/posts/2012-08-03-closures-in-javascript.markdown new file mode 100644 index 0000000..6047323 --- /dev/null +++ b/posts/2012-08-03-closures-in-javascript.markdown @@ -0,0 +1,181 @@ +--- +layout: post +title: "Closures in Javascript (und Scala)" +date: 2012-08-03 21:37 +comments: true +categories: Javascript +keywords: "closures, javascript, scala" +--- + +Closures[^terminologie] sind meiner Meinung nach eines der +interessantesten Sprachkonstrukte von Javascript. Sie erlauben sehr +elegante Lösungen, die sonst nicht möglich wären. Was das konkret +bedeutet, werde ich an einem Beispiel erläutern. Zunächst möchte ich +aber erklären, was Closures sind. + +## Was ist eine Closure? + +**Eine Closure beinhaltet eine Funktion und (auch nicht-lokale) +Variablen, die innerhalb der Funktion referenziert werden.** Closures +verändern die Lebensdauer von Variablen. Schauen wir uns dazu ein +Beispiel an: + +``` javascript +var x = 0; + +function foo() { + var y = 42; + return x + y; +} + +x = x + 1; +``` + +Wir sehen hier zwei Variablen, `x` und `y`. Im Hinblick auf die +Sichtbarkeit unterscheiden sich die Variablen darin, dass `y` nur +*innerhalb* der Funktion `foo` sichtbar ist. Was die Lebensdauer +betrifft, so existiert `y` nur während `foo` ausgeführt wird. + +Sichtbarkeit und Lebensdauer für sich genommen sind keine schwierigen +Konzepte. Javascript ist allerdings eine funktionale Sprache und da wird +die Sache interessant. Javascript erlaubt es nämlich, Funktionen als +Rückgabewert anderer Funktionen zu verwenden. Dazu erweitern wir das +obige Beispiel. + +``` javascript +function makeFoo() { + var x = 0; + + function foo() { + var y = 41; + x = x + 1; + return x + y; + } + + return foo; +} + +var bar = makeFoo(); +console.log(bar()); +console.log(bar()); +console.log(bar()); +``` + +In der Konsole erhält man folgende Ausgabe: + +``` +42 +43 +44 +``` + +Das ist auf den ersten Blick überraschend, wenn wir davon ausgehen, dass +lokale Variablen nur existieren, solange die Funktion, in der sie +definiert wurden, ausgeführt wird. Die Variable `x` hingegen bleibt +weiterhin innerhalb der Funktion `foo` bzw. `bar` sichtbar und behält +zudem ihren Zustand, obwohl `makeFoo` vollständig abgearbeitet wurde. +*`foo` wurde zusammen mit `x` in eine Closure gepackt*. + +## Praktische Anwendung + +Das obige Beispiel ist konstruiert und in der Praxis kaum nützlich. +Closures haben aber durchaus sinnvolle Anwendungen. Stellen wir uns +einmal vor, wir wollten verschiedene Objekte mit einer eindeutigen +Nummer (einer ID) versehen. Dazu wollen wir eine Funktion `generateId` +definieren, die stets eine andere Zahl zurückliefert. Der Einfachheit +halber zählen wir von 0 aufwärts. Wir haben mehrere Möglichkeiten dieses +Problem zu lösen. + +### Möglichkeit 1: Globaler Zähler + +``` javascript +var counter = 0; + +function generateId() { + var id = counter; + counter = counter + 1; + return id; +} + +var obj = { + id: generateId() +} +``` + +Ich halte diese Lösung für nicht sehr sinnvoll. `counter` ist eine +globale Variable. D.h. wir verschmutzen hier den globalen Namensraum mit +einer Variable, die nur für eine einzige Funktion benötigt wird. +Außerdem kann die Variable praktisch an jeder Stelle im Programm +versehentlich geändert werden. Und es wird überhaupt nicht klar, dass +counter` und `generateId` zusammengehören. + +### Möglichkeit 2: Zähler und Funktion in einem Objekt + +``` javascript +var idGenerator = { + counter: 0, + generateId: function() { + var id = this.counter; + this.counter = this.counter + 1; + return id; + } +}; + +var obj = { + id: idGenerator.generateId() +} +``` + +Diese Lösung ist schon etwas besser, in der Hinsicht, dass wir auf eine +globale Variable `counter` verzichten. Auch wird der Zusammenhang von +`counter` und `generateId` deutlicher. Allerdings ist diese Variante +unhandlich in der Verwendung (`idGenerator.generateId()`). Außerdem kann +auch hier `counter` an anderer Stelle im Programm geändert werden, +obwohl die Variable einzig und allein von der Funktion `generateId` +manipuliert werden sollte. + +### Möglichkeit 3: Closure + +``` javascript +var generateId = (function() { + var counter = 0; + return function() { + var id = counter; + counter = counter + 1; + return id; + }; +})(); + +var obj = { + id: generateId() +} +``` + +Ich halte diese Lösung für die eleganteste. Der Zusammenhang von +`counter` und `generateId` wird deutlich und der Zähler ist außerhalb +der Funktion überhaupt nicht sichtbar. + +## Anhang: Das Beispiel in Scala + +Closures gibt es nicht nur in Javascript, sondern in wohl jeder +funktionalen Programmiersprache. Ich habe mich kürzlich im Rahmen einer +Vorlesung mit Scala beschäftigen dürfen, daher hier das obige Beispiel +in Scala: + +``` scala +val generateId = (() => { + var counter = 0 + () => { + var id = counter; + counter = counter + 1; + id + } +}).apply() +``` + +[^terminologie]: + Kurz zur Terminologie: Das deutsche Wort für „function +closure“ ist wohl „Funktionsabschluss“. Allerdings hat +man wenig Glück, wenn man danach googlet. Mir scheint der Begriff nicht +sehr gebräuchlich zu sein, also bleibe ich bei der englischen +Bezeichnung. diff --git a/posts/2013-03-15-hadoop-unter-debian-squeeze-installieren.markdown b/posts/2013-03-15-hadoop-unter-debian-squeeze-installieren.markdown new file mode 100644 index 0000000..3a0f675 --- /dev/null +++ b/posts/2013-03-15-hadoop-unter-debian-squeeze-installieren.markdown @@ -0,0 +1,234 @@ +--- +layout: post +title: "Hadoop unter Debian Squeeze installieren" +date: 2013-03-15 12:09 +comments: true +categories: Linux +keywords: "hadoop, installation, debian" +--- + +Im folgenden Artikel beschreibe ich, wie Hadoop unter Debian Squeeze im +sogenannten *pseudo-verteilten* Modus installiert werden kann. Den Text +habe ich im Rahmen meiner Tätigkeit als studentische Hilfskraft beim +*Leibniz-Zentrum für Psychologische Information und Dokumentation* +([ZPID](http://www.zpid.de/)) für ein internes Wiki verfasst. Da ich +denke, dass diese Anleitung auch für andere nützlich sein könnte, +veröffentliche ich sie auch hier im Blog. + +---------------------- + +Die wichtigsten Bestandteile von Hadoop sind: + +* Hadoop Distributed File System (im Folgenden HDFS) +* Hadoop MapReduce (im Folgenden HMR) + +Beide folgen einer Master/Slave-Architektur. Der Master-Dienst heißt bei +HDFS NameNode, der Slave-Dienst DataNode. Bei HMR ist der sogenannte +JobTracker der Master und die TaskTracker sind die Slaves. +Typischerweise besteht ein Hadoop-Cluster aus mindestens drei Arten von +Maschinen: + +* Ein dedizierter NameNode +* Ein dedizierter JobTracker +* Mehrere Maschinen, auf denen sowohl der DataNode- als auch der + TaskTracker-Dienst läuft + +Als Einstieg in den Betrieb eines Hadoop-Clusters, und um Programme zu +testen, die das HMR-Framework verwenden, bietet es sich an, erst einmal +alle Dienste auf einer einzigen Maschine laufen zu lassen. Dieser +Operationsmodus wird als *pseudo-verteilt* bezeichnet. + +Wir gehen von folgenden Voraussetzungen aus: + +* Betriebssystem: Debian 6 Squeeze (sollte aber auch für die meisten + anderen Debian-basierten Distributionen funktionieren) +* Installierte Java Runtime Environment 6 (hier das Paket + `openjdk-6-jre-headless`) + +## Installation + +Download-Links sind unter zu +finden. Wir laden z.B. die aktuelle stabile Version für x86-Systeme und +deren Signatur von einem Spiegel-Server herunter: + +``` sh +wget http://mirror.synyx.de/apache/hadoop/common/hadoop-1.0.4/hadoop_1.0.4-1_i386.deb +wget http://mirror.synyx.de/apache/hadoop/common/hadoop-1.0.4/hadoop_1.0.4-1_i386.deb.asc +``` + +Außerdem laden wir die Datei KEYS von einem Server der *Apache +Foundation* und importieren die Schlüssel in den GPG-Schlüsselring. +Anschließend verifizieren wir die Signatur. + +``` sh +wget http://www.eu.apache.org/dist/hadoop/common/KEYS +gpg --import KEYS +gpg --verify hadoop_1.0.4-1_i386.deb.asc +``` + +Schließlich installieren wir das Paket: + +``` sh +sudo dpkg -i hadoop_1.0.4-1_i386.deb +``` + +Bei der Installation werden automatisch die Gruppe `hadoop` und die +Benutzer `hdfs` und `mapred` angelegt. + +## Konfiguration + +Zunächst müssen unter `/etc/hadoop` die Dateien `core-site.xml`, +`hdfs-site.xml` und `mapred-site.xml` mit folgendem Inhalt angelegt +werden: + +``` xml core-site.xml + + + fs.default.name + hdfs://localhost:9000 + + +``` + +``` xml hdfs-site.xml + + + dfs.replication + 1 + + + dfs.name.dir + /var/local/lib/hadoop-dfs/name + + + dfs.data.dir + /var/local/lib/hadoop-dfs/data + + +``` + +``` xml mapred-site.xml + + + mapred.job.tracker + localhost:9001 + + + mapred.system.dir + /hadoop/mapred/system + + + mapreduce.jobtracker.staging.root.dir + /user + + +``` + +Eine Übersicht über alle Konfigurationsoptionen und deren Standardwerte +findet sich unter: + +* `core`: +* `hdfs`: +* `mapred`: + +Zuletzt müssen wir noch sicherstellen, dass die Umgebungsvariable +`JAVA_HOME` korrekt gesetzt wird. Dazu bearbeiten wir die Datei +`/etc/hadoop/hadoop-env.sh` bearbeiten. Wir ersetzen die Zeile + +``` sh +export JAVA_HOME=/usr/lib/jvm/java-6-sun +``` + +durch + +``` sh +export JAVA_HOME=/usr/lib/jvm/java-6-openjdk +``` + +*Wichtig!* Damit die letzte Änderung wirksam wird, müssen wir uns aus- +und wieder einloggen. Mittels `echo $JAVA_HOME` kann überprüft werden, +ob die Variable richtig gesetzt ist. + +## Erstes Starten der Dienste + +Wir werden zuerst das HDFS und dann HMR starten. + +### HDFS starten + +Bevor wir HDFS starten, müssen wir die lokalen Ordner erstellen, in +denen die Daten des HDFS abgelegt werden. Es handelt sich dabei, um die +Ordner die zuvor in der Konfigurationsdatei `hdfs-site.xml` festgelegt +wurden. Anschließend wirds verteilte Dateisystem formatiert. Einige der +Operationen müssen als Benutzer `hdfs` ausgeführt werden. In diesen +Fällen steht am Beginn des Befehls `sudo -u hdfs`. + +``` sh +sudo mkdir -p /var/lib/local/hadoop-dfs +sudo chown hdfs:hadoop /var/lib/local/hadoop-dfs +sudo -u hdfs mkdir /var/lib/local/hadoop-dfs/name /var/lib/local/hadoop-dfs/data +sudo -u hdfs hadoop namenode -format +``` + +Nun können wir den NameNode-Dienst und den DataNode-Dienst starten. + +``` sh +sudo service hadoop-namenode start +sudo service hadoop-datanode start +``` + +Nun sollte es möglich sein unter den aktuellen +Status des NameNodes und der DataNodes zu einzusehen. + +Sollte irgendetwas nicht funktionieren, hilft es bei der Diagnose der +Probleme einen Blick in die Log-Dateien zu werfen. Diese werden unter +`/var/log/hadoop` abgelegt. Fehler des NameNode-Dienstes bspw. findet +man unter `/var/log/hadoop/hadoop--namenode-HOSTNAME.log`. Wobei +`HOSTNAME` durch den tatsächlichen Hostnamen bzw. Rechnernamen ersetzt +werden muss. + +### HMR starten + +Bevor wir die Dienste für MapReduce starten können, müssen wir im HDFS +das Verzeichnis `/hadoop/mapred/system` anlegen und `mapred` als +Besitzer des Verzeichnisses festlegen. + +``` sh +sudo -u hdfs hadoop fs -mkdir /hadoop/mapred/system +sudo -u hdfs hadoop fs -chown -R mapred:hadoop /hadoop/mapred +``` + +Mittels `hadoop fs -ls /hadoop/mapred`, können wir uns davon überzeugen, +dass der Ordner mit den richtigen Rechten erstellt wurde. + +Nun können wir die TaskTracker- und JobTracker-Dienste starten: + +``` sh +sudo service hadoop-jobtracker start +sudo service hadoop-tasktracker start +``` + +Hat alles geklappt, lässt sich unter der Status +des TaskTrackers und der JobTracker einsehen. + +### Benutzer-Verzeichnis erstellen + +``` sh +sudo -u hdfs hadoop fs -mkdir /user/BENUTZER +sudo -u hdfs hadoop fs -chown BENUTZER:GRUPPE /user/BENUTZER +``` + +## Ein Beispiel-Programm ausführen + +Unsere Hadoop-Installation testen wir mit einem Beispiel-Programm aus, +das in der Hadoop-Distribution enthalten ist. Zunächst kopieren wir die +Eingabedaten in das verteilte Dateisystem, dann führen wir das Programm +aus, und schließlich kopieren wir die Ausgabedaten des Programms auf das +lokale Dateisystem. + +``` sh +hadoop fs -put /usr/share/hadoop/templates/conf/ input +hadoop jar /usr/share/hadoop/hadoop-examples-1.0.4.jar grep input output 'dfs[a-z.]+' +hadoop fs -get output output +``` + +Mittels `cat output/*` können wir uns das Ergebnis ansehen. diff --git a/posts/2013-04-15-unter-linux-einen-proxy-verwenden.markdown b/posts/2013-04-15-unter-linux-einen-proxy-verwenden.markdown new file mode 100644 index 0000000..94f7ec3 --- /dev/null +++ b/posts/2013-04-15-unter-linux-einen-proxy-verwenden.markdown @@ -0,0 +1,41 @@ +--- +layout: post +title: "Unter Linux einen Proxy verwenden" +date: 2013-04-15 21:11 +comments: true +categories: Linux +description: "Wie man unter Linux einen Proxy-Server verwendet, aber dennoch auf bestimmte Rechner direkt zugreift." +keywords: "linux, proxy, ausnahmen, no_proxy" +--- + +Manchmal ist man in Netzwerken unterwegs, deren Firewall erst mal +jeglichen Netzwerkverkehr blockt. Um den Benutzern dennoch zu +ermöglichen, zumindest auf das Web zuzugreifen, wird dann meist ein +Proxy-Server zur Verfügung gestellt, der zwischen den Benutzern und dem +eigentlichen Ziel der Anfragen vermittelt. + +Nehmen wir einmal an, dass der Proxy-Server unter der IP-Adresse +192.168.0.42 erreichbar ist und auf Port 8080 lauscht. Dann muss in die +Datei `/etc/profile` folgendes eingetragen werden: + +``` bash +export http_proxy=http://192.168.0.42:8080 +export https_proxy=http://192.168.0.42:8080 +export ftp_proxy=http://192.168.0.42:8080 +export HTTP_PROXY=$http_proxy +export HTTPS_PROXY=$https_proxy +export FTP_PROXY=$ftp_proxy +``` + +Was aber, wenn man für manche Anfragen explizit *keinen* Proxy-Server +verwenden will, z.B. weil man auf Dienste zugreifen will, die auf dem +eigenen Rechner oder innerhalb des lokalen Netzwerkes laufen? Dazu dient +die Umgebungsvariable `no_proxy`. Möchte man beispielsweise für Anfragen +an `localhost` oder die IP-Adresse 192.168.0.10 keinen Proxy verwenden, +so sollte der Datei `/etc/profile` folgende Zeile hinzugefügt werden: + +``` bash +export no_proxy=localhost,192.168.0.10 +``` + + diff --git a/posts/2013-05-21-bittorrent-sync-auf-qnap-nas-geraten.markdown b/posts/2013-05-21-bittorrent-sync-auf-qnap-nas-geraten.markdown new file mode 100644 index 0000000..ec2a358 --- /dev/null +++ b/posts/2013-05-21-bittorrent-sync-auf-qnap-nas-geraten.markdown @@ -0,0 +1,36 @@ +--- +layout: post +title: "BitTorrent Sync auf QNAP-NAS-Geräten" +date: 2013-05-21 17:31 +comments: true +categories: Linux +--- + +[Dropbox](http://db.tt/RfeVRSy) (Referral-Link) ist an sich eine schöne +Sache. Einfach Dateien in einen Ordner werfen, und auf jedem Gerät, das +man mit seinem Dropbox-Account verbindet, wird dieser Ordner +synchronisiert. Das erlaubt mir beispielsweise, überall auf die Dateien +zuzugreifen, die ich für die Uni brauche. Aber Dropbox hat auch +Nachteile. Es ist mit einem Dollar pro Jahr und Gigabyte recht teuer. +Außerdem hat Dropbox jederzeit Zugriff, auf die Daten, die man ihnen +anvertraut. + +Und hier kommt [BitTorrent Sync](http://labs.bittorrent.com/experiments/sync.html) +ins Spiel. Das Programm erlaubt es, beliebig große Ordner zwsichen +beliebig vielen Rechnern verschlüsselt über das BitTorrent-Protokoll zu +synchronisieren. BitTorrent Sync ist zwar erst in der Alpha-Phase, läuft +aber bereits recht stabil. + +Die Synchronisierung zwischen zwei Rechnern funktioniert natürlich nur, +wenn beide Rechner gleichzeitig eingeschaltet sind. Um eine mit Dropbox +vergleichbare Funktionalität zu bekommen, braucht man also einen Server, +der rund um die Uhr eingeschaltet ist, oder zumindest immer dann, wenn +einer der anderen Rechner läuft. Dafür kommt beispielsweise ein +[NAS-Server](http://de.wikipedia.org/wiki/Network_Attached_Storage) in +Frage, wie sie etwa von [QNAP](http://www.qnap.com/) hergestellt werden. + +Und damit kommen wir zum eigentlichen Inhalt dieses Artikels. Ich hatte +am Pfingst-Wochenende etwas Zeit zum Experimentieren und habe BitTorrent +Sync auf meinem QNAP-NAS zum Laufen bekommen. Eine Anleitung und die +benötigten Skripte sind unter zu +finden. diff --git a/posts/2014-05-23-git-repositories-ohne-root-rechte-hosten-mit-gitolite.markdown b/posts/2014-05-23-git-repositories-ohne-root-rechte-hosten-mit-gitolite.markdown new file mode 100644 index 0000000..5e8c759 --- /dev/null +++ b/posts/2014-05-23-git-repositories-ohne-root-rechte-hosten-mit-gitolite.markdown @@ -0,0 +1,184 @@ +--- +layout: post +title: "Git-Repositories ohne Root-Rechte hosten mit Gitolite" +date: 2014-05-23 13:04:45 +0200 +comments: true +categories: Linux +keywords: gitolite, git +--- + +Über die Vorzüge von [Git](http://git-scm.com/) brauche ich an dieser +Stelle nicht viele Worte verlieren. Das verteilte Versionkontrollsystem +ist bei der Software-Entwicklung ein äußerst nützliches Werkzeug. Ein +Server ist dabei nicht unbedingt notwendig, um es zu verwenden. Aber ein +zentrales Repository, das immer erreichbar ist, hat durchaus einige +Vorteile. In diesem Artikel möchte ich zeigen, wie einfach es ist, für +einzelne Benutzer oder für Gruppen Repositories auf einem Server zu +hosten. Und das Beste dabei ist: mehr als einen SSH-Zugang mit einfachen +Benutzerrechten braucht man dazu nicht! + +Im Folgenden gehen wir davon aus, dass ein SSH-Zugang mit dem +Benutzernamen "benutzer" auf dem Server "server" vorhanden ist. + +## Einzelne Benutzer + +Möchte man ganz allein an einem Repository arbeiten, so ist die +Einrichtung besonders simpel. Es reicht aus, auf dem Server mit `git +init --bare repo.git`[^endung] ein "nacktes" Repository zu erzeugen, +also ein Repository das keine Arbeitsverzeichnis enthält. Unter der +Annahme, dass der vorhergehende Befehl im Verzeichnis $HOME/git des +Servers ausgeführt wurde, kann auf der lokalen Maschine jetzt mittels +`git clone benutzer@server:git/repo.git` ein Klon des Repositories +erstellt werden. Mit `git push` und `git pull` Änderungen zwischen +lokalem und entferntem Repository übermittelt werden. + +## Gruppen + +Nehmen wir nun an, dass wir auch anderen Personen lesenden oder +schreibenden Zugriff auf ein oder mehrere Repositories gewähren wollen. +Außerdem nehmen wir an, dass wir diesen Personen nur den Zugriff auf die +Repositories nicht aber auf unser komplettes Benutzerkonto gestatten +wollen. Ohne die notwendigen Rechte, um eigens dafür eine Unix-Gruppe zu +erstellen, scheint das Problem nur schwierig zu lösen zu sein. Doch dank +[gitolite](http://gitolite.com/gitolite/index.html) kann man einen +anderen Weg gehen. Neben Git muss der Server dazu nur zwei +Voraussetzungen erfüllen: + +1. der Server muss SSH-Authentifizierung mittels Schlüsselpaar erlauben, + und +2. es muss ein Perl-Interpreter vorhanden sein. + +Beides sollte unter den meisten Unix-Systemen gegeben sein. + +Kurz zur Funktionsweise von Gitolite. SSH erlaubt die Authentifizierung +mittels +[Schlüsselpaar](https://de.wikipedia.org/wiki/Asymmetrisches_Kryptosystem). +Gitolite nutzt diesen Mechanismus, um am Schlüssel zu erkennen, welcher +Gitolite-Benutzer sich einloggt. Gitolite erlaubt dabei aber den +Benutzern nur den Zugriff auf die Git-Repositories nicht auf den +vollständigen Benutzer-Account. + +### Gitolite einrichten + +Als erstes erstellen wir auf dem lokalen Rechner ein SSH-Schlüsselpaar. +Dazu wird das Kommando `ssh-keygen` verwendet. Die Voreinstellung für +den Dateinamen kann man mit Return bestätigen. Es ist ratsam eine gute +Passphrase zu verwenden[^pass]. Den öffentlichen Teil des soeben +erzeugten Schlüsselpaares kopiert man nun auf den Server. Der Name der +Datei auf dem Server kann dabei frei gewählt werden, und entspricht dem +Namen unter dem Gitolite den Benutzer später kennen wird (hier: +"alice"). + +``` bash +scp $HOME/.ssh/id_rsa.pub benutzer@server:alice.pub +``` + +Nun loggen wir uns auf dem Server ein und stellen mittels `echo $PATH` +sicher, dass der Ordner `bin` im Homeverzeichnis existiert und Teil des +Suchpfads für ausführbare Dateien ist. Falls nicht: + +``` bash +mkdir $HOME/bin +export PATH=$HOME/bin:$PATH +``` + +Damit die Änderung von `$PATH` auch nach dem Schließen des Terminals +oder dem Ausloggen erhalten bleibt, trägt man die zweite Zeile außerdem +in die Datei `$HOME/.profile` oder `$HOME/.bashrc` ein. + +Nun wird Gitolite installiert und initialisiert. Hier im Beispiel wird +Gitolite in das Verzeichnis `$HOME/src/gitolite` installiert. + +``` bash +mkdir $HOME/src +cd $HOME/src +git clone git://github.com/sitaramc/gitolite +gitolite/install -ln +cd $HOME +gitolite setup -pk alice.pub +``` + +Falls vorher schon der selbe SSH-Schlüssel zur Anmeldung verwendet +wurden, wird nach der Eingabe des letzten Befehls eventuell eine Warnung +angezeigt. Der Grund ist, dass der Schlüssel nun doppelt in der Datei +`$HOME/.ssh/authorized_keys` vorhanden ist. Falls dies der Fall ist, +sollte der entsprechende alte Eintrag entfernt werden. **ACHTUNG**: Mit +dem Schlüssel ist dann aber keine Anmeldung mehr mit vollem +Shell-Zugriff möglich, es sei denn der folgende Schritt wird ausgeführt. + +### Einem Gitolite-Nutzer Shell-Zugriff erlauben + +Dem Gitolite-Nutzer (hier "alice") dem der eigentliche SSH-Zugang +gehört, sollte man vollen Zugriff auf den (Unix-)Nutzeraccount gewähren. +Dazu wird zunächst der Befehl `echo alice +> $HOME/.gitolite.shell-users` ausgeführt. Dann wird an zwei Stellen die +Datei `$HOME/.gitoliterc` bearbeitet. Die erste Stelle ist die folgende +Zeile: + +``` perl +# SHELL_USERS_LIST => "$ENV{HOME}/.gitolite.shell-users", +``` + +Hier wird das Zeichen # entfernt. Die zweite Stelle sieht so aus: + +``` perl +# give some users direct shell access +# 'Shell', +``` + +Auch hier wird in der zweiten Zeile das # entfernt. Anschließend muss +noch der Befehl `gitolite compile; gitolite trigger POST_COMPILE` +ausgeführt werden. + +### Administration von Gitolite + +Damit ist die Einrichtung von Gitolite abgeschlossen. Nun stellt sich +die Frage, wie man weitere Benuter und Repositories hinzufügt. In +Gitolite wird die gesamte Administration über ein dafür bei der +Initialisierung erzeugtes Repository abgewickelt. Auf dem lokalen +Rechner wird dieses daher erst mal geklont: + +``` bash +git clone benutzer@server:gitolite-admin.git +``` + +In diesem Repository befinden sich zwei Unterverzeichnisse, `conf` und +`keydir`. Benutzer kann man nun einfach hinzufügen, indem man deren +öffentliche Schlüssel nach `keydir` kopiert und sie nach dem Schema +`name.pub` benennt. + +Um Repositories hinzuzufügen muss die Datei `conf/gitolite.conf` +bearbeitet werden. Ein Beispieleintrag sähe folgendermaßen aus: + +``` text gitolite-admin/conf/gitolite.conf +repo foo + RW+ = alice + R = bob + RW = eve +``` + +In diesem Beispiel hat Alice darf lesen, schreiben und Rewinds +durchführen; Bob darf nur lesen; Eve darf lesen und schreiben, aber +keine Rewinds durchführen. + +Nachdem Änderungen durchgeführt wurden, müssen diese committet werden und +auf den Server gepusht werden. Erst dann werden sie wirksam und hier im +Beispiel wird das Repository foo erstellt. Anschließend kann etwa Eve +mit + +``` bash + git clone benutzer@server:foo.git +``` + +das Repository klonen. Wobei der Unix-Benuter "benutzer" für alle +Gitolite-Benutzer der selbe ist. + +[^endung]: + Die Endung ".git" ist dabei nicht notwendig, aber per Konvention + werden so nackte Repositories kenntlich gemacht, um sie von normalen + Repositories zu unterscheiden. + +[^pass]: + Eine gute Methode, um sichere Passphrasen zu erzeugen, die dennoch + leicht zu merken sind, ist + [Diceware](http://world.std.com/~reinhold/diceware.html). diff --git a/posts/2014-11-26-installing-rust-nightly-builds-into-your-home-directory.markdown b/posts/2014-11-26-installing-rust-nightly-builds-into-your-home-directory.markdown new file mode 100644 index 0000000..da93f5d --- /dev/null +++ b/posts/2014-11-26-installing-rust-nightly-builds-into-your-home-directory.markdown @@ -0,0 +1,97 @@ +--- +layout: post +title: "Installing Rust nightly builds into your home directory" +date: 2014-11-26 23:53:52 +0100 +comments: true +categories: Rust +description: "How to install Rust into your home directory" +keywords: "rust, rust lang, home directory, sudo, root" +--- + +Currently, the easiest way to get up and running with +[Rust](http://www.rust-lang.org/) is to run the following command in +your shell: + + curl -s https://static.rust-lang.org/rustup.sh | sudo sh + +This will install Rust into `/usr/local` and you usually need root +permissions to do that. I had been looking for an alternative for two +reasons: + +* On my Macbook, `/usr/local` is mostly managed by + [Homebrew](http://brew.sh/) and `brew doctor` complains if it finds + libraries that were put there by someone else. +* I don't have root permissions at the university computer lab. + +Fortunately, installing Rust into `$HOME` is relatively painless. +`rustup.sh` lets you specify a custom prefix. The above command only has +to be slightly tweaked: + + curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --prefix=$HOME/.local + +Once Rust has been installed, there's still three things left to do. + +1. Put `rustc` etc. on your $PATH. +2. Tell `rustc` where to find the Rust libraries. +3. Tell `man` where to find the manual pages. + +The first two points can be accomplished by adding the following to your +`$HOME/.bashrc` or `$HOME/.zshrc`: + +``` bash +if [ -d $HOME/".local/bin" ] ; then + export PATH="$HOME/.local/bin:$PATH" +fi + +rust_dyld=$HOME/.local/lib/rustlib/x86_64-apple-darwin/lib +if [ ! -d $rust_dyld ] ; + rust_dyld=$HOME/.local/lib/rustlib/x86_64-unknown-linux-gnu/lib +fi + +if [ -d $rust_dyld ] ; then + if [ -z $DYLD_LIBRARY_PATH ] ; then + export DYLD_LIBRARY_PATH=$rust_dyld + else + export DYLD_LIBRARY_PATH=$rust_dyld:$DYLD_LIBRARY_PATH + fi +fi + +unset rust_dyld +``` + +Note: Take a look at lines 5 to 8. You should check whether either of +these two directories actually exists. If not, you have to modify those +lines accordingly. + +If you are using [fish](http://fishshell.com/), put this into +`$HOME/.config/fish/config.fish` instead: + +``` plain +if test -d $HOME/.local/bin + set -gx PATH $HOME/.local/bin $PATH +end + +set -l rust_dyld $HOME/.local/lib/rustlib/x86_64-apple-darwin/lib +if test ! -d $rust_dyld + set rust_dyld $HOME/.local/lib/rustlib/x86_64-unknown-linux-gnu/lib +end + +if test -d $rust_dyld + set -gx DYLD_LIBRARY_PATH $rust_dyld $DYLD_LIBRARY_PATH +end +``` + +Now we need to tell `man` where to find the manual pages. Add the +following line to `$HOME/.manpath`: + + MANPATH_MAP /Users/martin/.local/bin /Users/martin/.local/share/man + +Finally, start a new terminal session and try the following: + + rustc --version + man rustc + +If you later want to upgrade to the latest nightly, just rerun +`rustup.sh` (like above): + + curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --prefix=$HOME/.local diff --git a/posts/2015-06-28-fundstucke-27-slash-2015.markdown b/posts/2015-06-28-fundstucke-27-slash-2015.markdown new file mode 100644 index 0000000..0b71b59 --- /dev/null +++ b/posts/2015-06-28-fundstucke-27-slash-2015.markdown @@ -0,0 +1,53 @@ +--- +layout: post +title: "Fundstücke 27/2015" +date: 2015-06-28 21:20:01 +0200 +comments: true +categories: Fundstücke +--- + +Statt gelegentlich Links kommentarlos über Twitter zu verteilen, will +ich in Zukunft hier im Blog mehr oder weniger (eher weniger) regelmäßig +auf interessante Artikel, Vorträge, Musik etc. verweisen. + +[The Tradeoff Fallacy](https://www.asc.upenn.edu/sites/default/files/TradeoffFallacy_1.pdf) (PDF, via [TechCrunch](http://techcrunch.com/2015/06/06/the-online-privacy-lie-is-unraveling/)) +Es wird ja gerne behauptet, dass Konsumenten gerne ihre Daten abgeben, +um im Gegenzug kostenfreie Dienste zu erhalten. Diese Studie belegt, +dass eine Mehrheit der Konsumenten keineswegs mit diesem Deal +einverstanden ist, sondern sich einfach machtlos fühlt. Meine Meinung: +Unternehmen wie Facebook sitzen dank [Netzwerkeffekt](https://de.wikipedia.org/wiki/Netzwerkeffekt) auf einem Monopol, das sie ausnutzen, um die Konditionen zu diktieren. Natürlich könnte ich auf Whatsapp verzichten und einen anderen Messenger nutzen, aber da sind eben nicht die Leute, die ich erreichen will. + +[The Internet's Original Sin](http://www.theatlantic.com/technology/archive/2014/08/advertising-is-the-internets-original-sin/376041/) +Der Artikel verweist auch auf einen [großartigen Vortrag von Maciej Cegłowski](http://idlewords.com/bt14.htm). Werbefinanzierte Geschäftsmodelle führen notwendigerweise zu +Zentralisierung und Überwachung. + +[A Constructive Look At TempleOS](http://www.codersnotes.com/notes/a-constructive-look-at-templeos) +Es wäre leicht, TempleOS als eine Kuriosität abzutun. Immerhin behauptet +der Programmierer, von Gott beauftragt worden zu sein, ein +Betriebssystem zu entwickeln. Aber statt billige Witze zu machen, geht +der Autor ohne Vorurteile an die Sache heran. Und er stellt fest, dass +TempleOS tatsächliche einige coole Ideen beinhaltet. + +[The Death Of The Von Neumann Architecture](http://www.codersnotes.com/notes/the-death-of-the-von-neumann-architecture) +Beim Lesen des Artikels musste ich direkt an [Cory Doctorows Vortrag auf dem 28C3](http://media.ccc.de/browse/congress/2011/28c3-4848-en-the_coming_war_on_general_computation.html) denken. +Es geht um Kontrolle und Macht. Wenn ich einen Computer kaufe, gehört er +dann mir, oder dem Hersteller? [Wenn ich ein Auto kaufe, gehört es dann mir oder dem Hersteller?](http://www.slate.com/blogs/future_tense/2015/05/22/gm_and_john_deere_say_they_still_own_the_software_in_cars_customers_buy.html) + +[How to Make Money from Open Source Platforms](http://www.linux.com/news/software/applications/831018-how-to-make-money-from-open-source-platforms) [Teil 2](http://www.linux.com/news/software/applications/831645-how-to-make-money-from-open-source-platforms-part-2) [Teil 3](https://www.linux.com/news/software/applications/833312-how-to-make-money-from-open-source-platforms-part-3) [Teil 4](https://www.linux.com/news/software/applications/833939-how-to-make-money-from-open-source-platforms-part-4) +Kann man mit Freier Software Geld verdienen? Vor allem Teil 3 fand ich +aufschlussreich. + +[Artificial intelligence?](http://radar.oreilly.com/2015/06/artificial-intelligence.html) +"We need to be aware of our prejudices and bigotries, and make sure that we don’t build systems that grant our prejudices the appearance of science. That’s ultimately why AI scares us: we worry that it will be as inhuman as humans all too frequently are. If we are aware of our own flaws, and can honestly admit and discuss them, we’ll be OK." "We might use AI to hide from our responsibility for our mistakes, but they will most certainly be our mistakes." + +[TIS-100](http://www.zachtronics.com/tis-100/) und [Door Kickers](http://inthekillhouse.com/doorkickers/) +Zwei tolle Spiele! Vielleicht muss man Programmierer sein, um mit +TIS-100 Spaß zu haben. Andererseit hätte ich selbst niemals gedacht, dass ich mal freiwillig +Assembler programmieren würde. + +[9 Anti-Patterns Every Programmer Should Be Aware Of](http://sahandsaba.com/nine-anti-patterns-every-programmer-should-be-aware-of-with-examples.html) +Besonders über Punkt 3 ("Analysis Paralysis") stolpere ich leider gelegentlich. + +[The World Was Never Closer To Nuclear War Than On Jan. 25, 1995](http://www.businessinsider.com/the-world-has-never-been-closer-to-nuclear-war-than-it-was-during-this-1995-event-2012-8?IR=T) + +[Endangered Blood: NPR Music Tiny Desk Concert](https://www.youtube.com/watch?v=3rHD1_kUC5E) diff --git a/posts/2015-07-05-fundstucke-28-slash-2015.markdown b/posts/2015-07-05-fundstucke-28-slash-2015.markdown new file mode 100644 index 0000000..f8517a9 --- /dev/null +++ b/posts/2015-07-05-fundstucke-28-slash-2015.markdown @@ -0,0 +1,44 @@ +--- +layout: post +title: "Fundstücke 28/2015" +date: 2015-07-05 12:14:29 +0200 +comments: true +categories: Fundstücke +--- + +## Griechenland + +Die jetzige Zuspitzung der Krise in und um Griechenland ist nur ein +Symptom viel tiefer liegendender Probleme unseres Wirtschaftssystems. +Man könnte vieles zu dem Thema schreiben. Vielleicht mache ich das auch +irgendwann. Hier erst mal nur Links, ohne Kommentare. + +["Die Politik hat sich ins Gefängnis der Märkte begeben"](http://www.sueddeutsche.de/politik/krise-in-griechenland-die-politik-hat-sich-ins-gefaengnis-der-maerkte-begeben-1.2538360) + +[Gregor Gysi: Der Prohpet](http://le-bohemien.net/2015/07/03/gregor-gysi-der-prophet/) + +["Volksbefragung": EU entsetzt über neuartige Entscheidungsmethode aus Griechenland](http://www.der-postillon.com/2015/06/volksbefragung-eu-entsetzt-uber.html) + +[“Wenn es ernst wird, muss man lügen”](http://blog.zeit.de/herdentrieb/2015/07/02/wenn-es-ernst-wird-muss-man-luegen_8554) + +## Sonstiges + +[Inspeqtor and OSS Products With Mike Perham](http://5by5.tv/changelog/130) +Mike Perham hat zwei Open-Source-Projekte gestartet, von denen er +mittlerweile ganz gut leben kann. Genau genommen, verdient er sein Geld +mit proprietären Zusatzfeatures. [In dem Artikel](http://www.linux.com/news/software/applications/831018-how-to-make-money-from-open-source-platforms), +den ich [letzte Woche](/blog/2015/06/28/fundstucke-27-slash-2015/) +verlinkt habe, wurde dieses Modell als "Open Core" bezeichnet. + +[“Kein Aserbaidschaner würde je behaupten, in einer Demokratie zu +leben”](http://erscheinungsraum.de/er033-kein-aserbaidschaner-wuerde-je-behaupten-in-einer-demokratie-zu-leben/) +Ich wusste bisher sehr wenig über Aserbaidschan. Jetzt weiß ich mehr. + +[The Future of UI Design? Old-School Text Messages](http://www.wired.com/2015/06/future-ui-design-old-school-text-messages/) und [On conversational UIs](http://interconnected.org/home/2015/06/16/conversational_uis) +"Conversational UIs" sind anscheinend ein großer Trend in China. Ich bin +skeptisch. Künstliche Intelligenz ist eben meistens doch nicht +intelligent genug. Aber es schadet nicht über Alternativen +nachzudenken. Kennt jemand Beispiele für solche "Apps", die man +hierzulande mal ausprobieren könnte? + +[The Lone Bellow - Button](https://www.youtube.com/watch?v=ahyIALLgUN4) diff --git a/posts/2015-08-03-fundstucke-31-slash-2015.markdown b/posts/2015-08-03-fundstucke-31-slash-2015.markdown new file mode 100644 index 0000000..5594d31 --- /dev/null +++ b/posts/2015-08-03-fundstucke-31-slash-2015.markdown @@ -0,0 +1,39 @@ +--- +layout: post +title: "Fundstücke 31/2015" +date: 2015-08-03 17:25:43 +0200 +comments: true +categories: Fundstücke +--- + +Nach mehrwöchiger Pause gibt es nun neue Fundstücke von mir. + +[Are You Living in a Computer Simulation?](http://www.simulation-argument.com/simulation.html) +"This paper argues that at least one of the following propositions is true: (1) the human species is very likely to go extinct before reaching a “posthuman” stage; (2) any posthuman civilization is extremely unlikely to run a significant number of simulations of their evolutionary history (or variations thereof); (3) we are almost certainly living in a computer simulation. It follows that the belief that there is a significant chance that we will one day become posthumans who run ancestor-simulations is false, unless we are currently living in a simulation. A number of other consequences of this result are also discussed." + +[Encryption's holy grail is getting closer, one way or another](http://www.zdnet.com/article/encryptions-holy-grail-is-getting-closer-one-way-or-another/) +"The ultimate goal -- encryption's holy grail, some have called it -- is something called fully homomorphic encryption, where the entire system works on encrypted data, and returns an encrypted result. The only point in the process where data would be decrypted would be when the user wanted to see the result, and that would presumably happen in the application or client software, not in the database server in the cloud." + +[What is the Truck Factor of Popular GitHub +Applications? A First Assessment (PDF)](https://peerj.com/preprints/1233v1.pdf) +Leider hängt Software oft von einzelnen Entwicklern ab. Was passiert, +wenn diesen etwas zustößt? Bei freier Software hat man immerhin noch den +Quellcode. + +[Moving Fast With High Code Quality](https://engineering.quora.com/Moving-Fast-With-High-Code-Quality) +In dem Artikel wird beschrieben, wie die Leute bei Quora für gute +Code-Qualität sorgen. + +[So ein Europäer will ich gar nicht sein](http://kiezneurotiker.blogspot.de/2015/07/so-ein-europaer-will-ich-gar-nicht-sein.html) +"Das Europa 2015 ringt mir keinen Pathos mehr ab. Es steht nur noch für die Herrschaft der Buchhalter, für die Ablehnung demokratischer Instrumente wie Abstimmungen, für das Mobben legitimer Regierungen, das Europa 2015 steht für tausende ersoffene Flüchtlinge im Mittelmeer, Überwachung, Militarisierung, Freihandel zugunsten der globalisierten Konzerne, [...]" Ich selbst bin ähnlich enttäuscht von Europa. + +[Einfach. Gut. Leben.](http://itsyour.life/einfach-gut-leben/) +Ich finde die Idee des Minimalismus sehr ansprechend. Mittlerweile +überlege ich mir jede Anschaffung drei mal. Zeug und Konsum machen nicht +glücklich. + +[ident.me: Your Address as a Service](http://api.ident.me/) +Mit ``curl ident.me ; echo`` kann man sich ganz einfach seine +öffentliche IP-Adresse anzeigen lassen. + +[Jon Spencer Blues Explosion - Get Your Pants On (Live on KEXP)](https://www.youtube.com/watch?v=i45CNVx7e8Y) diff --git a/posts/2015-08-09-fundstucke-32-slash-2015.markdown b/posts/2015-08-09-fundstucke-32-slash-2015.markdown new file mode 100644 index 0000000..b608633 --- /dev/null +++ b/posts/2015-08-09-fundstucke-32-slash-2015.markdown @@ -0,0 +1,20 @@ +--- +layout: post +title: "Fundstücke 32/2015" +date: 2015-08-09 21:27:24 +0200 +comments: true +categories: Fundstücke +--- + +[Homme de Plume: What I Learned Sending My Novel Out Under a Male Name](http://jezebel.com/homme-de-plume-what-i-learned-sending-my-novel-out-und-1720637627) +"Total data: George sent out 50 queries, and had his manuscript requested +17 times. He is eight and a half times better than me at writing the +same book. Fully a third of the agents who saw his query wanted to see +more, where my numbers never did shift from one in 25." + +[Beyond PEP 8 -- Best practices for beautiful intelligible code - PyCon 2015](https://www.youtube.com/watch?v=wf-BqAjZb8M) +Aufschlussreicher Vortrag, der aufzeigt wie man besser verständlichen +Python-Code schreiben kann. Die ersten ca. 20 Minuten hätte man zwar +durchaus etwas kürzen können, aber danach wird es richtig interessant. + +[Deap Vally - Baby I Call Hell](https://www.youtube.com/watch?v=wUXVi3l-GUg) diff --git a/posts/2015-08-17-fundstucke-33-slash-2015.markdown b/posts/2015-08-17-fundstucke-33-slash-2015.markdown new file mode 100644 index 0000000..7180e56 --- /dev/null +++ b/posts/2015-08-17-fundstucke-33-slash-2015.markdown @@ -0,0 +1,37 @@ +--- +layout: post +title: "Fundstücke 33/2015" +date: 2015-08-17 22:23:48 +0200 +comments: true +categories: Fundstücke +--- + +[With Windows 10, Microsoft sells you out](http://jasonlefkowitz.net/2015/07/with-windows-10-microsoft-sells-you-out/) +"[...] **your interest in how your computer works and Microsoft’s interest are no +longer aligned.** While you will want your computer to do things quickly +and efficiently and unobtrusively, Microsoft will want it to do those +things slowly and clunkily and painfully; because every delay, every +useless dialog box you have to click through, is another opportunity for +them to show you an ad. And while you will want your computer to keep +your secrets secret, you won’t be able to trust Microsoft to want the +same thing anymore, because suddenly all those secrets are worth money +to them. They can use them to match you up even more exquisitely with +advertisers, who have become Microsoft’s real customers for Windows." + +[Fix Windows 10](https://fix10.isleaked.com/) +Immerhin erlaubt Windows 10 recht genau einzustellen, welche Daten an +Microsoft gesendet werden. Hier wird das ausführlich mit Screenshots +erklärt. + +[Documentation at scale: The principles](http://250bpm.com/blog:58) +"1. Acknowledge that brute force doesn't work. 2. Make documentation a first +class citizen. 3. Make documentation executable. 4. Track the intent. 5. Measure it." + + +[Ein Abgrund von Landesverrat](http://www.zeit.de/gesellschaft/zeitgeschehen/2015-08/pressefreiheit-netzpolitik-fischer-im-recht/komplettansicht) +Bundesrichter Thomas Fischer schreibt in seiner Kolumne über den Fall +#landesverrat. Dabei kommt seine Meinung sehr deutlich durch. Auch wenn +man diese nicht vollständig teilt, ist der Artikel sehr interessant zu +lesen. + +[Lee Fields and the Expressions - "Faithful Man" (Live at WFUV)](https://www.youtube.com/watch?v=4ZibJKnW6gI) diff --git a/posts/2015-08-25-fundstucke-34-slash-2015.markdown b/posts/2015-08-25-fundstucke-34-slash-2015.markdown new file mode 100644 index 0000000..37e9782 --- /dev/null +++ b/posts/2015-08-25-fundstucke-34-slash-2015.markdown @@ -0,0 +1,34 @@ +--- +layout: post +title: "Fundstücke 34/2015" +date: 2015-08-25 17:05:05 +0200 +comments: true +categories: Fundstücke +--- + +[Reportage: Drei Brüder aus Syrien in der Trierer Aufnahmeeinrichtung für Asylbegehrende](http://lokalo.de/artikel/95112/reportage-drei-brueder) +Ich finde den Artikel aus zwei Gründen bemerkenswert: die Reportage ist +ein positives Beispiel für Lokaljournalismus, und hier wird *mit* +Flüchtlingen statt nur *über* sie gesprochen. + +[The Architecture of Open Source Applications: ZeroMQ](http://www.aosabook.org/en/zeromq.html) +Dieses Kapitel aus [The Architecture of Open Source Applications](http://aosabook.org) +gibt einen guten Überblick über [ZeroMQ](http://zeromq.org/). Das war +für mich ganz hilfreich, weil ich ZeroMQ eventuell bald für ein Projekt +einsetzen werde. Übrigens kann ich [die ganze Reihe](http://www.aosabook.org/) +empfehlen. Ich habe zwar bisher nur einzelne Kapitel gelesen, die waren +aber allesamt sehr lehrreich. + +[Waterboarding für den gemeingefährlichen Irren! Deutsche Journalisten über Claus Weselsky](http://www.stefan-niggemeier.de/blog/21153/waterboarding-fuer-den-gemeingefaehrlichen-irren-deutsche-journalisten-ueber-claus-weselsky/) +Erschreckend. + +[Web Design: The First 100 Years](http://idlewords.com/talks/web_design_first_100_years.htm) +"The Internet is full of projects big and small whose defining trait is +that they came out of nowhere and captured people's imaginations. It's +also full of awesome cat videos. The key part of this vision is that the +Internet succeeds by remaining open and participatory. No one acts as +gatekeeper, and it is not just a channel for mindless consumption." +([Weitere Vorträge von Maciej Cegłowski](http://idlewords.com/talks/)) + +[Confronting New Madrid](http://idlewords.com/2015/07/confronting_new_madrid.htm) +Maciej Cegłowski ist durch die [New Madrid Seismic Zone](https://en.wikipedia.org/wiki/New_Madrid_Seismic_Zone) gereist und schreibt darüber. diff --git a/posts/2015-08-31-fundstucke-35-slash-2015.markdown b/posts/2015-08-31-fundstucke-35-slash-2015.markdown new file mode 100644 index 0000000..c6b526e --- /dev/null +++ b/posts/2015-08-31-fundstucke-35-slash-2015.markdown @@ -0,0 +1,24 @@ +--- +layout: post +title: "Fundstücke 35/2015" +date: 2015-08-31 12:21:17 +0200 +comments: true +categories: Fundstücke +--- + +[Momo](https://de.wikipedia.org/wiki/Momo_%28Roman%29) +Der Roman ist 1973 erschienen, also bin ich mit meiner Empfehlung etwas +spät dran. Das Buch hat aber nichts von seiner Aktualität verloren, eher +im Gegenteil. Man findet das Werk zwar meist in der Kinder- und +Jugendbuchabteilung, aber gerade auch für Erwachsene gibt es hier viele +Denkanstöße. Was ist Zeit und wie gehen wir damit um? + +[Momo, Dogen. and the Commodification of Time](http://ccbs.ntu.edu.tw/FULLTEXT/JR-MISC/101783.htm) +"This essay will explore the deep resonances between Ende's view of time +in Momo and the Buddhist perspective on time, particularly as expressed +by the Japanese Zen master Dogen (1200 - 1253). These resonances are of +more than literary or historical interest: understanding what Ende and +Dogen have to say about time gives us important insight into how we +experience time today." + +[The Cat Empire Live at AB - Ancienne Belgique (Full concert)](https://www.youtube.com/watch?v=eiY3xMM4DSk) diff --git a/posts/2015-09-15-fundstucke-37-slash-2015.markdown b/posts/2015-09-15-fundstucke-37-slash-2015.markdown new file mode 100644 index 0000000..004ca78 --- /dev/null +++ b/posts/2015-09-15-fundstucke-37-slash-2015.markdown @@ -0,0 +1,28 @@ +--- +layout: post +title: "Fundstücke 37/2015" +date: 2015-09-15 18:39:48 +0200 +comments: true +categories: Fundstücke +--- + +[The Inspection Paradox is Everywhere](http://allendowney.blogspot.de/2015/08/the-inspection-paradox-is-everywhere.html) +Viele schöne Beispiele zu einem statistischen Paradoxon. + +[“Und wenn du einfach unter einem Männernamen schreibst?”](https://zoebeck.wordpress.com/2015/08/22/und-wenn-du-einfach-unter-einem-maennernamen-schreibst/) +Die Autorin bezieht sich auf [einen Artikel](http://localhost:4000/blog/2015/08/09/fundstucke-32-slash-2015/), +den ich hier [vor ein paar Wochen](http://mpuppe.de/blog/2015/08/09/fundstucke-32-slash-2015/) +auch schon mal verlinkt hatte. + +[TSA Master Keys](https://www.schneier.com/blog/archives/2015/09/tsa_master_keys.html) +Unter anderem deswegen sind staatlich vorgeschriebene Backdoors eine sehr, +sehr dumme Idee. + +[The Bottom Of The Well](http://www.npr.org/sections/money/2015/07/22/425392169/episode-640-the-bottom-of-the-well) +Stellvertretend für viele spannende Episoden des Podcasts "Planet Money". + +[WR470 Nachgefragt: Kurdistan](http://www.wrint.de/2015/08/30/wr470-nachgefragt-kurdistan/) +Holger Klein spricht mit Enno Lenze über dessen jüngste Reise nach +Kurdistan. + +[Caravan](https://www.youtube.com/watch?v=TS-G4UQTfUo) diff --git a/posts/2015-09-20-fundstucke-38-slash-2015.markdown b/posts/2015-09-20-fundstucke-38-slash-2015.markdown new file mode 100644 index 0000000..e00b1b4 --- /dev/null +++ b/posts/2015-09-20-fundstucke-38-slash-2015.markdown @@ -0,0 +1,18 @@ +--- +layout: post +title: "Fundstücke 38/2015" +date: 2015-09-20 19:37:42 +0200 +comments: true +categories: Fundstücke +--- + +[Why Futurism Has a Cultural Blindspot](http://nautil.us/issue/28/2050/why-futurism-has-a-cultural-blindspot) +'“Futurology is almost always wrong,” the historian Judith Flanders suggested to me, “because it rarely takes into account behavioral changes.” And, she says, we look at the wrong things: “Transport to work, rather than the shape of work; technology itself, rather than how our behavior is changed by the very changes that technology brings.” It turns out that predicting who we will be is harder than predicting what we will be able to do.' + +[Inside Amazon: Wrestling Big Ideas in a Bruising Workplace](http://www.nytimes.com/2015/08/16/technology/inside-amazon-wrestling-big-ideas-in-a-bruising-workplace.html) +Ich werde mich in Zukunft vermehrt nach Alternativen zu Amazon umsehen. + +[Alternativlos, Folge 35](http://alternativlos.org/35/) +"In Alternativlos Folge 35 reden wir über Diskurs- und Debattenkultur und die Facebook-Löschdebatte." + +[Aynotchesh Yererfu by The Budos Band](https://thebudosband.bandcamp.com/track/aynotchesh-yererfu) diff --git a/posts/2015-09-27-fundstucke-39-slash-2015.markdown b/posts/2015-09-27-fundstucke-39-slash-2015.markdown new file mode 100644 index 0000000..cea9324 --- /dev/null +++ b/posts/2015-09-27-fundstucke-39-slash-2015.markdown @@ -0,0 +1,21 @@ +--- +layout: post +title: "Fundstücke 39/2015" +date: 2015-09-27 21:54:44 +0200 +comments: true +categories: Fundstücke +--- + +[How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/) +Ein paar gute Hinweise. + +[What Happens Next Will Amaze You](http://idlewords.com/talks/what_happens_next_will_amaze_you.htm) +"State surveillance is driven by fear. And corporate surveillance is +driven by money. The two kinds of surveillance are as intimately +connected as tango partners. They move in lockstep, eyes rapt, searching +each other's souls. The information they collect is complementary. By +defending its own worst practices, each side enables the other. +Today I want to talk about the corporate side of this partnership." + +[Zitat am Freitag: Was wirklich gegen Erkältung hilft](https://buggisch.wordpress.com/2015/09/18/zitat-am-freitag-was-wirklich-gegen-erkaeltung-hilft/) +tl;dr: Ausreichend schlafen beugt Erkältungen vor. diff --git a/posts/2015-11-02-fundstucke-44-slash-2015.markdown b/posts/2015-11-02-fundstucke-44-slash-2015.markdown new file mode 100644 index 0000000..8db4fc7 --- /dev/null +++ b/posts/2015-11-02-fundstucke-44-slash-2015.markdown @@ -0,0 +1,26 @@ +--- +layout: post +title: "Fundstücke 44/2015" +date: 2015-11-02 23:04:37 +0100 +comments: true +categories: Fundstücke +--- + +[Automatic Face Recognition and Surveillance](https://www.schneier.com/blog/archives/2015/10/automatic_face_.html) +"We need limitations on how our images can be collected without our +knowledge or consent, and on how they can be used. The technologies +aren't going away, and we can't uninvent these capabilities. But we can +ensure that they're used ethically and responsibly, and not just as a +mechanism to increase police and corporate power over us." + +[Schaffen wir das?](http://www.zeit.de/gesellschaft/zeitgeschehen/2015-10/fluechtlinge-fischer-im-recht/komplettansicht) +'Die Formel "nach Maßgabe der Möglichkeiten" ist also, als +verfassungsrechtliche Formel, die Verweisung entweder auf ein +intellektuelles Nichts oder auf nichts als die politische Willkür. Und +sonst wirklich nichts!' + +[Hardcore History 56 Kings of Kings](http://www.dancarlin.com/product/hardcore-history-56-kings-kings/) +Eine neue Folge von Dan Carlins "Hardcore History". + +[Frazey Ford - Done](https://www.youtube.com/watch?v=PXRrySTujn8) +Neulich bei [detektor.fm](https://detektor.fm/) entdeckt. diff --git a/posts/2016-04-03-knobeln-mit-clojure.markdown b/posts/2016-04-03-knobeln-mit-clojure.markdown new file mode 100644 index 0000000..c449cf6 --- /dev/null +++ b/posts/2016-04-03-knobeln-mit-clojure.markdown @@ -0,0 +1,144 @@ +--- +layout: post +title: "Knobeln mit Clojure" +date: 2016-04-03 20:46:00 +0200 +comments: true +--- + +Das [ZEITmagazin](https://de.wikipedia.org/wiki/Die_Zeit#Zeitmagazin) +enthält regelmäßig unter der Überschrift "Logelei" ein Logikrätsel. +Neulich hatte ich Ausgabe 14/2016 vor mir liegen. Der vollständige Text +ist [hier](http://www.zeit.de/2016/14/spiele-logelei-14) zu finden. Ich +fasse die wesentlichen Punkte zusammen. Gesucht wird die Kombination für +ein Zahlenschloss. Das Zahlenschoss hat sechs Ziffern. Die gesuchte Zahl +muss die folgenden Bedingungen erfüllen: + +1. Die Zahl ist durch 4 teilbar. +2. Die Zahl ist rückwärts ebenfalls durch 4 teilbar. +3. Die Zahl ist durch 7 teilbar. +4. Die Zahl ist *nicht* durch 11 teilbar. +5. Die Quersumme der Zahl beträgt 32. +6. Jede Ziffer kommt in der Zahl entweder doppelt oder gar nicht vor. + +Nun habe ich erst versucht das Rätsel nur mit Papier und Stift zu lösen. +Leider ist Zahlentheorie nicht meine Stärke und mein Wissen erschöpfte +sich im konkreten Fall in dem Fakt, dass es reicht die letzten beiden +Ziffern einer Zahl zu betrachten, um zu überprüfen, ob sie durch 4 +teilbar ist. Also habe ich stattdessen meinen Laptop zur Hand genommen +und eine +[Clojure](https://en.wikipedia.org/wiki/Clojure)-[REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) +geöffnet. Ich habe mir die nötigen Funktionen definiert und schließlich +alles zusammengestöpselt. So war das Rätsel trotz Brute-Force-Ansatz +relativ schnell gelöst. + +Heute habe ich alles noch mal ordentlich aufgeschrieben.Zusätzlich habe +ich noch ein paar Tests geschrieben. Den gesamten Quellcode habe ich +[auf Github veröffentlicht](https://github.com/puppe/zahlenschloss). +Bitte schön! + +``` clojure +(ns zahlenschloss.core + (:gen-class)) + +(defn teilbar? + "Gibt `true` zurück, genau dann wenn `n` durch `x` teilbar ist." + [x n] + (= 0 (mod n x))) + +(doseq [x [4 7 11]] + (intern *ns* + (symbol (str "teilbar" x "?")) + (partial teilbar? x))) + + +(defn ziffern + "Nimmt eine Zahl `n` und gibt die Folge der Ziffern der Zahl zurück." + [n] + (loop [n n + ziffern (list)] + (if (= n 0) + ziffern + (recur (int (/ n 10)) (conj ziffern (mod n 10)))))) + +; http://stackoverflow.com/a/5058544 +(defn- exp [x n] + "Berechnet x hoch n." + (reduce * (repeat n x))) + +(defn wert + "Nimmt eine Folge von Ziffern und berechnet ihren Zahlenwert." + [ziffern] + (loop [summe 0 + faktor (exp 10 (dec (count ziffern))) + [ziffer & ziffern] ziffern] + (if ziffer + (recur + (+ summe (* ziffer faktor)) + (/ faktor 10) + ziffern) + summe))) + +(defn links-auffuellen + "Nimmt eine Folge von Ziffern und füllt sie, falls nötig, links mit + Nullen auf, sodass das Ergebnis aus mindestens sechs Ziffern besteht." + [ziffern] + (loop [laenge (count ziffern) + ziffern ziffern] + (if (>= laenge 6) + ziffern + (recur + (inc laenge) + (conj ziffern 0))))) + +(defn rueckwaerts + "Nimmt eine Zahl und dreht die Folge ihrer Ziffern um. Dabei wird + angenommen, dass die Zahl mindestens sechsstellig ist. Das Ergebnis + ist daher mindestens auch sechsstellig." + [n] + (wert (reverse (links-auffuellen (ziffern n))))) + +(defn quersumme + "Berechnet die Quersumme der Zahl `n`." + [n] + (apply + (ziffern n))) + +(defn zaehle-ziffern + "Zählt, wie oft die einzelnen Ziffern in der Zahl `n` vorkommen. Es + wird angenommen, dass `n` mindestens sechsstellig ist." + [n] + (reduce + (fn [m ziffer] + (assoc m ziffer (inc (get m ziffer 0)))) + {} + (links-auffuellen (ziffern n)))) + +(defn doppelt-oder-gar-nicht? + "Gibt `true` zurück, genau dann wenn jede Ziffer in der Zahl doppelt + oder gar nicht vorkommt. Es wird angenommen, dass `n` mindestens + sechsstellig ist." + [n] + (if (some #(not= % 2) (vals (zaehle-ziffern n))) + false + true)) + +(defn -main + [& args] + (println "Mögliche Lösung(en):") + (apply + println + (->> (range 0 1000000) + ; Die Zahl ist durch 4 teilbar. + (filter teilbar4?) + ; Die Zahl ist rückwärts ebenfalls durch 4 teilbar. + (filter #(teilbar4? (rueckwaerts %))) + ; Die Zahl ist durch 7 teilbar. + (filter teilbar7?) + ; Die Zahl ist nicht durch 11 teilbar. + (filter (complement teilbar11?)) + ; Die Quersumme der Zahl beträgt 32. + (filter #(= 32 (quersumme %))) + ; Jede Ziffer kommt entweder doppelt oder gar nicht vor. + (filter doppelt-oder-gar-nicht?) + ; Wir geben maximal 10 Zahlen aus. + (take 10)))) +```