When making a Dungeons & Dragons character, an alternative to rolling ability scores is to assign them within a power budget called point buy. Higher ability scores cost more points, especially towards the upper end: a score of 8 is free, and raising a score by 1 costs 1 point, except raising to 15 or 16 costs 2 points, and raising to 17 or 18 costs 3 points.

+-------+------+
| Score | Cost |
+-------+------+
|     8 |    0 |
|     9 |    1 |
|    10 |    2 |
|    11 |    3 |
|    12 |    4 |
|    13 |    5 |
|    14 |    6 |
|    15 |    8 |
|    16 |   10 |
|    17 |   13 |
|    18 |   16 |
+-------+------+

In list form:

[(8, 0), (9, 1), (10, 2), (11, 3), (12, 4), (13, 5), (14, 6), (15, 8), (16, 10), (17, 13), (18, 16)]

The point buy cost is summed for all six ability scores.

Ability scores: 16   17   8  13   8  12
Point buy cost: 10 + 13 + 0 + 5 + 0 + 4  = 32

Given six ability scores, each 8 through 18, output the total point buy cost. Fewest bytes wins.

• Ähm is it just me or is the given challange missing? 0o – Zaibis Dec 23 '15 at 14:19
• @Zaibis Not sure what you mean. I put in "fewest bytes wins" -- did you mean that? – xnor Dec 23 '15 at 19:39
• tmp blah blah to say: yep – Zaibis Dec 23 '15 at 19:41

# JavaScript (ES7), 4442 40 bytes

Crossed out 44 is still regular 44 :(

a=>a.map(s=>t+=s-9-~((s-14)**1.3),t=0)|t

Thanks to @apsillers for saving 2 bytes!

## Explanation

The interesting part is -1-~((s-14)**1.3). (s-14)**1.3 produces 1, 2, 4 and 6 for the values 15 - 18. Any number that is less than 15 causes an error because the JavaScript implementation of exponential cannot operate on negative values with a fractional exponent. Basically, any value for s < 15 causes it to return NaN, so the -1-~ is there to cast it to a number (0).

a=>                       // a = input scores as an array of numbers
a.map(s=>               // for each passed score
t+=                   // add to the total
s-9                 // point value = s - 8 (-1 used for next line)
-~((s-14)**1.3),    // add extra points for scores 15 - 18
t=0                   // t = total points (this happens BEFORE the map call)
)
|t                      // return the total points

### ES6 Solution (42 bytes)

a=>a.map(s=>t+=s-9-~[1,2,4,6][s-15],t=0)|t

## Test

This test uses Math.pow instead the exponential operator (**) so that it can run in any standard browser.

var solution = a=>a.map(s=>t+=s-9-~Math.pow(s-14,1.3),t=0)|t
Scores separated by spaces = <input type="text" id="input" value="16 17 8 13 8 12" />
<button onclick="result.textContent=solution(input.value.split(' '))">Go</button>
<pre id="result"></pre>

• One more byte: use |t instead of &&t. The ECMAScript operation ToInt32 will always coerce the result of map here to 0, because multi-element arrays will always ToNumber-ify to NaN. (This would be a problem if the spec allowed single-element arrays as input, but it requires 6 elements.) – apsillers Dec 23 '15 at 14:53
• @apsillers Ooh, that's a nice tip! Thanks – user81655 Dec 23 '15 at 15:15

## CJam, 18 bytes

l~[8EG]ff-:~0fe>:+

or

l~[8EG]m*::m0fe>:+

Test it here.

### Explanation

The idea is decompose the point cost into three components:

Score: 8  9 10 11 12 13 14 15 16 17 18
0  1  2  3  4  5  6  7  8  9 10
0  0  0  0  0  0  0  1  2  3  4
0  0  0  0  0  0  0  0  0  1  2
--------------------------------
Cost:  0  1  2  3  4  5  6  8 10 13 16

All three components can be computed via a single subtraction and restricting the result to non-negative values.

l~    e# Read and evaluate input.
[8EG] e# Push [8 14 16].
ff-   e# For each pair from the two lists, subtract one from the other.
:~    e# Flatten the result.
0fe>  e# Clamp each difference to non-negative values.
:+    e# Sum them all up.

# Pyth, 14 bytes

s>#0-M*Q+14yB8

Test suite

This uses the same fundamental means of calculation as Martin Büttner, namely:

max(n-8, 0) + max(n-14, 0) + max(n-16, 0)

That being said, the means of calculation are very different. To generate the list of numbers to subtract, I use the expression +14yB8. yB8 means "Bifurcate 8 on the function y". y doubles numbers, so this gives [8, 16]. Then, we add on 14, giving the list [14, 8, 16].

Next, we take the Cartesian product with the input and subtract every pair of values.

Next, perform the maximization operation, we simply filter for positive values only, and sum the remainder.

# Samau, 19 bytes

Not sure if the question is posted after the last commit of my new language. They are both 2 hours ago. But all the features used here was added before that.

▐[8 14 16]-o;0>*ΣΣ

Samau uses CP737 as its default character encoding.

▐[8 14 16]-o;0>*ΣΣ
▐                      read a list of numbers
[8 14 16]             push [8 14 16]
`-           push the function [-]
o          outer product
;         duplicate
0>       for each element, test if it's larger than 0
*      times
ΣΣ    take the sum twice because it's a 2d array

## PowerShell, 48 Bytes

$args|%{$t+=$_-8+@{15=1;16=2;17=4;18=10}[$_]};$t (Pretty sure this isn't optimal.) Takes input command-line arguments and pipes them into a loop |%{...}. Each iteration, we increment our total$t+= with the current number minus 8 $_-8 plus the result of indexing into a hashtable for the more-expensive values @{...}[$_]. Then we simply output \$t at the end.

# (🐂👍) Ox++, 248 bytes (62 characters)

🐀👉🌑👺🐁👉🌑👺😂🐀🐟🌗😂🐂👉😷😺😺😷👺🐁👉🐁👏🐂🙌🌙👏🌜🐂🐳🌒🌕🌛👥🌜🐂🙌🌒🌕🌛👏🌜🐂🐳🌒🌗🌛👥🌜🐂🙌🌒🌗🌛👺🐀👍😂👄🐁👄

Language I'm working on. Paste in the code here.

• My browser can only display 7 of these characters. – isaacg Dec 23 '15 at 20:39