DEV Community

Daily Challenge #39 - Virus

dev.to staff on August 12, 2019

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' ...
Collapse
 
alvaromontoro profile image
Alvaro Montoro • Edited

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 !.

Collapse
 
anwar_nairi profile image
Anwar • Edited

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.

Collapse
 
jmplourde profile image
Jean-Michel Plourde • Edited

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)
Collapse
 
hectorpascual profile image
Héctor Pascual

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

Collapse
 
jmplourde profile image
Jean-Michel Plourde

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.)

Collapse
 
ynndvn profile image
La blatte • Edited

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."
Collapse
 
alvaromontoro profile image
Alvaro Montoro

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

Collapse
 
mangelsnc profile image
Miguel Ángel Sánchez Chordi

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

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

Collapse
 
hanachin profile image
Seiei Miyagi

ruby <3

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

After a day, I feel def cure is better,

Collapse
 
tanguyandreani profile image
Tanguy Andreani

Ohh with all the new syntax from 2.7 ;))

Collapse
 
hanachin profile image
Seiei Miyagi

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

Collapse
 
kvharish profile image
K.V.Harish

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.

Collapse
 
matrossuch profile image
Mat-R-Such

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
Collapse
 
itsdarrylnorris profile image
Darryl Norris

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.

Collapse
 
hectorpascual profile image
Héctor Pascual

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())
Collapse
 
jmplourde profile image
Jean-Michel Plourde

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

Collapse
 
hectorpascual profile image
Héctor Pascual

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 :)

Thread Thread
 
jmplourde profile image
Jean-Michel Plourde

Your solution is very good btw. Good job

Collapse
 
jay profile image
Jay

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(" ")
}