Comma quibbling: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎Tcl: Added implementation)
No edit summary
Line 43: Line 43:
{ A, B, C and D }
{ A, B, C and D }
{ A, B, C, D and E }</pre>
{ A, B, C, D and E }</pre>

=={{header|C++}}==
<lang cpp>#include <iostream>

template<class T>
void quibble(std::ostream& o, T i, T e) {
o << "{";
if (e != i) {
T n = i++;
const char* more = "";
while (e != i) {
o << more << *n;
more = ", ";
n = i++;
}
o << (*more?" and ":"") << *n;
}
o << "}";
}

int main(int argc, char** argv) {
char const* a[] = {"ABC","DEF","G","H"};
for (int i=0; i<5; i++) {
quibble(std::cout, a, a+i);
std::cout << std::endl;
}
return 0;
}
</lang>

{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF and G}
{ABC, DEF, G and H}
</pre>


=={{header|D}}==
=={{header|D}}==

Revision as of 18:52, 6 October 2013

Comma quibbling is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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

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

  1. An input of no words produces the output string of just the two brace characters "{}".
  2. An input of just one word, e.g. ["ABC"], produces the output string of the word inside the two braces, e.g. "{ABC}".
  3. 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}".
  4. 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.

C#

<lang csharp>

       public static string Quibble(string[] input)
       {
           var len = input.Length;
           return "{ " +
               String.Join("", input.Take(len - 2).Select(n => n + ", ")
               .Concat(input.Skip(len < 2 ? len : len - 2).Take(1).Select(n => n + " and ")))
               + (input.LastOrDefault() ?? "") + " }";
       }
       static void Main(string[] args)
       {
           Console.WriteLine(Quibble(new string[] { }));
           Console.WriteLine(Quibble(new[] { "A" }));
           Console.WriteLine(Quibble(new[] { "A", "B" }));
           Console.WriteLine(Quibble(new[] { "A", "B", "C" }));
           Console.WriteLine(Quibble(new[] { "A", "B", "C", "D" }));
           Console.WriteLine(Quibble(new[] { "A", "B", "C", "D", "E" }));
       }

</lang>

Output:
{  }
{ A }
{ A and B }
{ A, B and C }
{ A, B, C and D }
{ A, B, C, D and E }

C++

<lang cpp>#include <iostream>

template<class T> void quibble(std::ostream& o, T i, T e) {

 o << "{";
 if (e != i) {
   T n = i++;
   const char* more = "";
   while (e != i) {
     o << more << *n;
     more = ", ";
     n = i++;
   }
   o << (*more?" and ":"") << *n;
 }
 o << "}";

}

int main(int argc, char** argv) {

 char const* a[] = {"ABC","DEF","G","H"};
 for (int i=0; i<5; i++) {
   quibble(std::cout, a, a+i);
   std::cout << std::endl;
 }
 return 0;

} </lang>

Output:
{}
{ABC}
{ABC and DEF}
{ABC, DEF and G}
{ABC, DEF, G and H}

D

<lang d>import std.stdio, std.string;

string quibbler(in string[] seq) pure /*nothrow*/ {

   if (seq.length <= 1)
       return format("{%-(%s, %)}", seq);
   else
       return format("{%-(%s, %) and %s}", seq[0 .. $-1], seq[$-1]);

}

void main() {

   //foreach (immutable test; [[],
   foreach (const test; [[],
                         ["ABC"],
                         ["ABC", "DEF"],
                         ["ABC", "DEF", "G", "H"]])
       test.quibbler.writeln;

}</lang>

Output:
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}

F#

This example does not show the output mentioned in the task description on this page (or a page linked to from here). Please ensure that it meets all task requirements and remove this message.
Note that phrases in task descriptions such as "print and display" and "print and show" for example, indicate that (reasonable length) output be a part of a language's solution.


<lang fsharp>let quibble list =

   let rec inner = function
       | [] -> ""
       | [x] -> x
       | [x;y] -> sprintf "%s and %s" x y
       | h::t -> sprintf "%s, %s" h (inner t)
   sprintf "{%s}" (inner list)

// test interactively quibble [] quibble ["ABC"] quibble ["ABC"; "DEF"] quibble ["ABC"; "DEF"; "G"] quibble ["ABC"; "DEF"; "G"; "H"] </lang>

Perl 6

<lang perl6>sub comma-quibbling(@A) {

   "\{$_\}" given 
   @A < 3 ?? @A.join(' and ') !!
   @A[0..*-2].join(',') ~ ' and ' ~ @A[*-1]

}

say comma-quibbling($_) for ((), (<ABC>,), (<ABC DEF>), (<ABC DEF G H>)).tree;</lang>

Output:
{}
{ABC}
{ABC and DEF}
{ABC,DEF,G and H}

Python

<lang python>>>> def strcat(sequence): # replace(..) can only replace the first X occurrences not the last # Hence the replace is done on the reverse of the intermediate string # then reversed back. return '{%s}' % ', '.join(sequence)[::-1].replace(',', 'dna ', 1)[::-1]

>>> for seq in ([], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]): print('Input: %-24r -> Output: %r' % (seq, strcat(seq)))


Input: [] -> Output: '{}' Input: ['ABC'] -> Output: '{ABC}' Input: ['ABC', 'DEF'] -> Output: '{ABC and DEF}' Input: ['ABC', 'DEF', 'G', 'H'] -> Output: '{ABC, DEF, G and H}' >>> </lang>

PL/I

<lang pli>*process or(!);

quib: Proc Options(main);
/*********************************************************************
* 06.10.2013 Walter Pachl
*********************************************************************/
  put Edit(quibbling())(Skip,a);
  put Edit(quibbling('ABC'))(Skip,a);
  put Edit(quibbling('ABC DEF'))(Skip,a);
  put Edit(quibbling('ABC DEF G H'))(Skip,a);
  return;
quibbling: proc(s) Returns(Char(100) Var);
  Dcl s Char(*);
  Dcl result Char(100) Var;
  Dcl (wi,p) Bin Fixed(31);
  If s= Then result=;
  Else Do;
    Do wi=1 By 1 While(s^=);
      p=index(s,' ');
      If p=0 Then Do;
        If wi>1 Then
          result=result!!' and '!!s;
        else
          result=s;
        s=;
        End;
      Else Do;
        If wi=1 Then
          result=left(s,p-1);
        Else
          result=result!!', '!!left(s,p-1);
        s=substr(s,p+1);
        End;
      End;
    End;
  Return('{'!!result!!'}');
  End;
End;</lang>
Output:
{}
{ABC}
{ABC, DEF}
{ABC, DEF, G, H}   

REXX

<lang rexx>say quibbling() say quibbling('ABC') say quibbling('ABC DEF') say quibbling('ABC DEF G H') exit

quibbling: procedure

   parse arg list
   Select
     When list= Then result=
     When words(list)=1 then result=word(list,1)
     Otherwise result=translate(strip(subword(list,1,words(list)-1)),',',' '),
       'and' word(list,words(list))
     End
   Return '{'result'}'</lang>
Output:
{}
{ABC}
{ABC and DEF}
{ABC,DEF,G and H}

Rust

This example is incomplete. output for no input words missing. Please ensure that it meets all task requirements and remove this message.

<lang Rust>fn quibble(seq: &[~str]) -> ~str {

   match seq {
       [] => ~"{}",
       [ref w] => fmt!("{%s}", *w),
       [..ws, ref w] => fmt!("{%s and %s}", ws.connect(", "), *w),
   }

}

fn main() {

   println(quibble([~"ABC"]));
   println(quibble([~"ABC", ~"DEF"]));
   println(quibble([~"ABC", ~"DEF", ~"G", ~"H"]));

}</lang>

Output:
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}

Tcl

<lang tcl>proc commaQuibble {lst} {

   if {[llength $lst] > 1} {

set lst [lreplace $lst end-1 end [join [lrange $lst end-1 end] " and "]]

   }
   return \{[join $lst ", "]\}

}

foreach input { {} {"ABC"} {"ABC" "DEF"} {"ABC" "DEF" "G" "H"} } {

   puts [commaQuibble $input]

}</lang>

Output:
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}