# Scrabble scorer

### Challenge:

Take a string of upper or lower case letters as input (optional), and calculate the score that string would get in a game of Scrabble in English.

### Rules:

The score of each letter is as follows (use this even if there are other versions of the game):

1 point: E, A, I, O, N, R, T, L, S, U
2 points: D, G
3 points: B, C, M, P
4 points: F, H, V, W, Y
5 points: K
8 points: J, X
10 points: Q, Z


The score of a string is simply the sum of the scores of each of the letters used. You may assume that you have plenty of tiles available, so long words, and words with many of the same letters are valid input.

### Test cases:

ABC       ->    7
PPCG      ->   11
STEWIE    ->    9
UGPYKXQ   ->   33
FIZZBUZZ  ->   49
ABCDEFGHIJKLMNOPQRSTUVWXYZ  -> 87


The shortest answer in each language wins! The input and output formats are flexible, so you may take the input as an array of characters (upper or lower case) if you want.

• I'm hoping to see a MATLAB/Octave solution. All my attempts were horribly long... =/ Apr 17, 2018 at 19:04
• I'm hoping to see a Beatnik solution. Cuz, you know, that would be the right tool for the job. Apr 17, 2018 at 19:28
• @StewieGriffin Does 85 bytes count as horribly long? Apr 17, 2018 at 21:11
• Hasn't Mathematica a built-in for it? Apr 18, 2018 at 0:30
• @manassehkatz you should definitely give it a go! I highly recommend that you post the challenge in the Sandbox to get some feedback and help with it before posting it on the main site. Complex challenges are notoriously difficult to get right without any feedback. Apr 18, 2018 at 19:37

# K (oK), 60 38 bytes

Solution:

+/1+.:'"02210313074020029000033739"65!


Try it online!

Explanation:

Index into the scores, sum up result.

+/1+.:'"02210313074020029000033739"65! / the solution
65! / input modulo 65 to get position in A-Z
"02210313074020029000033739"    / index into the scores (1 point lower)
.:'                                / value (.:) each (') to convert to ints
1+                                   / increase by 1
+/                                     / sum up


# Japt -x, 433935 30 bytes

£2+dglbcÛghvwylk¥ljx¥qzqÊaøX


Try it online!

## 35 byte solution:

¬£Ò('0+#Ý03#740#È29e4+33739 g65nXc


Run it online

# Beatnik, 379 bytes

K ZZZZKF ZD ZD ZD ZD ZD ZD ZD
K ZZZZZZZZA J Z ZD ZB B
K XA KD ZD ZF F ZA ZD KF KF ZD ZB B
K D Z ZD ZB B
K ZF Z ZD ZF KA ZA ZD ZD KF KF KF ZD ZB B
K A KD ZD ZF D ZA KF ZD ZB B
K ZF KD ZD ZB B
K D Z ZD ZB B
K A Z ZD ZB B
K ZF Z ZD ZB B
K D Z ZD ZF D ZA KF ZD ZB B
K Z KD ZD ZB B
K B Z ZD ZB B
K Z Z ZD ZB B
K A Z ZD ZF F ZA KF ZB Z
K K KD ZD ZB B
K B Z ZF A KF
KF
XX ZZZZZZZZZZZZZX


Try it online!

# APL (Dyalog Extended), 40 bytes

+/1+⍎¨'02210313074020029000033739'[⎕A⍳⎕]


The same method as the K answer, index into a list of scores, add 1 to them, and sum.

Try it online!

• nice answer. You should post it here. Sep 27, 2020 at 15:18
• Bounty will be delivered here.
Oct 21, 2020 at 5:10

# JavaScript (ES6), 69 bytes

Takes input as an array of characters.

s=>s.map(c=>t-=~'9200204703130122093733'[parseInt(c,36)*25%26],t=0)|t


Try it online!

# Bash + GNU utilities, 64

sed -es/[{QZ]/JD,JX]/KB,K]/FE,FHVWY]/BE,BCMP]/DE,DG]/EE}/g|wc -c


Try it online!

Input read from STDIN. Uses a brace expansion to generate sed expressions equivalent to those in my sed answer.

# Perl 6, 55 bytes

{sum .map:{:36<Z3P8JOBRZ4X1FBXLWSVL>+>(.ord*4-260)%16}}


Try it online!

Takes an array of characters. Uses a 4-bit lookup table encoded in base-36.

# Perl 5-pF, 73 bytes

$\+=(1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,(1)x4,4,4,8,4,10)[-65+ord]for@F}{  Try it online! • Managed to save a few using =~/./g, but can't get it down as far as @nwellnhof's answer... Try it online! Apr 18, 2018 at 11:48 • My Perl6 solution is pretty similar to this, I opted to use value-1 thus only needing 0-9 which are single digits and then split 022103... Apr 19, 2018 at 21:11 # Red, 97 bytes func[s][t: :to-integer n: 0 foreach c s[n: n - 47 + t pick{02210313074020029000033739}t c - 64]n]  Takes a string as input. ## Explanation of the ungolfed solution: f: func[s][ n: 0 ; n will store the sum foreach c s [ ; for each character in the argument n: n - 47 + to-integer pick {02210313074020029000033739} to-integer c - 64 ; find its offset from "A" (to-integer c - 64) ; use this as an index in the string with scores (pick {...} ...) ; to extract the score and convert it to an integer ; increase it with 1 and add it to the sum ] n ; return the sum ]  Try it online! # Pip, 34 33 bytes 1+("3V1S1QFRU1SMQ12W7"FB36)@A_MSa  Takes input in lowercase as a command-line argument. Try it online! ### Explanation We map a function to each character of the command-line argument a and sum the results using MS. In the function, we convert the argument _ to its ASCII code using A, and then use that to index into the magic number 30740200290000337390221031. With cyclic indexing, this maps a -> 0, b -> 2, ... , z -> 9 (one less than the Scrabble score). We then add 1 to get the correct score of each letter. We save one byte by encoding the number in base 36 (the highest base Pip's builtin base conversion can handle) as the string "3V1S1QFRU1SMQ12W7" and then converting it from base 36 to decimal using FB. # SmileBASIC, 8785 78 bytes INPUT S$WHILE""<S$S=S+VAL(@2210313074020029000033739[ASC(POP(S$))-65])+1WEND?S


Old method:

INPUT S$WHILE""<S$S=S+(INSTR(@DG+@___BCMP_FHVWYK*2+"JX"*4+@QZ,POP(S$))+4)DIV 5+1WEND?S  # Go, 96 94 bytes func(i string){a,s:=  ,0;for _,c:=range i{s+=int(a[c-65])};print(s)}  Go allows any byte sequence in a raw string, except \r and , this saves about 3 bytes off the total. This is just a remix of existing solutions in other languages, so no real new innovation here. Edit: I missed the memo where we dont have to name our functions Try it online! # Powershell with amazing 297 Bytes Any idea to make the script shorter? $1=read-Host
$s=0$l=$1.ToCharArray()$l|%{switch($_){{'E','A','I','O','N','R','T','L','S','U'-contains$_}{$s+=1}{'D','G'-contains$_}{$s+=2}{'B','C','M','P'-contains$_}{$s+=3}{'F','H','V','W','Y'-contains$_}{$s+=4}{'J','X'-contains$_}{$s+=8}{'Q','Z'-contains$_}{$s+=10}{'K'-contains$_}{$s+=5}}}$s

• You can remove the string $s=0. The -in is sorter than -contains. switch can returns a value $s+=$(switch($_){...{1}...{2}... ...{5}}). and etc :) Welcome! Mar 1, 2019 at 14:50
• Thank you :D !!! I'm not very experienced in Code golfing so can you explain me what you did in your Code? Mar 1, 2019 at 15:08
• Step 1: obvious thing 240 bytes Mar 1, 2019 at 17:05
• Step 2: big case to default 195 bytes Mar 1, 2019 at 17:07
• Step 3: to take out repeating code 171 bytes Mar 1, 2019 at 17:09

# brainfuck, 386 382 bytes

->,[>>,]->+>>+++>>+++>>++>>+>>++++>>++>>++++>>+>>++++++++>>+++++>>+>>+++>>+>>+>>+++>>++++++++++>>+>>+>>+>>+>>++++>>++++>>++++++++>>++++>>+++++++++++[-<<+]->+[->++++++++[<-------->-]<-[[->+]>>-<+[-<+]->]+[->+]->[->+>[>>]>++[-<+]->]>[-<+>]<<+<[<<]>-<+[-<+]>>->+]>[>>]>>+[[-]<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->[-]>>+>+<<<]]]]]]]]]<]>>[>]++++++[-<++++++++>]>>]<<<[.[-]<<<]


Try it online!

Pretty much ungolfed, but first brainfuck code for this question. This code can only handle uppercase letters. Any other symbol will lead to an endless loop. Also the maximum score depends on the used bf-interpreter. On tio.run this can handle scores up to 254.

points:
abcde fghij klmno pqrst uvwxyz
13321 42418 51311 3x111 14484x (x = 10)

tape:
[input], 0, [points table], 0, 0, score
input: current letter marker (0 or neg 1), current letter
points table: check letter marker (0 or neg 1), points

code:
-           set current letter marker
>,[>>,]     input characters

->          set check letter marker
fill points table
+>>+++>>+++>>++>>+>>
++++>>++>>++++>>+>>++++++++>>
+++++>>+>>+++>>+>>+>>
+++>>++++++++++>>+>>+>>+>>
+>>++++>>++++>>++++++++>>++++>>++++++++++

+[-<<+]->                   go to first input letter
+                           bugfix: intersecting pointers
[                       main loop
-                         bugfix: intersecting pointers
>++++++++[<-------->-]<-  subtract 65 from current letter (ASCII A)
[                         check loop: mark the entry in points table that's related to the current letter
[->+]                   decrease letter and go to check letter marker
>>-                     set new check letter marker
<+[-<+]-                go back to current letter marker
>                       go to current letter
]
the related points entry is found so we need to add the points to the score
+[->+]->                  go to related points entry
->+                     decrease points entry and save points to temporary cell
>[>>]>+                 go to score and add 1
+[-<+]->                go back to related points entry
]
>[-<+>]                   move points back from temp cell
<<+                       delete "check letter marker"
<[<<]>-                   set "check letter marker" at A
<+[-<+]                   go to current letter marker
>>-                       set new current letter marker
>                         next input letter
+                         exit loop if cell pointer is at "check letter marker" position
]

>[>>]>                      go to score
number printing routine from esolangs
>+[[-]<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->[-]>>+>+<<<]]]]]]]]]<]>>[>]++++++[-<++++++++>]>>]<<<[.[-]<<<]


if unary output is allowed then this 297 293 bytes code can be used:

->,[>>,]->+>>+++>>+++>>++>>+>>++++>>++>>++++>>+>>++++++++>>+++++>>+>>+++>>+>>+>>+++>>++++++++++>>+>>+>>+>>+>>++++>>++++>>++++++++>>++++>>+++++++++++[-<<+]->+[->++++++++[<-------->-]<-[[->+]>>-<+[-<+]->]+[->+]->[->+>[>>]>++[-<+]->]>[-<+>]<<+<[<<]>-<+[-<+]>>->+]>[>>]<+++++++[>+++++++<-]>>[-<.>]


Try it online!

# SNOBOL4 (CSNOBOL4), 224 bytes

	V =ARRAY(10,0)
V<1> ='EAIONRTLSU'
V<2> ='DG'
V<3> ='BCMP'
V<5> ='FHVWY'
V<8> ='JX'
V<10> ='QZ'
I =INPUT
N	S =I
X =LT(X,10) X + 1	:F(O)
R	S ANY(V<X>) =	:S(R)
O =O + X * (SIZE(I) - SIZE(S))
I =S	:(N)
O	OUTPUT =O
END


Try it online!

Very naive approach. Stores the letters in an ARRAY with indices equal to the scores. It tries to match 0 for point values that don't exist, which ends in a score of 0.

	V =ARRAY(10,0)			;* set up value array of 10 values with contents all 0
V<1> ='EAIONRTLSU'		;* set contents at appropriate indices
V<2> ='DG'
V<3> ='BCMP'
V<5> ='FHVWY'
V<8> ='JX'
V<10> ='QZ'
N	S =I				;* begin Next iteration
X =LT(X,10)	X + 1	:F(O)	;* increment X or GOTO output
R	S ANY(V<X>) =	:S(R)		;* replace ANY letters in V<X> with nothing
O =O + X * (SIZE(I) - SIZE(S))	;* add to the score
I =S	:(N)			;* set I to S and goto N
O	OUTPUT =O
END


# x86-machine code, IBM PC DOS, 37 bytes

00000000: bb18 0133 d2ac 2c41 d0e8 9cd7 d410 9d72  ...3..,A.......r
00000010: 0286 e002 d0e2 eec3 1332 1424 1851 3113  .........2.$.Q1. 00000020: a111 1448 4a ...HJ  Listing: BB 0118 MOV BX, OFFSET TBL ; load score table into BX 33 D2 XOR DX, DX ; clear letter count LOOP_LETTER: AC LODSB ; load next char from DS:SI into AL, advance SI 2C 41 SUB AL, 'A' ; convert letter to zero-based index D0 E8 SHR AL, 1 ; divide index by 2, set CF if odd index 9C PUSHF ; save CF D7 XLAT ; AL = packed score byte D4 10 AAM 16 ; unpack nibbles into AH/AL (clobbers CF though) 9D POPF ; restore CF 72 02 JC ODD ; if odd index, use low nibble 86 E0 XCHG AH, AL ; otherwise is even, use high nibble ODD: 02 D0 ADD DL, AL ; add tile to score E2 EE LOOP LOOP_LETTER ; loop through all letters C3 RET ; return to caller TBL: DB 013H,032H,014H,024H,018H,051H,031H,013H,0A1H,011H,014H,048H,04AH  Try it online! Note: using link above, re-run with input on command line like ASM ABC, etc. As a callable function, input string at [SI], length in CX. Output to DX. Explanation Uses a score table of 4-bit nibbles for each tile's score. Loops through the input string and converts each letter to a zero-based index. Each index is divided by two to find the corresponding byte in the table. The low nibble is added if the index is odd, otherwise the high nibble is added if the index is even. Test Program I/O ## Visual Basic for Applications, 117 bytes s=inputbox(u):for i=1to 16:s=replace(s,mid("DGBCMPFHVWYKJXQZ",i,1),space(mid("1122223333347799",i,1)+1)):next:?len(s)  Run in immediate (debug) window. ## C# 49 bytes s.Sum(i=>"02210313074020029000033739"[i-65]-47);  Where s is a string containing the word in uppercase. Uses the LINQ operator sum which examines each character and subtracts 65 (upper case A) and uses the resultant value to lookup a number in the long string, which represents the scores in alphabetical order starting with 0 as 1, 1 as 2 etc. The final subtraction -47 reduces the score to its ASCII value = 0 becomes 1, 1 becomes 2 etc • You can not assume input to be present in a predefined variable: codegolf.meta.stackexchange.com/a/8731/56433 Apr 19, 2018 at 22:12 • So this is the broken and "cheating" version of my answer posted a day before yours? Apr 20, 2018 at 10:17 • @TheLethalCoder No - whacked this out over lunch and forgot about it. Didn't see yours until I l read your comment. There aren't many ways of doing this as succinctly as possible, and I guess I came up with the same method (albeit with a glaring mistake) as you, but if it makes your fragile ego feel better, go ahead and accuse me of cheating. Apr 23, 2018 at 8:54 • The "cheating" is that you haven't included the method signature, in this case i=> and you haven't included the using System.Linq; into your byte count. You can also drop the trailing semi-colon. My ego is, however, very much intact thank you very much. Apr 23, 2018 at 8:59 # PHP, 74 bytes while($c=$argn[$i++])$s+=1+_02210313074020029000033739[ord($c)&31];echo$s;  case insensitive. Run as pipe with -nR or try it online. # C# (.NET Core), 48 + 18 = 66 bytes s=>s.Sum(c=>"!#C²!$1XhQJ"[c%13]-16>>c%2*4&15)


+18 bytes is for using System.Linq;

Try it online!

• Isnt the function signature part of the code? Apr 20, 2018 at 22:01
• @KristofferSall-Storgaard I'm not actually sure on the code golf rules since I don't post often. I just mimicked TheLethalCoder's setup and tried to save a few bytes. Apr 21, 2018 at 22:54
• I was wrong. It would appear we dont need to name the functions Apr 23, 2018 at 12:24

# T-SQL, 106 bytes

Accepting uppercase characters.

Inserted a line break to make this readable:

DECLARE @ varchar(max)='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

WHILE'='<@
SET
@=stuff(@,1,1,'')+'-~'+substring('02210313074020029000033739',ascii(@)-64,1)
EXEC('print'+@)


# Rockstar, 187 184 bytes

listen to W
cut W into S
T's"DG1BCMP1FHVWY1K111JX11QZ"
X's0
while W at X
P's1
Y's0
while T at Y
let L be T at Y
let P be+L is 1
if L is W at X
let S be+P

let Y be+1

let X be+1

say S


Try it here (Code will need to be pasted in)

Abuses a nice little feature in Rockstar whereby the variable (S in this case) an array is assigned to can be used to reference both the array (e.g., S at index) or, by itself, the length of the array. So, by cutting the input Word into the array S we, straight away, have a base score of 1 point per letter.

From there we just loop over the Word, with an initial Point value of 1, inner loop over the Tiles, increment P if the current tile is 1 and increment the Score by P if the 2 letters match.

# Zsh + bc, 54 bytes

bc<<<$#1tr a-z 02210313074020029000033739<<<${1///+}


Try it online!

# Pure Zsh, 55 bytes

<<<$[$#1tr a-z 02210313074020029000033739<<<\${1///+}]
`

Try it online!