35
\$\begingroup\$

Your input will be an English sentence, phrase, or word. It will only contain a-zA-Z' -,.!?. Your task is to take the input, remove spaces, and then redistribute capitalization such that letters at indexes that were capitalized before (and only letters at indexes that were capitalized before) are capitalized.

For example, if the input is A Quick Brown Fox Jumped Over The Lazy Dog, the (0-based) indexes of the capital letters are 0, 2, 8, 14, 18, 25, 30, 34, 39. Next, remove spaces from the input: AQuickBrownFoxJumpedOverTheLazyDog. Next, lowercase all letters, but uppercase those at 0, 2, 8, 14, 18, 25, 30, 34, 39: AqUickbrOwnfoxJumpEdovertHelazYdog, which is your output.

Input

Your input will be an English sentence, phrase, or word. It can only contain lowercase letters, uppercase letters, hyphens, apostrophes, commas, periods, question marks, exclamation marks, and spaces.

Output

The input with spaces removed, lowercase-d, with letters at the index of capital letters in the input uppercase-d.

NOTE: Your program cannot crash (error such execution terminates) with an IndexOutOfRange or similar error.

Test Cases

Hi! Test!
Hi!tEst!

A Quick Brown Fox Jumped Over The Lazy Dog
AqUickbrOwnfoxJumpEdovertHelazYdog

testing TESTing TeStING testing testing TESTING
testingtESTIngteStInGTEstingtestingtestiNG

TESTING... ... ... success! EUREKA???!!! maybe, don't, NOOOOO
TESTING.........success!eureKA???!!!maybe,don't,nooooo

Enter        PASSWORD ---------
Enterpassword---------

A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Z z
AabbCcddEeffGghhIijjKkllMmnnOoppQqrrSsttUuvvWwxxZz

  TEST
teST
\$\endgroup\$
7
  • \$\begingroup\$ Sandbox \$\endgroup\$
    – Stephen
    Commented Jun 28, 2017 at 21:06
  • \$\begingroup\$ 'For example, if the input is "A Quick Brown Fox Jumped Over The Lazy Dog", the (0-based) indexes of the capital letters are 0, 2, 8, 14, 18, 23, 27, 32' They are 0, 2, 8, 14, 18, 25, 30, 34, 39 \$\endgroup\$ Commented Jun 28, 2017 at 21:18
  • \$\begingroup\$ @LukeSawczak thank you, my bad \$\endgroup\$
    – Stephen
    Commented Jun 28, 2017 at 21:23
  • \$\begingroup\$ Traling spaces not allowed, I assume? \$\endgroup\$
    – Luis Mendo
    Commented Jun 28, 2017 at 21:38
  • \$\begingroup\$ @LuisMendo your assumption is correct. This is code-golf, right? :P \$\endgroup\$
    – Stephen
    Commented Jun 28, 2017 at 21:40

43 Answers 43

1
2
2
\$\begingroup\$

Ruby, 80 bytes

->a{n=a.downcase.delete' '
n.size.times{|i|(?A..?Z)===a[i]&&n[i]=n[i].upcase}
n}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ You can save a couple bytes by using n.gsub(/./){} instead of n.size.times{};n: n.gsub(/./){(?A..?Z)===a[i]?$&.upcase: $&}. \$\endgroup\$
    – Jordan
    Commented Dec 3, 2017 at 2:06
2
\$\begingroup\$

Perl, 92 bytes

$p[$i++]=$-[0]while s/[A-Z]/lc($&)/e;s/\s//g;for$c(@p){substr($_,$c,1)=~tr[a-z][A-Z]};print;

Explanation:

$p[$i++]=$-[0]while s/[A-Z]/lc($&)/e;   #get locations of caps into an array at the same time converting letters to lowercase

s/\s//g;   #delete all spaces

for$c(@p){substr($_,$c,1)=~tr[a-z][A-Z]};   #convert lowercase letters to uppercase where uppercase letters were present

print;   # print (of course) :)
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Welcome to PPCG! :) \$\endgroup\$
    – Stephen
    Commented Jul 3, 2017 at 20:37
  • \$\begingroup\$ You need to add -n flag to make your answer valid. A few golfing things: s/ //g is enough (no need \s), y/a-z/A-Z/ is the same as tr[a-z][A-Z], you can use -p flag so you don't need the last print, you don't need the parenthesis in lc$&. \$\endgroup\$
    – Dada
    Commented Jul 4, 2017 at 9:44
2
\$\begingroup\$

GNU sed, 67 + 1 = 68 bytes

+1 byte for -r flag.

:A
s/$/;/
:
s/([A-Z]);(.?)/;\l\1\u\2/
t
s/(\S);/;\1/
t
s/ ;//
/ /bA

Try it online!

Explanation

The algorithm is pretty simple:

  1. Insert a cursor (;) at the end of the line:

    :A
    s/$/;/
    :
    
  2. If the character before the cursor is an uppercase letter, lowercase it (\l) and uppercase the character after the cursor (\u), moving the cursor to the left, and branch back to :

    s/([A-Z]);(.?)/;\l\1\u\2/
    t
    
  3. Otherwise, if the character before the cursor is not a space, move the cursor to the left and branch back to ;:

    s/(\S);/;\1/
    t
    
  4. Otherwise, if the cursor is preceded by a space, delete both:

    s/ ;//
    
  5. Finally, if there are any spaces left, branch back to :A:

    / /bA
    
\$\endgroup\$
2
\$\begingroup\$

Jelly, 11 bytes

ŒlðḲFŒuT}¦n

Try it online!

Just a restructuring of Dennis' original solution to avoid repeating Œl.

Œl             Lowercase the input.
  ð            Make that the left argument to the following dyadic chain.
   Ḳ           Split on spaces,
    F          flatten out the splits,
     Œu        then uppercase that
       T}¦     at the indices where
Œlð       n    the lowercase doesn't equal the original.
\$\endgroup\$
2
\$\begingroup\$

Rust, 143 bytes

|s|str::to_lowercase(s).replace(' ',"").chars().zip(s.chars()).for_each(|(c,d)|print!("{}",if d.is_uppercase(){c.to_ascii_uppercase()}else{c}))

Try it online!

Ungolfed:

  |input: &str|
    input.to_lowercase()          // create lowercase string
         .replace(' ', "")        // remove all spaces
         .chars()                 // iterate over characters
         .zip(input.chars())      // zip with input character iterator
         .for_each(|(c, input_c)| // for each character in both strings:
           print!("{}",                  // print the following:
             if input_c.is_uppercase() { // if the input character is uppercase
               c.to_ascii_uppercase()    // `c` in uppercase
             }
             else { c }                  // else `c`
           )
         )

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

Arturo, 61 bytes

$->s[i:0map--s` `'c[c(upper? s\[i])?[upper][lower]'i+1]|join]

Try it!

Explanation

$->s[]            ; a function taking a string s
i:0               ; assign zero to i
map               ; map over...
--s` `            ; input without spaces...
'c[]              ; ...assigning current char to c
c                 ; push c
(upper? s\[i])?   ; is i'th character in (unmodified) input upper case?
[upper]           ; then uppercase c
[lower]           ; else lowercase it
'i+1              ; increment i
|                 ; then...
join              ; join mapped letters to string
\$\endgroup\$
1
\$\begingroup\$

C, 103 bytes

i,j,c;f(char*s){for(i=j=0;c=tolower(s[j++]);)c-32&&putchar(c-32*(s[i]>64&&s[i]<91&&c>96&&c<123))&&++i;}

Try it online!

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

Python 3, 125, 124 bytes

lambda s:''.join(c.upper()if i in(s.find(q)for q in s if q.isupper())else c for i,c in enumerate(s.replace(' ','').lower()))

Try it online!

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

Python 2, 106 105 bytes

s=input()
print''.join(map(lambda(c,u):[c.lower,c.upper][u](),zip(s.replace(' ',''),map(str.isupper,s))))

Edit: save one byte via print ''.join => print''.join.

Lambda form, 99 bytes

lambda s:''.join(map(lambda(c,u):[c.lower,c.upper][u](),zip(s.replace(' ',''),map(str.isupper,s))))
\$\endgroup\$
1
\$\begingroup\$

SCALA, 128 chars, 128 bytes

var l=s.toLowerCase().filter(x=>x!=32)
for(i<-0 to l.size-1){if(s(i).isUpper)l=l.substring(0,i)+l(i).toUpper+l.substring(i+1)}
l

Thanks for this challenge. Try it online!

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

q/kdb+, 49 bytes

Solution:

{@[a;(&)#:[a:lower x except" "]#x in .Q.A;upper]}

Examples:

q){@[a;(&)#:[a:lower x except" "]#x in .Q.A;upper]}"Hi! Test!"
"Hi!tEst!"

q){@[a;(&)#:[a:lower x except" "]#x in .Q.A;upper]}"A Quick Brown Fox Jumped Over The Lazy Dog"
"AqUickbrOwnfoxJumpEdovertHelazYdog"

q){@[a;(&)#:[a:lower x except" "]#x in .Q.A;upper]}"testing TESTing TeStING testing testing TESTING"
"testingtESTIngteStInGTEstingtestingtestiNG"

q){@[a;(&)#:[a:lower x except" "]#x in .Q.A;upper]}"TESTING... ... ... success! EUREKA???!!! maybe, don't, NOOOOO"
"TESTING.........success!eureKA???!!!maybe,don't,nooooo"

q){@[a;(&)#:[a:lower x except" "]#x in .Q.A;upper]}"Enter        PASSWORD ---------"
"Enterpassword---------"

q){@[a;(&)(#:[a:lower x except" "]#x)in .Q.A;upper]}"A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Z z"
"AabbCcddEeffGghhIijjKkllMmnnOoppQqrrSsttUuvvWwxxZz"

q){@[a;(&)#:[a:lower x except" "]#x in .Q.A;upper]}"  TEST"
"teST"

Explanation:

Find indices where input is uppercase and then apply function upper to those indices on a lowercase, space-removed version of the input string. Note that we cannot apply the function beyond the length of the string, so use take (#) to truncate the input string to length of the lowercase, space-removed version.

{@[a;where count[a:lower x except " "]#x in .Q.A;upper]} / ungolfed
{                                                      } / lambda function
 @[ ;                                           ;     ]  / apply FUNC to VAR at INDICES: @[VAR;INDICES;FUNC]
                                                 upper   / uppercase, upper["abc"] -> "ABC"
                                       x in .Q.A         / boolean list where input is in uppercase alphabet ABC..XYZ
                                      #                  / take this many elements from list on the right (ie truncate)
           count[                    ]                   / returns length of the stuff inside the brackets, count["ABC"] -> 3                                        
                         x except " "                    / remove " " from string
                   lower                                 / lowercase, lower["ABC"] -> "abc"
                 a:                                      / save in variable a
     where                                               / returns indices where true where[101b] -> 0 2
   a                                                     / our lowercased, space-stripped input

Bonus:

After reading the answers, thought I'd try a solution where I iterate over the input, so far I've only managed a 53 byte solution:

{a{$[y in .Q.A;upper x;x]}'#:[a:lower x except" "]#x}
\$\endgroup\$
1
\$\begingroup\$

Swift 3.0, 199 bytes

var s="AS Ff",i=[String](),p=[Int](),j=0;for c in s.characters{if c>="A"&&c<="Z"{p.append(j)};if c != " "{i.append(String(c).lowercased())};j=j+1};for c in p{i[c]=i[c].uppercased()};print(i.joined())

Try it Online!

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

PHP, 110 bytes

$q=strtr($s=$argn,[' '=>'']);foreach(str_split($s)as$k=>$v)echo$v<lcfirst($v)?ucfirst($q[$k]):lcfirst($q[$k]);

Breakdown

$q=strtr($s=$argn,[' '=>''])

We take our input ($argn) and store it in a smaller variable because we need it later, before stripping out all the spaces with strtr

foreach(str_split($s)as$k=>$v)

We then take our original string, split it into an array of characters, and loop through each of them.

echo$v<lcfirst($v)?ucfirst($q[$k]):lcfirst($q[$k])

We check to see if the current letter is uppercase (A is less than a probably because ASCII), and echo out the corresponding letter from the space-stripped string with the appropriate case.

\$\endgroup\$
1
2

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.