zeroclickinfo-goodies/lib/DDG/Goodie/Base.pm

66 lines
1.9 KiB
Perl
Raw Normal View History

package DDG::Goodie::Base;
# ABSTRACT: convert numbers between arbitrary bases
use strict;
use DDG::Goodie;
use Math::Int2Base qw(int2base base2int);
use 5.010;
use bigint;
my %base_map = (
hex => 16,
hexadecimal => 16,
oct => 8,
octal => 8,
binary => 2,
dec => 10,
decimal => 10
);
2014-10-15 00:17:44 -07:00
my $map_keys = join '|', keys %base_map;
2012-04-15 18:31:26 -07:00
triggers any => 'base', keys %base_map;
zci answer_type => "conversion";
zci is_cached => 1;
2012-11-06 12:34:58 -08:00
primary_example_queries '255 in hex';
secondary_example_queries '255 in base 16', '42 in binary';
description 'convert a number to an arbitrary base';
name 'Base';
code_url 'https://github.com/duckduckgo/zeroclickinfo-goodies/blob/master/lib/DDG/Goodie/Base.pm';
category 'conversions';
topics 'math';
attribution web => [ 'http://perlgeek.de/blog-en', 'Moritz Lenz' ],
2015-01-07 10:37:42 -08:00
github => [ 'http://github.com/moritz', 'Moritz Lenz'];
2012-11-06 12:34:58 -08:00
handle query_clean => sub {
return unless /^(?<inp>[0-9A-Za-z]+)\s*((?:(?:in|as)\s+)?(?:(?<lt>$map_keys)|(?:base\s*(?<ln>[0-9]+)))\s+)?(?:(?:in|as|to)\s+)?(?:(?<rt>$map_keys)|(?:base\s*(?<rn>[0-9]+)))$/;
my $input = $+{'inp'};
my $from_base = 10;
if (defined $+{'ln'}) {
$from_base = $+{'ln'};
} elsif (defined $+{'lt'}) {
$from_base = $base_map{$+{'lt'}}
}
my $to_base = $+{'rn'} // $base_map{$+{'rt'}};
return if $to_base < 2 || $to_base > 36 || $from_base < 2 || $from_base > 36;
my $output = 0;
eval { $output = convert_base($input, $from_base, $to_base) }; return if $@;
return "$input in base $to_base is $output",
2014-10-15 00:17:44 -07:00
structured_answer => {
input => ["$input"],
operation => "From base $from_base to base $to_base",
result => $output
2014-10-15 00:17:44 -07:00
};
};
sub convert_base {
my ($num, $from, $to) = @_;
return int2base( base2int( uc $num, $from), $to);
}
1;