10
\$\begingroup\$

Sales taxes in the United States are complicated, to say the least. Generally, there's a state sales tax (there are a handful of states that do not collect a state sales tax), but there could also be a county sales tax, a school district sales tax, a municipal (city) sales tax, or a metropolitan area sales tax. There could even be different sales taxes in different parts of a city. For the purposes of this challenge, however, we're going to focus on just the state sales tax.

Given a U.S. dollar amount greater than zero (accurate to two decimal places) and a state (either the full name or the two-letter abbreviation, your choice, case doesn't matter), and using the below chart of sales tax percentages, output the corresponding state sales tax required to be collected for that particular sale, accurate and truncated to two decimal places. Please specify how your code handles rounding.

Edit: The abbreviation for Washington was listed incorrectly as WS instead of WA. Answers may use either abbreviation, since that was my goof.

State          Abbr   %
Alabama         AL  4.00%
Alaska          AK  0.00%
Arizona         AZ  5.60%
Arkansas        AR  6.50%
California      CA  6.00%
Colorado        CO  2.90%
Connecticut     CT  6.35%
Delaware        DE  0.00%
Florida         FL  6.00%
Georgia         GA  4.00%
Hawaii          HI  4.00%
Idaho           ID  6.00%
Illinois        IL  6.25%
Indiana         IN  7.00%
Iowa            IA  6.00%
Kansas          KS  6.50%
Kentucky        KY  6.00%
Louisiana       LA  5.00%
Maine           ME  5.50%
Maryland        MD  6.00%
Massachusetts   MA  6.25%
Michigan        MI  6.00%
Minnesota       MN  6.875%
Mississippi     MS  7.00%
Missouri        MO  4.23%
Montana         MT  0.00%
Nebraska        NE  5.50%
Nevada          NV  4.60%
New Hampshire   NH  0.00%
New Jersey      NJ  6.88%
New Mexico      NM  5.13%
New York        NY  4.00%
North Carolina  NC  4.75%
North Dakota    ND  5.00%
Ohio            OH  5.75%
Oklahoma        OK  4.50%
Oregon          OR  0.00%
Pennsylvania    PA  6.00%
Rhode Island    RI  7.00%
South Carolina  SC  6.00%
South Dakota    SD  4.50%
Tennessee       TN  7.00%
Texas           TX  6.25%
Utah            UT  4.70%
Vermont         VT  6.00%
Virginia        VA  4.30%
Washington      WA  6.50%
West Virginia   WV  6.00%
Wisconsin       WI  5.00%
Wyoming         WY  4.00%

Example for California at 6% state sales tax --

CA
1025.00

61.50

Example for Minnesota at 6.875% --

MN
123.45

8.49
\$\endgroup\$
  • 14
    \$\begingroup\$ inb4 Mathematica builtin. \$\endgroup\$ – DJMcMayhem Sep 5 '17 at 14:20
  • \$\begingroup\$ Minnesota MN 6.875% - because .005% is, well, actually a lot. \$\endgroup\$ – Magic Octopus Urn Sep 5 '17 at 14:22
  • 1
    \$\begingroup\$ Ahhh... right... this isn't income tax. \$\endgroup\$ – Magic Octopus Urn Sep 5 '17 at 14:29
  • 2
    \$\begingroup\$ @Shaggy No, case doesn't matter. \$\endgroup\$ – AdmBorkBork Sep 5 '17 at 14:43
  • 2
    \$\begingroup\$ Pedantry: the state abbreviation for Washington is WA, not WS. \$\endgroup\$ – Michael Seifert Sep 5 '17 at 19:10

12 Answers 12

15
\$\begingroup\$

Mathematica, 112 103 77 76 66 bytes

Mathematica has a builtin for everything

NumberForm[Interpreter["USState"][#]@"StateSalesTaxRate"#2,{9,2}]&

Takes a state name (any format; abbreviation or full name) and the dollar amount.

Try it on Wolfram Sandbox

Usage

f = NumberForm[Interpreter["USState"][#]@"StateSalesTaxRate"#2,{9,2}]&

 

f["CA", 1025.00]

61.50

f["miNnNesToA", 123.45]

8.49

Explanation

Interpreter["USState"][#]

Interpret the input as a US State name and generate an Entity.

... @"StateSalesTaxRate"

Get the sales tax rate.

... #2

Multiply that by the second input.

NumberForm[..., {9,2}]

Format the result into a number with 9 digits to the left of the decimal and 2 digits to the right.

\$\endgroup\$
  • 6
    \$\begingroup\$ Mathematica. Of course... \$\endgroup\$ – Ven Sep 5 '17 at 14:40
  • 8
    \$\begingroup\$ This is just getting silly now! \$\endgroup\$ – Shaggy Sep 5 '17 at 14:41
  • \$\begingroup\$ Why do you need to use an API as long as the string to get the 142nd property? \$\endgroup\$ – Neil Sep 5 '17 at 15:07
  • 11
    \$\begingroup\$ There's a semi-serious pedantic point here. Given that Mathematica sources its real-word data from a constantly updating datastore, what happens when the tax rate of a particular state changes? Doesn't this answer then become invalid with respect to the spec given in the question? \$\endgroup\$ – ymbirtt Sep 5 '17 at 16:19
  • 4
    \$\begingroup\$ @ymbirtt should be fine per this meta discussion. \$\endgroup\$ – JungHwan Min Sep 5 '17 at 17:19
5
\$\begingroup\$

R, 219 212 bytes

function(S,m)sprintf("%.2f",c(4,0,5.6,6.5,6,2.9,6.35,0,6,4,4,6,6.25,7,6,6.5,6,5,5.5,6,6.25,6,6.875,7,4.23,0,5.5,4.6,0,6.88,5.13,4,4.75,5,5.75,4.5,0,6,7,6,4.5,7,6.25,4.7,6,4.3,6.5,6,5,4)[match(S,state.abb)]*m/100)

Takes the state as an abbreviation (all caps).

state.abb is the builtin R data with the state abbreviations in alphabetical order, so it hardcodes the sales taxes, finds the index of the state, calculates the sales tax, and formats to 2 decimal places (output as a string).

Try it online!

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

05AB1E, 134 bytes

.•2=Šλ₁ÙH ’€9¿FîβïLT_s€¤Ôтαxì8ÜuK8º'DιÒ—pcλ¯øÒÔ\’þü€ŒβÞéΣŽZê•#.å1kUX0‹i6*т/ëX•Ž½ì∞в’±₃C¸wiα·¥žYÉúžĆƵ˜šŸ‰Ê‡†Σgλ&/ûjDĆв₆•hR„AB„ .‡#è*т/}

Try it online!


RIP Mathematica wins.


All this does is compresses the following strings:

AKDEMTNHOR CO ALGANYHIWY MO VA SDOK NV UT NC LANDWI NM MENE AZ OH ILMATX CT ARKSWS MN NJ INMSRITN

And:

0 2.9 4 4.23 4.3 4.5 4.6 4.7 4.75 5 5.13 5.5 5.6 5.75 6.25 6.35 6.5 6.875 6.88 7

Then uses the index of the input state to determine the index of the rate, defaulting to 6, because there are so many states with 6%.


For others to consume:

AKDEMTNHOR 0
CO         2.9
ALGANYHIWY 4
MO         4.23
VA         4.3
SDOK       4.5
NV         4.6
UT         4.7
NC         4.75
LANDWI     5
NM         5.13
MENE       5.5
AZ         5.6
OH         5.75
CAFLIDIAKYMDMIPASCVTWV 6
ILMATX     6.25
CT         6.35
ARKSWS     6.5
MN         6.875
NJ         6.88

Note this only works because I ordered the states such that no intersection of 2 states creates a different state E.G. (OHIN contains [OH,IN,HI] whereas INOH only contains [IN,OH])


Most of the ideas for this came from my previous state-based entry.

\$\endgroup\$
  • \$\begingroup\$ TIO link has -d flag \$\endgroup\$ – H.PWiz Sep 5 '17 at 14:51
  • \$\begingroup\$ @H.PWiz That's for visualizing the stack. If you remove it, you will see the regular output of the program. \$\endgroup\$ – Mr. Xcoder Sep 5 '17 at 14:54
  • \$\begingroup\$ @H.PWiz it's for visualization purposes only, takes it command-by-command and lets you see why the program works. \$\endgroup\$ – Magic Octopus Urn Sep 5 '17 at 14:55
  • \$\begingroup\$ Ah, I thought it was left in by mistake. \$\endgroup\$ – H.PWiz Sep 5 '17 at 14:56
3
\$\begingroup\$

Pyth, 270 258 233 219 bytes

*c@[6Z5.75K6.25 5.5 5 4Z7 6.5J6 7J6.875 7 4J6.35Z6 7 5 4.75 4 4.23J5J5.13 4.6JJ4J4 4.3 4.5Z5.6J.5 4.7K4.5KZ6.5 6.88 5.5J2.9)xc."AZ-íâFT34r7²¨cK'ÉT?Ú5Ï)}4Që7ËÅÖpuªXTiÖ¶7×ì­Éͨ."2w100

Must be passed parameters like so:

1025
CA

Explanation:

*c@[...)xc."..."2w100
          ."..."       Decompress the string
         c      2      Cut the string in chunks of size 2 (states abbreviations)
        x        w     Get the index of the second parameter in that string
  @[    )              Index into the tax array
 c                100  Generate a percentage
*                      Multiply that with the implicit input at the end
Alas, `.Z` makes this longer. Maybe there's a way to write the array more efficiently, by repeating the keys, but I havn't found one yet.

Thanks to @Mr.Xcoder.

\$\endgroup\$
3
\$\begingroup\$

Java (OpenJDK 8), 594 + 19 592 580 575 412 bytes

s->a->{float[]r={0};java.util.Arrays.asList("AL4`AK0`AZ5.6`AR6.5`CA6`CO2.9`CT6.35`DE0`FL6`GA4`HI4`ID6`IL6.25`IN7`IA6`KS6.5`KY6`LA5`ME5.5`MD6`MA6.25`MI6`MN6.875`MS7`MO4.23`MT0`NE5.5`NV4.6`NH0`NJ6.88`NM5.13`NY4`NC4.75`ND5`OH5.75`OK4.5`OR0`PA6`RI7`SC6`SD4.5`TN7`TX6.25`UT4.7`VT6`VA4.3`WS6.5`WV6`WI5`WY4".split("`")).forEach(e->{if(e.contains(s))r[0]=a/100*new Float(e.substring(2));});return s.format("%.2f",r[0]);}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ You can save 9 bytes by directly addressing Arrays as java.util.Arrays and getting rid of the import statement. I'd include a TIO link but it's too long. :P \$\endgroup\$ – totallyhuman Sep 5 '17 at 15:19
  • \$\begingroup\$ You can save a few more bytes by removing final; changing double to float; changing Double.parseDouble to new Float; and changing (s,a)-> to s->a-> by using currying. Here is the TIO-link to see how. \$\endgroup\$ – Kevin Cruijssen Sep 5 '17 at 19:30
  • 1
    \$\begingroup\$ Oh, and you can also remove all commas and trailing zeroes and change substring(3) to substring(2): TIO 415 bytes. That's shorter than my Java answer.. ;) \$\endgroup\$ – Kevin Cruijssen Sep 5 '17 at 19:36
3
\$\begingroup\$

Java 8, 486 467 309 299 290 289 bytes

s->a->{float r=6;for(String x:"AKDENHORMT0 CO2.9 ALGANYHIWY4 MO4.23 VA4.3 SDOK4.5 NV4.6 UT4.7 NC4.75 LANDWI5 NM5.13 MENE5.5 AZ5.6 OH5.75 ILMATX6.25 CT6.35 ARKSWS6.5 MN6.875 NJ6.88 MSRINTN7".split(" "))if(x.contains(s))r=new Float(x.replaceAll("[A-Z]",""));return s.format("%.2f",a*r/100);}

-19 bytes thanks to @MagicOctopusUrn by removing the semicolons.

Explanation:

Try it here.

s->a->                    // Method with String and float parameters and String return-type
  float r=6;              //  Float starting at 6 (most states had 6.00 as tax)
  for(String x:"...".split(" "))
                          //  Loop over all states + amounts
    if(x.contains(s))     //   If the input-state is found in String `x`:
      r=new Float(x.replaceAll("[A-Z]",""));
                          //    Set float `r` to the amount of this state
                          //  End of loop (implicit / single-line body)
  return s.format("%.2f", //  Return result rounded to 2 decimal points:
     a*r/100);            //   Float input multiplied by `r` divided by 100
}                         // End of method
\$\endgroup\$
  • 1
    \$\begingroup\$ If you use the ordering from my answer you can remove all semicolons in your strings. \$\endgroup\$ – Magic Octopus Urn Sep 5 '17 at 14:59
  • \$\begingroup\$ HI;NY and MT;NH are currently the only things in your code stopping you from removing all semi-colons. Reverse the order of both and it'd work for like 20 bytes saved. \$\endgroup\$ – Magic Octopus Urn Sep 5 '17 at 15:03
  • 1
    \$\begingroup\$ @MagicOctopusUrn Thanks, edited! Btw, you might want to add the states for 7 to your answer as well (although TN does interfere with the current order of 0). \$\endgroup\$ – Kevin Cruijssen Sep 5 '17 at 19:25
  • \$\begingroup\$ @MagicOctopusUrn INMSRITN 7.00 & AKDENHORMT 0.00 is possible without conflicting with anything else. \$\endgroup\$ – Kevin Cruijssen Sep 5 '17 at 19:45
2
\$\begingroup\$

Perl 6, 341 bytes

my%a=((<ME NE>X=>5.5),CO=>2.9,MO=>4.23,MN=>6.875,NJ=>6.88,(<LA ND WI>X=>5),(<AK DE MT NH OR>X=>0),(<IN MS RI TN>X=>7),(<AR KS WS>X=>6.5),AZ=>5.6,(<AL GA HI NY WY>X=>4),VA=>4.3,UT=>4.7,(<IL MA TX>X=>6.25),(<CA FL ID IA KY MD MI PA SC VT WV>X=>6),(<OK SD>X=>4.5),NV=>4.6,NM=>5.13,CT=>6.35,OH=>5.75,NC=>4.75).flat;{round $^a*(%a{$^b}/100),0.01}

So, huh. This is pretty contrived, I guess. This uses Perl 6's meta-operators, like X=> here, which is X (cross product) combined with =>.

That means <ME NE> X=> 5.5 (where <ME NE> means ('ME', 'NE')) gets => 5.5 applied on each element of the array, yielding ME => 5.5, NE => 5.5. The parentheses are merely here for precedence...


As a golfer (erm...), I obviously didn't write that one by hand (except the actual function). So I wrote a meta-golfer to generate the most efficient combination!

my %values;
my %simple;
for lines() {
  my $abb = m/<[A .. Z]> ** 2/.Str;
  my $val = m/\d\.\d+/.Str;
  %values{$val}.push: $abb;
  %simple{$abb} = $val;
}

say "(", (join ',', do for %values.kv -> $key, @vals {
  my $int-key = +$key;
  if @vals > 1 {
    "(<{@vals}>X=>$int-key)"
  } else {
    "{@vals}=>$int-key"
  }
}), ").flat";

say();

say join ',', do for %simple.kv -> $key, $val {
  "$key=>" ~ +$val
}

It generates both the X=> cases and the more simple case (with each one being enumerated), and I picked the shortest one (the former).

\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 227 224 bytes

Takes input in currying syntax (s)(v) where s is the state and v is the amount. Uses floor rounding.

s=>v=>(v*(p=s=>parseInt(s,36))('3344bk50k4mo28k4we4tm5eg3uw48s5az39i3js5b43yi3ny4fq3h03mk3bg'.substr(p('k039017k00038f00030022h00g000j00k600k080k707h30706800ba0030305ic0303303930460000e00d2'[p(s)*84%943%85])*3,3))/1e3|0)/100

Demo

let f =

s=>v=>(v*(p=s=>parseInt(s,36))('3344bk50k4mo28k4we4tm5eg3uw48s5az39i3js5b43yi3ny4fq3h03mk3bg'.substr(p('k039017k00038f00030022h00g000j00k600k080k707h30706800ba0030305ic0303303930460000e00d2'[p(s)*84%943%85])*3,3))/1e3|0)/100

console.log(f("CA")(1025))
console.log(f("MN")(123.45))

\$\endgroup\$
1
\$\begingroup\$

Kotlin, 444 bytes

val S="0|AK|DE|MT|NH|OR#2.9|CO#4|AL|GA|HI|NY|WY#4.23|MO#4.3|VA#4.5|OK|SD#4.6|NV#4.7|UT#4.75|NC#5|LA|ND|WI#5.13|NM#5.5|ME|NE#5.6|AZ#5.75|OH#6|CA|FL|ID|IA|KY|MD|MI|PA|SC|VT|WV#6.25|IL|MA|TX#6.35|CT#6.5|AR|KS|WS#6.875|MN#6.88|NJ#7|IN|MS|RI|TN"
fun c(t:String,d:Double){
val m=mutableMapOf<String,Double>()
S.split("#").map{val s=it.split("|")
for (item in s.subList(1, s.size))m.put(item, s[0].toDouble())}
System.out.printf("%.2f", m[t]!!*d*.01)}

Try it online!

Beautified

// Tax rate followed by states with that rate separated by pipes, with hashes in between
val STATES="0|AK|DE|MT|NH|OR#2.9|CO#4|AL|GA|HI|NY|WY#4.23|MO#4.3|VA#4.5|OK|SD#4.6|NV#4.7|UT#4.75|NC#5|LA|ND|WI#5.13|NM#5.5|ME|NE#5.6|AZ#5.75|OH#6|CA|FL|ID|IA|KY|MD|MI|PA|SC|VT|WV#6.25|IL|MA|TX#6.35|CT#6.5|AR|KS|WS#6.875|MN#6.88|NJ#7|IN|MS|RI|TN"

fun function(targetState: String, amount: Double) {
    // Stores data
    val m = mutableMapOf<String, Double>()
    // For each rate
    STATES.split("#").map {
        // Split the data out
        val rateData = it.split("|")
        // For each state with that rate
        for (stateCode in rateData.subList(1, rateData.size)) {
            // Put it in the dataset
            m.put(stateCode, rateData[0].toDouble())
        }
    }

    // Print out the tax rate
    System.out.printf("%.2f", m[targetState]!! * amount * .01)
}
\$\endgroup\$
1
\$\begingroup\$

Python 3, 303 bytes

import re
t=re.split("(\d+)","AL4AK0AZ56AR65CA6CO29CT635DE0FL6GA4HI4ID6IL625IN7IA6KS65KY6LA5ME55MD6MA625MI6MN6875MS7MO423MT0NE55NV46NH0NJ688NM513NY4NC475ND5OH575OK45OR0PA6RI7SC6SD45TN7TX625UT47VT6VA43WS65WV6WI5WY4")
f=lambda s,a:"%.2f"%({t[i-1]:float(t[i])/10**-~len(t[i])for i in range(1,len(t),2)}[s]*a)

Try it online!

Very simple: the data is stored data as two chars + list of digits: every percentage is less than 10, thus it can be stored as integer part (1 digit) + decimal part (0-... digit(s)).

\$\endgroup\$
1
\$\begingroup\$

C#, 318 309 bytes


Data

  • Input String s The 2 letter abbreviation of the state uppercase.
  • Input Double v The value
  • Output String The tax value to be collected rounded to 2 decimal places

Golfed

(s,v)=>{for(int i=0;i<21;i++)if("NHAKDEMTOR,CO,ALHIGANYWY,MO,VA,SDOK,NV,UT,NC,NDLAWI,NM,MENE,AZ,OH,KYCAFLIDIAMDMIPASCVTWV,ILMATX,CT,ARKSWA,MN,NJ,MSINRITN".Split(',')[i].Contains(s))return $"{v*(new[]{0,2.9,4,4.23,4.3,4.5,4.6,4.7,4.75,5,5.13,5.5,5.6,5.75,6,6.25,6.35,6.5,6.875,6.88,7}[i]/100):F2}";return "";};

Ungolfed

( s, v ) => {
    for( int i = 0; i < 21; i++ )
        if( "NHAKDEMTOR,CO,ALHIGANYWY,MO,VA,SDOK,NV,UT,NC,NDLAWI,NM,MENE,AZ,OH,KYCAFLIDIAMDMIPASCVTWV,ILMATX,CT,ARKSWA,MN,NJ,MSINRITN".Split( ',' )[ i ].Contains( s ) )
            return $"{v * ( new[] { 0, 2.9, 4, 4.23, 4.3, 4.5, 4.6, 4.7, 4.75, 5, 5.13, 5.5, 5.6, 5.75, 6, 6.25, 6.35, 6.5, 6.875, 6.88, 7 }[ i ] / 100 ):F2}";
    return "";
};

Ungolfed readable

// Takes a 2 letter abbreviation state ( 's' ) and a value ( 'v' )
( s, v ) => {

    // Cycles through an array with the states grouped by tax value
    for( int i = 0; i < 21; i++ )

        // Checks if the state group at the current index contains the state 's'
        if( "NHAKDEMTOR,CO,ALHIGANYWY,MO,VA,SDOK,NV,UT,NC,NDLAWI,NM,MENE,AZ,OH,KYCAFLIDIAMDMIPASCVTWV,ILMATX,CT,ARKSWA,MN,NJ,MSINRITN".Split( ',' )[ i ].Contains( s ) )

            // Returns the value 'v' * the corresponding state percentage divided by 100
            return $"{v * ( new[] { 0, 2.9, 4, 4.23, 4.3, 4.5, 4.6, 4.7, 4.75, 5, 5.13, 5.5, 5.6, 5.75, 6, 6.25, 6.35, 6.5, 6.875, 6.88, 7 }[ i ] / 100 ):F2}";

    // If the state isn't found, return an empty string
    return "";
};

Full code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestBench {
    public static class Program {
        private static Func<String, Double, String> f = ( s, v ) => {
            for( int i = 0; i < 21; i++ )
                if( "NHAKDEMTOR,CO,ALHIGANYWY,MO,VA,SDOK,NV,UT,NC,NDLAWI,NM,MENE,AZ,OH,KYCAFLIDIAMDMIPASCVTWV,ILMATX,CT,ARKSWA,MN,NJ,MSINRITN".Split( ',' )[ i ].Contains( s ) )
                    return $"{v * ( new[] { 0, 2.9, 4, 4.23, 4.3, 4.5, 4.6, 4.7, 4.75, 5, 5.13, 5.5, 5.6, 5.75, 6, 6.25, 6.35, 6.5, 6.875, 6.88, 7 }[ i ] / 100 ):F2}";
            return "";
        };

        static void Main( string[] args ) {
            List<KeyValuePair<String, Double>>
                testCases = new List<KeyValuePair<String, Double>>() {
                    new KeyValuePair<String, Double>( "CA", 1025.0d ),
                    new KeyValuePair<String, Double>( "MN", 123.45d ),
                };

            foreach( KeyValuePair<String, Double> testCase in testCases ) {
                Console.WriteLine( $" STATE: {testCase.Key}\n VALUE: {testCase.Value}\nOUTPUT: {f( testCase.Key, testCase.Value )}\n" );
            }

            Console.ReadLine();
        }
    }
}

Releases

  • v1.0 - 318 bytes - Initial solution.
  • v1.1 - - 9 bytes - Changed the .ToString("F2") used in the first return to interpolated strings.

Notes

  • None
\$\endgroup\$
0
\$\begingroup\$

AWK, 277 bytes

{split("LANDWI 5 VA 4.3 IACAFLIDKYMDMIPASCVTWV 6 SDOK 4.5 MO 4.23 CO 2.9 NM 5.13 NV 4.6 UT 4.7 NJ 6.88 MENE 5.5 AZ 5.6 ARKSWA 6.5 MN 6.875 MSINRITN 7 ILMATX 6.25 NC 4.75 CT 6.35 ALGANYWYHI 4 OH 5.75 AKDEMTORNH 0",T)
for(i in T)if(T[i]~s=".*"$1".*")printf"%.2f\n",$2*T[i+1]*.01}

Try it online!

A respectable score, but nowhere near Mathematica. I did add 2 bytes by having a newline print after each check, but I think it's prettier that way :)

(Hopefully it's obvious that input should be the state abbreviation and a value on one line. )

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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