use 5.010;
use strict;
use Carp qw/croak/;
use List::Util qw/max/;
sub xor_strings
{
croak "should be passed two arguments" unless @_==2;
state $chunk_size = 4;
state $pattern = sprintf '%%0%dx', $chunk_size;
# Make strings equal length, and a multiple of $chunk_size.
my $length = max(map { length $_ } @_);
$length += $chunk_size - ($length % $chunk_size);
my @strings = map { ('0'x($length - length $_)) . $_ } @_;
# Join results of each chunk
return join q{},
map {
# Parse chunk hex to an integer
my $i = $_;
my @nums = map { hex substr $_, $i*$chunk_size, $chunk_siz
+e } @strings;
# Xor them and convert to hex.
sprintf $pattern, $nums[0] ^ $nums[1]
}
0 .. ($length/$chunk_size)-1;
}
say xor_strings(
'112233112233112233112233112233112233112233112233112233',
'aabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc112233',
);
The chunk size of 4 is fairly conservative. It means that the string in processed in four-digit (i.e. 16 bit) chunks. You can probably get a minor speed up using a larger chunk size if you know that your computer will be able to handle it. The returned value will be left-padded with zeroes to be a length that is a multiple of the chunk size.
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
|