DEV Community

dev.to staff
dev.to staff

Posted on

5

Daily Challenge #167 - Return String As Sorted Blocks

Task

You will receive a string consisting of lowercase letters, uppercase letters, and digits as input. Your task is to return this string as blocks separated by dashes ("-"). The elements of a block should be sorted with respect to the hierarchy listed below, and each block cannot contain multiple instances of the same character.

The hierarchy is:

  • lowercase letters (a - z), in alphabetic order
  • uppercase letters (A - Z), in alphabetic order
  • digits (0 - 9), in ascending order

Examples

  • "21AxBz" -> "xzAB12" - since input does not contain repeating characters, you only need 1 block

  • "abacad" -> "abcd-a-a" - character "a" repeats 3 times, thus 3 blocks are needed

  • "" -> "" - an empty input should result in an empty output


This challenge comes from airatmulk 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!

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

While many AI coding tools operate as simple command-response systems, Qodo Gen 1.0 represents the next generation: autonomous, multi-step problem-solving agents that work alongside you.

Read full post →

Top comments (4)

Collapse
 
craigmc08 profile image
Craig McIlwrath

Solution in Haskell.

import Data.List (group, sortBy, intercalate)

between :: (Ord a) => a -> a -> a -> Bool
between lo hi v = v >= lo && v <= hi

compareLetters :: Char -> Char -> Ordering
compareLetters a b
  | setA < setB = LT
  | setA > setB = GT
  | otherwise   = compare a b
  where setOf c = if between 'a' 'z' c then 0
                  else if between 'A' 'Z' c then 1
                  else 2
        setA    = setOf a
        setB    = setOf b

blocks :: [[a]] -> [[a]]
blocks [] = []
blocks xss = let ys  = map head xss
                 yss = filter (not . null) $ map tail xss
             in  ys : blocks yss

blockify :: (Eq a) => ([a] -> [a]) -> [a] -> [[a]]
blockify sort = blocks . group . sort

blockifyString :: String -> String
blockifyString = intercalate "-" . blockify (sortBy compareLetters)

It sorts the input string, then groups it into arrays of each piece (e.g. "abbcddde" -> ["a", "bb", "c", "ddd", "e"]. The blocks method combines corresponding elements of the sub-arrays after grouping (continuing the example -> ["abcde", "bd", "d"]). Then the strings are joined by a hyphen. My least favorite part of my solution is the compareLetters function which determines the order of 2 letters for letters. I couldn't come up with a better way to do this.

Collapse
 
amcmillan01 profile image
Andrei McMillan

python

import re

def sorted_blocks(input_str):
    str_usage = {}
    arr_list = {}

    upper_case = re.findall('[A-Z]', input_str)
    lower_case = re.findall('[a-z]', input_str)
    numbers = re.findall('[0-9]', input_str)

    upper_case.sort()
    lower_case.sort()
    numbers.sort()

    for dataset in [lower_case, upper_case, numbers]:

        for item in dataset:
            if str_usage.get(item) is not None:
                str_usage[item] += 1
            else:
                str_usage[item] = 1

            index = str_usage[item]

            arr_list.setdefault(index, '')
            arr_list[index] += item

    print 'input    : "' + input_str + '"'
    print 'block(s) : "' + '-'.join(arr_list.values()) + '"'
    print ' '

# tests
sorted_blocks('21AxBz')
sorted_blocks('21BxAzAasfdaXZas')
sorted_blocks('abacad')
sorted_blocks('')

# output

# input    : "21AxBz"
# block(s) : "xzAB12"
# 
# input    : "21BxAzAasfdaXZas"
# block(s) : "adfsxzABXZ12-asA-a"
# 
# input    : "abacad"
# block(s) : "abcd-a-a"
# 
# input    : ""
# block(s) : ""


Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli

Someone ask on SO, and I answered:

For funzies, here's how I would have approached the problem:

const isLower = new RegExp('[a-z]');
const isUpper = new RegExp('[A-Z]'); 
const isDigit = new RegExp('[0-9]');
const isDigitOrUpper = new RegExp('[0-9A-Z]');
const isDigitOrLower = new RegExp('[0-9a-z]');
const isLowerOrUpper = new RegExp('[a-zA-Z]');

function lowerUpperNumber(a, b)
{
  if(isLower.test(a) &&

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay