17
\$\begingroup\$

Many programming language provide operators for manipulating the binary (base-2) digits of integers. Here is one way to generalize these operators to other bases:

Let x and y be single-digit numbers in base B. Define the unary operator ~ and binary operators &, |, and ^ such that:

  • ~x = (B - 1) - x
  • x & y = min(x, y)
  • x | y = max(x, y)
  • x ^ y = (x & ~y) | (y & ~x)

Note that if B=2, we get the familiar bitwise NOT, AND, OR, and XOR operators.

For B=10, we get the “decimal XOR” table:

^ │ 0 1 2 3 4 5 6 7 8 9
──┼────────────────────
0 │ 0 1 2 3 4 5 6 7 8 9
1 │ 1 1 2 3 4 5 6 7 8 8
2 │ 2 2 2 3 4 5 6 7 7 7
3 │ 3 3 3 3 4 5 6 6 6 6
4 │ 4 4 4 4 4 5 5 5 5 5
5 │ 5 5 5 5 5 4 4 4 4 4
6 │ 6 6 6 6 5 4 3 3 3 3
7 │ 7 7 7 6 5 4 3 2 2 2
8 │ 8 8 7 6 5 4 3 2 1 1
9 │ 9 8 7 6 5 4 3 2 1 0

For multi-digit numbers, apply the single-digit operator digit-by-digit. For example, 12345 ^ 24680 = 24655, because:

  • 1 ^ 2 = 2
  • 2 ^ 4 = 4
  • 3 ^ 6 = 6
  • 4 ^ 8 = 5
  • 5 ^ 0 = 5

If the operands are different lengths, then pad the shorter one with leading zeros.

The challenge

Write, in as few bytes as possible, a program or function that takes as input two integers (which may be assumed to be between 0 and 999 999 999, inclusive) and outputs the “decimal XOR” of the two numbers as defined above.

Test cases

  • 12345, 24680 → 24655
  • 12345, 6789 → 16654
  • 2019, 5779 → 5770
  • 0, 999999999 → 999999999
  • 0, 0 → 0
asked Sep 17, 2019 at 2:51
\$\endgroup\$
8
  • \$\begingroup\$ May we take the input or output as strings or char arrays? \$\endgroup\$ Commented Sep 17, 2019 at 3:01
  • 6
    \$\begingroup\$ How about a digit array? Is that acceptable? \$\endgroup\$ Commented Sep 17, 2019 at 3:06
  • 1
    \$\begingroup\$ Is 09 an acceptable result for an input of 90, 99? \$\endgroup\$ Commented Sep 17, 2019 at 9:39
  • 1
    \$\begingroup\$ I wish there was a generalisation that maintained A^B^B=A \$\endgroup\$ Commented Sep 18, 2019 at 18:20
  • 2
    \$\begingroup\$ @trichoplax, you can't have both a^b=b^a and a^b^b=a for bases with an odd prime divisor \$\endgroup\$ Commented Sep 28, 2019 at 14:57

7 Answers 7

3
\$\begingroup\$

Jelly, 14 bytes

DUz0«9_ṚƊṀƊ€UḌ

Try it online!

Grid of all single digit pairs

A monadic link taking a list of two integers as its argument and returning an integer.

Explanation

D | Decimal digits
 U | Reverse order of each set of digits
 z0 | Transpose with 0 as filler
 Ɗ€ | For each pair of digits, do the following as a monad:
 « Ɗ | - Minimum of the two digits and the following as a monad (vectorises):
 9_ | - 9 minus the digits
 Ṛ | - Reverse the order
 Ṁ | - Maximum
 U | Reverse the order of the answer to restore the orignal order of digits
 Ḍ | Convert back from decimal digits to integer

If a digit matrix is acceptable input/output:

Jelly, 12 bytes

Uz0«9_ṚƊṀƊ€U

Try it online!

answered Sep 17, 2019 at 6:19
\$\endgroup\$
0
2
\$\begingroup\$

Pyth, 31 bytes

LhS,hb-9ebjkmeS,ydy_d_.t_MjRTQ0

Try it online!

LhS,hb-9eb # Helper function, computes the (x & ~y) part
L # y = lambda b:
 S # sorted( ) 
 , # [ , ]
 hb # b[0]
 -9eb # 9-b[-1]
 h # [0] # sorted(...)[0] = minimum
jkmeS,ydy_d_.t_MjRTQ0 # Main program (example input Q: [123, 45])
 jRTQ # convert each input to a list of digits -> [[1,2,3],[4,5]]
 _M # reverse each -> [[3,2,1],[5,4]]
 .t 0 # transpose, padding right with 0 -> [[3,5],[2,4],[1,0]]
 _ # reverse -> [[1,0],[2,4],[3,5]]
 m # map that over lambda d:
 S, # sorted([ , ])
 yd # y(d)
 y_d # y(d[::-1]) # reversed
 e # [-1] # sorted(...)[-1] = maximum
jk # ''.join( ^^^ )
answered Sep 17, 2019 at 6:36
\$\endgroup\$
2
\$\begingroup\$

Python 2, 71 bytes

f=lambda n,m,T=10:n+m and max(min(n%T,~m%T),min(m%T,~n%T))+f(n/T,m/T)*T

Try it online!

answered Sep 17, 2019 at 19:22
\$\endgroup\$
1
\$\begingroup\$

Forth (gforth), 111 bytes

: m 10 /mod rot ;
: t 9 swap - min ;
: f 2dup + 0> if m m recurse 10 * -rot 2dup swap t -rot t max + 1 then * ;

Try it online!

Code Explanation

: m \ start a new word definition
 10 /mod \ get quotient and remainder of dividing by 10
 rot \ move item in 3rd stack position to top of stack
; \ end word definition
\ word implementing "not" followed by "and"
: t \ start a new word definition
 9 swap - \ subtract top stack element from 9
 min \ get the minimum of the top two stack elements
; \ end word definition
: f \ start a new word definition
 2dup + \ duplicate top two stack elements and add them together
 0> if \ if greater than 0
 m m \ divide both by 10, move remainders behind quotients
 recurse \ call self recursively
 10 * \ multiply result by 10 (decimal left shift of 1)
 -rot \ get remainders from original division
 2dup \ duplicate both remainders 
 swap t \ swap order and call t (b & !a)
 -rot t \ move result back and call t on other pair (a & !b)
 max + 1 \ get the max of the two results and add to total. put 1 on top of stack
 then \ end if block
 * \ multiply top two stack results (cheaper way of getting rid of extra 0)
; \ end word definition
answered Sep 17, 2019 at 20:35
\$\endgroup\$
1
\$\begingroup\$

C# (Visual C# Interactive Compiler), 75 bytes

a=>b=>a.Select((x,y)=>Math.Max(9-x<(y=y<b.Count?b[y]:0)?9-x:y,9-y<x?9-y:x))

Saved 6 bytes thanks to @someone

Try it online!

answered Sep 17, 2019 at 3:45
\$\endgroup\$
2
  • \$\begingroup\$ 76 bytes. I think this question might be a unique opportunity to use Zip. \$\endgroup\$ Commented Sep 17, 2019 at 4:02
  • 1
    \$\begingroup\$ @someone Thanks! Regarding Zip, you can't use it as it automatically truncates the longer collection to the length of the shorter one \$\endgroup\$ Commented Sep 17, 2019 at 4:03
0
\$\begingroup\$

PHP, (削除) 111 (削除ここまで) 109 bytes

for(;''<($a=$argv[1][-++$i]).$b=$argv[2][-$i];)$s=min($a<5?9-$a:$a,max($a<5?$a:9-$a,$a<5?$b:9-$b)).$s;echo$s;

Try it online!

Tests: Try it online!

If we call the digits we want to XOR, $a and $b, I found that:

  • When $a is less than 5, XOR = min(9-$a, max($a, $b))
  • When $a is equal to or more than 5, XOR = min($a, max(9-$a, 9-$b))

So I implemented this logic plus a hack to handle numbers with different lengths. I take each digit form the end of both input numbers (with negative indexes like input[-1], input[-2], ...) and compute the XOR and put the result in reversed order in a string to be printed at the end. Since I take digits from the end of numbers, XOR results should be put together in reversed order. When one of the inputs is longer than the other one, the negative index on shorter input results in an empty string which is equal to 0.

answered Sep 17, 2019 at 9:29
\$\endgroup\$
0
\$\begingroup\$

Retina, (削除) 85 (削除ここまで) 59 bytes

^'0P`.+
N$`.
$.%`
¶
/../_(`^
$"
T`d`Rd`.¶.
%N`.
^N`..
L`^.

Try it online! Takes input as separate lines, but link is to test suite that reformats comma-separated input. Explanation:

^'0P`.+

Left-pad with zeros both lines to the same length.

N$`.
$.%`
¶

Sort each digit by its column index, then delete the newline. This has the effect of pairing the digits together in much the same way as a transpose would.

/../_(`

Apply separately to each pair of digits, joining the results together.

^
$"

Duplicate the pair.

T`d`Rd`.¶.

Reverse the second digit of the first pair and the first digit of the second, so we now have x ~y on one line and ~x y on the other.

%N`.

Sort the digits of each line in order, so that the first digit is now x & ~y or ~x & y as appropriate.

^N`..

Reverse sort the lines.

L`^.

And extract the first digit, which is the desired result.

answered Sep 17, 2019 at 12:12
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.