43
\$\begingroup\$

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.

\$\endgroup\$
  • 6
    \$\begingroup\$ I'm hoping to see a MATLAB/Octave solution. All my attempts were horribly long... =/ \$\endgroup\$ – Stewie Griffin Apr 17 '18 at 19:04
  • 4
    \$\begingroup\$ I'm hoping to see a Beatnik solution. Cuz, you know, that would be the right tool for the job. \$\endgroup\$ – Giuseppe Apr 17 '18 at 19:28
  • \$\begingroup\$ @StewieGriffin Does 85 bytes count as horribly long? \$\endgroup\$ – Luis Mendo Apr 17 '18 at 21:11
  • 3
    \$\begingroup\$ Hasn't Mathematica a built-in for it? \$\endgroup\$ – sergiol Apr 18 '18 at 0:30
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ – Stewie Griffin Apr 18 '18 at 19:37

52 Answers 52

1
2
2
\$\begingroup\$

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
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Japt -x, 43 39 35 30 bytes

£2+`dglbcÛghvwylk¥ljx¥qz`qÊaøX

Try it online!

35 byte solution:

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

Run it online

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

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!

See also MickyT's answer.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

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!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ nice answer. You should post it here. \$\endgroup\$ – Razetime Sep 27 at 15:18
  • \$\begingroup\$ Bounty will be delivered here. \$\endgroup\$ – Adám Oct 21 at 5:10
1
\$\begingroup\$

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!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Managed to save a few using =~/./g, but can't get it down as far as @nwellnhof's answer... Try it online! \$\endgroup\$ – Dom Hastings Apr 18 '18 at 11:48
  • \$\begingroup\$ 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... \$\endgroup\$ – Phil H Apr 19 '18 at 21:11
1
\$\begingroup\$

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!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

SmileBASIC, 87 85 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
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ 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! \$\endgroup\$ – mazzy Mar 1 '19 at 14:50
  • \$\begingroup\$ Thank you :D !!! I'm not very experienced in Code golfing so can you explain me what you did in your Code? \$\endgroup\$ – Add-TheNewOne Mar 1 '19 at 15:08
  • \$\begingroup\$ Step 1: obvious thing 240 bytes \$\endgroup\$ – mazzy Mar 1 '19 at 17:05
  • \$\begingroup\$ Step 2: big case to default 195 bytes \$\endgroup\$ – mazzy Mar 1 '19 at 17:07
  • \$\begingroup\$ Step 3: to take out repeating code 171 bytes \$\endgroup\$ – mazzy Mar 1 '19 at 17:09
1
\$\begingroup\$

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
  [                     addition loop
    ->+                     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!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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'
	I =INPUT			;* read input
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
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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

enter image description here

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

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

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ You can not assume input to be present in a predefined variable: codegolf.meta.stackexchange.com/a/8731/56433 \$\endgroup\$ – Laikoni Apr 19 '18 at 22:12
  • 1
    \$\begingroup\$ So this is the broken and "cheating" version of my answer posted a day before yours? \$\endgroup\$ – TheLethalCoder Apr 20 '18 at 10:17
  • \$\begingroup\$ @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. \$\endgroup\$ – supermeerkat Apr 23 '18 at 8:54
  • \$\begingroup\$ 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. \$\endgroup\$ – TheLethalCoder Apr 23 '18 at 8:59
0
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

C# (.NET Core), 48 + 18 = 66 bytes

s=>s.Sum(c=>"!#C²!$1$$XhQJ"[c%13]-16>>c%2*4&15)

+18 bytes is for using System.Linq;

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Isnt the function signature part of the code? \$\endgroup\$ – Kristoffer Sall-Storgaard Apr 20 '18 at 22:01
  • \$\begingroup\$ @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. \$\endgroup\$ – Geoffrey Apr 21 '18 at 22:54
  • \$\begingroup\$ I was wrong. It would appear we dont need to name the functions \$\endgroup\$ – Kristoffer Sall-Storgaard Apr 23 '18 at 12:24
0
\$\begingroup\$

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'+@)
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
1
2

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.