13
\$\begingroup\$

Background

Here in the UK1, these are the income tax rules:

  • You get a personal allowance (untaxed) of up to £12,570:
    • If you earn less than £100,000, you get the full £12,570 as personal allowance
    • For every £2 over £100,000, your personal allowance goes down by £1
  • After the personal allowance, the next £37,700 is taxed at the "basic rate" of 20%
  • After that, the next £99,730 is taxed at the "higher rate" of 40%
  • Finally, anything above this is taxed at the "additional rate" of 45%

1: This isn't actually the case in Scotland; only England, Wales and Northern Ireland.

Your task

Using the above tax rules, take in an annual salary (as a positive integer) and calculate the income tax.

Test cases

Input    Output
12570    0
50000    7486
80000    19432
120000   39432
200000   75588.5

Note: the final test case can be any of 75588, 75588.5, or 75589 (any is fine)

Clarifications

  • You can choose whether to make the personal allowance an integer or keep it as a float
    • e.g. if the input is £100,003, the personal allowance can be £12,569, £12,568.50, or £12,568
  • The same goes for the final output. If it ends up as a float, you can make it an integer or keep it as a float
    • (see the final test case)
  • This is , so shortest answer in bytes wins!
\$\endgroup\$
10
  • \$\begingroup\$ Sandbox \$\endgroup\$
    – The Thonnu
    Dec 25, 2022 at 9:49
  • \$\begingroup\$ Presumably your personal allowance can never be negative. \$\endgroup\$
    – Simd
    Dec 25, 2022 at 10:06
  • \$\begingroup\$ @Simd yes, after something like £125,140 you have £0 personal allowance. \$\endgroup\$
    – The Thonnu
    Dec 25, 2022 at 10:08
  • 2
    \$\begingroup\$ This is actually quite similar to how Australian taxation works, which makes sense given we're part of y'all anyway :p \$\endgroup\$
    – lyxal
    Dec 25, 2022 at 10:11
  • 1
    \$\begingroup\$ @matteo_c done. \$\endgroup\$
    – The Thonnu
    Dec 25, 2022 at 10:15

8 Answers 8

9
\$\begingroup\$

JavaScript (ES6), 99 bytes

Works with floats and rounds the final result.

n=>[137430.45,37700.4,.2].map(v=>x+=v%1*(n-(n-=m(n-~~v))),x=0,n-=(m=v=>v>0&&v)(12570-m(n-1e5)/2))|x

Try it online!

n =>                 // n = input
[                    // in this array, the integer part is the threshold (T)
                     // and the decimal part is the tax rate (R)
  137430.45,         //   T = 99730 + 37700, R = 45%
  37700.4,           //   T = 37700, R = 40%
  .2                 //   T = 0, R = 20%
]                    //
.map(v =>            // for each entry v:
  x +=               //   add to x:
    v % 1 *          //     the tax rate multiplied by
    ( n -            //     the difference between the current value of n
      ( n -=         //     and the updated value of n, which is:
          m(n - ~~v) //       n - max(0, n - threshold)
      )              //
    ),               //
  x = 0,             //   start with x = 0
  n -=               //   start by applying the personal allowance
    ( m = v =>       //   m is a helper function taking v ...
      v > 0 && v     //   ... and returning max(0, v)
    )                //
    (                //   personal allowance:
      12570 -        //     12570 - max(0, n - 100000) / 2
      m(n - 1e5) / 2 //
    )                //
)                    // end of map()
| x                  // return the final value of x
\$\endgroup\$
7
\$\begingroup\$

Python, 83 80 77 bytes

-3 thanks to @Max by removing the 0 from the beginning of the floating points.

-3 thanks to @tsh by using integers which are then divided instead of floats and changing the personal allowance operation.

lambda m:sum(([4]*37700+[8]*99730+[9]*m)[:m-max(0,min(62570-m//2,12570))])/20

Attempt This Online!

Fun use of Python indexing and list multiplication.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ I think you can remove the leading zero from 0.2 etc. \$\endgroup\$
    – Max
    Dec 26, 2022 at 15:39
  • 2
    \$\begingroup\$ lambda m:sum(([4]*37700+[8]*99730+[9]*m)[:m-max(0,min(62570-m//2,12570))])/20 \$\endgroup\$
    – tsh
    Dec 27, 2022 at 5:34
6
\$\begingroup\$

Charcoal, 49 bytes

IΣ×I⪪”‴⌈↷¶»^w⁷k²zV” E⁻NI⪪”←¶➙~!¬‴″ζCER⁵kςⅈ” ∧›ι⁰ι

Attempt This Online! Link is to verbose version of code. Explanation:

           N            Input as a number
          ⁻             Vectorised subtract
              ...       Compressed string `12570 50270 100000 125140 137430`
             ⪪          Split on spaces
            I           Cast to number
         E              Map over values
                    ι   Current value
                   ›    Is greater than
                     ⁰  Literal integer `0`
                  ∧     Logical And
                      ι Current value
  ×                     Vectorised multiply by
     ...                Compressed string `.2 .2 .2 -.2 .05`
    ⪪                   Split on spaces
   I                    Cast to number
 Σ                      Take the sum
I                       Cast to string
                        Implicitly print

73 bytes for a version that calculates the personal allowance as an integer first:

Nθ≔⟦⁹⁹⁷³⁰¦³⁷⁷⁰⁰⌈⟦⁰⁻¹²⁵⁷⁰÷⌈⟦⁰⁻θXχ⁵⟧²⟧⟧η≔⁰ζF³«≔⌊⟦θ⊟η⟧ε≧⁺×∕ι⁵εζ≧⁻εθ»I⁺ζ×θ·⁴⁵

Try it online! Link is to verbose version of code.

\$\endgroup\$
5
\$\begingroup\$

Haskell, 132 129 bytes

-3 bytes thanks to @The Thonnu

r#(-1.0)=r;r#l=min r l
g(t,r)(l,p)=(t+r#l*p/20,r-r#l)
f x=fst$foldl g(0,x)$zip[max(12570-max(x-1e5)0/2)0,37700,99730,-1][0,4,8,9]

Attempt This Online!

\$\endgroup\$
1
  • \$\begingroup\$ Nice answer (+1). I think you could change 100000 to 1e5 to save 3 bytes: Attempt This Online! \$\endgroup\$
    – The Thonnu
    Dec 25, 2022 at 19:10
3
\$\begingroup\$

05AB1E, 32 31 bytes

5ÐD(20)zI•5HwŸJ}Ütæ•žFвT*-Dd**O

Port of @Neil's Charcoal answer, so make sure to upvote him as well!

Try it online or verify all test cases.

Explanation:

5            # Push a 5
 ÐD          # Triplicate + Duplicate so there are four 5s on the stack
   (         # Negate the top one
    20       # Push 20
      )      # Wrap all five values on the stack into a list: [5,5,5,-5,20]
       z     # Get 1/value for each of them: [0.2,0.2,0.2,-0.2,0.05]
I            # Push the input
 •5HwŸJ}Ütæ• # Push compressed integer 90598507370046338479
  žFв        # Convert 90598507370046338479 to base-16384 as list: 
             #  [1257,5027,10000,12514,13743]
     T*      # Multiply each by 10: [12570,50270,100000,125140,137430]
I      -     # Subtract each from the input
        D    # Duplicate this list
         d   # Pop and do a non-negative (>=0) check for each
          *  # Multiply the values at the same positions (negative values have become 0)
*            # Multiply the values at the same positions with list [0.2,0.2,0.2,-0.2,0.05]
 O           # Sum everything together
             # (which is output implicitly as result)

See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand why •5HwŸJ}Ütæ• is 90598507370046338479 and •5HwŸJ}Ütæ•žFв is [1257,5027,10000,12514,13743].

\$\endgroup\$
2
+100
\$\begingroup\$

Vyxal, 58 48 33 bytes

5D:N20WĖ⁰»+gḊ6ß/ċi∴o@t»k4τ-:0≥**∑

Try it online!

  • -15 thanks to lyxal

Port of Neil's Charcoal answer

Explanation

5D:                             # Push 5 and quadruplicate
   N                            # Negate the top one
    20                          # Push 20
      W                         # Wrap the stack in a list
       Ė                        # Reciprocal of each
        ⁰                       # Push the input
         »...»                  # Push the base-255 compressed integer 12570050270100000125140137430
              k4τ               # Convert to list: [12570,50270,100000,125140,137430]
                 -              # Subtract each from the input
                  :             # Duplicate this list
                   0≥           # Check if each element is ≥0
                     *          # Multiply with the list so negative values are now 0
                      *         # Multiply together
                       ∑        # And sum, outputting implicitly
\$\endgroup\$
3
  • \$\begingroup\$ Try it Online! for 40 bytes \$\endgroup\$
    – lyxal
    Dec 31, 2022 at 12:46
  • \$\begingroup\$ or Try it Online! for 33 \$\endgroup\$
    – lyxal
    Dec 31, 2022 at 12:50
  • \$\begingroup\$ @lyxal thanks, updated \$\endgroup\$
    – The Thonnu
    Dec 31, 2022 at 13:10
2
\$\begingroup\$

QB64, 183 bytes

p=12570:If i>100000Then
p=p-Int((i-100000)/2):If p<0Then p=0
endif
l=p+37700:m=l+99730:If i>m Then
t=.45*(i-m):i=m
endif
If i>l Then
t=t+.4*(i-l):i=l
endif
If i>p Then t=t+.2*(i-p)
?t
\$\endgroup\$
1
  • \$\begingroup\$ Suggest (i-p)/5 instead of .2*(i-p) \$\endgroup\$
    – ceilingcat
    Jan 3 at 2:41
1
\$\begingroup\$

C (gcc), 120 107 102 bytes

  • -18 thanks to ceilingcat
#define F+fdim(i
f(i){i=fmin(37700,i=F,F-i+12570,F,1e5)/2)))/5+.4*fmin(99730,i=F,37700))F,99730)*.45;}

Try it online!

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.