DEV Community

loading...

Daily Challenge #34 - WeIrD StRiNg CaSe

dev.to staff on August 06, 2019

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...
pic
Editor guide
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
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
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
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'))
Collapse
itsasine profile image
ItsASine (Kayla)

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

Collapse
brightone profile image
Oleksii Filonenko

Elixir:

defmodule Case do
  require Integer

  def weird(string) do
    string
    |> String.graphemes()
    |> Enum.with_index()
    |> Enum.map(fn
      {char, i} when Integer.is_even(i) -> String.upcase(char)
      {char, _} -> String.downcase(char)
    end)
    |> Enum.join()
  end
end
Collapse
peter279k profile image
peter279k

Here is the simple solution with PHP:

function toWeirdCase($string) {
    $strings = explode(' ', $string);

    $stringsIndex = 0;
    foreach ($strings as $string) {
      $index = 0;
      for (; $index < strlen($string); $index++) {
        if ($index % 2 === 0) {
          $string[$index] = strtoupper($string[$index]);
        } else {
          $string[$index] = strtolower($string[$index]);
        }
      }

      $strings[$stringsIndex] = $string;
      $stringsIndex++;
    }

    return implode(' ', $strings);
}
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
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
kvharish profile image
K.V.Harish • Edited

My solution in js

const toWeirdCase = (str = '') => (str.split(' ').map((s) => ([...s].map((char, index) => (index % 2) ? char.toLowerCase() : char.toUpperCase())).join(''))).join(' ');
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
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
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
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
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
itsdarrylnorris profile image
Darryl Norris

PHP 💻

<?php

/**
 * Daily Challenge #34 - WeIrD StRiNg CaSe
 * @param  string $string
 * @return string
 */
function toWeirdCase(string $string): string
{
  return implode(" ",array_map(function($word) {
    $splitWord = str_split($word);
    return implode("", array_map(function($value, $key) {
      return ($key % 2 === 0) ? strtoupper($value) : strtolower($value);
    }, $splitWord, array_keys($splitWord)));

  }, explode(" ", $string)));
}


echo toWeirdCase('Weird string case');
// Output: 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..]
Collapse
hectorpascual profile image
Héctor Pascual

Python with a function :

def to_weird_case(string):
    weird_string = ''
    i = 0
    for c in string.lower():
        if i%2:
            weird_string += c
        else:
            weird_string += c.upper()
        i += 1
    return weird_string

One liner with list comprehension :

weird_case = ''.join([string[i].lower() if i%2 else string[i].capitalize() for i in range(0,len(string))])

Collapse
carmenhchung profile image
Carmen Chung

Hey! We loved this challenge and actually got three developers to live code a solution in 15 minutes (with commentary): youtu.be/Z1fQ7J5fZhY

We also release similar videos every week on other Javascript, HTML/CSS, Python and Ruby challenges, so don't forget to like and subscribe if you're interested! ♥️

Collapse
dbalseiro profile image
Diego Balseiro

Here is a little Haskell one-liner

import Data.Char (toUpper, toLower)

toWeirdCase :: String -> String
toWeirdCase = unwords . map (zipWith ($) (cycle [toUpper, toLower])) . words
Collapse
shaber profile image
ShaBer • Edited

A JS single line solution that works with multi-line texts:

toWeirdCase=s=>s.replace(/[A-z][^]?/g,m=>m[0].toUpperCase()+(m[1]||'').toLowerCase());
Enter fullscreen mode Exit fullscreen mode