| Bytes | Lang | Time | Link |
|---|---|---|---|
| 085 | Python | 240524T140835Z | Julian F |
| 192 | Go | 220923T143057Z | bigyihsu |
| 117 | Python 3 | 220922T051219Z | Pandu |
| 014 | Japt | 220919T142007Z | Shaggy |
| 001 | Vyxal | 220919T134902Z | lyxal |
| 019 | Vim | 210413T135704Z | Aaroneou |
| 076 | C gcc | 200516T085751Z | Noodle9 |
| 081 | Red | 200518T054539Z | Galen Iv |
| 033 | perl p | 200516T142627Z | Abigail |
| 013 | Retina | 200516T102041Z | Jarmex |
| 019 | Retina 0.8.2 | 200516T113553Z | Neil |
| 101 | JavaScript Node.js | 200516T084653Z | Yaroslav |
| 077 | Erlang escript | 200516T002928Z | user9206 |
| 067 | Python 3 | 200516T002520Z | dingledo |
| 003 | 05AB1E | 200516T002027Z | lyxal |
Python, 85 bytes
(No regex)
(With an improvement suggested by emanresu A)
lambda s,a=0:' '.join([s.replace(' ','').title()[a:(a:=a+len(x))]for x in s.split()])
Here is an 85-byte solution for making the sentence case capitalization in Python. It is diffent from the other Python answers because it does not use regular expressions, but relies on the title function. Here even some difficult cases including the capitalization of the letters with the diacritics - Österreich, for instance, are treated correctly. Also, apparently, no problems with the combinations of several punctuation symbols (.!?) and, particularly, numbers.
How this works.
As mentioned before, the solution makes use of the function title, which converts the first letter of each word to the uppercase and the rest to the lowercase. We don't want each word, but only the first one, so, let's convert the sentence to a single word by removing the spaces. Once the spaces are removed, the title() is applied and then the spaces are reintroduced again (a verbose part, unfortunately!) - their positions are taken from the original sentence.
Go, 192 bytes
import(y"bytes";."regexp";u"unicode")
type k=[]byte
func f(s k)k{return MustCompile(`\w[\w ]+`).ReplaceAllFunc(s,func(b k)k{return append(k{byte(u.ToUpper(rune(b[0])))},y.ToLower(b[1:])...)})}
A port of @dingledooper's answer.
Python 3, 117 bytes
import re
f=lambda s:''.join(map(lambda p:re.sub(r'[a-z]',lambda m:m[0].upper(),p.lower(),1),re.split(r'([.?!])',s)))
For some reason, I made a solution that handles a few extra test cases that OP may or may not have cared about :) This is much longer than the current shortest Python solution, but I'd be sad to just throw this code away, so here it is!
Extra test cases:
"a.b.c" // "A.B.C"
(no space after punctuation)
"hello. goodbye" // "Hello. Goodbye"
(more than one space after punctuation)
"I'M A ROBOT" // "I'm a robot"
(punctuation other than sentence terminator)
Commented solution:
f = (
lambda string:
''.join(map(
# Capitalize first letter in part
lambda part: re.sub(
r'[a-z]',
lambda match: match[0].upper(),
part.lower(),
1
),
# Split on punctuation
re.split(r'([.?!])',string)
))
)
Vyxal, 1 byte
¡
"Nothing like a good old built-in answer!" I suppose not younger lyxal, I suppose not.
Alternatively, a non-trivial 24 byte answer:
`([.?!])`ṡλ⇩⌈:Th~iǐȦṄ;Ẇṅ
Explained
`([.?!])`ṡλ⇩⌈:Th~iǐȦṄ;Ẇṅ
` `ṡ # Split the input on the regex "[.?!]", keeping the thing that causes splits (wrapping something in `()` when regex splitting keeps it in the split list)
λ ;Ẇ # To each second item of that list (guaranteed to not be punctuation), starting at index 0:
⇩⌈ # Split the lowercase version of the string on spaces
:Th~i # Get the first word by getting the first truthy index in the splitted string (because it may contain `""`s) and get the item at that index
ǐȦṄ # Replace the word at that index with a title-cased version of the string, and join the list on spaces.
ṅ # Join the result on nothing
Vim, 20 19 bytes
Saved 1 byte by using ~ to toggle casing instead of vU.
v$uqq~/[.!?]
w@qq@q
Explanation:
v$u # Selects whole line and changes it to lowercase
qq # Starts recording macro q
~ # Toggles uppercase on current character
/[.!?] # Jumps to next . ! or ?
w # Jumps to next non-whitespace character
@q # Calls macro q recursively
q@q # Ends macro q and calls it
C (gcc), 80 \$\cdots\$ 87 76 bytes
Added 13 bytes to fix a bug kindly pointed out by Abigail.
c;b;f(char*s){for(b=1;c=*s;b|=ispunct(c))*s++=isalpha(c)?b?b=0,c&95:c|32:c;}
How
Capitalises the first letter and every letter after a punctuation mark. Every other letter is converted to lower case. Simply prints everything else.
Red, 81 bytes
func[s][parse lowercase s[any[any" "p: change skip(p/1 - 32)thru["."|"!"|"?"]]]s]
perl -p, 33 bytes
$_=lc=~s/(^|\pP)\s*\K\pL/uc$&/erg
This lowercases the string, then upper cases any letter following either the beginning of the string, or after a punctuation character (skipping any whitespace in between). This does turn a string "foo, bar, baz" into "Foo, Bar, Baz", but that's how I read the requirement about all punctuation.
Retina, 13 bytes
.+
$T
\b .
$L
Explanation
General approach is to convert every word to title-case, then un-convert the words that shouldn't have been converted
.+ Matches the entire string, $T converts it to title case (every word lowercase with an uppercase first character
\b . - \b Matches the position between a word-character and a non-word character (i.e. the end of a word without a full stop) followed by a space and any other character .
$L converts this to lowercase
Retina 0.8.2, 19 bytes
T`L`l
T`l`L`^.|\W .
Try it online! Link includes test cases. Explanation:
T`L`l
Lowercase everything.
T`l`L`^.|\W .
Uppercase the first character and any character that follows a non-word character and a space. It might not be the world's best heuristic but it works on the test case.
JavaScript (Node.js), 101 bytes
s=>(s.reduce((a,c)=>c=='.'?(r+=c,'Upp'):c>' '?(r+=c['to'+a+'erCase'](),'Low'):(r+=c,a),'Upp',r=''),r)
Erlang (escript), 77 bytes
If non-periods are allowed... well, that greatly golfs my program!
g(H)->[string:titlecase(string:lowercase(I))||I<-re:split(H,"(\\W[\\W ]+)")].
Explanation
g(H)-> % Define a function.
re:split(H,"(\\W[\\W ]+)") % Split the operand on "sentences", keeping the items reserved for splitting.
% I.e. none of the items from the string is missing after the split
||I<- ] % For every item in a sentence,
[string:titlecase(string:lowercase(I))
% Title case the sentence.
. % End the function.
Python 3, 67 bytes
-7 bytes thanks to Surculose Sputum
If other punctuation like ! or ? are allowed.
lambda s:re.sub(r'\w[\w ]+',lambda x:x[0].capitalize(),s)
import re
Python 2, 53 bytes
lambda s:'. '.join(map(str.capitalize,s.split('. ')))
05AB1E, 3 bytes
l.ª
Nothing like a good old built-in answer! This converts the string to lowercase and then performs sentence case.