# How to limit only two “0 and 1” strings for an xor implement?

I tried to implement some logic gates for a series of "0 & 1" strings, just like and, or, nand, nor and not listed below. How could I limit xor only accept a two strings list as its argument?

str2 = {"11000000", "10000001", "11111111"};

or[str : {__String}] :=
StringJoin[
Characters[str] /. {"0" -> False, "1" -> True}] /. {False -> "0", True -> "1"}];

and[str : {__String}] :=
StringJoin[
Characters[str] /. {"0" -> False, "1" -> True}] /. {False -> "0", True -> "1"}];

nand[str : {__String}] :=
not[StringJoin[
Characters[str] /. {"0" -> False, "1" -> True}] /. {False -> "0", True -> "1"}]];

nor[str : {__String}] :=
not[StringJoin[
Characters[str] /. {"0" -> False, "1" -> True}] /. {False -> "0", True -> "1"}]];

not[str : _String ] :=
StringJoin[
Characters[str] /. {"1" -> False, "0" -> True}  /. {False -> "0", True -> "1"}];

(* ????? *)
xor[str : {_String, _String}] :=
StringJoin[
Characters[str] /. {"0" -> False, "1" -> True}] /. {False -> "0", True -> "1"}];


-
I'm having trouble following. Could you provide an example of your desired input/output? – mfvonh Jul 19 '14 at 21:37
I suppose xor should only take two strings for its xor operation, as I used the {_string,_string} pattern to control the argument. The example above showed that it took str2(a three string list) as its argument with no sign of error and gave a wrong result! – Putterboy Jul 19 '14 at 21:59
@user16069 Have you tried restarting your kernel? You could have some old definition lingering that accepts more than two strings. The current definition looks right to me. – C. E. Jul 19 '14 at 22:28
@Pickett You are right. Everything becomes normal after quitting MM and back again. – Putterboy Jul 20 '14 at 3:28

I think it would be simpler to implement the logic directly, with fewer transformations:

str2={"11000000","10000001","11111111"};

not=StringReplace[#,{"1"->"0","0"->"1"}]&;
not@str2[[1]]


"00111111"

or=do[!FreeQ[{##},"1"]&];
or@str2


"11111111"

and=do[FreeQ[{##},"0"]&];
and@str2


"10000000"

nand=do[!FreeQ[{##},"0"]&];
nand@str2


"01111111"

nor=do[FreeQ[{##},"1"]&];
nor@str2


"00000000"

xor=do[Count[{##},"1"]==1&];
xor@str2


"00111110"

-

Perhaps

xor[ab : {a_String /; StringFreeQ[a, Except["0" | "1"]],
b_String /; StringFreeQ[b, Except["0" | "1"]]}] :=
StringJoin[
MapThread[Xor, Characters[ab] /. {"0" -> False, "1" -> True}] /.
{False -> "0", True -> "1"}]


Since xor is limited to two strings in the list it will be convenient to support this form:

xor[a_String, b_String] := xor[{a, b}]


Some tests:

a = "1100"; b = "1010"; c = "1111"; d = "105a";
xor[{a, b}]

"0110"

xor[{a, b, c}]

xor[{"1100", "1010", "1111"}]

xor[a, b]

"0110"

xor[a, d]

xor[{"1100", "105a"}]

-

Here's a bitwise approach, using a two-argument definition like @m_goldberg:

xor[str1_String, str2_String] :=
IntegerString[
BitXor[FromDigits[str1, 2], FromDigits[str2, 2]],
2,
StringLength[str1]];


The other functions could be implemented with bitwise operators, too.

-
@Karsten7. I didn't notice your deleted answer until now. If you'll undelete, I delete mine. I think it's worth showing the bitwise approach (obviously, since I did). – Michael E2 Jul 20 '14 at 1:04