41
\$\begingroup\$

The Task

Your task is to create a program or a function that, given an input, outputs the input text with random letters capitalized, while keeping already capitalized letters capitalized.

Every combination of capitalizations of the lowercase letters should be possible. For example, if the input was abc, there should be a non-zero probability of outputting any of the following combinations: abc, Abc, aBc, abC, ABc, AbC, aBC or ABC.

Input

Your input is a string, containing any number of printable ASCII characters, for example Hello World. The outputs for that input include HeLLo WoRlD, HElLO WOrld, etc.

Scoring

This is code-golf, so the shortest answer in each language wins!

\$\endgroup\$
6
  • \$\begingroup\$ It's possible for something to happen, yet still have zero probability. Link here. Does it just have to be possible, or does it need to to have a strictly non-zero probability, as stated? \$\endgroup\$
    – AviFS
    Jun 18, 2021 at 1:20
  • \$\begingroup\$ @AviFS It's only possible for something that occurs to have zero probability if the number of possibilities is infinite. For any finite input, it's a moot point. And for any infinite input there are necessarily possibilities with 0 probability. \$\endgroup\$
    – Chris
    Jun 20, 2021 at 0:14
  • \$\begingroup\$ @Chris It may be true (though I don't get the piece about in/finite input.) But I promise my question still stands. The validity of the answer I have in mind is dependent on the answer. \$\endgroup\$
    – AviFS
    Jun 20, 2021 at 6:30
  • \$\begingroup\$ @AviFS Well the OP hasn't been on the site in years, so you're not likely to get a response from them. If you think your answer follows the rules as stated, I'd just post it if I were you. Either way I'd be interested to see your answer. ;) \$\endgroup\$
    – Chris
    Jun 20, 2021 at 11:01
  • \$\begingroup\$ From my reading, you can assume the input is always a finite string. So I don't see how you can have something that happens unless it has a non-zero probability. \$\endgroup\$
    – Chris
    Jun 20, 2021 at 11:03

69 Answers 69

14
\$\begingroup\$

TI-Basic (83 series), 137 bytes

For(I,1,length(Ans
Ans+sub(sub(Ans,I,1)+"ABCDEFGHIJKLMNOPQRSTUVWXYZ",1+int(2rand)inString("abcdefghijklmnopqrstuvwxyz",sub(Ans,I,1)),1
End
sub(Ans,I,I-1

Takes input in Ans, as illustrated in the screenshot below:

enter image description here

(If the screenshot looks scrambled, as it sometimes does for me, try opening it in a new tab?)

TI-Basic (at least the TI-83 version... maybe I should branch out into TI-89 golfing) is a terrible language to try to golf this challenge in, since:

  1. It provides absolutely no support for any arithmetic with characters, knowing the uppercase version of a lowercase character, or even knowing the alphabet.
  2. Every single lowercase character takes 2 bytes to store. (In fact, I had to use an assembly script just to be able to type the lowercase letters.)

The result is that 78 bytes of this program (more than half) are just storing the alphabet, twice.

Anyway, the idea is that we loop through the string, with a chance of turning lowercase characters into uppercase ones as we go, and adding the result onto the end of the string so that both the input and the output are stored in Ans. When we leave the For( loop, I is one more than the length of the original string, so taking the I-1 characters starting at I gives the output.

\$\endgroup\$
2
  • \$\begingroup\$ The apps "MirageOS" and "OmniCalc" both allow you to type lowercase letters just by pressing alpha twice. And they also have other nice features. \$\endgroup\$ Dec 1, 2017 at 7:45
  • \$\begingroup\$ @Fabian The assembly script, and the apps you mentioned, both work essentially the same way: they set a flag in the operating system that enables "press alpha twice for lowercase". \$\endgroup\$ Dec 1, 2017 at 7:51
13
\$\begingroup\$

Python 2, 66 65 bytes

lambda s:`map(choice,zip(s.upper(),s))`[2::5]
from random import*

Try it online!

\$\endgroup\$
12
\$\begingroup\$

Japt, 6 bytes

®m`«`ö

Test it online!

Explanation

®m`«`ö   Implicit input
®        Map each char in the input by
 m         mapping each char in this char through
  `«`ö       a random character of "us". (`«` is "us" compressed)
             The u function converts to uppercase, and s is slice, which does nothing here.
         Implicit output
\$\endgroup\$
10
\$\begingroup\$

C,  47  46 bytes

Thanks to @l4m2 for saving a byte!

f(char*s){for(;*s++-=(*s-97u<26&rand())*32;);}

Try it online!

Would be 42 bytes, if it could be assumed that {|}~ don't appear in the input:

f(char*s){for(;*s++-=(*s>96&rand())*32;);}

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ Worth noting that, given a particular implementation, the capitalization is perfectly deterministic (the C standard provides an implicit srand(1) at the start of the program, so in each execution the sequence of values returned by rand() will be the same). \$\endgroup\$ Nov 30, 2017 at 11:39
  • \$\begingroup\$ f(char*s){for(;*s++-=(*s-'a'<26&rand())*32;);} for some compiler (def. -funsigned-char) work \$\endgroup\$
    – l4m2
    May 27, 2018 at 16:58
  • \$\begingroup\$ @l4m2 Thanks! That doesn't work though for some reason. Changing 'a' to 97u works and doesn't even require the -funsigned-char flag. \$\endgroup\$
    – Steadybox
    May 28, 2018 at 2:29
  • \$\begingroup\$ It seems that when you subtract 'a' (which is signed int, not unsigned char) from *s (which is unsigned char), *s gets promoted to signed int instead of unsigned int, hence negative values being possible and the comparison not working as intended. \$\endgroup\$
    – Steadybox
    May 28, 2018 at 2:44
9
\$\begingroup\$

Jelly, 5 bytes

Another one bytes the dust thanks to dylnan.

żŒuX€

Try it online!

Explanation

żŒuX€  main link: s = "Hello world"

żŒu    zip s with s uppercased  ["HH", "eE", "lL", "lL", "oO", "  ", ...]
   X€  map random choice        "HeLLo woRlD"
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I need to use ŒṘ more often to see how things are represented under the hood \$\endgroup\$
    – dylnan
    Nov 29, 2017 at 21:55
8
\$\begingroup\$

Perl 5, 23 bytes

22 bytes code + 1 for -p.

s/./rand>.5?uc$&:$&/ge

Try it online!

\$\endgroup\$
7
\$\begingroup\$

JavaScript (ES6), 56 bytes

s=>s.replace(/./g,x=>Math.random()<.5?x.toUpperCase():x)

If uniform randomness is not required, we can save 6 bytes by using the current time as the source of randomness:

s=>s.replace(/./g,x=>new Date&1?x.toUpperCase():x)

This tends to either uppercase or leave alone all letters at once.

\$\endgroup\$
2
  • \$\begingroup\$ "there should be a non-zero probability of outputting any of the following combinations: abc, Abc, aBc, abC, ABc, AbC, aBC or ABC", while yours can't output AbC because the time won't change so fast \$\endgroup\$
    – l4m2
    May 27, 2018 at 16:52
  • \$\begingroup\$ @l4m2 if you have a really slow machine, it might ;-) Maybe I should just remove that part though... \$\endgroup\$ May 28, 2018 at 3:09
7
\$\begingroup\$

R, 66 bytes

for(i in el(strsplit(scan(,""),"")))cat(sample(c(i,toupper(i)),1))

Try it online!

Another R answer.

\$\endgroup\$
1
  • \$\begingroup\$ I've been writing too much "regular" R code and didn't even think to try a for-loop! Nice one. \$\endgroup\$
    – Giuseppe
    Nov 29, 2017 at 22:36
6
\$\begingroup\$

Excel VBA, 74 71 64 Bytes

The Randomize call always makes random output costly in VBA :(

Anonymous VBE immediate window function that takes input from range [A1] and outputs to the VBE immediate window. Produces a 50% (on average) UCased output.

For i=1To[Len(A1)]:a=Mid([A1],i,1):?IIf(Rnd>.5,a,UCase(a));:Next
\$\endgroup\$
3
  • \$\begingroup\$ Hello Sir. you can save 2 bytes by removing Randomize: and changing Rnd with [RAND()>.5] . Or just ignore it. :) \$\endgroup\$
    – remoel
    Dec 1, 2017 at 9:52
  • \$\begingroup\$ @remoel, unfortunately, the [Rand()] call is only psuedo-random and has a period length of roughly 10^13, making it functionally identical to the un Randomized Rnd call, in fact the two use the same seed (which the Randomize call sets by using the timer function output). \$\endgroup\$ Dec 1, 2017 at 16:20
  • \$\begingroup\$ @romoel, I do however suppose that given the clarifications on the prompt that I could remove the Randomize call and instead use Rnd>.5 \$\endgroup\$ Dec 1, 2017 at 16:25
6
\$\begingroup\$

Charcoal, 8 7 bytes

⭆S‽⁺↥ιι

Try it online! Link is to verbose version of code. Explanation:

 S          Input string
      ι     Character
    ↥ι      Uppercase character
   ⁺        Concatenate
  ‽         Random element
⭆           Map over each character and join the result
            Implicitly print
\$\endgroup\$
4
\$\begingroup\$

Ruby, 40 Bytes

Lambda function that takes a string. Saved 1 byte thanks to Arnauld. Saved 5 bytes thanks to Snack.

->s{s.gsub(/./){|x|[x,x.upcase].sample}}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Welcome to PPCG! Could you save a byte with <1 instead of ==1? \$\endgroup\$
    – Arnauld
    Nov 29, 2017 at 21:57
  • 1
    \$\begingroup\$ 40 bytes \$\endgroup\$
    – Snack
    Nov 29, 2017 at 22:47
  • \$\begingroup\$ Nice work @displayname. FWIW when users improve their score, many like to "cross out" the old score with the <s> tag, e.g. "Ruby, <s>46</s> 40 bytes." Of course it's not required. \$\endgroup\$
    – Jordan
    Nov 30, 2017 at 15:48
3
\$\begingroup\$

APL+WIN, 37 bytes

⎕av[c-((n÷2)<n?n←⍴s)×32×s←98<c←⎕av⍳⎕]

Prompts for screen input, identifies lower case letters and randomly converts them to upper case.

\$\endgroup\$
3
\$\begingroup\$

R, 89 88 bytes

outgolfed by djhurio!

cat(sapply(el(strsplit(scan(,""),"")),function(x)"if"(rt(1,1)<0,toupper,`(`)(x)),sep="")

Try it online!

This program takes each character, and with probability 1/2 converts it to uppercase or leaves it alone. It's possible to tweak this probability by playing with different values of df and 0.

rt draws from the Student's t-distribution, which has median 0 with any degree of freedom (I selected 1 since it's the smallest number possible).

\$\endgroup\$
3
3
\$\begingroup\$

Wolfram Language (Mathematica), 52 49 44 bytes

StringReplace[c_/;Random[]<.5:>Capitalize@c]

Try it online!

Uses the operator form of StringReplace: providing it a rule (or a list of rules) but no string gives a function which applies that rule to any string you give it as input.

We could do a lot better (RandomChoice@{#,Capitalize@#}&/@#& is 34 bytes) if we decided to take as input (and produce as output) a list of characters, which people sometimes argue is okay in Mathematica because it's the only kind of string there is in other languages. But that's no fun.


-5 bytes thanks to M. Stern

\$\endgroup\$
3
  • \$\begingroup\$ Save one byte by using Capitalize \$\endgroup\$
    – M. Stern
    Nov 30, 2017 at 18:22
  • \$\begingroup\$ If you would ignore that Random is deprecated you could save another four bytes by implementing your own RandomChoice: StringReplace[c_/;Random[]<.5:>Capitalize@c], \$\endgroup\$
    – M. Stern
    Nov 30, 2017 at 18:48
  • \$\begingroup\$ @M.Stern I was trying to get Random to work at one point, but I forgot about the /; so I was trying to put into an If statement. Thanks! \$\endgroup\$ Nov 30, 2017 at 18:50
3
\$\begingroup\$

Ruby, 39 bytes

->s{s.gsub(/./){[$&,$&.upcase].sample}}

Largely inspired from displayname's answer. (I couldn't comment to suggest this one-byte-less version for lack of reputation, sorry displayname)

\$\endgroup\$
2
  • 3
    \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ Dec 1, 2017 at 11:19
  • \$\begingroup\$ I wasn't expecting greetings, how nice! Thank you! \$\endgroup\$ Dec 1, 2017 at 13:39
3
\$\begingroup\$

Swift 4, 86 bytes

s.map{let s="\($0)",u=s.uppercased();return u==s ? u:arc4random()%2==0 ? u:s}.joined()
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ Dec 1, 2017 at 11:19
3
\$\begingroup\$

Java 8, 46 bytes

This lambda is from IntStream to IntStream (streams of code points).

s->s.map(c->c>96&c<'{'&Math.random()>0?c-32:c)

Try It Online

Capitalization distribution

Whether to capitalize a letter used to be the quite sensible condition that Math.random()<.5, which was satisfied about half the time. With the current condition of Math.random()>0 (which saves a byte), capitalization occurs virtually every time, which makes a test program kind of pointless. But it does satisfy the randomness requirement.

Acknowledgments

  • -1 byte thanks to Olivier Grégoire
\$\endgroup\$
3
  • \$\begingroup\$ If you go the stream route, you can use code points and do 41 bytes. \$\endgroup\$ Nov 30, 2017 at 8:49
  • \$\begingroup\$ Well, that breaks if the input contains ASCII characters above z. I could throw it in with a qualification though. \$\endgroup\$
    – Jakob
    Nov 30, 2017 at 16:04
  • 1
    \$\begingroup\$ Fix for 6 more bytes. \$\endgroup\$ Nov 30, 2017 at 16:08
3
\$\begingroup\$

Funky, 55 bytes

s=>s::gsub("."c=>{0s.upper,s.lower}[math.random(2)](c))

Try it online!

Thanks to optional commas, it's one byte shorter to do 0s.upper in the table definition, which means the math.random will randomly pick either 1 or 2, than to do math.random(0,1) in the random and not have the 0.

\$\endgroup\$
3
\$\begingroup\$

R, 60 59 58 57 56 63 bytes

intToUtf8((s=utf8ToInt(scan(,"")))-32*rbinom(s,s%in%97:122,.5))

Try it online!

Different approach from the other two R answers here and here. Improved and fixed thanks to Giuseppe!

\$\endgroup\$
5
  • \$\begingroup\$ I did not know the sampling functions behaved like that! \$\endgroup\$
    – Giuseppe
    May 28, 2018 at 18:21
  • \$\begingroup\$ @Giuseppe Just when I thought this couldn't be golfed down... \$\endgroup\$
    – JayCe
    May 28, 2018 at 18:27
  • \$\begingroup\$ 57 bytes \$\endgroup\$
    – Giuseppe
    May 28, 2018 at 18:39
  • \$\begingroup\$ @Giuseppe Not only is this golfier but also more elegant! Love it! \$\endgroup\$
    – JayCe
    May 28, 2018 at 18:51
  • \$\begingroup\$ upon second view, this won't work when printable ascii characters above 90 like [, but this fixes it for +7 bytes which is still golfier than djhurio's answer \$\endgroup\$
    – Giuseppe
    Jun 1, 2018 at 15:31
3
\$\begingroup\$

05AB1E, 6 5 bytes

Thank you Adnan for -1 byte

uø€ΩJ

Try it online!

Explanation

uø€ΩJ   
u      Upper case of top of stack. Stack: ['ZZZAA']
 ø     Zip(a,b) (uses implicit input). Stack: ['zZ', 'zZ', 'zZ', 'AA', 'AA']
  €    Following operator at each element of its operand
   Ω   Random choice. Stack: ['z', 'Z', 'z', 'A', 'A'] (for example)
    J  Join a by ''. Stack: 'zZzAA'
       Implicit output

Method taken from @totallyhuman's answer

\$\endgroup\$
7
  • 1
    \$\begingroup\$ Will anyone ever beat 6? :P \$\endgroup\$ Nov 29, 2017 at 23:13
  • 1
    \$\begingroup\$ @ETHproductions If Jelly had a single byte operator for upper case like 05AB1E we would! \$\endgroup\$
    – dylnan
    Nov 29, 2017 at 23:15
  • 3
    \$\begingroup\$ You can leave the duplicate out :) \$\endgroup\$
    – Adnan
    Nov 30, 2017 at 9:07
  • 1
    \$\begingroup\$ Will anyone beat 5? :P \$\endgroup\$ Nov 30, 2017 at 16:26
  • 1
    \$\begingroup\$ @totallyhuman yes. You can leave out the J since a list of characters is considered a string. Making this improvement ties you for #1 alongside @Shaggy. You're welcome in advance :) \$\endgroup\$
    – Makonede
    Jan 31, 2021 at 0:30
3
\$\begingroup\$

Dyalog APL, 23 18 17 14 bytes

This is a function which takes a string and returns it with random capitalization (as specified in the question).

{(?2)⌷⍵,1⎕C⍵}¨

Edits: Answer improved using suggestions by @LdBeth and @EliasMårtenson at the APL Orchard.

New Edit: Answer improved using suggestion by @Adam at APL Orchard.

\$\endgroup\$
4
  • \$\begingroup\$ Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in APL page for ways you might be able to further golf your submission \$\endgroup\$
    – pxeger
    Sep 27, 2021 at 17:35
  • \$\begingroup\$ @pxeger Thanks - I'll check out that page now! By the way, do you have any tips for improving this answer / reducing the character count? \$\endgroup\$ Sep 27, 2021 at 17:55
  • \$\begingroup\$ Sorry, I don't know any APL, so I can't help you there. You coiuld ask in the APL chat room \$\endgroup\$
    – pxeger
    Sep 27, 2021 at 18:28
  • \$\begingroup\$ @pxeger Thanks for your suggestion. As you suggested, I've posted on the APL chat room - let's see if I get any replies! \$\endgroup\$ Sep 29, 2021 at 13:59
2
\$\begingroup\$

Ouroboros, 25 bytes

i.b*)..96>\123<*?2*>32*-o

Try it here

The only fancy part is the control flow, .b*). Let's talk about the rest first.

i..                    Get a character of input, duplicate twice
   96>                 Test if charcode greater than 96
      \                Swap with copy #2
       123<            Test if charcode less than 123
           *           Multiply the two tests (logical AND): test if it is lowercase letter
            ?          Random number between 0 and 1
             2*        Times 2
               >       Is lcase test greater? If test was 1 and rand*2 < 1, then 1, else 0
                32*-   Multiply by 32 and subtract from charcode to ucase lcase letter
                    o  Output as character

We then loop back to the beginning of the line. Control flow involves changing where the end of the line is; if it is moved to the left of the IP, execution terminates. Thus:

 .     Duplicate input charcode
  b*   Push 11 and multiply
    )  Move end of line that many characters to the right

When the charcode is positive, ) is a no-op, since the end of the line is as far right as it can go. But when all characters have been read, i gives -1. Then we move the end of the code -11 characters to the right--that is, 11 characters to the left. It takes a couple iterations, but eventually the IP is past the end of the code and the program halts.

\$\endgroup\$
2
\$\begingroup\$

MATL, 12 11 bytes

"@rEk?Xk]v!

Try it online!

Saved 1 byte thanks to @LuisMendo

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

Brachylog, 5 bytes

ụᶻṛᵐc

Try it online!

Explanation

Example input: "Test"

ụᶻ        Zip uppercase:      [["T","T"],["e","E"],["s","S"],["t","T"]]
  ṛᵐ      Map random element: ["T","e","S","T"]
    c     Concatenate:        "TeST"
\$\endgroup\$
2
\$\begingroup\$

Alice, 17 15 bytes

Thanks to Leo for saving 2 bytes.

/uRUwk
\i*&o.@/

Try it online!

Explanation

/...
\...@/

This is the usual framework for largely linear programs operating entirely in Ordinal mode.

i    Read all input as a string.
R    Reverse the input.
&w   Fold w over the characters of the string. w is nullary which means it
     doesn't actually use the individual characters. So what this does is that
     a) it just splits the string into individual characters and b) it invokes
     w once for each character in the string. w itself stores the current 
     IP position on the return address stack to begin the main loop which
     will then run N+1 times where N is the length of the string. The one
     additional iteration at the end doesn't matter because it will just
     output an empty string.
.    Duplicate the current character.
u    Convert it to upper case (does nothing for characters that aren't
     lower case letters).
*    Join the original character to the upper case variant.
U    Choose a character at random (uniformly).
o    Print the character.
k    If the return address stack is not empty yet, pop an address from it
     and jump back to the w.
@    Terminate the program.

I first tried doing this entirely in Cardinal mode, but determining if something is a letter just based on character code would probably take more bytes.

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

Pyth, 10 7 6 bytes

smO,r1

Saved 3 bytes thanks to ovs and 1 thanks to Steven H.

Try it online

Explanation

smO,r1
 m      Q   For each character in the (implicit) input...
   ,r1dd    ... get the capitalized version and the (implicit) character, ...
  O         ... and pick one at random.
s           Concatenate the result.
\$\endgroup\$
1
  • \$\begingroup\$ r1d=rd1, allowing you to implicit-input golf another byte out. \$\endgroup\$
    – Steven H.
    Nov 30, 2017 at 19:44
2
\$\begingroup\$

PHP, 63 53 bytes

while($a=$argv[1][$i++])echo rand()%2?ucfirst($a):$a;

Managed to reduce the code with 10 bytes by (partialy) following Titus' suggestion.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Nice one! No need for a space before $a. Try while(~$a=$argn[$i++]) instead of foreach (run as pipe). \$\endgroup\$
    – Titus
    Dec 2, 2017 at 7:47
  • \$\begingroup\$ Using that code i got a "Uncaught Error: Unsupported operand types" error. And i cant see why it does that, but i suspect the ~. (and maybe because i use PHP7 and the method only works for 5.6) \$\endgroup\$
    – RFSnake
    Dec 2, 2017 at 14:07
2
\$\begingroup\$

PowerShell, 57 56 bytes

-join([char[]]"$args"|%{(("$_"|% *per),$_)[(Random)%2]})

Try it online!

-1 byte thanks to briantist

Takes input as a string, explicitly casts the $args array to a string, casts it as a char-array, then feeds the characters through a loop. Each iteration, we 50-50 either output the character as-is $_ or convert it to upper-case "$_".ToUpper() (that's the ("$_"|% *per) garbage). That's chosen by getting a Random integer and taking it mod 2.

Those characters are left on the pipeline and then -joined back together into a single string, which is itself left on the pipeline and output is implicit.

\$\endgroup\$
2
  • \$\begingroup\$ You can save a single byte changing "$_".ToUpper() to ("$_"|% *per) :-/ \$\endgroup\$
    – briantist
    Dec 3, 2017 at 0:21
  • 1
    \$\begingroup\$ @briantist Good thing we don't care about readability. ;-) Thanks! \$\endgroup\$ Dec 4, 2017 at 15:29
2
\$\begingroup\$

Julia, 35 bytes

s->map(c->rand([c,uppercase(c)]),s)

Try it online!

Still pretty easy to read as a human. In Julia rand(A) returns a random element from A.

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$
    – Steadybox
    Dec 17, 2017 at 1:47
2
\$\begingroup\$

APL (Dyalog Unicode), 28 bytes

28 bytes (https://github.com/abrudz/SBCS/)
50 bytes (UTF-8)

{1(819⌶)@(?n⍴⍨?n←≢⍸~⍵∊⎕A)⊢⍵}

Inspired by Graham's APL+Win solution

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.