28
\$\begingroup\$

a XAND b

a AND b, but not at the same time.


I've always found the idea of an XAND gate amusing.

Many would claim such a gate can not exist, but I suspect they're just not trying hard enough.


Popularity Contest

You simply need to demonstrate an XAND gate.

The rules are simple:

  1. Create two identifiers a and b
  2. They do not have to be primitives but can be anything [eg variables, functions, macros, constants, types, etc].
  3. They must both be truthy by themselves [eg if (a)]
  4. They must fail to be truthy together [eg if (a && b)]
  5. Once rules 3 & 4 are achieved, they must continue to hold true throughout the duration of your program. [Explained in detail at the end].

The most straight-forward way to demonstrate this would be to simply use three conditionals:

if (a) {
   print("a");
}

if (b) {
   print("b");
}

if (!(a&&b)) {
   print("but not at the same time");
}

However, this is a popularity contest, so it's actually up to you how you wish to demonstrate it, and up to voters to determine how valid your XAND is.

I use && in the code above, but you are allowed to get creative in demonstrating the "but not at the same time" nature of your gate; so, you are not limited to using a strict a&&b conditional, per se (voters will determine validity).


Rule 5 Explained:

It must remain true in your code that:
a is truthy
b is truthy
a AND b is not truthy

These conditions must remain true no matter how many times you'd demonstrate these conditions or what order you'd demonstrate them in.

So you can not just have a value that simply changes after it's read the first time so that the second time you make the comparison it is no longer truthy.

Perhaps this is more easily explained with pseudocode:

while (1)
    i = random%3;
    switch(i):
        case 0:
            if (a) //This must always be true
        case 1:
            if (b) //This must always be true
        case 2:
            if (a AND b) //This must always be false

And again, this is a popularity contest, so you do not have to strictly demonstrate this in any particular way...

You just need to demonstrate to your audience the XAND nature of your gate. You are not necessarily forced to explicitly use && for example.

You just need to demonstrate in a clear way "a AND b, but not at the same time"

...so get creative XAND have fun!

\$\endgroup\$
8
  • 12
    \$\begingroup\$ I think this is one of the good examples of a modern pop-con challenge, tbh. The spec is rigorous about what answers must do and must not do and voters can easily tell if an answer is or isn't valid, but it also doesn't shoehorn answers into either all being the same or all trying to find "workarounds" to stand out \$\endgroup\$ Commented Oct 19 at 23:45
  • 1
    \$\begingroup\$ This feels like an underhanded challenge, which used to be allowed. But I'm not sure about that. \$\endgroup\$ Commented Oct 20 at 9:37
  • 1
    \$\begingroup\$ @Fmbalbuena we recently held a discussion about this exact topic. consensus is either that underhanded is fully rehabilitated, or that it is "banned" to discourage it but allowed on a case-by-case basis when it is clear the challenge is good. \$\endgroup\$ Commented Oct 20 at 15:13
  • 14
    \$\begingroup\$ Just to be clear, we need to be 'Creative' and 'Have Fun', but not simultaneously? \$\endgroup\$ Commented Oct 20 at 15:35
  • 2
    \$\begingroup\$ @Sidney If I'm understanding correctly, the challenge doesn't actually involve anything called a "XAND gate." The idea of a XAND gate is mentioned as part of the theme, but isn't actually part of the challenge. \$\endgroup\$ Commented Oct 21 at 13:48

25 Answers 25

30
\$\begingroup\$

Python 3

def fuzzy_and(x, y):
	return x*y

a = 0.7
b = 0.7

if round(a):
	print("a is truthy (probably)")
else:
	print("a is not truthy (probably)")


if round(b):
	print("b is truthy (probably)")
else:
	print("b is not truthy (probably)")


if round(fuzzy_and(a, b)):
	print("a & b is truthy (probably)")
else:
	print("a & b is not truthy (probably)")

Try it online!

Nobody said you coudn't use fuzzy/probabalistic logic!

Basically, a is more likely to be true than not, same with b, but a & b is more likely to be false than true.

\$\endgroup\$
2
  • 4
    \$\begingroup\$ This is the only one that gets my upvote, since it seems most in the spirit of the concept of an XAND gate :) \$\endgroup\$ Commented Oct 20 at 12:39
  • 4
    \$\begingroup\$ this is similar to how 1 + 1 can be = 3 or = 1 for sufficiently large or small values of 1 ;) \$\endgroup\$ Commented Oct 21 at 7:07
26
\$\begingroup\$

Python

a = 1
b = 2

if a: print("a is truthy")
if b: print("b is truthy")
if a & b: print("a and b are both truthy")

Try it online!

In Python, & does "bitwise and" as opposed to logical and. So, 1&2==0 since these numbers share no set bits. All numbers but 0 are truthy, so 1 and 2 each satisfy an if, but 0 does not.

We could also have a and b be disjoint sets, on which & does set intersection.

\$\endgroup\$
1
  • 20
    \$\begingroup\$ fitting username(: \$\endgroup\$ Commented Oct 19 at 23:13
21
\$\begingroup\$

C (GCC)

#include <stdio.h>
#define if(x) if(!x ^ 1)

int main() {
  int a = 1;
  int b = 1;
  if (a) puts("a is true");
  if (b) puts("b is true");
  if (a && b) puts("a && b is true");
}

Attempt This Online!

\$\endgroup\$
1
  • \$\begingroup\$ That's evil! I like. \$\endgroup\$ Commented Oct 20 at 7:49
20
\$\begingroup\$

JavaScript

let a = new Boolean();
let b = new Boolean();
if (a) console.log("a is truthy");
if (b) console.log("b is truthy");
if (a & b) console.log("a & b is truthy");

Try it online!

\$\endgroup\$
18
\$\begingroup\$

C++ (GCC -O0)

#include <cstdlib>
#include <cstdint>
#include <iostream>

void *aCaller = NULL;
bool a()
{
    aCaller = __builtin_extract_return_addr(__builtin_return_address(0));
    return true;
}
bool b()
{
    void *bCaller = __builtin_extract_return_addr(__builtin_return_address(0));
    return abs(((char*)bCaller - (char*)aCaller)) > 9;
}

int main()
{
    if (a()) std::cout << "a is true" << std::endl;
    if (b()) std::cout << "b is true" << std::endl;
    if (a() && b()) std::cout << "a && b is true" << std::endl;
    return 0;
}

Attempt This Online!

As of submission, this is the only solution so far that doesn't use a different/redefined AND or operator precedence tricks, but rather uses a straight-up logical AND.

The trick is that a() and b() are functions, the latter of which returns false if it's been called very close after a() was last called. As such it's probably not very portable, and if it is, at the very least the threshold of 9 bytes may need to be modified to work on different architectures.

\$\endgroup\$
7
  • \$\begingroup\$ Does this meet the requirement that the condition "must continue to hold true throughout the duration of your program"? In particular, the explanation that "you can not just have a value that simply changes after it's read the first time so that the second time you make the comparison it is no longer truthy." \$\endgroup\$ Commented Oct 21 at 0:43
  • \$\begingroup\$ @ChrisBouchard As long as you don't call a() or b() bare (as a lone statement without using its value), it should be hard or impossible to get b() to return a different value when called from the same point in the program. I invite you to try. \$\endgroup\$ Commented Oct 21 at 2:17
  • 2
    \$\begingroup\$ I tried to make this more robust so it could be compiled with optimization enabled. __attribute__((noinline,noipa)) on both a and b gets it to print a is true a && b is true. godbolt.org/z/G8ebdf5Mz shows the asm from g++ -O2 for x86-64. The first two if statements compile with jumps to blocks at the bottom of the function which then jump back, so the callsites are very close. a() && b() compiles with the two callsites far apart. godbolt.org/z/nnGsGrc5G shows using [[likely]] to override the branch layout, and bumps up the threshold to 16 bytes to "fix" it. \$\endgroup\$ Commented Oct 21 at 19:39
  • \$\begingroup\$ @PeterCordes Nicely done! I didn't know about the [[likely]] annotation. But it seems to work even without that. \$\endgroup\$ Commented Oct 21 at 20:00
  • 1
    \$\begingroup\$ Without the noipa attribute, GCC can see that a unconditionally returns true, which has a similar effect to [[likely]] on that block (or __builtin_expect(!!a(), 1) like Linux likely(a()) macros), but without even doing a conditional branch on the return value, just calling it (because noinline) and then printing. And in the short-circuit code, call a is directly followed by call b. With noipa like I used, or with the definition in a different file and no LTO, it assumes that printing is unlikely and puts that block out of line at the bottom of the function after the ret. \$\endgroup\$ Commented Oct 21 at 20:25
12
\$\begingroup\$

Python 3.13

import inspect
import ast

and_detected = False
class Visitor(ast.NodeVisitor):
    global and_detected
    def visit_BoolOp(self, node):
        global and_detected
        if isinstance(node.op, ast.And):
            and_detected = True

        
class _:
    @property
    def a(self) -> bool:
        line = inspect.stack()[1].code_context[0]
        Visitor().visit(ast.parse(line))
        return not and_detected
    @property
    def b(self) -> bool:
        return True

print(f"a: { _().a}, b: {_().b}")
print(f"and: {_().a and _().b}")
print(f"or: {_().a or _().b}")
$ python3 main.py
a: True, b: True
and: False
or: True

The idea here is _().a (and _().b) are properties of the class _, so they're just functions internally. The function for b is easy, it just returns True.

However, for a, it gets the text of the current line and parses it to see if it contains any ands. If so, it returns False to make this work.

It's not perfect, as something like print(f"a: { _().a}, b: {_().b} / {_().a and _().b}") would not work correctly. But, it does work when each test is a unique line.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ As a note, this fails if you actually use an if (as anything other than a one-liner) as ast.parse("if _().a:") will fail because, without an indented line following, it's syntactically invalid. \$\endgroup\$ Commented Oct 21 at 14:42
10
\$\begingroup\$

C (portable)

This solution uses macro expansion to subvert the otherwise normal test code. && comes before %= in the precedence rules, so a,b can both equal 1 while a&&b evaluates to 0 because 3 % 1 is 0.

#include <stdio.h>

#define a x=3,x%=2
#define b 1

int main(int argc, char ** argv) {
  int x;
  if (a) printf("a is truthy,\n");
  if (b) printf("b is truthy,\n");
  if (!(a && b)) printf("but a&&b is not.\n");
}

Try it online!

Edit:

The original version does have the drawback that b&&a generates a compiler error (which still "fails to be truthy" per the question). Thanks to a clever optimization by Albert Renshaw, here is an improved version:

#include <stdio.h>

#define a (x=3),x%=2
#define b (x=5),x%=2

int main(int argc, char ** argv) {
  int x;
  if (a) printf("a is truthy,\n");
  if (b) printf("b is truthy,\n");
  if (!(a && b)) printf("but a&&b is not.\n");
  if (!(b && a)) printf("And now b&&a is not!\n");
}

Try it online!

This change adds a few new ideas. We assign values to x multiple times within the macro, but luckily && and , are sequence points so the value is never undefined. Assignment operators can be chained, so the block 2&&(x=3) both assigns a value to x and passes that value into the logical comparison. Finally, x is modded a second time after being set to 0, but this will never change its value.

New contributor
test_account is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
4
  • \$\begingroup\$ I like this one a lot! I had a hunch some clever macro-variable solution would exist \$\endgroup\$ Commented 2 days ago
  • 1
    \$\begingroup\$ For this to compile properly in Try It Online I had to format the macro like this: (x=3),x%=2. If you use #define a (x=3),x%=2 and #define b (x=5),x%=2, you can have it work for a&&b and b&&a! \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ Thanks :) Macro solutions turn out to be rare because && has very low precedence. On the other hand, it is rather amusing that each step is required in the language standard. So, xand gates are a necessary facet of the design of the C language. \$\endgroup\$ Commented yesterday
  • \$\begingroup\$ Were you trying to set up b&&a when you added the parentheses to a? The code I posted works on tio, but swapping the arguments produces (1&&x)=3,x%=2, which is garbage. The parentheses convert this to 1&&(x=3),x%=2, which is shorthand for 1&&3,x=3,x%=2. \$\endgroup\$ Commented yesterday
7
\$\begingroup\$

R

The simplest way is to redefine && operator to always return FALSE:

`&&` <- \(x,y)FALSE

a = TRUE
b = TRUE

if(a) print('a')
if(b) print('b')
if(a && b) print('a&&b')

Attempt This Online!


The more convoluted way - && checks now if both arguments are TRUE - that's what and is after all?

`&&` = \(x,y)isTRUE(x) && isTRUE(y)

a = 1
b = 1

if(a) print('a')
if(b) print('b')
if(a && b) print('a&&b')

Attempt This Online!

The trick is that anything numerical nonzero is truthy, but isTRUE checks explicitly if input is logical TRUE.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ The second approach is explicitly forbidden in the challenge. \$\endgroup\$ Commented Oct 20 at 6:24
  • \$\begingroup\$ @Adamátor you're right. Changed. \$\endgroup\$ Commented Oct 20 at 19:14
6
\$\begingroup\$

Haskell, using GHCi

Technically I can do this by redefining how && works :)

ghci> (&&) True True = False
ghci> a = True
ghci> b = True
ghci> a
True
ghci> b
True
ghci> a && b
False

This is based on this answer which defines 2+2 to equal 5.

\$\endgroup\$
5
\$\begingroup\$

Python 3.9

import code
import dis
import sys

class Bool(int):
    __slots__ = ()
    _last_code = None
    _last_offset = None
    _last_target = None  # absolute

    def __bool__(self):
        frame = sys._getframe(1)
        ##code.interact(local = locals())  # enable for development
        insts = dis.get_instructions(frame.f_code)
        for inst in insts:
            if inst.offset == frame.f_lasti:
                break
        else:
            inst = None  # fallback
        if inst and inst.opname == 'JUMP_IF_FALSE_OR_POP':
            target = inst.argval
            result = False
        elif inst and inst.opname == 'JUMP_IF_TRUE_OR_POP':
            target = next(inst).offset
            result = True
        else:
            target = float('NaN')

        xand = (Bool._last_code is frame.f_code
            and Bool._last_offset != frame.f_lasti
            and Bool._last_target == target
        )
        Bool._last_code = frame.f_code
        Bool._last_offset = frame.f_lasti
        Bool._last_target = target
        if xand:
            return result
        return super().__bool__()

    def __repr__(self):
        return "TRUE" if self else "FALSE"

TRUE = Bool(1)
FALSE = Bool(0)
Bool.__new__ = lambda cls, x: TRUE if x else FALSE

Demonstration

>>> if TRUE:
...     print("Hello, world!")
...
Hello, world!
>>> if TRUE and TRUE:
...     print("Goodbye, world!")
...
>>> import random
>>> a = b = TRUE
>>> while TRUE:
...     i = random.randint(0, 2)
...     if i == 0 and a:
...         print("a")
...     elif i == 1 and b:
...         print("b")
...     elif i == 2 and not (a and b):
...         print("but not at the same time")
b
a
a
a
b
b
KeyboardInterrupt
>>>

Remarks

When writing Python code, it's important to adhere to PEP 8 – Style Guide for Python Code:

  • Class names should normally use the CapWords convention.

  • Constants are usually defined on a module level and written in all capital letters with underscores separating words.

This approach should work in everything from Python 3.1 to Python 3.10. It won't work in Python 3.11+, thanks to the compiler revamp, but they didn't re-use the opcode names so adding support should be easy enough. (Just take care not to mix up relative and absolute jump offsets.)

It needs JUMP_FORWARD support to handle if FALSE: pass else: ..., and JUMP_ABSOLUTE support to handle if at the end of while loops, but I grow tired of this program.

\$\endgroup\$
5
\$\begingroup\$

C#

Operator definitions, but not & or &&:

boolean a = true;
boolean b = true;
boolean a_and_b = a & b;

if (a) System.Console.WriteLine("a is true");
if (b) System.Console.WriteLine("b is true");
if (a_and_b)
  System.Console.WriteLine("a and b is true");
else
  System.Console.WriteLine("a and b is false");

// ideally, put this away in an innocuous file
public class boolean {
  private bool Value;
  public boolean(bool b)
  {
    Value = b;  
  }
  public boolean(int i)
  {
    Value = i != 0;
  }

  public static implicit operator int(boolean b) => b.Value ? 0 : 1;    
  public static implicit operator boolean(int i) => new boolean(i); 
  public static implicit operator boolean(bool b) => new boolean(b);
  public static bool operator true(boolean b) => b.Value;
  public static bool operator false(boolean b) => b.Value;
}

dotnet fiddle

Notes

  • Uses the operator allowing a class to have a truth value to separately evaluate a and b truth values.
  • a & b = false is accomplished via code in implicit type casts.
  • Had to use & and go through int instead of && because unfortunately order of operations has implicit conversion to bool as higher priority to the true/false operators.
  • I've used boolean to mimic the Java keyword (and probably others), but you could use Boolean and shadow System.Boolean to try to trick those more familiar with C#.
  • As a bonus, if a = false, b = false, then a & b = true, so two wrongs make a right.
  • I recommend this as a bug finding exercise for Java programmers being introduced to C# (if you don't like them).

A variant

Using similar implicit conversions, we can use the native && operator, but I like this solution less as I've not found a way to not declare the initial variables false (or use negation), resulting in immediately suspicious looking code:

boolean a = false;
boolean b = false;
boolean a_and_b = a && b;

if (a) System.Console.WriteLine("a is true");
if (b) System.Console.WriteLine("b is true");
if (a_and_b)
  System.Console.WriteLine("a and b is true");
else
  System.Console.WriteLine("a and b is false");

public struct boolean {
  private bool Value;
  public static implicit operator boolean(bool b) => new boolean { Value = b };
  public static implicit operator bool(boolean b) => !b.Value;
}

dotnet fiddle 2

\$\endgroup\$
4
\$\begingroup\$

C++ (portable)

Operator overloading (yes, && can be overloaded; this disables short-circuiting evaluation, but that's no problem here):

struct A{operator bool(){return 1;}};
bool operator&&(A,A){return 0;}

#include <print>
int main()
{
    A a,b;
    if (a) std::println("a is true");
    if (b) std::println("b is true");
    if (a&&b) std::println("a&&b is true");
    else std::println("a&&b is false");
}
\$\endgroup\$
4
\$\begingroup\$

05AB1E (legacy)

1 U
1 V

X i "X is truthy", }
Y i "Y is truthy", }
X Y && i "X and Y are both truthy", }

Try it online or try it online in reversed order of if-blocks.

Explanation:

Two things to note about 05AB1E itself:

  1. Only 1 (as well as "1", "01", etc.) is truthy in 05AB1E, everything else is falsey.
  2. 05AB1E uses Polish notation, hence why it's X Y && i as apposed to X && Y i in the final if-statement (in this second case of X && Y i, it would use the if-statement on the top of the stack Y instead, which is of course always 1/truthy).

Code explanation:

1U                # Push a 1; then pop and set variable `X` to this 1
1V                # Push a 1; then pop and set variable `Y` to this 1
Xi                # If `X` is 1:
  "X is truthy",  #  Output this string with trailing newline
 }                # Close the if-statement
Yi"Y is truthy",} # Likewise for `Y`
XY                # Push both `X` and `Y` to the stack
  &&i             # Pop both, and if both† are truthy:
     "X and Y are both truthy",
                  #  Output this string with trailing newline
    }             # Close the if-statement (for consistency, since it could have
                  # been omitted at the end of the program)

†: & is a bitwise-AND, so in this case the && are basically two bitwise-ANDs in a row. The first one will do X&Y, resulting in 1, but the second will do the & on this resulting 1 + nothing, since the stack is otherwise empty and there isn't any input, resulting in 0/falsey. Try it online with manual debug-lines.

Fun fact: in the new version of 05AB1E, instead of the legacy version, this would still have been truthy: try it online. This is because it'll use the first pushed value instead of nothing when there aren't any values left on the stack and there also isn't any input. So the second & will use this implicit 1 plus the resulting 1 of the earlier X&Y, still resulting in a 1/truthy. Try it online with manual debug-lines.

\$\endgroup\$
4
\$\begingroup\$

Silliness with objects that are True when evaluated once per line, and False when evaluated multiple times per line:

Python

import inspect

class Xand:
    _last_line = None
    _last_index = None

    def __bool__(self):
         frame = inspect.stack()[1].frame
         try:
             curline = frame.f_lineno
             curindex = frame.f_lasti
         finally:
            del frame
         cls = type(self)
         if cls._last_line == curline and cls._last_index != curindex:
             cls._last_line = cls._last_index = None
             return False
         cls._last_line = curline
         cls._last_index = curindex
         return True

Attempt This Online!

We overload truthiness testing for these objects to make them be considered True if they're evaluated on a different line from the last evaluation, or on the same line at the same bytecode index, and False if on the same line but at different bytecode indices. This isn't foolproof, thanks to parentheses and line-continuation characters, as:

if (a and
    b):
    print("Truthy")

and:

if a and\
   b:
    print("Truthy")

will both print. You could go to a lot more trouble to walk the bytecode forwards or backwards to check for an and occurring immediately before or after the truthiness test the same expression, but since and isn't directly represented in bytecode, this gets ugly quickly, and I'm okay with leaving complete coverage of multiline expressions as an exercise.

\$\endgroup\$
4
\$\begingroup\$

Bash / Zsh

ulimit -u 1
a () { true; }
b () { true; }

if a; then echo 1; fi
if b; then echo 2; fi
if a & b; then echo 3; fi

Attempt This Online!

The boolean AND operator in shell scripts is definitely &.

Actually, & runs the two commands concurrently (a in the background, b in the foreground). But with ulimit -u 1, the number of processes available is limited to 1, so a & b produces an error - errors mean "false" in shell languages. Amusingly, in Bash, when spawning another process with & fails, it retries with exponential backoff up to 5 times before finally erroring. Zsh returns immediately.

\$\endgroup\$
3
\$\begingroup\$

VBScript (Windows Script Host)

This intrigued me enough to dust off a language I haven't used in quite some time. I don't know of any online try-it-out sites for it, but if you're on a Windows installation that has VBScript installed (which most I think still do, but they're working on phasing that out), then you can copy this into xand.vbs, and run cscript xand.vbs to run it. It was inspired in part by xnor's Python answer, and basically works the same way, except that VBScript only has bitwise-and available, and one can do math on the default False (0) and True (-1) constants to obfuscate things a little.

a = True - 1
b = False + 1
If a Then WScript.Echo "a is true"
If b Then WScript.Echo "b is true"
If a And b Then WScript.Echo "a and b are both true"

Output:

>cscript xand.vbs
Microsoft (R) Windows Script Host Version 10.0
Copyright (C) Microsoft Corporation. All rights reserved.

a is true
b is true
\$\endgroup\$
1
3
\$\begingroup\$

JavaScript (Node.js), 240 bytes

a = 1e-200;
b = 1e-200;

if(a) console.log('a');
if(b) console.log('b');
// Yeah it's a thing to do logical and using `*` to save byte
// Apply to both js golf and some golfing languages(may have no `&&` at all)
if(a*b) console.log('BOOM');

Try it online!

\$\endgroup\$
3
\$\begingroup\$

TeX

No need for any definition. My "variables" are aa and bb. The following code prints True True False in the document.

\if aa True \else False \fi
\if bb True \else False \fi
\if {aa && bb} True \else False \fi
\bye

The way it works is that \if compares the next two tokens. In the third line these are { and a.

\$\endgroup\$
2
\$\begingroup\$

Nim

Overriding the built-in and:

proc `and`(x, y: bool): bool =
  false

let
  a = true
  b = true

if a:
  echo("a is true")
if b:
  echo("b is true")
if a and b:
  echo("a and b is true")

Attempt This Online!

Using a term-rewriting template:

template xand{`and`(x, y)}(x, y: bool): bool =
  false

let
  a = true
  b = true

if a:
  echo("a is true")
if b:
  echo("b is true")
if a and b:
  echo("a and b is true")

Attempt This Online!

Using a custom type:

type XandBool = enum
  xFalse
  xTrue

converter toBool(x: XandBool): bool =
  case x
  of xFalse: false
  of xTrue: true

proc `and`(x, y: XandBool): XandBool =
  xFalse

let
  a = xTrue
  b = xTrue

if a:
  echo("a is true")
if b:
  echo("b is true")
if a and b:
  echo("a and b is true")

Attempt This Online!

\$\endgroup\$
2
\$\begingroup\$

Wolfram Language (Mathematica)

Wolfram Language is very strict about If in that the only "truthy" value for it is True, so I doubt there's a very interesting answer unless we allow InterpretedTrueQ as a wrapper inside of If. So I just did this:

a=b=(Unprotect[And];And=Nand;True);

Try it online!

In Wolfram Language, an expression can be an entire block of code that just evaluates to what the last line does. So here both a and b can redefine And as Nand. So when && is used, it turns into And which turns into Nand and yields False for two true things like a and b.

\$\endgroup\$
3
  • \$\begingroup\$ a = True; b = True; a && b ^= False; Print[a]; Print[b]; Print[a && b]; (would work with If, but it's longer to demonstrate). If you want to golf that, maybe a&&b^=!(a=b=True)? \$\endgroup\$ Commented Oct 21 at 19:19
  • \$\begingroup\$ @BrunoLeFloch That seems like a different answer worth posting separately since you use a mechanism other than merely defining a and b. \$\endgroup\$ Commented Oct 22 at 1:06
  • \$\begingroup\$ Yes indeed it's quite different. Thinking about it, I'm giving an UpValue to a and you are globally redefining And. \$\endgroup\$ Commented Oct 22 at 14:51
1
\$\begingroup\$

If I read the spec correctly a "true" XAND should return False no matter what the input is.

Class C below implements that behaviour (and not much else):

Python, 26 bytes

class C:__and__=lambda*x:0

Attempt This Online!

\$\endgroup\$
1
\$\begingroup\$

Lua, 54 43 bytes

The one time the Lua submission is actually short!

…so yeah, it's another "just overload the operator" situation.

-11 bytes by Adamátor

a=setmetatable({},{__band=loadstring""})b=0
\$\endgroup\$
3
  • \$\begingroup\$ If you really want to golf it, -1 byte \$\endgroup\$ Commented Oct 20 at 18:54
  • \$\begingroup\$ In fact, -11 bytes \$\endgroup\$ Commented Oct 20 at 18:55
  • \$\begingroup\$ time to see if literally any of my other solutions used functions called with a single string argument \$\endgroup\$ Commented Oct 20 at 22:09
1
\$\begingroup\$

C++ (portable)

#include <iomanip>
#include <iostream>
         
struct XandValue
{
    bool x;                                                                                 static constexpr bool b[] = {1,0};
    operator bool() const { return x; }
    friend std::ostream& operator<<(std::ostream& o, XandValue v){ return o << v.x   [b]; } XandValue(bool x):x{!x}{}
};

int main(){
    XandValue a{true}, b{true};
    std::cout << std::boolalpha
              << "a is " << a << "\n"
              << "b is " << b << "\n"
              << "a && b is " << (a && b) << '\n';
}

Output:

a is true
b is true
a && b is false

Scroll rightwards to see the lies

\$\endgroup\$
1
\$\begingroup\$

Uiua

Print‼ ←^ $"&p$\"_: \_\" _" ⊙(⍜⊜□≡⋅"¬×"⊸⦷@×) °□₂

A ← 1
B ← 1

Print‼(A|A)
Print‼(B|B)
Print‼(A AND B|×A B)

Try it in the pad!

Output:

A: 1
B: 1
A AND B: 0

1 is truthy and 0 is falsy, as always.

Explanation

In Uiua, we usually do logical AND with × multiply. The Print‼ macro defined at the top of the code, other than being a nice wrapper, also hides a piece of code that turns any instance of × into ¬×, effectively inverting any logical ANDs done inside it.

\$\endgroup\$
0
\$\begingroup\$

Google Sheets

=let(
  and, lambda(a, b, xor(a, b)),
  a, true,
  b, true,
  vstack(
    if(a, a),
    if(b, b),
    if(and(a, b), and(a, b)),
    if(not(and(a, b)), "not at the same time")
  )
)

Redefines and() so that it returns true when the number of true arguments is odd, and false when the number of true arguments is even.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.