DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #15 - Stop gninnipS My sdroW!

Good morning, everyone.
Let's warm up for the start of the week by playing with strings.

s'yadoT egnellahc semoc from user xDranik on sraWedoC!

Write a function that takes in a string of one or more words and returns the same string, but with all words with five letters or more reversed. Strings passed in will consist of only letters and spaces.

Be sure to keep the order of the words the same and only reverse the letters.

Good luck, yppaH gniedoc!


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 (23)

Collapse
 
willsmart profile image
willsmart • Edited

JS quickie

theString => theString.split(' ').map(
  word => word.length >= 5 ?
    [...word].reverse().join('')
    : word
).join(' ')
Collapse
 
willsmart profile image
willsmart • Edited

And one that modifies a string inplace using C

#include <stdio.h>
#include <string.h>

char *unspin(char *input) {
    for (
        char *eoinput = input + strlen(input),
             *nextSpace=input,
             *nextWord=input ;

        nextSpace < eoinput ;

        nextWord = nextSpace + 1 ,
        nextSpace = memchr(nextWord,' ',eoinput-nextWord),
        nextSpace = nextSpace ? nextSpace : eoinput
      ) {
        if (nextSpace >= nextWord + 5) for (
            char *wordStart = nextWord, 
            *wordEnd = nextSpace-1 ;

            wordStart < wordEnd ;

            ++wordStart,
            --wordEnd
        ) {
            *wordStart += *wordEnd;
            *wordEnd = *wordStart - *wordEnd;
            *wordStart -= *wordEnd;
        }
      }
      return input;
}

int main()
{
    char s[] = "Stop gninnipS My sdroW";
    printf("%s", unspin(s));

    return 0;
}
Collapse
 
yzhernand profile image
Yozen Hernandez

Perl one-liner:

my $string = "Good luck, Happy coding!"; my $res = join " ", map { (length($_) >= 5) ? scalar reverse($_) : $_ } split / /, $string; say $res;

A bit more cleaned up, taking user input:

#!/usr/bin/perl

use v5.24;
use strict;
use warnings;
use Carp;

# Challenge says only letters and spaces, but this won't be picky
sub reverse_over_4 {
    my $string = shift or croak "Error: missing argument to function.";
    my $res    = join " ",
        map { ( length($_) > 4 ) ? scalar reverse($_) : $_ } split / /,
        $string;
    return $res;
}

print "Enter string: ";
my $input = <STDIN>;
chomp $input;
say reverse_over_4($input);

See runnable demo on PerlBanjo

Collapse
 
choroba profile image
E. Choroba

Note that ($_) is not needed for length and reverse.

Collapse
 
yzhernand profile image
Yozen Hernandez

Yeah, true, that's just my personal preference 🙂

Collapse
 
alvaromontoro profile image
Alvaro Montoro

JavaScript

const spinner = sentence => sentence.split(' ')
                                    .reduce((acc, val) => `${acc} ${val.length > 4 ? val.split('').reverse().join('') : val}`, '')
                                    .trim();

Using reduce to generate a string from the array, but then I have to use trim as I end up with a space at either end :-/

Live demo on CodePen.

Collapse
 
willsmart profile image
willsmart

Nice one!
If you replace the trim() with a substring(1) then it'll work with strings that have spaces in front and behind since you're reliably adding a single space to the front, none to the back.

See the warning here re thesplit('') call. Seems the recommended way now is [...string].

Collapse
 
kerrishotts profile image
Kerri Shotts

This one was fun! I decided to approach it from a slightly different angle by building a general-purpose when function that could be used to decide when to map to a value (vs return the original value) based on a condition... just for kicks :-)

Here's my go:

const when = (when = () => false, fn = i => i) => 
    (v, idx, arr) => when(v, idx, arr) 
        ? (typeof fn === "function" ? fn(v, idx, arr) : fn)
        : v;

const reverseString = str => Array.from(str).reverse().join("");

const reverseWords = ({inString = "", ofLength = 0} = {}) => 
    inString.split(" ")
        .map(when(w => w.length >= ofLength, reverseString))
        .join(" ");

const gnirtS = reverseWords({inString: "one two three four", ofLength: 5});

Gist (w/ some tests): gist.github.com/kerrishotts/ac0f30...

Collapse
 
tarptaeya profile image
Anmol Gautam • Edited

Haskell, with user input

condRev :: [Char] -> [Char]
condRev s = if length s >= 5 then reverse s else s

toString :: [[Char]] -> [Char]
toString [] = []
toString (x:[]) = x
toString (x:xs) = x ++ " " ++ toString xs

solve :: [Char] -> IO ()
solve s = putStrLn $ toString $ map condRev $ words s

main :: IO ()
main = do
    line <- getLine
    solve line

Collapse
 
aadibajpai profile image
Aadi Bajpai • Edited

Python one-liner:
for x in input().split(): print(x[::1]*(len(x)<5) or x[::-1], end=' ')

65 chars at most :)

Or,
print(*map(lambda x: x[::1]*(len(x)<5)or x[::-1], input().split()))

Also 65 at most :)

Collapse
 
coreyja profile image
Corey Alexander

Here is my Rust solution and test cases!

The Rust std lib made this one pretty simple!

pub fn spin_words(input: &str) -> String {
    input
        .split(" ")
        .map(|word| {
            if word.len() >= 5 {
                word.chars().rev().collect()
            } else {
                word.to_string()
            }
        })
        .collect::<Vec<String>>()
        .join(" ")
}

#[cfg(test)]
mod tests {
    use crate::*;

    #[test]
    fn it_works_for_words_shorter_than_4_chars() {
        assert_eq!(spin_words("Test"), "Test".to_string());
        assert_eq!(spin_words("Te"), "Te".to_string());
        assert_eq!(spin_words("ant"), "ant".to_string());
        assert_eq!(
            spin_words("lots of tiny word"),
            "lots of tiny word".to_string()
        );
    }

    #[test]
    fn it_words_for_the_example() {
        assert_eq!(
            spin_words("Stop gninnipS My sdroW"),
            "Stop Spinning My Words".to_string()
        );
    }

    #[test]
    fn it_words_with_space_padded_strings() {
        assert_eq!(
            spin_words(" Stop gninnipS My sdroW "),
            " Stop Spinning My Words ".to_string()
        );
    }
}
Collapse
 
brightone profile image
Oleksii Filonenko • Edited

Elixir:

defmodule Spinner do
  @spec spin(String.t()) :: String.t()
  def spin(sentence) do
    String.replace(sentence, ~r/\w+/, fn word ->
      if String.length(word) > 4 do
        String.reverse(word)
      else
        word
      end
    end)
  end
end

"Please spin me around!"
|> Spinner.spin()
|> IO.puts()

# => "esaelP spin me dnuora!"
Collapse
 
praneetnadkar profile image
Praneet Nadkar

A quick one in C#

 var input = Console.ReadLine().Split(' ');
 var output = new List<string>();
 foreach (var word in input)
 {
    if (word.Length <= 4)
    {
      output.Add(word);
      continue;
    }

    // word reversal. This can be done using inbuilt functions as well
    var wordArray = word.ToCharArray();
    var current = string.Empty;
    for (int i = word.Length - 1; i >= 0 ; i--)
    {
       current += wordArray[i];
    }

    output.Add(current);
 }

 Console.WriteLine(string.Join(" ", output));
 Console.ReadKey();
Collapse
 
qm3ster profile image
Mihail Malo • Edited

Rust, sort of in place

fn reverse_in_place(input: &mut [u8]) {
    input
        .split_mut(|&byte| byte == b' ')
        .filter(|word| word.len() >= 5)
        .for_each(<[_]>::reverse);
}

The rest of the story below the fold:

fn reverse(input: &str) -> String {
    let mut output = input.as_bytes().to_vec();
    reverse_in_place(&mut output);
    String::from_utf8(output).unwrap()
}

fn main() {
    let test = "Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!";
    println!("{}", reverse(test));
    println!("{}", reverse(&reverse(test)));
}

Collapse
 
p810 profile image
Payton Bice • Edited

PHP 5.3.0 to 7.3.x:

preg_replace_callback('/(\b\w{5,}\b)+/i', function ($match) {
    return strrev($match[0]);
}, 'Hello world, this is a test string.');

PHP >= 7.4:

preg_replace_callback('/(\b\w{5,}\b)+/i', fn($match) => strrev($match[0]), 'Hello world, this is a test string.');
Collapse
 
scrabill profile image
Shannon Crabill

Ruby

def wordSpinner(string)
  string.split(" ").map do |word|
    if word.length >= 5
      word.reverse
    else
      word
    end
  end.join(" ")
end

Tests

wordSpinner("Everything small is just a smaller version of something big")
wordSpinner("Bad biscuits make the baker broke bro")
wordSpinner("Sometimes life is scary and dark")

Results

"gnihtyrevE llams is just a rellams noisrev of gnihtemos big"
"Bad stiucsib make the rekab ekorb bro" 
"semitemoS life is yracs and dark" 
Collapse
 
mkrl profile image
Mikhail Korolev • Edited

Ruby

string.split.map{ |s| s.length >= 5 ? s.reverse! : s } * " "
Collapse
 
kvharish profile image
K.V.Harish

My solution in js

const reverseWords = sentence => sentence.split(' ')
                                         .map(word => word.length > 4 ? word.split('').reverse().join('') : word)
                                         .join(' ');