DEV Community

Discussion on: Daily Coding Puzzles - Nov 11th - Nov 16th

Collapse
 
aspittel profile image
Ali Spittel

Wednesday - Format words into a sentence (6 KYU)

Complete the method so that it formats the words into a single comma separated value. The last word should be separated by the word 'and' instead of a comma.

codewars.com/kata/format-words-int...

Collapse
 
skyller360 profile image
Anthony Tomson

My Js solution:

function formatWords(words) {
  if (!words || words.length < 1) return '';

  words = words.filter(val => !!val);
  const length = words.length;

  if (!length) return '';


  return words.reduce((acc, cumul, index) => {
    return index + 1 === length ?
      `${acc} and ${cumul}` :
      `${acc}, ${cumul}`
  });
}
Collapse
 
ben profile image
Ben Halpern • Edited

Ruby

def format_words(words)
  words.reject(&:blank?).join(", ").reverse.sub(',', 'dna ').reverse
end
Collapse
 
kungtotte profile image
Thomas Landin • Edited

My Nim solution :)

Nim supports specifying ranges both in absolute terms and in relative terms. ^2 would be the second to last position of a range, etc :) As you can see at the end of the procedure you can also supply just one end of the range and Nim will infer the other end, so filtered[^1] would be just the final element of the sequence.

import sequtils # for filter

proc format_words(words: seq[string]): string =
  result = ""
  if words.len > 0:
    var filtered = filter(words, proc(w: string): bool = w.len > 0)
    for word in filtered[0..^2]:
      result.add(word & ", ")
    return result[0..^3] & (" and " & filtered[^1])

echo format_words(@["ninja","samurai","ronin","leonardo","michelangelo","donatello","raphael"])
echo format_words(@["ninja","samurai","ronin"])
echo format_words(@["ninja","", "ronin"])
echo format_words(@[])
Collapse
 
jay profile image
Jay

Rust Solution:

fn format_words(words: &[&str]) -> String {
    let words: Vec<&str> = words
        .into_iter()
        .filter(|&w| !w.is_empty())
        .map(|&x| x)    // deref &&str -> &str
        .collect();
      words
        .iter()
        .enumerate()
        .fold(String::new(), |mut sent, (i, w)| {
            if i == 0 {
                sent += w
            } else if i == words.len() - 1 {
                sent += &format!(" and {}", w);
            } else {
                sent += &format!(", {}", w);
            }
            sent
        })
}
Collapse
 
aspittel profile image
Ali Spittel
def format_words(words):
    sentence = ''
    if words:
        words = [word for word in words if word]
        for index, word in enumerate(words):
            if index == 0:
                sentence += word
            elif index == len(words) - 1:
                sentence += " and " + word
            else:
                sentence += ", " + word
    return sentence
Collapse
 
arnemahl profile image
Arne Mæhlum

This is a fun way of doing it, though it might be a bit confusing at first glance 😂

const format_words = words =>
  words
    .filter(Boolean)
    .join(', ')
    .split('').reverse().join('')
    .replace(' ,', ' dna ')
    .split('').reverse().join('')
Collapse
 
gypsydave5 profile image
David Wickes • Edited

Common Lisp

Inhumane format version:

(defun format-words (words)
  (format nil "~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~}" words))

appropriated from Practical Common Lisp


More humane version (kinda like a string builder but using a stream):

(defun format-words (words)
  (with-output-to-string (s)
    (format s "~{~a~^, ~}" (butlast words))
    (unless (= 1 (length words))
      (format s " and "))
    (format s "~a" (car (last words)))))
Collapse
 
clandau profile image
Courtney • Edited
function formatWords(words) {
    if(!words) return '';
    words = words.filter((word) => word.length);
    let returnString = '';
    for(let i=0; i<words.length; i++) {
        if(i === words.length - 1 && i > 0) {
        returnString += ` and `;
        }
        else if (i > 0){
            returnString += `, `;
        }
        returnString += words[i];
    }
    return returnString;
}
Collapse
 
choroba profile image
E. Choroba

Perl solution, tests included:

#! /usr/bin/perl
use warnings;
use strict;

sub format_words {
    my @words = grep length, @_;
    my $last = pop @words;
    return join(', ', @words) . (@words ? " and $last" : "")
}

use Test::More tests => 3;
is format_words('ninja', 'samurai', 'ronin'), 'ninja, samurai and ronin';
is format_words('ninja', '', 'ronin'), 'ninja and ronin';
is format_words(), "";