26
\$\begingroup\$

Given string s of even length as input, randomly capitalize exactly half of the letters.

  • You can assume the input will always be a non-zero, even length
  • You can assume the input will consist of only lowercase letters ([a-z])
  • Exactly half of the letters should be capitalized in the output
  • Every permutation that has exactly half of the characters capitalized should have an equal probability of being output

Scoring

This is so fewest bytes in each language wins!

\$\endgroup\$
1

41 Answers 41

11
\$\begingroup\$

05AB1E, 7 bytes

Code

Uses the 05AB1E codepage.

ā.rÈÅÏu

Try it online!

Explanation

             # example input: "abcdefgh"
ā            # Indices of the input                   -> ex. [1, 2, 3, 4, 5, 6, 7, 8]
 .r          # Randomly shuffle this list             -> ex. [5, 4, 6, 3, 2, 8, 1, 7]
   È         # Map (x % 2 == 0) on each element       -> ex. [0, 1, 1, 0, 1, 1, 0, 0]
    ÅÏ       # Apply the following on truthy indices:
      u      #   Convert to uppercase                 -> ex. "aBCdEFgh"
\$\endgroup\$
0
7
\$\begingroup\$

Python, 86 bytes

lambda s:bytes(map(int.__xor__,s,sample(len(s)//2*[0,32],len(s))))
from random import*

Attempt This Online!

Uses Rɪᴋᴇʀ's idea to toggle case using ^32, but taken a bit further.

-1 byte thanks to @ovs.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ -1 with sample instead of shuffle \$\endgroup\$
    – ovs
    Dec 1, 2021 at 21:16
6
\$\begingroup\$

R, 52 51 33 bytes

Or R>=4.1, 25 bytes by replacing the word function with \.

function(s)s-sample(seq(s))%%2*32

Try it online!

Inputs and outputs through vector of character codes.

Inspired by @Adnan's solution.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I got 49 bytes using characters instead of character codes, but I'll never beat 33... \$\endgroup\$ Dec 1, 2021 at 21:26
6
\$\begingroup\$

C (clang), 57 56 bytes

i,r;f(*s,z){for(i=z;s[r=rand()%z]>96?s[r]-=32,i-=2:i;);}

Try it online!

  • takes a pointer to a widechar string and modifies it.
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think i-- should be --i instead. Otherwise you can get an additional uppercase character. \$\endgroup\$
    – ovs
    Dec 1, 2021 at 21:21
  • \$\begingroup\$ Thanks @ovs , btw while fixing it I found a way to save another 1 \$\endgroup\$
    – AZTECCO
    Dec 1, 2021 at 22:23
6
\$\begingroup\$

Jelly, 8 bytes

ŒuJḂẊTƲ¦

Attempt This Online!

Using the mod-2 trick from Adnan's 05AB1E answer.

Explanation:

ŒuJḂẊTƲ¦

Œu   TƲ¦   uppercase at truthy indices:
  J          range [1..length(input()]
   Ḃ         each modulo 2
    Ẋ        random permutation

JḂ essentially creates [0, 1, 0, 1, ..., 0, 1] up to the length of the input.

Jelly, 9 bytes

ŒuJẊŒHḢƲ¦

Attempt This Online!

Explanation:

ŒuJẊŒHḢƲ¦

Œu     Ʋ¦   uppercase at indices:
  JẊ          random permutation of [1..length(input)]
    ŒH        split that list into two halves
      Ḣ       take the first of those two halves

I think there ought to be a shorter way of doing the JẊŒHḢ, perhaps by picking a random combinationnope. Or, at least, a shorter version of ŒHḢ.

\$\endgroup\$
1
  • \$\begingroup\$ nice golf, the 0,1,0,1 array is clever \$\endgroup\$ Dec 1, 2021 at 20:34
6
\$\begingroup\$

APL (Dyalog Extended), 14 9 bytes

−5 bytes thanks to ovs.

Anonymous tacit prefix function

⌈@(2|≢?≢)

Try it online!

 uppercase

@() at the positions indicated by the following mask:

≢?≢ shuffle the indices 1 through the tally of elements in the argument (lit. take n random elements from 1…n, without replacement)

2| division remainders when divided by 2

\$\endgroup\$
2
  • 4
    \$\begingroup\$ I think ⌈@(2|≢?≢) works for 9 \$\endgroup\$
    – ovs
    Dec 1, 2021 at 21:38
  • \$\begingroup\$ @ovs Yes, of course. Thank you! \$\endgroup\$
    – Adám
    Dec 2, 2021 at 23:08
5
\$\begingroup\$

JavaScript (Node.js), 76 bytes

f=s=>(S=Buffer(s).map(c=>c^=Math.random(n++)<.5?32:--n-n--,n=0),n?f(s):S)+''

Try it online!

Commented

f = s =>               // s = input string
( S =                  // S = output
  Buffer(s)            // turn s into a buffer
  .map(c =>            // for each ASCII code c in s:
    c ^=               //   update c:
      Math.random(n++) //     increment n
      < .5 ?           //     with 1/2 probability:
        32             //       turn c into uppercase
      :                //     or:
        --n - n--,     //       leave c unchanged and decrement n twice
    n = 0              //   start with n = 0
  ),                   // end of map()
  n ? f(s)             // try again if we haven't capitalized exactly
                       // half of the letters
    : S                // otherwise, stop and return S
)                      //
+ ''                   // coerce the output buffer back to a string
\$\endgroup\$
1
  • \$\begingroup\$ --n-n-- haha this part is clever, but a nightmare to read, dont forget your priorities! \$\endgroup\$
    – Kaddath
    Dec 2, 2021 at 9:02
3
\$\begingroup\$

J, 21 bytes

toupper@{~`]`[}-:@#?#

Try it online!

  • -:@#?# Randomly "Deal" ? half-the-length -:@# number of indices from all possible indices.
  • toupper@{~][} And Amend } just those indices with their uppercased versions toupper@{~.
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 154 bytes

-1 thanks to emanresu A, with their v<{} trick

s=>(t=(f=x=>x?f(x.slice(1)).flatMap(y=>[x[0]+y,x[0].toUpperCase()+y]):[""])(s).filter(w=>![...w].reduce((u,v)=>u+(v<{})*2-1,0)))[Math.random()*t.length|0]

Explanation:

  • (f=x=>x?f(x.slice(1)).flatMap(y=>[x[0]+y,x[0].toUpperCase()+y]):[""])(s): Recursively finds all ways to capitalize the string
  • .filter(w=>![...w].reduce((u,v)=>u+(v<{})*2-1,0)): Filters out items which don't have the correct number of capitalized letters, by checking if the sum of -1 (for capitalized) and 1 (for lowercase) is 0
  • [Math.random()*t.length|0]: Choose a random item
\$\endgroup\$
3
\$\begingroup\$

Jelly, 8 bytes

JẊị"żŒu$

Try It Online!

-2 bytes thanks to a clever trick from Adnan using cyclical indexing, thus tying pxeger's answer

JẊị"żŒu$    Main Link
J           [1, 2, ..., len(input)]
 Ẋ          random permutation of that
  ị"        vectorize - index (half of them are even, half are odd, and it wraps)
    żŒu$    the input zipped with itself capitalized
\$\endgroup\$
4
  • \$\begingroup\$ I actually had a version that used Ø. ... but had something longer than ; I wonder if I can combine it to get something shorter. \$\endgroup\$
    – pxeger
    Dec 1, 2021 at 20:04
  • 2
    \$\begingroup\$ You can replace Ø.ṁ with J, as Jelly supports cyclic indexing: JẊị"żŒu$. \$\endgroup\$
    – Adnan
    Dec 1, 2021 at 20:06
  • \$\begingroup\$ Much less smart than what Adnan just suggested, but if you replace ị"żŒu$ with Œu ... TƲ¦ you get 9 bytes: ato.pxeger.com/… \$\endgroup\$
    – pxeger
    Dec 1, 2021 at 20:09
  • \$\begingroup\$ Alternatively, Ø.ṁ can be JḂ as in my second answer (which was taken from @Adnan's 05AB1E answer) \$\endgroup\$
    – pxeger
    Dec 1, 2021 at 20:34
3
\$\begingroup\$

Factor + sequences.repeating, 43 39 bytes

[ "\0 "over length cycle randomize v- ]

Try it online!

            ! "hamburgers"
"\0 "       ! "hamburgers" "\0 "
over        ! "hamburgers" "\0 " "hamburgers"
length      ! "hamburgers" "\0 " 10
cycle       ! "hamburgers" "\0 \0 \0 \0 \0 "
randomize   ! "hamburgers" "\0\0\0    \0 \0"
v-          ! "hamBURGeRs"
\$\endgroup\$
3
\$\begingroup\$

Ruby, 59 bytes

->s{[*0...q=s.size].sample(q/2).map{|w|s[w]=s[w].upcase};s}

Try it online!

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

C (clang), 58 51 bytes

-1 thanks to AZTECCO
-6 with wide string and clang

i;f(*s,l){for(i=l/2;rand()%l--<i?s[l]^=32,--i:i;);}

Try it online!

Outputs by modifying the input string.

Each letter has a \$\frac in\$ chance of being capitalized, where \$i\$ is the number of remaining capital letters and \$n\$ is the number of remaining letters (including this one).

\$\endgroup\$
2
  • \$\begingroup\$ Very interesting! You can also switch to clang \$\endgroup\$
    – AZTECCO
    Dec 2, 2021 at 8:59
  • \$\begingroup\$ And save another 1 by merging condition+increment Try it online! \$\endgroup\$
    – AZTECCO
    Dec 2, 2021 at 10:03
3
\$\begingroup\$

Julia 1.0, 73 bytes

!s=(E=length(s);v=rand(E);prod(i->s[i]-32*(i∈sortperm(v)[1:E÷2]),1:E))

Try it online!

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

Uiua, 12 10 bytes

⍜▽⌵◿2⍏≡⋅⚂.

Try it

-2 thanks to chunes’s nice idea to use gap .

Explanation:

≡⋅⚂.

To each of the input’s rows , drop the item with gap and give a random value between 0 and 1.

rise gives the index of each number if you had sorted the list in ascending order.

◿2

Take each number modulus 2.

⍜▽⌵

under keep basically takes a list of 1’s and 0’s and a list of the same length, and applies a function to every item in the second list corresponding with a 1 in the first. absolute value , if given a character, uppercases it.

\$\endgroup\$
2
  • \$\begingroup\$ -2 no need to make a new list of random numbers, just stick them in a copy of the input. \$\endgroup\$
    – chunes
    Mar 13 at 18:18
  • \$\begingroup\$ @chunes nice, that was my first idea but i had rows(rand pop) because i forgot about gap \$\endgroup\$
    – noodle man
    Mar 13 at 18:53
2
\$\begingroup\$

Retina, 81 bytes

/^((?<-2>[a-z])|(?<-3>[A-Z])|([A-Z])|([a-z]))*(?(2)^)(?(3)^)$/^+/./_?(T`l`L
T`L`l

Try it online! Explanation:

/^((?<-2>[a-z])|(?<-3>[A-Z])|([A-Z])|([a-z]))*(?(2)^)(?(3)^)$/

Check whether the input contains equal numbers of lower and upper case letters. Groups 2 and 3 contain any excess upper and lower case letters respectively; if they are non-empty then the letter of the opposite case decrements the group, otherwise the letter increments the group appropriately. At the end both groups are required to be empty.

^+

Repeat while it does not.

/./_

Loop over each letter.

?(

Random choice between one of the following.

T`l`L

Uppercase.

T`L`l

Lowercase.

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

Wolfram Language (Mathematica), 52 bytes

MapAt[Capitalize,#,RandomSample[i=0;{++i}&/@#,i/2]]&

Try it online!

-16 bytes thanks to @att

\$\endgroup\$
1
  • 2
    \$\begingroup\$ 52 bytes outputting as a character list \$\endgroup\$
    – att
    Dec 1, 2021 at 23:27
2
\$\begingroup\$

C#, 145 bytes

Hey! I'm completely new to this and my answer will make that apparent. I thought I'd post so that I can refer back to later to see my progress. Let me know if I anything is incorrect involving my answer.

didn't include logging, output is the t string

string t="";int p=0;while(p!=s.Length/2){t="";p=0;foreach(char c in s){char l=c;if(new Random().Next(2)==0){l=char.ToUpper(l);p++;}t=$"{t}{l}";}}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Welcome to Code Golf! Using predefined variables for input or outputting by defining a variable are not permitted input formats according to our site-wide default policy, and the challenge poster has not modified these rules. However, you can define a function that takes s as an argument and returns t, which would be permitted by the default policy. This is a great first answer though, and I look forward to seeing your progress too :) \$\endgroup\$
    – hyper-neutrino
    Dec 2, 2021 at 17:07
  • \$\begingroup\$ Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in C# page for ways you can golf your program. Unfortunately, assuming the input/output is in a variable (s and t here) isn't an acceptable method of I/O. I suggest either turning this into a function or a full program \$\endgroup\$ Dec 2, 2021 at 17:07
2
\$\begingroup\$

ayr, 13 bytes

(];-){:2|#?.#

Try it!

Explained

       #?.# Roll N-sided die N times, where N is len of y
     2|     Convert this to a length-N boolean vector (half 1s, half 0s)
   {:       Use this to catalogue..
];-         A matrix of the string and the string with inverted caps
\$\endgroup\$
2
\$\begingroup\$

Python 2,127 119 bytes

Not super happy with this, I'll probably come back to it after class (or not, we'll see). Takes input from stdin using Python 2 input() rules - aka "test" rather than test.

Requires Python 2 for range returning a list, since that would require *x, instead of x otherwise, and would lose a byte on the print statement and I don't think you can gain more than 2 from inline variable assignments.

Using chr/ord is shorter than [s[i],s[i].upper()][i in x[::2]], I think that's optimal as well.

Thanks to enzo for -8, from switching from using a while loop to just str.join.

from random import*
s=input()
n=len(s)
r=range(n)
x=sample(r,n)
print''.join(chr(ord(s[i])-32*(i in x[::2]))for i in r)

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ 119 bytes using str.join instead of a while loop. \$\endgroup\$
    – enzo
    Dec 3, 2021 at 2:01
  • 1
    \$\begingroup\$ @enzo oh, good catch, thanks! \$\endgroup\$
    – Riker
    Dec 3, 2021 at 2:05
2
\$\begingroup\$

In true Perl spirit, TMTOWTDI:

Perl 5 -MList::Util=shuffle -F, 35 bytes

map$_=uc,(shuffle@F)[1..@F/2];say@F

Try it online!

Perl 5 -F, 49 bytes

@k{0..$#F}=1;map$_=uc,@F[(keys%k)[1..@F/2]];say@F

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Vyxal, 9 bytes

ẏṖ℅Ih⁽N¨M

Try it Online!

Explanation:

ẏ         # List of [0..len(input))
 Ṗ℅       # Random permutation
   Ih     # First half of the list
     ⁽N¨M # Toggle case of the indexes in the list

There is actually a dedicated builtin for Random Permutation, which is faster, but there is a bug in it, so we have to get every permutation and choose a random one.

\$\endgroup\$
2
  • \$\begingroup\$ There's no bug anymore \$\endgroup\$
    – lyxal
    Dec 4, 2021 at 10:09
  • \$\begingroup\$ @lyxal u sure bout that? (looks like another LazyList bug) \$\endgroup\$ Dec 5, 2021 at 14:44
1
\$\begingroup\$

Python 3, 105 bytes

lambda s:''.join([x,x.upper()][y%2]for x,y in zip(s,sample([*range(len(s))],len(s))))
from random import*

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ The range() iterable is enough for sample(), no need to convert it to list: sample(range(len(s)),len(s)) \$\endgroup\$
    – movatica
    Dec 6, 2021 at 11:00
1
\$\begingroup\$

Excel, 89 bytes

=LET(x,LEN(A1),y,RANDARRAY(x),CONCAT(CHAR(CODE(MID(A1,SEQUENCE(x),1))-(y>MEDIAN(y))*32)))

This breaks the string into an array of characters. Then generates an array of random numbers of the same length. For each number in the random array that is greater that the median of the array, the corresponding letter is changed to upper case (ASCII value reduced by 32). Then all of the characters are concatenated.

\$\endgroup\$
1
\$\begingroup\$

Perl 5 -pF, 43 bytes

1 byte saved thanks to @Kjetil S!

$F[rand@F]&=_,$_=join"",@F
while@F/2>y;A-Z;

Try it online!


Perl 5 + -pa, 38 bytes

-5 bytes using a space separates string (Thanks @Kjetil S!)

$F[rand@F]&=_,$_="@F"
while@F/2>y;A-Z;

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Good answer! @F*rand can be replaced by rand@F. Also, if you agree, since nothing in the challenge clearly forbids adding a space between the letters in the output join"",@F can be replaced by $_="@F" to save 5 extra bytes. \$\endgroup\$
    – Kjetil S
    Dec 2, 2021 at 19:00
  • \$\begingroup\$ @KjetilS Yes of course! I've been golfing on my phone and sure I tried rand@F which didn't work for some reason and stopped using it, but I probably just messed it up somehow! Thank you! The list of chars might be pushing it a little but I've added it too. Thanks! \$\endgroup\$ Dec 2, 2021 at 22:04
1
\$\begingroup\$

Raku, 41 bytes

{[~] {@_[pick @_/2,^@_]».=uc;@_}(.comb)}

Try it online!

  • .comb splits the input string into a list of characters, which is then fed to the brace-delimited anonymous function, which takes the list in the @_ array. This is just a short way to get an array with writeable elements without having to declare one explicitly.
  • pick @_ / 2, ^@_ randomly selects half of the indices in the character array.
  • @_[...]».=uc slices into the array of characters with the random selection of indices, and uppercases the characters at those indices. The original array is then returned.
  • [~] concatenates the characters into a single string.
\$\endgroup\$
1
\$\begingroup\$

YASEPL, 100 bytes

=1'±""=a®1=b$a/=i`1=r¢1,a-=c¥r,1=u$32`2!t$u»}3,c,3!u+|2`3!u}2,91-32»!¤r,u!i+}2,b=i`4=c¥i,1~!i+}2,a,4

explanation:

=1'±""=a®1=b$a/=i`1=r¢1,a-=c¥r,1=u$32`2!t$u»}3,c,3!u+|2`3!u}2,91-32»!¤r,u!i+}2,b=i`4=c¥i,1~!i+}2,a,4             packed
=1'                                                                                                              get user input and set it to var1
   ±""                                                                                                           split it every character (to bypass a bug in the yasepl code)
      =a®1                                                                                                       A = length of var1
          =b$a/                                                                                                  B = length of var1 divided by 2
               =i                                                                                                increment variable
                 `1                                                      !i }2,b                                 do while I < B...
                   =r¢1,a-=c¥r,1                                                                                 C = character from var1 at random position
                                =u$32`2!t$u»}3,c,3!u+|2`3!u}2,91                                                 if C is uppercase then continue loop, do not increment. if not, continue
                                                                -32»!¤r,u                                        make character at the position lowercase in list
                                                                           +                                     increment I
                                                                                =i`4=c¥i,1~!i+}2,a,4             join list together once done and print it
\$\endgroup\$
1
\$\begingroup\$

Scratch,452 bytes

Although Scratch functions do not distinguish between uppercase and lowercase, still the letters in the different cases can be stored and outputted. We assume that every position in the string has equal chances to be capitalized.

ask and wait
set L to ABCDEFGHIJKLMNOPQRSTUVWXYZ
set i to 
repeat until length of R>(length of answer)/2-1
 set t to pick random 1 to length of answer
 if not R contains t? then
  add t to R
repeat length of answer
   if R contains i? then
    set j to 1
    repeat 26
     if letter i of answer = letter j of L then
      set a to letter j of L
     change j by 1
    else
     set a to letter i of answer
    set C to join C a
    change j by 1
say C

enter image description here

Input:

abcdefghijklmnopqrstuvwxyz

Output:

enter image description here

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

Charcoal, 20 bytes

W⁻⊗LΦKA№ακLθP⭆θ‽⁺κ↥κ

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

W⁻⊗LΦKA№ακLθ

Repeat until uppercase letters make up exactly half of the canvas...

P⭆θ‽⁺κ↥κ

... output the input string but randomly uppercase each letter.

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

APL+WIN, 37 bytes

Prompts for string

s[i]←s[i←(.5×⍴s)?⍴s←⎕av⍳⎕]+48⋄⎕av[s]

Try it online!Thanks to Dyalog Classic

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