<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.3.3" -->
<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/"
	>

<channel>
	<title>Vacuous Virtuoso &#187; Programming</title>
	<link>http://lipidity.com</link>
	<description>Despotic Development</description>
	<pubDate>Tue, 23 Dec 2008 06:24:04 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.3</generator>
	<language>en</language>
			<item>
		<title>CTGradient code bloat</title>
		<link>http://lipidity.com/apple/ctgradient-code-bloat/</link>
		<comments>http://lipidity.com/apple/ctgradient-code-bloat/#comments</comments>
		<pubDate>Tue, 20 Nov 2007 21:05:12 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

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

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

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

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

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

		<category><![CDATA[Source Code]]></category>

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

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

		<guid isPermaLink="false">http://lipidity.com/apple/cgradient-code-bloat/</guid>
		<description><![CDATA[While getting rid of extraneous junk in an application package is easy using Trimmit, the only way to prevent &#34;code bloat&#34; (and accompanying excess RAM and CPU usage) is through good programming practices. Where most developers fall short is in poor optimization of borrowed code. Let&#8217;s take CTGradient as an example as it&#8217;s well known [...]]]></description>
			<content:encoded><![CDATA[<p>While getting rid of extraneous junk in an application package is easy using <a href="http://lipidity.com/software/trimmit/">Trimmit</a>, the only way to prevent &quot;code bloat&quot; (and accompanying excess RAM and CPU usage) is through good programming practices. Where most developers fall short is in poor optimization of borrowed code. Let&#8217;s take CTGradient as an example as it&#8217;s well known and used (or more accurately, abused) in dozens of applications.</p>

<!--more-->

<p>CTGradient contains an incredible diversity of built-in gradients, gradient styles, and methods for creating fancy rainbows, radial gradients, linear gradients, aqua gradients, and a number of other interesting class and instance methods. It allows you to dynamically alter gradients by adding or removing colors, changing the level of transparency, filling NSRects or NSBezierPaths, rotating the gradient, etc. For demonstration purposes, all these features are excellent. For production, this is a nightmare.</p>

<p><strong><a href="http://pub.lipidity.com/CTGradient/CTGradient.m">CTGradient.m</a> weighs in at over 1300 lines of code.</strong></p>

<p>Ignoring Mr. Weider&#8217;s unique style of formatting, take a look through the code. If you&#8217;re putting this class in an application, you can immediately remove over a thousand lines. Just like that. But if you take some time to understand what&#8217;s going on, you can optimize this thing till it runs like a Ferrari.</p>

<p>You&#8217;ll notice <a href="http://lipidity.com/software/trimmit/">Trimmit</a> uses a gradient background for it&#8217;s window. Let&#8217;s cut down CTGradient until it matches the level of optimization of Trimmit&#8217;s gradient code.</p>

<h2>Clear the junk</h2>

<p>Firstly, let&#8217;s remove the methods we know for sure we won&#8217;t need. Remove the following methods completely from both the interface and the implementation (scroll down for more):</p>

<pre style='height:340px;overflow:scroll'><code>// We don't need the preset gradients

+ (id)dividerGradient;
+ (id)statusBarGradient;
+ (id)aquaSelectedGradient;
+ (id)aquaNormalGradient;
+ (id)aquaPressedGradient;
+ (id)unifiedSelectedGradient;
+ (id)unifiedNormalGradient;
+ (id)unifiedPressedGradient;
+ (id)unifiedDarkGradient;
+ (id)sourceListSelectedGradient;
+ (id)sourceListUnselectedGradient;
+ (id)rainbowGradient;
+ (id)hydrogenSpectrumGradient;

// We won't make any drastic modifications to the gradient once created

- (CTGradient *)gradientWithAlphaComponent:(float)alpha;
- (CTGradient *)addColorStop:(NSColor *)color atPosition:(float)position;
- (CTGradient *)removeColorStopAtIndex:(unsigned)index;
- (CTGradient *)removeColorStopAtPosition:(float)position;
- (CTGradientBlendingMode)blendingMode;
- (NSColor *)colorStopAtIndex:(unsigned)index;
- (NSColor *)colorAtPosition:(float)position;

// Now we don't need to conform to the NSCopying and NSCoding protocols

- (id)copyWithZone:(NSZone *)zone;
- (void)encodeWithCoder:(NSCoder *)coder;
- (id)initWithCoder:(NSCoder *)coder;

// We only need to fill a simple NSRect

- (void)drawSwatchInRect:(NSRect)rect;
- (void)radialFillRect:(NSRect)rect;
- (void)fillBezierPath:(NSBezierPath *)path angle:(float)angle;
- (void)radialFillBezierPath:(NSBezierPath *)path;

// Remove the entire (Private) category;
// but leave -addElement:

- (void)_commonInit;
// move setBlendingMode code into init
- (void)setBlendingMode:(CTGradientBlendingMode)mode;
- (CTGradientElement *)elementAtIndex:(unsigned)index;
- (CTGradientElement)removeElementAtIndex:(unsigned)index;
- (CTGradientElement)removeElementAtPosition:(float)position;
</code></pre>

<p>The following C functions are now unused:</p>

<pre><code>static void chromaticEvaluation(void *info, const float *in, float *out);
static void inverseChromaticEvaluation(void *info, const float *in, float *out);
static void transformRGB_HSV(float *components);
static void transformHSV_RGB(float *components);
static void resolveHSV(float *color1, float *color2);
</code></pre>

<p>And also remove the following from the header:</p>

<pre><code>typedef enum  _CTBlendingMode
    {
    CTLinearBlendingMode,
    CTChromaticBlendingMode,
    CTInverseChromaticBlendingMode
    } CTGradientBlendingMode;
</code></pre>

<p>Remove the <code>&lt;protocols&gt;</code> and unnecessary instance variables so the interface looks like this:</p>

<pre><code>@interface CTGradient : NSObject {
    CTGradientElement* elementList;
    CGFunctionRef gradientFunction;
}
+ (id)gradientWithBeginningColor:(NSColor *)begin endingColor:(NSColor *)end;
- (void)fillRect:(NSRect)rect angle:(float)angle;
- (void)addElement:(CTGradientElement *)newElement;
@end
</code></pre>

<p>Before we go further, we&#8217;ll need to take a detour and fix the remaining code so that it compiles. That&#8217;s easy enough - just remove any references to code we&#8217;ve removed.</p>

<p>If you&#8217;ve been following along, your CTGradient should now look like <a href="http://pub.lipidity.com/CTGradient/CTGradient2.m">this</a> (also made it readable!).</p>

<p>In a few short minutes, we&#8217;re down from more than <strong>1300</strong> to a little over <strong>200 lines</strong>.</p>

<p><big>It gets better.</big></p>

<h2>Optimize it</h2>

<p>First stop, <code>fillRect:angle:</code>. Since the gradient for Trimmit&#8217;s window only runs vertically (angle 90), we can straight away take out the <var>angle</var> argument, and also cut the entire if / else structure with the angle down to the two lines that are under the <code>if(angle == 90)</code>. Ah, much better.</p>

<p>Now things start getting a teeny bit more complex - and fun.</p>

<hr />

<p>The CTGradient code is written so that one can have many different color stops. The CTGradientElement struct has a nextElement which points to the next CTGradientElement and the position of the current element is stored under the float <var>position</var>. However, we need just two - the starting and ending shades.</p>

<p>Let&#8217;s take a look at cutting the multiple elements down to just two.</p>

<p>The <code>addElement:</code> method has a lot of looping to insert the element at the correct place. However, since we know that we only ever need two, we can cut it down to this:</p>

<pre><code>- (void)addElement:(CTGradientElement *)newElement {
    if(elementList) {
        // elementList exists, add second element
        elementList-&gt;nextElement = malloc(sizeof(CTGradientElement));
        *(elementList-&gt;nextElement) = *newElement;
        elementList-&gt;nextElement-&gt;nextElement = 0;
    } else {
        // no elements - add first element
        elementList = malloc(sizeof(CTGradientElement));
        *elementList = *newElement;
        elementList-&gt;nextElement = 0;
    }
}
</code></pre>

<p>Similarly with <code>dealloc</code>,</p>

<pre><code>- (void)dealloc {
    CGFunctionRelease(gradientFunction);
    free(elementList-&gt;nextElement);
    free(elementList);
    [super dealloc];
}
</code></pre>

<p>While we&#8217;re at it, let&#8217;s clean up <code>init</code> as well:</p>

<pre><code>- (id)init {
    if(self = [super init]) {
        CGFunctionCallbacks evaluationCallbackInfo = {0 , &amp;linearEvaluation, 0};
        static const float input_value_range[2] = { 0, 1 };
        static const float output_value_ranges[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
        gradientFunction = CGFunctionCreate(&amp;elementList, 1, input_value_range, 4, output_value_ranges, &amp;evaluationCallbackInfo);
    }
    return self;
}
</code></pre>

<p>Now we head to the <code>linearEvaluation</code> function. <var>info</var> passed in refers to <var>elementList</var> (see the CGFunctionCreate call). Again, since we know that we&#8217;ll only ever have two elements we can reduce it to:</p>

<pre><code>void linearEvaluation (void *info, const float *in, float *out) {
    float position = *in;

    CTGradientElement *color1 = *(CTGradientElement **)info;
    CTGradientElement *color2 = color1-&gt;nextElement;

    out[0] = (color2-&gt;red - color1-&gt;red)*position + color1-&gt;red; 
    out[1] = (color2-&gt;green - color1-&gt;green)*position + color1-&gt;green;
    out[2] = (color2-&gt;blue - color1-&gt;blue)*position + color1-&gt;blue;
    out[3] = (color2-&gt;alpha - color1-&gt;alpha)*position + color1-&gt;alpha;
}
</code></pre>

<p>And now we can finally remove the lines from <code>+gradientWithBeginningColor:endingColor:</code> where the positions are set, and also remove the <var>position</var> float from the CTGradientElement struct.</p>

<hr />

<p>We&#8217;re now down to a little over <strong>100 lines</strong>. Your CTGradientElement.m should now be looking something like <a href="http://pub.lipidity.com/CTGradient/CTGradient3.m">this</a>. Going well, but let&#8217;s take things up a notch.</p>

<hr />

<p>For Trimmit&#8217;s background, we&#8217;re not interested in the red, green, blue and alpha components - we just need a grayscale shading. This is the most fun part.</p>

<p>Instead of <code>float red, green, blue, alpha;</code> in the CTGradientElement struct, we can have just <code>float shade;</code>.</p>

<p>Now, during <code>init</code> we have:</p>

<pre><code>CGFunctionCallbacks evaluationCallbackInfo = {0 , &amp;linearEvaluation, 0};
static const float input_value_range[2] = { 0, 1 };
static const float output_value_ranges[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
gradientFunction = CGFunctionCreate(&amp;elementList, 1, input_value_range, 4, output_value_ranges, &amp;evaluationCallbackInfo);
</code></pre>

<p>The third argument, <var>input_value_range</var> is the domain. This gets passed into linearEvalution through <var>*in</var>.This is the independent variable. When we&#8217;re drawing the gradient, linearEvaluation is called with <var>*in</var> (the domain) starting at the first value of <var>input_value_range</var> and ending up at the second. So, something like 0.000, 0.001, 0.002 &#8230; 0.998, 0.999, 1.000. The function&#8217;s job is to set the the color components for each given value of the domain.</p>

<p>The first optimization we can make here is to return only one channel instead of four. This changes it to:</p>

<pre><code>- (id)init {
    if (self = [super init]) {
        CGFunctionCallbacks evaluationCallbackInfo = {0, &amp;linearEvaluation, 0};
        static const float range[2] = {0, 1};
        static const float domain[2] = {0, 1};
        gradientFunction = CGFunctionCreate(&amp;elementList, 1, domain, 1, range, &amp;evaluationCallbackInfo);
    }
    return self;
}
</code></pre>

<p>This change impacts back on the linearEvaluation function - now it only needs to return one channel:</p>

<pre><code>void linearEvaluation (void *info, const float *in, float *out) {
    CTGradientElement *color1 = *(CTGradientElement **)info;
    out[0] = (color1-&gt;nextElement-&gt;shade - color1-&gt;shade)*(*in) + color1-&gt;shade;
}
</code></pre>

<p>And don&#8217;t forget <code>+gradientWithBeginningColor:endingColor:</code>. We improve performance here, as we only need the shade - not a color. We can rename it to something appropriate.</p>

<pre><code>+ (id)gradientWithBeginningShade:(float)begin endingShade:(float)end {
    id newInstance = [[[self class] alloc] init];
    CTGradientElement color1, color2;

    color1.shade = begin; color2.shade = end;

    [newInstance addElement:&amp;color1];
    [newInstance addElement:&amp;color2];
    return [newInstance autorelease];
}
</code></pre>

<p>Now we&#8217;re only returning one grayscale channel. But hold on, we&#8217;re still in the RGB colorspace! That&#8217;s easily fixed. In <code>fillRect:</code>, replace:</p>

<pre><code>#if MAC_OS_X_VERSION_MAX_ALLOWED &gt;= MAC_OS_X_VERSION_10_4
    CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
#else
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
#endif
</code></pre>

<p>with:</p>

<pre><code>CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
</code></pre>

<p class="note">CGColorSpaceCreateDeviceGray is device-dependent on Mac OS X 10.3 and below, but starting from Tiger, it&#8217;s now device-independent which is good in terms of appearance.</p>

<p>While we&#8217;re in <code>fillRect:</code>, we can also make a few more improvements:</p>

<pre><code>- (void)fillRect:(NSRect)rect {
    CGContextRef currentContext = [[NSGraphicsContext currentContext] graphicsPort];
    CGContextSaveGState(currentContext);
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
    CGContextClipToRect(currentContext, *(CGRect *)&amp;rect);
    CGShadingRef myCGShading = CGShadingCreateAxial(colorspace, CGPointMake(0, 0), CGPointMake(0, NSMaxY(rect)), gradientFunction, 0, 0);
    CGContextDrawShading(currentContext, myCGShading);

    CGShadingRelease(myCGShading);
    CGColorSpaceRelease(colorspace);
    CGContextRestoreGState(currentContext);
}
</code></pre>

<p>I moved the startPoint and endPoint CGPoints straight into the CGShadingCreateAxial call. Also, we only ever fill the whole view with the gradient, so just put in <code>0</code> instead of using NSMinX and NSMinY. We could replace the <code>CGPointMake(0, 0)</code> with <code>(CGPoint){0,0}</code>, but I&#8217;m not sure if that&#8217;d be noticeably faster.</p>

<hr />

<p>Our code is at a lean <strong>80 lines</strong>. Now for the biggest change yet.</p>

<hr />

<p>Heading back to dear old linearEvaluation. Look at this line:</p>

<pre><code>out[0] = (color1-&gt;nextElement-&gt;shade - color1-&gt;shade)*(*in) + color1-&gt;shade;
</code></pre>

<p>What&#8217;s happening here? Think about it like this:</p>

<p>Essentially, we&#8217;re just &quot;graphing&quot; a straight line:</p>

<pre><code>y = mx + c
</code></pre>

<p>where <var>x</var> is the position, <var>*in</var>, and <var>y</var> is the shade we return (<var>out[0]</var>), and <var>c</var> is the initial shade.</p>

<p>Since our <var>x</var> value only goes from 0 to 1 (see domain in CGFunctionCreate), at <code>x = 0</code>, we will have <code>y = c</code>. At <code>x = 1</code>, we&#8217;ll have <code>y = m + c</code>.</p>

<p><img src='http://lipidity.com/wordpress/wp-content/uploads/2007/11/gradient-graph.png' alt='Graph of Gradient Function' class='feature' /></p>

<p><strong>So</strong> we only need the start shade as our <var>*info</var> value, since we can have <var>m</var> as the difference between the final and initial shades. Let&#8217;s effect this in our code.</p>

<p>We can get rid of the CTGradientElement struct. Remove from the header:</p>

<pre><code>typedef struct _CTGradientElement {
    float shade;
    struct _CTGradientElement *nextElement;
} CTGradientElement;
</code></pre>

<p>Instead of the struct, we&#8217;ll use a single <var>shade</var> instance variable. We don&#8217;t need the <code>+gradientWithBeginningShade:endingShade:</code> anymore, nor do we need <code>-addElement:</code>. So our interface now looks like this:</p>

<pre><code>@interface CTGradient : NSObject {
    float shade;
    CGFunctionRef gradientFunction;
}
- (void)fillRect:(NSRect)rect;
@end
</code></pre>

<p>From the implementation, we can remove the <code>free</code> calls in <code>dealloc</code> as well as the whole of <code>+gradientWithBeginningShade:endingShade:</code> and <code>addElement:</code>. We can set the <code>shade</code> in the init method (and replace <code>&amp;elementList</code> with <code>&amp;shade</code>), and change the linearEvaluation function to:</p>

<pre><code>void linearEvaluation (void *info, const float *in, float *out) {
    out[0] = *(float*)info + (*in)*0.1;
}
</code></pre>

<p>The <code>0.1</code> is what determines how much brighter the top of the gradient is (it&#8217;s the <var>m</var> value of our straight line) compared to the bottom.</p>

<p><strong>But</strong> since the <code>(*in)*0.1</code> will go from <code>0</code> to <code>0.1</code> (as <var>*in</var> goes from 0 to 1), we can actually change the <code>domain</code> we declare for CGFunctionCreate to {0, 0.1} and have our function as:</p>

<pre><code>void linearEvaluation (void *info, const float *in, float *out) {
    out[0] = *(float*)info + *in;
}
</code></pre>

<p>You can now add accessors for <code>shade</code> if you need to change the shade of the gradient or you could even have an <code>initWithShade:</code> method. In fact, here&#8217;s an Xcode project with the gradient.</p>

<p class="download"><a href="http://pub.lipidity.com/CTGradient/GradientSample.tar.bz2">Lean Gradient Xcode Project</a></p>

<p>We now have our gradient code down <big>from <strong>1300 lines</strong> to just over <strong>30 lines</strong></big>.</p>

<hr />

<p>We&#8217;ve almost reached a similar level of optimization to Trimmit&#8217;s gradient. There will be further optimizations you can make, but it depends on what you&#8217;re using the gradient for. For example, if the gradient you&#8217;re drawing is always the same, you can optimize further by removing the <code>shade</code> instance variable and all references to it, and hardcode the value into the linearEvaluation function.</p>

<p>Getting to the end of this article, you&#8217;re probably thinking that it would be a bit of a waste to use CTGradient if by the time you optimize it for your application, it doesn&#8217;t resemble the original at all. And you&#8217;re quite right. The documentation already shows you <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_shadings/chapter_9_section_6.html">how to draw gradients</a>, yet the number of applications using CTGradient - the whole 1300 lines of it - is astonishing.</p>

<p>Please: When you use other people&#8217;s code, don&#8217;t put it in without a thought. Go through it, understand it, and optimize it for your specific need. For the better performance and reduced RAM usage, computers will thank you.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/ctgradient-code-bloat/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Programming Challenge #3</title>
		<link>http://lipidity.com/development/programming-challenge-3/</link>
		<comments>http://lipidity.com/development/programming-challenge-3/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 05:40:59 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Programming]]></category>

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

		<guid isPermaLink="false">http://dev.lipidity.com/general/programming-challenge-3</guid>
		<description><![CDATA[Another little puzzle to keep you thinking. I saw this problem during the reign of the dinosaurs, and thought it was pretty clever.



El problemo

Write some code that prints 543210012345.

You code must meet the following conditions:


You must use single a loop (eg. for or while) and each iteration of your loop may only print one character [...]]]></description>
			<content:encoded><![CDATA[<p>Another little puzzle to keep you thinking. I saw this problem during the reign of the dinosaurs, and thought it was pretty clever.</p>

<!--more-->

<h3>El problemo</h3>

<p>Write some code that prints <code>543210012345</code>.</p>

<p>You code must meet the following conditions:</p>

<ul>
<li>You must use <ins>single</ins> a loop (eg. <code>for</code> or <code>while</code>) and each iteration of your loop may only print one <del datetime="2007-07-13T07:05:59+00:00">character</del> <ins>digit</ins>.</li>
<li>No <code>if</code> statements, no ternary operators.</li>
<li>No strings, no arrays. Numbers only.</li>
<li>You may only use at most one variable.</li>
<li>You may use language-specific functions / methods (but it&#8217;s not necessary).</li>
</ul>

<hr />

<p>As always, use any programming language you like and post up your answers in the comments. Once there have been several attempts, I&#8217;ll post up my suggested answers. It&#8217;ll be interesting to see the different ways people do this, and the various optimization techniques that are utilized.</p>

<p>Good luck!</p>

<p><strong>Note:</strong> When leaving a comment, indent your code blocks by four space or one tab so the formatting is saved and you don&#8217;t have to escape characters. For inline code, wrap it in backticks, eg. <code>`This is some code`</code></p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/development/programming-challenge-3/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Programming challenge #2</title>
		<link>http://lipidity.com/development/programming-challenge-2/</link>
		<comments>http://lipidity.com/development/programming-challenge-2/#comments</comments>
		<pubDate>Tue, 08 May 2007 10:53:19 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Programming]]></category>

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

		<guid isPermaLink="false">http://dev.lipidity.com/dev/programming-challenge-2</guid>
		<description><![CDATA[Another little mini-question to keep you thinking. The <a href="http://dev.lipidity.com/dev/programming-challenge-1">first one</a> was definitely too easy, so we'll slowly increase the degree of difficulty as we go along.

No more trigonometric functions this time; we're going to Cartesian coordinates. This is a re-adapted version of a sample problem from Google Code Jam. Here it is.]]></description>
			<content:encoded><![CDATA[<h2>Part A</h2>

<p>The new iFone<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> mobile needs to be able to find and connect to the nearest phone tower. Each phone is fed a list of Cartesian coordinates of the towers within range, and a coordinate of the phone&#8217;s current position.</p>

<p>The coordinates and IDs of the phone towers are passed to the phone as soon as they are within range.</p>

<p>Write a function that takes parameters of the ID, x and y coordinates of a phone tower and if it&#8217;s closer than the current connected tower, calls the <code>connectToTower()</code> function passing the ID of the tower.</p>

<p>The phone&#8217;s coordinates are two global variables, <code>phoneX</code> and <code>phoneY</code>, while the currently connected tower has coordinates stored in <code>cTowerX</code> and <code>cTowerY</code>.</p>

<p>A little pseudo-code to help you along the way:</p>

<pre><code>function checkTower(towerID, towerX, towerY){
    // phoneX, phoneY, cTowerX and cTowerY are available...
    find distance to currently connected tower
    find distance to passed tower
    if( passed tower is closer than currently connected tower ){
        connectToTower( towerID );
    }
}
</code></pre>

<!--
ANS:
function checkTower(towerID, towerX, towerY){
distToCurrent = ( (phoneX-cTowerX)^2 + (phoneY-cTowerY)^2 )^0.5;
distToThis = ( (phoneX-towerX)^2 + (phoneY-towerY)^2 )^0.5;
if( distToThis < distToCurrent ){
connectToTower(towerID);
}
}
-->

<p>This should be fairly straightforward. As usual, post up the answers in the comments using any programming language you like. Good luck!</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>Don&#8217;t sue me Apple!&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/development/programming-challenge-2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Programming challenge #1</title>
		<link>http://lipidity.com/development/programming-challenge-1/</link>
		<comments>http://lipidity.com/development/programming-challenge-1/#comments</comments>
		<pubDate>Thu, 26 Apr 2007 09:32:52 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Programming]]></category>

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

		<guid isPermaLink="false">http://dev.lipidity.com/dev/programming-challenge-1</guid>
		<description><![CDATA[Programming is more than simply remembering a few functions and properties and calling them. It's about thinking, processing, ordering, planning and implementing. Programming, real programming, requires a keen understanding of what you want to do, what you're doing, and what needs to be done. Sound complicated? It's not. Here's the first of a few questions that you as a programmer should be able to do in your sleep. You can leave answers in the comments. The programming language you use doesn't matter.]]></description>
			<content:encoded><![CDATA[<h2>Part A</h2>

<p>Write a function that returns the height of a bouncing ball above ground in metres after specified time (in seconds) if the ball is taking five seconds to complete each bounce (up and back down) and reaches a maximum height of 3 metres at the peak of each bounce. The initial position of the ball (after 0 seconds) is at ground level (0 metres).</p>

<p>Your function should take as a parameter the time elapsed in seconds (<code>t</code>) and return a numerical value of the height of the ball after that many seconds. Any approximations should be to at least four decimal places.
<!--
ANS:
`function height(t){ return ((3*sin(2*3.1416*t/10))^2)^(0.5); }`
--></p>

<p>Bonus points earned if your function uses only one line of code.</p>

<p>Hint: Think periodic / cyclic function and half your work is done.
Duoble Hint: You could use Grapher.app to check your answer&#8230;</p>

<h2>Part B</h2>

<p>Expand your function from Part A so that every time the ball hits the ground, the <code>boink()</code> function is called. (Assume <code>boink()</code> is already defined)</p>

<hr />

<p>Easy? I&#8217;m sure many people wouldn&#8217;t bother reading past the first sentence, but it just shows how important it is as a programmer to be familiar with math and physics, and to be able to apply your skills. Those application tasks that you hated at school were good for you.</p>

<p>While a lot of this could be done through using or examining readily available source code or libraries, it&#8217;s beneficial to be familiar with the basic concepts. Quoting <a href="http://howstuffworks.com">howstuffworks</a>, &#8220;it&#8217;s good to know&#8221;.</p>

<p><strong><a href="http://dev.lipidity.com/dev/programming-challenge-2">Continue to challenge #2</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/development/programming-challenge-1/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Forget text files - here&#8217;s a .php only database system</title>
		<link>http://lipidity.com/development/forget-text-files-heres-a-php-only-database-system/</link>
		<comments>http://lipidity.com/development/forget-text-files-heres-a-php-only-database-system/#comments</comments>
		<pubDate>Tue, 03 Apr 2007 03:35:55 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Programming]]></category>

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

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

		<guid isPermaLink="false">http://dev.lipidity.com/feature/tutorial/forget-text-files-heres-a-php-only-database-system</guid>
		<description><![CDATA[What do you do when you're writing a web app that needs to store data, but using a dedicated relational database system would be overkill? Many developers are taking advantage of PHP's file editing capabilities to use plain text files to store and retrieve data. While this is a more lightweight solution, reading the contents of a file is not always the fastest way to retrieve stored information. Here's my very own technique to use a database-like system with PHP files only, with just one line of code needed to grab the information, ready to be used.

This technique is best suited to situations when speed is required in accessing the data. It works best with small amounts of data, and it's possible to store arrays, strings, numbers, etc. Let's explore the basic theory behind the system.]]></description>
			<content:encoded><![CDATA[<h2>Basic premises</h2>

<ul>
    <li>PHP includes a function called parse_str() that takes a string and parses it as if it were the query section of the URI.</li>
    <li>The fopen / fwrite functions can be used on almost any ASCII files - even PHP files.</li>
    <li>Including a PHP file with a simple include() is much faster than using fopen to connect to and read the contents of a text file.</li>
</ul>

<h2>(Very basic) pseudo-code</h2>

<p>Here&#8217;s essentially what our code needs to do in (partial) pseudo-code. Database.php is the file that&#8217;ll store our data, but we&#8217;ll come to that later. If you don&#8217;t understand this section, just skip it; it&#8217;s only meant to be a brief explanation of how the code needs to be structured.
<code>index.php</code></p>

<pre><code>if ( $_REQUEST['data-type'] is set) {
        include 'database.php'
        get_settings_from_database.php()
        echo relevant_settings
        exit;
}</code></pre>

<p><code>admin.php</code></p>

<pre><code>
        start_session()
        if( user not logged in || logging out ){
                show_login_form()
        } else {
                show_administration()
        }</code></pre>

<h2>The real deal</h2>

<p><code>index.php</code></p>

<p>In index.php, we only need code to echo the relevant settings. In this example, I&#8217;ve outputted the results as javascript to be included in script tags.</p>

<pre><code>
&lt;?php

if( isset($_REQUEST['app']) ){
    include_once 'database.php';
    parse_str($theData, $sets);

    $appInfo = $sets[$_REQUEST['app']];

header("content-type: application/x-javascript");
echo "latest = new Array('";
echo implode ( '', '', $appInfo );
echo "');";
}
exit;
?&gt;</code></pre>

<p><code>admin.php</code>
The admin.php file takes care of the database editing. Note that this example only has one table. You could easily add more if you needed to.</p>

<pre><code>
&lt;?php
session_start();
?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html;charset=utf-8" /&gt;

&lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;
&lt;link rel="shortcut icon" href="favicon.ico" type="image/x-icon"&gt;
&lt;link rel="stylesheet" type="text/css" href="style.css" /&gt;

&lt;/head&gt;
&lt;body&gt;
&lt;?php

// your 'oh so secure' password...
@define('MY_PASSWORD','');

// fields you're going to have in your 'table'.
$fields = array('Build No','Version','Download','Info URL');

// the following could be written better, but there's really no need for this basic example.

if( isset($_SESSION['loggedIn']) &amp;&amp; $_SESSION['loggedIn']== 'LOGGEDIN' ){
    if( isset($_POST['logout']) ){
        $_SESSION['loggedIn'] = 0;
        logInForm();
    } else {
        backEnd();
    }
} else {
    if( isset($_POST['login']) &amp;&amp; $_POST['pwd'] == (MY_PASSWORD) ){
        $_SESSION['loggedIn'] = 'LOGGEDIN';
        backEnd();
    } else {
        logInForm();
    }
}

function logInForm(){
        echo "
&lt;form action='' method='post'&gt;
&lt;input type='password' name='pwd' /&gt;
&lt;input type='submit' name='login' value='Log in' /&gt;
&lt;/form&gt;
";
}

function backEnd(){
    if( isset($_POST['edited']) ){
        set_options();
    }
    backEnd_form();
}

function backEnd_form(){
    $output='';
    $output .= "
&lt;form action='' method='post'&gt;
&lt;input type='submit' name='logout' value='Log out' /&gt;
&lt;/form&gt;
";
    $settings = $GLOBALS['fields'];

    include_once 'database.php';
    parse_str($theData, $sets);

//  print_r ($sets);
    $output .= "&lt;form action='' method='post'&gt;&lt;table&gt;&lt;tbody&gt;";

    foreach( $sets as $key =&gt; $value ){
        if( is_array($value) ){
            $output .= "&lt;tr&gt;
&lt;th&gt;{$key}&lt;/th&gt;
&lt;th&gt;&lt;input type='checkbox' name='del_{$key}' id='{$key}' /&gt;
&lt;label for='{$key}'&gt;delete&lt;/label&gt;&lt;/th&gt;
&lt;/tr&gt;n";
            foreach( $value as $keyd =&gt; $data ){
                $output .= "&lt;tr&gt;
&lt;td&gt;{$settings[$keyd]}&lt;/td&gt;
&lt;td&gt;&lt;input type='text' name='a[{$key}][]' value='{$data}' /&gt;&lt;/td&gt;
&lt;/tr&gt;n";
            }
        }
    }

    $output .= "&lt;tr&gt;
&lt;th colspan='2'&gt;Add new:&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add new:&lt;/td&gt;
&lt;td&gt;&lt;input type='text' name='add' value='' /&gt;&lt;/td&gt;&lt;/tr&gt;n";
    $output .= "&lt;tr&gt;&lt;td colspan='2'&gt;
&lt;input type='submit' value='Edit Updates' name='edited' /&gt;&lt;/td&gt;
&lt;/tr&gt;";
    $output .= "&lt;/tbody&gt;&lt;/table&gt;&lt;/form&gt;";

    echo $output;
}

function set_options(){
    $result = '&lt;?php
    $theData="';
    $num_fields = count($GLOBALS['fields']);

    if( $_POST['a'] ){
        foreach ( $_POST['a'] as $keys =&gt; $keydata ){
            if( !$_POST['del_'.$keys] ){
                foreach ( $keydata as $value ){
                    $result .= $keys."[]=".urlencode($value)."&amp;";
                }
            }
        }
    }
    if( isset($_POST['add']) &amp;&amp; ''!=$_POST['add'] ){
        for ( $k=0; $k&lt;$num_fields; $k++ ) {
            $result .= $_POST['add']."[]=&amp;";
        }
    }
    $result .= '";
    ?&gt;';
    $myFile = "database.php";
    $fh = fopen($myFile, 'w') or die("error");
    fwrite($fh, $result);
    fclose($fh);
}
?&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>

<p><code>database.php</code></p>

<pre><code>
&lt;?php

?&gt;</code></pre>

<h2>Adding info</h2>

<p>Navigate to admin.php, and login with your password. Type in a name in the &#8220;add new&#8221; section and submit the form. You&#8217;ll be presented with an editable list of keys / values that you can configure.</p>

<p><a href="http://dev.lipidity.com/wp-content/uploads/2007/04/phpdb.png" title="PHP DB screenshot" rel="lightbox"><img src="http://dev.lipidity.com/wp-content/uploads/2007/04/phpdb.thumbnail.png" alt="PHP DB screenshot" /></a></p>

<p>This procedure is really not recommended for commercial products, but for simple personal applications, this is the perfect way to store data. I use a slightly modified version of this method for the update-checking functionality of my <a href="http://dev.lipidity.com/feature/wp-plugin-gregarious">Gregarious</a> plugin for WordPress.</p>

<h2>Variations on a theme</h2>

<p>Instead of using a php file for a database, you could also use a .ini file. PHP has a built-in function called <code>parse_ini_file</code> which gets the contents of the ini file as an array.</p>

<p>The lesson to be learnt here is that if you&#8217;re after something that&#8217;s not already available - innovate. Plan it, think it, write it.</p>

<p>Now, I know the code above could be written a lot better. I also know that I made claims of this technique being superfast without performing any quantitative tests. So, let me know how this could be improved or any other tips and tricks you know to get the most out of your code.</p>

<h2>Ermm&#8230;</h2>

<p>Just to clarify, the idea presented here is extremely useful - I use it all the time for small scale personal projects. However, please don&#8217;t copy and paste the code straight into your public web app as (at the very least) it needs filtering for php injection. Joachim <a href="#comment-3874">points out</a> that serialize / unserialize is a safer and more robust option for use in this circumstance, and I have used that in the past.</p>

<p>So if it&#8217;s years since you last used SQL or a database is just overkill, now you have an alternative!</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/development/forget-text-files-heres-a-php-only-database-system/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CSS Style guide generator</title>
		<link>http://lipidity.com/web/css-style-guide-generator/</link>
		<comments>http://lipidity.com/web/css-style-guide-generator/#comments</comments>
		<pubDate>Thu, 15 Mar 2007 08:37:18 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Design]]></category>

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

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

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

		<guid isPermaLink="false">http://dev.lipidity.com/dev/css-style-guide-generator</guid>
		<description><![CDATA[For a web designer, remembering the properties of all the CSS classes, IDs and elements that have been written, often over multiple stylesheets, can be a real task. Often developers need to keep referring back to their CSS to check the definitions, look at the properties and classes and find the right element. This is time wasted. Time that could be spent on more constructive endeavours.]]></description>
			<content:encoded><![CDATA[<p><a href="http://dev.lipidity.com/wp-content/uploads/2007/03/cssedit.png" style="border: 1px solid #cccccc; margin: 5px; padding: 5px; float: left" title="CSSEdit shot" rel="lightbox"><img src="http://dev.lipidity.com/wp-content/uploads/2007/03/cssedit.thumbnail.png" alt="CSSEdit shot" /></a>MacRabbit&#8217;s CSSEdit eases the burden slightly by displaying a graphical representation of each CSS definition in the sidebar. This however, is still missing information on positioning, padding, margins, borders background images, background properties, font styles and various other vital pieces of data. Of course, it would be unreasonable to stipulate that kind of display in the application as it&#8217;s meant to be a CSS editor. Click on a definition on the left to bring up the full CSS.</p>

<p>But the web designer is not doomed to be eternally editing CSS. The HTML needs to be written as much as the styles, and it&#8217;s really very obtrusive and awkward to have to search through your CSS to see what a particular class or ID looks like. Which where style guides come into play.</p>

<p>A style guide is critical for any designer undertaking a project of a decent size. Not only does it help you remember your classes if you&#8217;re working on multiple projects or if it&#8217;s been a while, it&#8217;s also a great way to  get instantaneous updates, and easy cross-browser rendering to see what your styles look like in different browsers. A style guide will also benefit any other person working on the same website who may not be familiar with the styles you have created.</p>

<p>The benefits of having a style guide are numerous, and fairly obvious (Refer to <a href="http://72.14.253.104/search?q=cache:http://www.willjessup.com/?p=25">this article</a>), but often the time and effort taken to write up a style guide can be a deterrent. Not any more.</p>

<h1 style="text-align: center"><a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="color: #8000ff; margin-right: 3px">style</span><span style="color: #0080ff">say</span></a></h1>

<p><a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="color: #8000ff; margin-right: 2px">style</span><span style="color: #0080ff">say</span></a> is, to my knowledge, the first ever style guide generator, and it couldn&#8217;t be easier to use. It&#8217;s been written with a single, clear goal in mind - to provide designers with a resource from which CSS style guides can be created quickly, and with minimal effort.</p>

<p>Currently, <a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="margin-right: 2px">style</span><span>say</span></a> is still being developed, but the feature-set is now near enough to completion that it does its job. There is no syntax to learn; <a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="margin-right: 2px">style</span><span>say</span></a> recognizes CSS elements, classes and IDs, so you can copy and paste portions straight from your stylesheet. For the moment, the default text includes some basic documentation in the comments, but that will eventually be moved when the project goes final.</p>

<p>Would you find <a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="color: #8000ff; margin-right: 2px">style</span><span style="color: #0080ff">say</span></a> to be useful? Or are there any features that you would like to request?</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/web/css-style-guide-generator/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Function - call thyself</title>
		<link>http://lipidity.com/development/function-call-thyself/</link>
		<comments>http://lipidity.com/development/function-call-thyself/#comments</comments>
		<pubDate>Wed, 07 Mar 2007 12:16:36 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Programming]]></category>

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

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

		<guid isPermaLink="false">http://dev.lipidity.com/feature/tutorial/function-call-thyself</guid>
		<description><![CDATA[A function that calls itself. What sorts of pictures does that conjure in your mind? Errors, warnings or infinite loops? Crashes? Bugs? Believe it or not, using a function that calls itself can be used for more than hanging up IE. It can cut down on the amount of code you have to write, often by hundreds of lines.]]></description>
			<content:encoded><![CDATA[<p>I see that grimace. You don&#8217;t believe me do you? That&#8217;s all right, I didn&#8217;t believe myself at first either. The sort of thing you probably associate with this sort of thing would be something along the lines of:</p>

<pre class="code">
function writeNumber(number){
    print( number );
    print( " and " );
    writeNumber(number + 1);
}
writeNumber(1);</pre>

<p>If your first language is a programming languauge rather than, say, English, you would realise immediately that the preceding code will, in theory, execute for eternity - kind of like counting to infinite. The output would be <samp>1 and 2 and 3 and 4 &#8230;</samp> and it would keep increasing forever: <samp>75374524 and 75374525 and 75374526 and 75374527 and &#8230;</samp>. It&#8217;s not as bad as:</p>

<pre class="code">
for( i = 0; i &gt;= 0; i++ ){
    print( i );
}</pre>

<p>but in both cases the script would either time out or have to be terminated. Another common mistake while we&#8217;re on the topic of inifinite loops is the forever while.</p>

<pre class="code">
i = 1;
while ( i &lt; 10 ){
    echo i;
}</pre>

<p>Again, the output is not pretty. (As I said, it may be hard for beginners to spot the mistake in this one. The problem here is that <var>i</var> is always less than ten as we&#8217;re not changing it, so the loop continues forever as <var>i</var> is always 1. Adding a simple <code>i++;</code> line before closing the loop will solve the problem.)</p>

<p>There are a lot of ugly connotations related with topics such as this, especially if you&#8217;ve encountered (or written) some of the above code. So if you panicked when I said a function that called itself could be useful, I completely understand your apprehension.</p>

<p>But have no fear; I am not completely crazy (yet) and taking over the world through blatant misinformation is still a long way down on my todo list. So, cast aside your doubt for the time being, and allow me to demonstrate to you how this sort of recursive programming that I&#8217;m talking about can make a serious impact in your code.</p>

<p>The most beautiful way of using this technique (yes, inspiring code is beautiful) is to run through files and folders, arrays or collections of any sort that contain children collections (such as XML markup).</p>

<p>Here&#8217;s an example in PHP:</p>

<pre class="code">
function loop($array, $parent=''){

    foreach( $array as $option =&gt; $value ){
        if( $parent != '' ){
            $option = $parent . '[' . $option . ']';
        }
        if( is_array($value) ){
            loop($value, $option);
        } else {
            ?&gt;
        &lt;div&gt;&lt;?php echo $option; ?&gt; = &lt;?php echo $value; ?&gt;&lt;/div&gt;
            &lt;?php
        }
    }

}

loop ( $names );</pre>

<p>Ingenius, isn&#8217;t it?</p>

<p>If the above code is not clear to you, let&#8217;s take a look at some example usage. I&#8217;ll be working in PHP, but the language doesn&#8217;t really matter; the principle is the important thing.</p>

<p>Let&#8217;s say I have an array, with usernames in it, like so:</p>

<pre class="code">
var $names = array ();

$names[0] = "Bobster";
$names[1] = "Billy";
$names[2] = "Matty";
$names[3] = "Joey";
$names[4] = "Jacko";</pre>

<p>To output these values just requires an easy peasy:</p>

<pre class="code">
foreach ( $names as $name ){
    echo $name;
}</pre>

<p>So why in the world did you just write that <code>loop()</code> function, I hear you exclaim. In this case, it&#8217;s summarised in one word: extensibility.</p>

<p>We&#8217;ve decided that the usernames aren&#8217;t enough. We need to store the the first and last names in the array as well.</p>

<pre class="code">
var $names = array ();

$names[0] = array (
    'username' =&gt; "Bobster",
    'firstname' =&gt; 'Bob',
    'lastname' =&gt; 'Johnson');
$names[1] = array (
    'username' =&gt; "Billy",
    'firstname' =&gt; 'William',
    'lastname' =&gt; 'Gates');
$names[2] = array (
    'username' =&gt; "Matty",
    'firstname' =&gt; 'Matthew',
    'lastname' =&gt; 'Jefferson');
$names[3] = array (
    'username' =&gt; "Joey",
    'firstname' =&gt; 'Joseph',
    'lastname' =&gt; 'Carlton');
$names[4] = array (
    'username' =&gt; "Jacko",
    'firstname' =&gt; 'Jack',
    'lastname' =&gt; 'Richardson');</pre>

<p>Our array is now <em>multi-dimensional</em>. So, to get Bob&#8217;s username, we&#8217;d call <code>$names[0]['username'];</code>. Now, outputting all the values isn&#8217;t so easy:</p>

<pre class="code">
foreach ( $names as $userarray ){
    foreach ( $userarray as $field =&gt; $key ){
        echo $field . ' = ' . $key . '';
    }
}</pre>

<p>Do you see where I&#8217;m heading? What happens when instead of having firstname and lastname keys, we make is another array containing the first and last names like <code>$names[0]['name']['first']</code>? The array is now three-dimensional and we start to run into some problems in outputting our values:</p>

<pre class="code">
foreach ( $names as $userarray ){
    foreach ( $userarray as $field =&gt; $key ){
        if( is_array($field) ){
            foreach ($field as $sub_key =&gt; $value ){
                echo $key . ' ' . $sub_key . ' = ' . $value;
            }
        } else {
            echo $field . ' = ' . $key . '';
        }
    }
}</pre>

<p>Boy! Did that double in size or what! Becoming clearer now? If we decide to make another field that has another array in it, so we get four dimensions, the code will again need to be changed. But, what if we have an array where we <em>don&#8217;t know how many dimensions it has</em>? This is exactly the situation developers are faced with when trying to traverse files and folders. We don&#8217;t know how many levels of nested folders exists inside a particular loction. Trying to write a single function that traverses a filesystem is like trying to write a single function to crawl the internet. And guess what? I already showed you how its done.</p>

<p>Rather than nesting an arbitary number of foreach statements, we finally get back to our <code>loop</code> function.</p>

<pre class="code">
function loop($array, $parent=''){

    foreach( $array as $option =&gt; $value ){
        if( $parent != '' ){
            $option = $parent . '[' . $option . ']';
        }
        if( is_array($value) ){
            loop($value, $option);
        } else {
            ?&gt;
    &lt;div&gt;&lt;?php echo $option; ?&gt; = &lt;?php echo $value; ?&gt;&lt;/div&gt;
            &lt;?php
        }
    }

}

loop ( $names );</pre>

<p>In the <code>loop</code> function, we go through the array, and if the array contains another array, we run <code>loop</code> on it. The beauty of this function is that we pass the key as well as the child array, so we don&#8217;t lose the level that we&#8217;re on. An entry located at <code>$names[0]['admins'][2]['superadmins']['users'] = 'Bob'</code> would be correctly displayed by the <code>loop</code> function as <code>names[0][admins][2][superadmins][users] = Bob</code> The quotes aren&#8217;t printed by this example, but you easily add them in.</p>

<p>Similarly, archiving files could use a function that looks at the contents of the current folder, archives any files, then runs itself on any subfolders.</p>

<p>Find this code inspiring? Or do you know of any other techniques that save time and effort?</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/development/function-call-thyself/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Consolidate your programming skills</title>
		<link>http://lipidity.com/apple/consolidate-your-programming-skills/</link>
		<comments>http://lipidity.com/apple/consolidate-your-programming-skills/#comments</comments>
		<pubDate>Thu, 07 Dec 2006 07:59:42 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

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

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

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

		<guid isPermaLink="false">http://dev.lipidity.com/feature/tutorial/consolidate-your-programming-skills</guid>
		<description><![CDATA[Beginning Logical Programming

What is logical programming? Programming in the most efficient manner, and providing the best user experience to the user where everything &#8220;just works&#8221;.


Logic: reasoning conducted or assessed according to strict principles of validity or the systematic use of symbolic and mathematical techniques to determine the forms of valid deductive argument.

What distinguishes a good [...]]]></description>
			<content:encoded><![CDATA[<h2>Beginning Logical Programming</h2>

<p><cite>What is logical programming? Programming in the most efficient manner, and providing the best user experience to the user where everything &#8220;just works&#8221;.</cite>
<!--more--></p>

<p class="note"><strong>Logic:</strong> <em>reasoning conducted or assessed according to strict principles of validity</em> or <em>the systematic use of symbolic and mathematical techniques to determine the forms of valid deductive argument.</em></p>

<p>What distinguishes a good programmer from a great one? Plenty of comments? Clean and readable code? Geekiness? These are all fine, but (as you can probably tell from the title) one of the most important things a programmer must know is logic, an integral part of math.</p>

<p>You can call it logic or lateral thinking or even insanity, but the fact remains, that to be able to write code - good code - you must be able to use conditionals, loops and increments; all of which make up a part of mathematics. Since logic is a portion of mathematics, I&#8217;ll be referring to logic, thinking, and calculating under the umbrella term of just &#8216;math&#8217;.</p>

<p>Without math, programming wouldn&#8217;t exist. Every time you write an <code>if else statement</code>, a <code>for</code> loop, or a <code>while</code> loop; that&#8217;s math. Every time you manipulate variables, or process data; that&#8217;s math. Most programmers don&#8217;t realize the importance of mathematics, and will probably dislike the very subject that earns them a living, however we use it without realizing all the time.</p>

<h3>Conditionals</h3>

<p>So we know that we use math a lot, and that it&#8217;s important, but how? Well, let me show you. For my <a href="http://dev.lipidity.com/apple/core-graphics-meet-core-image-demo-app">Core Graphics demonstration app</a> I had a window that would animate using a cube transition once a tab view item was changed. Simple enough, but I wanted the window to behave like a real cube. A cube has six faces, so the window had to show the distinct top, base and four other sides. I wanted the first face to move up, then across until four faces had been shown, then finally up once more to show the base of the cube. Let&#8217;s have a look at the code:</p>

<pre><code>int option; // for direction

if(toTab &gt; fromTab){ // moving forward
    if(toTab == lastTab || fromTab == 0){ //to last tab or from first tab
        option = CGSUp;
    } else {
        option = CGSLeft;
    }
} else if(toTab &lt; fromTab){ // moving backwards
    if(toTab == 0 || fromTab == lastTab){ // to first tab or from last tab
        option = CGSDown;
    } else {
        option = CGSRight;
    }
}
[self _turnWithTransition:transitionStyle option:option duration:TRANSITION_DURATION];
</code></pre>

<h3>Structure</h3>

<p>&lt;</p>

<p>p>Notice how I&#8217;ve grouped the logic into two sections; one part deals with moving forward through the tab view items and the other is for moving back. If we really wanted to, we could fit most of the above code in one line:</p>

<p>&lt;</p>

<p>p></p>

<pre style='overflow:auto'><code>option = (toTab > fromTab) ? (toTab == lastTab || fromTab == 0) ? CGSUp : CGSLeft : (toTab == 0 || fromTab == lastTab) ? CGSDown : CGSRight;</code></pre>

<p>It&#8217;s exactly the same but uses less less code. Why don&#8217;t we use this instead of the longer method? You take a look at both and tell me which one is easier to understand ;). More thinking if someone tries to figure out what&#8217;s going on equals more hassle. I wont expand further on the code, but do look at how I&#8217;ve written it. Can you think why this technique might be better than using a <code>select case</code> routine or by running through <code>if (toTab==1)... else if(toTab==2)...</code> etc?</p>

<h3>Error Prevention</h3>

<p>The above example is also a demonstration of basic error checking. Okay, not really error checking, but more error preventing. Rather than write code for six tab view items, I&#8217;ve added integers to hold values for the indices (plural of index) of destination, origin, first and last tabs. So now if I only have two tab view items, and I run the code, it doesn&#8217;t throw a nasty error. In fact, if you open up the demo app and change the number of tab view items, it wont ever be thrown out of whack.</p>

<h2>Archiver</h2>

<p>Part of error checking (yes, we do real error checking this time) is the order in which you assert your data. One of the places I worked at required an application to scan through the network and archive files which were older than a specified date. It was (surprise, surprise) for Windows to be written in Visual Studio. In short, the user was to be given the option to punch in the number of days that a file&#8217;s creation date had to be be over for it to be archived, as well as the directories in which to scan and location to archive any files. (Of course, there were a lot more features than this, such as generating tables of file types, files sizes, keeping logs, etc.) Oh, and when I say &#8220;archive&#8221;, I mean &#8220;move the file to the archive location, replacing it with a text file of the same name explaining that the file is gone.&#8221;</p>

<p>Since I am now an Apple convert, let&#8217;s translate this into the Mac equivalent. Here is mockup of this (not a real app):</p>

<p style='text-align: center'>
<img id="image87" src="http://dev.lipidity.com/wp-content/uploads/2006/12/archiver_screenshot.png" alt="Archiver II Screenshot" /></p>

<p>In the Apple context, let&#8217;s say the user chooses Macintosh HD and tells the application to to archive files more than a day old. Houston, we have a problem. Files more than a day old would probably include the majority of the files, including system files, any documents, folders, or applications. Essentially you would be wiping out your hard drive, replacing everything you have with a nice little text file explaining that the file has been archived on this date to this location. So, we need to show an error; possibly in a sheet (or a modal dialog which, using Apple lingo, I belileve could be deemed a &#8220;panel&#8221;). The way you show the error is not that important. What you show is of more value. Let&#8217;s take a look.</p>

<p>The errors or problems with the settings on the Archiver could include:</p>

<ol>
<li>That the user has chosen the entire Macintosh HD to <del>delete</del> archive.</li>
<li>Files more than one day old is going to include almost everything that exists.</li>
<li>The user has unchecked the &#8220;simulation only&#8221; option, which means the program will actually delete everything more than a day old, rather than just report how much space could be saved.</li>
</ol>

<p>So, what do we tell the user? &#8220;Are you sure you wish to run Archiver on Macintosh HD?&#8221;, &#8220;Are you sure you don&#8217;t want to run a simulation?&#8221;, or &#8220;You&#8217;ve opted to remove everything more than 1 day old. Are you sure you want to do this?&#8221;. Or perhaps we should present them with a list with everything that&#8217;s wrong or dangerous. As with most scenarios such as this, there is no right or wrong answer. However, there are some options which work better than others.</p>

<p>We really don&#8217;t want to simply say &#8220;Are you sure you wish to run Archiver on Macintosh HD?&#8221;. Imagine you&#8217;re an average user who doesn&#8217;t know the ins and outs of the Mac, and doesn&#8217;t realize there is actually a whole heap of stuff buried in /Library/ that keeps your computer operational, and doesn&#8217;t think that his photos, music and work will be deleted. Would you have a problem with that dialog? Why should you worry, right? A dialog such as this could also be taken as the &#8220;annoying confirmation of everything&#8221; that Windows gets a lot of and Apple is starting to see more of. Either way, it&#8217;s bad news for the user when he realises that all his &#8220;stuff&#8221; is now no longer on his computer. Okay, it&#8217;s archived, but do you really think that restoring everything would be a matter of dragging everything back in? Even if system files are protected, the hard drive will still need to be cleaned out (Archiver leaves a text file in place of everything, remember? That&#8217;s a lot of text files if you run it on your whole HD). Nope, simply asking &#8220;are you sure you want to do this&#8221; doesn&#8217;t cut it in most circumstances.</p>

<p>Hang on a second. What if the user just wants to see how many old files he&#8217;s got on his computer. Should we be asking &#8220;Are you sure you don&#8217;t want to run a simulation?&#8221; Again, various issues persist. This statement is very ambiguous. Of course, you could run a simulation to see how much space you could save by removing old files, but if you want to actually archive them, you don&#8217;t want to run a simulation. You just want the program to do it&#8217;s job. So if we ask &#8220;do you just want to run a simulation?&#8221;, it&#8217;s not likely that the user will realize why we&#8217;re asking them that question. This will probably result in running the archiver process and losing data from your drive.</p>

<h3>Ressurection of the Apple Human Interface Guidelines</h3>

<p class="note" style='font-size:100%; background-color:#fff; border: 0;'>The Apple Human Interface Guidelines (HIG for short) have come under a lot of attack recently with many people declaring it&#8217;s time is up. I don&#8217;t want to take sides, but many of the concepts in the HIG are vital to present a clear and easy to learn experience for users. Other ideas present in the document, of course, are debatable.</p>

<p>So what should we say? Well, Apple clearly spell out how to show alert sheets in the <acronym title="Human Interface Guidelines">HIG</acronym>, which defines how an application should interact with a user. It&#8217;s mostly common sense, but is one of the many reasons Mac software is easy to use. In Chapter 17 Section 6, <a href="http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_6.html#//apple_ref/doc/uid/20000961-DontLinkElementID_1771">alert dialogs</a> are defined by Apple as &#8220;dialogs that appear when the system or an application needs to communicate information to the user. Alerts provide messages about error conditions or warn users about potentially hazardous situations or actions.&#8221; Exactly what we want.</p>

<p style='text-align: center'><img src="http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/art/wn_alert.gif" alt=" [Alert sheet as defined by the Apple Human Interface Guidelines] " /></p>

<p>Note the message text asks the user if they&#8217;re certain they want to proceed, but then we have the <strong>informative text</strong> which tells them exactly <em>why</em> continuing with the present course of action could be a bad idea. Obviously there needs to be a way for the user to cancel if they realize that&#8217;s not what they want (the cancel button) and a way for them to continue on if they&#8217;re sure they know what they&#8217;re doing (the action button).</p>

<p>In our instance, we certainly don&#8217;t even want to provide the option of archiving everything more than a day old from the entire HD, so we can add simply check <code>if(archiveFrom == MacHD &#038;&#038; daysOld &lt;= 30)</code> and if true, cancel the command while telling the user something along the lines of &#8220;You cannot choose to archive files more than a day old on your system hard drive.&#8221; and informing them that &#8220;Macintosh HD contains files necessary for your computer to function which should not be archived.&#8221; We want to only cancel if both conditions are true - if they&#8217;re archiving files from the entire HD that are less than a specified number of days (it should really be more than 30, but that&#8217;s just an example). So the code only cancels if both conditions are true since it could still be a command legitimate to archive everything a day old from a folder where you want to get rid of your previous work (of course, it might be an idea to have an alert anyway but allowing the user to continue on if they understand the risk).</p>

<p>In the case that the &#8220;archive from&#8221; location is not the entire HD or any important folder such as &#8220;System&#8221; or &#8220;Library&#8221;, and the number of days is less than say 30, we still need to confirm this as files more than 30 days old could be a lot. We could do <code>if(daysOld &lt;= 30) [self doAlert];</code> to achieve this. However, the key in all this is to <em>check everything in order</em>. If you get the order right, it reduces the amount of code that needs to be written drastically.</p>

<h2>Order it out</h2>

<pre><code>
-(BOOL)archive
{
if(archiveFrom == MacHD || archiveFrom == Library || archiveFrom == System)
     return [self doError:
          @"You can't archive from a folder that your computer
           needs in order to operate correctly."];

if(daysOld &lt;= 30)
     return [self doAlert:
          @"Archiving files older than your specified date could result in a large
           volume of archived files."];

if(![chkSimulation selected])
     return [self doAlert:
          @"There is no turning back. Are you sure your settings are correct?"];

[self runArchive];
}
</code></pre>

<p>See how we avoid the use of multiple <code>else if</code>&#8217;s and <code>case this:, case that:</code> by checking each field in order. If the user is archiving from System or Library, we throw an error. It would be annoying to get them to fix an error in the number of days and then tell them they had the first step wrong the whole time. It&#8217;s important to fix things in the logical order that the user sees and use your conditionals such that each one has an effect on the proceeding code. In our case, if the first step is wrong, we throw an error, and exit the method. This is important. The second and third segments of code <em>never get called if the first conditional returns true</em>. Can you image the user clicking out of a dialog, only to be faced with another? We don&#8217;t want to emulate Windows ;). Likewise, progress is halted at the second and third conditionals if they return true.</p>

<h3>Really, now</h3>

<p>This example is really the most basic that I could have given. Essentially, the motto of this article is &#8220;write good code well&#8221;, which means you must not only write well-commented and easy to follow code, but you must write it <em>well</em>. You need to use conditionals in smart ways, to follow your program&#8217;s flow and always ask yourself: &#8220;How can I improve this?&#8221;</p>

<p>Remember: Programming is not something learnt through a degree or accreditation; there are always things to learn or concepts to apply.</p>

<p>Best wishes,</p>

<p>Ankur</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/consolidate-your-programming-skills/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CGS Framework now Universal! Tremendous power&#8230;</title>
		<link>http://lipidity.com/apple/cgs-framework-now-universal-tremendous-power/</link>
		<comments>http://lipidity.com/apple/cgs-framework-now-universal-tremendous-power/#comments</comments>
		<pubDate>Mon, 30 Oct 2006 12:18:45 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

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

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

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

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

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

		<guid isPermaLink="false">http://dev.lipidity.com/apple/cgs-framework-now-universal-tremendous-power</guid>
		<description><![CDATA[The fabled Core Graphics Framework is now released!

All the PPC / Intel specific bugs have been found, caught, and eradicated. The framework should now be ready for developer consumption for use in commercial apps, or for experimentation and utter bewilderment. Be amazed. Be very amazed, and download the framework straight from here or read and [...]]]></description>
			<content:encoded><![CDATA[<p class="callout">The fabled <a href="http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource" title="The Core Graphics Framework for everything Core Graphics.">Core Graphics Framework</a> is now released!</p>

<p>All the PPC / Intel specific bugs have been found, caught, and eradicated. The framework should now be ready for developer consumption for use in commercial apps, or for experimentation and utter bewilderment. <strong>Be amazed</strong>. Be very amazed, and download the framework straight from <a href="http://pub.lipidity.com/CGSFramework.tar.bz2" title="Download the Core Graphics framework straight away (direct link)">here</a> or read and download it from <a href="http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource" title="The Core Graphics Framework for everything Core Graphics.">the original post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/cgs-framework-now-universal-tremendous-power/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The ultimate Core Graphics resource</title>
		<link>http://lipidity.com/apple/the-ultimate-core-graphics-resource/</link>
		<comments>http://lipidity.com/apple/the-ultimate-core-graphics-resource/#comments</comments>
		<pubDate>Fri, 27 Oct 2006 13:39:37 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

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

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

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

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

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

		<guid isPermaLink="false">http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource</guid>
		<description><![CDATA[Liberate your application

Now works on all architectures, and without hiccups!

Can&#8217;t get enough of window transitions? Love a little eye candy? Well, you&#8217;re in luck. The Core Graphics Framework and Xcode Project Template make adding the fantastic Core Graphics function to your app a breeze. In fact, it&#8217;s even more complete than the tutorial, and already [...]]]></description>
			<content:encoded><![CDATA[<h2>Liberate your application</h2>

<p class="blue_hilite">Now works on all architectures, and without hiccups!</p>

<p>Can&#8217;t get enough of window transitions? Love a little eye candy? Well, you&#8217;re in luck. The Core Graphics Framework and Xcode Project Template make adding the fantastic Core Graphics function to your app a breeze. In fact, it&#8217;s even more complete than the <a href="http://dev.lipidity.com/tutorial/xcode-transitions-core-graphics-image-2" title="The complete Core Graphics tutorial for beginners">tutorial</a>, and already has more features in it before you write a single line of code! It doesn&#8217;t stop there, however. This framework powerful enough to use the <strong>genie effect</strong>. That&#8217;s right. That awesome Mac OS X transform you can get when you minimize an application. Core Graphics contains a wealth of resources. You really have to check it out.</p>

<!--more-->

<h3>Point. Click. Zoom!</h3>

<p>The <acronym title="Core Graphics">CGS</acronym> Framework is a an implementation of transitions, transforms and everything Core Graphics. It includes the definitions and implementations for the methods, so that using a transition or transform is as simple as calling a single method! For example, scaling a window is as simple as a &#8220;- scale: about:&#8221; call on the window, and rotating it just requires a single &#8220;- rotate: about:&#8221;. In the same way, Core Graphics is laid bare with this framework, for you to utilize at your pleasure!</p>

<h3>Don&#39;t lift a finger</h3>

<p>The framework does all the work for you, but even then, it gets simpler. Source for a  sample app is included which means that you can create Core Graphics projects straight away by building on top of it. This saves you, the developer time in adding and linking the Framework, and reading and implementing the Core Graphics class in Interface Builder, as well as adding the framework to your project. A single double-click on the sample project and it&#8217;s all done for you. What more could you ask? Download a copy and check it out today. You&#8217;ll be surprised how powerful it is.</p>

<h3>Gimme already!</h3>

<p><strong>Now a universal binary for your developing pleasure!</strong></p>

<p class="download"><a id="p23" href="http://pub.lipidity.com/CoreGFX.tar.bz2" title="CGS Framework / Project">CGS Framework + Sample App</a></p>

<p>Once downloaded, open CoreGFX.app to view some of the possible effects. You can copy the source folder to hard drive if you need to build a Core Graphics enabled app. Enjoy the wonderfulness, and I hope you have fun!</p>

<hr />

<p>Any queries, <a title="Jump straight to the comment form to leave a reply." href="http://dev.lipidity.com/apple/the-ultimate-core-graphics-resource#comment-form">fire away.</a> </p>

<p>Make sure you understand that some of the functions of Core Graphics used in this framework are undocumented, internal APIs that Apple haven&#8217;t released. (Calm down. It&#8217;s not illegal). Having said that, apps like <a href="http://quicksilver.blacktree.com/" title="Quicksilver is an essential application for Mac OS X. It is a lot more than an application launcher; it gives you control over your entire Mac and will definitely increase your productivity. The eye candy is great too, courtesy of Core Graphics.">Quicksilver</a> would be quite bland without the use of the undocumented Core Graphics functions, so exercise your discretion.</p>

<p>This project relies heavily on work by <a href="http://homepage.cs.latrobe.edu.au/wjtregaskis/" title="Wade's stuff. Little bland, but contains a gem in the form of Rotated Windows.">Wade Tregaskis</a> and his Rotating Windows.</p>

<p>&copy; 2006 Ankur Kothari.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/the-ultimate-core-graphics-resource/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
