Comma quibbling: Difference between revisions
Content deleted Content added
→Nu: add |
|||
(92 intermediate revisions by 41 users not shown) | |||
Line 1:
{{task}}
Comma quibbling is a task originally set by Eric Lippert in his [
Line 13:
<br>
Test your function with the following series of inputs showing your output here on this page:
* []
* ["ABC"]
* ["ABC", "DEF"]
Line 20:
<br>
Note: Assume words are non-empty strings of uppercase characters for this task.
{{Template:Strings}}
<br><br>
=={{header|11l}}==
<syntaxhighlight lang="11l">F quibble(words)
R S words.len
0
‘{}’
1
‘{’words[0]‘}’
E
‘{’words[0.<(len)-1].join(‘, ’)‘ and ’words.last‘}’
print(quibble([‘’] * 0))
print(quibble([‘ABC’]))
print(quibble([‘ABC’, ‘DEF’]))
print(quibble([‘ABC’, ‘DEF’, ‘G’, ‘H’]))</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|360 Assembly}}==
<
COMMAQUI CSECT
USING COMMAQUI,R13 base register
Line 99 ⟶ 124:
CJ DS CL1
YREGS
END COMMAQUI</
{{out}}
<pre>
Line 108 ⟶ 133:
</pre>
=={{header|8080 Assembly}}==
<syntaxhighlight lang="8080asm"> org 100h
jmp demo
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Given a list of strings in HL, and a pointer in DE, write
;; the resulting string starting at DE.
quibble: mvi a,'{' ; Write the first {,
stax d
inx d ; And increment the pointer
push h ; Keep start of list
call strseqlen ; Get length of list
pop h ; Restore start of list
xra a ; Is the list empty?
ora b
jz quibend ; If empty list, we're done.
quibcopy: call strcpy ; Copy current string into output
inx h ; Advance input pointer to next string
dcr b ; Decrement counter
jz quibend ; If zero, that was the last string
push h ; Push input pointer
mov a,b ; Is the counter 1 now?
cpi 1
lxi h,quibcomma ; Add a comma and space,
jnz quibsep ; unless the counter was 1,
lxi h,quiband ; then use " and "
quibsep: call strcpy ; Copy the separator into the output
pop h ; Restore the input pointer
jmp quibcopy ; Do the next string in the list
quibend: mvi a,'}' ; Write the final '}'
stax d
inx d
mvi a,'$' ; And write a string terminator
stax d
ret
quibcomma: db ', $'
quiband: db ' and $'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Copy the string under HL to DE until the terminator $.
;; The terminator is not copied; HL and DE are left one byte
;; beyond the last byte copied.
strcpy: mov a,m ; Get byte from input
cpi '$' ; Are we at the end?
rz ; Then stop.
stax d ; Otherwise, store byte at output
inx h ; Increment the pointers
inx d
jmp strcpy ; Copy next byte.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Return in B the amount of strings in the string list in HL
strseqlen: mvi a,'$' ; String end
mvi b,0 ; String counter
count: cmp m ; Empty string?
rz ; Then we're done
inr b ; Otherwise, we have a string
strsrch: cmp m ; Find the end of the string
inx h
jnz strsrch
jmp count
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Demo code: run 'quibble' on the examples
demo: mvi c,4 ; Four examples
lxi h,examples ; Pointer to first example
example: push b ; Push example count
lxi d,buffer ; Into the buffer,
call quibble ; write the output of comma-quibbling
inx h ; Point to next example
push h ; Save pointer to next example
lxi d,buffer ; Write the output to the console
mvi c,9
call 5
lxi d,newline ; Write a newline to the console
mvi c,9
call 5
pop h ; Restore example pointer
pop b ; Restore example counter
dcr c ; If not zero,
jnz example ; do the next example.
ret
newline: db 10,13,'$'
examples: db '$'
db 'ABC$$'
db 'ABC$DEF$$'
db 'ABC$DEF$G$H$$'
buffer:</syntaxhighlight>
{{out}}
<pre>A>quib
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|ABC}}==
<syntaxhighlight lang="ABC">HOW TO RETURN quibble words:
PUT "" IN result
PUT #words IN remaining
FOR word IN words:
PUT result^word IN result
PUT remaining-1 IN remaining
IF remaining = 1: PUT result^" and " IN result
IF remaining > 1: PUT result^", " IN result
RETURN "{" ^ result ^ "}"
PUT {} IN tests
INSERT {} IN tests
INSERT {[1]: "ABC"} IN tests
INSERT {[1]: "ABC"; [2]: "DEF"} IN tests
INSERT {[1]: "ABC"; [2]: "DEF"; [3]: "G"; [4]: "H"} IN tests
FOR test IN tests:
WRITE quibble test/</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Acornsoft Lisp}}==
There's no string data type; symbols are used instead. The <code>implode</code> function is used to concatenate a list of symbols. When writing a symbol in source code, exclamation mark is an escape character that allows characters such as spaces and exclamation marks to be treated as part of the symbol's name.
<syntaxhighlight lang="lisp">
(defun examples ()
(map '(lambda (words) (printc (quibble words)))
'(() (ABC) (ABC DEF) (ABC DEF G H))))
(defun quibble (words)
(implode (list '{ (quibbles words) '})))
(defun quibbles (words)
(implode (conjunction words)))
(defun conjunction (words)
(cond ((null words)
'())
((null (cdr words))
words)
((null (cddr words))
(list (car words) '! and! (cadr words)))
(t
(cons (car words)
(cons ',! (conjunction (cdr words)))))))
</syntaxhighlight>
{{out}}
Calling <code>(examples)</code> will output:
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE PTR="CARD"
PROC Append(CHAR ARRAY text,suffix)
BYTE POINTER srcPtr,dstPtr
BYTE len
len=suffix(0)
IF text(0)+len>255 THEN
len=255-text(0)
FI
IF len THEN
srcPtr=suffix+1
dstPtr=text+text(0)+1
MoveBlock(dstPtr,srcPtr,len)
text(0)==+suffix(0)
FI
RETURN
PROC Quibble(PTR ARRAY items INT count CHAR ARRAY result)
INT i
result(0)=0
Append(result,"(")
FOR i=0 TO count-1
DO
Append(result,items(i))
IF i=count-2 THEN
Append(result," and ")
ELSEIF i<count-2 THEN
Append(result,", ")
FI
OD
Append(result,")")
RETURN
PROC Test(PTR ARRAY items BYTE count)
CHAR ARRAY result(256)
Quibble(items,count,result)
PrintE(result)
RETURN
PROC Main()
PTR ARRAY items(5)
Test(items,0)
items(0)="ABC"
Test(items,1)
items(1)="DEF"
Test(items,2)
items(2)="G"
Test(items,3)
items(3)="H"
Test(items,4)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Comma_quibbling.png Screenshot from Atari 8-bit computer]
<pre>
()
(ABC)
(ABC and DEF)
(ABC, DEF and G)
(ABC, DEF, G and H)
</pre>
=={{header|Ada}}==
<
procedure Comma_Quibble is
Line 126 ⟶ 374:
Argument(Argument_Count) & "}");
end case;
end Comma_Quibble;</
{{out}}
Line 141 ⟶ 389:
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.win32}}
<
# separated by ", ", except for the last which is separated from the rest by #
# " and ". The list is enclosed by braces #
Line 217 ⟶ 465:
test to list( "ABC" );
test to list( "ABC DEF" );
test to list( "ABC DEF G H" )</
{{out}}
<pre>: {}
Line 226 ⟶ 474:
=={{header|ALGOL W}}==
<
% returns a list of the words contained in wordString, separated by ", ", %
Line 332 ⟶ 580:
testToList( "ABC DEF G H" );
end.</
{{out}}
<pre>
Line 340 ⟶ 588:
ABC DEF G H : {ABC, DEF, G and H}</pre>
=={{header|APL}}==
<syntaxhighlight lang="APL">quibble ← 1⌽'}{',(∊⊢,¨2↓(' and ' ''),⍨(⊂', ')⍴⍨⍴)</syntaxhighlight>
{{out}}
<pre> quibble ⍬
{}
quibble ⊂'ABC'
{ABC}
quibble 'ABC' 'DEF'
{ABC and DEF}
quibble 'ABC' 'DEF' 'G' 'H'
{ABC, DEF, G and H}</pre>
=={{header|AppleScript}}==
{{Trans|JavaScript}}
<
on quibble(xs)
if length of xs > 1 then
Line 527 ⟶ 786:
on |words|(s)
words of s
end |words|</
{{Out}}
<pre>{}
Line 537 ⟶ 796:
{Jack and Jill}
{Loner}</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="rebol">quibble: $[sequence :block][
if? 0 = size sequence
-> return "{}"
if? 1 = size sequence
-> return ~"{|sequence\0|}"
last: pop 'sequence
return ~« {|join.with: ", " sequence| and |last|}
]
sentences: [
[]
["ABC"]
["ABC" "DEF"]
["ABC" "DEF" "G" "H"]
]
loop sentences 'sentence [
print quibble sentence
]</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Astro}}==
<
let result = s.join(' and ').replace(|| and ||, ", ", length(s) - 1)
return "{ $result }"
let s = [
[]
["ABC"]
["ABC", "DEF"]
["ABC", "DEF", "G", "H"]
]
for i in s:
print(quibble i)</syntaxhighlight>
=={{header|AutoHotkey}}==
<
MsgBox % quibble(["ABC"])
MsgBox % quibble(["ABC", "DEF"])
Line 569 ⟶ 860:
}
return "{" . s . "}"
}</
{{out}}
<pre>{}
Line 577 ⟶ 868:
=={{header|AWK}}==
<
for (i = 1; i < n - 1; i++) s = s a[i] ", "
i = n - 1; if (i > 0) s = s a[i] " and "
Line 589 ⟶ 880:
n = split("ABC DEF", c); print quibble(c, n)
n = split("ABC DEF G H", d); print quibble(d, n)
}</
{{out}}
<pre>{}
Line 597 ⟶ 888:
=={{header|Batch File}}==
<
setlocal enabledelayedexpansion
Line 637 ⟶ 928:
echo {!output!}
goto :EOF
::/THE FUNCTION</
{{out}}
<pre>{}
Line 645 ⟶ 936:
Press any key to continue . . .</pre>
=={{header|BCPL}}==
<syntaxhighlight lang="bcpl">get "libhdr"
// Add a character to the end of a string
let addch(s, ch) be
$( s%0 := s%0 + 1
s%(s%0) := ch
$)
// Add s2 to the end of s1
and adds(s1, s2) be
for i = 1 to s2%0 do
addch(s1, s2%i)
// Comma quibbling on strs, which should be a 0-terminated
// vector of string pointers.
let quibble(strs, buf) = valof
$( buf%0 := 0
addch(buf, '{')
until !strs = 0 do
$( addch(buf, '"')
adds(buf, !strs)
addch(buf, '"')
unless strs!1 = 0
test strs!2 = 0
then adds(buf, " and ")
else adds(buf, ", ")
strs := strs + 1
$)
addch(buf, '}')
resultis buf
$)
let start() be
$( let words = vec 4
let buf = vec 63
words!0 := 0
writef("%S*N", quibble(words, buf))
words!0 := "ABC" ; words!1 := 0
writef("%S*N", quibble(words, buf))
words!1 := "DEF" ; words!2 := 0
writef("%S*N", quibble(words, buf))
words!2 := "G" ; words!3 := "H" ; words!4 := 0
writef("%S*N", quibble(words, buf))
$)</syntaxhighlight>
{{out}}
<pre>{}
{"ABC"}
{"ABC" and "DEF"}
{"ABC", "DEF", "G" and "H"}</pre>
=={{header|Bracmat}}==
<
& ABC:?L2
& ABC DEF:?L3
Line 662 ⟶ 1,007:
& whl
' (!names:%?name ?names&out$(!name concat$!!name))
);</
{{out}}
<pre>L1 {}
Line 670 ⟶ 1,015:
=={{header|C}}==
<
#include <string.h>
#include <stdlib.h>
Line 722 ⟶ 1,067:
}
return EXIT_SUCCESS;
}</
{{Out}}
<pre>{}
Line 731 ⟶ 1,076:
=={{header|C sharp|C#}}==
<
using System.Linq;
Line 763 ⟶ 1,108:
#endregion
}
}</
{{out}}
<pre>
Line 773 ⟶ 1,118:
=={{header|C++}}==
<
template<class T>
Line 798 ⟶ 1,143:
}
return 0;
}</
{{out}}
<pre>
Line 809 ⟶ 1,154:
=={{header|Clojure}}==
<
(let [sep (if (pos? (count sq)) " and " "")]
(apply str
Line 826 ⟶ 1,171:
(test quibble)
(test quibble-f)</
{{out}}
<pre>{}
Line 833 ⟶ 1,178:
{ABC, DEF, G and H}
</pre>
=={{header|CLU}}==
<syntaxhighlight lang="clu">quibble = proc (words: array[string]) returns (string)
out: string := "{"
last: int := array[string]$high(words)
for i: int in array[string]$indexes(words) do
out := out || words[i]
if i < last-1 then
out := out || ", "
elseif i = last-1 then
out := out || " and "
end
end
return(out || "}")
end quibble
start_up = proc ()
as = array[string]
aas = array[as]
po: stream := stream$primary_output()
testcases: aas := aas$
[as$[],
as$["ABC"],
as$["ABC","DEF"],
as$["ABC","DEF","G","H"]]
for testcase: as in aas$elements(testcases) do
stream$putl(po, quibble(testcase))
end
end start_up</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|COBOL}}==
{{works with|OpenCOBOL|2.0}}
<
IDENTIFICATION DIVISION.
PROGRAM-ID. comma-quibbling-test.
Line 910 ⟶ 1,292:
MOVE FUNCTION CONCATENATE("{", str) TO str
.
END FUNCTION comma-quibbling.</
{{out}}
Line 922 ⟶ 1,304:
=={{header|CoffeeScript}}==
<
'{' +
(most.join ', ') +
Line 931 ⟶ 1,313:
console.log quibble(s) for s in [ [], ["ABC"], ["ABC", "DEF"],
["ABC", "DEF", "G", "H" ] ]
</syntaxhighlight>
{{out}}
<pre>{}
Line 937 ⟶ 1,319:
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Commodore BASIC}}==
The Commodore character set has no curly braces, so I substituted square brackets. The solution could no doubt be improved, but some of the elegance of other solutions is not possible simply because a FOR loop always executes at least once, even if its parameters would seem to indicate that it should not.
<syntaxhighlight lang="basic">100 DIM A$(3)
110 FOR TC=1 TO 4
120 : READ A: IF A=0 THEN 160
130 : FOR I=0 TO A-1
140 : READ A$(I)
150 : NEXT I
160 : GOSUB 200
170 : PRINT CQ$
180 NEXT TC
190 END
200 CQ$="["
210 IF A < 1 THEN 290
220 CQ$ = CQ$ + A$(0)
230 IF A < 2 THEN 290
240 IF A < 3 THEN 280
250 FOR I=1 TO A - 2
260 : CQ$ = CQ$ + ", " + A$(I)
270 NEXT I
280 CQ$ = CQ$ + " AND " + A$(A - 1)
290 CQ$ = CQ$ + "]"
300 RETURN
310 DATA 0
320 DATA 1, ABC
330 DATA 2, ABC, DEF
340 DATA 4, ABC, DEF, G, H
</syntaxhighlight>
{{out}}
<pre>[]
[ABC]
[ABC AND DEF]
[ABC, DEF, G AND H]</pre>
=={{header|Common Lisp}}==
<
(defun quibble (&rest args)
(format t "{~{~a~#[~; and ~:;, ~]~}}" args))
Line 947 ⟶ 1,363:
(quibble "ABC" "DEF")
(quibble "ABC" "DEF" "G" "H")
</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Cowgol}}==
<syntaxhighlight lang="cowgol">include "cowgol.coh";
sub quibble(words: [[uint8]],
length: intptr,
buf: [uint8]):
(out: [uint8]) is
sub append(s: [uint8]) is
while [s] != 0 loop
[buf] := [s];
buf := @next buf;
s := @next s;
end loop;
end sub;
out := buf;
append("{");
while length > 0 loop
append([words]);
words := @next words;
case length is
when 1: break;
when 2: append(" and ");
when else: append(", ");
end case;
length := length - 1;
end loop;
append("}");
[buf] := 0;
end sub;
var w1: [uint8][] := {};
var w2: [uint8][] := {"ABC"};
var w3: [uint8][] := {"ABC","DEF"};
var w4: [uint8][] := {"ABC","DEF","G","H"};
print(quibble(&w1[0], @sizeof w1, LOMEM)); print_nl();
print(quibble(&w2[0], @sizeof w2, LOMEM)); print_nl();
print(quibble(&w3[0], @sizeof w3, LOMEM)); print_nl();
print(quibble(&w4[0], @sizeof w4, LOMEM)); print_nl();
</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
Line 955 ⟶ 1,422:
=={{header|D}}==
<
string quibbler(in string[] seq) pure /*nothrow*/ {
Line 971 ⟶ 1,438:
["ABC", "DEF", "G", "H"]])
test.quibbler.writeln;
}</
{{out}}
<pre>{}
Line 979 ⟶ 1,446:
===Alternative Version===
<
enum quibbler = (in string[] a) pure =>
Line 988 ⟶ 1,455:
[[], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]]
.map!quibbler.writeln;
}</
{{out}}
<pre>["{}", "{ABC}", "{ABC and DEF}", "{ABC, DEF, G and H}"]</pre>
=={{header|dc}}==
<syntaxhighlight lang="dc">[(q)uibble: main entry point. print brackets, calling n in between if stack not
empty.]sx
[ [{]n z 0 !=n [}]pR ]sq
[(n)onempty: if more than 1 item, call m. then print top of stack.]sx
[ z 1 !=m n ]sn
[(m)ore: call f to flip stack into r register, call p to print most of it,
then pop the last item back onto the main stack so it's there to be printed
after we return]sx
[ lfx lpx Lr ]sm
[(f)lip: utility routine to reverse the stack into the r register]sx
[ Sr z 0 !=f ]sf
[(p)rint: get next item from stack in r register and print it. If there are
more than 2 items left on the register stack (which never drops below one
item), print a comma (c) and recurse. If there are exactly two items left,
print " and " (a) and return.]sx
[ Lr n 2 yr >c 2 yr =a 2 yr >p]sp
[(c)omma: utility routine to print a comma followed by a space]sx
[ [, ]n ]sc
[(a)and: utility routine to print " and "]sx
[ [ and ]n ]sa
[run tests]sx
lqx
[ABC] lqx
[ABC] [DEF] lqx
[ABC] [DEF] [G] [H] lqx</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|DCL}}==
<
$ gosub comma_quibbling
$ write sys$output return_string
Line 1,027 ⟶ 1,535:
$ done2:
$ return_string = return_string + "}"
$ return</
{}out}}
<pre>$ @comma_quibbling
Line 1,035 ⟶ 1,543:
{ABC, DEF, G and H}</pre>
=={{header|Delphi}}==
See [[#Pascal|Pascal]].
=={{header|Déjà Vu}}==
<
"}" )
if lst:
Line 1,050 ⟶ 1,560:
!. comma-quibble [ "ABC" ]
!. comma-quibble [ "ABC" "DEF" ]
!. comma-quibble [ "ABC" "DEF" "G" "H" ]</
{{out}}
<pre>"{}"
Line 1,056 ⟶ 1,566:
"{ABC and DEF}"
"{ABC, DEF, G and H}"</pre>
=={{header|EasyLang}}==
<syntaxhighlight lang=text>
func$ tolist s$ .
s$[] = strsplit s$ " "
r$ = "{"
n = len s$[]
for i = 1 to n - 2
r$ &= s$[i] & ", "
.
if n > 0
if n > 1
r$ &= s$[n - 1] & " and "
.
r$ &= s$[n]
.
r$ &= "}"
return r$
.
print tolist ""
print tolist "ABC"
print tolist "ABC DEF"
print tolist "ABC DEF G H"
</syntaxhighlight>
=={{header|EchoLisp}}==
<
(lib 'match)
Line 1,079 ⟶ 1,613:
("ABC" "DEF") ----> "{ ABC and DEF }"
("ABC" "DEF" "G" "H") ----> "{ ABC, DEF, G and H }"
</syntaxhighlight>
=={{header|ed}}==
Uses basic regular expressions (BREs).
<syntaxhighlight lang="sed">
# by Artyom Bologov
H
,p
g/.*/s/ /, /g
g/[,]/s/,\([^,]*\)$/ and\1/
g/.*/s//{&}/
,p
Q
</syntaxhighlight>
{{out}}
<pre>$ ed -s comma-quibling.input < comma-quibling.ed
Newline appended
ABC
ABC DEF
ABC DEF G H
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Eiffel}}==
<syntaxhighlight lang="eiffel">
class
APPLICATION
Line 1,131 ⟶ 1,691:
end
</syntaxhighlight>
{{out}}
<pre>
Line 1,142 ⟶ 1,702:
=={{header|Elixir}}==
{{trans|Erlang}}
<
def generate( list ), do: "{#{ generate_content(list) }}"
Line 1,157 ⟶ 1,717:
Enum.each([[], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]], fn list ->
IO.inspect RC.generate(list)
end)</
{{out}}
Line 1,168 ⟶ 1,728:
=={{header|Erlang}}==
<syntaxhighlight lang="text">
-module( comma_quibbling ).
Line 1,186 ⟶ 1,746:
With_commas = [X ++ "," || X <- T],
string:join(lists:reverse([Last, "and", Second_to_last | With_commas]), " ").
</syntaxhighlight>
{{out}}
<pre>
Line 1,193 ⟶ 1,753:
</pre>
=={{header|F_Sharp|F#}}==
===One Way===
<syntaxhighlight lang="fsharp">let quibble list =
let rec inner = function
| [] -> ""
Line 1,207 ⟶ 1,768:
quibble ["ABC"; "DEF"]
quibble ["ABC"; "DEF"; "G"]
quibble ["ABC"; "DEF"; "G"; "H"]</
Output from testing (in F# Interactive 3.0, Open Source version):
<syntaxhighlight lang="text">
> quibble [];;
val it : string = "{}"
Line 1,219 ⟶ 1,780:
val it : string = "{ABC, DEF and G}"
> quibble ["ABC"; "DEF"; "G"; "H"];;
val it : string = "{ABC, DEF, G and H}"</
===or Another===
====The Function====
<syntaxhighlight lang="fsharp">
let quibble quibbler quibblee = Seq.zip quibblee quibbler //Sorry, just too good a line to miss, back in my Latin classes
</syntaxhighlight>
====The Task====
<syntaxhighlight lang="fsharp">
let fN n = quibble (List.mapi(fun n _->match n with 0->"" |1-> " and " |_->", ") n |> List.rev) n
printf "{"; fN ["ABC"; "DEF"; "G"; "H"] |> Seq.iter(fun(n,g)->printf "%s%s" n g); printfn"}"
printf "{"; fN ["ABC"; "DEF"; "G"] |> Seq.iter(fun(n,g)->printf "%s%s" n g); printfn"}"
printf "{"; fN ["ABC"; "DEF"] |> Seq.iter(fun(n,g)->printf "%s%s" n g); printfn"}"
printf "{"; fN ["ABC"] |> Seq.iter(fun(n,g)->printf "%s%s" n g); printfn"}"
printf "{"; fN [] |> Seq.iter(fun(n,g)->printf "%s%s" n g); printfn"}"
</syntaxhighlight>
{{out}}
<pre>
{ABC, DEF, G and H}
{ABC, DEF and G}
{ABC and DEF}
{ABC}
{}
</pre>
=={{header|
This example uses the <code>inverse</code> vocabulary, which builds on the concept of invertible quotations as the basis for pattern matching. It is discussed at length in this approachable [http://micsymposium.org/mics_2009_proceedings/mics2009_submission_72.pdf paper].
<syntaxhighlight lang="factor">USING: inverse qw sequences ;
: (quibble) ( seq -- seq' )
{
{ [ { } ] [ "" ] }
{ [ 1array ] [ ] }
{ [ 2array ] [ " and " glue ] }
[ unclip swap (quibble) ", " glue ]
} switch ;
: quibble ( seq -- str ) (quibble) "{%s}" sprintf ;
{ } qw{ ABC } qw{ ABC DEF } qw{ ABC DEF G H }
[ quibble print ] 4 napply</syntaxhighlight>
{{out}}
<pre>
</pre>
=={{header|Forth}}==
The efficient and beautiful way to solve the task is to keep a sliding triplet of consequent words. First we unconditionally read the first two words; if there are none, "read" gives us an empty word. Then we read the input stream, typing third to last word together with a comma. When the loop ends, we have two (possible empty) words on the stack, and the only thing left to do is to output it accordingly.
<syntaxhighlight lang="text">
: read bl parse ;
: not-empty? ( c-addr u -- c-addr u true | false ) ?dup-if true else drop false then ;
: third-to-last 2rot ;
: second-to-last 2swap ;
: quibble
." {"
read read begin read not-empty? while third-to-last type ." , " repeat
second-to-last not-empty? if type then
not-empty? if ." and " type then
." }" cr ;
quibble
quibble ABC
quibble ABC DEF
quibble ABC DEF G H
</syntaxhighlight>
=={{header|Fortran}}==
Line 1,370 ⟶ 1,854:
Subroutine QUIBBLE doesn't have to worry about this because it works with TEXT as a parameter, whatever its size (various integer limits apply) however, it too has the same problem because it locates the start and end positions of each word, and, how many words are going to be found? So once again, the arrays are made "surely large enough" for the expected class of problem. The first stage is to locate the words separated by any amount of "white space", which, thanks to the inability to rely on the evaluation of compound boolean expressions (of the form <code>IF (''in bounds'' & ''Array indexing'')</code>) in the "shortcut" manner, employs a battery of IF-statements. Fortran does not offer a data type "list of ..." so there is no prospect of placing the words into such an entity then inserting commas and "and" elements into the list to taste. Instead, the list of words is represented by a sequence of values in ordinary arrays.
The source style is Fortran 77, thus the use of COMMON to pass some I/O unit numbers. The plan initially was to engage in trickery with the variable FORMAT features, of the form <''expression''>(blah blah) to signify some number of repetitions of (blah blah), which number might be ''zero'', but alas, although <0>X works, it proved not to work for grouped items in place of a format code. So the <..> extension had to be abandoned, and plainer F77 results.<
CHARACTER*(*) TEXT !The text, delimited by spaces.
LOGICAL OXFORDIAN !Just so.
Line 1,435 ⟶ 1,919:
Closedown
30 END !All files are closed by exiting.</
Output:
<pre>
Line 1,452 ⟶ 1,936:
=={{header|FreeBASIC}}==
<
' FB 1.05.0 Win64
Line 1,511 ⟶ 1,995:
Print "Press any key to quit the program"
Sleep
</syntaxhighlight>
{{out}}
Line 1,519 ⟶ 2,003:
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|Frink}}==
<syntaxhighlight lang="frink">quibble[enum] :=
{
list = toArray[enum] // This makes it work on any enumerating expression
size = length[list]
if size >= 2
return "{" + join[", ", first[list, size-1]] + " and " + last[list] + "}"
else
return "{" + join["", list] + "}"
}
data = [[], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]]
for line = data
println[quibble[line]]</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|FutureBasic}}==
Long solution:
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
local fn CommaQuibber( string as CFStringRef ) as CFStringRef
CFStringRef tempStr
NSUInteger i
tempStr = fn StringByReplacingOccurrencesOfString( string, @"[", @"" )
tempStr = fn StringByReplacingOccurrencesOfString( tempStr, @"]", @"" )
tempStr = fn StringByReplacingOccurrencesOfString( tempStr, @" ", @"" )
tempStr = fn StringByReplacingOccurrencesOfString( tempStr, @"\"", @"" )
CFMutableStringRef quibStr = fn MutableStringWithCapacity(0)
CFArrayRef arr = fn StringComponentsSeparatedByString( tempStr, @"," )
NSUInteger count = len(arr)
select switch ( count )
case 0 : MutableStringSetString( quibStr, @"{}" ) : break
case 1 : MutableStringSetString( quibStr, fn StringWithFormat( @"{%@}", arr[0] ) ) : break
case 2 : MutableStringSetString( quibStr, fn StringWithFormat( @"{%@ and %@}", arr[0], arr[1] ) ) : break
case else
MutableStringAppendFormat( quibStr, @"{" )
for i = 0 to count -1
if ( i != count -1 )
MutableStringAppendFormat( quibStr, @"%@, ", arr[i] )
else
MutableStringAppendFormat( quibStr, @"and %@}", arr[i] )
end if
next
end select
end fn = quibStr
NSLog( @"%@", fn CommaQuibber( @"[]" ) )
NSLog( @"%@", fn CommaQuibber( @"[\"ABC\"]" ) )
NSLog( @"%@", fn CommaQuibber( @"[\"ABC\", \"DEF\"]" ) )
NSLog( @"%@", fn CommaQuibber( @"[\"ABC\", \"DEF\", \"G\", \"H\"]" ) )
HandleEvents
</syntaxhighlight>
Short solution:
<syntaxhighlight lang="futurebasic">
local fn CommaQuibbler( s as CFArrayRef ) as CFStringRef
CFStringRef result = NULL
select ( len(s) )
case 0: exit fn = @"{}"
case 1: exit fn = fn StringWithFormat( @"{%@}", s[0] )
case 2: exit fn = fn StringWithFormat( @"{%@ and %@}", s[0], s[1] )
case else
result = fn StringWithFormat( @"{%@}", fn ArrayComponentsJoinedByString( s, @", " ) )
CFRange lastComma = fn StringRangeOfStringWithOptions( result, @",", NSBackwardsSearch )
result = fn StringByReplacingCharactersInRange( result, lastComma, @" and" )
end select
end fn = result
print fn CommaQuibbler( @[] )
print fn CommaQuibbler( @[@"ABC"] )
print fn CommaQuibbler( @[@"ABC", @"DEF"] )
print fn CommaQuibbler( @[@"ABC", @"DEF", @"G", @"H"] )
HandleEvents
</syntaxhighlight>
Shorter solution:
<syntaxhighlight lang="futurebasic">
local fn Quibble( string as CFStringRef ) as CFStringRef
CfArrayRef arr = fn StringComponentsSeparatedByString( string, @" " )
CFStringRef rst
if ( len(arr) == 0 ) then rst = @"" else rst = fn StringWithFormat( @"%@", fn ArrayLastObject( arr ) )
if ( len(arr) > 1 )
CFArrayRef subArray = fn ArraySubarrayWithRange( arr, fn CFRangeMake( 0, len(arr) - 1 ) )
rst = fn StringWithFormat( @"%@ and %@", fn ArrayComponentsJoinedByString( subArray, @", " ), rst )
end if
end fn = fn StringWithFormat( @"{%@}", rst )
print fn Quibble( @"" )
print fn Quibble( @"ABC")
print fn Quibble( @"ABC DEF" )
print fn Quibble( @"ABC DEF G H" )
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G, and H}
</pre>
=={{header|Gambas}}==
'''[https://gambas-playground.proko.eu/?gist=8edc63b206a1de50dd104cd12486ac03 Click this link to run this code]'''
<
Dim sInput As String[] = ["", "ABC", "ABC DEF", "ABC DEF G H"]
Dim sTemp As String
Line 1,537 ⟶ 2,135:
Next
End</
Output:
<pre>
Line 1,548 ⟶ 2,146:
=={{header|Go}}==
The blog mentioned code maintenence. The idea here is to make the code easy for maintainers to understand by making it correspond as directly as possible to the problem description.
<
import (
Line 1,577 ⟶ 2,175:
fmt.Println(q([]string{"ABC", "DEF"}))
fmt.Println(q([]string{"ABC", "DEF", "G", "H"}))
}</
{{out}}
<pre>
Line 1,587 ⟶ 2,185:
=={{header|Groovy}}==
<
'''Testing:'''
<
println "Verifying commaQuibbling($input) == $expected"
assert commaQuibbling(input) == expected
}</
{{out}}
<pre>Verifying commaQuibbling([]) == {}
Line 1,600 ⟶ 2,198:
=={{header|Haskell}}==
<
where quibbles [] = ""
quibbles [a] = a
Line 1,609 ⟶ 2,207:
[[], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]] ++
(map words ["One two three four", "Me myself I", "Jack Jill", "Loner" ])
</syntaxhighlight>
{{Out}}
<pre>
Line 1,623 ⟶ 2,221:
Or, defining just two cases, and drawing more on standard libraries than on hand-crafted pattern-matching and recursion:
<
--------------------- COMMA QUIBBLING --------------------
quibble :: [String] -> String
quibble ws@(_ : _ : _) =
intercalate
( [intercalate ", " . reverse . tail, head]
)
quibble xs = concat xs
--------------------------- TEST -------------------------
main :: IO ()
main =
mapM_ (putStrLn . (`intercalate` ["{", "}"]) . quibble) $
[[], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]]
<> ( words
<$> [ "One two three four",
"Me myself I",
"Jack Jill",
"Loner"
]
)</syntaxhighlight>
{{Out}}
<pre>{}
Line 1,650 ⟶ 2,257:
=={{header|Icon}} and {{header|Unicon}}==
The following works in both languages:
<
every write(quibble([] | ["ABC"] | ["ABC","DEF"] | ["ABC","DEF","G","H"]))
end
Line 1,660 ⟶ 2,266:
while s := pull(A)||join||s do join := if *join = 0 then " and " else ", "
return "{"||s||"}"
end</
Sample run:
Line 1,674 ⟶ 2,280:
=={{header|J}}==
<
withoutLast2=: ([: # _2&}.) {. ]
quibble=: '{', '}' ,~ ', ' joinstring withoutLast2 , <@quibLast2</
'''Testing:'''
<
quibble every Tests
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</
Alternative implementation:
<
quibble=: '{','}',~ commaand</
(same results)
=={{header|Java}}==
<
public static String quibble(String[] words) {
Line 1,714 ⟶ 2,320:
System.out.println(quibble(new String[]{"ABC", "DEF", "G", "H"}));
}
}</
{{out}}
Line 1,725 ⟶ 2,331:
=={{header|JavaScript}}==
===ES5===
<
return "{" +
words.slice(0, words.length-1).join(",") +
Line 1,737 ⟶ 2,343:
console.log(quibble(s));
}
);</
{{out}}
<pre>{}
Line 1,748 ⟶ 2,354:
{{Trans|Haskell}}
Composing from a set of generic functions:
<
'use strict';
//
// quibble :: [String] -> String
const quibble = xs =>
intercalate(' and ')(
),
head
])([reverse(xs)])
)
) : concat(xs);
//
const main = () =>
unlines(
map(compose(x => '{' + x + '}', quibble))(
append([
[],
["ABC"],
["ABC", "DEF"],
["ABC", "DEF", "G", "H"]
])(
map(words)([
"One two three four",
"Me myself I",
"Jack Jill",
"Loner"
])
)
));
// ---------------- GENERIC FUNCTIONS ----------------
//
const
// The sequential application of each of a list
// of functions to each of a list of values.
// apList([x => 2 * x, x => 20 + x])([1, 2, 3])
// -> [2, 4, 6, 21, 22, 23]
xs => fs.flatMap(f => xs.map(f));
//
const
// A list defined by the
// concatenation of two others.
ys => xs.concat(ys);
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
const compose = (...fs) =>
// A function defined by the right-to-left
// composition of all the functions in fs.
fs.reduce(
(f, g) => x => f(g(x)),
x => x
);
// concat :: [[a]] -> [a]
// concat :: [String] -> String
const concat = xs => (
ys => 0 < ys.length ? (
ys.every(Array.isArray) ? (
[]
) : ''
).concat(...ys) : ys
)(xs);
// head :: [a] -> a
const head = xs => (
ys => ys.length ? (
ys[0]
) : undefined
)(list(xs));
// intercalate :: String -> [String] -> String
const intercalate = s =>
// The concatenation of xs
// interspersed with copies of s.
xs => xs.join(s);
// list :: StringOrArrayLike b => b -> [a]
const list = xs =>
// xs itself, if it is an Array,
// or an Array derived from xs.
Array.isArray(xs) ? (
xs
) : Array.from(xs || []);
// map :: (a -> b) -> [a] -> [b]
const map =
// The list obtained by applying f
// to each element of xs.
// (The image of xs under f).
xs => [...xs].map(f);
// reverse :: [a] -> [a]
const reverse = xs =>
xs.
) :
// tail :: [a] -> [a]
const tail = xs =>
// A new list consisting of all
// items of xs except the first.
xs.slice(1);
// unlines :: [String] -> String
const unlines = xs =>
// A single string formed by the intercalation
// of a list of strings with the newline character.
xs.join('\n');
// words :: String -> [String]
// List of space-delimited sub-strings.
// MAIN
return main();
})();</syntaxhighlight>
{{Out}}
<pre>{}
Line 1,850 ⟶ 2,504:
{Jack and Jill}
{Loner}</pre>
Alternative implementation:
<syntaxhighlight lang="javascript">
function quibble(words) {
var words2 = words.join()
var words3 = [...words2].reverse().join('');
var res = words3.replace(",", " dna ");
var words4 = [...res].reverse().join('');
return '{'+words4+'}';
}
</syntaxhighlight>
=={{header|jq}}==
{{works with|jq|1.4}}
<
if length == 0 then ""
elif length == 1 then .[0]
else (.[0:length-1] | join(", ")) + " and " + .[length-1]
end
| "{" + . + "}";</
'''Example''':
<
{{Out}}
<
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</syntaxhighlight>
=={{header|Julia}}==
{{works with|Julia|0.6}}
<
if isempty(arr) rst = "" else rst = "$(arr[end])" end
if length(arr) > 1 rst = join(arr[1:end-1], ", ") * " and " * rst end
Line 1,880 ⟶ 2,547:
@show quibble(["ABC"])
@show quibble(["ABC", "DEF"])
@show quibble(["ABC", "DEF", "G", "H"])</
{{Out}}
Line 1,889 ⟶ 2,556:
=={{header|Kotlin}}==
<
fun commaQuibble(s: String): String {
Line 1,914 ⟶ 2,581:
)
for (input in inputs) println("${input.padEnd(24)} -> ${commaQuibble(input)}")
}</
{{out}}
Line 1,922 ⟶ 2,589:
["ABC", "DEF"] -> {ABC and DEF}
["ABC", "DEF", "G", "H"] -> {ABC, DEF, G and H}
</pre>
=={{header|Lang}}==
<syntaxhighlight lang="lang">
fp.quibble = (&words) -> {
$len $= @&words
$output = \{\e
$i
repeat($[i], $len) {
$output += &words[$i] ||| ($i == -|$len?\e:($i == $len - 2?\sand\s:\,\s))
}
$output += \}\e
return $output
}
fn.println(fp.quibble(fn.arrayOf()))
fn.println(fp.quibble(fn.arrayOf(ABC)))
fn.println(fp.quibble(fn.arrayOf(ABC, DEF)))
fn.println(fp.quibble(fn.arrayOf(ABC, DEF, G, H)))
</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|Lasso}}==
<
local(collection =
Line 1,947 ⟶ 2,645:
}
}</
Output:
Line 1,957 ⟶ 2,655:
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
do
read in$
Line 2,002 ⟶ 2,700:
data "END" 'Sentinel for EOD.
</syntaxhighlight>
{{Out}}
<pre>
Line 2,012 ⟶ 2,710:
=={{header|Logo}}==
<
output cond [
[ [empty? :list] :result ]
Line 2,037 ⟶ 2,735:
]
bye</
{{out}}
<pre>{}
Line 2,046 ⟶ 2,744:
=={{header|Lua}}==
<
local outString, join = "{"
for strNum = 1, #strTab do
Line 2,067 ⟶ 2,765:
{"ABC", "DEF", "G", "H"}
}
for _, input in pairs(testCases) do print(quibble(input)) end</
{{out}}
<pre>{}
Line 2,073 ⟶ 2,771:
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|M2000 Interpreter}}==
===Using string as argument===
<syntaxhighlight lang="m2000 interpreter">
Module Checkit {
function f$ {
what$=mid$(trim$(letter$),2)
what$=Left$(what$, len(what$)-1)
flush ' erase any argument from stack
Data param$(what$)
m=stack.size
document resp$="{"
if m>2 then {
shift m-1, 2 ' get last two as first two
push letter$+" and "+letter$
m-- ' one less
shiftback m ' move to last position
}
while not empty {
resp$=letter$+if$(not empty->", ", "")
}
=resp$+"}"
}
\\ we use ? for Print
? f$({[]})
? f$({["ABC"]})
? f$({["ABC", "DEF"]})
? f$({["ABC","DEF", "G", "H"]})
}
Checkit
</syntaxhighlight>
===Using String functions only===
<syntaxhighlight lang="m2000 interpreter">
Module Checkit {
function f$ {
what$=filter$(trim$(letter$), chr$(34))
what$=Mid$(what$, 2, len(what$)-2)
count=Len(what$)-Len(filter$(what$,","))
if count>2 then m=rinstr(what$, ", ") : insert m, 2 what$=" and "
="{"+what$+"}"
}
? f$({[]})
? f$({["ABC"]})
? f$({["ABC", "DEF"]})
? f$({["ABC","DEF", "G", "H"]})
}
Checkit
</syntaxhighlight>
===Using array as argument===
<syntaxhighlight lang="m2000 interpreter">
Module Checkit {
function f$(ar) {
flush
Data ! ar
m=stack.size
document resp$="{"
if m>2 then {
shift m-1, 2 ' get last two as first two
push letter$+" and "+letter$
m-- ' one less
shiftback m ' move to last position
}
while not empty {
resp$=letter$+if$(not empty->", ", "")
}
=resp$+"}"
}
? f$((,))
? f$(("ABC",))
? f$(("ABC", "DEF"))
? f$(("ABC","DEF", "G", "H"))
}
Checkit
</syntaxhighlight>
{{out}}
<pre >
{}
{ABC}
{ABC, DEF}
{ABC, DEF, G and H}
</pre >
=={{header|Maple}}==
<
uses StringTools;
Fence( proc()
Line 2,086 ⟶ 2,869:
end if
end(), "{", "}" )
end proc:</
Check it on the required inputs:
<
"{}"
Line 2,100 ⟶ 2,883:
> Quibble( ["ABC", "DEF", "G", "H"] );
"{ABC, DEF, G and H}"
</syntaxhighlight>
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<
ToString@{StringJoin@@
Replace[Riffle[{words}, ", "],
{most__, ", ", last_} -> {most, " and ", last}]}</
{{out}}
<pre>
Line 2,120 ⟶ 2,903:
In[5]:= quibble["ABC","DEF","G","H"]
Out[5]= {ABC, DEF, G and H}
</pre>
=={{header|MATLAB}} / {{header|Octave}}==
<syntaxhighlight lang="matlab">
function r = comma_quibbling(varargin)
if isempty(varargin)
r = '';
elseif length(varargin)==1;
r = varargin{1};
else
r = [varargin{end-1},' and ', varargin{end}];
for k=length(varargin)-2:-1:1,
r = [varargin{k}, ', ', r];
end
end
end;
</syntaxhighlight>
{{out}}
<pre>
octave:73> comma_quibbling('')
ans =
octave:74> comma_quibbling('ABC')
ans = ABC
octave:75> comma_quibbling('ABC','DEF')
ans = ABC and DEF
octave:76> comma_quibbling('ABC','DEF','G')
ans = ABC, DEF and G
octave:77> comma_quibbling('ABC','DEF','G','H')
ans = ABC, DEF, G and H
</pre>
=={{header|MAXScript}}==
<syntaxhighlight lang="maxscript">
fn separate words: =
(
Line 2,147 ⟶ 2,961:
)
)
</syntaxhighlight>
Output:
<syntaxhighlight lang="maxscript">
separate words:#()
"{}"
Line 2,158 ⟶ 2,972:
separate words:#("ABC","DEF","G","H")
"{ABC, DEF, G and H}"
</syntaxhighlight>
=={{header|Miranda}}==
<syntaxhighlight lang="miranda">main :: [sys_message]
main = [Stdout (show test ++ ": {" ++ quibble test ++ "}\n") | test <- tests]
tests :: [[[char]]]
tests = [ [],
["ABC"],
["ABC","DEF"],
["ABC","DEF","G","H"] ]
quibble :: [[char]]->[char]
quibble [] = []
quibble [word] = word
quibble [word1,word2] = word1 ++ " and " ++ word2
quibble (word:words) = word ++ ", " ++ quibble words</syntaxhighlight>
{{out}}
<pre>[]: {}
["ABC"]: {ABC}
["ABC","DEF"]: {ABC and DEF}
["ABC","DEF","G","H"]: {ABC, DEF, G and H}</pre>
=={{header|NetRexx}}==
<
options replace format comments java crossref symbols nobinary
Line 2,186 ⟶ 3,021:
end lst
return
</syntaxhighlight>
{{out}}
<pre>
Line 2,196 ⟶ 3,031:
=={{header|Nim}}==
<
result = ""
for i, c in s:
Line 2,205 ⟶ 3,040:
var s = @[@[], @["ABC"], @["ABC", "DEF"], @["ABC", "DEF", "G", "H"]]
for i in s:
echo commaQuibble(i)</
=={{header|Nu}}==
<syntaxhighlight lang="nu">def quibble [] {
if ($in | length) < 3 { $in } else [($in | drop | str join ', ') ($in | last)]
| $'{($in | str join " and ")}'
}
# test
[
[]
[ABC]
[ABC DEF]
[ABC DEF G H]
]
| each { quibble }</syntaxhighlight>
{{out}}
<pre>
╭───┬─────────────────────╮
│ 0 │ {} │
│ 1 │ {ABC} │
│ 2 │ {ABC and DEF} │
│ 3 │ {ABC, DEF, G and H} │
╰───┴─────────────────────╯
</pre>
=={{header|Oberon-2}}==
{{works with|oo2c}}
<
MODULE CommaQuibbling;
IMPORT
Line 2,255 ⟶ 3,114:
Out.String(":> ");Out.String(str);Out.Ln
END CommaQuibbling.
</syntaxhighlight>
{{out}}
<pre>
Line 2,270 ⟶ 3,129:
</pre>
=={{header|
<syntaxhighlight lang="objeck">class Quibbler {
function : Quibble(words : String[]) ~ String {
text := "{";
each(i : words) {
text += words[i];
if(i < words->Size() - 2) {
text += ", ";
}
else if(i = words->Size() - 2) {
text += " and ";
};
};
text += "}";
return text;
}
function : Main(args : String[]) ~ Nil {
words := String->New[0];
Quibble(words)->PrintLine();
words := ["ABC"];
Quibble(words)->PrintLine();
words := ["ABC", "DEF"];
Quibble(words)->PrintLine();
words := ["ABC", "DEF", "G", "H"];
Quibble(words)->PrintLine();
}
}</syntaxhighlight>
Output:
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|OCaml}}==
<syntaxhighlight lang="ocaml">open Printf
let quibble list =
let rec aux = function
| a :: b :: c :: d :: rest -> a ^ ", " ^ aux (b :: c :: d :: rest)
| [a; b; c] -> sprintf "%s, %s and %s}" a b c
| [a; b] -> sprintf "%s and %s}" a b
| [a] -> sprintf "%s}" a
| [] -> "}" in
"{" ^ aux list
let test () =
[[];
["ABC"];
["ABC"; "DEF"];
["ABC"; "DEF"; "G"; "H"]]
|> List.iter (fun list -> print_endline (quibble list))</syntaxhighlight>
{{works with|Core|v0.9.116.03+91}}
<syntaxhighlight lang="ocaml">open Core
let quibble = function
| [| |] -> "{}"
| [| a |] -> sprintf "{%s}" a
| array ->
let last, rest = Array.last array, Array.slice array 0 (-1) in
sprintf "{%s and %s}" (String.concat_array ~sep:", " rest) last
let test () =
[[||];
[|"ABC"|];
[|"ABC"; "DEF"|];
[|"ABC"; "DEF"; "G"; "H"|]]
|> List.iter ~f:(fun list -> print_endline (quibble list))</syntaxhighlight>
{{out}}
<pre># test ();;
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|Oforth}}==
<syntaxhighlight lang="oforth">: quibbing(l) -- string
| i s |
StringBuffer new "{" <<
Line 2,280 ⟶ 3,224:
i s == ifTrue: [ " and " << ]
]
"}" << dup freeze ; </
{{out}}
Line 2,288 ⟶ 3,232:
</pre>
=={{header|
<syntaxhighlight lang="scheme">
(define (quibble . args)
(display "{")
(let loop ((args args))
(unless (null? args) (begin
(display (car args))
(cond
((= 1 (length args)) #t)
((= 2 (length args))
(display " and "))
(else
(display ", ")))
(loop (cdr args)))))
(print "}"))
; testing =>
(quibble)
(quibble "ABC")
(quibble "ABC" "DEF")
(quibble "ABC" "DEF" "G" "H")
</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|PARI/GP}}==
<syntaxhighlight lang="parigp">comma(v)={
if(#v==0, return("{}"));
if(#v==1, return(Str("{"v[1]"}")));
Line 2,300 ⟶ 3,274:
comma(["ABC"])
comma(["ABC", "DEF"])
comma(["ABC", "DEF", "G", "H"])</
Output:
<pre>%1 = "{}"
Line 2,306 ⟶ 3,280:
%3 = "{ABC and DEF}"
%4 = "{ABC, DEF, G and H}"</pre>
<syntaxhighlight lang="pascal">
program CommaQuibbling;
uses
SysUtils,
Classes,
StrUtils;
const
OuterBracket =['[', ']'];
type
{$IFNDEF FPC}
SizeInt = LongInt;
{$ENDIF}
{ TCommaQuibble }
Line 2,325 ⟶ 3,310:
property CommaQuibble: string read GetCommaquibble write SetCommaQuibble;
end;
{$IFNDEF FPC} // Delphi support
function WordPosition(const N: Integer; const S: string; const WordDelims:
TSysCharSet): SizeInt;
var
PS, P, PE: PChar;
Count: Integer;
begin
Result := 0;
Count := 0;
PS := PChar(pointer(S));
PE := PS + Length(S);
P := PS;
while (P < PE) and (Count <> N) do
begin
while (P < PE) and (P^ in WordDelims) do
inc(P);
if (P < PE) then
inc(Count);
if (Count <> N) then
while (P < PE) and not (P^ in WordDelims) do
inc(P)
else
Result := (P - PS) + 1;
end;
end;
function ExtractWordPos(N: Integer; const S: string; const WordDelims:
TSysCharSet; out Pos: Integer): string;
var
i, j, l: SizeInt;
begin
j := 0;
i := WordPosition(N, S, WordDelims);
if (i > High(Integer)) then
begin
Result := '';
Pos := -1;
Exit;
end;
Pos := i;
if (i <> 0) then
begin
j := i;
l := Length(S);
while (j <= l) and not (S[j] in WordDelims) do
inc(j);
end;
SetLength(Result, j - i);
if ((j - i) > 0) then
Result := copy(S, i, j - i);
end;
function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet):
string; inline;
var
i: SizeInt;
begin
Result := ExtractWordPos(N, S, WordDelims, i);
end;
{$ENDIF}
{ TCommaQuibble }
Line 2,330 ⟶ 3,377:
procedure TCommaQuibble.SetCommaQuibble(AValue: string);
begin
AValue := ExtractWord(1, AValue, OuterBracket);
commatext :=
end;
function TCommaQuibble.GetCommaquibble: string;
var
Del: string;
begin
result := '';
Del := ', ';
for x := 0 to Count - 1 do
begin
result
if x = Count - 2 then
else if x = Count - 1 then
Del := '';
result := result + Del;
end;
result := '{' + result + '}';
end;
const
TestData: array[0..7] of string = ('[]',
'["ABC", "DEF", "G", "H"]', '', '"ABC"', '"ABC",
var
Quibble: TCommaQuibble;
TestString: string;
begin
Quibble := TCommaQuibble.Create;
for TestString in TestData do
begin
Quibble.CommaQuibble := TestString;
writeln(Quibble.CommaQuibble);
end;
end.</syntaxhighlight>
Output:
<Pre>
Line 2,385 ⟶ 3,430:
=={{header|Perl}}==
{{trans|
<
return "{$_}" for
@_ < 2 ? "@_" :
Line 2,393 ⟶ 3,438:
print comma_quibbling(@$_), "\n" for
[], [qw(ABC)], [qw(ABC DEF)], [qw(ABC DEF G H)];</
{{out}}
<pre>{}
Line 2,402 ⟶ 3,447:
'''Perl 5.01 version and other approach:'''
<
sub comma_quibbling {
my $last = pop // '';
return '{'. (@_ ? (join ', ', @_).' and '.$last : $last).'}';
Line 2,409 ⟶ 3,454:
say for map {comma_quibbling(@$_)}
[], [qw(ABC)], [qw(ABC DEF)], [qw(ABC DEF G H)];</
{{out}}
<pre>{}
Line 2,430 ⟶ 3,462:
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">quibble</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)>=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">words</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">words</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]&</span><span style="color: #008000;">" and "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">words</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #008000;">"{"</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">,</span><span style="color: #008000;">", "</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">"}"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"ABC"
<span style="color: #0000FF;">{</span><span style="color: #008000;">"ABC"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"DEF"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"ABC"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"DEF"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"G"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"H"</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">quibble</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,454 ⟶ 3,488:
=={{header|PHP}}==
<syntaxhighlight lang="php"><?php
function quibble($arr) {
case 0:
return '{}';
case 1:
return
default:
$left = implode(', ', array_slice($arr, 0, -1));
return "{{$left} and {$right}}";
}
}
Line 2,483 ⟶ 3,519:
foreach ($tests as $test) {
echo quibble($test) . PHP_EOL;
}
?></syntaxhighlight>
{{out}}
<pre>{}
Line 2,491 ⟶ 3,528:
=={{header|PicoLisp}}==
<
(let H (head -1 L)
(prinl
Line 2,498 ⟶ 3,535:
(and H " and ")
(last L)
"}" ) ) )</
Output:
<pre>{}
Line 2,504 ⟶ 3,541:
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|PL/I}}==
<
quib: Proc Options(main);
/*********************************************************************
Line 2,552 ⟶ 3,588:
Return('{'!!result!!'}');
End;
End;</
{{out}}
<pre>
Line 2,559 ⟶ 3,595:
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|PL/M}}==
<syntaxhighlight lang="plm">100H:
/* COPY A STRING (MINUS TERMINATOR), RETURNS LENGTH (MINUS TERMINATOR) */
COPY$STR: PROCEDURE(SRC, DST) ADDRESS;
DECLARE (SRC, DST) ADDRESS;
DECLARE (SCH BASED SRC, DCH BASED DST) BYTE;
DECLARE L ADDRESS;
L = 0;
DO WHILE SCH <> '$';
DCH = SCH;
SRC = SRC + 1;
DST = DST + 1;
L = L + 1;
END;
RETURN L;
END COPY$STR;
/* QUIBBLE GIVEN ARRAY OF $-TERMINATED STRINGS, STORE RESULT IN BUFR */
QUIBBLE: PROCEDURE(WORDS, BUFR) ADDRESS;
DECLARE (WORDS, BUFR, ADR) ADDRESS;
DECLARE (WORD BASED WORDS, WPTR) ADDRESS;
DECLARE (WCHAR BASED WPTR, BCHAR BASED BUFR) BYTE;
/* BRACES AND LOWERCASE LETTERS ARE NOT WITHIN PL/M CHARSET */
DECLARE LBRACE LITERALLY '123', RBRACE LITERALLY '125';
DECLARE ANDSTR DATA (32,97,110,100,32,'$');
ADR = BUFR;
BCHAR = LBRACE;
BUFR = BUFR + 1;
DO WHILE WORD <> 0;
BUFR = BUFR + COPY$STR(WORD, BUFR);
WORDS = WORDS + 2;
IF WORD <> 0 THEN
IF WORD(1) <> 0 THEN
BUFR = BUFR + COPY$STR(.', $', BUFR);
ELSE
BUFR = BUFR + COPY$STR(.ANDSTR, BUFR);
END;
BCHAR = RBRACE;
BUFR = BUFR + 1;
BCHAR = '$';
RETURN ADR;
END QUIBBLE;
/* --- CP/M OUTPUT AND TESTING --- */
BDOS: PROCEDURE(FUNC, ARG); /* MAKE CP/M SYSTEM CALL */
DECLARE FUNC BYTE, ARG ADDRESS;
GO TO 5;
END BDOS;
DECLARE BDOS$EXIT LITERALLY '0', /* EXIT TO CP/M */
BDOS$PUTS LITERALLY '9'; /* PRINT STRING */
PUTS: PROCEDURE(S);
DECLARE S ADDRESS;
CALL BDOS(BDOS$PUTS, S);
CALL BDOS(BDOS$PUTS, .(13,10,'$'));
END PUTS;
/* ARRAY WITH INITIALLY NO CONTENTS */
DECLARE ARR (5) ADDRESS INITIAL (0,0,0,0,0);
CALL PUTS(QUIBBLE(.ARR, .MEMORY)); /* NO STRINGS */
ARR(0) = .'ABC$';
CALL PUTS(QUIBBLE(.ARR, .MEMORY)); /* ABC */
ARR(1) = .'DEF$';
CALL PUTS(QUIBBLE(.ARR, .MEMORY)); /* ABC AND DEF */
ARR(2) = .'G$';
ARR(3) = .'H$';
CALL PUTS(QUIBBLE(.ARR, .MEMORY)); /* ABC, DEF, G AND H */
CALL BDOS(BDOS$EXIT, 0);
EOF</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Plain English}}==
<syntaxhighlight lang="plainenglish">To quibble four words:
Add "ABC" to some string things.
Add "DEF" to the string things.
Add "G" to the string things.
Add "H" to the string things.
Quibble the string things.
To quibble one word:
Add "ABC" to some string things.
Quibble the string things.
To quibble some string things:
Quibble the string things giving a string.
Destroy the string things.
Write the string on the console.
To quibble some string things giving a string:
Append "{" to the string.
Put the string things' count into a count.
If the count is 0, append "}" to the string; exit.
Get a string thing from the string things.
If the count is 1, append the string thing's string then "}" to the string; exit.
Loop.
If a counter is past the count minus 2, append the string thing's string then " and " then the string thing's next's string then "}" to the string; exit.
Append the string thing's string then ", " to the string.
Put the string thing's next into the string thing.
Repeat.
To quibble two words:
Add "ABC" to some string things.
Add "DEF" to the string things.
Quibble the string things.
To quibble zero words:
Quibble some string things.
To run:
Start up.
Quibble zero words.
Quibble one word.
Quibble two words.
Quibble four words.
Wait for the escape key.
Shut down.</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
function Out-Quibble
{
Line 2,604 ⟶ 3,775:
"{" + $outStr -f $text + "}"
}
</syntaxhighlight>
<syntaxhighlight lang="powershell">
Out-Quibble
Out-Quibble "ABC"
Out-Quibble "ABC", "DEF"
Out-Quibble "ABC", "DEF", "G", "H"
</syntaxhighlight>
{{Out}}
<pre>
Line 2,619 ⟶ 3,790:
</pre>
What it might look like when working with a file:
<syntaxhighlight lang="powershell">
$file = @'
Line 2,631 ⟶ 3,802:
Out-Quibble -Text ($line -split ", ")
}
</syntaxhighlight>
{{Out}}
<pre>
Line 2,641 ⟶ 3,812:
=={{header|Prolog}}==
{{works with|SWI-Prolog|7.1}}
<
words_serialized(Words, Serialized),
atomics_to_string(["{",Serialized,"}"], Bracketed).
Line 2,661 ⟶ 3,831:
( words_series(Words, Series),
format('~w ~15|=> ~w~n', [Words, Series]))
).</
{{Out}}
<
[] => {}
[ABC] => {ABC}
[ABC,DEF] => {ABC and DEF}
[ABC,DEF,G,H] => {ABC, DEF, G and H}
true.</
=={{header|PureBasic}}==
<syntaxhighlight lang="purebasic">
EnableExplicit
Line 2,707 ⟶ 3,877:
CloseConsole()
EndIf
</syntaxhighlight>
{{out}}
Line 2,722 ⟶ 3,892:
hence the replace is done on the reverse of the intermediate string
then reversed back.
<
return '{%s}' % ', '.join(sequence)[::-1].replace(',', 'dna ', 1)[::-1]
Line 2,733 ⟶ 3,903:
Input: ['ABC', 'DEF'] -> Output: '{ABC and DEF}'
Input: ['ABC', 'DEF', 'G', 'H'] -> Output: '{ABC, DEF, G and H}'
>>> </
===Python: Counted replacement===
Line 2,739 ⟶ 3,909:
replace() will replace nothing if the count of items to replace is zero, (and negative integer counts act to replace all occurrences).
This combines with the length of the input sequence to allow this to work:
<
return '{%s}' % ' and '.join(s).replace(' and ', ', ', len(s) - 2)
for seq in ([], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"]):
print('Input: %-24r -> Output: %r' % (seq, commaQuibble(seq)))</
{{out}}
Line 2,752 ⟶ 3,922:
===Python: Functional===
<
return ('{' +
(', '.join(s[:-1]) + ' and ' if len(s) > 1 else '') +
Line 2,766 ⟶ 3,936:
Input: ['ABC', 'DEF'] -> Output: '{ABC and DEF}'
Input: ['ABC', 'DEF', 'G', 'H'] -> Output: '{ABC, DEF, G and H}'
>>> </
=={{header|Quackery}}==
<syntaxhighlight lang="quackery">[ swap join join ] is glue ( [ [ [ --> [ )
[ [ dup size
dup 0 = iff
[ 2drop [] ] done
dup 1 = iff
[ drop unpack ] done
2 = iff
[ unpack $ ' and ' glue ] done
behead swap recurse $ ', ' glue ]
$ '{' swap join $ '}' join ] is quibble ( [ --> $ )
[] quibble echo$ cr
$ 'ABC' nest$ quibble echo$ cr
$ 'ABC DEF' nest$ quibble echo$ cr
$ 'ABC DEF G H' nest$ quibble echo$</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|R}}==
<syntaxhighlight lang="rsplus">quib <- function(vect)
{
#The task does not consider empty strings to be words, so we remove them immediately.
#We could also remove non-upper-case characters, but the tasks gives off the impression that the user will do that.
vect <- vect[nchar(vect) != 0]
len <- length(vect)
allButLastWord <- if(len >= 2) paste0(vect[seq_len(len - 1)], collapse = ", ") else ""
paste0("{", if(nchar(allButLastWord) == 0) vect else paste0(allButLastWord, " and ", vect[len]), "}")
}
quib(character(0)) #R has several types of empty string, e.g. character(0), "", and c("", "", "").
quib("")
quib(" ")
quib(c("", ""))
quib(rep("", 10))
quib("ABC")
quib(c("ABC", ""))
quib(c("ABC", "DEF"))
quib(c("ABC", "DEF", "G", "H"))
quib(c("ABC", "DEF", "G", "H", "I", "J", ""))</syntaxhighlight>
{{out}}
<pre>> quib(character(0))
[1] "{}"
> quib("")
[1] "{}"
> quib(" ")
[1] "{ }"
> quib(c("", ""))
[1] "{}"
> quib(rep("", 10))
[1] "{}"
> quib("ABC")
[1] "{ABC}"
> quib(c("ABC", ""))
[1] "{ABC}"
> quib(c("ABC", "DEF"))
[1] "{ABC and DEF}"
> quib(c("ABC", "DEF", "G", "H"))
[1] "{ABC, DEF, G and H}"
> quib(c("ABC", "DEF", "G", "H", "I", "J", ""))
[1] "{ABC, DEF, G, H, I and J}"</pre>
=={{header|Racket}}==
<
(define (sub-quibbling words)
(match words
Line 2,779 ⟶ 4,016:
(for ((input '([] ["ABC"] ["ABC" "DEF"] ["ABC" "DEF" "G" "H"])))
(printf "~s\t->\t~a~%" input (quibbling input)))</
{{out}}
<pre>() -> {}
Line 2,785 ⟶ 4,022:
("ABC" "DEF") -> {ABC and DEF}
("ABC" "DEF" "G" "H") -> {ABC, DEF, G and H}</pre>
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>sub comma-quibbling(@A) {
<{ }>.join: @A < 2 ?? @A !! "@A[0..*-2].join(', ') and @A[*-1]";
}
say comma-quibbling($_) for
[], [<ABC>], [<ABC DEF>], [<ABC DEF G H>];</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|REBOL}}==
===Straightforward implementation===
<
comma-quibbling: func [block] [
Line 2,806 ⟶ 4,057:
foreach t [[] [ABC] [ABC DEF] [ABC DEF G H]] [print comma-quibbling t]
</syntaxhighlight>
{{out}}
<pre>{}
Line 2,813 ⟶ 4,064:
{ABC, DEF, G and H}</pre>
===Alternative (more efficient) version with oxford comma switch===
<
; builds string instead of using an intermediate block
Line 2,837 ⟶ 4,088:
print "Now with Oxford comma"
foreach t test [print comma-quibbling/oxford t]
</syntaxhighlight>
{{out}}
<pre>{}
Line 2,848 ⟶ 4,099:
{ABC and DEF}
{ABC, DEF, G, and H}</pre>
=={{header|Refal}}==
<syntaxhighlight lang="refal">$ENTRY Go {
= <Prout <Quibble>>
<Prout <Quibble ('ABC')>>
<Prout <Quibble ('ABC') ('DEF')>>
<Prout <Quibble ('ABC') ('DEF') ('G') ('H')>>;
};
Quibble {
e.X = '{' <Quibble1 e.X> '}';
};
Quibble1 {
= ;
(e.Word) = e.Word;
(e.Word1) (e.Word2) = e.Word1 ' and ' e.Word2;
(e.Word) e.Words = e.Word ', ' <Quibble1 e.Words>;
};</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|REXX}}==
===version 1:===
<
say quibbling('ABC')
say quibbling('ABC DEF')
Line 2,865 ⟶ 4,140:
'and' word(list,words(list))
End
Return '{'result'}'</
{{out}}
<pre>
Line 2,874 ⟶ 4,149:
</pre>
===version 2:===
<
say quibbling('ABC')
say quibbling('ABC DEF')
Line 2,894 ⟶ 4,169:
result=result 'and' word.wn
End
Return '{'result'}'</
{{output}}
<pre>
Line 2,904 ⟶ 4,179:
===version 3:===
{{trans|NetRexx}}
<
i_ = 0
Line 2,927 ⟶ 4,202:
lst = overlay(' ', insert('and', lst, lc), lc)
lst = space(lst, 1) -- remove extra spaces
return '{'lst'}'</
{{out}}
<pre>
Line 2,937 ⟶ 4,212:
=={{header|Ring}}==
<
# Project : Comma Quibbling
text = list(4)
Line 2,982 ⟶ 4,254:
see str + nl
next
</syntaxhighlight>
Output:
<pre>
Line 2,989 ⟶ 4,261:
{ABC DEF}
{ABC, DEF, G and H}
</pre>
=={{header|RPL}}==
Whilst it is always important to ensure overall code clarity for maintenance by using explicit variable names and structured control flows, the spirit of reverse Polish notation programming is to optimize some key part of the algorithm in order to make it as compact - and possibly as fast - as possible, whatever the induced loss of readability. Here, two <code>IFTE</code> low-level instructions are nested to deliver the appropriate liaison substring between two words or before the first word.
{{works with|Halcyon Calc|4.2.7}}
≪ DUP SIZE → words n
≪ "{" 1
'''WHILE''' DUP n ≤ '''REPEAT'''
DUP 1 ≠ OVER n ≠ ", " " and " '''IFTE''' "" '''IFTE'''
ROT SWAP +
words 3 PICK GET +
SWAP 1 +
'''END'''
DROP "}" +
≫ ≫ 'CMAQBL' STO
{{in}}
<pre>
{ } CMAQBL
{ "ABC" } CMAQBL
{ "ABC", "DEF" } CMAQBL
{ "ABC", "DEF", "G", "H" } CMAQBL
</pre>
{{out}}
<pre>
4: "{}"
3: "{ABC}"
2: "{ABC and DEF}"
1: "{ABC, DEF, G and H}"
</pre>
=={{header|Ruby}}==
{{trans|
<
%w<{ }>.join(a.length < 2 ? a.first :
"#{a[0..-2].join(', ')} and #{a[-1]}")
Line 3,000 ⟶ 4,300:
[[], %w<ABC>, %w<ABC DEF>, %w<ABC DEF G H>].each do |a|
puts comma_quibbling(a)
end</
{{out}}
<pre>{}
Line 3,006 ⟶ 4,306:
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Run BASIC}}==
<
[""ABC""]
[""ABC"", ""DEF""]
Line 3,026 ⟶ 4,325:
next i
print a$
WEND</
{{out}}
<pre>[] ==> {}
Line 3,034 ⟶ 4,333:
=={{header|Rust}}==
<
fn quibble(seq: &[&str]) -> String {
match seq.len() {
Line 3,053 ⟶ 4,352:
println!("{}", quibble(&["ABC", "DEF", "G", "H"]));
}
</syntaxhighlight>
{{out}}
<pre>
Line 3,063 ⟶ 4,362:
=={{header|Scala}}==
<
case m if m.isEmpty => "{}"
case m if m.length < 3 => m.mkString("{", " and ", "}")
Line 3,075 ⟶ 4,374:
println( quibble( List("ABC","DEF") ) )
println( quibble( List("ABC","DEF","G","H") ) )
}</
{{out}}
<pre>{}
Line 3,083 ⟶ 4,382:
=={{header|Scheme}}==
<syntaxhighlight lang="scheme">
(define (quibble . args)
(display "{")
Line 3,100 ⟶ 4,398:
(quibble "ABC" "DEF")
(quibble "ABC" "DEF" "G" "H")
</syntaxhighlight>
{{out}}
Line 3,109 ⟶ 4,407:
{ABC, DEF, G and H}
</pre>
=={{header|Sed}}==
script-file:
<syntaxhighlight lang="sed">s/#.*$//g
y/[/{/
y/]/}/
s/"//g
s/ [A-Z][A-Z]*}/ and&/g
s/, and/ and/</syntaxhighlight>
test.txt:
<syntaxhighlight lang="text">[] # (No input words).
["ABC"]
["ABC", "DEF"]
["ABC", "DEF", "G", "H"]</syntaxhighlight>
sed -f script-file test.txt
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Seed7}}==
<
const func string: quibble (in array string: input) is func
Line 3,131 ⟶ 4,449:
writeln(quibble([] ("ABC", "DEF")));
writeln(quibble([] ("ABC", "DEF", "G", "H")));
end func;</
{{out}}
Line 3,140 ⟶ 4,458:
{ABC, DEF, G and H}
</pre>
=={{header|SenseTalk}}==
<syntaxhighlight lang="sensetalk">Quibble [] // (No input words).
Quibble ["ABC"]
Quibble ["ABC", "DEF"]
Quibble ["ABC", "DEF", "G", "H"]
to Quibble with wordList
if the number of items in wordList is ...
... 0 then put "{}"
... 1 then put "{" & item 1 of wordList & "}"
... else put "{" & (items first to penultimate of wordList) joined by ", " & " and " & the last item of wordlist & "}"
end if
end Quibble
</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|SETL}}==
<syntaxhighlight lang="setl">program comma_quibbling;
tests := [
[],
["ABC"],
["ABC","DEF"],
["ABC","DEF","G","H"]
];
loop for t in tests do
print(t, "=", quibble(t));
end loop;
proc quibble(words);
ret := '{';
loop while words /= [] do
word fromb words;
ret +:= word;
case of
(#words = 1):
ret +:= " and ";
(#words > 1):
ret +:= ", ";
end case;
end loop;
return ret + '}';
end proc;
end program;</syntaxhighlight>
{{out}}
<pre>[] = {}
[ABC] = {ABC}
[ABC DEF] = {ABC and DEF}
[ABC DEF G H] = {ABC, DEF, G and H}</pre>
=={{header|Sidef}}==
<
'{' + ([words.
}
[<>, <ABC>, <ABC DEF>, <ABC DEF G H>].each { |w|
say comma_quibbling(w)
}</
{{out}}
<pre>{}
Line 3,156 ⟶ 4,531:
=={{header|Standard ML}}==
<
fun quib [] = ""
| quib [x] = x
Line 3,170 ⟶ 4,545:
val t_quibble_2 = quibble ["ABC", "DEF"] = "{ABC and DEF}"
val t_quibble_3 = quibble ["ABC", "DEF", "G", "H"] = "{ABC, DEF, G and H}"
</syntaxhighlight>
=={{header|Swift}}==
<
func quibbling(var words:[String]) {
Line 3,194 ⟶ 4,570:
for word in inputs {
quibbling(word)
}</
{{out}}
<pre>
Line 3,203 ⟶ 4,579:
=={{header|Tcl}}==
<
return \{[join [lreplace $lst end-1 end [join [lrange $lst end-1 end] " and "]] ", "]\}
}
Line 3,209 ⟶ 4,585:
foreach input { {} {"ABC"} {"ABC" "DEF"} {"ABC" "DEF" "G" "H"} } {
puts [commaQuibble $input]
}</
{{out}}
<pre>
Line 3,219 ⟶ 4,595:
=={{header|TXR}}==
<syntaxhighlight lang="txrlisp">(defun quib (list)
(tree-bind (: last . lead) (reverse list)
`{@{(nreverse lead) ", "}@(if lead " and ")@last}`))</
=={{header|Uiua}}==
{{works with|Uiua|0.10.0-dev.1}}
<syntaxhighlight lang="Uiua">
Tests ← {{}
{"ABC"}
{"ABC" "DEF"}
{"ABC" "DEF" "G" "H"}}
Jam ← ◇⊂◇⊂:□
Quibble ← |1 ⟨""◌|°□⊢|Jam" and "°⊟|Quibble⊂⊃(□Jam", "°⊟↙2)(↘2)⟩↧3⧻.
Wrap ← ⊂⊂"{" : "}" Quibble
⍚(&pWrap) Tests
</syntaxhighlight>
=={{header|UNIX Shell}}==
{{works with|Bourne Again SHell}}
{{works with|Korn Shell}}
{{works with|Z Shell}}
<syntaxhighlight lang="bash">
quibble() {
printf '{'
shift
done
if (( $# )); then
printf '%s' "$1"
shift
fi
if (( $# )); then
printf ' and %s' "$1"
fi
printf '%s\n' '}'
}</syntaxhighlight>
With a slight modification, it will work in any POSIX shell, or even older Bourne-compatible shells as long as they have functions and <b>printf</b>:
<syntaxhighlight lang="sh">
quibble() {
printf '{'
while [ $# -gt 2 ]; do
printf '%s, ' "$1"
shift
done
if [ $# -gt 0 ]; then
printf '%s' "$1"
shift
fi
if [ $# -gt 0 ]; then
printf ' and %s' "$1"
fi
printf '%s\n' '}'
}</syntaxhighlight>
Going the other way, Zsh-specific code can be more compact:
{{works with|Z Shell}}
<syntaxhighlight lang="zsh">quibble() {
printf '{'
if (( $# > 1 )) printf '%s and ' ${(j:, :)@[1,-2]}
printf '%s}\n' $@[-1]
}</syntaxhighlight>
The test code is the same either way:
<syntaxhighlight lang="sh">
quibble
quibble ABC
quibble ABC DEF
quibble ABC DEF G H</
{{out}}
<pre>{}
Line 3,246 ⟶ 4,674:
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|VBA}}==
<syntaxhighlight lang="vb">Option Explicit
Sub Main()
Debug.Print Quibbling("")
Debug.Print Quibbling("ABC")
Debug.Print Quibbling("ABC, DEF")
Debug.Print Quibbling("ABC, DEF, G, H")
Debug.Print Quibbling("ABC, DEF, G, H, IJKLM, NO, PQRSTUV")
End Sub
Private Function Quibbling(MyString As String) As String
Dim s As String, n As Integer
s = "{" & MyString & "}": n = InStrRev(s, ",")
If n > 0 Then s = Left(s, n - 1) & " and " & Right(s, Len(s) - (n + 1))
Quibbling = s
End Function</syntaxhighlight>
{{out}}
<pre>{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
{ABC, DEF, G, H, IJKLM, NO and PQRSTUV}</pre>
=={{header|VBScript}}==
<
arr = Split(s,",")
If s = "" Then
Line 3,274 ⟶ 4,726:
WScript.StdOut.WriteLine
WScript.StdOut.Write Quibble("ABC,DEF,G,H")
WScript.StdOut.WriteLine</
{{out}}
<pre>{}
Line 3,280 ⟶ 4,732:
{ABC and DEF}
{ABC, DEF, G and H}</pre>
=={{header|Visual Basic .NET}}==
FormatEnumerable() accepts an IEnumerable(Of String), as per Lippert's original specification. FormatArray() contains an alternative implementation for String().
<syntaxhighlight lang="vbnet">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
</syntaxhighlight>
{{out}}
<pre>{}
{}
{ABC}
{ABC}
{ABC and DEF}
{ABC and DEF}
{ABC, DEF, G and H}
{ABC, DEF, G and H}</pre>
=={{header|V (Vlang)}}==
{{trans|go}}
<syntaxhighlight lang="v (vlang)">fn q(s []string) string {
match s.len {
0 {
return '{}'
}
1 {
return '{${s[0]}}'
}
2 {
return '{${s[0]} and ${s[1]}}'
}
else{
return '{${s[0..s.len-1].join(', ')} and ${s[s.len-1]}}'
}
}
}
fn main(){
println(q([]))
println(q(['ABC']))
println(q(['ABC','DEF']))
println(q(['ABC','DEF','G','H']))
}</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|Wren}}==
<syntaxhighlight lang="wren">var quibbling = Fn.new { |w|
var c = w.count
if (c == 0) return "{}"
if (c == 1) return "{%(w[0])}"
if (c == 2) return "{%(w[0]) and %(w[1])}"
return "{%(w[0..-2].join(", ")) and %(w[-1])}"
}
var words = [ [], ["ABC"], ["ABC", "DEF"], ["ABC", "DEF", "G", "H"] ]
for (w in words) System.print(quibbling.call(w))</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF, G and H}
</pre>
=={{header|XBS}}==
<syntaxhighlight lang="text">func task(a:array){
set x:string="";
foreach(k,v as a){
set out:string="";
if ((k==(?a-2))&((?a)>1)){out=" and "}elif(k!=(?a-1)){out=", "}
x+=v+out;del out;
}
send "{"+x+"}";
}
log(task([]));
log(task(["ABC"]));
log(task(["ABC","DEF"]));
log(task(["ABC","DEF","GHI"]));</syntaxhighlight>
{{out}}
<pre>
{}
{ABC}
{ABC and DEF}
{ABC, DEF and GHI}
</pre>
=={{header|XLISP}}==
I like the Oxford comma; but specifications are specifications. So this implementation produces the required output by default. It also, however, allows an optional <tt>OXFORD-COMMA</tt> parameter: pass a true value, and you won't find yourself saying things like "I want to thank my parents, Ayn Rand and God".
<
(define final
(if (and (caddr inputs) oxford-comma)
Line 3,311 ⟶ 4,895:
(print (quibble '("ABC") t))
(print (quibble '("ABC" "DEF") t))
(print (quibble '("ABC" "DEF" "G" "H") t))</
{{out}}
<pre>"{}"
Line 3,324 ⟶ 4,908:
=={{header|XPL0}}==
<
proc Quibble(N, S);
Line 3,341 ⟶ 4,925:
for I:= 0 to 4 do
if I#3 then [Quibble(I, ["ABC", "DEF", "G", "H"]); CrLf(0)]
</syntaxhighlight>
{{out}}
Line 3,353 ⟶ 4,937:
=={{header|zkl}}==
This is a cheese ball solution that replies on no commas in the inputs
<
if(list.len()<2) text;
else{
Line 3,359 ⟶ 4,943:
String(text[0,z]," and ",text[z+2,*])
}
}</
List.toString("*") converts List(1,2,3) to "L(1,2,3)" with all elements; without the *, long lists are shortened to L(1,2,3,...)
{{out}}
Line 3,370 ⟶ 4,954:
=={{header|ZX Spectrum Basic}}==
<
20 DATA 1,"ABC"
30 DATA 2,"ABC","DEF"
Line 3,389 ⟶ 4,973:
1090 NEXT i
1100 PRINT "{";s$;"}"
1110 RETURN</
|