DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #66- Friend List

John has invited some friends. His list is:

s = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";

Could you make a program that:
-makes this string uppercase
-gives it sorted in alphabetical order by last name

When the last names are the same, sort them by first name. Last name and first name of a guest come in the result between parentheses separated by a comma.

So the result of function meeting(s) will be:

"(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)"

It can happen that in two distinct families with the same family name two people have the same first name too.


Today's challenge comes from g964 on 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 (14)

Collapse
 
ynndvn profile image
La blatte

Lets do it:

s
.split(';')
.map(n=>n.split(':').reverse().join(':'))
.sort()
.map(n=>`(${n.split(':')[0]}, ${n.split(':')[1]})`.toUpperCase())
.join``

It's pretty straightforward:

  • split(';') gets us all Name:Surname
  • .map(n=>n.split(':').reverse().join(':')) reverses them to be Surname:Name
  • .sort() sorts them alphabetically
  • .map(n=>(${n.split(':')[0]}, ${n.split(':')[1]}).toUpperCase()) reformats every name (uppercase it, place parentheses and commas)
  • The last step is equivalent to .join(''), which transforms the name array to an output string

Here is the output:

"Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill"
.split(';')
.map(n=>n.split(':').reverse().join(':'))
.sort()
.map(n=>`(${n.split(':')[0]}, ${n.split(':')[1]})`.toUpperCase())
.join``;


// "(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)"
Collapse
 
blindfish3 profile image
Ben Calder • Edited

Same but different:

  const s = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
  return s.toUpperCase().split(';')
          .map(name => name.split(':').reverse())
          .sort()
          .reduce((accumulator, name) => ( accumulator += `(${name[0]}, ${name[1]})`), "");

You don't need the arbitrary join(':') after reverse() since sort() coerces the nested arrays to strings for you. That means you can avoid having to split again later.

But Amin is right:

  const s = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
  return s.toUpperCase().split(';')
             .map(name=> `(${name.split(':')[1]}, ${name.split(':')[0]}`)
             .sort()
             .join('');
Collapse
 
ynndvn profile image
La blatte

That's way shorter! Thanks a lot for the input

Collapse
 
aminnairi profile image
Amin

I see we got a similar solution you and I!

I think you can even shorten (if I'm not mistaken) your solution by reducing one .map down and doing like me the surrounding in your first call to the .map method!

Should such a .surround method exist in String.prototype? I have came accross several cases where I would need it like in a WYSIWYG editor. But I don't want to risk proposing such a method to the community haha!

Good take btw!

Collapse
 
idanarye profile image
Idan Arye
s="Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill"

echo $s \
    | tr ';' '\n' \
    | awk -F: '{print toupper("("$2":"$1")")}' \
    | sort \
    | paste -sd '' -
Collapse
 
peledzohar profile image
Zohar Peled

Not much of a challenge, I'm afraid. Pretty straight forward split, split, join, sort and join again. A one liner in most modern languages, I suspect.
In c# it would look like this:

string meeting(string s)
{
    return "(" + string.Join(")(", 
        s.
        ToUpper().
        Split(';').
        Select(n => n.Split(':')).
        Select(n => string.Join(":", n.Reverse())).
        OrderBy(n => n)
    ) + ")"; 
}
Collapse
 
brightone profile image
Oleksii Filonenko

Rust:

fn meeting(list: &str) -> String {
    let list = list.to_uppercase();
    let list: Vec<_> = list.split(|c| [';', ':'].contains(&c)).collect();
    let mut list: Vec<_> = list
        .chunks_exact(2)
        .map(|chunk| format!("({}, {})", chunk[1], chunk[0]))
        .collect();
    list.sort();
    list.join("")
}
Collapse
 
aminnairi profile image
Amin • Edited

My take at the challenge written in Elm

Source-Code

$ touch src/FriendList.elm
module FriendList exposing (friendList)


surround : String -> String -> String -> String
surround left right string =
    left ++ string ++ right


toUpperTuples : String -> String
toUpperTuples =
    String.split ":"
        >> List.reverse
        >> String.join ", "
        >> surround "(" ")"
        >> String.toUpper


friendList : String -> String
friendList =
    String.split ";"
        >> List.map toUpperTuples
        >> List.sort
        >> String.join ""

Unit test source-code

$ touch tests/FriendListTest.elm
module FriendListTest exposing (suite)

import Expect
import FriendList exposing (friendList)
import Test exposing (Test)


suite : Test
suite =
    Test.describe "Friend list"
        [ Test.test "It should return the correct friend list" <|
            \_ ->
                let
                    expectations =
                        "(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)"

                    friends =
                        "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill"

                    result =
                        friendList friends
                in
                Expect.equal expectations result
        ]
Collapse
 
choroba profile image
E. Choroba

Perl solution:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my $in = 'Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill';

say join "",
    map "($_->[1], $_->[0])",
    sort { $a->[1] cmp $b->[1] || $a->[0] cmp $b->[0] }
    map [split /:/],
    split /;/,
    uc $in;
 
therealkevinard profile image
Kevin Ard • Edited

Anyone who says rex is too clever clearly hasn't bumped into bit-shifting code-golf lol

Rex is a very appropriate amount of cleverness 😉

Collapse
 
aminnairi profile image
Amin

Clever use of the regex split. I like it!