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

34 Answers 34

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
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 '21 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 '21 at 21:21
  • \$\begingroup\$ Thanks @ovs , btw while fixing it I found a way to save another 1 \$\endgroup\$
    – AZTECCO
    Dec 1 '21 at 22:23
6
\$\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 '21 at 21:16
5
\$\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 '21 at 20:34
5
\$\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
  • 3
    \$\begingroup\$ I think ⌈@(2|≢?≢) works for 9 \$\endgroup\$
    – ovs
    Dec 1 '21 at 21:38
  • \$\begingroup\$ @ovs Yes, of course. Thank you! \$\endgroup\$
    – Adám
    Dec 2 '21 at 23:08
4
\$\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 '21 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 '21 at 20:04
  • 2
    \$\begingroup\$ You can replace Ø.ṁ with J, as Jelly supports cyclic indexing: JẊị"żŒu$. \$\endgroup\$
    – Adnan
    Dec 1 '21 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 '21 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 '21 at 20:34
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 '21 at 8:59
  • \$\begingroup\$ And save another 1 by merging condition+increment Try it online! \$\endgroup\$
    – AZTECCO
    Dec 2 '21 at 10:03
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\$

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\$
2
\$\begingroup\$

Perl 5 -F, 49 bytes

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

Try it online!

\$\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 '21 at 23:27
2
\$\begingroup\$

Ruby, 59 bytes

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

Try it online!

\$\endgroup\$
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 '21 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 '21 at 17:07
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 '21 at 2:01
  • 1
    \$\begingroup\$ @enzo oh, good catch, thanks! \$\endgroup\$
    – Riker
    Dec 3 '21 at 2:05
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 '21 at 10:09
  • \$\begingroup\$ @lyxal u sure bout that? (looks like another LazyList bug) \$\endgroup\$ Dec 5 '21 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 '21 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 '21 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 '21 at 22:04
1
\$\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\$
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\$
0
\$\begingroup\$

Python 3, 124 bytes:

import random as r
j=range
f=lambda s:(lambda v:''.join(chr(ord(s[i])-32*(i in v))for i in j(l)))(r.sample(j(l:=len(s)),l//2))
\$\endgroup\$
0
\$\begingroup\$

(new Array(s.length)).fill(0).map((i,j)=> j % 2).sort(() => Math.random() - 0.5).map((i, j) => (i ? s[j].toUpperCase() : s[j])).join("")

\$\endgroup\$
3
  • \$\begingroup\$ This site is for code golf. And shorter answer is better. So you may try to minimize your byte count by at least remove unnecessary space characters. Also, you should include what language you are using and the byte count in the post. And it would be even better if a code snippet or link to online runner is provided so everyone may test your code. \$\endgroup\$
    – tsh
    Dec 2 '21 at 12:03
  • \$\begingroup\$ How does this take input? It doesn't look like it has input. \$\endgroup\$
    – Wheat Wizard
    Dec 2 '21 at 12:30
  • \$\begingroup\$ Welcome to Code Golf! This doesn't actually have a uniform chance of capitalizing the different characters, as .sort(() => Math.random() - 0.5) is a biased way to shuffle. \$\endgroup\$ Dec 2 '21 at 14:29
0
\$\begingroup\$

Ly, 44 bytes

irysp>l[0f1f,,]p<[>sprl0y?[,sprl]psp<l' *-o]

Try it online!

This one works by generating a list of 0 1 pairs on a list the size of the input string. Then for each input character it reverses the list of 0 1 pairs a random number of times, then pops the top off the resulting stack. That value is used to decide whether or not to capitalize the character before printing it out.

  1. Prep the input strings
ir      - read input codepoints into the stack, reverse the stack
  ysp   - save the number of char, delete that from the stack
     >  - switch to an empty stack
  1. Generate a list of 0 1 pairs
      l[0f1f,,]p
      l[    ,,]p  - loop "n/2" times adding "0,1" pairs to the stack
        0f        - add a "0" to the stack, pull the iterating var forward
          1f      - add a "1" to the stack and pull the iterator forward again
  1. Process each of the input chars on the input stack
<[                         ] - loop until the input stack is empty
  *3.1*                      - get a random 0/1 from the boolean stack
                    <l       - back to input stack, load boolean 0/1 capitalization choice
                      ' *    - multiple " " by the boolean
                         -   - subtract to capitalize (of boolean was true)
                          o  - print the current input char

3.1 Pull a random boolean off the list

>                   - switch to the boolean stack
 sprl               - disrupt pattern on list, move top entry to the bottom
     0y?            - pick a random number between 0 and the stack size
        [,sp l]p    - loop that number of time, using backup cell for iterator val
            r       - reverse the stack
                sp  - save the random boolean to the backup cell
\$\endgroup\$
0
\$\begingroup\$

MathGolf, 14 bytes

δ^hr¥áÅ;v^mÅ~§

I/O as a list of characters.

Try it online.

Explanation:

δ              # Capitalize each character in the (implicit) input-list
               #  e.g. ['a','b','c','d','e'] → ['A','B','C','D','E']
 ^             # Zip it with the (implicit) input-list
               #  → [['a','A'],['b','B'],['c','C'],['d','D'],['e','E']]
  h            # Push the length (without popping)
               #  → 5
   r           # Pop and push a list in the range [0,length)
               #  → [0,1,2,3,4]
    ¥          # Mod-2 on each
               #  → [0,1,0,1,0]
     á         # Sort it by,
      Å        # using the following 2 characters as inner code-block:
       ;       #  Discard the value
        v      #  Push a random integer in the range [-2147483648,2147483647]
               #  e.g. [0,1,0,0,1]
         ^     # Zip these shuffled 0s/1s with the earlier pair of characters
               #  → [[['a','A'],0],[['b','B'],1],[['c','C'],0],[['d','D'],0],[['e','E'],1]]
          m    # Map over each,
           Å   # using 2 characters as inner code-block again:
            ~  #  Dump the pair and integer separated to the stack
             § #  Index the integer into the pair
               #  → ['a','B','c','d','E']
               # (after which the entire stack is output implicitly as result)
\$\endgroup\$
0
\$\begingroup\$

TI-Basic, 160 bytes

Input Str1
length(Str1
Ans/2≥randIntNoRep(1,Ans→S
"abcdefhijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ→Str2
".
For(I,1,dim(ʟS
Ans+sub(Str2,inString(Str2,sub(Str1,I,1))+26ʟS(I),1
End
sub(Ans,2,dim(ʟS

Output is stored in Ans and displayed. Only works on calculators that support randIntNoRep(.

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