20
\$\begingroup\$

My dad is a retired teacher, and he used to give combined spelling and math quizzes, where the student would spell a word, and then 'score' the word by adding up the letters, where a=1, b=2, etc. (e.g. cat = 3+1+20=24). This made grading the quizzes easier, as he would just have to check for incorrect 'scores' rather than incorrectly spelled words, and had the added benefit of testing 2 skills at once.

He hired a friend of mine to write a program that would score words for him, so he could generate lengthy answer keys without error. This problem is inspired by that program.

Requirements:

  1. Accept any word with uppercase and lowercase letters
  2. Return an error for any special characters, i.e. spaces, hyphens, @^%# etc.
  3. a=1, b=2,... and A=1, B=2,...
  4. Print the score of the word
  5. (Optional) check that the word is in a dictionary after scoring, and print a warning if it is not.
  6. No importing an external letter->number dictionary. You must generate it yourself.

Any language is acceptable. This is similar to the 'digital root battle,' but much simpler.

\$\endgroup\$
12
  • 2
    \$\begingroup\$ Is this supposed to be a code golf? \$\endgroup\$ Apr 23 '11 at 18:08
  • 2
    \$\begingroup\$ @Zach Using the code-golf tag. \$\endgroup\$
    – Lowjacker
    Apr 23 '11 at 18:24
  • 3
    \$\begingroup\$ Yeah, only checking scores? I'd spell cat as aaaaaaaaaaaaaaaaaaaaaaaa. Dad: Score is 24? That's right! \$\endgroup\$
    – ericw31415
    May 8 '16 at 14:13
  • 4
    \$\begingroup\$ @ericw31415 Every hashing function has collisions ;-). So far none of his students have tried that attack vector \$\endgroup\$
    – Zach
    May 9 '16 at 15:39
  • 3
    \$\begingroup\$ @Zach Also, it would be too complex if his dad made his students do SHA-512 of their words. \$\endgroup\$
    – ericw31415
    May 10 '16 at 20:42

38 Answers 38

1
2
1
\$\begingroup\$

JavaScript, 68 Bytes

This can almost certainly be golfed more

w=>[...w.toLowerCase()].map(v=>v.charCodeAt()-96).reduce((a,b)=>a+b)

With dictionary check (Node.js & Unix Descendants only) 195 Bytes

Uses /usr/share/dict/words, and can definitely be shortened (see the warn message)

w=>(require("fs").readFile("/usr/share/dict/words",(e,t)=>!(t+"").split`
`.includes(w=w.toLowerCase())&&console.warn(w+" not found in dict")),[...w].map(v=>v.charCodeAt()-96).reduce((a,b)=>a+b))
\$\endgroup\$
5
  • \$\begingroup\$ For an error message, you do console.error(), not console.warn(). \$\endgroup\$
    – ericw31415
    May 8 '16 at 17:59
  • \$\begingroup\$ But the challenge said to warn (5. (Optional) check that the word is in a dictionary after scoring, and print a warning if it is not.) Don't mean to be pedantic, but the challenge specified a warning \$\endgroup\$
    – bren
    May 8 '16 at 20:24
  • \$\begingroup\$ @SpeedyNinja I think it still counts, that isn't really the point of the challenge... \$\endgroup\$ May 8 '16 at 20:48
  • \$\begingroup\$ @EᴀsᴛᴇʀʟʏIʀᴋ it is 1 character shorter ;) \$\endgroup\$
    – bren
    May 8 '16 at 20:59
  • \$\begingroup\$ @SpeedyNinja You're right, I misread. \$\endgroup\$
    – ericw31415
    May 9 '16 at 0:55
1
\$\begingroup\$

JavaScript (V8), 51 bytes

w=>w.split``.reduce((a,l)=>a+parseInt(l,36)-9,0)||x

Surprised nobody's made this golf yet.

Explanation:

w =>                // Function with w as argument
w.split``           // Split w into an array of characters
.reduce((a,l)=>a+   // Take the sum of...
parseInt(l,36)-9    // The value of the letter in base 36, then subtract nine (gives the number of the letter)
,0)||x              // Error if it's NaN (there was a special character), because x is not defined
\$\endgroup\$
2
  • \$\begingroup\$ Does this error for input of "123"? \$\endgroup\$ Nov 19 '20 at 22:46
  • \$\begingroup\$ @DominicvanEssen No, but my understanding of the requirements was that only symbols/special characters had to be handled, not numbers. If numbers also need to be handled it would be 12 more bytes. (As far as I can tell, none of the other JS answers error if given symbols anyway) \$\endgroup\$ Nov 19 '20 at 22:56
1
\$\begingroup\$

Perl 5 -pF, 26 bytes

/\PL/||map$\+=037&ord,@F}{

Try it online!

Outputs nothing as its error condition

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

Forth, 48 bytes

0 -rot bounds [do] [i] c@ 32 xor 64 - + [loop] .

(takes arguments from the stack)

a version that reads from stdin:

0 pad pad pad stdin read-line 2drop bounds [do] [i] c@ 32 xor [if] 64 - + [loop] .

the second version, but commented:

0 pad \ used later
pad \ where to put the bytes
pad \ how many bytes (it's an address, so it's a big number, and forth doesn't have types)
stdin \ where to get the bytes
read-line \ get the bytes (also returns the number of bytes got)
2drop \ ignore IO errors 
bounds \ turn an address and a length into a start and end address
[do] \ iterate over all the address in said range 
[i] \ get the current address
c@ \ get the character at the current address
32 xor \ make it uppercase
64 - \ letter to number (eg a -> 1)
+ \ add number to total (this is what the 0 is for)
[loop] \ end loop
. \ print resulting number
\$\endgroup\$
1
  • \$\begingroup\$ This doesn't handle uppercase characters in the input correctly, but the fix actually saves a byte: Try it online! That being said, this also doesn't appear to perform the required input validation. If validation is too clunky, feel free to keep a non-validating version as well, so long as you mark it as such. Also I'm not entirely sure that that snippet is a valid submission, but you save two more bytes by making it a named function. \$\endgroup\$ Nov 19 '20 at 23:28
0
\$\begingroup\$

K, 44

{$[=/x in\:a:.Q.a,.Q.A;+/(a!,/2#,1+!26)x;`]}

Returns ` for any non alphabetic input

\$\endgroup\$
0
\$\begingroup\$

VBA 120

Sub s(t)
For i=1 To Len(t)
a=Asc(Mid(t,i,1))-64
a=IIf(a>32,a-32,a)
If a<1 Or a>26 Then Print
b=b+a
Next
MsgBox b
End Sub

Print does not cause a compile-time error, though the syntax is invalid, which causes an exception to be thrown and the program to exit if, and only if, the character is not an upper- or lower-case letter.

\$\endgroup\$
0
\$\begingroup\$

C, 97 Chars

int r(c*z){int x=0;while(*z){char w=tolower(*(z++));if(w<96|w>122)return-1;x+=w-96;}return x;}

It returns -1 if there's an invalid character.

\$\endgroup\$
0
\$\begingroup\$

Perl (42 31)

perl -F -pale '$c+=ord(uc$_)-64for@F;$_=$c'

I hope counting F, p, a and l as 1 character was correct.

\$\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.