[Question]
  [
According to [this site](http://grammar.yourdictionary.com/capitalization/rules-for-capitalization-in-titles.html#8Xf7g96YSUq87kkL.99) a general rule recommended by *The U.S. Government Printing Office Style Manual* is
> 
> Capitalize all words in titles of publications and documents, except
>  a, an, the, at, by, for, in, of, on, to, up, and, as, but, or, and
>  nor.
> 
> 
> 
This might not be true as I'm unable to find such a recommendation in the [Style Manual](https://www.gpo.gov/fdsys/search/pagedetails.action?granuleId=&packageId=GPO-STYLEMANUAL-2008), but let's use this rule anyway.
---
**The Challenge** 
Given an input string consisting of lower case words delimited by spaces, output the capitalization of the string according to the following rules
* The first and last word is capitalized.
* All other words are capitalized, except *a*, *an*, *the*, *at*, *by*, *for*, *in*, *of*, *on*, *to*, *up*, *and*, *as*, *but*, *or*, and *nor*.
The input string will contain at least one word and each word contains at least one letter and only characters from `a` to `z`.
This is a code golf challenge, so try to use as few bytes as possible in the language of your choice. You may write a full program or a function to accomplish the task.
**Testcases**
```
"the rule of thumb for title capitalization" -> "The Rule of Thumb for Title Capitalization"
"programming puzzles and code golf" -> "Programming Puzzles and Code Golf"
"the many uses of the letter a" -> "The Many Uses of the Letter A"
"title" -> "Title"
"and and and" -> "And and And"
"a an and as at but by for in nor of on or the to up" -> "A an and as at but by for in nor of on or the to Up"
"on computable numbers with an application to the entscheidungsproblem" -> "On Computable Numbers With an Application to the Entscheidungsproblem"
```
  
[Answer]
## Python 2, 118 bytes
Look ma, no regex!
```
for w in`input()`.split():print[w.title(),w][`w`in"'a'an'and'as'at'the'by'but'for'nor'in'of'on'or'to'up'"].strip("'"),
```
Input must be wrapped in quotes. Output has a trailing space and no trailing newline (I assume that's okay). [Verify all test cases on Ideone](http://ideone.com/zgCcW9).
### Explanation
Let's take the input `a or an` as our example.
Using Python 2's ``x`` shortcut for `repr`, we wrap the input in single quotes: `'a or an'`. Then we split on whitespace and iterate over the words.
Inside the loop, we take the `repr` *again*. For the first and last words, this gives `"'a"` and `"an'"`. For other words, it gives `'or'`. We want to avoid capitalizing words if they fit the latter pattern and are in the short-words list. So we can represent the word list as the string `"'a'an'...'up'"` and know that the `repr` of any short word will be a substring.
``w` in "..."` gives a boolean value, which we can treat as `0` or `1` for the purposes of indexing into the list `[w.title(), w]`. In short, we title-case the word if it is at the beginning, at the end, or not in the list of short words. Otherwise, we leave it alone. Fortunately, `title()` still works as expected with input like `'a`.
Finally, we strip any single quotes from the word and print it with a trailing space.
[Answer]
# [05AB1E](http://github.com/Adriandmen/05AB1E), ~~68~~ 61 bytes
Saved 7 bytes thanks to *Adnan*
```
™ð¡Dg<UvyN__NXQ_“a€¤€€€›€‹€‡€†€‚€‰€„€¾€ƒ€œ€³€—š¯“#™yå&&il})ðý
```
[Try it online!](http://05ab1e.tryitonline.net/#code=4oSiw7DCoURnPFV2eU5fX05YUV_igJxh4oKswqTigqzigqzigqzigLrigqzigLnigqzigKHigqzigKDigqzigJrigqzigLDigqzigJ7igqzCvuKCrMaS4oKsxZPigqzCs-KCrOKAlMWhwq_igJwj4oSiecOlJiZpbH0pw7DDvQ&input=dGhlIHJ1bGUgb2YgdGh1bWIgZm9yIHRpdGxlIGNhcGl0YWxpemF0aW9u)
**Explanation**
`“a€¤€€€›€‹€‡€†€‚€‰€„€¾€ƒ€œ€³€—š¯“` is a dictionary string translated as `a an the at by for in of on to up and as but or nor`.
```
™                          # title case input string
ð¡                         # split on spaces
Dg<U                       # store index of last word in X
vy                         # for each word
  N__                      # is it not first index?
     NXQ_                  # is it not last index
         “...“             # the compressed string 
              #            # split on spaces
               ™           # convert to title case
                yå         # is current word in this list?
                  &&       # and the 3 previous conditions together
                    il     # if all are true, convert to lower case
                      }    # end loop
)ðý                        # wrap stack in list and join by spaces
```
[Answer]
# GNU sed ~~81 74~~ 73 Bytes
Includes +1 for -r
```
s/\b./\u&/g
:;s/.(And?|A[st]?|The|By|But|[FN]or|In|O[fnr]|To|Up) /\L&/;t
```
The first line capitalizes the first letter of every word. The second switches all of the required words back to lowercase.
[Try it Online!](http://sed.tryitonline.net/#code=cy9cYi4vXHUmL2cKOjtzLy4oQW5kP3xBW3N0XT98VGhlfEJ5fEJ1dHxbRk5db3J8SW58T1tmbnJdfFRvfFVwKSAvXEwmLzt0&input=dGhlIHJ1bGUgb2YgdGh1bWIgZm9yIHRpdGxlIGNhcGl0YWxpemF0aW9uCnByb2dyYW1taW5nIHB1enpsZXMgYW5kIGNvZGUgZ29sZgp0aGUgbWFueSB1c2VzIG9mIHRoZSBsZXR0ZXIgYQp0aXRsZQphbmQgYW5kIGFuZAphIGFuIGFuZCBhcyBhdCBidXQgYnkgZm9yIGluIG5vciBvZiBvbiBvciB0aGUgdG8gdXAKb24gY29tcHV0YWJsZSBudW1iZXJzIHdpdGggYW4gYXBwbGljYXRpb24gdG8gdGhlIGVudHNjaGVpZHVuZ3Nwcm9ibGVtCmEgYSBh&args=LXI)
[Answer]
# Retina, ~~69~~ 66 bytes
Capitalize the first letter of every word, then change the selected words to lowercase if they're not the first or last word. There's a space at the end of the last line.
```
T`l`L`\b.
+T`L`l` (And?|A[st]?|The|By|But|[FN]or|In|O[fnr]|To|Up) 
```
[**Try it online**](http://retina.tryitonline.net/#code=VGBsYExgXGIuCitUYExgbGAgKEFuZD98QVtzdF0_fFRoZXxCeXxCdXR8W0ZOXW9yfElufE9bZm5yXXxUb3xVcCkg&input=dGhlIHJ1bGUgb2YgdGh1bWIgZm9yIHRpdGxlIGNhcGl0YWxpemF0aW9uCnByb2dyYW1taW5nIHB1enpsZXMgYW5kIGNvZGUgZ29sZgp0aGUgbWFueSB1c2VzIG9mIHRoZSBsZXR0ZXIgYQp0aXRsZQphbmQgYW5kIGFuZAphIGFuIGFuZCBhcyBhdCBidXQgYnkgZm9yIGluIG5vciBvZiBvbiBvciB0aGUgdG8gdXAKb24gY29tcHV0YWJsZSBudW1iZXJzIHdpdGggYW4gYXBwbGljYXRpb24gdG8gdGhlIGVudHNjaGVpZHVuZ3Nwcm9ibGVt)
This also works with a `.` instead of the first space.
There are a lot of regexes with the same length, but I can't find a way to trim it anymore...
[Answer]
## JavaScript (ES6), ~~141~~ ~~138~~ ~~135~~ 133 bytes
*Saved 3 bytes thanks to mbomb007*
```
s=>s.replace(/(\w+)( ?)/g,(a,w,n,i)=>i&&n&&/^(a[nst]?|the|by|in|of|on|to|up|and|but|[fn]?or)$/.exec(w)?a:a[0].toUpperCase()+a.slice(1))
```
### Test cases
```
let f =
s=>s.replace(/(\w)(\w*)( ?)/g,(a,l,w,n,i)=>i&&n&&/^(a[nst]?|the|by|in|of|on|to|up|and|but|[fn]?or)$/.exec(l+w)?a:l.toUpperCase()+w+n)
console.log(f("the rule of thumb for title capitalization"));
console.log(f("programming puzzles and code golf"));
console.log(f("the many uses of the letter a"));
console.log(f("title"));
console.log(f("and and and"));
console.log(f("a an and as at but by for in nor of on or the to up"));
console.log(f("on computable numbers with an application to the entscheidungsproblem"));
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 58 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’b26ịØaṣ”z
e€¢¬T;2Ḷ¤
ḲŒtÇ¦K
```
**[TryItOnline!](http://jelly.tryitonline.net/#code=4oCcw5Av4bmDxofCrMO-4bmE4bqKxpnigqws4oG94bmZxqzCrk_huapKIsmmM8OXa2Yz4bmYw6clxKF14oCZYjI24buLw5hh4bmj4oCdegpl4oKswqLCrFQ7MuG4tsKkCuG4ssWSdMOHwqZL&input=&args=dGhlIG1hbnkgdXNlcyBvZiB0aGUgbGV0dGVyIGE)** or [run all tests](http://jelly.tryitonline.net/#code=4oCcw5Av4bmDxofCrMO-4bmE4bqKxpnigqws4oG94bmZxqzCrk_huapKIsmmM8OXa2Yz4bmYw6clxKF14oCZYjI24buLw5hh4bmj4oCdegpl4oKswqLCrFQ7MuG4tsKkCuG4ssWSdMOHwqZLCsOH4oKsWQ&input=&args=WyJ0aGUgcnVsZSBvZiB0aHVtYiBmb3IgdGl0bGUgY2FwaXRhbGl6YXRpb24iLCJwcm9ncmFtbWluZyBwdXp6bGVzIGFuZCBjb2RlIGdvbGYiLCJ0aGUgbWFueSB1c2VzIG9mIHRoZSBsZXR0ZXIgYSIsInRpdGxlIiwiYW5kIGFuZCBhbmQiLCJhIGFuIGFuZCBhcyBhdCBidXQgYnkgZm9yIGluIG5vciBvZiBvbiBvciB0aGUgdG8gdXAiLCJvbiBjb21wdXRhYmxlIG51bWJlcnMgd2l0aCBhbiBhcHBsaWNhdGlvbiB0byB0aGUgZW50c2NoZWlkdW5nc3Byb2JsZW0iXQ)
### How?
A compressed string with spaces separating the words would be `47` bytes, splitting it costs `1` byte, for `48` bytes.
Two unseparated compressed strings of the words of length `2` and `3` (with an 'a' on the end of one) respectively would be `40` bytes plus `2` to split each and `1` to join them, for `45` bytes.
One base 250 number as described below is `32` bytes, then `3` to convert to base 26, `3` to index into the lowercase alphabet and `3` to split it on the unused character, `'z'`, for `41` bytes.
So, the lookup for the words not to capitalise:  
`“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’`  
was formed like so:
Take those words and join them with a separator:  
`s="a an the at by for in of on to up and as but or nor"`
Next label `'a'` as `1`, `'b'` as `2` with the separator as `0`:
```
alpha = ' abcdefghijklmnopqrstuvwxyz'
x = [alpha.index(v) for v in s]
x
[1,0,1,14,0,20,8,5,0,1,20,0,2,25,0,6,15,18,0,9,14,0,15,6,0,15,14,0,20,15,0,21,16,0,1,14,4,0,1,19,0,2,21,20,0,15,18,0,14,15,18]
```
Convert this into a base `26` number (the last letter used is `'y'` plus a digit for the separator, Python code for this is:  
`n=sum(v*26**i for i,v in enumerate(x[::-1]))`
Convert that into a base `250` number (using a list for the digits):
```
b=[]
while n:
    n,d = divmod(n,250)
    b=[d]+b
b
[16,48,220,145,8,32,202,209,162,13,45,142,244,153,9,80,207,75,35,161,52,18,108,103,52,205,24,38,237,118]
```
Lookup the characters at those indexes in jelly's codepage:
```
codepage = '''¡¢£¤¥¦©¬®µ½¿€ÆÇÐÑ×ØŒÞßæçðıȷñ÷øœþ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~¶°¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾ƁƇƊƑƓƘⱮƝƤƬƲȤɓƈɗƒɠɦƙɱɲƥʠɼʂƭʋȥẠḄḌẸḤỊḲḶṂṆỌṚṢṬỤṾẈỴẒȦḂĊḊĖḞĠḢİĿṀṄȮṖṘṠṪẆẊẎŻạḅḍẹḥịḳḷṃṇọṛṣṭụṿẉỵẓȧḃċḋėḟġḣŀṁṅȯṗṙṡṫẇẋẏż«»‘’“”'''
r=''.join(codepage[i-1] for i in b)
r
'Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu'
```
(note: since the actual implementation is bijective, if `b` had any `0` digits one would need to carry down first)
The rest:
```
ḲŒtÇ¦K - Main link: title string
Ḳ      - split on spaces
    ¦  - apply to indexes
   Ç   -     given by calling the last link (1) as a monad (with the split title string)
 Œt    -     title case (first letter of each (only) word to upper case)
     K - join on spaces
e€¢¬T;2Ḷ¤ - Link 1, find indexes to capitalise: split title string
e€        - is an element of, for €ach
  ¢       - the result of calling the last link (2) as a nilad
   ¬      - logical not
    T     - get the truthy indexes (indexes of words that are not in the list)
     ;    - concatenate with
        ¤ - nilad followed by link(s) as a nilad
      2Ḷ  - range(2) -> [0,1]
                (we always want to capitalise the first index, 1, and the last index, 0)
“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’b26ịØaṣ”z - Link 2, make the word list: no arguments
“Ð/ṃƇ¬þṄẊƙ€,⁽ṙƬ®OṪJ"ɦ3×kf3Ṙç%ġu’          - the base 250 number
                                b26       - convert to base 26
                                   ị      - index into
                                    Øa    - lowercase alphabet
                                      ṣ   - split on
                                       ”z - literal 'z' (the separator 0 indexes into `z`)
```
[Answer]
# PHP, 158 Bytes
10 Bytes saved by [@Titus](https://codegolf.stackexchange.com/users/55735/titus)
```
foreach($w=explode(" ",$argv[1])as$k=>$v)echo" "[!$k],$k&&$k+1<count($w)&&preg_match("#^(a[snt]?|and|[fn]or|up|by|but|the|to|in|o[rnf])$#",$v)?$v:ucfirst($v);
```
Previous version PHP, 174 Bytes
```
foreach($w=explode(" ",$argv[1])as$k=>$v)$k&&$k+1<count($w)&&in_array($v,[a,an,the,at,by,"for",in,of,on,to,up,"and","as",but,"or",nor])?:$w[$k]=ucfirst($v);echo join(" ",$w);
```
[Answer]
# TI-Basic, 295 + 59 + 148 = 502 bytes
*Now you can capitalize on your calculator. Great for school :)*
**Main Program, 295 bytes**
Basically, the trick to matching words so all `A` don't become `a` is to enclose with spaces, such as replace `" A "` with `" a "`. This also automatically makes it so that the first and last words stay capitalized, because they do not have a space on both sides and will thus not match any of the words. (Genius, right? And super long because lowercase letters are two bytes each...)
```
"("+Ans+")→Str1
"@A ~ a@An ~ an@The ~ the@At ~ at@By ~ by@For ~ for@In ~ in@Of ~ of@On ~ on@To ~ to@Up ~ up@And ~ and@As ~ as@But ~ but@Or ~ or@Nor ~ nor@→Str2
For(I,2,length(Ans
If "@"=sub(Str2,I-1,1
Then
" "+Str1+"~"+sub(Str2,I,inString(Str2,"@",I)-I)+" "
prgmQ
Ans→Str1
End
End
```
**Subprogram (`prgmQ`), 59 bytes:**
```
Ans→Str9
inString(Ans,"~
sub(Str9,Ans,length(Str9)-Ans+1→Str8
Str9
prgmR
Repeat Str9=Ans+Str8
Ans+Str8→Str9
prgmR
End
```
**Subprogram (`prgmR`), 148 bytes:**
```
Ans→Str0
inString(Ans,"~→Z
inString(Str0,"~",Ans+1→Y
inString(sub(Str0,1,Z-1),sub(Str0,Z+1,Ans-Z-1→X
sub(Str0,1,-1+inString(Str0,"~
If X
sub(Str0,1,X-1)+sub(Str0,Y+1,length(Str0)-Y)+sub(Str0,X+length(sub(Str0,Z+1,Y-Z-1)),Z-X-length(sub(Str0,Z+1,Y-Z-1
```
P.S. `~` represents token `0x81` and `@` represents token `0x7F`, learn more [here](http://tibasicdev.wikidot.com/one-byte-tokens).
[Answer]
# Java 7, ~~271~~ ~~259~~ 258 bytes
```
String c(String x){String a[]=x.split(" "),s=" ",r=w(a[0])+s;for(int i=0,l=a.length-1;i<l;r+=(!s.matches("^(a[nst]?|the|by|in|of|on|to|up|and|but|[fn]?or)$")|i==l?w(s):s)+" ")s=a[++i];return r;}String w(String w){return(char)(w.charAt(0)-32)+w.substring(1);}
```
**Ungolfed & test code:**
[Try it here.](https://tio.run/nexus/java-openjdk#hVJNj5swEL3vr5iiHmyRomx7W4qi/oCc9ohYyRADlvyB7HHZJM5vTweWnrFkzch@8@bNszstQoDz/fmOXtkBOrYln/y@ZaJuqs8iTFohyyDjh1BROPhqZqI@NjwPZe88UxZBVceDrkShpR1w/PFaqt@69HnFvoXCCOxGGVj2QWU2YHNKOMrUXpOyyfXJ2YQuxSkJe0ltxFT3tjk5z79nPKmq0qeZBf4WeL6ICJWo81w1pZcYvQVfPja58/8JZn7/umTdKDxnc7HEP8iO/OPXT57PRYhtWLHslZePJ8AUW606CCiQwl@nLmCEshtj3YDg9xegdQYDFVg5w5nxcj16vwaUpnARi4nQqC0zRccyGhJ81BJcDzhG0wK5BaiQjjoxKRRa3aifsxnfoZq8G7wwZpluireblgHILejcRcLgdL/LsIgxwl4hBqpdFUnQElF6EPvVi@hd1KJo2/tYQn2BaRIEenZor6tByoKlQBKdhcUwEooO4rTLSfjOmSmiaMliS45LH2BWOK7NJvrI3er3wrfQSouBvqa6RDsE8pjKzNbl8fJ4/gM)
```
class M{
  static String c(String x){
    String a[] = x.split(" "),
           s = " ",
           r = w(a[0]) + s;
    for(int i = 0, l = a.length-1; i < l; r += (!s.matches("^(a[nst]?|the|by|in|of|on|to|up|and|but|[fn]?or)$") | i == l
                                                 ? w(s)
                                                 : s)   + " "){
      s = a[++i];
    }
    return r;
  }
  static String w(String w) {
    return (char)(w.charAt(0) - 32) + w.substring(1);
  }
  public static void main(String[] a){
    System.out.println(c("the rule of thumb for title capitalization"));
    System.out.println(c("programming puzzles and code golf"));
    System.out.println(c("the many uses of the letter a"));
    System.out.println(c("title"));
    System.out.println(c("and and and"));
    System.out.println(c("a an and as at but by for in nor of on or the to up"));
    System.out.println(c("on computable numbers with an application to the entscheidungsproblem"));
  }
}
```
**Output:**
```
The Rule of Thumb for Title Capitalization 
Programming Puzzles and Code Golf 
The Many Uses of the Letter A 
Title 
And and And 
A an and as at but by for in nor of on or the to Up 
On Computable Numbers With an Application to the Entscheidungsproblem 
```
[Answer]
# Groovy, 131 129
Two bytes saved thanks to carusocomputing
```
{it.split()*.with{a->a in "a an the at by for in of on to up and as but or nor".split()?a:a.capitalize()}.join(" ").capitalize()}
```
[Answer]
## C#, 305 bytes
Lots of room for improvement still but here you go:
```
s=>{;var b=s.Split(' ');b[0]=((char)(b[0][0]-32))+b[0].Substring(1);int i=0,n=b.Length;for(;++i<n;)if(!"a,an,the,at,by,for,in,of,on,to,up,and,as,but,or,nor".Split(',').Contains(b[i]))b[i]=((char)(b[i][0]-32))+b[i].Substring(1);b[n-1]=((char)(b[n-1][0]-32))+b[n-1].Substring(1);return string.Join(" ",b);};
```
[Answer]
# Ruby, ~~123~~ ~~117~~ ~~111~~ 102 bytes
```
->s{s.gsub(/ .|^./,&:upcase).gsub(/ (A[nts]?|The|By|In|To|Up|And|But|[NF]or|O[rnf])(?= )/,&:downcase)}
```
Sorry for all the edits - this should be the last one.
[Answer]
# Python, 177 bytes
Delivered in function format for byte saving purposes. This is not an especially competitive answer, but it is one that doesn't require `repr()` or `regex` trickery. It is also version-agnostic; it works with Python 2 or 3.
Though it is perhaps a very by-the-rules solution.
```
def t(s):
 w="a an the the at by for in of on to up and as but or nor".split()
 l=[(s.title(),s)[s in w]for s in s.split()]
 for x in(0,-1):l[x]=l[x].title()
 return' '.join(l)
```
[Answer]
# PHP, ~~109~~ 142 bytes
```
<?=preg_replace_callback("# (A[snt]?|And|[FN]or|Up|By|But|The|To|In|O[rnf])(?= )#",function($m){return strtolower($m[0]);},ucwords($argv[1]));
```
A merger of [user59178´s](https://codegolf.stackexchange.com/a/97669#97669) and [mbomb007´s](https://codegolf.stackexchange.com/a/97573#97573) answer.
uppercases the first letter of every word, then lowercases all words from the list surrounded by spaces.  
Unfortunately, the callback has to operate on the complete set; this costs 29 bytes.
[Answer]
## Racket 353 bytes
```
(define(cap i)(set! i(string-append i))(define c(string-ref i 0))(string-set! i 0(if(char-upper-case? c)c(integer->char(-(char->integer c)32))))i)
(let*((ex(list"a""an""the""at""by""for""in""of""on""to""up""and""as""but""or""and""nor"))(sl(string-split s)))
(string-join(for/list((i sl)(n(in-naturals)))(cond[(= n 0)(cap i)][(member i ex)i][(cap i)]))))
```
Ungolfed: 
```
(define (f s)
  (define (cap i)                 ; sub-fn to capitalize first letter of a word
    (set! i (string-append i))
    (define c (string-ref i 0))
    (string-set! i 0
                 (if (char-upper-case? c)
                     c
                     (integer->char (-(char->integer c)32))))
    i)
  (let* ((ex (list "a""an""the""at""by""for""in""of""on""to""up""and""as""but""or""and""nor"))
         (sl (string-split s)))
    (string-join
     (for/list
         ((i sl)
          (n (in-naturals)))
       (cond
         [(= n 0) (cap i)]
         [(member i ex) i]
         [(cap i)]
         )))))
```
Testing: 
```
(f "the rule of thumb for title capitalization")
```
Output: 
```
"The Rule of Thumb for Title Capitalization"
```
[Answer]
# Java 7, ~~431 317~~ 311 bytes
*Thanks to @KevinCruijssen for **114** bytes.*
  
*Thanks to @RosLup for saving **6** bytes.*
```
String c(String s){String v="",x,l[]=s.split(" "),b[]={"a","an","the","at","but,"by","for","in","of","on","to","‌​up","as","or","and","nor"};int i=0,f=0,z=0;for(String c:l){for(f=0;f<b.length;z=c.equals(b[f++])|z>0?1:0);x=(char)(c.charAt(0)-32)+c.substring(1);v+=(z>0?i<1|i>l.length-2?x:c:x)+" ";i++;}return v;}
```
# ungolfed
first answer above 250 bytes
```
 static String c(String s) {
      String v = "", x, l[] = s.split(" "),
b[]={"a","an","the","at","by","for","in","of","on","to",
                                         "‌​up","and","as","or","nor","but"};
    int i , f , z = i = f = 0;
    for (String c : l) {
   for (f = 0; f < b.length; z = c.equals( b[f++] ) | z > 0 ? 1 : 0);
        x = (char)(c.charAt(0) - 32) + c.substring(1);
        v += (z > 0 ? i < 1 | i > l.length - 2 ? x : c : x) + " ";
        i++;
   }
    return v;
    }
```
[Answer]
# PHP, ~~117~~ ~~118~~ 112 bytes
```
<?=strtr(ucwords(preg_replace("# (?=(a[snt]?|and|[fn]or|up|by|but|the|to|in|o[rnf]) )#","!",$argv[1])),'!',' ');
```
Uses the behaviour of `ucwords()` and escapes the relevant words that are surrounded by spaces then deletes the escape characters.
I copied the `(a[snt]?|and|[fn]or|up|by|but|the|to|in|o[rnf])` from Jörg Hülsermann's answer but as the approach is completely different I'm posting it as a separate answer.
edit: bug noticed by Titus, fixing it cost 1 byte. also: 6 bytes saved thanks to his helpful comment about strtr
[Answer]
## *Pure* `bash` - 253
(no external programs called) - needs bash v4
```
declare -A b;for x in A An The At By For In Of On To Up And As But Or Nor;do b[$x]=1;done
while read -a w;do
n=${#w[@]};o[0]=${w[0]^}
for((i=1;i<n-1;i++)){
g=${w[$i]^};((${b[$g]}))&&o+=(${g,,})||o+=($g);}
((n>1))&&o[$n]=${w[-1]^}
echo ${o[@]};o=()
done
```
normal view with comments
```
#create the "blacklist"
declare -A b
for w in A An The At By For In Of On To Up And As But Or Nor
do
    b[$x]=1
done
# logic:
# read each line (split by words) into array
# and each word is assigned capitalized to the new output array
# but the blacklisted ones
#read each line to array w (split on spaces)
while read -a w
do
    n=${#w[@]}         # get the number of words
    o[0]=${w[0]^}          # copy the capitalized word1
    for((i=1 ; i<n-1 ; i++)) { # loop over 2 up to last -1 words
        g=${w[$i]^}    # for the given word
        # check if it is in the blacklisted ones
        # if yes - convert to lowercase, if not leave as it is
        # and append to the output array
        (( ${b[$g]} )) && o+=(${g,,}) || o+=($g)
    }
    # capitalize the last word if here is more words
    (( n>1 )) && o[$n]=${w[-1]^}
    # make a line from the words
    echo ${o[@]}
    o=() #cleanup
done
```
output
```
Title
And and And
The Rule of Thumb for Title Capitalization
Programming Puzzles and Code Golf
The Many Uses of the Letter A
A an and as at but by for in nor of on or the to Up
On Computable Numbers With an Application to the Entscheidungsproblem
```
[Answer]
# [Japt](https://github.com/ETHproductions/japt), 71 bytes
```
£`a  e  by f     up d  ¿t  n`¸aX >0©Y¦0©YÄ¦Zl ?X:Xg u +XÅ}S
```
[Try it online!](https://tio.run/nexus/japt#JY0xCsJAAAS/MqQVQVsLfYQIZ5cLSVSQO9FLYWFnxMaobxAEf5BOWB8WD4Vld2GK6fRILTqiW4Fqsj2lGnRGV3RBd6pN5Dk6oXcgQqcmVWsN44Fecz3/PVO7pj@cmJFZUNEzn/ow7brEYl1Mjt1hA1kVfhK/ZeVwcXyJd8QTlgXBR1/yBQ)
### Explanation:
```
£`a  e  by f     up d  ¿t  n`¸aX >0©Y¦0©YÄ¦Zl ?X:Xg u +XÅ}S
£`...`qS aX >0&&Y!=0&&Y!=UqS l -1?X:Xg u +Xs1}S
£                                            }S   // Split at spaces and map each item X by this function:
 `...`                                            //  Backticks are used to decompress strings
      qS                                          //  Split the decompressed string at spaces.
         aX >J                                    //  If this contains X
              &&Y!=0                              //  and the index is non-zero (it's not the first word)
                    &&Y!=UqS l -1                 //  and the index is not the length of the input -1 (it's not the last word),
                                 ?X               //  return X.
                                   :Xg u +Xs1     //  Else, return X capitalized. (Literally X[0].toUpperCase() + X.slice(1))
                                             }S   // Rejoin with spaces
```
One of my favorite Japt features is its string compression, which uses the [shoco library](http://ed-von-schleck.github.io/shoco/).
You can compress a string by wrapping it in `Oc"{string}"` → `Oc"a an the at by for in of on to up and as but or nor"`
Then decompressing it with backticks or `Od"{compressed string}"` → `Od"a e by f up d ¿t n"`
[Answer]
## *Pure* `bash` - ~~205~~ ~~192~~ 181 bytes
```
tc(){
while read -a x
do x=(${x[@]^})
for ((i=1;i<${#x[@]}-1;i++))
do
case "${x[i]}" in
A|A[nts]|The|By|[FN]or|In|O[fnr]|To|Up|And|But)x[i]=${x[i],};;
esac
done
echo ${x[@]}
done
}
```
Like [jm66's answer](https://codegolf.stackexchange.com/a/113666/53016) `tc` accepts standard input.
[Answer]
# [Actually](http://github.com/Mego/Seriously), 79 bytes
```
' ,ÿsd@p@`;0"A0An0The0At0By0For0In0Of0On0To0Up0And0As0But0Or0Nor"síu'ù*ƒ`Moq' j
```
[Try it online!](http://actually.tryitonline.net/#code=JyAsw79zZEBwQGA7MCJBMEFuMFRoZTBBdDBCeTBGb3IwSW4wT2YwT24wVG8wVXAwQW5kMEFzMEJ1dDBPcjBOb3Iic8OtdSfDuSrGkmBNb3EnIGo&input=InRoZSBydWxlIG9mIHRodW1iIGZvciB0aXRsZSBjYXBpdGFsaXphdGlvbiI)
Explanation:
```
' ,ÿsd@p@`;0"longstring"síu'ù*ƒ`Moq' j
' ,ÿs                                   title case input, split on spaces
     d@p@                               pop first and last words to stack
         `;0"longstring"síu'ù*ƒ`M       for every word except the first and last:
          ;0"longstring"s                 duplicate word, split the long string on 0s
                         íu               1-based index of word in list (0 if not found)
                           'ù*            "ù"*(index)
                              ƒ           execute the resulting string as a function (lowercases word if it's in the list)
                                 oq' j  put the first and last word back in the list, join with spaces
```
[Answer]
## Batch, 323 bytes
```
@echo off
set s=
for %%w in (@%*@)do call:w %%w
echo%s%
exit/b
:w
for %%s in (a an the at by for in of on to up and as but or nor)do if %%s==%1 set s=%s% %1&exit/b
set w=%1
set w=%w:@=%
set f=%w:~0,1%
for %%c in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)do call set f=%%f:%%c=%%c%%
set s=%s% %f%%w:~1%
```
With comments:
```
@echo off
rem Start with an empty output string
set s=
rem Wrap the parameters in @ signs to identify the first and last words 
for %%w in (@%*@) do call :w %%w
rem Ignore the leading space when printing the result
echo%s%
exit/b
:w
rem Check whether this is a word that we don't change
for %%s in (a an the at by for in of on to up and as but or nor) do if %%s==%1 set s=%s% %1&exit/b
set w=%1
rem Delete any @ signs from the first and last words
set w=%w:@=%
rem Get the first character
set f=%w:~0,1%
rem Case insensitively replace each upper case letter with itself
for %%c in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do call set f=%%f:%%c=%%c%%
rem Concatenate with the rest of the word
set s=%s% %f%%w:~1%
```
]