﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>jurkow commented on The tax calculation challenge</title><description>        private static readonly double[] TaxTable = new double[] { 0, 0.1, 0.14, 0.23, 0.3, 0.33, 0.45 };
        private static readonly double[] T = new double[] { 0, 5070, 8660, 14070, 21240, 40230 };
        public static double Tax(double value, int t = 0, double tax = 0)
        {
            return (++t &lt; T.Count() &amp;&amp; value &gt; T[t] - T[t - 1]) ? Tax(value - T[t] + T[t - 1], t, tax + (T[t] - T[t - 1]) * TaxTable[t]) : tax + value * TaxTable[t];
        }</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment80</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment80</guid><pubDate>Tue, 18 Oct 2011 20:54:59 GMT</pubDate></item><item><title>JJoos commented on The tax calculation challenge</title><description>I over engineered a C# solution: http://pastebin.com/VDQ6VFhY . It's based on Geert Baeyaert solution.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment79</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment79</guid><pubDate>Fri, 07 Oct 2011 11:39:06 GMT</pubDate></item><item><title>Bruno commented on The tax calculation challenge</title><description>@Robert
Thanks for read my implementation. Please, give me a more detailed feedback. It's important to my learning.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment78</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment78</guid><pubDate>Thu, 29 Sep 2011 12:26:14 GMT</pubDate></item><item><title>Keith Baker commented on The tax calculation challenge</title><description>My solution - https://gist.github.com/1248932</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment77</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment77</guid><pubDate>Wed, 28 Sep 2011 19:36:27 GMT</pubDate></item><item><title>Andrew commented on The tax calculation challenge</title><description>From C# Program in LINQPad

http://pastebin.com/gmwKbwws


</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment76</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment76</guid><pubDate>Wed, 28 Sep 2011 17:16:39 GMT</pubDate></item><item><title>Yan Cui commented on The tax calculation challenge</title><description>F#: https://gist.github.com/1247782</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment75</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment75</guid><pubDate>Wed, 28 Sep 2011 12:11:53 GMT</pubDate></item><item><title>ZyZ commented on The tax calculation challenge</title><description>        public static decimal CalculateTax(decimal amount)
        {
            var rates = new Dictionary&lt;decimal, int&gt; { { 40230, 45 }, { 21240, 33 }, { 14070, 30 }, { 8660, 23 }, { 5070, 14 }, { 0, 10 } };
            return rates.Where(rate =&gt; rate.Key &lt;= amount).Sum(rate =&gt;
            {
                var tmp = amount;
                amount = rate.Key;
                return (tmp - rate.Key) * rate.Value * 0.01m;
            });
        }</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment74</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment74</guid><pubDate>Tue, 27 Sep 2011 20:45:34 GMT</pubDate></item><item><title>David Cuccia commented on The tax calculation challenge</title><description>To be the gadfly: there is no question. Just saying.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment73</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment73</guid><pubDate>Tue, 27 Sep 2011 19:39:03 GMT</pubDate></item><item><title>Nicola Baldi commented on The tax calculation challenge</title><description>And now, my super-over-engineered (and quite useless) solution!

http://nbaldi.codeplex.com/SourceControl/list/changesets</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment72</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment72</guid><pubDate>Tue, 27 Sep 2011 12:42:42 GMT</pubDate></item><item><title>Ken Tong commented on The tax calculation challenge</title><description>Let me join the party. My approach is to allow more trivial tax rate setting. But the implementation is a bit tricky.

http://pastebin.com/YkUB8RvG</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment71</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment71</guid><pubDate>Tue, 27 Sep 2011 09:33:53 GMT</pubDate></item><item><title>Adam Langley commented on The tax calculation challenge</title><description>1. I'd avoid using a class to encapsulate such simple data unless I was returning/consuming that class... (I might use an anonymous class though, purely for readability).
2. Linq-be-gone... I personally feel it reduces the readability of something so simple...
3. Sure, some iterations are unnecessary given your tax bracket, and they could be skipped using conditions, but whats the point? A couple of extra CPU cycles and the code is much simpler. Of course, this isnt written with the intention of calculating a million samples per second....

readability&lt;---&gt;performance. Just my 2c.

http://pastebin.com/Ezi5BL7u</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment70</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment70</guid><pubDate>Mon, 26 Sep 2011 21:42:41 GMT</pubDate></item><item><title>Joe commented on The tax calculation challenge</title><description>
public class TaxCalc
{
	public static decimal Calculate(int salary)
	{
		var brackets = new List&lt;TaxBracket&gt;{
			new TaxBracket(0, 5070, 10),
			new TaxBracket(5000, 6000, 10),
			new TaxBracket(5071, 8660, 14),
			new TaxBracket(8661, 14070, 23),
			new TaxBracket(14071, 21240, 30),
			new TaxBracket(21241, 40230, 33),
			new TaxBracket(40231, Decimal.MaxValue, 45)
		};
		
		return brackets.Sum (b =&gt; b.GetTax(salary));
		
	}
}


public class TaxBracket
{
	public decimal MinValue {get;set;}
	public decimal MaxValue {get;set;}
	public decimal Rate {get;set;}
	
	public TaxBracket(decimal min, decimal max, decimal rate)
	{
		MinValue = min;
		MaxValue = max;
		Rate = rate;
	}
	
	public decimal GetTax(int salary) 
	{
		var nums = Enumerable.Range(1, salary);
		var taxableDollars = nums.Where(n =&gt; n &gt;= MinValue &amp;&amp;  n &lt;= MaxValue);
		return taxableDollars.Count() * (Rate /  100);
	}
}</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment69</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment69</guid><pubDate>Mon, 26 Sep 2011 17:51:27 GMT</pubDate></item><item><title>Robert commented on The tax calculation challenge</title><description>@Bruno, you're fired.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment68</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment68</guid><pubDate>Mon, 26 Sep 2011 12:06:24 GMT</pubDate></item><item><title>Simon Cousins commented on The tax calculation challenge</title><description>@Colin,

You're hired.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment67</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment67</guid><pubDate>Mon, 26 Sep 2011 11:23:48 GMT</pubDate></item><item><title>Colin Bull commented on The tax calculation challenge</title><description>@Simon, 

This function can actually be generalised to deal with any ranges of objects without any code changes the only thing required is that the objects passed in as `rates` support comparison (IComparable) and the addition operator. It is only the naming that makes this function specific to taxes. 

Of couse this could be done in C# aswell through generics but the ceremony is far higher. </description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment66</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment66</guid><pubDate>Mon, 26 Sep 2011 11:18:43 GMT</pubDate></item><item><title>Simon Cousins commented on The tax calculation challenge</title><description>Most things turn out to be a fold:

&lt;pre&gt;&lt;code&gt;
let taxes salary =
    let rates = [40230.0m,0.45m;21240.0m,0.33m;14070.0m,0.3m;8660.0m,0.23m;5070.0m,0.14m;0.0m,0.1m]
    let taxAtRate (tax,remainder) (threshold,rate) =
        let taxable = remainder - threshold
        if taxable &gt; 0.0m 
        then tax + rate * taxable, remainder - taxable 
        else tax,remainder
    List.fold taxAtRate (0.0m, salary) rates |&gt; fst
&lt;/code&gt;&lt;/pre&gt; </description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment65</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment65</guid><pubDate>Mon, 26 Sep 2011 11:01:54 GMT</pubDate></item><item><title>Timothy Walters commented on The tax calculation challenge</title><description>While most of the answers are quite "clever" and show an understanding of some nice coding methods, I would pick Daniel Lidström's answer if I was hiring.

It's short, to the point, simple, easy to follow, and shows a greater understanding of the customer's needs than the programmer's needs.

Tax for the portion below each bracket can be pre-calculated, it's static, you simply have to tax the remainder.

Of course it would probably load the rates from a database with pre-calculated values (that should be calculated on data entry instead of on use), but there was no requirement for that in the "test" above. This could be easily refactored later to allow for this.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment64</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment64</guid><pubDate>Mon, 26 Sep 2011 03:35:17 GMT</pubDate></item><item><title>Mark commented on The tax calculation challenge</title><description>In Australia, progressive tax is usually specified by the tax office as:

(Between {min} and {max}, {base amount} plus {% on each $ above min}.)+

Which has the nice side effect of the primary source material easily translating into a ordered list which makes a LINQ query a readable SkipWhile, First.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment63</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment63</guid><pubDate>Mon, 26 Sep 2011 02:45:44 GMT</pubDate></item><item><title>Alex commented on The tax calculation challenge</title><description>I compulsively order from small to large, hence the Reverse :D
Not the most efficient but nice and small. 
https://gist.github.com/1241154</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment62</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment62</guid><pubDate>Sun, 25 Sep 2011 21:12:56 GMT</pubDate></item><item><title>Alexander I. Zaytsev commented on The tax calculation challenge</title><description>So got I the job?</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment61</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment61</guid><pubDate>Sun, 25 Sep 2011 16:39:48 GMT</pubDate></item><item><title>Steve Py commented on The tax calculation challenge</title><description>Regarding the benchmarking: The idea was not to try and come up with the fastest solution, it was to measure the potential performance impact of what people thought were good solutions. The goal of the test should be that 
#1. (Obviously) the code compiles and runs.
#2. The code passes a set of test scenarios.
#3. The code is reasonably well structured and easy to follow.

Depending on the whims of the project lead they are bound to look for other things such as it being easy to extend or swap out interest rates, validates itself robustly, is unit tested effectively, is efficient, etc. The idea of a benchmark isn't always to make things faster, it can be to measure the potential trade off in performance to try making something better.

If anyone wants to play around with the benchmark and add their own sample that I missed, it is available for download at:
http://www.mediafire.com/?d91x97jvzx14jd6

</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment60</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment60</guid><pubDate>Sun, 25 Sep 2011 00:54:15 GMT</pubDate></item><item><title>Daniel Lidström commented on The tax calculation challenge</title><description>Here's the simplest solution I could come up with:

    private double TaxFor(double amount)
    {
        if (amount &gt; 40230)
            return 0.45 * (amount - 40230) + 10671.6 /*TaxFor(40230)*/;
        else if (amount &gt; 21240)
            return 0.33 * (amount - 21240) + 4404.9 /*TaxFor(21240)*/;
        else if (amount &gt; 14070)
            return 0.30 * (amount - 14070) + 2253.9 /*TaxFor(14070)*/;
        else if (amount &gt; 8660)
            return 0.23 * (amount - 8660) + 1009.6 /*TaxFor(8660)*/;
        else if (amount &gt; 5070)
            return 0.14 * (amount - 5070) + 507 /*TaxFor(5070)*/;
        else
            return 0.10 * amount;
    }
</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment59</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment59</guid><pubDate>Sat, 24 Sep 2011 18:28:54 GMT</pubDate></item><item><title>Bruno commented on The tax calculation challenge</title><description>Java solution. It's slightly different from others. I used a factory to create calculators and some parameter validations (like a precondition). I think that practices are important, even in naive implementations.
https://gist.github.com/1239534</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment58</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment58</guid><pubDate>Sat, 24 Sep 2011 16:53:28 GMT</pubDate></item><item><title>Roberto commented on The tax calculation challenge</title><description>Just another C# solution:
https://gist.github.com/9cbe9ab68f75f52eebfb</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment57</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment57</guid><pubDate>Sat, 24 Sep 2011 11:06:17 GMT</pubDate></item><item><title>Demis Bellot commented on The tax calculation challenge</title><description>Hi @Steve Py

Out of curiosity what numbers do you get if you plug CalcTaxFast from: 
https://gist.github.com/1238962 in?
</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment56</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment56</guid><pubDate>Sat, 24 Sep 2011 09:46:30 GMT</pubDate></item><item><title>Steve Py commented on The tax calculation challenge</title><description>Correction: Oddly enough Damien's test failed when working with decimals and passing the decimal rate (I.e. .23) while removing the / 100.

Damien x Failed. :  $5800, expected $609.2, actual $609.34| $9000, expected $1087.8, actual $1088.17| $15000, expected $2532.9, actual $2533.57| $50000, expected $15068.1, actual $15069.55

It seems the rounding may have been concealing a bit of a bug. (or I may have lost something in translation.) One thing that did look a bit odd was that there was overlap between ranges. (5070-8660, 8660-14070) This may be throwing off the calculation.

For fun when I was looking over Peter's example (which is quite a bit of code to maintain) it got me thinking perhaps a double - linked list might work, but the best I could get out of it without it looking obfuscated was still slightly slower than my original. 

Additionally I made one pretty obvious mistake in the test sets: I had it generating a random range of values from $0-3M. This is going to result in a very disproportionate # of values falling into the upper tax bracket. I revised the generation to between $0-100k and the results changed a bit. Apparently Alexander's solution handles a lot of rich people better than mine. The extra load I had at start up though pays off in the larger # of requests.

I also incorporated Frank's sample from the previous post since that was one lean looking piece of code. It covered all of the test cases however the performance was surprisingly unimpressive:

Steve Py x 5000: 8.0004ms
Steve Py 2 x 5000: 9.0006ms
Alexander x 5000: 7.0004ms
Damien x 5000: 17.0009ms
Dmitry x 5000: 7.0004ms
Eric x 5000: 7.0004ms
Geert x 5000: 12.0007ms
Link Goron x 5000: 8.0005ms
Peter x 5000: 12.0007ms
Thomas x 5000: 9.0005ms
Frank x 5000: 8.0004ms
Frank x 5000: 7.0004ms
Steve Py x 100000: 95.0054ms
Steve Py 2 x 100000: 95.0054ms
Alexander x 100000: 101.0058ms
Damien x 100000: 237.0135ms
Dmitry x 100000: 114.0065ms
Eric x 100000: 127.0073ms
Geert x 100000: 204.0117ms
Link Goron x 100000: 129.0074ms
Peter x 100000: 163.0093ms
Thomas x 100000: 144.0083ms
Frank x 100000: 150.0085ms
Frank x 100000: 129.0074ms
Steve Py x 1000000: 921.0527ms
Steve Py 2 x 1000000: 935.0534ms
Alexander x 1000000: 1076.0616ms
Damien x 1000000: 2413.138ms
Dmitry x 1000000: 1145.0655ms
Eric x 1000000: 1278.0731ms
Geert x 1000000: 2079.1189ms
Link Goron x 1000000: 1298.0742ms
Peter x 1000000: 1637.0937ms
Thomas x 1000000: 1381.079ms
Frank x 1000000: 1464.0837ms

but the original was declaring the arrays in each call, a quick tweak turned:
Frank x 1000000: 1464.0837ms
to:
Frank x 1000000: 1261.0721ms

In any case, not a concern for such a slick little bit of code.
</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment55</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment55</guid><pubDate>Sat, 24 Sep 2011 05:29:57 GMT</pubDate></item><item><title>Demis Bellot commented on The tax calculation challenge</title><description>I think calculating benchmarks for something like this is a bit pointless as the fastest algorithm is also likely to be the hardest to maintain. So just for kicks I created a fast version of in C# - which funnily enough is similar in spirit to the interviewee's submission :)

Full Gist at: https://gist.github.com/1238962 

public static decimal CalcTaxFast(int salary)
{			
	const int band1 = 5070;
	const decimal rate1 = 0.10m;
	const int band2 = 8660;
	const decimal rate2 = 0.14m;
	const int band3 = 14070;
	const decimal rate3 = 0.23m;
	const int band4 = 21240;
	const decimal rate4 = 0.30m;
	const int band5 = 40230;
	const decimal rate5 = 0.33m;
	
	const decimal rate6 = 0.45m;
	
	const decimal bandTax1 = band1 * rate1;
	const decimal bandTax2 = (band2 - band1) * rate2 + bandTax1;
	const decimal bandTax3 = (band3 - band2) * rate3 + bandTax2;
	const decimal bandTax4 = (band4 - band3) * rate4 + bandTax3;
	const decimal bandTax5 = (band5 - band4) * rate5 + bandTax4;
	
	if (salary &amp;gt; band5) 
		return (salary - band5) * rate6 + bandTax5;
	if (salary &amp;gt; band4) 
		return (salary - band4) * rate5 + bandTax4;
	if (salary &amp;gt; band3) 
		return (salary - band3) * rate4 + bandTax3;
	if (salary &amp;gt; band2) 
		return (salary - band2) * rate3 + bandTax2;
	if (salary &amp;gt; band1) 
		return (salary - band1) * rate2 + bandTax1;
	
	return salary * rate1;
}

P.S: For ultimate perf, someone should rewrite this in ASM :)</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment54</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment54</guid><pubDate>Sat, 24 Sep 2011 04:27:38 GMT</pubDate></item><item><title>Steve Py commented on The tax calculation challenge</title><description>Readability is a personal preference thing, but I decided to take a bunch of the C# samples and benchmark their performance and test that they actually worked...
Here are the results:

Timed tests...

Steve Py x 5000: 9.0005ms
Alexander x 5000: 7.0004ms
Damien x 5000: 23.0013ms
Dmitry x 5000: 8.0004ms
Eric x 5000: 8.0005ms
Geert x 5000: 13.0007ms
Link Goron x 5000: 9.0005ms
Peter x 5000: 12.0007ms
Thomas x 5000: 9.0005ms
Steve Py x 100000: 103.0059ms
Alexander x 100000: 97.0056ms
Damien x 100000: 375.0215ms
Dmitry x 100000: 128.0073ms
Eric x 100000: 146.0083ms
Geert x 100000: 225.0129ms
Link Goron x 100000: 140.008ms
Peter x 100000: 173.0099ms
Thomas x 100000: 150.0085ms
Steve Py x 1000000: 1014.058ms
Alexander x 1000000: 972.0556ms
Damien x 1000000: 3782.2164ms
Dmitry x 1000000: 1321.0755ms
Eric x 1000000: 1459.0835ms
Geert x 1000000: 2281.1304ms
Link Goron x 1000000: 1411.0808ms
Peter x 1000000: 1714.098ms
Thomas x 1000000: 1504.086ms

Unit tests...

Steve Py...
Steve Py x Passed!
Alexander...
Alexander x Passed!
Damien...
Damien x Passed!
Dmitry...
Dmitry x Passed!
Eric...
Eric x Passed!
Geert...
Geert x Passed!
Goron...
Goron x Passed!
Peter...
Peter x Passed!
Thomas...
Thomas x Passed!


Sorry to anyone that had c# examples that I missed...

The unit tests section just ran through Ayende's examples plus $0. Since most of the samples used decimal, I converted the double/int versions to decimal for consistency of test sets. This was just measured with DateTime &amp; Timespan checks not a precision timer so it's not going to be terribly accurate. There were swings between test runs but the performance comparison was pretty-much the same. 

Notables: 
Alexander's was noticably better performing than the rest, and all passed the test scenarios. 

Damien's sample nearly ended up with an all-fail by a factor of 100 until I spotted he chose to pass tax rates as percentages.

Geert's sample didn't compile as provided. 2 minor adjustments needed. Additionally Geert's sample was improved a bit by extracting out the set of taxbrackets as a member variable instead of each time the method was called:
Geert x 1000000: 2281.1304ms
to
Geert x 1000000: 1944.1112ms

This brought him a bit closer in-line with the other samples.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment53</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment53</guid><pubDate>Sat, 24 Sep 2011 01:29:01 GMT</pubDate></item><item><title>Steve Sheldon commented on The tax calculation challenge</title><description>Another way to look at this problem.  If I have a salary of 50,000...  The answer is calculated as:

(50000 - 40230) * .45 + 10671.6 = 15068.1

So I wrote this is a series of rules, check for a match and calculate tax.  Could even convert this into a Boo DSL.

http://pastebin.com/yzxRqSx0

I've been working for a big payroll house the past two years.  We didn't calculate tax, as theire are third party libraries for that sort of thing, but I did enough excel spreadsheets for creating test data to know how tax is calculated.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment52</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment52</guid><pubDate>Sat, 24 Sep 2011 00:19:33 GMT</pubDate></item><item><title>Rich commented on The tax calculation challenge</title><description>@Jamie -- every single one eh?  Did you even look at them all?  The second one added (hazzik's) had tests.  So did Damien Powell's example.  Get off your high horse and look at them before making a blanket statement like that.</description><link>http://ayende.com/108545/the-tax-calculation-challenge#comment51</link><guid>http://ayende.com/108545/the-tax-calculation-challenge#comment51</guid><pubDate>Fri, 23 Sep 2011 23:28:23 GMT</pubDate></item></channel></rss>