DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #179 - Hide Phone Numbers

Setup

Implement a function that will hide the last six digits of each phone number. Your function should be able to understand the separators for US numbers. Phone numbers can be separated by spaces, periods, or hyphens.

Examples

Original: 201-680-0202
Encrypted: `201-6XX-XXXX

Tests

encryptNum("328 6587120")
encryptNum("212-420-0202")
encryptNum("211-458-7851")


This challenge comes from otrebor6 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 (19)

Collapse
 
avaq profile image
Aldwin Vlasblom • Edited

JavaScript:

const encryptNum = num => num.replace(/(\d[ .-]?){6}$/, x => x.replace(/\d/g, 'X'))

The first replace finds the last 6 digits, with or without trailing separators.
The resulting match undergoes another replace call to substitute any digits for X's.

The first expression can also be relaxed to allow any separators: /(\d[^\d]?){6}$/, or even any number of separators: /(\d[^\d]*){6}$/.

Collapse
 
alvaromontoro profile image
Alvaro Montoro

This is neat

Collapse
 
cirlorm_io profile image
C I R L O R M ⚡

Winner

Collapse
 
alvaromontoro profile image
Alvaro Montoro

JavaScript

If we want all the phone numbers to have the same format, we could use a regular expression to detect all the digits (assuming that the phone number is correct) and format it accordingly:

const encryptNum = (num) => {
  const nums = num.match(/\d/gi).join("");
  return `${nums.substring(0,3)}-${nums.substring(3,6)}-${nums.substring(6)}`;
}

If we want to keep the original format (and again, assuming the phone number is correct), another solution would be transforming the string into an array (strings are immutable, an array would be easier to operate), parse the last 6 digits and return its concatenation:

const encryptNum = (num) => {
  let numbers = 0;
  let position = num.length - 1;
  let formattedNum = num.split("");

  while (numbers < 6 && position > 0) {
    if (num[position] >= "0" && num[position] <= "9") { 
      formattedNum[position] = "x";
      numbers++;
    }
    position--;
  }

  return formattedNum.join("");
}
Collapse
 
epranka profile image
Edvinas Pranka

Javascript

function encryptNum(num){
  return num.substr(0, 5) + 'XX-XXXX'
}
Collapse
 
exts profile image
Lamonte

This only works if you're expecting a certain value. Output would be weird otherwise.

Collapse
 
epranka profile image
Edvinas Pranka

Yeah, but the data validation is not required in this challange.

Thread Thread
 
georgewl profile image
George WL • Edited

True, but it does expect the tests to all pass still, which they won't with that solution

Collapse
 
aminnairi profile image
Amin

Nice short solution!

If I'm being correct, for the string "328 6587120", the expected output should be "328 6XXXXXX".

But in your case, the output would be "328 6XX-XXXX".

Collapse
 
idanarye profile image
Idan Arye

Rust:

fn encrypt_num(phone_number: String) -> String {
    let mut bytes = phone_number.into_bytes();
    for ch in bytes.iter_mut().rev().filter(|b| {
        let c = **b as char;
        '0' <= c && c <= '9'
    }).take(6) {
        *ch = 'X' as u8;
    }
    String::from_utf8(bytes).unwrap()
}

fn main() {
    assert_eq!(encrypt_num("328 6587120".to_owned()), "328 6XXXXXX");
    assert_eq!(encrypt_num("212-420-0202".to_owned()), "212-4XX-XXXX");
    assert_eq!(encrypt_num("211-458-7851".to_owned()), "211-4XX-XXXX");
}
Collapse
 
cipharius profile image
Valts Liepiņš

Haskell, similar idea to my solution in Ruby

import Data.Char (isDigit)

encryptNum :: String -> String
encryptNum = reverse . encryptDigit 0 . reverse
    where
        encryptDigit 6 xs     = xs
        encryptDigit i (x:xs) | isDigit x = 'X' : encryptDigit (i+1) xs
                              | otherwise =  x  : encryptDigit i xs
Collapse
 
aminnairi profile image
Amin

Elm

encryptDigit : Char -> Char
encryptDigit character =
    if Char.isDigit character then
        'X'

    else
        character


encryptNum : String -> String
encryptNum string =
    String.map encryptDigit ( String.dropLeft 5 string )
        |> String.append ( String.left 5 string )
Collapse
 
zoejm profile image
zoe-j-m

Scala,

def encryptNum(input : String) = {
  def encryptInner(remain : Int, toGo : List[Char]) : List[Char] = {
    toGo match {
      case Nil => Nil
      case _ if remain == 0 => toGo
      case x::xs if x.isDigit => 'X' :: encryptInner(remain - 1, xs)
      case x::xs => x :: encryptInner(remain, xs)
    }
  }

  encryptInner(6, input.reverse.toList).reverse.mkString
}
Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli • Edited

ONE REGEX TO RULE THEM

Put your separators where you want! I'll find them all.

const encryptNum = num => num.replace(/((\d[-\s.]?){4})(\d)([\s.-]?)(\d)([\s.-]?)(\d)([\s.-]?)(\d)([\s.-]?)(\d)([\s.-]?)(\d)/, '$1X$4X$6X$8X$10X$12X');
Collapse
 
exts profile image
Lamonte • Edited

Dart - not a fan of being creative.

String encryptNum(String phoneNum) {
  var regexp = RegExp(r"([0-9- .]+)");
  var result = regexp?.firstMatch(phoneNum)?.group(0);
  result = result?.replaceAll(new RegExp(r"(\.|-|\s)"), "");
  if(result.length == 10) {
    var val = StringBuffer();
    for(var idx = 0; idx < result.length; idx++) {
      if(idx < 4) {
        val.write(result[idx]);
      } else {
        val.write("X");
      }
      switch(idx) {
        case 2:
        case 5:
          val.write("-");
        break;
      }
    }
    return val.toString();
  }
  return null;
}
print(encryptNum("142 424 2142"));
print(encryptNum("142 424-2142"));
print(encryptNum("142 424.2142"));
print(encryptNum("142 4242142"));
print(encryptNum("142-424-2142"));
print(encryptNum("142-424 2142"));
print(encryptNum("142-424.2142"));
print(encryptNum("142-4242142"));
print(encryptNum("142.424 2142"));
print(encryptNum("142.424-2142"));
print(encryptNum("142.424.2142"));
print(encryptNum("142.4242142"));
print(encryptNum("142424-2142"));
print(encryptNum("142424.2142"));
print(encryptNum("142424 2142"));
print(encryptNum("1424242142"));
Collapse
 
viktordimitrievski profile image
Viktor

JavaScript solution:

const encryptNum = num => {
    num = num.replace(/[-,\s]/g,"");
    return `${num.substring(0,3)}-${num.substring(3,4)}XX-XXXX`
}