<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Jan-Krueger.net</title>
	<atom:link href="http://jan-krueger.net/feed" rel="self" type="application/rss+xml" />
	<link>http://jan-krueger.net</link>
	<description>Creative Engineering</description>
	<pubDate>Thu, 24 Jul 2008 19:47:36 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>How to use TrueCrypt®-encrypted Windows system drives on Linux</title>
		<link>http://jan-krueger.net/development/truecrypt-system-drive-on-linux</link>
		<comments>http://jan-krueger.net/development/truecrypt-system-drive-on-linux#comments</comments>
		<pubDate>Wed, 23 Jul 2008 07:36:27 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/?p=37</guid>
		<description><![CDATA[TrueCrypt® is a multi-platform on-the-fly drive encryption tool. It allows you to encrypt all your data in a filesystem and still use everything normally. On Windows, it supports encrypting the system (boot) partition (or the entire boot drive); you can even make TrueCrypt® encrypt your existing partitions live and continue working (though the I/O performance [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://truecrypt.org/">TrueCrypt</a>® is a multi-platform on-the-fly drive encryption tool. It allows you to encrypt all your data in a filesystem and still use everything normally. On Windows, it supports encrypting the system (boot) partition (or the entire boot drive); you can even make TrueCrypt® encrypt your existing partitions live and continue working (though the I/O performance sucks until it&#8217;s finished encrypting everything), pause and resume the encryption process (even across reboots). In short: it&#8217;s rather useful.</p>
<p>Even though TrueCrypt® introduced Windows system encryption in version 5.0 in February 2008 (that&#8217;s five months ago), its Linux version still doesn&#8217;t support accessing these encrypted partitions at all (it does mount &#8220;normal&#8221; TrueCrypt® volumes though). Since I recently encrypted my entire Windows drive but couldn&#8217;t live without the music files stored on it, I now humbly present the result of two wasted nights: a solution. <span id="more-37"></span></p>
<h3>This just in!</h3>
<p>A letter from the friendly folks over at truecrypt.org (®?) notified me that they don&#8217;t like my using their trademark TrueCrypt® in the name of my tool. To help avoid uncomfortable situations, I would like to point out to everybody that this tool is called dmsetup-tc and not dmsetup-TrueCrypt®.</p>
<p>To demonstrate that I take trademarks very seriously, I have taken great care in this article to give the trademark all the attention it undoubtedly deserves.</p>
<h3>Before you join the fun&#8230;</h3>
<p>I&#8217;d love to take a dive into technical details now but you&#8217;ll probably go away before I even get myself warmed up properly, so I&#8217;ll try and appease myself by mentioning that I learned lots of new things, including the gory details of XTS and PKCS#5/PBKDF2. Oh, and I first tried patching this stuff into TrueCrypt® but failed mainly due to two reasons: first, TrueCrypt® is written in C++ and it shows in the architecture; second, C++ itself. When I had everything but the correct initialization of the XTS tweak working, I gave up and started writing a separate tool. The positive side: it compiles in about a second and is snappier than TrueCrypt® when it runs, too (and it doesn&#8217;t do whatever weird things TrueCrypt® does with FUSE).</p>
<p>Oh, right, I wanted to keep the details out of this. Sorry.</p>
<h3>What you need</h3>
<ul>
<li>A computer with a little-endian architecture (rule of thumb: if Windows runs on it, you&#8217;re fine). Support for big-endian architecture will be added if someone else writes a patch. ;)</li>
<li>A Windows sytem partition or drive that has been encrypted (completely; partial encryption is absolutely not supported) with TrueCrypt®. Normal TrueCrypt® partitions are <em>not</em> supported; after all, TrueCrypt® for Linux works fine for them.</li>
<li>A Linux system that you want to access the partition(s) from.</li>
<li>libgcrypt (tested with version 1.2.4) and its development files.</li>
<li>GNU make.</li>
<li>A C compiler (tested with GCC 4.2.3).</li>
<li>Optionally, experience with C and so on if you want to track down (and fix) bugs or add features.</li>
</ul>
<h3>Install it</h3>
<ol>
<li>Download the source code: <a href="http://jan-krueger.net/src/dmsetup-tc-0.1.tar.bz2">dmsetup-tc-0.1.tar.bz2</a>.</li>
<li>Extract it somewhere.</li>
<li>Run make. You know the drill.</li>
<li>Put the resulting binary wherever you like.</li>
</ol>
<h3>Use it</h3>
<p>Now, suppose you&#8217;ve got an encrypted system drive on /dev/sda and you want to mount the partition /dev/sda1. Then you just do the following (as root):</p>
<pre>.../dmsetup-tc /dev/sda /dev/sda1 | dmsetup create win1</pre>
<p>This will create a DM device <em>/dev/mapper/win1</em>. You can now mount it. Assuming it&#8217;s got an NTFS filesystem (and you actually have a mountpoint called <em>/media/win1</em>):</p>
<pre>mount -t ntfs-3g -o uid=(your numeric uid),umask=077 /dev/mapper/win1 /media/win1</pre>
<p>There, all done. After umounting, remember to remove the DM device so that even root can&#8217;t get at your data anymore:</p>
<pre>dmsetup remove win1</pre>
<p><strong>Important:</strong> don&#8217;t use dmsetup-tc on its own; always pipe its output directly into dmsetup! It outputs your volume master keys. You don&#8217;t want anybody to get a hold of those. There is a certain security risk to piping the data, too (it might get paged out and end up in your swap, which is problematic if you don&#8217;t use encrypted swap; additionally, the data from the pipe might reside somewhere in your physical memory for some time, possibly allowing root to read the master key even after you have remove the DM device). You have been warned.</p>
<h3>Contribute</h3>
<p>I&#8217;m developing the tool in a Git repository and you can join in! See the <a href="http://repo.or.cz/w/dmsetup-tc.git">repository page</a> for details.</p>
<p>You can also contribute by sending me feedback, but my capacity for actively adding new features to this tool is very limited.</p>
<p>In either case, thank you very much!</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/development/truecrypt-system-drive-on-linux/feed</wfw:commentRss>
		</item>
		<item>
		<title>Finally: the perfect CAPTCHA</title>
		<link>http://jan-krueger.net/comm/internet/finally-the-perfect-captcha</link>
		<comments>http://jan-krueger.net/comm/internet/finally-the-perfect-captcha#comments</comments>
		<pubDate>Tue, 22 Apr 2008 15:11:03 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[Internet]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/?p=35</guid>
		<description><![CDATA[CAPTCHAs: these warped images you have to copy text out of in order to submit comments on an ever-growing number of websites.
The warped image approach has a number of serious flaws. Firstly, there is a strong correlation between the difficulty bots have with extracting the code from the image and the difficulty humans have with [...]]]></description>
			<content:encoded><![CDATA[<p>CAPTCHAs: these warped images you have to copy text out of in order to submit comments on an ever-growing number of websites.</p>
<p>The warped image approach has a number of serious flaws. Firstly, there is a strong correlation between the difficulty bots have with extracting the code from the image and the difficulty humans have with extracting the code from the image. In <a href="http://rapidshare.com/">some cases</a>, I hear it&#8217;s actually easier for machines than it is for humans.</p>
<p>Secondly, blind people and people without graphical output on their computers are automatically banned from your CAPTCHA-protected system. Bad.</p>
<p>A different approach is needed. Text-based CAPTCHAs, however, would likely require a knowledge base that challenges are generated from, and due to technical limitations, that knowledge base would probably be finite. A finite knowledge base means that it can probably be inferred from a decent number of challenges.</p>
<p>Some other approaches, such as Hashcash-style challenges, require that the user&#8217;s computer solves a difficult mathematical problem which ensures that it will be busy for quite a while until the correct solution is obtained (and the challenge can thus be passed). Again, this results in problems with accessibility.</p>
<p>Luckily, there is an alternative family of approaches that make spamming absolutely infeasible without causing any of the typical accessibility issues. As you know, spamming only pays off due to the ludicrously large number of places you can put your advertisements. Were said places to implement a disincentive to placing a large number of ads, spam would instantly leave them alone.</p>
<p>Enter the disincentive-based solution: ccCAPTCHA. Developed by myself, it works by charging commenters a certain monetary value. All the user has to do is supply their credit card number. You can now test ccCAPTCHA online at my <a href="http://jan-krueger.net/cccaptcha/">ccCAPTCHA prototype site</a>. On that page, I&#8217;m also making the technical parts of ccCAPTCHA available to other interested webmasters. And it&#8217;s all for free!</p>
<p>You&#8217;re welcome.</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/comm/internet/finally-the-perfect-captcha/feed</wfw:commentRss>
		</item>
		<item>
		<title>My first take on the &#8220;Album A Day&#8221; challenge</title>
		<link>http://jan-krueger.net/general-creativity/album-a-day-01</link>
		<comments>http://jan-krueger.net/general-creativity/album-a-day-01#comments</comments>
		<pubDate>Sun, 20 Apr 2008 21:18:24 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[General Creativity]]></category>

		<category><![CDATA[Music]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/?p=34</guid>
		<description><![CDATA[Tom7, also known as Tom Murphy VII, has been challenging musicians to create an entire album in 24 hours. Consecutive hours, that is. In other words, this challenge is an excellent source of sleep deprivation and a great way to avoid doing things I ought to be doing instead. So I thought to myself: one [...]]]></description>
			<content:encoded><![CDATA[<p>Tom7, also known as Tom Murphy VII, has been challenging musicians to <a href="http://crapart.spacebar.org/aad/">create an entire album in 24 hours</a>. Consecutive hours, that is. In other words, this challenge is an excellent source of sleep deprivation and a great way to avoid doing things I ought to be doing instead. So I thought to myself: one day I simply must give this a try. That day was today (and yesterday). I proudly present my first Album-A-Day: <strong>You Vs. The Others</strong>. <span id="more-34"></span></p>
<p>I&#8217;d been contemplating creating an AAD since I first heard of it (which was a long time ago), but now I actually sat down and did it.</p>
<p>I deliberately didn&#8217;t listen to any of the existing AADs so that I didn&#8217;t have any pressure to reach any particular level of quality. I just went with pretty much all ideas that popped up in my head and made them into something longer than a minute (well, with one exception).</p>
<p>I started out at 10 pm (that&#8217;s yesterday, obviously) and it went pretty well. After a quarter of the allotted time was over, I already had eight minutes worth of music finished. Especially after the first song, I was rather impressed with myself. I wouldn&#8217;t have expected to be able to accomplish this much in this little time.</p>
<p>At 2 pm I took a break that ended up lasting until about 6 pm (I decided to get a bit of sleep after being awake for 24 hours in a row). At this point I had five songs finished, totalling at 14 minutes and 17 seconds. When the break ended, I spent about half of the remaining time <span style="text-decoration: line-through;">lazing around</span> recharging creativity and the rest writing the last couple of songs. I grudgingly had to include a purely instrumental (and completely improvised) song of two minutes and ten seconds to make it before the deadline. Well, that&#8217;s life.</p>
<h3>Take it out for a test drive</h3>
<p>Since I don&#8217;t care for exceeding my traffic limits, I have uploaded the songs to the Internet Archive. You can listen to them using some black Flash magic, or download them from the <a href="http://www.archive.org/details/jk_aad01_you_vs_the_others">Internet Archive details page</a>.</p>
<p>Please note that the Flash thing below uses MP3 files of Some Quality, so you&#8217;d better have a broadband connection.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="170" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="id" value="xspf_player" /><param name="align" value="middle" /><param name="allowScriptAccess" value="sameDomain" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="src" value="http://www.archive.org/audio/xspf_player.swf?autoload=true&amp;playlist_url=http%3A%2F%2Fwww.archive.org%2Faudio%2Fxspf-maker.php%3Fidentifier%3Djk_aad01_you_vs_the_others%26playlist%3Dhttp%253A%252F%252Fwww.archive.org%252Fdownload%252Fjk_aad01_you_vs_the_others%252Fformat%253DVBR%2BM3U" /><embed id="xspf_player" type="application/x-shockwave-flash" width="400" height="170" src="http://www.archive.org/audio/xspf_player.swf?autoload=true&amp;playlist_url=http%3A%2F%2Fwww.archive.org%2Faudio%2Fxspf-maker.php%3Fidentifier%3Djk_aad01_you_vs_the_others%26playlist%3Dhttp%253A%252F%252Fwww.archive.org%252Fdownload%252Fjk_aad01_you_vs_the_others%252Fformat%253DVBR%2BM3U" bgcolor="#ffffff" quality="high" allowscriptaccess="sameDomain" align="middle"></embed></object></p>
<h3>Data about the album</h3>
<ul>
<li>Title: <strong>You Vs. The Others</strong></li>
<li>Total time spent, including breaks: about <strong>23 hours and 40 minutes</strong> (from 2008-04-19 22:00 to 2008-04-20 21:40 CEST)</li>
<li>Authors and participants: me and myself.</li>
<li>Recording gear:
<ul>
<li>Yamaha MG 10/2 (miniature mixing panel)</li>
<li>Studio Projects B1 1&#8243; condenser microphone</li>
<li>Sennheiser E835s dynamic microphone</li>
<li>REAPER 2.201, a really cool multi-track audio sequencing application</li>
</ul>
</li>
<li>Instruments:
<ul>
<li>Voice (mine. Repeatedly.)</li>
<li>Guitar (nylon and steel acoustic)</li>
<li>Samplers (Cockos ReaSynth &amp; ReaSynthDr and E-MU Proteus X LE)</li>
</ul>
</li>
<li>Full length: 20:02 (according to media player) or <strong>20:01</strong> (when I add up the numbers myself). Barely qualifies!</li>
<li>Average length of songs: 2:13 (standard deviation: 0:45)</li>
</ul>
<p>Now for the individual songs. Yes, the official track numbering does start at zero.</p>
<ol start="0">
<li>
<p><strong>Take Your Time</strong></p>
<p>This isn&#8217;t actually the first song I wrote, it&#8217;s the third. Apart from that, this list is in chronological order. I thought some sort of intro would be nice. It&#8217;s supposed to add a bit of perspective to the overall album, so there is a reference to the AAD challenge in it.</p>
<ul>
<li>Length: <strong>2:01</strong></li>
<li>Took me: <strong>90 minutes</strong></li>
<li><a href="http://jan-krueger.net/aad/01/lyrics%20-%2000%20-%20take%20your%20time.txt">Lyrics</a></li>
</ul>
</li>
<li>
<p><strong>Go Alone</strong></p>
<p>Sometimes, you have to do things yourself. Outside help is a great thing but not if you&#8217;re going to lord your accomplishments over others; then you must work alone.</p>
<ul>
<li>Length: <strong>3:37</strong></li>
<li>Took me: <strong>4 hours</strong></li>
<li><a href="http://jan-krueger.net/aad/01/lyrics%20-%2001%20-%20go%20alone.txt">Lyrics</a></li>
</ul>
</li>
<li>
<p><strong>Feature Creep</strong></p>
<p>The nightmare of every programmer. There are no fixed requirements and suddenly you&#8217;re supposed to make your software do everything on the fricking earth. By the way, feature creep can occur in songs, too.</p>
<ul>
<li>Length: <strong>2:29</strong></li>
<li>Took me: <strong>4 hours</strong></li>
<li><a href="http://jan-krueger.net/aad/01/lyrics%20-%2002%20-%20feature%20creep.txt">Lyrics</a></li>
</ul>
</li>
<li>
<p><strong>Until The End</strong></p>
<p>Atheists. Pesky buggers. How can they honestly believe something that isn&#8217;t what I believe? I know I&#8217;m right! I always am.</p>
<ul>
<li>Length: <strong>3:53</strong></li>
<li>Took me: <strong>90 minutes</strong></li>
<li><a href="http://jan-krueger.net/aad/01/lyrics%20-%2003%20-%20until%20the%20end.txt">Lyrics</a></li>
</ul>
</li>
<li>
<p><strong>Going Down</strong></p>
<p>A bit morbid perhaps.</p>
<ul>
<li>Length: <strong>2:28</strong></li>
<li>Took me: <strong>30 minutes</strong> (plus time to get the creative thing going)</li>
<li><a href="http://jan-krueger.net/aad/01/lyrics%20-%2004%20-%20going%20down.txt">Lyrics</a></li>
</ul>
</li>
<li>
<p><strong>Sucks To Be Them</strong></p>
<p>Why not flaunt it for once? Just because they&#8217;re unhappy doesn&#8217;t mean you have to be. And you can make them even more unhappy by telling them so in the smuggest fashion you can muster.</p>
<ul>
<li>Length: <strong>1:37</strong></li>
<li>Took me: <strong>8 hours and 20 minutes</strong> (subtract the huge break and lots of laziness and it&#8217;s 1 hour 20 minutes)</li>
<li><a href="http://jan-krueger.net/aad/01/lyrics%20-%2005%20-%20sucks%20to%20be%20them.txt">Lyrics</a></li>
</ul>
</li>
<li>
<p><strong>Cake</strong></p>
<p>I defeated GLaDOS and all I got was this lousy song. Warning: contains spoilers for a certain video game.</p>
<ul>
<li>Length: <strong>1:34</strong></li>
<li>Took me: <strong>1 hour</strong></li>
<li><a href="http://jan-krueger.net/aad/01/lyrics%20-%2006%20-%20cake.txt">Lyrics</a></li>
</ul>
</li>
<li>
<p><strong>Improvised Right Padding</strong></p>
<p>Nothing to comment on, but without this one I would never have managed the 20 minutes requirement.</p>
<ul>
<li>Length: <strong>2:10</strong></li>
<li>Took me: <strong>2:10 times two</strong> :)</li>
</ul>
</li>
<li>
<p><strong>23 Seconds</strong></p>
<p>&#8220;Why not cut it as close as possible and still mess with some people&#8217;s heads?&#8221; I thought to myself. 23 seconds indeed.</p>
<ul>
<li>Length: <strong>0:23</strong> (oh, really!)</li>
<li>Took me: <strong>5 minutes</strong></li>
<li><a href="http://jan-krueger.net/aad/01/lyrics%20-%2008%20-%2023%20seconds.txt">Lyrics</a></li>
</ul>
</li>
</ol>
<p>There is no hidden bonus track. There can&#8217;t be. I would have run out of time.</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/general-creativity/album-a-day-01/feed</wfw:commentRss>
		</item>
		<item>
		<title>HOWTO: encode a string into a complicated-looking trigonometric function</title>
		<link>http://jan-krueger.net/development/howto-encode-your-string-trigonometrically</link>
		<comments>http://jan-krueger.net/development/howto-encode-your-string-trigonometrically#comments</comments>
		<pubDate>Thu, 03 Apr 2008 18:49:19 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/?p=33</guid>
		<description><![CDATA[Today&#8217;s glance at reddit.com yielded a blog posting by a fellow who calls himself &#8220;Poromenos&#8221; and who recently wasted his day by designing a function made up of sines and cosines that encode the string &#8220;Hello world!&#8221;. &#8220;Hey&#8221;, I immediately thought, &#8220;I can do that too! I&#8217;m an expert at wasting my day, after all.&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>Today&#8217;s glance at reddit.com yielded a blog posting by a fellow who calls himself &#8220;Poromenos&#8221; and who recently wasted his day by <a title="Printing &quot;Hello world!&quot; using curve fitting techniques (or: The &quot;Hello world!&quot; function)" href="http://www.poromenos.org/node/89">designing a function made up of sines and cosines that encode the string &#8220;Hello world!&#8221;</a>. &#8220;Hey&#8221;, I immediately thought, &#8220;I can do that too! I&#8217;m an expert at wasting my day, after all.&#8221; Only I decided to go a step further and write a program that generates this sort of function. I&#8217;m lazy, remember?  <span id="more-33"></span></p>
<h3>The theory</h3>
<p>The magic behind Poromenos&#8217;s function is the Fourier theorem: any &#8220;mostly&#8221; continuous and periodic function can be expressed as a sum of sines and cosines. I&#8217;m not going to bore you with the details; suffice to say that this also works for sampled functions, i.e. discrete series of values.</p>
<p>There&#8217;s an algorithm called DFT (Discrete Fourier Transform) that takes a series of <em>N</em> complex sample values and generates a corresponding Fourier series which encodes the various sine/cosine coefficients in <em>N</em> complex output values. In the special case of real input values (which is an extremely common case), you can effectively throw away half of these output values and take the remaining <em>N</em> real/imaginary components, do a bit of magic, and end up with coefficients for a function of the form:</p>
<blockquote><p>f(t) = x<sub>0</sub> + x<sub>1</sub> cos(t) + x<sub>2</sub> sin(t) + x<sub>3</sub> cos(2t) + x<sub>4</sub> sin(2t) + &#8230;</p></blockquote>
<p>Now, <em>f(2 pi n/N)</em> returns exactly the <em>(n+1)</em>th character of the original string.</p>
<h3>Magic?</h3>
<p>Glad you ask. No, it&#8217;s not really magic. In fact, I used the trigonometric interpolation polynomial from Wikipedia&#8217;s article on the <a href="http://en.wikipedia.org/wiki/Discrete_Fourier_transform">Discrete Fourier transform</a> (remember: it&#8217;s science if you copied it from Wikipedia!):</p>
<blockquote><p>p(t) = 1/N * (X<sub>0</sub> + X<sub>1</sub> e<sup>it</sup> + &#8230; + X<sub>N/2</sub> cos(N/2 t) + X<sub>N/2+1</sub> e<sup>(-N/2+1)it</sup> + &#8230; + X<sub>N-1</sub> e<sup>-it</sup></p></blockquote>
<p>Here, <em>X<sub>i</sub></em> are the complex values of the Fourier series, and <em>e<sup>±it</sup></em> transforms to <em>cos t ± i sin t</em> according to Euler&#8217;s formula. The lone <em>cos</em> term in the middle doesn&#8217;t show up if <em>N</em> is odd.</p>
<p>Now, if the Discrete Fourier Transform is fed with real values, it holds that</p>
<blockquote><p>X<sub>i</sub> = X<sub>N-i</sub><sup>*</sup></p></blockquote>
<p>or, in other words, the right half of the series is equal to the complex conjugates (<em>(a + i b)<sup>*</sup> = a - i b</em>) of the left half in reverse order. Due to that, <em>p(t)</em> gets a lot simpler after a bit of reduction:</p>
<blockquote><p>p(t) = 1/N * (X<sub>0</sub> + 2 Re{X<sub>1</sub>} cos t - 2 Im{X<sub>1</sub>} sin t + &#8230; + Re{X<sub>N/2</sub>} cos(N/2 t)</p></blockquote>
<p>Again, the last term disappears for odd <em>N</em>.</p>
<p>There we are, all magic has now been reduced to more or less tangible math.</p>
<h3>The program</h3>
<p>I&#8217;ve written a small C program that takes as its input an arbitrary string and outputs the above function, modified a bit so that you can use the character index directly, i.e. f(4) gives you the<br />
fifth character of the original string.</p>
<p>The generated function will typically have an error of less than 0.1 at each position (which goes away by rounding the values as Poromenos does it in his code). In fact, for the string &#8220;Hello world!&#8221;, the mean square error is less than 0.0019.</p>
<p>Because this isn&#8217;t exactly a serious project, I didn&#8217;t spend any time adding stuff like UTF-8 support. You&#8217;ll have to resign yourself to using <acronym title="American Standard Code for Information Interchange">ASCII</acronym> or any 8-bit-per-character encoding.</p>
<p>Compiling the code requires that you have <a href="http://fftw.org/">fftw3</a> installed (including header files).</p>
<p>You can <a href="http://jan-krueger.net/src/fourierfit.c">download the code</a> or look at it in all its syntax-highlighted glory:</p>

<div class="wp_syntax"><div class="code"><pre class="c"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339933;">#include &lt;string.h&gt;</span>
<span style="color: #339933;">#include &lt;complex.h&gt;</span>
<span style="color: #339933;">#include &lt;math.h&gt;</span>
<span style="color: #339933;">#include &lt;fftw3.h&gt;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/*
 * fourierfit.c:
 * Fits a series of sines/cosines onto a series of character values from a
 * string.
 *
 * Copyright (c) 2008, Jan Krueger &lt;jast@heapsort.de&gt;
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 */</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/*
 * Compile like this:
 * cc -o fourierfit -lm -lfftw3 fourierfit.c
 */</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/*
 * Precision of output function (in digits after decimal point).
 * Yes, it's a string. printf much?
 */</span>
<span style="color: #339933;">#define PRECISION &quot;3&quot;</span>
<span style="color: #808080; font-style: italic;">/* Names of cos/sin functions to use in output */</span>
<span style="color: #339933;">#define COSNAME &quot;cos&quot;</span>
<span style="color: #339933;">#define SINNAME &quot;sin&quot;</span>
<span style="color: #808080; font-style: italic;">/* Name of function variable */</span>
<span style="color: #339933;">#define FNAME &quot;t&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Don't change below here etc. */</span>
&nbsp;
<span style="color: #339933;">#define PREC_FORMAT &quot;%.&quot;PRECISION&quot;f&quot;</span>
<span style="color: #993333;">const</span> <span style="color: #993333;">char</span> *cos_format = <span style="color: #ff0000;">&quot; %c &quot;</span>PREC_FORMAT<span style="color: #ff0000;">&quot;*&quot;</span>COSNAME<span style="color: #ff0000;">&quot;(&quot;</span>PREC_FORMAT<span style="color: #ff0000;">&quot;*&quot;</span>FNAME
	<span style="color: #ff0000;">&quot;)&quot;</span>;
<span style="color: #993333;">const</span> <span style="color: #993333;">char</span> *sin_format = <span style="color: #ff0000;">&quot; %c &quot;</span>PREC_FORMAT<span style="color: #ff0000;">&quot;*&quot;</span>SINNAME<span style="color: #ff0000;">&quot;(&quot;</span>PREC_FORMAT<span style="color: #ff0000;">&quot;*&quot;</span>FNAME
	<span style="color: #ff0000;">&quot;)&quot;</span>;
&nbsp;
<span style="color: #993333;">void</span> format_term<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> *f, <span style="color: #993333;">double</span> d, <span style="color: #993333;">int</span> p, <span style="color: #993333;">int</span> N<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #000066;">printf</span><span style="color: #66cc66;">&#40;</span>f, <span style="color: #66cc66;">&#40;</span>d &gt;= <span style="color: #cc66cc;">0</span> ? <span style="color: #ff0000;">'+'</span> : <span style="color: #ff0000;">'-'</span><span style="color: #66cc66;">&#41;</span>,
		fabs<span style="color: #66cc66;">&#40;</span>d<span style="color: #66cc66;">&#41;</span>, <span style="color: #808080; font-style: italic;">/* scale of function */</span>
		<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">double</span><span style="color: #66cc66;">&#41;</span>p * M_PI * <span style="color: #cc66cc;">2.0</span> / <span style="color: #66cc66;">&#40;</span><span style="color: #993333;">double</span><span style="color: #66cc66;">&#41;</span>N <span style="color: #808080; font-style: italic;">/* scale of parameter */</span>
	<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">int</span> argc, <span style="color: #993333;">char</span> **argv<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #993333;">int</span> N;
	<span style="color: #993333;">int</span> odd;
	<span style="color: #993333;">int</span> i;
	<span style="color: #993333;">double</span> *in;
	fftw_complex *out;
	fftw_plan p;
	<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>argc != <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
		puts<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Syntax: fourierfit &lt;string&gt;&quot;</span><span style="color: #66cc66;">&#41;</span>;
		exit<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
	<span style="color: #66cc66;">&#125;</span>
	N = strlen<span style="color: #66cc66;">&#40;</span>argv<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
	odd = N % <span style="color: #cc66cc;">2</span>;
&nbsp;
	in = fftw_malloc<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">sizeof</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333;">double</span><span style="color: #66cc66;">&#41;</span> * N<span style="color: #66cc66;">&#41;</span>;
	out = fftw_malloc<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">sizeof</span> <span style="color: #66cc66;">&#40;</span>fftw_complex<span style="color: #66cc66;">&#41;</span> * N<span style="color: #66cc66;">&#41;</span>;
&nbsp;
	p = fftw_plan_dft_r2c_1d<span style="color: #66cc66;">&#40;</span>N, in, out,
		FFTW_ESTIMATE | FFTW_DESTROY_INPUT<span style="color: #66cc66;">&#41;</span>;
&nbsp;
	<span style="color: #808080; font-style: italic;">/* Fill in array */</span>
	<span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span>i = <span style="color: #cc66cc;">0</span>; i &lt; N; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
		in<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> = <span style="color: #66cc66;">&#40;</span><span style="color: #993333;">double</span><span style="color: #66cc66;">&#41;</span> argv<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>;
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	fftw_execute<span style="color: #66cc66;">&#40;</span>p<span style="color: #66cc66;">&#41;</span>;
	fftw_destroy_plan<span style="color: #66cc66;">&#40;</span>p<span style="color: #66cc66;">&#41;</span>;
	fftw_free<span style="color: #66cc66;">&#40;</span>in<span style="color: #66cc66;">&#41;</span>;
&nbsp;
	<span style="color: #808080; font-style: italic;">/* &quot;DC&quot; */</span>
	<span style="color: #000066;">printf</span><span style="color: #66cc66;">&#40;</span>PREC_FORMAT, creal<span style="color: #66cc66;">&#40;</span>out<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>/N<span style="color: #66cc66;">&#41;</span>;
&nbsp;
	<span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span>i = <span style="color: #cc66cc;">1</span>; i &lt;= <span style="color: #66cc66;">&#40;</span>N<span style="color: #cc66cc;">-1</span><span style="color: #66cc66;">&#41;</span>/<span style="color: #cc66cc;">2</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
		format_term<span style="color: #66cc66;">&#40;</span>cos_format, <span style="color: #cc66cc;">2.0</span>*creal<span style="color: #66cc66;">&#40;</span>out<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>/N, i, N<span style="color: #66cc66;">&#41;</span>;
		format_term<span style="color: #66cc66;">&#40;</span>sin_format, <span style="color: #cc66cc;">-2.0</span>*cimag<span style="color: #66cc66;">&#40;</span>out<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>/N, i, N<span style="color: #66cc66;">&#41;</span>;
	<span style="color: #66cc66;">&#125;</span>
	<span style="color: #808080; font-style: italic;">/* Nyquist component */</span>
	<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>!odd<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
		format_term<span style="color: #66cc66;">&#40;</span>cos_format, creal<span style="color: #66cc66;">&#40;</span>out<span style="color: #66cc66;">&#91;</span>N/<span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>/N, N/<span style="color: #cc66cc;">2</span>, N<span style="color: #66cc66;">&#41;</span>;
	<span style="color: #66cc66;">&#125;</span>
	<span style="color: #000066;">printf</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #66cc66;">&#41;</span>;
	fftw_free<span style="color: #66cc66;">&#40;</span>out<span style="color: #66cc66;">&#41;</span>;
	exit<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<h3>The example</h3>
<p>For the sake of completeness, here&#8217;s the function for &#8220;Hello world!&#8221; as generated by the above code:</p>
<blockquote><p>f(t) = 93.083 - 10.549*cos(0.524*t) - 0.195*sin(0.524*t) - 17.167*cos(1.047*t) + 22.805*sin(1.047*t) - 5.000*cos(1.571*t) - 1.833*sin(1.571*t) + 8.667*cos(2.094*t) + 19.630*sin(2.094*t) - 7.951*cos(2.618*t) - 1.638*sin(2.618*t) + 10.917*cos(3.142*t)</p></blockquote>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/development/howto-encode-your-string-trigonometrically/feed</wfw:commentRss>
		</item>
		<item>
		<title>Why Humanity Is Blocked</title>
		<link>http://jan-krueger.net/comm/internet/why-humanity-is-blocked</link>
		<comments>http://jan-krueger.net/comm/internet/why-humanity-is-blocked#comments</comments>
		<pubDate>Sun, 25 Nov 2007 18:04:20 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[Internet]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/uncategorized/why-humanity-is-blocked</guid>
		<description><![CDATA[ Please read carefully the following important message that does not come from the anonymous persons running whyfirefoxisblocked.com and whydiggisblocked.com.
You&#8217;ve reached this page because the site you were trying to visit now blocks visitors from the human race and other beings capable of browsing the web.
The users on continents such as America, Asia, Europe and [...]]]></description>
			<content:encoded><![CDATA[<p> Please read carefully the following important message that does not come from the anonymous persons running whyfirefoxisblocked.com and whydiggisblocked.com.</p>
<p style="text-align: center; font-size: 200%; color: #c10000; line-height: 120%">You&#8217;ve reached this page because the site you were trying to visit now blocks visitors from the human race and other beings capable of browsing the web.</p>
<p><strong>The users on continents such as America, Asia, Europe and Antarctica openly endorse critical thinking, a function of the human brain that allows humans to ignore irrelevant perceptions such as advertisement on web sites, and are well known for paying no huge amount of money  to the owners of sites they visit. Humans that ignore all advertisement are an infringement of the rights of web site owners and developers. Numerous web sites exist in order to provide quality content in exchange for displaying ads, humans who don&#8217;t click on these ads are stealing bandwidth without paying for it and website owners deserve a method to block this unauthorized bandwith theft.</strong></p>
<p><strong>Since the human brain does not allow website owners a method for excluding perceptions and do not obey &#8220;give away all your money&#8221; law, abiding webmasters are forced to block all humans. Demographics have shown that not only are humans a somewhat small and insignificant percentage of the planet, they actually are even smaller in terms of value, therefore blocking these beings seems to have only minimal financial drawbacks, whereas ending resource theft has tremendous financial rewards for honest, hard-working website owners and developers.</strong></p>
<p><strong>If you wish to view the site you came from we suggest stopping being human and becoming a machine instead.</strong></p>
<p>(Of course, <a href="http://whydiggisblocked.com/" rel="nofollow">humans using Digg are where the real evil is at</a>.)</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/comm/internet/why-humanity-is-blocked/feed</wfw:commentRss>
		</item>
		<item>
		<title>Git cheat sheet, extended edition</title>
		<link>http://jan-krueger.net/development/git-cheat-sheet-extended-edition</link>
		<comments>http://jan-krueger.net/development/git-cheat-sheet-extended-edition#comments</comments>
		<pubDate>Tue, 18 Sep 2007 22:51:52 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/development/git-cheat-sheet-extended-edition</guid>
		<description><![CDATA[A few days ago, I posted a cheat sheet for Git (just as last time, Git is a really cool revision control system). Let&#8217;s face it: it was ugly. Not something you would actually hang up where other people could see it, was it? Here&#8217;s the remedy, which also works on both A4 and Letter [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago, I posted a <a href="http://jan-krueger.net/development/git-cheat-sheet-take-two">cheat sheet for Git</a> (just as last time, <a href="http://git.or.cz/">Git</a> is a really cool revision control system). Let&#8217;s face it: it was ugly. Not something you would actually hang up where other people could see it, was it? Here&#8217;s the remedy, which also works on both A4 and Letter and is more detailed. <span id="more-21"></span></p>
<p>In more detail, the additional details are:</p>
<ul>
<li>The old &#8220;structure overview&#8221; diagram showing the big picture of repositories and working trees is now a lot bigger and a lot <strong>more detailed</strong>. It comes along with a glossary, a few notes on getting started, a list of useful tools you may want to look at, and links to the most important websites of all (cough).</li>
<li>The whole workflow diagram is gone since it was not really all that clear. Instead, some of the groups of commands are connected with lines, indicating in which sequence you&#8217;ll probably use some of these commands.</li>
<li>Some commands have shuffled around a bit, and there&#8217;s a new box with information on Git&#8217;s <strong>configuration options</strong>.</li>
<li>In order to fit it all together, it&#8217;s now a two-sided cheat sheet. The &#8220;front&#8221; side has overview-style things on it and the &#8220;back&#8221; side is mostly a command reference.</li>
</ul>
<p>So how&#8217;s it look like? Observe:<br />
<img src="http://jan-krueger.net/wordpress/wp-content/uploads/2007/09/git-cheat-sheet1.png" alt="Thumbnail for Git cheat sheet, version 2" /></p>
<p>Because Inkscape saw fit to generate annoyingly huge <acronym title="Portable Document Format">PDF</acronym> files from the source, this time you get a zipped two-page <acronym title="Portable Document Format">PDF</acronym> document as well as the Inkscape source files.</p>
<ul>
<li><a href="http://jan-krueger.net/wordpress/wp-content/uploads/2007/09/git-cheat-sheet-v2.zip">Git Cheat Sheet, version 2 (<acronym title="Portable Document Format">PDF</acronym> in ZIP archive, 1.6 <acronym title="Megabyte">MB</acronym> compressed)</a></li>
<li><a href="http://jan-krueger.net/wordpress/wp-content/uploads/2007/09/git-cheat-sheet-v2-front.svg">Git Cheat Sheet, version 2 front side (Inkscape <acronym title="Scalable Vector Graphics">SVG</acronym>)</a></li>
<li><a href="http://jan-krueger.net/wordpress/wp-content/uploads/2007/09/git-cheat-sheet-v2-back.svg">Git Cheat Sheet, version 2 back side (Inkscape <acronym title="Scalable Vector Graphics">SVG</acronym>)</a></li>
</ul>
<p>Another thing that I didn&#8217;t pay attention to last time was the license. No longer: this cheat sheet is licensed to you under the terms of a <a href="http://creativecommons.org/licenses/by-nc/3.0/">Creative Commons Attribution-NonCommercial 3.0 license</a>. For attribution, should you want to create a derived work, please include a mention of http://git.jk.gs/ and, if available space permits, my name.</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/development/git-cheat-sheet-extended-edition/feed</wfw:commentRss>
		</item>
		<item>
		<title>Git cheat sheet, take two</title>
		<link>http://jan-krueger.net/development/git-cheat-sheet-take-two</link>
		<comments>http://jan-krueger.net/development/git-cheat-sheet-take-two#comments</comments>
		<pubDate>Wed, 12 Sep 2007 23:22:41 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/development/git-cheat-sheet-take-two</guid>
		<description><![CDATA[Update: Since I first posted this, I have created a new and (in my opinion) better Git cheat sheet. You might want to have a look at that one.
Today I came across Zack Rusin&#8217;s Git cheat sheet (just so we&#8217;re on the same page: Git is a really good distributed revision control system). I quite [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update:</strong> Since I first posted this, I have created a new and (in my opinion) <a href="/development/git-cheat-sheet-extended-edition">better Git cheat sheet</a>. You might want to have a look at that one.</p>
<p>Today I came across <a href="http://zrusin.blogspot.com/2007/09/git-cheat-sheet.html">Zack Rusin&#8217;s Git cheat sheet</a> (just so we&#8217;re on the same page: Git is a really good distributed revision control system). I quite like the idea but unfortunately, Zack&#8217;s design is fairly useless to me because</p>
<ul>
<li>the colors don&#8217;t print well on black and white;</li>
<li>it&#8217;s designed for Letter paper. Letter paper doesn&#8217;t exist around here. Give me A4.</li>
</ul>
<p>While trying to change Zack&#8217;s file to address these issues, Inkscape kept crashing on me until I finally gave up and just started from scratch (in – don&#8217;t tell anyone – OpenOffice.org Draw). This is the result:  <a href="http://jan-krueger.net/wordpress/wp-content/uploads/2007/09/git-cheat-sheet.pdf" title="Git Cheat Sheet (A4 PDF version)">Git Cheat Sheet (A4 <acronym title="Portable Document Format">PDF</acronym> version)</a>.<span id="more-15"></span>Here&#8217;s a preview:</p>
<p><a href="http://jan-krueger.net/wordpress/wp-content/uploads/2007/09/git-cheat-sheet.pdf"><img src="http://jan-krueger.net/wordpress/wp-content/uploads/2007/09/git-cheat-sheet.png" alt="Git Cheat Sheet Thumbnail" /></a></p>
<p>You will quickly notice that my cheat sheet has a number of differences from Zack&#8217;s:</p>
<ul>
<li><strong>Less work on design.</strong> I concentrated on readability. Rounded corners is all you&#8217;ll get from me.</li>
<li><strong>Different commands.</strong> I think some commands from the original selection are not all that regularly used; instead, I included other commands. My list of commands is a lot longer; to make up for that, I omitted lots of explanations. I focussed on explaining things that are not obvious to people who already have experience with more classic revision control systems. The information in my cheat sheet was compiled from Zack&#8217;s cheat sheet and the <a href="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html">Git user&#8217;s manual</a>.</li>
<li><strong>Additional graph.</strong> Because Git&#8217;s ideas of commits, working copies and branches are a bit different from those in some other systems, I tried to visualize how it works.</li>
</ul>
<p>There might be mistakes in the document, or things that can easily be improved on. If you spot any (or have anything else to add), I&#8217;d love to hear from you. Anyway, I hope this cheat sheet is useful for you.</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/development/git-cheat-sheet-take-two/feed</wfw:commentRss>
		</item>
		<item>
		<title>Acer&#8217;s &#8220;Linux&#8221; notebooks&#8230; boot. What, you need more?</title>
		<link>http://jan-krueger.net/general-creativity/acers-linux-notebooks-boot</link>
		<comments>http://jan-krueger.net/general-creativity/acers-linux-notebooks-boot#comments</comments>
		<pubDate>Mon, 10 Sep 2007 23:53:19 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[General Creativity]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/uncategorized/creative-marketing-acers-linux-notebooks-boot</guid>
		<description><![CDATA[I am always happy to find alternative applications of creativity. Today&#8217;s focus is on Acer or, more specifically, on Acer&#8217;s so-called Linux notebooks. Shipped exlusively in Europe (as far as I can tell), they attract interest by being cheaper than the version shipped with some version of Windows. Currently, the difference in price weighs in [...]]]></description>
			<content:encoded><![CDATA[<p>I am always happy to find alternative applications of creativity. Today&#8217;s focus is on <a href="http://en.wikipedia.org/wiki/Acer_%28company%29" title="Acer - Wikipedia, the free encyclopedia">Acer</a> or, more specifically, on Acer&#8217;s so-called Linux notebooks. Shipped exlusively in Europe (as far as I can tell), they attract interest by being cheaper than the version shipped with some version of Windows. Currently, the difference in price weighs in at 47.01 € at Amazon Germany (that&#8217;s, very roughly, 10% of the full price).</p>
<p>And, of course, they come with Linux pre-installed. So that&#8217;s fine for basic usage, even if it takes a little getting used to for the more Windows- savvy people. Right?</p>
<p>Let&#8217;s take a closer look. Acer&#8217;s Linux distribution of choice appears to be <a href="http://www.linpus.com/" title="Linpus Linux">Linpus Linux</a> (a <a href="http://fedora.redhat.com/" title="Fedora Linux">Fedora</a> fork developed by Linpus Technologies of Taiwan). Their website is down right now (I wonder&#8230;), but from what I gather from the rest of the web, Linpus comes in several flavors, among them a desktop edition and a server edition. The desktop edition is based on KDE 3.4 et cetera et cetera, so nothing really surprising there. Even if Linpus is rather unusual, it&#8217;s probably decent enough. Right? Right? Well&#8230; Guess again.<span id="more-14"></span></p>
<h3>So what&#8217;s the big deal?</h3>
<p>Turns out Acer thought it would be just spiffy to install the basic edition of Linpus. I would provide you with a screenshot but&#8230; did I mention that their website is down? So, as <a href="http://www.linuxforums.org/forum/linux-newbie/102278-acer-laptop-linpus-linux.html">several</a> <a href="http://www.linuxquestions.org/questions/showthread.php?t=462978">unhappy</a> <a href="http://www.linuxquestions.org/questions/showthread.php?t=576433">customers</a> <a href="http://broadcomwireless.blogspot.com/2005/10/what-is-this-blog-about.html">explain</a> <a href="http://ivangarcia.org/blog/?p=13">with</a> <a href="http://blog.hanoilug.org/?p=60">varying</a> <a href="http://www.driverheaven.net/linux-operating-systems/62655-im-linux-green.html">levels</a> <a href="http://linux.slashdot.org/comments.pl?sid=258763&amp;cid=20074795">of</a> <a href="http://larko.wordpress.com/2006/11/03/computing-problems/">frustration</a>, all you get with Acer&#8217;s idea of Linux is a root prompt, i.e. a black and white text screen on which you can enter. That&#8217;s right, there is no graphical user interface <em>at all</em>.</p>
<p>This is a clever move by Acer. I&#8217;m sure it&#8217;s easy to ship their laptops with something like that, and it gets those pesky legal restrictions out of the way which tell vendors they have to include an operating system in the package.</p>
<p>As a consequence, users who may have heard that Linux is pretty alright to work with and thus give Acer&#8217;s Linux notebooks a try are pretty much stumped. Some installations even ask the user to log in even though they never created any accounts. Suffice to say that the login data is not supplied in the manuals shipped with the notebook. It&#8217;s hidden somewhere on the Acer support website, and you can find it on the Linpus website (which, as I may have written already, is unreachable right now). For reference, the user name is root (which is the user that has total control over the system and can royally mess things up) and the password is something like &#8220;111111&#8243;. we should have known that, shouldn&#8217;t we?</p>
<h3>What does Acer say?</h3>
<p>Acer, if asked about this in support queries, appears to be pretty blunt in its answers, basically telling customers that they only ship with Linux so they meet the legal requirements, and they really don&#8217;t care how usable that Linux is. This would be perfectly reasonable if Acer actually included some note to that degree in its product descriptions. Advertising these notebooks as shipping with Linux (or even Linpus Linux, of which there exist versions with graphical interface as well) seems like a misrepresentation of the package contents to me.</p>
<h3>On the positive side&#8230;</h3>
<p>Let&#8217;s keep in mind, though, that if you actually know your way around computers, you can easily install something different on those laptops, like your old copy of Windows or a more sensible Linux distribution such as <a href="http://www.ubuntu.com/" title="Ubuntu">Ubuntu</a>. In that case, buying one of Acer&#8217;s Linux notebooks might be for you.</p>
<p>I&#8217;m secretly of the opinion that notebooks are throw-away hardware; no notebook any of my friends or myself have bought in the last several years has lasted longer than two years; in most cases, first defects (such as the display going on LSD and becoming totally psychedelic) appear as early as one year after purchase. That&#8217;s simply not acceptable for the more expensive notebooks out there (in 2001, I bought a notebook for 2500.- €, only to have its CPU fan&#8217;s screw sockets detach from the mainboard after about a year (random CPU overheating, anyone?) and the touchpad and battery dying in half-year intervals after that).</p>
<p>In short, I think it might be sensible to go for the cheapest thing that could possibly work (within a set of standards of your choice). In this sense, Acer&#8217;s Linux notebooks might be a reasonable choice, provided you are going to setup your own operating system. On the other hand, you might want to wait for the Asus Eee notebooks.</p>
<h3>Conclusion</h3>
<p>Good on you, Acer! Easy way of increasing your target market without any hassle. Let&#8217;s hope that any frustrated customers  blame their problems on Linux instead of you, so you can keep cutting costs this way. Or let&#8217;s just hope that the legal restrictions get dropped so you can drop the act and there are no disappointments anymore.</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/general-creativity/acers-linux-notebooks-boot/feed</wfw:commentRss>
		</item>
		<item>
		<title>Problems in life engineering</title>
		<link>http://jan-krueger.net/life/problems-in-life-engineering</link>
		<comments>http://jan-krueger.net/life/problems-in-life-engineering#comments</comments>
		<pubDate>Wed, 25 Jul 2007 17:15:30 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[Life Engineering]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/life/problems-in-life-engineering</guid>
		<description><![CDATA[Okay, so there are problems in knowledge engineering, AGI in particular (to recall, AGI is a machine or program that can demonstrate intelligence on the complexity level of humans). More generally, in every domain of sufficiently complex structure, AI fails, sometimes spectacularly. A well-known example is the board game Go, for which nobody has managed [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, so there are <a href="/ke/problems-in-knowledge-engineering">problems in knowledge engineering</a>, <acronym title="Artificial General Intelligence">AGI</acronym> in particular (to recall, <acronym title="Artificial General Intelligence">AGI</acronym> is a machine or program that can demonstrate intelligence on the complexity level of humans). More generally, in every domain of sufficiently complex structure, <acronym title="Artificial Intelligence">AI</acronym> fails, sometimes spectacularly. A well-known example is the board game Go, for which nobody has managed yet to design a computer opponent that can beat players above the level of novice.</p>
<p>Yet humans manage many of these tasks seemingly without any problems. One might be tempted to think that the human brain is the ideal &#8220;thinking machine&#8221;. In reality, it has a staggering number of bugs which produce incorrect actions or results in a variety of situations.<span id="more-12"></span></p>
<h3>Humans are not statisticians</h3>
<p>Simple statistical questions are easy for humans. It is not difficult for most people to estimate that the chances for rolling a 6 are significantly higher than those for rolling a 6 three times in a row. You don&#8217;t even need formal knowledge of probability theory to know that.</p>
<p>It gets more complicated when you introduce conditional probabilities. Observe.</p>
<h4>Which door?</h4>
<p>A once popular game show works this way: you are asked to choose one of three doors, behind one of which there is treasure beyond measure (sorry for that&#8230; I promise I won&#8217;t do it again in this article). After you have chosen, the show master opens one of the two other doors (making sure that it isn&#8217;t the one with the riches behind it). Now you are allowed to change your choice to the other door that is still closed, if you want to. What&#8217;s better, sticking with the old choice or changing your mind?</p>
<p>You will probably be tempted to say that it doesn&#8217;t make a difference, and you would be wrong. In fact, if you stick with your first choice, your chance of getting rich (during the show, to be precise) amounts to one out of three. On the other hand, if you change your mind, it&#8217;s two out of three.  In case you don&#8217;t believe me, get your hands on a recent introductory book about probability theory. I&#8217;m fairly sure they all have this example.</p>
<p>Here&#8217;s a great trick to earn money with this: on any party with more than 23 guests (under normal circumstances), start a bet that at least two guests have the same birthday (excluding year, of course). You will win more often than not (50.7% of the time when there are 23 guests; on a party with 30 guests, it&#8217;s 70%).</p>
<h4>Will I die, doctor?</h4>
<p>It gets even worse when <a href="http://http://en.wikipedia.org/wiki/Bayes%27_theorem" title="Bayes' theorem - Wikipedia, the free encyclopedia">Bayes&#8217; theorem</a> (which is about dependencies between various conditional probabilities) gets involved. A popular example goes this way. Suppose there is a medicinical test designed to diagnose cancer, which occurs in 0.5% of the population. The test detects the cancer correctly in 99% of all cases, but it also incorrectly gives a positive results in 2% of healthy people. Now suppose someone gets tested and the test comes out positive. What&#8217;s the probability that the person has cancer?</p>
<p>Okay, let&#8217;s think about this. 99% is a pretty high number, right? And 2% is a pretty low one? So the test should be fairly accurate, i.e. the chance that our subject will die is high enough. Or so you might think&#8230; the correct answer is about 20%. Not so good after all, huh?</p>
<p>If you want to see it for yourself, there&#8217;s a more in-depth page with <a href="http://yudkowsky.net/bayes/bayes.html" title="An Intuitive Explanation of Bayesian Reasoning">an intuitive explanation of Bayesian Reasoning</a> that has the same example with slightly different numbers and a detailed solution.</p>
<h3>Humans are not hypothesis testers</h3>
<p>Suppose I give you data and ask you if it supports a given hypothesis. Chances are that you&#8217;ll either tell me that the data supports the hypothesis or that it supports the opposite of the hypothesis. It&#8217;s probably a lot less likely that you tell me the data says nothing, i.e. that it&#8217;s random. That&#8217;s because humans don&#8217;t see randomness easily. For example, from the three plots of &#8220;random&#8221; data in &#8220;<a href="http://norvig.com/experiment-design.html" title="Warning Signs in Experimental Design and Interpretation">Warning Signs in Experimental Design and Interpretation</a>&#8221; (section D7), which one is truly random? I&#8217;ll give you a hint: it&#8217;s not the right one.</p>
<p>Although the rightmost graph looks like it&#8217;s random (because there are no clusters of dots), it&#8217;s actually not. Random data doesn&#8217;t mean that there are no clusters. In truly random data, clusters occur naturally. The truly random graph is the one on the left.</p>
<p>It gets even worse if you don&#8217;t have an overview of the data in question. I regularly use the bus to get downtown, and I keep catching myself thinking &#8220;these buses are always early when I&#8217;m at the bus stop right on time&#8221;. This is, of course, very much impossible (given the knowledge that the buses are not always early). What gives? I obviously only notice those cases in which my hypothesis is indeed correct and don&#8217;t notice the others because they are not noteworthy enough.</p>
<p>This incorrect thinking is subject to the so-called <em>confirmation bias</em>. There&#8217;s <em>disconfirmation bias</em> too, which means that you doubt hypotheses by default, even if they are true most of the time, because you&#8217;re too focused on the times when they are not true.</p>
<h3>Humans think too highly of their thinking</h3>
<p>It gets even worse. Let&#8217;s get to central issues in living. Happiness is an interesting problem there. People at Harvard have found that <a href="http://www.hno.harvard.edu/gazette/2004/01.15/01-happiness.html" title="Scientists pursue happiness">&#8220;when we try to predict what will make us happy, we&#8217;re often wrong&#8221;</a>. I&#8217;m ready to bet that this is true for many other central areas in life. Another particularly sad example of the same phenomenon is those people who keep sending you &#8220;funny&#8221; e-mails. They actually think you find those mails funny!</p>
<p>Here&#8217;s another goof in the brain, the one which motivates meditation: getting worked up over something that upsets you does not help at all, even if it&#8217;s the straightforward thing to do. Meditation actually makes it possible for the adept practitioner to let emotions like anger pass so that they are left with the pure facts and can decide what to do with them. Emotions, by the way, are the most defining difference between real intelligence and artificial intelligence. At least that&#8217;s what I believe. Emotions motivate us and keep us running, but they are also hindrances in many situations, more so for some than for others.</p>
<p>Another popular myth is that the conscious mind (the part of your mind you&#8217;re thinking with) does anything <em>except</em> thinking. Utterly wrong; everything you actually do is controlled by parts of your mind you are not aware of. It can be measured, for example, that you have decided to move your arm before you know that you are going to move it (though I&#8217;d really like to know how the experiment is set up&#8230; &#8220;Now! Uh, wait, that was a dud&#8230; now! Or now?&#8221;). This extends to many other areas. Telling yourself you are not afraid of the big black spider right next to you doesn&#8217;t usually make a difference. Neither does telling yourself to remember the answer on a test question that you are sure you knew before the test began. The list goes on and on.</p>
<p>Some people have argued that consciousness developed in humans less than two thousand years ago (I&#8217;m afraid I forgot the actual numbers). In other words, humans have functioned without it before. Hard too imagine, though, isn&#8217;t it?</p>
<h3>Conclusion</h3>
<p>Let&#8217;s face it: we&#8217;re actually incompetent at living (and many other things), at least by default. Error correction is possible but it takes a serious amount of getting used to, and conscious intervention.</p>
<p>Now why did people want to clone human intelligence again?</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/life/problems-in-life-engineering/feed</wfw:commentRss>
		</item>
		<item>
		<title>Problems in knowledge engineering</title>
		<link>http://jan-krueger.net/ke/problems-in-knowledge-engineering</link>
		<comments>http://jan-krueger.net/ke/problems-in-knowledge-engineering#comments</comments>
		<pubDate>Mon, 21 May 2007 21:42:46 +0000</pubDate>
		<dc:creator>Jan</dc:creator>
		
		<category><![CDATA[Knowledge Engineering]]></category>

		<guid isPermaLink="false">http://jan-krueger.net/ke/problems-in-knowledge-engineering</guid>
		<description><![CDATA[Given the &#8220;right&#8221; philosophical attitude about how the world works, the ultimate goals of knowledge engineering, namely obtaining, processing, using and making accessible all kinds of knowledge, can definitely be achieved. This set of bold goals, however, presents researchers with very difficult problems. All attempts that exist today are restricted to small classes of knowledge.
What [...]]]></description>
			<content:encoded><![CDATA[<p>Given the &#8220;right&#8221; philosophical attitude about how the world works, the ultimate goals of knowledge engineering, namely obtaining, processing, using and making accessible all kinds of knowledge, can definitely be achieved. This set of bold goals, however, presents researchers with very difficult problems. All attempts that exist today are restricted to small classes of knowledge.<span id="more-7"></span></p>
<h3>What needs to be done</h3>
<p>One of the major applications of knowledge engineering is generating knowledge (that is, meaningful information) from input. This input may be arbitrary data, sometimes incomplete or noisy, and often confusing. A classic example is a black-and-white photograph of a zebra standing in front of a similarly striped wall of some sort or, in this case, a highly artistic drawing of the same (sadly, I have neither the zebra nor the wall to take a photograph of):</p>
<p style="text-align: center"><img src="http://jan-krueger.net/wordpress/wp-content/uploads/2007/05/zebra.png" title="Zebra" alt="Zebra" height="300" width="400" /></p>
<h3>Brain vs. computer, round one: autonomy</h3>
<p>I&#8217;m not saying it will be impossible to build a system that recognizes zebras, but it will probably need to be tailored to this exact purpose, such as a program that can decide whether a given image shows a zebra in front of a wall. The human brain does the recognition job quite easily, along with other jobs that are not exactly easy to do with machines.</p>
<p>At some point, many knowledge engineers that are presented with the task of building pattern recognition software will probably get rather jealous of evolution, which managed to create a system that is astonishingly flexible and manages all kinds of learning without obvious struggle. If only we had the source code&#8230;</p>
<p>This desire becomes most obvious in the wish for so-called <em>strong <acronym title="Artificial Intelligence">AI</acronym></em> or specifically <em>artificial general intelligence (<acronym title="Artificial General Intelligence">AGI</acronym>)</em>, i.e. a machine that can do everything the human brain is capable of. We are nowhere near that, though, so research typically investigates <em>weak <acronym title="Artificial Intelligence">AI</acronym></em>, which is about solving domain-specific problems (there are <a href="http://agiri.org/" title="Artificial General Intelligence Research Institute">people doing research on <acronym title="Artificial General Intelligence">AGI</acronym></a> though).</p>
<h4>Supervised learning</h4>
<p>The usual way of going about that involves setting up some kind of exciting algorithm and then feeding it with training data (examples of inputs along with the desired outcome of the recognition task). This is called <em>supervised learning</em>.</p>
<p>This approach actually works quite well for many things. Even given very limited experience with machine learning, I have managed to write software that performs <a href="http://en.wikipedia.org/wiki/Speaker_recognition" title="Speaker recognition - Wikipedia, the free encyclopedia">speaker recognition</a>, with the assistance of a few other people. I can&#8217;t give you hard numbers about its accuracy because the numbers we had were restricted to a miniature set of test files so they didn&#8217;t really say much, but within that test set it was very good. Still, we had to research domain-specific methods to extract the most meaningful features of the human voice from speech files and even more effort went into fine-tuning parameters, so most of the work was ours and not the machine&#8217;s.</p>
<h4>Unsupervised learning</h4>
<p>Right, but what if you do not know the right answers yourself? This is where<em> unsupervised learning</em> comes in, which means finding groups of similar samples in the input data. If the unsupervised learning system is given inputs which can be separated into three different groups, chances are it will learn to sort inputs into three categories (this is called <em>clustering</em>). The disadvantage, of course, is that the clusters are not labelled, so someone else gets to make sense of them. Also, since nobody knows just how many &#8220;real&#8221; clusters there are, you can&#8217;t be sure if the system doesn&#8217;t decide on the &#8220;wrong&#8221; number of clusters.</p>
<h4>Reinforcement learning</h4>
<p>Now suppose you want a system to learn on its own, because it needs to be autonomous. This will happen in a trial-and-error process: the system is faced with a situation, decides on an action and observes the outcome (and, specifically, the quality of this outcome). But how will the system decide how good the outcome of its actions was? It can&#8217;t, because it does not actually understand the meaning of the task it&#8217;s performing. The solution is to supply it with a goal function. The goal function maps each possible outcome to a score value, and the task of unsupervised learning is to optimize its actions with respect to that goal function.  And who do you think will be responsible for designing this goal function? That&#8217;s right.</p>
<h4>The conclusion</h4>
<p>These observations allow only one conclusion right now: even weak <acronym title="Artificial Intelligence">AI</acronym> does not work without human intervention in most realistic cases. Winner of this round: brain.</p>
<h3>Explanation?</h3>
<p>It is difficult to make accurate general statements about <acronym title="Artificial Intelligence">AI</acronym>. Is it actually possible to design an <acronym title="Artificial General Intelligence">AGI</acronym>? Probably, because if the brain can do it, logic suggests that it can be imitated. Is it likely that this will happen? That&#8217;s next to impossible to say. I believe that the answer is no.</p>
<p>Strong intelligence in its existing implementations (humans) is extremely complex. In fact, nobody really understands how the brain works. Now, is it likely that anybody will ever fully understand the brain? No, because that would require that a single brain be capable of understand every aspect of itself. In other words, the brain would need the capacity to describe itself, which is logically impossible (just like no solid box can fit inside itself). The only way the brain could ever be fully explained is by collaboration of a team of researchers. Even then, though, I am very skeptical about the odds of success; have you ever seen a team of substantial size that can communicate well enough that it can be seen as a properly distributed &#8220;hive mind&#8221;?</p>
<p>It is far more likely, then, that a working <acronym title="Artificial General Intelligence">AGI</acronym> will be discovered by coincidence, just like many other scientific breakthroughs were coincidental. Humans are pathetically bad at estimating the odds in complex problems, so I will not presume to be able to make an accurate prediction. Anyway, it is my personal belief that this will not happen for a very long time, at the very least not during my lifetime.</p>
<h3>And now?</h3>
<p>For this reason, like many other people, I will focus on implementing weak <acronym title="Artificial Intelligence">AI</acronym> to solve problems. A number of successful approaches in weak <acronym title="Artificial Intelligence">AI</acronym> are not well understood either, but at least they work (some surprisingly well) and can be made sense of to some degree.</p>
<p>In the context of my general topic of interest, I would like to state that I even believe that <acronym title="Artificial General Intelligence">AGI</acronym> would come with its own set of difficult problems that may be even harder to control than those occurring in weak <acronym title="Artificial Intelligence">AI</acronym>. I will go into more detail in a follow-up that presents the human side of the scale.</p>]]></content:encoded>
			<wfw:commentRss>http://jan-krueger.net/ke/problems-in-knowledge-engineering/feed</wfw:commentRss>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.498 seconds -->
