DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #210 - Separate Capitalization

Given a string, capitalize the letters that occupy even indexes and odd indexes separately, and return as shown below. Index 0 will be considered even.

For example, capitalize("abcdef") = ['AbCdEf', 'aBcDeF']. The input will be a lowercase string with no spaces.

Tests

capitalize("dev")
capitalize("method")
capitalize("hello")

Good luck!


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

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

Top comments (18)

Collapse
 
aminnairi profile image
Amin • Edited

Elm

Note: returning a tuple because returning a List String would mean it can be a list of 0 element as it can be a list of 10, 100, 1000, Infinity elements. Returning a Tuple gives the information to the user that this function will always return two elements in this case, which is suggested by the goal of this challenge. It will be then possible to extract them easily with the Tuple.first & Tuple.second functions.

even : Int -> Bool
even integer =
    modBy 2 integer == 0


odd : Int -> Bool
odd integer =
    not <| even integer


upperIf : ( Int -> Bool ) -> Int -> Char -> Char
upperIf predicate index character =
    if predicate index then
        Char.toUpper character

    else
        character


capitalizeIf : ( Int -> Bool ) -> String -> String
capitalizeIf predicate string =
    string
        |> String.toList
        |> List.indexedMap ( upperIf predicate )
        |> String.fromList


capitalize : String -> ( String, String )
capitalize string =
    ( capitalizeIf even string, capitalizeIf odd string ) 
Collapse
 
not_jffrydsr profile image
@nobody

This is a hallmark of proper functional programming. Elm looks intimidating than more traditional grammars but it's essentially strongly-typed function composition. I love it, and the outer function reads like english.

Collapse
 
aminnairi profile image
Amin • Edited

I won't lie, since this was my first real functional programming language, it was tough, really tough. And this is essentially due to the fact that I was not used to no parens (or not at the same position at least) and function composition mainly.

But functional programming is like a muscle. The best competitors are working hard to obtain a great physical condition. This is the same thing for people like you and me that are used to procedural or oriented-object programming. It requires a lot of practices to get out of our habits.

But when you practiced enough, you'll start to love functional programming and that is the only certainty you have. The rest is up to you. And actually, since I'm a Web Developer, and doing most of my stuff in JavaScript at work (I hope I get to include Elm one day) this has made me a better overall JavaScript developer. There is no time wasted on learning this language, trust me.

Collapse
 
fluffynuts profile image
Davyd McColl
function capitalize(str) {
  return str.split("").reduce((acc, cur, i) => {
    const 
      odd = i % 2,
      upper = cur.toUpperCase();
    acc[0] += !odd ? upper : cur;
    acc[1] += odd ? upper : cur;
    return acc;
  }, ["", ""]);
}
Collapse
 
not_jffrydsr profile image
@nobody

Interesting JS solution....I haven't seen ternary operators used so haphazardly before, I'm not comfortable with them still.

Collapse
 
avalander profile image
Avalander • Edited

Scala

A good old fold and I use the Next type to know which side to capitalize next.

sealed trait Next
case object Left extends Next
case object Right extends Next

def capitalize (str: String): (String, String) = {
  val (l, r, _) = str.foldLeft(("", "", Left: Next)) {
    case ((l, r, n), c) => n match {
      case Left  => (l :+ c.toUpper, r :+ c.toLower, Right)
      case Right => (l :+ c.toLower, r :+ c.toUpper, Left)
    }
  }
  (l, r)
}

println(capitalize("abcdef")) // ("AbCdEf", "aBcDeF")
Collapse
 
dmfay profile image
Dian Fay

SQL:

[local] dian#dian= WITH seq AS (
  SELECT regexp_split_to_table('string', '') AS c
), capitalized AS (
  SELECT
    CASE
      WHEN row_number() OVER () % 2 = 0 THEN upper(c)
      ELSE lower(c)
    END AS even,
    CASE
      WHEN row_number() OVER () % 2 = 1 THEN upper(c)
      ELSE lower(c)
    END AS odd
  FROM seq
)
SELECT
  string_agg(even, '') AS even,
  string_agg(odd, '') AS odd
FROM capitalized;
  even    odd   
────────┼────────
 sTrInG  StRiNg
(1 row)

Time: 0.613 ms

Break the string down into a table with one character per row, use the row_number window function to capitalize it each way, then reassemble the final product; the latter two steps can't be combined because window functions can't be nested in aggregate functions.

Collapse
 
craigmc08 profile image
Craig McIlwrath

Kinda silly solution using 2 mutually recursive functions (Haskell)

import Data.Char (toUpper, toLower) 

skip :: String -> String
skip [] = [] 
skip (c:cs) = c : capitalize' cs

capitalize' :: String -> String
capitalize' [] = [] 
capitalize' (c:cs) = toUpper c : skip cs

capitalize :: String -> (String, String) 
capitalize cs = (capitalize' cs, skip cs) 
Collapse
 
avalander profile image
Avalander

Ooh, clever! I like it!

Collapse
 
savagepixie profile image
SavagePixie • Edited

I'm a bit late to the party, but here's my Elixir solution:

defmodule Letters do
  import Integer, only: [ is_even: 1, is_odd: 1 ]

  def capitalise(str) do
    str
      |> String.split("", trim: true)
      |> Enum.with_index
      |> Enum.map(&_mapper/1)
      |> Enum.unzip
      |> _join
  end

  defp _mapper({ letter, idx })
    when is_even(idx) do
      { String.capitalize(letter), String.downcase(letter) }
    end
  defp _mapper({ letter, idx })
    when is_odd(idx) do
      { String.downcase(letter), String.capitalize(letter) }
    end
  defp _join({ a, b }), do: { Enum.join(a), Enum.join(b) }
end
Collapse
 
ksyula profile image
Ksenia • Edited

One more Python solution:

def capitalize(s: str) -> list:
    cap_s_even, cap_s_odd = "", ""
    for i in range(0, len(s)):
        if i % 2 == 0:
            cap_s_even+=s[i].upper()
            cap_s_odd+=s[i]
        else:
            cap_s_even+=s[i]
            cap_s_odd+=s[i].upper()
    return [cap_s_even, cap_s_odd]
Collapse
 
lordapple profile image
LordApple
#!/bin/sh

ARR=$(seq 0 $(( ${#1} - 1 )))
LOWER=$(echo "$1" | tr '[:upper:]' '[:lower:]')

for x in $ARR; do 
  (( $x % 2 == 0 )) && ARR_EVEN+=$(echo "${LOWER:$x:1}" | tr '[:lower:]' '[:upper:]') || ARR_EVEN+=$(echo "${LOWER:$x:1}")
  (( $x % 2 )) && ARR_ODD+=$(echo "${LOWER:$x:1}" | tr '[:lower:]' '[:upper:]') || ARR_ODD+=$(echo "${LOWER:$x:1}")
done

echo ${ARR_EVEN[@]} ${ARR_ODD[@]}

Here is some shit I wrote using shellscript

Collapse
 
nilbert profile image
Nilbert

Ruby

method = ->(s) { s.each_char.with_index.map { |c,i| [c.downcase,c.upcase].rotate(i[0])}.transpose.map(&:join)}

method.call 'dev'
=> ["dEv", "DeV"]

method.call 'method'
=> ["mEtHoD", "MeThOd"]

method.call 'hello'
=> ["hElLo", "HeLlO"]
Collapse
 
cipharius profile image
Valts Liepiņš

Solution in Haskell using folding:

import Data.Char (toUpper)

capitalize :: String -> [String]
capitalize str = folder skipCase <$> [("",0),("",1)] <*> pure str
  where
    folder fn init = fst . foldr fn init
    skipCase :: Char -> (String, Int) -> (String, Int)
    skipCase c (cs, i) | i `mod` 2 == 1 = ((toUpper c):cs, i+1)
                       | otherwise      = (c:cs, i+1)

The skipCase folding function takes care of upcasing every 2. letter. The folder is a makes it easier to map the function over both capitalization variations, which then can be applied to the input string.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.