#!/usr/bin/perl
use 5.016;
use warnings;
no warnings qw(once);
use List::Util qw(reduce);
use POSIX qw(ceil);

sub lb { log(shift) / log(2) }

sub f {
	my ($n, $l) = @_;

	if (ref $n){
		my $x = reduce{ $a * 2 + $b } @{$n};
		return ($_[0]->[0] ? $x - (2 ** @{$n}) : $x);
	}

	my @l = sub {
		$_[0] < 1 ? @{$_[1]} : __SUB__->(int($_[0] / 2), [$_[0] % 2, @{$_[1]}])
	}->(($n < 0 ? $n + 2 ** ceil(lb(abs $n) + 1) : $n), []);

	return sub {
		($_[0]) x (defined $l ? $l - @l : $_[1]), @l
	}->($n < 0 ? (1, 0) : (0, 1));
}

say f(0);
say f(1);
say f(-1);
say f(3);
say f(-3);
say f(10);
say f(10, 8);
say f(-8);
say f(-8, 8);

say f([0]);
say f([0, 1]);
say f([1]);
say f([0, 1, 1, 1]);
say f([1, 1, 1, 1]);
say f([1, 0, 0, 0]);
