AlTeRnAtE tHe CaSe

44

6

For today's challenge, you must write a program or function that alternates the case of a string. However, you must ignore non-alphabetic characters. This means that every alphabetic character must have a different case than the preceding and following alphabetic character. This is slightly more complex than uppercasing every other letter for example. If you take a string such as

hello world

and convert every other character to uppercase, you'll get:

hElLo wOrLd

As you can see, the lowercase o is followed by a lowercase w. This is invalid. Instead, you must ignore the space, giving us this result:

hElLo WoRlD

All non-alphabetic characters must be left the same. The output can start with upper or lowercase, as long as it consistently alternates. This means the following would also be an acceptable output:

HeLlO wOrLd

Your program should work regardless of the case of the input.

The input string will only ever contain printable ASCII, so you don't have to worry about unprintable characters, newlines or unicode. Your submission can be either a full program or a function, and you may take the input and output in any reasonable format. For example, function arguments/return value, STDIN/STDOUT, reading/writing a file, etc.

Examples:

ASCII                                   ->  AsCiI
42                                      ->  42
#include <iostream>                     ->  #InClUdE <iOsTrEaM>
LEAVE_my_symbols#!#&^%_ALONE!!!         ->  lEaVe_My_SyMbOlS#!#&^%_aLoNe!!!
PPCG Rocks!!! For realz.                ->  PpCg RoCkS!!! fOr ReAlZ.
This example will start with lowercase  ->  tHiS eXaMpLe WiLl StArT wItH lOwErCaSe
This example will start with uppercase  ->  ThIs ExAmPlE wIlL sTaRt WiTh UpPeRcAsE
A1B2                                    ->  A1b2

Since this is , standard loopholes apply and the shortest answer in bytes wins!

James

Posted 2017-05-25T17:17:08.950

Reputation: 54 537

35Ugh, I've only just realised this was that meme xD – Beta Decay – 2017-05-25T17:26:22.780

@BetaDecay Hahaha, that was not my intention. More just unfortunate timing. I though of it as a chat-mini-challenge, and I like the idea behind it because it's subtly harder than it seems.

– James – 2017-05-25T17:28:14.383

4The next challenge is to print an ascii spongebob à la cowsay – Frambot – 2017-05-25T19:41:59.387

1Darn it! I just wrote a CJam script for this (as in yesterday) and deleted it. – Esolanging Fruit – 2017-05-26T01:58:14.147

2There is some missed potential for the title or at least the examples using either penguin of doom or sporks. – Ian – 2017-05-26T06:00:06.993

Answers

20

JavaScript (ES6), 66 63 bytes

Starts with uppercase.

s=>s.replace(/[a-z]/gi,c=>c[`to${(s=!s)?'Low':'Upp'}erCase`]())

Test cases

let f =

s=>s.replace(/[a-z]/gi,c=>c[`to${(s=!s)?'Low':'Upp'}erCase`]())

console.log(f("ASCII"))
console.log(f("42"))
console.log(f("#include <iostream>"))
console.log(f("LEAVE_my_symbols#!#&^%_ALONE!!!"))
console.log(f("PPCG Rocks!!! For realz."))
console.log(f("This example will start with lowercase"))
console.log(f("This example will start with uppercase"))
console.log(f("A1B2"))

Arnauld

Posted 2017-05-25T17:17:08.950

Reputation: 111 334

Exactly how I was going to do it. I think I can see where you can save a couple of bytes but I'm on my phone so can't test properly. – Shaggy – 2017-05-25T17:24:31.073

Yup, using a ternary is what I was going to suggest. – Shaggy – 2017-05-25T17:39:46.010

1How does the s=!s trick work? – user41805 – 2017-05-25T17:44:21.547

That's a nice little trick :) – Shaggy – 2017-05-25T17:44:33.280

7@KritixiLithos Because s is the input string, !s first evaluates to false (unless the input string is empty, in which case it would evaluate to true -- but an empty string will not generate any match anyway). After that, it just becomes a standard boolean operation, alternating between false and true. Also, we don't mind losing the content of s at this point because it was already used to feed .replace(). – Arnauld – 2017-05-25T17:49:24.933

-1 byte if you use [A-z], and remove the i flag – MayorMonty – 2017-05-25T18:48:10.083

3@MayorMonty Unfortunately, that would match a few symbols. An input such as "A[I" would fail. – Arnauld – 2017-05-25T18:50:55.497

12

05AB1E, 11 8 bytes

Code:

lvyJ¤aiš

Uses the 05AB1E encoding. Try it online!

Explanation:

l           # Lowercase the input
 vy         # For each element..
   J        #   Join the entire stack into a single string
    ¤a      #   Check if the last character is alphabetic
      iš    #   If true, swapcase the entire string

Adnan

Posted 2017-05-25T17:17:08.950

Reputation: 41 965

I love how I try going in blind, knowing I have to beat 11-bytes; then slowly go from 17 to 11 bytes and realize lvy¾Fš}Da½J is exactly what you already had ._. – Magic Octopus Urn – 2017-05-25T18:18:41.287

1@carusocomputing There is a much easier 8 byte solution :p – Adnan – 2017-05-25T18:21:47.793

4oh, yeah, *super* easy haha. – Magic Octopus Urn – 2017-05-25T18:25:43.797

How do we pronounce this language? Sable, perhaps? – Octopus – 2017-05-26T06:25:38.627

2@Octopus There is some discussion about this, but I use both 'osable' and 'osabie'. – Adnan – 2017-05-26T08:00:12.250

@Octopus the github page says that its Base, from the github page: 'If the name 05AB1E was interpreted as a hexadecimal number and converted to base64, it would result into "Base" ' – Marnix Bouhuis – 2017-05-28T10:27:33.633

@Marnix, that explains its origin, not it's pronunciation. – Octopus – 2017-05-29T16:18:15.850

1@octopus I literally say Oh-Five-Ay-Bee-One-Eee, I am not a creative man. – Magic Octopus Urn – 2017-06-13T18:08:48.730

@MagicOctopusUrn I do the same, although it's Zero-Five, not Oh-Five. ;p – Kevin Cruijssen – 2018-11-20T12:53:48.473

11

GNU Sed, 33

  • 5 bytes saved thanks to @TobySpeight

Score includes +1 for -r flag to sed.

s/([a-z])([^a-z]*.?)/\U\1\L\2/gi

Try it online.

Digital Trauma

Posted 2017-05-25T17:17:08.950

Reputation: 64 644

8

Jelly, 13 bytes

nŒsTm2
ŒlŒuǦ

Try it online!

How it works

ŒlŒsǦ  Main link. Argument: s (string)

Œl      Cast to lowercase.
    Ǧ  At indices returned by the helper link...
  Œu        apply uppercase.


nŒsTm2      Helper link. Argument: s (string)

 Œs         Apply swapcase to s.
n           Perform vectorizing not-equal comparison.
   T        Compute the truthy indices.
    m2      Select every other one, starting with the first.

Dennis

Posted 2017-05-25T17:17:08.950

Reputation: 196 637

7

Japt, 16 14 bytes

r"%l"_m"uv"gT°

Try it online!

Explanation

r              // RegEx replace input
 "%l"          // [A-Za-z] as first arg to replace
     _         // created function Z=>Z as second arg to replace
       "uv"gT° // alternates "u" & "v"
      m        // map Z to either "u" upper or "v" lower

powelles

Posted 2017-05-25T17:17:08.950

Reputation: 1 277

Very nice! You can remove the ,. Unless it's a number (i.e. [12]), Japt knows they're different items. I believe you can remove the &1 as well. – Oliver – 2017-05-25T18:11:11.807

Thanks @obarakon. The Japt documentation is a little sparse. – powelles – 2017-05-25T18:13:48.497

Thanks for using Japt. Feel free to ask questions, suggestions, etc. in the Japt chat room. There's also a Tips for Japt thread. :)

– Oliver – 2017-05-25T18:16:22.627

_m"uv"gT° Nice. I was just about to suggest that. – Oliver – 2017-05-25T20:23:28.157

@obarakon Yeah I saw where ETH responded to your question in the chat and it got me trying things out. – powelles – 2017-05-25T20:32:52.813

You can save 2 bytes using Japt v2 – Oliver – 2019-02-27T16:42:13.013

6

Python 3, 86 76 68 66 63 bytes

-2 bytes thanks to DJMcMayhem
-3 bytes thanks to Cyoce

x=0
for i in input():print(end=(2*i).title()[x]);x^=i.isalpha()

Try it online! or Try all test cases

Rod

Posted 2017-05-25T17:17:08.950

Reputation: 17 588

Two bytes shorter in python 3: Try it online!

– James – 2017-05-25T22:14:02.140

1any reason you can't do print(end=(2*i).title()[x])? – Cyoce – 2017-05-26T03:50:33.790

5

C (tcc), 60 57 56 bytes

Thanks to DigitalTrauma for noticing bit 5 is the only difference for ASCII upper/lower case.

Special thanks to zch for golfing off three more bytes.

Save one more byte from RJHunter's idea

l;f(char*s){for(;*s=isalpha(*s)?*s&95|++l%2<<5:*s;s++);}

Try it online!

cleblanc

Posted 2017-05-25T17:17:08.950

Reputation: 3 360

I golfed it a bit more, and modified so it works on all of gcc, tcc, clang. FWIW, gcc puts string literals in read-only memory, so I used strdup() to get pointers to read-write memory in the test-driver code.

– Digital Trauma – 2017-05-25T18:29:34.687

1@DigitalTrauma thanks for that. I should have recognized bit 5 was the difference between upper and lower. Nice ! – cleblanc – 2017-05-25T18:38:50.210

I tried to make this version recursive too, but couldn't get it any shorter.

– Digital Trauma – 2017-05-25T19:05:57.383

You can replace inner conditional with *s&~32|++l%2<<5 to save 3 bytes. – zch – 2017-05-26T10:18:13.413

Since the input promises to be printable ASCII, you can replace &~33 with &95 to save a further byte. – RJHunter – 2017-05-26T23:59:39.513

5

Alice, 18 bytes

/olZlYuN
@iy.u..//

Try it online!

Explanation

This program follows a lesser-known template for odd-length programs that run entirely in ordinal mode. The linearized version of this code is:

il.l.uN.YuZyo@

Explanation of code:

i - push input onto stack            ["Hello world!"]
l - convert to lowercase             ["hello world!"]
. - duplicate                        ["hello world!", "hello world!"]
l - convert to lowercase (should be no-op, but avoids what seems to be a bug in the TIO implementation)
. - duplicate again                  ["hello world!", "hello world!", "hello world!"]
u - convert to uppercase             ["hello world!", "hello world!", "HELLO WORLD!"]
N - difference between sets          ["hello world!", "helloworld"]
. - duplicate reduced string         ["hello world!", "helloworld", "helloworld"]
Y - unzip (extract even positions)   ["hello world!", "helloworld", "hlool", "elwrd"]
u - convert to uppercase             ["hello world!", "helloworld", "hlool", "ELWRD"]
Z - zip evens back into string       ["hello world!", "helloworld", "hElLoWoRlD"]
y - perform substitution             ["hElLo WoRlD!"]
o - output                           []
@ - terminate

Without using l on the duplicate, the stack after N would be ["helloworld", "helloworld"]. I strongly suspect this is a bug.

Nitrodon

Posted 2017-05-25T17:17:08.950

Reputation: 9 181

4

MATL, 16 15 bytes

Xktkyy-f2L))5M(

Try it online! Or verify all test cases.

Explanation

Consider input 'hello world'

Xk    % To upper case
      % STACK: 'HELLO WORLD'
t     % Duplicate top element
      % STACK: 'HELLO WORLD', 'HELLO WORLD'
k     % To lower case
      % STACK: 'HELLO WORLD', 'hello word'
yy    % Duplicate top two elements
      % STACK: 'HELLO WORLD', 'hello word', 'HELLO WORLD', 'hello word'
-     % Difference (of code points; element-wise)
      % STACK: 'HELLO WORLD', 'hello word', [-32 -32 -32 -32 -32 0 -32 -32 -32 -32 -32]
f     % Indices of nonzeros
      % STACK: 'HELLO WORLD', 'hello word', [1 2 3 4 5 7 8 9 10 11]
2L)   % Keep only even-indexed values (*)
      % STACK: 'HELLO WORLD', 'hello word', [2 4 7 9 11]
)     % Reference indexing (get values at indices)
      % STACK: 'HELLO WORLD', 'elwrd'
5M    % Push (*) again
      % STACK: 'HELLO WORLD', 'elwrd', [2 4 7 9 11]
(     % Assignment indexing (write values at indices). Implicit display
      % STACK: 'HeLlO wOrLd

'

Luis Mendo

Posted 2017-05-25T17:17:08.950

Reputation: 87 464

4

Ruby, 57 55 47 41 bytes

Byte count includes two bytes for command line options.
Run it for example like this: $ ruby -p0 alternate_case.rb <<< "some input"

gsub(/\p{L}/){($&.ord&95|32*$.^=1).chr}

With the p0 option, the entire input is consumed in one go, and the magical global $. is incremented to 1. This is later toggled between 0 and 1 and used for keeping the state.

Works with multiline input; Try it online!

Thanks to Ventero for amazing input -- check the comments for details.

daniero

Posted 2017-05-25T17:17:08.950

Reputation: 17 193

1Man, if it weren't for the fact that $. auto-increments with each gets call, a full program with the -p flag would've been shorter... – Value Ink – 2017-05-25T20:51:31.500

@ValueInk Hah didn't even think of using the -p switch, but yeah, that one's hard to get around if had to make it work for multiline inputs (which I think you should in this case). You could add the line $.+=1 on top to make it work, but then you're up to 56 bytes excluding the -p flag. And BEFORE{i=0} is way too long. Why isn't there another global integer? :D – daniero – 2017-05-25T21:11:44.367

Yeah, the problem is that you definitely need to work with multiple inputs with that solution in order to save space. Thankfully the -p flag usually counts as 1 byte by consensus, because ruby -pe 'your code' has an edit distance of 1 from ruby -e 'your code' so it is a tie with your solution at best. – Value Ink – 2017-05-25T21:22:46.650

11&$.+=1 allows you to drop the parentheses. And for completeness' sake, there is another global integer - it's unfortunately just read-only: $$. – Ventero – 2017-05-25T22:47:35.617

@Ventero thanks! – daniero – 2017-05-25T22:54:02.003

1Another thing about the command line flag: -p0 makes the interpreter read all available input in one go - so your code is only invoked once, allowing you to freely use $.. Combining that with the fact that gsub implicitly operates as $_.gsub! when specifying -p makes a full program significantly shorter: 48 characters for gsub(/[a-z]/i){[$&.upcase,$&.downcase][1&$.+=1]} and 2 for the p0 flag. – Ventero – 2017-05-25T22:56:25.377

1Final remark, I promise :) Once you're using -p0, you can actually save a few more characters in how you flip $. back and forth: Since it's now guaranteed to be 1 when your code is invoked, you can simply use $.^=1. – Ventero – 2017-05-25T23:04:19.673

2Turns out I lied, I have another comment :D As the input is guaranteed to only ever contain printable ASCII, we can use Ruby's support for Unicode categories in regular expressions: /\p{L}/ (Unicode category Letter) is one character shorter than /[a-z|/i. – Ventero – 2017-05-25T23:24:33.910

@Ventero oh wow, amazing stuff. Thanks a lot!! :) – daniero – 2017-05-25T23:34:51.273

@Ventero Hey, I got another Idea. Doesn't quite work yet -- Work in progress (really got to go to bed now): gsub(/\p{L}/){($&.ord&~(32*($.^=1))).chr} .. Too tired to see where the error is – daniero – 2017-05-25T23:47:34.947

instead of the BEFORE{i=0} thing you mentioned in a previous comment, you could do i||=0 – Cyoce – 2017-05-26T03:48:41.603

@daniero I'm sure you'll spot it when you're fresher, but the AND-NOT technique only works to unset the lowercase bit (upcase); you'd need OR to set the lowercase bit on an uppercase letter (so it can cover downcase). Switching between Boolean operators could be done cleverly but probably no shorter than switching between string methods. – RJHunter – 2017-05-26T05:58:58.920

@daniero: You first need to clear out bit 5 before toggling it with 32*$. to alternate between upper and lower case. After fiddling a bit with operator precedence, I think the shortest you can get with that approach is 42: gsub(/\p{L}/){($&.ord&~32|32*$.^=1).chr}. Unfortunately, Integer only has a [] method without corresponding []=, otherwise you could just set the bit directly ... – Ventero – 2017-05-26T22:25:05.170

1@Ventero Since the challenge limits input to ASCII, &95 should be safely equivalent to &~32 to clear the lowercase bit. – RJHunter – 2017-05-27T00:19:44.673

There we go :) Thanks again @Ventero, and RJHunter – daniero – 2017-05-27T13:31:39.147

4

Java 8, 99 bytes

a->{String r="";int i=0;for(int c:a)r+=(char)(c>64&c<91|c>96&c<123?i++%2<1?c|32:c&~32:c);return r;}

Explanation:

Try it here.

a->{                          // Lambda with char-array parameter and String return-type
  String r="";                //  Result-String
  int i=0;                    //  Flag for alteration
  for(int c:a)                //  Loop over the characters of the input
    r+=(char)                 //   And append the result-String with the following (converted to char):
      (c>64&c<91|c>96&c<123?  //    If it's a letter:
       i++%2<1?               //     And the flag states it should be lowercase:
        (c|32)                //      Convert it to lowercase
       :                      //     Else (should be uppercase):
        (c&~32)               //      Convert it to uppercase
      :                       //    Else:
       c);                    //     Simply append the non-letter character as is
                              //  End of loop (implicit / single-line body)
  return r;                   //  Return result-String
}                             // End of method

Kevin Cruijssen

Posted 2017-05-25T17:17:08.950

Reputation: 67 575

I couldn't get it shorter but you might be able to use (c+"").matches("[A-Za-z]") or Character.isLetter(c) to save bytes. – TheLethalCoder – 2017-05-26T11:31:01.053

@TheLethalCoder Both are longer than c>64&c<91|c>96&c<123 though. And since the I use int anyway for the Character.toUpperCase(...) and Character.toLowerCase(...) golfed parts (these: (char)(c&~32) and (char)(c|32)), I doubt I could make it shorter with either of those. – Kevin Cruijssen – 2017-05-26T11:54:33.777

1I thought you wouldn't be able to but worth posting to see if you could make use of them anyway – TheLethalCoder – 2017-05-26T11:56:10.657

@TheLethalCoder Ah ok. :) In some cases the first might help with a slightly different approach for other challenges, but for this challenge it's shorter as is. Thanks anyway. – Kevin Cruijssen – 2017-05-26T12:05:05.263

a->{String r="";int i=0,f=32;for(int c:a)r+=(char)(c>64&c<91|c>96&c<123?(f=~f):c);return r;}?? – Roman Gräf – 2017-05-26T13:25:07.573

@RomanGräf Umm.. but where does it use c in the (f=~f) part? Currently it doesn't really work..

– Kevin Cruijssen – 2017-05-26T13:38:35.590

3

Brachylog, 25 bytes

{ḷ|ụ}ᵐ.{ḷ∈Ạ&}ˢ¬{s₂{∈Ạ}ᵐ}∧

Try it online!

This is both long and slow.

Explanation

{   }ᵐ.                       The Output is the result of mapping on each char of the Input:
 ḷ                              Lowecase the char
  |                             Or
   ụ                            Uppercase the char
       {    }ˢ                In the Ouput, select the chars that:
        ḷ∈Ạ&                    when lowercased are in "abc...xyz" (ie are letters)
              ¬{       }∧     In that new string, it is impossible to find:
                s₂              a substring of 2 consecutive chars
                  {∈Ạ}ᵐ         where both of them are in the lowercase alphabet

Fatalize

Posted 2017-05-25T17:17:08.950

Reputation: 32 976

3

Perl 6,  32  30 bytes

{S:g/<:L><-:L>*<:L>?/$/.tclc()/}

Try it

{S:g{<:L><-:L>*<:L>?}=$/.tclc}

Try it

Expanded:

{  # bare block lambda with implicit parameter 「$_」

  S            # string replace (not in-place) implicitly against 「$_」

  :global

  {

    <+ :L >    # a letter
    <- :L >*   # any number of non-letters
    <+ :L >?   # an optional letter

  }

  =

  $/.tclc()    # uppercase the first letter, lowercase everything else
}

Brad Gilbert b2gills

Posted 2017-05-25T17:17:08.950

Reputation: 12 713

Pity you can't use .= in substitution regexes, otherwise you could do .=tclc – Jo King – 2019-12-23T04:51:30.443

3

q/kdb+, 51 42 38 bytes

Solution:

{@[x;;upper]1#'2 cut(&)x in .Q.a}lower

Example:

q){@[x;;upper]1#'2 cut(&)x in .Q.a}lower"hello world"
"HeLlO wOrLd"

Notes:

.Q.a        // abcde...xyz lowercase alphabet
(&) x in    // where, returns indices for where x (hello world) is an alpha
2 cut       // splits list into 2-item lists
1#'         // takes first item of each 2-item list; ie the indices to uppercase
@[x;;upper] // apply (@) upper to x at these indices

streetster

Posted 2017-05-25T17:17:08.950

Reputation: 3 635

3

Google Sheets, 264 bytes

=ArrayFormula(JOIN("",IF(REGEXMATCH(MID(A1,ROW(OFFSET(A1,0,0,LEN(A1))),1),"[A-Za-z]"),CHAR(CODE(UPPER(MID(A1,ROW(OFFSET(A1,0,0,LEN(A1))),1)))+MOD(LEN(REGEXREPLACE(LEFT(A1,ROW(OFFSET(A1,0,0,LEN(A1)))),"[^A-Za-z]","")),2)*32),MID(A1,ROW(OFFSET(A1,0,0,LEN(A1))),1))))

It's a big mess but it's a little easier if you expand it out:

=ArrayFormula(
  JOIN(
    "",
    IF(REGEXMATCH(MID(A1,ROW(OFFSET(A1,0,0,LEN(A1))),1),"[A-Za-z]"),
      CHAR(
        CODE(UPPER(MID(A1,ROW(OFFSET(A1,0,0,LEN(A1))),1)))
        +
        MOD(LEN(REGEXREPLACE(LEFT(A1,ROW(OFFSET(A1,0,0,LEN(A1)))),"[^A-Za-z]","")),2)*32
      ),
      MID(A1,ROW(OFFSET(A1,0,0,LEN(A1))),1)
    )
  )
) 

The pseudo-logic would run like this:

For each character {                                    // ArrayFormula()
  If (character is a letter) {                          // REGEXMATCH(MID())
    Return CHAR(                                        // CHAR()
      CODE(UPPER(letter))                               // CODE(UPPER(MID()))
      +
      If (nth letter found and n is odd) {32} else {0}  // MOD(LEN(REGEXREPLACE(LEFT())))
    )
  } else {
    Return character                                    // MID()
  }
}

Engineer Toast

Posted 2017-05-25T17:17:08.950

Reputation: 5 769

2

V, 17, 13 bytes

VUÍშáü$©/ì&

Try it online!

Or Verify all test cases!

HeXdUmP:

00000000: 5655 cde1 83a8 e1fc 24a9 2fec 26         VU......$./.&

Explanation:

This uses a compressed regex™️, so before explaining it, let's expand the regex out:

:%s/\v\a.{-}(\a|$)/\l&

The VU converts everything to uppercase. Then we run this:

:%                      " On every line:
  s/\v                  "   Substitute:
      \a                "     A letter
        .{-}            "     Followed by as few characters as possible
            (\a|$)      "     Followed by either another letter or an EOL
                  /     "   With:
                   \l   "     The next character is lowercased
                     &  "     The whole text we matched

Old/more interesting answer:

:se nows
Vuò~h2/á

James

Posted 2017-05-25T17:17:08.950

Reputation: 54 537

2

CJam, 26 24 bytes

qeu{_'[,65>&,T^:T{el}&}%

Try it online!

Explanation

q         e# Read all input.
eu        e# Uppercase it.
{         e# For each character:
 _        e#  Duplicate it.
 '[,65>&  e#  Set intersection with the uppercase alphabet.
 ,        e#  Length (either 0 or 1 in this case).
 T^:T     e#  XOR with T (T is initially 0), then store the result back in T.
 {el}&    e#  If The result of the XOR is true, lowercase the character.
}%        e# (end for)

Business Cat

Posted 2017-05-25T17:17:08.950

Reputation: 8 927

2

PHP, 71 Bytes

for(;a&$c=$argn[$i++];)echo ctype_alpha($c)?(ul[$k++&1].cfirst)($c):$c;

Try it online!

Jörg Hülsermann

Posted 2017-05-25T17:17:08.950

Reputation: 13 026

2

Retina, 32 bytes

T`l`L
01T`L`l`[A-Z][^A-Z]*[A-Z]?

Try it online!

First converts the input to uppercase, and then groups the input into matches containing up to two capital letters. The only time it will contain only one letter is if the last letter doesn't have a pair. Then it lowercases the first letter of each of these matches.

The 01 in the second stage translates roughly to: do not change the behaviour of this stage based on the match number, but only apply the changes to the first character of each match.

FryAmTheEggman

Posted 2017-05-25T17:17:08.950

Reputation: 16 206

2

Pyth, 11 bytes

srR~xZ}dGrZ

Try it here

Explanation

              # Z = 0; Q = eval(input())
srR~xZ}dGrZQ  # Auto-fill variables
         rZQ  # lowercase the input
 rR           # Apply the r function to each letter of the input with
   ~xZ}dG     # ... this as the other argument
   ~          # use the old value of the variable Z, then update it with the value of ...
    xZ        # Z xor ...
      }dG     # the variable d is a lowercase letter
              # because of how mapping works in pyth, d will contain the current letter
              # This causes Z to flip between 0 and 1, alternately upper and lower casing
              # the current character if it is a letter

FryAmTheEggman

Posted 2017-05-25T17:17:08.950

Reputation: 16 206

2

PowerShell, 86 bytes

-join($args[0]|%{if($_-match"[a-z]"-and($i=!$i)){"$_".toupper()}else{"$_".tolower()}})

Input is a [char[]] array.

Comments in code for explanation

# Join the array of string and char back together.
-join
    # Take the first argument and pass each element ([char]) down the pipe. 
    ($args[0]|%{
        # Check if this is a letter. Second condition is a boolean that changes at every pass 
        # but only if the current element is a letter. If not the condition never fires
        if($_-match"[a-z]"-and($i=!$i)){
            # Change the character to uppercase
            "$_".toupper()
        }else{
            # Output the character to lowercase. 
            # Special characters are not affected by this method
            "$_".tolower()
        }
    })

Matt

Posted 2017-05-25T17:17:08.950

Reputation: 1 075

2

Haskell, 105 83 + 2 4 + 1 byte of separator = 108 86 88 Bytes

import Data.Char
f#(x:y)|isLetter x=([toUpper,toLower]!!f)x:(1-f)#y|1>0=x:f#y
_#l=l

Function is (1#), starts lowercase. Try it online!

The sad thing is that this is longer than the Java and C# answers Thanks to Ørjan Johansen for saving 22 bytes by merging three lines into one!

Generic Display Name

Posted 2017-05-25T17:17:08.950

Reputation: 365

2I saw it needed those long imported functions so I didn't even try... but that's a bit much, you can merge some lines: f#(x:y)|isLetter x=([toUpper,toLower]!!f)x:(1-f)#y|1>0=x:f#y – Ørjan Johansen – 2017-05-29T02:29:18.583

Sorry for nitpicking, but I think 1# does not count as an anonymous function. In my understanding, one should be able to bind an anonymous function to an identifier, but e.g. f=1# won't work. Instead you need the section (1#) for +2 bytes. This is also implicitly stated in our community guidelines for golfing in Haskell, though maybe those should be adapted to explicitly mention this case.

– Laikoni – 2017-05-29T09:14:13.350

@Laikoni ok, answer updated – Generic Display Name – 2017-05-29T13:43:26.697

2

Perl 5, 24 bytes

23 bytes + 1 byte for -p.

Thanks to @Dada for -2 bytes.

s/\pl/--$|?uc$&:lc$&/eg

Try it online!

Dom Hastings

Posted 2017-05-25T17:17:08.950

Reputation: 16 415

Neat. \pl instead of [a-z] to 2 bytes tho :) – Dada – 2017-07-06T11:59:37.170

@Dada, I genuinely didn't know that! How didn't I know that!! Thank you! – Dom Hastings – 2017-07-06T12:06:13.717

I think I learned it from Ton Hospel, and I use it now and then (actually I tend to forget about it too often and use [a-z] instead!). If you wonder, it comes from perlrecharclass ;)

– Dada – 2017-07-06T12:09:31.717

1

Retina, 46 bytes

T`L`l
T`l`L`.(?=([^a-z]*|[a-z][^a-z]*[a-z])*$)

Try it online! Includes test cases.

Neil

Posted 2017-05-25T17:17:08.950

Reputation: 95 035

1

C 64 bytes

B;R(char *s){for(;*s=isalpha(*s)?(B=!B)?*s|=32:*s&=~32:*s;s++);}

Takes advantage of ascii encoding where upper and lower case letters are offset by 0x20.

user230118

Posted 2017-05-25T17:17:08.950

Reputation: 239

You don't need the ' ' space between char and *s – cleblanc – 2017-05-25T19:03:10.137

This looks very similar to @cleblanc's answer.

– Digital Trauma – 2017-05-25T19:08:32.573

I posted it when @cleblanc's post used toUpper() and toLower(). – user230118 – 2017-05-25T19:39:47.993

1My comment suggesting this approach was at 18:29:34Z. cleblanc's edit to incorporate this was at 18:37:36Z. Your answer was posted at 18:38:21Z. So I guess cleblanc's answer was less than a minute before your post. Your answer is remarkably similar to my suggestion, but I guess that's the nature of code-golf - often solutions in the same language will converge to the same thing - so I'll let it slide :) – Digital Trauma – 2017-05-26T00:15:22.340

1

PHP 5, 54 bytes

<?=preg_filter('/\pL/e','($0|" ")^a^aA[$i^=1]',$argn);

user63956

Posted 2017-05-25T17:17:08.950

Reputation: 1 571

1

C#, 100 bytes

s=>{var r="";int m=0;foreach(var c in s)r+=char.IsLetter(c)?(char)(++m%2>0?c|32:c&~32):c;return r;};

TheLethalCoder

Posted 2017-05-25T17:17:08.950

Reputation: 6 930

1

Python 3, 192 bytes

x=list(input())
s=[]
for i in x[1::2]:
 s.append(i)
 x.remove(i)
s.reverse()
while len(x)<len(s):
 x.append("")
while len(x)>len(s):
 s.append("")
for i in range(len(x)):
 print(end=x[i]+s[i])

Try it online!

user69279

Posted 2017-05-25T17:17:08.950

Reputation:

1

Groovy, 79 bytes

{x=0;it.toUpperCase().collect{(it==~/\w/)?x++%2?it:it.toLowerCase():it}.join()}

Magic Octopus Urn

Posted 2017-05-25T17:17:08.950

Reputation: 19 422

0

Convex, 16 bytes

¯{_U&,R^:R{¬}&}%

Try it online!

Convex port of @Business Cat's answer.

GamrCorps

Posted 2017-05-25T17:17:08.950

Reputation: 7 058

0

Python 3, 95 bytes

Not nearly as golfed as @Rod's, but I'm posting it nevertheless.

lambda s:"".join([s[i],[s[i].lower(),s[i].upper()][i%2]][s[i].isalpha()]for i in range(len(s)))

Try it online!

Fedone

Posted 2017-05-25T17:17:08.950

Reputation: 157

0

J, 40 bytes

(2|+/\@:e.&Alpha_j_)`(tolower,:toupper)}

Try it online!

This follows almost directly from the definition of Composite Item (}):

We stack the upper and lowercase version of the input for our two possibilities using (tolower,:toupper).

Next we create a boolean list to indicate whether each character is alphabetic: e.&Alpha_j_ and take the scan sum of that: +/\@: which creates a monotonically increasing list which increases only on alphabetic characters. Finally we turn that into a boolean list where evens are 0 and odds are 1: 2|.

Putting those parts together means we alternate between the lower and uppercase versions of our input whenever we encounter a new alphabetic character, and only then.

Jonah

Posted 2017-05-25T17:17:08.950

Reputation: 8 729

0

C# (Visual C# Interactive Compiler), 84 bytes

int m,c;for(;(c=Read())>0;)Write((char)(c>64&c<91|c>96&c<123?m++%2>0?c|32:c&~32:c));

Try it online!

Modified version of The Lethal Coder's answer that takes advantage of some of the features of the interactive compiler.

dana

Posted 2017-05-25T17:17:08.950

Reputation: 2 541

0

Japt v2.0a0, 11 bytes

r\lÈc^H*°Tv

Try it

Shaggy

Posted 2017-05-25T17:17:08.950

Reputation: 24 623

0

Acc!!, 110 bytes

N*8
Count i while _/256 {
_+_/520*(727/_)*2+_/776*(983/_)*4
Write _/8+32*(_%4/3-_%8%5/4)
(_+(_%8+2)/4)%2+N*8
}

Try it online!

Algorithm

Set toLower flag to 0
Read a character
While not EOL:
  Calculate isUpper and isLower flags
  If isUpper && toLower, output (character + 32)
  If isLower && !toLower, output (character - 32)
  Else, output character unchanged
  If isUpper or isLower, toggle toLower
  Reset isUpper and isLower, and read a new character

Accumulator partitioning

We reserve the lowest three bits of the accumulator for storing the flags: toLower in the 1's place, isUpper in the 2's place, and isLower in the 4's place. The rest of the accumulator, at the 8's place and above, stores the input character.

For example, with input of Hello World, after reading the H and calculating flags, the accumulator has a value of 578, or in binary:

1001000 0 1 0
   |    | | \-> toLower (false)
   |    | \---> isUpper (true)
   |    \-----> isLower (false)
   \----------> ASCII code for 'H'

After reading the space, the accumulator is 257:

0100000 0 0 1
   |    | | \-> toLower (true)
   |    | \---> isUpper (false)
   |    \-----> isLower (false)
   \----------> ASCII code for ' '

Code

Line 1

N*8

Stores the first input character and sets all the flags to 0.

Line 2

Count i while _/256 {

Loops while the accumulator value is >= 256 (i.e. the character's ASCII code is at least 32).

Line 3

_+_/520*(727/_)*2+_/776*(983/_)*4

Calculates the isUpper and isLower flags. The main trick here is using integer division for the inequalities. For example, if x is a printable-ASCII code, then 65 <= x is equivalent to x/65 with integer division: values smaller than 65 become 0, values between 65 and 126 become 1, and we don't have to worry about anything larger than 126. We can use this approach for all four inequalities (keeping in mind that the ASCII codes are all multiplied by 8 in the accumulator).

isUpper:

65 <= char <= 90
65*8 <= acc <= 90*8+7
acc/520 == 1 && 727/acc == 1

Expression: _/520*(727/_)

isLower:

97 <= char <= 122
97*8 <= acc <= 122*8+7
acc/776 == 1 && 983/acc == 1

Expression: _/776*(983/_)

This line, then, takes the accumulator and adds isUpper*2 + isLower*4 to it.

Line 4

Write _/8+32*(_%4/3-_%8%5/4)

Outputs the character, swapping case if necessary.

There are two instances in which we need to modify the ASCII value before output:

  1. isUpper is 1, toLower is 1
    • We need to convert the uppercase letter to lowercase by adding 32
    • The three flag bits are 011, i.e. acc%4 == 3
  2. isLower is 1, toLower is 0
    • We need to convert the lowercase letter to uppercase by subtracting 32
    • The three flag bits are 100, i.e. acc%8 == 4

We can simulate the equality test using mod and int-div. For example, acc%8 == 4 is equivalent to acc%8%5/4:

acc%8      0 1 2 3 4 5 6 7
     %5    0 1 2 3 4 0 1 2
       /4  0 0 0 0 1 0 0 0

This line, therefore, takes 1 if we need to convert upper-to-lower, subtracts 1 if we need to convert lower-to-upper, multiplies that by 32, adds it to the ASCII code, and outputs it.

Line 5

(_+(_%8+2)/4)%2+N*8

Toggle the toLower flag if necessary; inputs and stores a new character.

We need to toggle toLower if the character was a letter, i.e. either isUpper or isLower was set. The possible flag bit values are 010, 011, 100, and 101--i.e. 2 through 5 (note that 6 and 7 are not possible because a letter can't be both upper- and lowercase). This expression gives 1 for those values and 0 otherwise:

 _%8       0 1 2 3 4 5
    +2     2 3 4 5 6 7
(     )/4  0 0 1 1 1 1

Call this value isLetter. Then we want the new value of toLower to be toLower XOR isLetter (if isLetter is true, swap the value of toLower; otherwise, leave it unchanged). We can do XOR by adding the two values mod 2. Finally, we also read another character with N, multiply it by 8, and add it in.

DLosc

Posted 2017-05-25T17:17:08.950

Reputation: 21 213