8
\$\begingroup\$

I want to read two strings on separate lines, each string the same length and containing only 0's and 1's, and determine if the first is the one's complement of the second. How succinctly can this be done in Python3? (Sorry to specify the language, but this is for my son who's studying Python)

A list comprehension seems to work but is quite ugly.

if ['0' if x=='1' else '1' for x in input()] == list(input()): print('yep')

Is there a slicker/shorter way to do this?

\$\endgroup\$
7
  • 4
    \$\begingroup\$ Here's a simple, consice way: Try it online! \$\endgroup\$
    – naffetS
    Commented Oct 8, 2022 at 20:57
  • 4
    \$\begingroup\$ If we're trying to do this for the shortest possible code, here's 52 bytes: Try it online! But that isn't so clear. \$\endgroup\$
    – naffetS
    Commented Oct 8, 2022 at 20:57
  • \$\begingroup\$ Do you just want short code, or do you also want it to be elegant and/or readable? \$\endgroup\$
    – xnor
    Commented Oct 8, 2022 at 22:52
  • 1
    \$\begingroup\$ @JonathanAllan You simply can't have then, whether you have an else or not. \$\endgroup\$
    – naffetS
    Commented Oct 8, 2022 at 23:55
  • 1
    \$\begingroup\$ Thanks guys. I tried my code, noticed the error and fixed it, but forgot to fix it in my question above. Edited my question to correct it! \$\endgroup\$
    – Fixee
    Commented Oct 9, 2022 at 0:22

2 Answers 2

11
\$\begingroup\$

Python 3,  51 44 43  41 bytes

-7 thanks to loopy walt's suggestion to use *open.
-1 thanks to xnor's suggestion to replace any(...) with 1in ...
-2 thanks to dingledooper's suggestion of using str.find instead of str.__eq__

0in map(str.find,*open(0))or print('yep')

Try it online!

This is a full program that takes input from stdin until an EOF (which we assume the user provides at the end of the second line) with open(0) and maps across the two strings by splatting (*), calling str.find on each pair of characters in turn. If 0 is in the result (i.e. the characters are equal and so the index of the first in the second is 0 rather than -1 for "not found") then the right-hand clause of the or is not evaluated, and so we don't print.


My previous version, with xnor's and dingledooper's suggestions, at \$48\$, is interactive without the EOF faff:

0in map(str.find,input(),input())or print('yep')

You could save one more byte by printing to stderr instead of stdout by exiting the program early using exit in place of print.


A note to your son - this is not how I'd want someone in my team at work to write code :) - readability counts, a lot.

\$\endgroup\$
20
  • \$\begingroup\$ Don't you mean unless any of the pairs are equal to each other? \$\endgroup\$
    – Neil
    Commented Oct 8, 2022 at 23:52
  • \$\begingroup\$ @Neil thanks, I got there in the end :p (many edits) \$\endgroup\$ Commented Oct 8, 2022 at 23:55
  • 1
    \$\begingroup\$ any(map(str.__eq__,*open(0)))or print('yep') \$\endgroup\$
    – loopy walt
    Commented Oct 9, 2022 at 0:08
  • 1
    \$\begingroup\$ Looks like the any(...) can be 1in .. \$\endgroup\$
    – xnor
    Commented Oct 9, 2022 at 0:55
  • 3
    \$\begingroup\$ 41 bytes: 0in map(str.find,*open(0))or print('yep'). \$\endgroup\$ Commented Oct 9, 2022 at 2:22
4
\$\begingroup\$

Python3, 62 bytes

Since the bits at the similar position need to be set in one of the inputs and unset in the other, their bitwise XOR must have all bits set.

x=input()
int(x,2)^~-(1<<len(x))^int(input(),2)or print("yep")

Try it online!

-5 bytes thanks to Arnauld

Updated from my previous answer where I incorrectly assumed that checking bitwise AND = 0 was a sufficient condition.

\$\endgroup\$
1
  • \$\begingroup\$ 62 bytes \$\endgroup\$
    – Arnauld
    Commented Oct 10, 2022 at 9:20

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.