# Build a marginal tax calculator

There have been some tax rate calculator problems here that depend on defined rates (specifically US federal rates), but none that have done it for arbitrary lists.

Your task is to build a program or function that will take an arbitrary list of marginal tax brackets and calculate the effective amount of tax paid on a given amount of taxable income.

Your program will take as input:

• N pairs of numbers in the form (amt, rate), each representing a tax bracket.

• amt is the amount of taxable income above which at which the tax rate starts to apply. These amounts will all be integers, and appear in increasing order.

• rate is the tax rate, expressed as a decimal percentage from 0 to 100 inclusive.

• The amount of taxable income, as a nonnegative integer.

If no rate is specified for $0, the rate is assumed to be 0%. Alternatively, your program can also take as input two lists (amt1, amt2, ...) and (rate1, rate2, ...), containing the amounts and rates in the same order. Your program will then output the payable tax, either to two decimal places, or rounded down to the nearest whole currency unit. An example input (the most recent Canadian tax brackets, from 2016, with the basic personal tax credit applied and nothing else): 11474 15 45282 20.5 90563 26 140388 29 200000 33 393216  And its corresponding output: 108357.07 or 108357  The shortest program in any language to do this wins. • Is input as [[amt,amt,amt],[rate,rate,rate]] OK? Or does it have to be pairs of [amt,rate] ? – Emigna Jun 27 '16 at 14:54 • Could input be 1 list of amounts, 1 list of rates and the tax income value (3 inputs in total)? – Emigna Jun 27 '16 at 15:02 • Well, I've specified (amt, rate), but it doesn't fundamentally change the problem to accept the other list, so I'll modify it so you can. – Joe Z. Jun 27 '16 at 15:38 ## 6 Answers ## 05AB1E, 35 24 bytes vy³ï‚{0è)˜}³ï‚˜¥²ø€PTn/O  Explanation vy # for each amount ³ï‚ # pair with taxable income {0è # get min )˜} # add to list ³ï‚˜ # add income to the end of the list ¥ # get deltas ²ø # zip with tax rates €P # map product on each pair of [amount in tax bracket,rate] Tn/ # divide by 100 O # sum # implicitly display result  Try it online • Do human beings actually read and understand 05AB1E code? – DavidC Jun 27 '16 at 14:47 • @DavidC: I've learned to understand most of it. I'll write up an explanation though. Would have done it already, but wasn't sure if both input methods were OK. – Emigna Jun 27 '16 at 14:52 # Haskell, 67 66 bytes Thanks Damien for -1 byte. This solution is in the form of an infix function, ?, of type (Integral b, RealFrac r) => [(r, r)] -> r -> b. The helper function, #, does the required calculations while ? serves to handle the IO specifications. a?b=floor$reverse a#b
((m,p):r)#i|v<-min i m=p/100*(i-v)+r#v
_#_=0

• ((m,p):r)#i|v<-min i m=p/100*(i-v)+r#v saves 1 byte – Damien Jun 27 '16 at 11:22
• Thanks @Damien! I didn't know you could assign values inside a guard like that. – ankh-morpork Jun 27 '16 at 13:48

# Mathematica 85 82 bytes

Derived from Josh O'Brien's code in R.

d_~f~i_:=Tr@Thread[Differences@((i~Min~#&/@d[[All,1]]~Append~∞))d[[All,2]]/100.]


## Usage

f[{{11474, 15}, {45282, 20.5}, {90563, 26}, {140388, 29}, {200000, 33}}, 393216]


108357.

• So this has been asked before, just not on this particular site. Makes sense. – Joe Z. Jun 26 '16 at 0:40

## Matlab, 79 bytes

Assuming we can take amt and rate as separate column vectors:

function[]=f(a,b,c)
t=sort([0;a;c]);fix(sum(diff(t).*[0;b/100].*(t(2:end)<=c)))


If we can't (then a is a two-column matrix of amt and rate) it's 87 bytes.

function[]=f(a,c)
t=sort([0;a(:,1);c]);fix(sum(diff(t).*[0;a(:,2)/100].*(t(2:end)<=c)))


Explanation:

f(a,b,c)           -- takes amt, rate and income
[0;a;c]            -- gives a vector of amounts with 0 and the income amount
t=sort(...)        -- sort this vector
diff(t)            -- gives us amounts to be taxed in every bracket
diff(t).*[0;b/100] -- tax in every bracket
.*(t(2:end)<=c)    -- take only entries lower than the income
sum(...)           -- sum everything
fix(...)           -- round towards 0


## JavaScript (ES6), 60 bytes

(a,n)=>a.map(([b,r])=>{t+=n>b&&(n-b)*(r-p);p=r},p=t=0)|t/100


a is an array of arrays of band and rate, which would be [[11474, 15], [45282, 20.5], [90563, 26], [140388, 29], [200000, 33]] for the given example, and n is the income (393216).

• Can you provide more information on the input format? – Joe Z. Jun 27 '16 at 4:23

# Swift, 61 bytes

zip(zip(m+[i],+m).map{$0-$1},+r).map{$0*$1}.reduce(0,+)


Ungolfed, with test cases:

struct TaxContext {
let marginLowerBound: [Double]
let rates: [Double]
}

// ungolfed
extension TaxContext {
func calcAfterTaxIncome(_ income: Double) -> Double {
//drop first element (0), append income
let upper = marginLowerBound + [income]
let lower =  + marginLowerBound

let incomeInEachMargin = zip(upper, lower)
.map{ upperBound, lowerBound in upperBound - lowerBound }

let taxInEachMargin = zip(incomeInEachMargin, +rates)
.map{ incomeInMargin, rate in incomeInMargin * rate }

let totalTax = taxInEachMargin.reduce(0, +)

print(upper)
print(lower)
print(incomeInEachMargin)
print(rates)
print(taxInEachMargin)

}
}

// golfed
extension TaxContext {
// computed properties to serve as aliases for the golfed version
var m: [Double] { return self.marginLowerBound }
var r: [Double] { return self.rates }

func f(_ i: Double) -> Double {
return zip(zip(m+[i],+m).map{$0-$1},+r).map{$0*$1}.reduce(0,+)
}
}

let testCase1 = TaxContext(
marginLowerBound: [10_000, 20_000, 30_000],
rates: [0.1, 0.2, 0.3, 0.4]
)
let result1 = testCase1.calcAfterTaxIncome(70_000)
print(result1)

let testCase2 = TaxContext(
marginLowerBound: [11474 , 45282, 90563, 140388, 200000],
rates: [0.15, 0.205, 0.26, 0.29, 0.33]
)
let result2 = testCase2.calcAfterTaxIncome(393216)
print(result2)