How fast is my Hot Wheels car?

23

4

Several years back, Hot Wheels made a simple flash game called "Formula Fuelers Racers"*. To play the game, you select three ingredients from a fridge to put into your car, which is then raced against the computer's randomly-generated car. It turns out the mechanics of this game are pretty simple. First off, the actual race "time" of your car is randomly generated and has no bearing on whether or not you win the race. Secondly, the winner of the race is determined by a score which is calculated from the selected ingredients (duplicate ingredients are allowed, and the order matters). Each ingredient has an associated "value" and an associated "operation" as shown in the following table:

#   ingredient     val  op
1   Hot Salsa       2   +
2   Root Beer       1   +
3   Milk            1   +
4   Pickle Juice    2   +
5   Mystery Lunch   -3  *
6   BBQ Sauce       2   +
7   Egg             1   +
8   Ketchup         2   +
9   Mustard         -1  *
10  Melon           1   +
11  Chocolate Milk  1   +
12  Mayonnaise      -2  *
13  Baby Food       0   +
14  Pepper          1   +
15  Salt            2   +
16  Syrup           -1  *
17  Salad Dressing  2   +
18  Orange Juice    1   +
19  Soy Sauce       2   +

For convenience, this challenge will be referring to ingredients by their number and not their name. Here are the steps to compute a score:

  1. First, initialize the score with the value of the first ingredient.
  2. Then, use the second ingredient's operation to combine the current score and the second ingredient's value to get an updated score.
  3. Finally, use the third ingredient's operation to combine the current score and the third ingredient's value to get the final score.

Higher scores are better and always beat lower scores.

For example, the ingredients 1 2 3 have a score of (2+1)+1 = 4. The ingredients 7 5 6 have a score of (1*-3)+2 = -1. Therefore, 1 2 3 beats 7 5 6.

Challenge

In this challenge, you shall write a program which takes an ordered list of 3 integers and outputs the corresponding score.

Input

Your program may accept a list of three integers in the most convenient format. You are allowed to use either 1-indexing for the ingredient names (as above) or 0-indexing (subtract 1 from every index above).

Ouput

Your program must output a single integer indicating the score.

Test Cases

4 5 5  =>  18 // max score
5 5 5  =>  -27 // min score
13 13 13  =>  0
1 2 3  =>  4
7 5 6  =>  -1
16 2 19  =>  2
19 7 12  =>  -6

*This page is pretty outdated and doesn't work in some browsers, but you don't need to play the game for this challenge.

PhiNotPi

Posted 2017-04-09T22:04:16.753

Reputation: 26 739

1So basically Salsa+Lunch+Mayo=Invincible? – Matthew Roh – 2017-04-09T23:02:26.290

3@SIGSEGV Duplicate ingredients are allowed. Salsa, Lunch, Lunch is allowed for a score of 18 that beats your 12. – Level River St – 2017-04-09T23:21:25.160

2

For reference, here is an archive of the game.

– Matthew Roh – 2017-04-10T08:00:09.977

4Who keeps salt in the fridge? :) – Wossname – 2017-04-10T12:26:31.460

LUNCH LUNCH LUNCH means your car explodes the second the wheels touch pavement then I s'pose. – Magic Octopus Urn – 2017-04-10T17:49:51.103

3>

  • I don't know why salt would be in a fridge. 2. Yes, once you discover an 18-point combo you become literally invincible and the game becomes meaningless.
  • < – PhiNotPi – 2017-04-10T20:44:03.640

    Can we take input ingredients in reverse order? ([3,2,1] instead of [1,2,3]) – Arnauld – 2017-04-11T07:18:02.300

    @carusocomputing No, the score would then be 0, which is beaten by 18. – Erik the Outgolfer – 2017-04-11T11:36:58.693

    @EriktheOutgolfer the score is -27 for L L L. I meant "explode" with a negative connotation. – Magic Octopus Urn – 2017-04-11T13:28:01.710

    @Arnauld I'm leaning towards "no" mainly because that will probably affect the "golfiness" of the other existing answers. – PhiNotPi – 2017-04-12T13:07:51.357

    Answers

    13

    Jelly, 24 bytes

    “zẈ€$ụ¤’b6’ị@µỊị⁾+׿CFḊV
    

    Takes a list of 0-indexed ingredients.

    Try it online! or see a test suite

    How?

    Uses a slightly convoluted form of compressing the values as a base-6 number and the fact that the multiplicative entries are the negative ones. Instead of simply shifting up by 3 to get the base-6 digits, the complemented values incremented are used - this saves bytes by allowing the atom to pick out the negative entries prior to the complement step while also saving a byte in the base-250 compression.

    “zẈ€$ụ¤’b6’ị@µỊị⁾+׿CFḊV - Main link: 0-based ingredient list  e.g. [6,4,5]
    “zẈ€$ụ¤’                 - base 250 compressed number: 120851767994004
            b6               - convert to base 6: [1,1,0,5,0,1,0,3,1,1,4,2,1,0,3,0,1,0,0]
              ’              - decrement: [0,0,-1,4,-1,0,-1,2,0,0,3,1,0,-1,2,-1,0,-1,-1]
               ị@            - index into [reversed @rguments]          [0,4,-1]
                 µ           - monadic chain separation (call that x)
                  Ị          - insignificant(x)? (abs(x)<=1)            [1,0,1]
                    ⁾+×      - ['+','×']
                   ị         - index into                               ['+','×','+']
                        C    - complement(x) (1-x)                      [1,-3,2]
                       ż     - zip                                      [['+',1],['×',-3],['+',2]]
                         F   - flatten                                  ['+',1,'×',-3,'+',2]
                          Ḋ  - dequeue                                  [1,'×',-3,'+',2]
                           V - evaluate as Jelly code                   -1
    

    Jonathan Allan

    Posted 2017-04-09T22:04:16.753

    Reputation: 67 804

    How does the "base 250 compressed number" part work? – ckjbgames – 2017-04-10T14:46:15.467

    @ckjbgames The zẈ€$ụ¤ are read as their (1-indexed) indexes in the Jelly code-page, which are [123,188,13,37,226,4], and interpreted as a base-250 number: 123*250**5+188*250**4+13*250**3+37*250**2+226*250**1+4*250**0=120851767994004 (see the string-literal section of the tutorial.)

    – Jonathan Allan – 2017-04-10T15:26:32.363

    Oh, a string literal. – ckjbgames – 2017-04-10T15:36:17.610

    This was my approach until I realized "-3" doesn't mean "-3" when evaluating as 05AB1E code. – Magic Octopus Urn – 2017-04-10T17:56:18.570

    11

    JavaScript (ES6), 89 84 82 78 73 bytes

    Takes input as an array of 3 integers, using 0-indexing.

    a=>(o=a=>F()<0?a*n:a+n)(o((F=_=>n='5445054524413452545'[a.shift()]-3)()))
    

    Test cases

    let f =
    
    a=>(o=a=>F()<0?a*n:a+n)(o((F=_=>n='5445054524413452545'[a.shift()]-3)()))
    
    console.log(f([3, 4, 4]))     // =>  18
    console.log(f([4, 4, 4]))     // =>  -27
    console.log(f([12, 12, 12]))  // =>  0
    console.log(f([0, 1, 2]))     // =>  4
    console.log(f([6, 4, 5]))     // =>  -1
    console.log(f([15, 1, 18]))   // =>  2
    console.log(f([18, 6, 11]))   // =>  -6

    Previous version, 78 bytes

    Takes the 3 integers in currying syntax (a)(b)(c), using 0-indexing.

    a=>b=>(o=a=>b=>(n=F(b))<0?a*n:a+n)(o((F=n=>'5445054524413452545'[n]-3)(a))(b))
    

    How it works

    One slightly unusual thing about this code is that it only takes 2 arguments in 'common' currying syntax a => b => and eventually returns a function that takes the 3rd one.

    Breakdown

    F = n => '5445054524413452545'[n] - 3
    o = a => b => (n = F(b)) < 0 ? a * n : a + n
    f = a => b => o(o(F(a))(b))
    
    f(a)(b)(c)
      |  |  |
      |  |  +-- 'b' argument of the function returned by the outer call to 'o'
      |  +----- 'b' argument of the function returned by 'f'
      +-------- 'a' argument of 'f'
    

    Test cases

    let f =
    
    a=>b=>(o=a=>b=>(n=F(b))<0?a*n:a+n)(o((F=n=>'5445054524413452545'[n]-3)(a))(b))
    
    console.log(f(3)(4)(4))     // =>  18
    console.log(f(4)(4)(4))     // =>  -27
    console.log(f(12)(12)(12))  // =>  0
    console.log(f(0)(1)(2))     // =>  4
    console.log(f(6)(4)(5))     // =>  -1
    console.log(f(15)(1)(18))   // =>  2
    console.log(f(18)(6)(11))   // =>  -6

    Arnauld

    Posted 2017-04-09T22:04:16.753

    Reputation: 111 334

    1Strictly speaking, you're taking 1 argument and returning a function that takes 1 argument, computes a value to invoke a function that takes 1 argument and returns a function that takes 1 argument, and returns that final function... – Neil – 2017-04-10T10:09:16.333

    6

    PHP, 128 Bytes

    $i="5445054524413452545";[,$a,$b,$c]=$argv;echo(bc.($i[$c]-3<0?mul:add))((bc.($i[$b]-3<0?mul:add))($i[$a]-3,$i[$b]-3),$i[$c]-3);
    

    PHP, 138 Bytes

    $d=decbin(506743);$i="5445054524413452545";[,$a,$b,$c]=$argv;echo(bc.($d[$c]?add:mul))((bc.($d[$b]?add:mul))($i[$a]-3,$i[$b]-3),$i[$c]-3);
    

    Online Version

    Expanded

    $d=decbin(506743);
    $i="5445054524413452545";
    [,$a,$b,$c]=$argv;
    echo(bc.($d[$c]?add:mul))((bc.($d[$b]?add:mul))($i[$a]-3,$i[$b]-3),$i[$c]-3);
    

    Jörg Hülsermann

    Posted 2017-04-09T22:04:16.753

    Reputation: 13 026

    6

    Befunge, 74 73 bytes

    >&:0`!#^_1g68*-^:0`!#v_+
    ^2112-212/11.012/212 >*
    ^   @.$<       >">"35*0p
    

    Try it here! It's weird that my code works on this one interpreter only.

    The second row basically contains all of the values from the table. The non-numeric values are actually negative values as they come before the digits on the ASCII table. There's a bit of logic there that determines if the number is negative or not, and if it is, this number is multiplied by the result.

    The right side of the third row initializes the first number. If I didn't have to do that, I could save a lot of bytes.

    user55852

    Posted 2017-04-09T22:04:16.753

    Reputation:

    6

    Python 2, 123 110 107 bytes

    a,b,c=input()
    s=[int(i)-3for i in'05445054524413452545']
    n=s[a]
    for i in s[b],s[c]:n=[n*i,n+i][n>0]
    print n
    

    Try it online!


    -3 bytes thanks to @mathjunkie

    ovs

    Posted 2017-04-09T22:04:16.753

    Reputation: 21 408

    1Here is an improved version, 118 bytes – Mr. Xcoder – 2017-04-10T12:27:46.630

    25445054524413452545 then subtract 3 may save you *tons* of bytes. – Magic Octopus Urn – 2017-04-10T17:54:54.720

    1n=[n+i,n*i][i<0] inside the loop saves you 3 bytes – math junkie – 2017-04-11T14:47:32.990

    5

    05AB1E, 29 bytes

    •6SÚ²ÄOÕ6BS3-©¹è|v®yèD0‹i*ë+
    

    Try it online!

    •6SÚ²ÄOÕ6BS3-©               # Push [2, 1, 1, 2, -3, 2, 1, 2, -1, 1, 1, -2, 0, 1, 2, -1, 2, 1, 2] and store.
                   ¹è             # Get first score.
                     |v           # Iterate through remaining scores.
                       ®yèD0‹i*ë+ # Push score list, grab relevant score.
                                  # If negative, multiply, else add.
    

    This actually works for as many or as few inputs as you'd like, so you can have cars with 4 or more traits or cars with just 2. This was not intentional, just how it ended up.

    Magic Octopus Urn

    Posted 2017-04-09T22:04:16.753

    Reputation: 19 422

    5

    CJam, 43 38 bytes

    q~[YXXY-3YXYWXX-2TXYWYXY]f={_W>42+c~}*
    

    There might be a way to compress the list further...

    Uses 0-based indexing.

    Try it online!

    Explanation

    This program makes use of the fact that a value is multiplicative instead of additive if and only if its negative.

    q~                     e# Get the list from input
      [...]                e# Push the list of values for each ingredient. T=0, W=-1, 
                           e#   X=1, Y=2. 
           f=              e# Get the elements at the given indices 
             {             e# Reduce over this block:
              _W>          e#  Check if the second number is > -1 (returning 0 or 1)
                 42+c      e#  Add the result to 42 and cast to a char. 
                           e#    (ASCII 42 is * and 43 is +)
                     ~     e#  Eval the char (* is multiply, + is add)
                      }*   e# (end block)
    

    Business Cat

    Posted 2017-04-09T22:04:16.753

    Reputation: 8 927

    Nice + * trick! – Esolanging Fruit – 2017-04-17T17:48:39.527

    3

    Lua, 140 131 bytes

    i={2,1,1,2,-3,2,1,2,-1,1,1,-2,0,1,2,-1,2,1,2}function f(a,b,c)loadstring(("print("..i[a].."+"..i[b].."+"..i[c]..")"):gsub('%+%-','*-'))()end
    

    i={2,1,1,2,-3,2,1,2,-1,1,1,-2,0,1,2,-1,2,1,2}function f(a,b,c)x,y,z=i[a],i[b],i[c]v=y>0 and x+y or x*y;print(z>0 and v+z or v*z)end
    

    Blab

    Posted 2017-04-09T22:04:16.753

    Reputation: 451

    3

    JavaScript, 85 72 bytes

    a=a=>eval(a.map(x=>(b="5445054524413452545"[x]-3,b<0?"*":"+")+b).join``)
    

    Takes input in format [a,b,c]
    -13 bytes thanks to ETHproductions

    Bald Bantha

    Posted 2017-04-09T22:04:16.753

    Reputation: 463

    You can do x=>(b="...",b<0?"*":"+")+b to avoid the return, I think. (Also, you don't need the [... ], indexing works on strings) – ETHproductions – 2017-04-11T00:30:43.500

    @ETHproductions I get "Expected ';'. It may be my browser, does a=a=>eval(a.map(x=>(b="5445054524413452545"[x]-3,b<0?"*":"+")+b)).join``) work for you? – Bald Bantha – 2017-04-11T00:38:12.603

    You've got an extra ) after +b, I believe – ETHproductions – 2017-04-11T00:41:42.763

    2

    R, 125 123 bytes

    function(a,b,c){v=c(5,4,4,5,0,5,4,5,2,4,4,1,3,4,5,2,5,4,5)-3
    o=rep("+",19)
    o[v<0]="*"
    get(o[c])(get(o[b])(v[a],v[b]),v[c])}
    

    Anonymous function that takes three integers as input. Defines a list of values and operations, and then just evaluates the ones called by the input, i.e. o3(o2(v1,v2),v3). There's almost definitely a golfier way to do this!

    Update: after some re-working, I have an alternative, also 123 bytes. Again, an anonymous function, but takes input as a single vector of three values. Uses the same approach, defining a list of values and operations and evaluating it.

    function(x,f=c(sum,prod)[x[-1]%in%c(5,9,12,16)+1],s=c(5,4,4,5,0,5,4,5,2,4,4,1,3,4,5,2,5,4,5)[x]-3)f[[2]](el(f)(s[-3]),s[3])
    

    rturnbull

    Posted 2017-04-09T22:04:16.753

    Reputation: 3 689

    2

    Haskell, 186 116 112 108 bytes

    o x|x<0=(*)|0<1=(+)
    v=(map((-51+).fromEnum)"95445054524413452545"!!)
    w [x,y,z]=(o z)((o y)x y)z
    k=w.map v
    

    Main function is k. New to Code Golf so I am sure there are a few bytes I could shave off with clever use of $ operator versus parentheses. I will probably update the answer as I continue to find improvements.

    Essentially the program can be broken down like this:

    • v is a function that takes a 1 based index and returns the value of that food id.
    • o is a function that takes the food value and returns the appropriate operator (Eg. negative values are always * where positive values are always +)
    • w is a function that takes a List of 3 partial functions of v mapped to input integers and fetches the appropriate operations and values from each and returns the proper output.
    • k is the main function in point free style that maps v to input and composes this list for w to return the output.

    UPDATE

    Special thanks for pointing out the fromEnum trick! That worked out nicely. Also I missed the part in the rules that stated an acceptable solution could be a function that takes a list of integers. That saved a tremendous amount of work.

    UPDATE 2

    As per other suggestions, shaved a handful of bytes by reordering operations, creating an else guard that always evaluates to True, and a pattern matching on W that pattern matches on a List of 3 elements. Thanks for the suggestions!

    UPDATE 3

    Another thanks to Laikoni for pointing out more code golf rules that I was not aware of. Also mapping v to my input to create a list of partially applied functions was a phenomenal idea and saved me 4 additional bytes!

    maple_shaft

    Posted 2017-04-09T22:04:16.753

    Reputation: 421

    1Welcome to PPCG and Haskell golfing in particular! You can save a lot of bytes by writing a function [Int] -> Int instead of reading from stdin and writing to stdout. Doing so is allowed by default, but in this case its even explicitly mentioned in the challenge that taling a list of integers as input is acceptable. – Laikoni – 2017-04-12T19:35:07.637

    1Using fromEnum instead of digitToInt is likely to be shorter because it allows you to drop the import. – Laikoni – 2017-04-12T19:39:30.777

    @Laikoni Much thanks to you for pointing out some of the rules I wasn't aware of! The fromEnum trick worked like a charm too, don't know why I didn't think of working from the ASCII code but that saved a tremendous amount of bytes as well. – maple_shaft – 2017-04-13T01:59:19.763

    1v=(map((-51+).fromEnum)"95 ... 5"!!) saves two parenthesis. o x|x<0=(*)|0<1=(+) saves one byte in the second guard. – Laikoni – 2017-04-13T05:37:03.570

    1In w is an extra space left. Also, as you only need to handle lists of length 3, you can use w[x,y,z]= as pattern matching. – Laikoni – 2017-04-13T05:38:21.860

    @Laikoni Thanks for the additional suggestions. I still think I can shave an additional byte off of w but I am having trouble with it. I will see what I can do. – maple_shaft – 2017-04-13T14:39:07.407

    Anonymous functions are allowed as submission, so you can have w.map v as main function and save all the calls to v in w. Then v is only used once and can be inlined. – Laikoni – 2017-04-13T15:01:21.867

    92 bytes: o x|x<0=(*)|0<1=(+);k w|[x,y,z]<-([read[q]-3|q<-"95445054524413452545"]!!)<$>w=zoo y x y$z – BlackCap – 2017-04-14T12:27:36.277

    @BlackCap sounds like you should post this as an answer – maple_shaft – 2017-04-14T13:38:55.613

    1

    Haskell, 92 87 bytes

    x#y|x<0=(y*)|0<1=(y+)
    k[x,y,z]=z#z$y#x$y
    k.map([read[q]-3|q<-"95445054524413452545"]!!)
    

    Try it online!

    Based on @maple_shaft's answer, I just factorized it a bit.

    Thanks to @Laikoni for 5 bytes!

    BlackCap

    Posted 2017-04-09T22:04:16.753

    Reputation: 3 576

    1

    87 bytes: Try it online!

    – Laikoni – 2017-04-14T15:37:31.523

    @Laikoni I am pretty sure the newlines count – BlackCap – 2017-04-17T16:58:32.200

    I didn't count the two bytes for f= because anonymous functions are allowed as submission. They are only required to make the tio example work. – Laikoni – 2017-04-17T19:11:57.440

    0

    8086 machine code, 62 bytes

    00000000  be 3b 01 31 c0 86 c4 ac  e8 0a 00 81 fe 3e 01 72  |.;.1.........>.r|
    00000010  f4 b4 4c cd 21 bb 32 01  d0 e8 d7 73 03 c0 e0 04  |..L.!.2....s....|
    00000020  c0 f8 04 e3 05 31 c9 c3  86 c4 78 03 00 e0 c3 f6  |.....1....x.....|
    00000030  ec c3 21 12 d2 12 f1 1e  01 2f 12 00 00 00        |..!....../....|
    0000003e
    

    The last three bytes contain the (zero-indexed) input. Hey, you told me I could use the most convenient input format. In this case, that's hardcoding!
    Output is the error code returned to the shell.

    How it works:

                |   org 0x100
                |   use16
    be 3b 01    |       mov si, input   ; source = input
    31 c0       |       xor ax, ax      ; clear ax
    86 c4       |   @@: xchg al, ah     ; swap al/ah (ah = total value)
    ac          |       lodsb           ; al = *si++
    e8 0a 00    |       call fn
    81 fe 3e 01 |       cmp si, input+3 ; end of input?
    72 f4       |       jb @b           ; repeat if not
    b4 4c       |       mov ah, 0x4c    ; dos function: exit with al=error code
    cd 21       |       int 0x21        ; syscall
                |
    bb 32 01    |   fn: mov bx, table   ; pointer to lookup table
    d0 e8       |       shr al, 1       ; divide input by 2
    d7          |       xlatb           ; al = *(bx + al)
    73 03       |       jnc @f          ; skip next instruction if input was odd
    c0 e0 04    |       shl al, 4       ; shift low nibble to high nibble
    c0 f8 04    |   @@: sar al, 4       ; shift high nibble to low nibble with sign-extension
    e3 05       |       jcxz @f         ; return if cx is non-zero (only happens for the first input)
    31 c9       |       xor cx, cx      ; clear cx
    c3          |       ret
    86 c4       |       xchg al, ah     ; swap al/ah (al = total value)
    78 03       |   @@: js @f           ; multiply if negative, add if positive
    00 e0       |       add al, ah      ; al = al+ah
    c3          |       ret
    f6 ec       |   @@: imul ah         ; ax = al*ah
    c3          |       ret
    21 12 d2 12 |   table db 0x21, 0x12, 0xd2, 0x12, 0xf1, 0x1e, 0x01, 0x2f, 0x12
    f1 1e 01 2f |                       ; each value is stored in a 4-bit nibble
    12          |
    00 00 00    |   input db 3 dup(0)
    

    user5434231

    Posted 2017-04-09T22:04:16.753

    Reputation: 1 576

    0

    C, 171 161 bytes

    #include<stdio.h>
    r,z[3],*a=z,i;f(x){i?x<0?r*=x:(r+=x):(r=x);}main(){scanf("%d %d %d",a,a+1,a+2);for(;i++<3;f("05445054524413452545"[*a++]-51));printf("%d",r);}
    

    Peter Lenkefi

    Posted 2017-04-09T22:04:16.753

    Reputation: 1 577