Peter’s blog ✴ Week 308 ✴ 10 February 2025

THE WEEKLY CHALLENGE
AND and XOR

The Perl Camel

Task 2

Decode xor

You are given an encoded array and an initial integer. Write a script to find the original array that produced the given encoded array. It was encoded such that encoded[i] = orig[i] XOR orig[i + 1].

Examples


Example 1
Input: @encoded = (1, 2, 3), $initial = 1
Output: (1, 0, 2, 1)
Encoded array created like below, if the original array 
   was (1, 0, 2, 1)
$encoded[0] = (1 xor 0) = 1
$encoded[1] = (0 xor 2) = 2
$encoded[2] = (2 xor 1) = 3

Example 2
Input: @encoded = (6, 2, 7, 3), $initial = 4
Output: (4, 2, 0, 7, 4)

Analysis

Oh dear, I thought, caculations involving bitwise operations are always a bit tricky in Perl (and other languages) because the 'not' operator often doesn't do what you want. For example, we might think:

6 decimal is 110 binary
so not 6 is 001 binary
which is 1 decimal

... but Perl doesn't work like that. It thinks:

6 decimal is 00000000000000000000000000000110 binary
so not 6 is 11111111111111111111111111111001 binary
which is a humongous decimal number.

So to the challenge. The essence of this is that we have an equation
$a xor $b = $e where we know $a and $e and need to calculate $b.

My first thought was simply to loop $b over say 1 to 1000 and find the $a xor $b which equals $e. For even quite large values of $a and $e that works in a fraction of a second and - of course - gives the correct answer.

But there is a better way. If, as we know, $a xor $b = $e then it is also true that $a xor $e = $b, or to put it differently
$b = $a xor $e. So all we need to do is apply this to each encoded number $e, setting $a = $b after each one.

Perl Weekly’s review

from PW issue 708

Great detailed XOR operation is very interesting, and definitely not to be missed. Thanks for the contributions.

Try it 

Try running the script with any input:



example: 3, 1, 4, 1, 5, 9



example: 2

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2025-02-10
use utf8;     # Week 308 - task 2 - Decode xor
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

decode_xor([1, 2, 3], 1);
decode_xor([6, 2, 7, 3], 4);
decode_xor([47, 21, 33, 8], 4);

sub decode_xor {
    
    my (@e, $a, $b, $e, @result);
    
    # inputs
    @e = @{$_[0]};
    $a = $_[1];
    $result[0] = $a;
    
    # loop over values of @encoded
    for $e (@e) {
        $b = $e ^ $a;
        push @result, $b;
        $a = $b;
    }
    
    say qq[\nInput:  \@encoded = (] . join(', ', @e) . qq[), \$integer = $_[1]];
    say qq[Output: (] . join(', ', @result) . ')';
}

11 lines of code

Output from script


Input:  @encoded = (1, 2, 3), $integer = 1
Output: (1, 0, 2, 1)

Input:  @encoded = (6, 2, 7, 3), $integer = 4
Output: (4, 2, 0, 7, 4)

Input:  @encoded = (47, 21, 33, 8), $integer = 4
Output: (4, 43, 62, 31, 23)

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain