Given a string, capitalize it. By capitalization I mean conTeNT-lENgth changes to Content-Length. In the example I showed the string with 2 words with - as the word boundary. However I expect you to write the code for the string containing any number of words separated by a single character as the boundary. This boundary may change across the string.
Conditions
- using
regular expressionsis not allowed. - there could be any number of words in a sentence(string).
- each word will consist of
Englishletters[a-zA-Z]of any case. - different words in the sentence will be separated by a single character. This character will only be any one of
-,., ,/,&,#. You can safely assume that sentence will not contain any other character except the mentioned ones. - word boundaries should be preserved in the output.
- shortest code wins.
For example your program should output Begin/With.Type&Content for BeGin/wITH.tyPE&conTeNt.
Some test cases:
"aGeNT ACcEpT/LEngTh-tYPe USeR raNgE.TyPe"
"type&AgeNt/CC/COnteNt lEnGth#acCePT/AgeNt.RAnGe-Cc/contEnt/cODe"
"cc/rEspoNCe.lEngtH#tYpE-witH&UsEr/bEgIN&uSer.AGEnT&begIn/aCCEPt/Cc"
"lENgTH#USeR.tYpE/BeGiN&LENGth tYpe/ACCEpt#rANge/codE&AnD-ACCepT/ConTenT"
"contENT/ACcEpT"
"BeGin/wITH.tyPE&conTeNt"
"Code.cc#User.lenGTh-USer-AND&tyPE TypE&leNgtH.tYPe usER.UseR&with"
"RaNgE&COnTeNT WITh CoNTENT-TypE tyPe"
"BEgin COdE#uSeR#aGeNt.USeR"
"TypE LENGth"
38 Answers 38
Python 3,22
print(input().title())
This code will take a string as input from stdin and gives a capitalized output to stdout.
for example:
input:
BEGIN/wITH.tyPe&cOnTENt
ouput:
Begin/With.Type&Content
The following code is for multi-line inputs (if necessary)
Python 3, 46
import sys
for i in sys.stdin:print(i.title())
-
\$\begingroup\$
while 1:print(input.title())is a shorter equivalent for the last piece of code. \$\endgroup\$Ramchandra Apte– Ramchandra Apte2013年12月17日 14:44:47 +00:00Commented Dec 17, 2013 at 14:44 -
1
-
1\$\begingroup\$ I think the general consensus for golfs is that as long as the output is correct, errors don't matter \$\endgroup\$Volatility– Volatility2013年12月17日 23:26:22 +00:00Commented Dec 17, 2013 at 23:26
-
\$\begingroup\$ Dang; as soon as I saw this question, I thought of this, but you beat me to it. +1 \$\endgroup\$Justin– Justin2013年12月18日 06:38:46 +00:00Commented Dec 18, 2013 at 6:38
-
\$\begingroup\$ +1 I like this better than the golfscript one because it doesn't look like an obscenity. \$\endgroup\$Tim Seguine– Tim Seguine2014年01月01日 22:58:45 +00:00Commented Jan 1, 2014 at 22:58
-
\$\begingroup\$ That's pretty cool :-) \$\endgroup\$batman– batman2016年03月30日 09:12:07 +00:00Commented Mar 30, 2016 at 9:12
GolfScript, (削除) 36 (削除ここまで) (削除) 27 (削除ここまで) 19 characters
0\{95&+.47>32*\}%\;
A quite basic GolfScript approach which works for all input according to the specification. The examples can be tested online.
-
\$\begingroup\$ Cool. Was curious whether my solution is at least twice as a professional one. :) But I am sure you will shorten this several times before the day ends. \$\endgroup\$manatwork– manatwork2013年12月17日 12:15:19 +00:00Commented Dec 17, 2013 at 12:15
-
\$\begingroup\$ @manatwork Now we have a factor of two ;-) Still unhappy with all the swaps. \$\endgroup\$Howard– Howard2013年12月17日 13:50:43 +00:00Commented Dec 17, 2013 at 13:50
-
\$\begingroup\$ I knew you will not disappoint me. \$\endgroup\$manatwork– manatwork2013年12月17日 13:52:19 +00:00Commented Dec 17, 2013 at 13:52
JavaScript (94)
prompt().split(l='').map(function(a){return l='A'>l?a.toUpperCase():a.toLowerCase()}).join('')
-
\$\begingroup\$ Why not arrow functions? Edit: I just realised that this is from 2013 💀 \$\endgroup\$pavi2410– pavi24102023年01月27日 21:44:20 +00:00Commented Jan 27, 2023 at 21:44
Mathematica 62
Data
tests={"aGeNT ACcEpT/LEngTh-tYPe USeR raNgE.TyPe","type&AgeNt/CC/COnteNt lEnGth#acCePT/AgeNt.RAnGe-Cc/contEnt/cODe","cc/rEspoNCe.lEngtH#tYpEwitH&UsEr/bEgIN&uSer.AGEnT&begIn/aCCEPt/Cc","lENgTH#USeR.tYpE/BeGiN&LENGth tYpe/ACCEpt#rANge/codE&AnD-ACCepT/ConTenT","contENT/ACcEpT","BeGin/wITH.tyPE&conTeNt","Code.cc#User.lenGTh-USer-AND&tyPE TypE&leNgtH.tYPe usER.UseR&with","RaNgE&COnTeNT WITh CoNTENT-TypE tyPe","BEgin COdE#uSeR#aGeNt.USeR","TypE LENGth"}
Code
StringReplace[ToLowerCase@#,WordBoundary~~x_:>ToUpperCase@x]&
Usage
f["aGeNT ACcEpT/LEngTh-tYPe USeR raNgE.TyPe"]
"Agent Accept/Length-Type User Range.Type"
f /@ tests
{"Agent Accept/Length-Type User Range.Type",
"Type&Agent/Cc/Content Length#Accept/Agent.Range-Cc/Content/Code", "Cc/Responce.Length#Type-With&User/Begin&User.Agent&Begin/Accept/Cc", "Length#User.Type/Begin&Length Type/Accept#Range/Code&And-Accept/Content", "Content/Accept",
"Begin/With.Type&Content",
"Code.Cc#User.Length-User-And&Type Type&Length.Type User.User&With",
"Range&Content With Content-Type Type",
"Begin Code#User#Agent.User",
"Type Length"}
-
\$\begingroup\$ -1 That's basically regex \$\endgroup\$CalculatorFeline– CalculatorFeline2016年03月29日 19:47:59 +00:00Commented Mar 29, 2016 at 19:47
-
\$\begingroup\$ Mathematica can run regex directly but I used something else. It's similar to regex, but it is not regex. \$\endgroup\$DavidC– DavidC2016年03月29日 21:17:16 +00:00Commented Mar 29, 2016 at 21:17
-
\$\begingroup\$
%%%%%%%%\$\endgroup\$CalculatorFeline– CalculatorFeline2016年03月29日 21:22:14 +00:00Commented Mar 29, 2016 at 21:22
PHP : (削除) 78 (削除ここまで) (削除) 73 (削除ここまで) (削除) 65 (削除ここまで) 64 characters
$b=ucfirst;foreach(str_split($s)as$c)echo$b($c),!$b[0]=$c<A?u:l;
Input is passed in $s. It operates on the string as an array of characters.
It is a simple 2 state machine. It relies on lexical ordering of strings, and that the parser automatically assumes you meant to type a string in some cases.
The state is being stored in $b and is being represented as the name of the function that needs to be called on the next character. ucfirst and lcfirst are shorter to type and have identical behaviour to strtolower/strtoupper on single character strings. Also, since they only differ by one letter, we can use them efficiently to store the state. The original version needed to store the state explicitly in a boolean.
Since echo doesn't print anything for boolean false, I used a comma and the ! operator to "hide" the assignment(which in this case is truthy) in the echo statement. This allowed me to save a character by removing the {}.
-
\$\begingroup\$ Please use code block markup instead of inline code, so scripts like Code Golf UserScript Enhancement Pack can insert the size below the code. By the way, in your code all 3 space characters can be removed. \$\endgroup\$manatwork– manatwork2013年12月29日 14:32:48 +00:00Commented Dec 29, 2013 at 14:32
-
1\$\begingroup\$ Instead of
$b=ord($c)>64;try$b=$c>"@";. Or even$b=$c>=A;– AFAIR that throws a warning, but good coding practices are not a virtue here. \$\endgroup\$manatwork– manatwork2013年12月29日 17:02:20 +00:00Commented Dec 29, 2013 at 17:02 -
\$\begingroup\$ @manatwork thanks, didn't think of that. I am already throwing a warning for using an unset variable anyway. \$\endgroup\$Tim Seguine– Tim Seguine2013年12月29日 17:04:33 +00:00Commented Dec 29, 2013 at 17:04
-
1\$\begingroup\$ Hmm... What about not using $b just as a flag, but storing the actual function name in it?
$b=ucfirst;foreach(str_split($s)as$c){echo$b($c);$b[0]=$c>=A?l:u;}. \$\endgroup\$manatwork– manatwork2013年12月29日 17:08:39 +00:00Commented Dec 29, 2013 at 17:08 -
\$\begingroup\$ @manatwork great! I was trying to think of a way to do that with the function. My tries were all bigger. \$\endgroup\$Tim Seguine– Tim Seguine2013年12月29日 17:14:01 +00:00Commented Dec 29, 2013 at 17:14
C, 83
n;main(c){c=getchar();putchar(c>96?n?c:(n=c-32):c&64?n?c+32:(n=c):(n=0,c));main();}
Takes lines on stdin, translates them to stdout. (Prefers SIGINT to EOF.)
Powershell: 37 - 43
Depending on how you want to take the input...
Prompt the user for input: 43
(Culture).TextInfo.ToTitleCase((read-host))
Take input from pipeline: 38
(Culture).TextInfo.ToTitleCase($input)
Provide input as an argument when running the script: 37
(Culture).TextInfo.ToTitleCase($args)
NOTE: The above scripts will ignore all-caps words, leaving them as-is. If this needs to be accounted for, the input should be forced to lower-case before the Title Case conversion. This adds 10 characters to the first method, and 12 to the other two.
(Culture).TextInfo.ToTitleCase((read-host).ToLower())
(Culture).TextInfo.ToTitleCase("$input".ToLower())
(Culture).TextInfo.ToTitleCase("$args".ToLower())
-
\$\begingroup\$ Does not work according to the specification. Try
foo:bar. \$\endgroup\$Mormegil– Mormegil2013年12月17日 15:33:44 +00:00Commented Dec 17, 2013 at 15:33 -
\$\begingroup\$ @Mormegil Which one? The read-host version, at least, works fine for me. I tested it against all the test cases in the question and they all returned as expected except for the special cases I posted in comment to the question. \$\endgroup\$Iszi– Iszi2013年12月17日 15:35:57 +00:00Commented Dec 17, 2013 at 15:35
-
\$\begingroup\$
:(colon) is not listed as a word separator in rule #4, therefore, AFAICS,foo:barshould result inFoo:bar, notFoo:Bar. But that is just my (quite strict) reading of the specification. \$\endgroup\$Mormegil– Mormegil2013年12月17日 15:38:33 +00:00Commented Dec 17, 2013 at 15:38 -
2\$\begingroup\$ @Mormegil Well, this is neat. Looks like the spec was tweaked to resolve that ambiguity, while at the same time not invalidating this answer. \$\endgroup\$Iszi– Iszi2013年12月17日 16:19:04 +00:00Commented Dec 17, 2013 at 16:19
-
1\$\begingroup\$ You can replace
get-culturewithculture; see codegolf.stackexchange.com/a/778/1308 \$\endgroup\$Danko Durbić– Danko Durbić2013年12月18日 11:50:10 +00:00Commented Dec 18, 2013 at 11:50
Java - 209 characters
class C{
public static void main(String[]a){
for(String b:a){
char[]k=b.toLowerCase().toCharArray();
for(int i=-1;i<k.length;i++){if(i<0||"-. /&#".indexOf(k[i])>=0)k[++i]=(char)(k[i]-32);}
System.out.println(k);}}}
I added newlines only for readability.
R, (削除) 143 (削除ここまで) 116
A solution a bit long maybe but here we go:
f=function(x){a=sapply(1:nchar(x),function(y)substr(tolower(x),y,y));d=c(1,which(!a%in%letters)+1);a[d]=toupper(a[d]);cat(a,sep="")}
Slightly ungolfed and explained:
f <- function(x){
#Split the string in characters and "lower-case" everything
a <- sapply(1:nchar(x),function(y)substr(tolower(x),y,y))
#Select the first character and each character following a
#character that doesn't belong to lower case alphabet
d <- c(1,which(!a%in%letters)+1)
#Make those ones uppercase.
a[d] <- toupper(a[d])
#Output (stdout) while pasting them back together.
cat(a,sep="")
}
Edit: 116 characters
The main challenge here is to vectorize substr. Here's another less verbose way.
f=function(x){n=1:nchar(x);a=mapply(substr,tolower(x),n,n);d=c(T,!a%in%letters);a[d]=toupper(a[d]);cat(a[n],sep="")}
Indented:
f <- function(x){
n <- 1:nchar(x)
a <- mapply(substr,tolower(x),n,n)
d <- c(T,!a%in%letters) #This has been simplified as well
a[d] <- toupper(a[d])
cat(a[n],sep="") #Because a is now 1 char longer than x, need to subset a
}
Usage:
> f("aGeNT ACcEpT/LEngTh-tYPe USeR raNgE.TyPe")
Agent Accept/Length-Type User Range.Type
-
\$\begingroup\$ You can save some characters. Since
aconsits of lowercase characters only, there's no need to check for matches with uppercaseLETTERS. \$\endgroup\$Sven Hohenstein– Sven Hohenstein2013年12月18日 14:50:46 +00:00Commented Dec 18, 2013 at 14:50 -
\$\begingroup\$ Another one: You can replace
TRUEwithT. \$\endgroup\$Sven Hohenstein– Sven Hohenstein2013年12月18日 14:53:39 +00:00Commented Dec 18, 2013 at 14:53 -
\$\begingroup\$ Originally i had the
tolowerlater. \$\endgroup\$plannapus– plannapus2013年12月18日 15:02:24 +00:00Commented Dec 18, 2013 at 15:02 -
\$\begingroup\$ OK, here's another one ;-) You can replace
mapply(substr,tolower(x),n,n)withstrsplit(tolower(x),"")[[1]]to save one character. \$\endgroup\$Sven Hohenstein– Sven Hohenstein2013年12月18日 15:30:31 +00:00Commented Dec 18, 2013 at 15:30 -
\$\begingroup\$ @SvenHohenstein Ahah yes indeed. Although one would argue that argument
split(here an empty string) is technically treated as a regular expression! :) \$\endgroup\$plannapus– plannapus2013年12月18日 15:35:19 +00:00Commented Dec 18, 2013 at 15:35
Befunge 98 - (削除) 24 (削除ここまで) 45
~\j:'``!3*j' -;:'``b*j:'/`!3*j' +#;:,'/`!jc#@
Writing this hurt my brain.
This takes input through ~ and if the previous character was one of the separators (or if there was no previous character), it executes
:'``!3*j' -;
This snippet takes the character, and if its ascii value is greater than or equal to a, it subtracts 32 from it, thus changing it to upper case. If it is less than a, 3*j skips the adjustment. Afterwards, it skips the next part. This part handles changing from upper case to lower case (I'm sure it can be merged with the next part; I'm just not sure how):
:'``b*j:'/`!3*j' +#;
The character is printed (,), then this checks if the character is one of the boundaries:
'/`!
It basically compares the character to the ascii value of /. If the character is not a boundary, the code pushes 12 so that it will skip the capitalization adjustment the next time around. # skips over the end program: @, and if the end of the input is reached, ~ sends the code execution back to the @, ending the program.
Ruby: (削除) 60 (削除ここまで) (削除) 51 (削除ここまで) (削除) 50 (削除ここまで) 47 characters
$_.downcase.chars{|c|$><<$/=$/<?0?c.upcase: c}
Sample run:
bash-4.1$ for line in "${test[@]}"; do printf '%-75s | %s\n' "$line" "$( ruby -ne '$_.downcase.chars{|c|$><<$/=$/<?0?c.upcase: c}' <<< "$line" )"; done
aGeNT ACcEpT/LEngTh-tYPe USeR raNgE.TyPe | Agent Accept/Length-Type User Range.Type
type&AgeNt/CC/COnteNt lEnGth#acCePT/AgeNt.RAnGe-Cc/contEnt/cODe | Type&Agent/Cc/Content Length#Accept/Agent.Range-Cc/Content/Code
cc/rEspoNCe.lEngtH#tYpE-witH&UsEr/bEgIN&uSer.AGEnT&begIn/aCCEPt/Cc | Cc/Responce.Length#Type-With&User/Begin&User.Agent&Begin/Accept/Cc
lENgTH#USeR.tYpE/BeGiN&LENGth tYpe/ACCEpt#rANge/codE&AnD-ACCepT/ConTenT | Length#User.Type/Begin&Length Type/Accept#Range/Code&And-Accept/Content
contENT/ACcEpT | Content/Accept
BeGin/wITH.tyPE&conTeNt | Begin/With.Type&Content
Code.cc#User.lenGTh-USer-AND&tyPE TypE&leNgtH.tYPe usER.UseR&with | Code.Cc#User.Length-User-And&Type Type&Length.Type User.User&With
RaNgE&COnTeNT WITh CoNTENT-TypE tyPe | Range&Content With Content-Type Type
BEgin COdE#uSeR#aGeNt.USeR | Begin Code#User#Agent.User
TypE LENGth | Type Length
-
1\$\begingroup\$ Isn't
l==l.swapcasethe same asl<?0(not tested)? At least for the input allowed for this task. \$\endgroup\$Howard– Howard2013年12月17日 15:59:54 +00:00Commented Dec 17, 2013 at 15:59 -
\$\begingroup\$ Yes. Now that batman emphasized that no other separators have to be expected, indeed that is shorter. Thank you, @Howard. \$\endgroup\$manatwork– manatwork2013年12月17日 16:19:00 +00:00Commented Dec 17, 2013 at 16:19
JavaScript (string->string), 67 bytes
s=>[...s].map(a=>l=a[`to${'A'>l?'Upp':'Low'}erCase`](),l='').join``
Try it:
f=s=>[...s].map(a=>l=a[`to${'A'>l?'Upp':'Low'}erCase`](),l='').join``
console.log(f('aGeNT aCcEpT/LEngTh-tYPe USeR raNgE.TyPe'));
console.log(f('type&AgeNt/CC/COnteNt lEnGth#acCePT/AgeNt.RAnGe-Cc/contEnt/cODe'));
console.log(f('cc/rEspoNCe.lEngtH#tYpE-witH&UsEr/bEgIN&uSer.AGEnT&begIn/aCCEPt/Cc'));
console.log(f('lENgTH#USeR.tYpE/BeGiN&LENGth tYpe/ACCEpt#rANge/codE&AnD-ACCepT/ConTenT'));
console.log(f('contENT/ACcEpT'));
console.log(f('BeGin/wITH.tyPE&conTeNt'));
console.log(f('Code.cc#User.lenGTh-USer-AND&tyPE TypE&leNgtH.tYPe usER.UseR&with'));
console.log(f('RaNgE&COnTeNT WITh CoNTENT-TypE tyPe'));
console.log(f('BEgin COdE#uSeR#aGeNt.USeR'));
console.log(f('TypE LENGth'));
Jacob's variant - JavaScript (char[]->char[]), 55 bytes
s=>s.map(a=>l=a[`to${'A'>l?'Upp':'Low'}erCase`](),l='')
Try it:
f=s=>s.map(a=>l=a[`to${'A'>l?'Upp':'Low'}erCase`](),l='')
g = s => f([...s]).join``
console.log(g('aGeNT aCcEpT/LEngTh-tYPe USeR raNgE.TyPe'));
console.log(g('type&AgeNt/CC/COnteNt lEnGth#acCePT/AgeNt.RAnGe-Cc/contEnt/cODe'));
console.log(g('cc/rEspoNCe.lEngtH#tYpE-witH&UsEr/bEgIN&uSer.AGEnT&begIn/aCCEPt/Cc'));
console.log(g('lENgTH#USeR.tYpE/BeGiN&LENGth tYpe/ACCEpt#rANge/codE&AnD-ACCepT/ConTenT'));
console.log(g('contENT/ACcEpT'));
console.log(g('BeGin/wITH.tyPE&conTeNt'));
console.log(g('Code.cc#User.lenGTh-USer-AND&tyPE TypE&leNgtH.tYPe usER.UseR&with'));
console.log(g('RaNgE&COnTeNT WITh CoNTENT-TypE tyPe'));
console.log(g('BEgin COdE#uSeR#aGeNt.USeR'));
console.log(g('TypE LENGth'));
-
\$\begingroup\$ Nice answer! You can save a couple bytes by using character arrays instead of strings, by the way. \$\endgroup\$noodle person– noodle person2023年01月26日 14:41:05 +00:00Commented Jan 26, 2023 at 14:41
-
\$\begingroup\$ @Jacob Thank you! Can you please show how? \$\endgroup\$EzioMercer– EzioMercer2023年01月26日 14:43:08 +00:00Commented Jan 26, 2023 at 14:43
-
\$\begingroup\$ Just get rid of the
[...s]and the.join``. It's fairly common practice on this site - see codegolf.meta.stackexchange.com/a/8964/108687. If you use this, just make sure to mention in the answer that it uses character arrays. \$\endgroup\$noodle person– noodle person2023年01月26日 14:50:30 +00:00Commented Jan 26, 2023 at 14:50 -
\$\begingroup\$ tio.run/… \$\endgroup\$noodle person– noodle person2023年01月26日 14:50:47 +00:00Commented Jan 26, 2023 at 14:50
-
\$\begingroup\$ @Jacob Thank you! I read the all answers. But I think it is a big cheating to define second function which do some part of my function. The conditions say that my function must return a string and accept a string so I think it isn't fair to define another function which prepare data for main function and modifies the output \$\endgroup\$EzioMercer– EzioMercer2023年01月26日 15:06:03 +00:00Commented Jan 26, 2023 at 15:06
C# – 110
A simple finite-state-machine-based processing:
x.Aggregate(new{b=1>0,r=""},(s,c)=>new{b="-. /&#".Contains(c),r=s.r+(s.b?Char.ToUpper(c):Char.ToLower(c))}).r
(where x is the string to capitalize)
and of course, if you want to be boring (after the specification was updated), you can use
new CultureInfo(9).TextInfo.ToTitleCase(x)
or, with all the boring boilerplate:
class C{static void Main(string[]a){System.Console.WriteLine(new System.Globalization.CultureInfo(9).TextInfo.ToTitleCase(a[0]));}}
-
\$\begingroup\$ Nah, won't compile as C# is no scripting language and you need to encapsulate this in a class. \$\endgroup\$Pierre Arlaud– Pierre Arlaud2013年12月17日 14:04:53 +00:00Commented Dec 17, 2013 at 14:04
-
2\$\begingroup\$ Says who?
Microsoft (R) Roslyn C# Compiler version 1.2.20906.1 Loading context from 'CSharpInteractive.rsp'. Type "#help" for more information. > "foobar".Aggregate(new{b=1>0,r=""},(s,c)=>new{b="-. /&#".Contains(c),r=s.r+(s.b?Char.ToUpper(c):Char.ToLower(c))}).r "Foobar"But if you really care about the boring boilerplate, add 112 characters of it. \$\endgroup\$Mormegil– Mormegil2013年12月17日 15:31:59 +00:00Commented Dec 17, 2013 at 15:31 -
1\$\begingroup\$ You can cut the
publicandstring[]afrom the boilerplate \$\endgroup\$Johnbot– Johnbot2013年12月17日 17:34:36 +00:00Commented Dec 17, 2013 at 17:34 -
\$\begingroup\$ Oh yeah, you’re right with
public, but I need the arguments, as that is what I process... \$\endgroup\$Mormegil– Mormegil2013年12月18日 09:25:10 +00:00Commented Dec 18, 2013 at 9:25
Javascript 102
prompt().split(o=q='').map(function(c){o+=(q)?c.toLowerCase():c.toUpperCase(),q=('A'>c)?0:1})
alert(o)
-
\$\begingroup\$ You need no
(...)around the ternary condition. Even more, you not need the second ternary:function(c){o+=q?c.toLowerCase():c.toUpperCase(),q='@'<c}. \$\endgroup\$manatwork– manatwork2013年12月30日 09:34:50 +00:00Commented Dec 30, 2013 at 9:34
Forth, 135
: s swap ;
: c 1 begin key dup 96 > if s if 32 - then 0 s
else dup 64 > if s 0= if 32 + then 0 s then else 1 s then then emit again ; c
Translated output is written to stdout as it reads from stdin.
-
1\$\begingroup\$ "then then emit again" rhyming with forth! \$\endgroup\$cat– cat2016年03月30日 22:25:59 +00:00Commented Mar 30, 2016 at 22:25
Befunge-98 (29), C (65)
Since the method/algorithm is pretty much the same, I include both versions in the same post. Both rely on keeping track of whether the last character was a symbol or letter, in order to know whether to lowercase a letter or not.
Befunge-98 (29)#@~:'0` #v_,0>
',++@'% '< ^
C (65)
c,d;main(){for(;~(c=getchar());d=c>48)putchar(c<48?c:c&95|32*d);}
Python 3, 122 bytes
lambda s:''.join(chr(ord(c)+[[0,0],[0,32],[-32,0]][('@'<c<'[')-('`'<c<'{')]['@'<p<'['or'`'<p<'{'])for c,p in zip(s,'-'+s))
Not a great score, but I wanted to try it without builtin string operations for case changing.
AWK, (削除) 113 (削除ここまで) (削除) 103 (削除ここまで) 98 bytes
{OFS=""
for(n=split(0,ドルa,"");i<=n;s=a[++i]){$i=(L?tolower(s):toupper(s))
L=!(index("-. /&#",s))}}1
This works fine for single line content, but for multi-line input a few more inits need to be added
AWK, 104 bytes
{OFS=i=s=L=""
for(n=split(0,ドルa,"");i<=n;s=a[++i]){$i=(L?tolower(s):toupper(s))
L=!(index("-. /&#",s))}}1
It would have been nice to take advantage of AWK's automatic splitting of a record into fields and modifying said fields, but that throws away the field separators. :(
This update throws away the idea of tacking characters onto a string and then printing the string. Instead, each character becomes its own field. Without the OFS="" bit, each character/field would be separated by a space when printed, which isn't what was requested.
Realizing that "" is essentially the same thing as 0 in AWK shortens the byte-count for the multi-line version a little bit. (I know it's different... I said 'essentially' :p )
-
1\$\begingroup\$ Are you sure? None of the codes seems to produce the required output neither with
gawk,mawkororiginal-awk. (Tested on Ubuntu.) \$\endgroup\$manatwork– manatwork2016年03月30日 07:31:14 +00:00Commented Mar 30, 2016 at 7:31 -
\$\begingroup\$ It was written using
gawkon an RHEL6 box, but then transcribed to a windows box. There could very well be a transcription issue. I'll try testing after work when I can do testing and posting on the same machine.... I think I see the issue, anyway.l=0should beL=0\$\endgroup\$Robert Benson– Robert Benson2016年03月30日 12:53:25 +00:00Commented Mar 30, 2016 at 12:53 -
\$\begingroup\$ Hopefully it works now, @manatwork . Thanks for the testing. :) \$\endgroup\$Robert Benson– Robert Benson2016年03月30日 12:58:44 +00:00Commented Mar 30, 2016 at 12:58
-
1\$\begingroup\$ Now seems to work correctly. Not checked all test cases, but seems to be possible to reduce it a bit:
{for(l=split(0,ドルa,0ドル="");i<=l;s=a[++i]){0ドル=0ドル(L?toupper(s):tolower(s));L=index("-. /&#",s)}}1. \$\endgroup\$manatwork– manatwork2016年03月30日 13:23:06 +00:00Commented Mar 30, 2016 at 13:23 -
\$\begingroup\$ I like your use of changing
0ドルand the1label to avoid theprintcommand are things I haven't thought of doing. I'll have to keep it in mind for future golfing :) \$\endgroup\$Robert Benson– Robert Benson2016年03月30日 14:07:45 +00:00Commented Mar 30, 2016 at 14:07
QBasic, 74 bytes
1c$=LCASE$(INPUT$(1))
IF f=0THEN c$=UCASE$(c$)
f=c$>"@
?c$;
IF""<c$GOTO 1
Bytes are counted in CP-437; is a single byte (character code 20).
The input method here is a bit strange: characters are typed one at a time, and their capitalization is converted before they are displayed. So when you type in aGeNT, it appears on screen as Agent. Hitting Enter ends the program.
Vyxal, (削除) 20 (削除ここまで) 15 bytes
f:ʀĠ•ƛḣv⇩$⇧p;f∑
Or, if that's too long:
1 byte
ǐ
Explained
f:ʀĠ•ƛḣv⇩$⇧p;f∑
f: # Push two copies of the letters of the input
ʀ # is each letter in the first copy in the alphabet?
Ġ # group that on consecutive elements - this has the effect of grouping words.
• # reshape the other copy of the letters to have the same shape as that
ƛ # to each sublist L:
ḣv⇩ # push L[0] and [lower(x) for x in L[1:]] - on single length strings this just leaves L[0] on the stack.
$⇧p # uppercase L[0] and prepend it to the other list
; # close map
f∑ # deep flatten and summate to get a single string - the `d` flag would save 3 bytes here by removing this pair and allowing structure autocompletion to save a byte.
Excel VBA, 13 characters
In the Immediate window
?[Proper(A1)]
Function takes input from cell A1
VBScript
Set xlapp = CreateObject("excel.application")
wscript.echo xlapp.Evaluate("Proper(""BeGin/wITH.tyPE&conTeNt"")"
-
\$\begingroup\$ Could you provide some help on usage? I get "Compile error: External name not defined". (In Word 2013 on the Developer tab I clicked Visual Basic, then in Visual Basic for Application I copy-pasted your code in the Immediate window and pressed Enter.) \$\endgroup\$manatwork– manatwork2013年12月29日 13:29:50 +00:00Commented Dec 29, 2013 at 13:29
-
\$\begingroup\$ @manatwork I should have clarified it was in Excel. You can do this from Word but the path is longer as you need to automate Excel. \$\endgroup\$brettdj– brettdj2013年12月29日 13:34:19 +00:00Commented Dec 29, 2013 at 13:34
-
1\$\begingroup\$ Cool. Works perfectly when VBA is started from Excel 2013. \$\endgroup\$manatwork– manatwork2013年12月29日 13:47:42 +00:00Commented Dec 29, 2013 at 13:47
-
1\$\begingroup\$ Works in directly in Excel as well:
=PROPER(A1), also 11 bytes \$\endgroup\$Wernisch– Wernisch2018年03月28日 13:27:31 +00:00Commented Mar 28, 2018 at 13:27
Go, 153 bytes
import."strings"
func f(s string)(o string){c:=0<1
for i:=range s{x:=s[i:i+1]
if c{o+=ToUpper(x);c=!c}else{o+=ToLower(x)}
c=Contains("-. /&#",x)}
return}
JavaScript (Node.js), (削除) 54 (削除ここまで) 53 bytes
Exact same score as the RegEx approach would have been!
s=>Buffer(s.toLowerCase()).map(x=c=>x=x>64?c:c^32)+``
Try it online! (includes all test cases)
K (ngn/k), 36 bytes
{,/{`c$x-32*~!#x}'_(&1,~~"a{"'_x)_x}
_(&1,~~"a{"'_x)_xsplit input after each non-letter and lowecase it, e.g."Begin/With.Type&Content"to("begin/";"with.";"type&";"content"){`c$x-32*~!#x}'subtract 32 from the first character in each word and 0 from the rest (in effect capitalizing the first letter and leaving the others unchanged),/flatten back into a single string and (implicitly) return
T-SQL, 179
DECLARE @T VARCHAR(MAX)='foo',@X VARCHAR(2),@ INT=0WHILE @<LEN(@T)SELECT @X=SUBSTRING(@T,@,2),@+=1,@T=STUFF(@T,@,1,IIF(@X LIKE'[a-Z]_',LOWER(RIGHT(@X,1)),UPPER(RIGHT(@X,1))))PRINT @T
Try the SELECT version in SQL Server 2012 here.
Replace "foo" with the input string. The char count is for a zero-length string. This code traverses the string using an index, uppercasing or lowercasing the character at that position based on the previous character.
/CC/in line 2, or-AND&in line 7) should be left alone. Is this ok, for this challenge? \$\endgroup\$