loading...

Daily Challenge #39 - Virus

thepracticaldev profile image dev.to staff ・1 min read

You've just finished writing the last chapter for your novel when a virus suddenly infects your document. It has swapped the 'i's and 'e's in 'ei' words and capitalized random letters. In today's challenge, you will write a function which will:

a) remove the spelling errors in 'ei' words. (Example of 'ei' words: their, caffeine, deceive, weight)

b) only capitalise the first letter of each sentence. Make sure the rest of the sentence is in lower case.

Example: He haD iEght ShOTs of CAffIEne. => He had eight shots of caffeine.

Good luck and Happy Coding~!


This challenge comes from kkavita92 on CodeWars. 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!

Posted on by:

thepracticaldev profile

dev.to staff

@thepracticaldev

The hardworking team behind dev.to ❤️

Discussion

pic
Editor guide
 

JavaScript

const normalize = string => string.toLowerCase()
                                  .replace(/ie/g, "ei")
                                  .split('. ')
                                  .map(val => val[0].toUpperCase() + val.substring(1))
                                  .join('. ');

But this solution has the same problem that La battle mentions in another comment: if a word contains a valid "ie" string, it will be transformed into "ei" incorrectly. I was testing the sentence He haD iEght ShOTs of CAffIEne. thEn hE dIeD and the last "dIeD" was being transformed into "deid". One option could be extending the function to check a dictionary or make a call to an API to verify the word is valid, but that could be a pain too.

Another possible extension would be to split not only by ., but also by other sentence delimiters such as ? or !.

 

Also, if your sentence contains nouns such as He haD iEght ShOTs of CAffIEne in Paris. thEn hE dIeD, you will loose the upper P of Paris.

 

Python

edit: I changed my code to only consider periods at the end of a word so words like nice.gif wouldn't be considered as the end of a sentence.

def antivirus(text):
    str_arr = text.lower().replace('ie', 'ei').split(" ")
    first = True
    for i, s in enumerate(str_arr):
        if first:
            str_arr[i] = s.capitalize()
        first = True if s[-1:] == '.' else False
    return " ".join(str_arr)
 

Nice, that way (checking words containing dots) you can check if it is needed to capitalize more than once in the same line, clever!!

 

I edited my answer so my code would not consider periods in the middle of a word to be the end of a sentence (ie: This file is named nice.gif and it is weird.)

 

Well, this solution will work in every case but won't be able to handle the 21775 "ie" words:

antidote=(s)=>s.split`. `.map(b=>{b=b.replace(/ie/gi,'ei');return b[0].toUpperCase()+b.slice(1).toLowerCase()}).join`. `
antidote("He haD iEght ShOTs of CAffIEne. aFter thaT HE WenT tO SleeP.")
// "He had eight shots of caffeine. After that he went to sleep."
 

I was doing something like this. Then I deid testing.

 

There's a known set of rules to avoid handle all the "ie" words:

en.wikipedia.org/wiki/I_before_E_e...

 

ruby <3

def antivirus(s)
  s |> downcase |> gsub 'ie', 'ei' |> split ?. |> map { @1 |> sub(/\w/) { @1.upcase } } |> join ?.
end
 

After a day, I feel def cure is better,

 

Ohh with all the new syntax from 2.7 ;))

 

Yes! I love to try new syntax😆 So I use 2.7 in #challenge to promote the goodness of ruby 2.7✨

 

My solution in js

const cleanVirus = (sentence) => sentence.charAt(0).toUpperCase() + sentence.toLowerCase()
                                         .replace(/ie/g, 'ei')
                                         .replace(/[.+]\s\w/g, (str) => `. ${str[str.length -1].toUpperCase()}`)
                                         .slice(1);

As others mentioned this solution will change all the proper words with ie to ei and changes the first character of a noun to lowercase.

 

Python

def proofread(string):
    if string.rstrip()[:-1].count('.') == 0:    return string.lower().replace('ie','ei').capitalize()
    string= '. '.join([i.lower().replace('ie', 'ei').lstrip().capitalize() for i in string.split('.')])
    if string[-1] == ' ':   return string[:-1]
    else:   return string
 

PHP 💻

<?php

/**
 * Antivirus
 * @param  string $string
 * @return string
 */
function antivirus(string $string): string
{
  return implode(".", array_map(function($sentence) {
    $sentence = str_split($sentence);
    foreach ($sentence as $key => $value) {
      if ($key === 0 && $value === ' ') continue;
      else $sentence[$key] = strtoupper($value); break;
    }
    return implode("",$sentence);
  }, explode(".", str_replace('ie', 'ei', strtolower($string)))));
}


echo antivirus('He haD iEght ShOTs of CAffIEne. aFter thaT HE WenT tO SleeP.');
// Output: He had eight shots of caffeine. After that he went to sleep.

 

Python :

import re

def fix_virus(document):
    doc = document.lower().capitalize()
    return re.sub(r'ie','ei',doc)

Python one-liner :

fix_virus = lambda doc : re.sub(r'ie','ei',doc.lower().capitalize())
 

If it's a document, it will contains multiple sentences and capitalize is only uppercasing the first letter of a string

 

Ok then split document by lines and call the function :

document_splitted = document.split('\n')
for line in document_splitted:
    fix_virus(line)
    ....

Or capitalize each line of the document after lowering :)

Your solution is very good btw. Good job

 

Rust Solution: Playground

fn solver(sentance: &str) -> String {
    sentance
        .to_ascii_lowercase()
        .replace("ie", "ei")
        .split_whitespace()
        .enumerate()
        .map(|(i, word)| {
            if i == 0 {
                let mut ch = word.chars();
                match ch.next() {
                    None => String::new(),
                    Some(c) => c.to_uppercase().chain(ch).collect(),
                }
            } else {
                word.to_string()
            }
        })
        .collect::<Vec<String>>()
        .join(" ")
}