Comma quibbling is a task originally set by Eric Lippert in his blog.



Task

Write a function to generate a string output which is the concatenation of input words from a list/sequence where:

 An input of no words produces the output string of just the two brace characters "{}".
 An input of just one word, e.g. ["ABC"], produces the output string of the word inside the two braces, e.g. "{ABC}".
 An input of two words, e.g. ["ABC", "DEF"], produces the output string of the two words inside the two braces with the words separated by the string " and ", e.g. "{ABC and DEF}".
 An input of three or more words, e.g. ["ABC", "DEF", "G", "H"], produces the output string of all but the last word separated by ", " with the last word separated by " and " and all within braces; e.g. "{ABC, DEF, G and H}".


Test your function with the following series of inputs showing your output here on this page:

 [] # (No input words).
 ["ABC"]
 ["ABC", "DEF"]
 ["ABC", "DEF", "G", "H"]


Note: Assume words are non-empty strings of uppercase characters for this task.




Option Explicit On
Option Infer On
Option Strict On
 
Module Program
    Function FormatEnumerable(source As IEnumerable(Of String)) As String
        Dim res As New Text.StringBuilder("{")
 
        Using en = source.GetEnumerator()
            Dim moreThanOne As Boolean = False
            Dim nxt = If(en.MoveNext(), en.Current, String.Empty)
 
            Do While en.MoveNext()
                If moreThanOne Then res.Append(", ")
                moreThanOne = True
 
                res.Append(nxt)
                nxt = en.Current
            Loop
 
            Dim lastItem = If(moreThanOne, " and ", "") & nxt
            Return res.ToString() & lastItem & "}"
        End Using
    End Function
 
    Function FormatArray(source As String()) As String
        Select Case source.Length
            Case 0 : Return "{}"
            Case 1 : Return "{" & source(0) & "}"
            Case Else : Return "{" & String.Join(", ", source.Take(source.Length - 1)) & " and " & source(source.Length - 1) & "}"
        End Select
    End Function
 
    Sub Main()
        Dim cases As String()() = {Array.Empty(Of String), New String() {"ABC"}, New String() {"ABC", "DEF"}, New String() {"ABC", "DEF", "G", "H"}}
        For Each c In cases
            Console.WriteLine(FormatArray(c))
            Console.WriteLine(FormatEnumerable(c))
        Next
    End Sub
End Module
 