[Question]
  [
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](https://codegolf.stackexchange.com/questions/1128/my-word-can-beat-up-your-word),' but much simpler.
  
[Answer]
## Ruby, 43 characters
```
$_=gets.upcase;p~/[^A-Z]/?_: $_.sum-64*~/$/
```
The error message this generates isn't exactly helpful, though.
Both solutions posted here assume the input has no trailing linebreak, so to test them, use `echo -n`.
## Ruby, 76 characters with dictionary check
```
l=STDIN.gets;$_=l.upcase;p~/[^A-Z]/?_: $_.sum-64*~/$/;[*$<].index(l)||$><<?W
```
The warning message consists of the single character "W". The path to the dictionary has to be supplied via ARGV. Example usage:
```
$ echo -n asd | ruby addletters.rb /usr/share/dict/words
24
W
$ echo -n cat | ruby addletters.rb /usr/share/dict/words
24
```
[Answer]
## Golfscript - 23 chars
```
0\{.31&.(.26%=@64///+}/
```
Ensure there are no trailing newlines in input (e.g. use `echo -n`).
[Answer]
# Python (65 64)
```
print sum(['',ord(i)-64]['@'<i<'[']for i in raw_input().upper())
```
This raises an error if the word contains non-letter characters, but not a helpful or informative one. (Edit: tip of the hat to st0le for the indexing trick.)
[Answer]
# Python 2.6 (72 Chars) Without dictionary check
```
print sum(map(" abcdefghijklmnopqrstuvwxyz".index, raw_input().lower()))
```
# Python 2.6 (178 Chars\*) With dictionary check
```
w=raw_input().lower()
print sum(map(" abcdefghijklmnopqrstuvwxyz".index, w))
if w not in open('/usr/share/dict/american-english').read().split():
 print('Word not in dictionary')
```
\*Can be lowered to 156 with a less helpful error message. :-)
Thanks to all commenters for helping improve this.
[Answer]
## Python (80)
```
w=raw_input().lower()
s=0
for l in w:s+=range(97,123).index(ord(l))+1
print s
```
## Python v2 (65 but char ` will get accepted)
```
print sum(map(range(96,123).index,map(ord,raw_input().lower())))
```
## v3 (60 chars, @ will be accepted but not counted, thanks jloy)
```
print sum(map(range(64,91).index,map(ord,input().upper())))
```
[Answer]
## Scala: 59 chars, 7 of them payload, no dict:
```
(0/:"Payload".map(c=>if(c.isLetter)(c-'A')%32 else-999))(_+_)
67
```
No dictionary so far. Negative result means: Negative!
```
(0/:"Pay!wall?".map(c=>if(c.isLetter)(c-'A')%32 else-999))(_+_)   
-1915
```
Handles German Umlaute gracefully, by the way:
```
(0/:"Müllrößchen".map(c=>if(c.isLetter)(c-'A')%32 else-999))(_+_)
155
```
[Answer]
# Java + Google Guava libraries, 347 characters, with dictionary check
**Unreadable 1 long string version :-)**
```
import java.io.*;import com.google.common.base.*;import com.google.common.io.*;class C{public static void main(String[]a)throws Exception{int s=0;for(int c:a[0].toUpperCase().toCharArray()){assert(c>64&&c<91);s+=c-64;}String d=Files.toString(new File(a[1]),Charsets.UTF_8);if(StringUtils.containsIgnoreCase(d,a[0]))System.out.println("w");System.out.println(s);}}
```
**Human-readable version (sort of :-))**
```
import java.io.*;
import com.google.common.base.*;
import com.google.common.io.*;
class C {
    public static void main(String[] a) throws Exception {
        int s=0;
        for(int c : a[0].toUpperCase().toCharArray()) {
            System.out.println(c);
            assert(c > 64 && c < 91);
            s += c - 64;
        }
        String d = Files.toString(new File(a[1]), Charsets.UTF_8);
        if (d.contains(a[0])) System.out.println("w");
        System.out.println(s);
    }
}
```
The dictionary path is now passed in via `a[1]`, for assertions to work you have to use the `-ea`flag (+3 more chars). As for the dictionary, the dict `/usr/share/dict/words` (should be available on most \*nix systems) has been used.
[Answer]
## Python 3, 95 chars with dictionary
```
d=input().lower()
print(d in open("d").read()and sum(['',ord(c)-96]['`'<c<'{']for c in d)or'f')
```
The dictionary has to be in a file called d.
### Python 3, 61 without dictionary, but stolen idea
```
print(sum(['',ord(c)-96]['`'<c<'{']for c in input().lower()))
```
[Answer]
# VB.NET, ~~84~~ ~~82~~ ~~73~~ 71
```
Console.Write(Console.ReadLine.Sum(Function(c)Asc(Char.ToUpper(c))-64))
```
  
**Edit:** With validation is:
```
Dim r=Console.ReadLine
Console.Write(If(r.All(AddressOf Char.IsLetter),r.Sum(Function(c)Asc(Char.ToUpper(c))-64),"Invalid input."))
```
129 characters. In which case:
# C#, 118
```
var r=Console.ReadLine();Console.Write(r.All(char.IsLetter)?r.Sum(c=>char.ToUpper(c)-64).ToString():"Invalid input.");
```
[Answer]
# Improving slightly on John's answer: Python (90)
```
s=0
for i in raw_input().lower():
 s+=("abcdefghijklmnopqrstuvwxyz".index(i)+1)
print(s)
```
[Answer]
# **Erlang, 104**
```
a()->
a(string:to_lower(io:get_line([])),0).
a([_|[]],S)->
S;
a([C|R],S) when C<${, C>=$`->
a(R,S+C-$`).
```
[Answer]
## Perl (52) (48)
golfed even more thanks to [Timwi](https://codegolf.stackexchange.com/users/668/timwi)
`perl -lpe "($w=uc)=~/[^A-Z]/&&die;$w=~s/./$_-=64-ord$&/ge"`
[Answer]
**Golfscript - 39 chars**
```
n%~{.96>{96}{64}if-..26>\0<|{0/}*}%{+}*
```
The error it throws is not exactly the best, but hey, it aborts execution.
[Answer]
## PYTHON ~~62~~ 68\* Characters
```
print sum(map(chr,range(65,91)).index(c)+1 for c in input().upper())
```
Requires user to input strings using quotes, and is not safe (`input` executes code), but, as I said in a comment to another post, "user-friendly" and "not a security risk" ain't in the spec!
---
\* I forgot about `print`, dammit.
[Answer]
# [Husk](https://github.com/barbuz/Husk), 17 bytes
```
?osṁo%32c¹¨eŻ→¨Λ√
```
[Try it online!](https://tio.run/##yygtzv6f@6ip8b99fvHDnY35qsZGyYd2HlqRenT3o7ZJh1acm/2oY9b///@jlZITS5R0lJwdQ4CkoZExkFRW1FKKBQA "Husk – Try It Online")
Returns 'error' for invalid input, score of word otherwise.
```
?              Λ√       # if every element is a letter
 os                     # return the string of
   ṁ    c¹              # the sum of all their ASCII values
    o%32                # MOD 32
          ¨eŻ→¨         # otherwise, return the compressed string
                        # "error"
```
---
If it's acceptable to return '0' as the 'error' for invalid input, we can have a ~~11 byte~~ ~~10 byte~~ [9 byte](https://tio.run/##yygtzv6f@6ip8f@h5WoPdzaqGhudW5D7qGPW////o5WSE0uUdJScHUOAZKKhkTGQUlbUUooFAA) solution:
```
§&ṁ%32Πm√
```
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), 15 bytes
```
lvAyk>})D0åi0ëO
```
[Try it online!](https://tio.run/##yy9OTMpM/f8/p8yxMtuuVtPF4PDSTIPDq/3//09OLAEA "05AB1E – Try It Online") Returns `0` on error.
```
lvAyk>})D0åi0ëO  # full program
 v               # for y in...
                 # implicit input...
l                # lowercased...
    k            # push 0-based index of...
   y             # y...
    k            # in...
  A              # the lowercase alphabet...
    k            # or -1 if not found...
     >           # plus 1
      }          # end loop
           i     # if...
         0       # 0...
          å      # is in...
       )         # stack...
            0    # push 0
             ë   # else...
              O  # push sum...
        D        # of stack
                 # implicit output
```
[Answer]
## Ruby 1.9, 69
```
w=gets.chop.upcase
w[/[^A-Z]/]&&fail
p w.bytes.inject(0){|s,b|s+b-64}
```
[Answer]
## Perl (71)
```
($a)=lc<>;$a=~/[^a-z]/i&&die;$x+=ord$_ for split//,$a;die$x-96*length$a;
```
[Answer]
# GolfScript, 50(53)
Gives an error on bad characters, but not a very good one (50 characters):
```
);[{""123,97>+91,65>+?}/].-1?0<{{26%1+}%{+}*}{@}if
```
Gives "E" on error instead (53 characters):
```
);[{""123,97>+91,65>+?}/].-1?0<{{26%1+}%{+}*}{;"E"}if
```
The alphabet-generating snippet `123,97>+` is stolen from Ventero .
[Answer]
# J (55)
```
+/64-~-&32`]@.(<&97)`_:@.(<&65)`_:@.(>&122)"0,I.a.&e."0
```
This satisfies all the conditions except the dictionary one. As an error condition, it returns "infinity" (the underscore symbol in J) for words that contain anything but letters.
[Answer]
# Haskell (127)
(raises an error on weird characters)   
(also: the space between `toUpper.` and `\x` is needed otherwise it parses it as`(toUpper)` `.\` `(x)`)
```
import Char
main=getLine>>=putStrLn.show.sum.(map$(-65+).ord.toUpper. \x->if x`elem`['A'..'Z']++['a'..'z']then x else error"")
```
# Haskell (70)
(does not raise an error, but 45% shorter)
```
import Char
main=getLine>>=putStrLn.show.sum.(map$(-65+).ord.toUpper)
```
[Answer]
## C++ (~~111~~ 107)
```
void main(){int a=0;s8*b=new s8[99];for(cin>>b;*b;)if(isalpha(*b))a+=tolower(*b++)-96;else return;cout<<a;}
```
---
The "set up"/etc:
```
#include <iostream>
#include <cstdio>
#include <cctype>
#ifdef _MSC_VER
    typedef __int8 s8;
#else
    typedef signed char s8;
#endif
```
---
["Undefined" behavior](http://meta.codegolf.stackexchange.com/q/21/761) (It's more 'bad practice' than 'undefined', but oh well):
* `void main()` That says it all.
* I'm using `new` without `delete`.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~10~~ 9 bytes
```
ŒuØAiⱮoµS
```
[Try it online!](https://tio.run/##y0rNyan8///opNLDMxwzH21cl39oa/D///@VnBNLlAA "Jelly – Try It Online")
Seemingly, it turns out a byte shorter to actually error than to return 0.
```
Œu           Uppercase the input,
    i        find the index (or 0 if not found)
     Ɱ       of each letter from the input
  ØA         in "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
      o      replace any 0 with the corresponding character of the input,
       µS    then take the sum.
```
Jelly errors if it attempts to add integers and strings together, and although two strings can be added together by `+`, this still errors in the case of a fully symbolic input because `S` is defined specifically as a reduce starting from zero.
[Answer]
## JavaScript 1.8, 80 chars
Surprisingly readable!
```
alert(Array.reduce(prompt().toLowerCase(),function(a,b)a+b.charCodeAt(0)-96,0))
```
[Answer]
## APL (34)
```
+/{⍵∊⍳26:⍵}¨{64-⍨A-32×96<A←⎕UCS⍵}⍞
```
Gives either the score, or a `VALUE ERROR` if there are non-alphabetic characters in the input.
Explanation:
* `⍞`: read a line of input
* `{`...`}`: function applied to every character of input
* `A←⎕UCS⍵`: store the ASCII value of the current character in `A`
* `A-32×96<A`: make character uppercase: from `A` is subtracted 32 if `96<A` (so, if it's uppercase), otherwise 0
* `64-⍨`: subtract 64 from this, giving A=1, B=2 ...
* `¨`: apply this function to every character:
* `⍵∊⍳26`: if the character is between 1 and 26...
* `:⍵`: then return ⍵ (and since there's no else clause there will be a `VALUE ERROR` if it's not between 1 and 26)
* `+/`: sum all the values together (and this value is automatically outputted because it's the final result).
[Answer]
# JavaScript, 60 bytes
```
s=>[...s.toUpperCase()].reduce((a,b)=>a+b.charCodeAt()-64,0)
```
If the program **must** return an error on invalid inputs, then 80 bytes:
```
s=>/[^a-z]/i.test(s)?_:[...s.toUpperCase()].reduce((a,b)=>a+b.charCodeAt()-64,0)
```
If an input is invalid, then the console will say that `_` is not defined (there must not already be a variable defined called `_`).
[Answer]
# Python 3, ~~58~~ 55
```
print(sum(ord(x)%32for x in input()if x.isalpha()or z))
```
without dictionary or stolen idea but still unhelpful error ;)
thx @Eᴀsᴛᴇʀʟʏ
Test [here](https://repl.it/CO5q/1).
[Answer]
# C, 98 bytes
```
 int a(char *s){int b=0;while(*s){if(!isalpha(*s))throw 1;b+=(toupper(*(s++))-64);}printf("%d",b);}
```
[Answer]
# F# (no validation) 79 57 chars
```
let a w=w|>Seq.fold(fun a b->a+(int b)-65)0|>printfn"%i"
```
[Answer]
# C# with validation: 108 chars (with 12 for error message):
```
var s=Console.ReadLine();Console.Write(s.All(Char.IsLetter)?s.Sum(x=>x&'_'-'@').ToString():"Invalid input");
```
# C# without validation: 60 53 chars:
```
Console.Write(Console.ReadLine().Sum(x=>x&'_'-'@'));
```
]