35
\$\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\$

52 Answers 52

13
\$\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\$
  • \$\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\$ – Fabian Röling Dec 1 '17 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\$ – Misha Lavrov Dec 1 '17 at 7:51
11
\$\begingroup\$

Python 2, 66 65 bytes

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

Try it online!

\$\endgroup\$
10
\$\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\$
  • \$\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\$ – Matteo Italia Nov 30 '17 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 '18 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 '18 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 '18 at 2:44
7
\$\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
    \$\begingroup\$ I need to use ŒṘ more often to see how things are represented under the hood \$\endgroup\$ – dylnan Nov 29 '17 at 21:55
6
\$\begingroup\$

Perl 5, 23 bytes

22 bytes code + 1 for -p.

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

Try it online!

\$\endgroup\$
6
\$\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\$
  • \$\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 '18 at 16:52
  • \$\begingroup\$ @l4m2 if you have a really slow machine, it might ;-) Maybe I should just remove that part though... \$\endgroup\$ – ETHproductions May 28 '18 at 3:09
6
\$\begingroup\$

R, 66 bytes

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

Try it online!

Another R answer.

\$\endgroup\$
  • \$\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 '17 at 22:36
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\$
5
\$\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\$
  • \$\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 '17 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\$ – Taylor Scott Dec 1 '17 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\$ – Taylor Scott Dec 1 '17 at 16:25
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\$
  • 1
    \$\begingroup\$ Welcome to PPCG! Could you save a byte with <1 instead of ==1? \$\endgroup\$ – Arnauld Nov 29 '17 at 21:57
  • 1
    \$\begingroup\$ 40 bytes \$\endgroup\$ – Snack Nov 29 '17 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 '17 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
\$\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\$
  • 3
    \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – Martin Ender Dec 1 '17 at 11:19
  • \$\begingroup\$ I wasn't expecting greetings, how nice! Thank you! \$\endgroup\$ – Jérémie Bonal Dec 1 '17 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\$
  • 3
    \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – Martin Ender Dec 1 '17 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\$
  • \$\begingroup\$ If you go the stream route, you can use code points and do 41 bytes. \$\endgroup\$ – Olivier Grégoire Nov 30 '17 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 '17 at 16:04
  • 1
    \$\begingroup\$ Fix for 6 more bytes. \$\endgroup\$ – Olivier Grégoire Nov 30 '17 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\$
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\$
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\$
2
\$\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','ZZZAA']
 ø     Zip(a,b). Stack: ['zZ', 'zZ', 'zZ', 'AA', 'AA']
  €    Following operator at each element of it's operand
   Ω   Random choice. Stack: ['z', 'Z', 'z', 'A', 'A']
    J  Join a by ''. Stack: 'zZzAA'
        Implicit output

Method taken from @totallyhuman's answer

\$\endgroup\$
  • 1
    \$\begingroup\$ Will anyone ever beat 6? :P \$\endgroup\$ – ETHproductions Nov 29 '17 at 23:13
  • 1
    \$\begingroup\$ @ETHproductions If Jelly had a single byte operator for upper case like 05AB1E we would! \$\endgroup\$ – dylnan Nov 29 '17 at 23:15
  • \$\begingroup\$ Ooo... New command for random_pick eh? ε„luΩ.V was my attempt, nice one! \$\endgroup\$ – Magic Octopus Urn Nov 30 '17 at 0:55
  • 3
    \$\begingroup\$ You can leave the duplicate out :) \$\endgroup\$ – Adnan Nov 30 '17 at 9:07
  • 1
    \$\begingroup\$ Will anyone beat 5? :P \$\endgroup\$ – totallyhuman Nov 30 '17 at 16:26
2
\$\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\$
  • \$\begingroup\$ Save one byte by using Capitalize \$\endgroup\$ – M. Stern Nov 30 '17 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 '17 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\$ – Misha Lavrov Nov 30 '17 at 18:50
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\$
  • \$\begingroup\$ r1d=rd1, allowing you to implicit-input golf another byte out. \$\endgroup\$ – Steven H. Nov 30 '17 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\$
  • 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 '17 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 '17 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\$
  • \$\begingroup\$ You can save a single byte changing "$_".ToUpper() to ("$_"|% *per) :-/ \$\endgroup\$ – briantist Dec 3 '17 at 0:21
  • 1
    \$\begingroup\$ @briantist Good thing we don't care about readability. ;-) Thanks! \$\endgroup\$ – AdmBorkBork Dec 4 '17 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\$
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – Steadybox Dec 17 '17 at 1:47
2
\$\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\$
  • \$\begingroup\$ I did not know the sampling functions behaved like that! \$\endgroup\$ – Giuseppe May 28 '18 at 18:21
  • \$\begingroup\$ @Giuseppe Just when I thought this couldn't be golfed down... \$\endgroup\$ – JayCe May 28 '18 at 18:27
  • \$\begingroup\$ 57 bytes \$\endgroup\$ – Giuseppe May 28 '18 at 18:39
  • \$\begingroup\$ @Giuseppe Not only is this golfier but also more elegant! Love it! \$\endgroup\$ – JayCe May 28 '18 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 '18 at 15:31
1
\$\begingroup\$

Rebol, 61 bytes

u:func[t][n: random length? t t/(n): uppercase t/(n) print t]

Test:

>>c: "Test sTring"
>>u c
Test sTriNg
\$\endgroup\$
1
\$\begingroup\$

Jelly, 16 bytes

2ḶXø³L¤Ð¡ḊT
Œu¢¦

Try it online!

Explanation

2ḶXø³L¤Ð¡ḊT    First Link
2Ḷ             The list [0,1]
  X            Random element (1 is truthy, 0 is falsy)
   ø           Begin nilad
    ³L         Length of first input (the string)
      ¤        End nilad
       С      Random([0,1]) for each character in the input string and collect.
         Ḋ     The list had an extra None at the beginning. Don't know why. This removes it (the first element of the list)
          T    Get indices of all truthy 

Œu¢¦           Main Link
Œu             Capitalize
   ¦           At the indices in the list:
  ¢            The first link as a nilad (list of indices)

I couldn't get this to work in a single line. I also don't know why, but 2ḶXø³L¤Ð¡ gives the list [None,1,0,..,1] with 0s and 1s chosen randomly. The None is the reason for the in the first link.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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