DEV Community

dev.to staff for The DEV Team

Posted on

Daily Challenge #34 - WeIrD StRiNg CaSe

The goal of this challenge is to write a function that accepts a string and returns the same string with all even indexed characters uppercased and all odd indexed characters lowercased.

This indexing should be zero-based with the index in position zero being considered even. The input string will consist of only alphabetical characters and spaces. Spaces should only be present when there are multiple words.

Example:
to_weird_case('String'); # => returns 'StRiNg'
to_weird_case('Weird string case') # => returns 'WeIrD StRiNg CaSe'

Happy coding~!


This challenge comes from user xDranik. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge for a future post? Email yo+challenge@dev.to with your suggestions!

Top comments (32)

Collapse
 
ynndvn profile image
La blatte

Here goes a simple oneliner:

toWeirdCase=(s)=>[...s].map((e,i)=>i%2?e.toLowerCase():e.toUpperCase()).join('');

And the result:

toWeirdCase('String'); // "StRiNg"
toWeirdCase('Weird string case'); // "WeIrD StRiNg cAsE"
Collapse
 
dance2die profile image
Sung M. Kim

I believe case should be printed as CaSe as first letter (index 0) should be always capitalized.

Collapse
 
ynndvn profile image
La blatte

Indeed! Didn't catch that! Here is a little fix for that:

toWeirdCase=(a)=>a.split` `.map(s=>[...s].map((e,i)=>i%2?e.toLowerCase():e.toUpperCase()).join``).join` `;

which output is:

toWeirdCase('String'); // "StRiNg"
toWeirdCase('Weird string case'); // "WeIrD StRiNg CaSe"
Collapse
 
kenbellows profile image
Ken Bellows

Index 0 refers to the first letter of the entire string; we don't need to consider each word separately, just the string as a whole

Thread Thread
 
dance2die profile image
Sung M. Kim

Sorry about that.
I meant it as index 0 of each word.

the example shows the result should be

to_weird_case('Weird string case') # => returns 'WeIrD StRiNg CaSe'
Thread Thread
 
kenbellows profile image
Ken Bellows • Edited

Ah, you're right, that's interesting. I hadn't noticed that discrepancy with the capital 'C' in 'CaSe'; that makes this a more interesting challenge!

The original post should probably call that out a little more clearly, because it raises additional questions: Should punctuation count as a word separator? e.g., should 'word-other' become 'WoRd-oThEr' or 'WoRd-OtHeR'? Or should we only worry about letters and spaces? What characters are we considering?

@thepracticaldev , any help here?

Thread Thread
 
dance2die profile image
Sung M. Kim

For some reason, CodeWars isn't loading for me so won't be able to check the edge cases... 🤔

Collapse
 
kenbellows profile image
Ken Bellows • Edited

Python solution:

toWeirdCase = lambda s: ''.join([c.lower() if i%2 else c.upper() for i,c in enumerate(s)])

print(toWeirdCase('String')) #=> StRiNg
print(toWeirdCase('Weird string case')) #=> WeIrD StRiNg cAsE

EDIT
@dance2die pointed out in this comment that the multi-word example in the post seems to suggest that each word should be considered and cased separately, rather than the whole string. In that case, this becomes a bit more interesting.

Here's a simple modification to account only for spaces separating words:

toWeirdCase = lambda s: ' '.join([wordToWeirdCase(w) for w in s.split(' ')])
wordToWeirdCase = lambda s: ''.join([c.lower() if i%2 else c.upper() for i,c in enumerate(s)])

print(toWeirdCase('String')) #=> StRiNg
print(toWeirdCase('Weird string case')) #=> WeIrD StRiNg CaSe

But this could get a lot more complex if we need to account for things like punctuation and other whitespace characters.

As one last example, here's one that handles alternative whitespace characters using regular expressions:

import re

toWeirdCase = lambda s: (
  s[:re.search(r'\S', s).start() if re.match(r'\s', s) else 0] +   # handle leading whitespace
  ''.join(
    [wordToWeirdCase(w) for w in re.findall(r'\S+(?:\s+)?', s)]
  )
)

wordToWeirdCase = lambda s: ''.join([c.lower() if i%2 else c.upper() for i,c in enumerate(s)])

print(toWeirdCase('String')) #=> 'StRiNg'
print(toWeirdCase('Weird string case')) #=> 'WeIrD StRiNg CaSe'
print(toWeirdCase('  hELLO world\tHOW\'S EVeryTHInG???')) #=> '  HeLlO WoRlD   HoW'S EvErYtHiNg???'
Collapse
 
inrsaurabh profile image
Saurabh Ranjan

In Js ( Many Optimised solutions are already given, just tried different way)

const to_weird_case = (string) => {
    let  newString = [];
    for( let i in string ) {
        if(i%2 == 0){
            newString.push(string[i].toUpperCase());
        } else {
            newString.push(string[i].toLowerCase());
        }
    }
    return newString.join('');
};

to_weird_case('Weird string case');
Collapse
 
andy profile image
Andy Zhao (he/him)

Ruby, not optimal 🙃

def to_weird_case(string)
  if string.include? " "
    string.split(" ").map { |word| word.split("") }.each do |letter_array|
      letter_array.each_with_index do|letter, index|
        letter.upcase! if index % 2 == 0 }}.map(&:join).join(" ")
      end
    end
  else
    string.split("").each_with_index do |letter, index|
      letter.upcase! if index % 2 == 0
    end.join
  end
end
Collapse
 
alvaromontoro profile image
Alvaro Montoro • Edited

JavaScript

function formatText(message) {
    return message.split(" ")
                  .map(function(el) {
                    return el.split('')
                             .map(function(letter, idx) {
                               return idx % 2 === 0 ? letter.toLowerCase() : letter.toUpperCase();
                             })
                             .join('');
                  })
                  .join(' ')
  }

And as an extension, I used that function to create a Sponge Bob Mocking meme generator! (which is the first thing that I thought when I saw the challenge)

Collapse
 
laurentiumolnar profile image
LaurentiuMolnar

A simple solution in Javascript:

function toWeirdCase(string) {
  return string.split(' ')
    .map(word => {
      return word.split('')
        .map((char, index) => {
          if (index % 2 === 0) return char.toUpperCase()
          return char
        })
        .join('')
    })
    .join(' ')
}

console.log(toWeirdCase('string'))
console.log(toWeirdCase('Weird string  case'))
Enter fullscreen mode Exit fullscreen mode
Collapse
 
itsasine profile image
ItsASine (Kayla)

At work, we just call this serial killer case :P

Collapse
 
room_js profile image
JavaScript Room

Solution in Dart. Simple and not the shortest one, I guess. But it works =)

toWeirdCase(String str) {
  var result = new List();

  for (int i = 0; i < str.length; i++) {
    result.add(i%2 == 0 ? str[i].toUpperCase() : str[i].toLowerCase());
  }
  return result.join();
}

Link to the playground: dartpad.dartlang.org/f01143ca792ed...

Collapse
 
kerrishotts profile image
Kerri Shotts

Here's mine -- I'll admit that it took a little to recognize that the index was supposed to be word-based, not for the entire string. But that's what test cases are for! :-)

const TRANSFORMER = {
    LOWER: String.prototype.toLowerCase,
    UPPER: String.prototype.toUpperCase
};

const transform = (v, which) => which.apply(v);

const weirdCase = str => 
 str.split(" ")
    .map((part) => Array.from(part)
                        .map((ch, idx) => transform(ch, idx & 1 ? TRANSFORMER.LOWER 
                                                                : TRANSFORMER.UPPER ))
                        .join(""))
    .join(" ");

Gist: gist.github.com/kerrishotts/e3a213...

Collapse
 
hanachin profile image
Seiei Miyagi
def to_weird_case(s) s.split(' ').map { @1.chars.map.with_index
 { @2.even? ? @1.upcase : @1.downcase }.join }.join(' ') end
Collapse
 
andy profile image
Andy Zhao (he/him)

Ah I tried map_with_index but that's not a method. Did not know there was a .map.with_index!

Collapse
 
hanachin profile image
Seiei Miyagi

I'm glad to hear that. Enumerable has so many methods, which is useful but I take a little bit time to remember them.

Collapse
 
tanguyandreani profile image
Tanguy Andreani • Edited

Ruby solution. Doesn’t use modulo.

Works with the strange edge case. Also sorry typed on tablet.

str = "Weird ,string case."

class << str
  def to_weird_case
    String.new.tap do |s|
      i = 0

      while i < self.length
        # work out with edge case
        if self[i] =~ /[^a-zA-Z]/
          s << self[i]
          i += 1
          next
        end

        # we add to_s because we may be out of bounds;
        # that way we get the empty string instead of nil
        # and an exception
        s << self[i].to_s.upcase
        s << self[i + 1].to_s.downcase
        i += 2
      end
    end
  end
end

str.to_weird_case
Collapse
 
sebvaldez profile image
Sebastian

Heres my ruby example

def to_weird_case (str)
  raise "Incorrect input, expected String" if str.class != String
  str.split(/\s/).map{|w| w.chars.each_with_index.map{|c,i| i%2==0 ? c.upcase : c }.join }.join(' ')
end

result

to_weird_case('string') => "StRiNg"
to_weird_case('Weird string case') => "WeIrD StRiNg CaSe"
Collapse
 
dance2die profile image
Sung M. Kim

I've implemented based off of La blatte's answer.

const caser = {
  0: c => c.toUpperCase(),
  1: c => c.toLowerCase()   
}
const mod = i => i % 2
const weirdCase = text => text.split(' ').map(word => 
    [...word].map((c, i) => caser[mod(i)](c)).join('')
).join(' ')

console.log(["String", "Weird string case"].map(weirdCase))

prints,

["StRiNg", "WeIrD StRiNg CaSe"]
Collapse
 
devparkk profile image
Dev Prakash • Edited
def weird_string (string) :
    result = ""
    for index in range(len(string)) :
        if index % 2 == 0 :
            result += string[index].upper()
        else :
            result += string[index].lower()
    return result

print (weird_string("Weird string case"))

Python one liner


def weird_string (string) :
    result = ("").join([string[i].lower() if i%2 else string[i].upper() for i in range(len(string))])
    return result

print(weird_string("Weird string case"))

Collapse
 
craigmc08 profile image
Craig McIlwrath

Haskell:

import Data.Char (toLower, toUpper)
import Control.Applicative

toWeirdCase :: String -> String
toWeirdCase = unwords . map weirdifier . words
              where weirdifier = getZipList
                               . (ZipList [if even i then toUpper else toLower | i <- [0..]] <*>)
                               . ZipList

I used applicative functors here mostly for fun. I think it looks nicer to define weirdifier as

weirdifier = zipWith (\i -> if even i then toUpper else toLower) [0..]