Skip to content

Commit

Permalink
rename contextNondecimalBase.pl to contextBaseN.pl
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-Jordan authored and pstaabp committed Feb 13, 2024
1 parent 58cb5cb commit a65f2f5
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

=head1 NAME
contextNonDecimalBase.pl - Implements a MathObject class and context for numbers
contextBaseN.pl - Implements a MathObject class and context for numbers
in non-decimal bases
=head1 DESCRIPTION
Expand All @@ -16,15 +16,15 @@ =head1 DESCRIPTION
The original purpose for this is simple conversion and operations in another base, however
it is not limited to this.
To use a non-decimal base MathObject, first load the contextNondecimalBase.pl file:
To use a non-decimal base MathObject, first load the contextBaseN.pl file:
loadMacros('contextNondecimalBase.pl');
loadMacros('contextBaseN.pl');
There are two contexts: C<NondecimalBase> and C<LimitedNondecimalBase>, where the former
There are two contexts: C<BaseN> and C<LimitedBaseN>, where the former
allows operations between numbers and the latter only allows numbers. To use either,
one must set the base. For example:
Context('NondecimalBase')->setBase(5);
Context('BaseN')->setBase(5);
Now most numerical strings in Compute, Formula, and student answers will be read in base five.
Expand All @@ -49,16 +49,16 @@ =head1 DESCRIPTION
$p = Point(29, 68);
For many problems, one may wish to not allow operators in the student answers. Use
'LimitedNondecimalBase' for this.
'LimitedBaseN' for this.
Context('LimitedNondecimalBase')->setBase(5);
Context('LimitedBaseN')->setBase(5);
$sum = Compute("104+233"); # There will be an error on this line now.
In both 'NondecimalBase' and 'LimitedNondecimalBase', another option is to pass the
In both contexts, rather than pass the base as a number, another option is to pass the
digits used for the number to the C<setBase> method. For example, if one wants to use base-12
and use the alternative digits 0..9,'T','E', then
Context('NondecimalBase')->setBase([0 .. 9, 'T', 'E']);
Context('BaseN')->setBase([0 .. 9, 'T', 'E']);
Then one can use the digits 'T' and 'E' in a number like:
Expand All @@ -80,9 +80,9 @@ =head2 Sample PG problem
A simple PG problem that asks a student to convert a number into base-5:
DOCUMENT();
loadMacros(qw(PGstandard.pl PGML.pl contextNondecimalBase.pl));
loadMacros(qw(PGstandard.pl PGML.pl contextBaseN.pl));
Context('LimitedNondecimalBase')->setBase(5);
Context('LimitedBaseN')->setBase(5);
# decimal number picked randomly.
$a = random(130,500);
Expand All @@ -96,18 +96,18 @@ =head2 Sample PG problem
=cut

sub _contextNondecimalBase_init {
context::NondecimalBase::Init(@_);
sub convertBase { context::NondecimalBase::convert(@_); }
sub _contextBaseN_init {
context::BaseN::Init(@_);
sub convertBase { context::BaseN::convert(@_); }
}

package context::NondecimalBase;
package context::BaseN;

# Define the contexts 'NondecimalBase' and 'LimitedNondecimalBase'
# Define the contexts 'BaseN' and 'LimitedBaseN'
sub Init {
my $context = $main::context{NondecimalBase} = context::NondecimalBase::Context->new();
$context = $main::context{LimitedNondecimalBase} = $context->copy;
$context->{name} = 'LimitedNondecimalBase';
my $context = $main::context{BaseN} = context::BaseN::Context->new();
$context = $main::context{LimitedBaseN} = $context->copy;
$context->{name} = 'LimitedBaseN';
$context->operators->undefine($context->operators->names);
$context->parens->undefine('|', '{', '[');
}
Expand Down Expand Up @@ -158,7 +158,7 @@ sub convert {
my $from = $options{'from'} // 10;
my $to = $options{'to'} // 10;

$convertContext = $main::context{NondecimalBase}->copy unless $convertContext;
$convertContext = $main::context{BaseN}->copy unless $convertContext;
if ($from != 10) {
$convertContext->setBase($from);
$value = $convertContext->fromBase($value);
Expand All @@ -170,31 +170,31 @@ sub convert {
return $value;
}

package context::NondecimalBase::Context;
package context::BaseN::Context;
our @ISA = ('Parser::Context');

# Create a Context based on Numeric (Real) that allows +, -, *, / and ^ on nondecimal numbers.
# Create a Context based on Numeric that allows +, -, *, /, %, and ^ on BaseN integers.

sub new {
my $self = shift;
my $class = ref($self) || $self;
my $context = bless Parser::Context->getCopy('Numeric'), $class;
$context->{name} = 'NondecimalBase';
$context->{parser}{Number} = 'context::NondecimalBase::Number';
$context->{value}{Real} = 'context::NondecimalBase::Real';
$context->{name} = 'BaseN';
$context->{parser}{Number} = 'context::BaseN::Number';
$context->{value}{Real} = 'context::BaseN::Real';
$context->functions->disable('All');
$context->constants->clear();
$context->{pattern}{number} = '[' . join('', 0 .. 9, 'A' .. 'Z') . ']+';
$context->{precedence}{NondecimalBase} = $context->{precedence}{special};
$context->{pattern}{number} = '[' . join('', 0 .. 9, 'A' .. 'Z') . ']+';
$context->{precedence}{BaseN} = $context->{precedence}{special};
$context->flags->set(limits => [ -1000, 1000, 1 ]);
$context->operators->add(
'%' => {
class => 'context::NondecimalBase::BOP::modulo',
precedence => 3,
class => 'context::BaseN::BOP::modulo',
precedence => 3,
associativity => 'left',
type => 'bin',
string => ' % ',
TeX => '\mathbin{\%}',
type => 'bin',
string => ' % ',
TeX => '\mathbin{\%}',
}
);
return $context;
Expand All @@ -206,12 +206,12 @@ sub setBase {
my ($self, $base) = @_;
my $digits;

$base = [0, 1] if ($base eq 'binary');
$base = [0 .. 7] if ($base eq 'octal');
$base = [0 .. 9] if ($base eq 'decimal');
$base = [0 .. 9, '2', 'B'] if ($base eq 'duodecimal');
$base = [0 .. 9, 'A' .. 'F'] if ($base eq 'hexadecimal');
$base = ['A' .. 'Z', 'a' .. 'z', 0 .. 9, '_', '?'] if ($base eq 'base64');
$base = [ 0, 1 ] if ($base eq 'binary');
$base = [ 0 .. 7 ] if ($base eq 'octal');
$base = [ 0 .. 9 ] if ($base eq 'decimal');
$base = [ 0 .. 9, '2', 'B' ] if ($base eq 'duodecimal');
$base = [ 0 .. 9, 'A' .. 'F' ] if ($base eq 'hexadecimal');
$base = [ 'A' .. 'Z', 'a' .. 'z', 0 .. 9, '_', '?' ] if ($base eq 'base64');

if (ref($base) eq 'ARRAY') {
$digits = $base;
Expand Down Expand Up @@ -277,7 +277,7 @@ sub fromBase {

# A replacement for Parser::Number that accepts numbers in a non-decimal base and
# converts them to decimal for internal use
package context::NondecimalBase::Number;
package context::BaseN::Number;
our @ISA = ('Parser::Number');

# Create a new number in the given base and convert to base 10.
Expand All @@ -297,17 +297,16 @@ sub eval {
}

# Modulo operator
package context::NondecimalBase::BOP::modulo;
package context::BaseN::BOP::modulo;
our @ISA = ('Parser::BOP::divide');

#
# Do the division.
#
sub _eval { $_[1] % $_[2] }


# A replacement for Value::Real that handles non-decimal integers
package context::NondecimalBase::Real;
package context::BaseN::Real;
our @ISA = ('Value::Real');

# Stringify and TeXify the number in the context's base
Expand Down
18 changes: 9 additions & 9 deletions t/contexts/nondecimal_base.t
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env perl

=head1 NondecimalBase context
=head1 BaseN context
Test the functionality for the NondecimalBase context.
Test the functionality for the BaseN context.
=cut

Expand All @@ -13,13 +13,13 @@ do "$ENV{PG_ROOT}/t/build_PG_envir.pl";

use lib "$ENV{PG_ROOT}/lib";

loadMacros('PGstandard.pl', 'MathObjects.pl', 'contextNondecimalBase.pl');
loadMacros('PGstandard.pl', 'MathObjects.pl', 'contextBaseN.pl');

use Value;
require Parser::Legacy;
import Parser::Legacy;

Context('NondecimalBase');
Context('BaseN');

subtest 'conversion from a non-decimal base to base 10' => sub {
is convertBase('101010', from => 2), 42, 'convert from base 2';
Expand Down Expand Up @@ -55,7 +55,7 @@ subtest 'Convert between two non-decimal bases' => sub {
};

# Now test the Context.
Context('NondecimalBase')->setBase(5);
Context('BaseN')->setBase(5);

subtest 'Check that the Context parses number correct' => sub {
is Context()->{base}, 5, 'Check that the base is stored.';
Expand Down Expand Up @@ -136,7 +136,7 @@ subtest 'Use alternative digits' => sub {
};

subtest 'check for other errors' => sub {
Context('NondecimalBase');
Context('BaseN');
like dies { Compute('1234') }, qr/The base must be set for this context/,
'Check that there is a error if the base is not set.';

Expand All @@ -146,8 +146,8 @@ subtest 'check for other errors' => sub {
'Check that there is a digit list for large bases';
};

subtest 'Check the LimitedNondecimalBase features' => sub {
Context('LimitedNondecimalBase')->setBase(5);
subtest 'Check the LimitedBaseN features' => sub {
Context('LimitedBaseN')->setBase(5);

like dies { Compute("104+320"); }, qr/Can't use '\+' in this context/, "Check that '+' is not allowed.";
like dies { Compute("320-104"); }, qr/Can't use '\-' in this context/, "Check that '-' is not allowed.";
Expand All @@ -159,7 +159,7 @@ subtest 'Check the LimitedNondecimalBase features' => sub {
};

subtest 'Test with different set of digits' => sub {
Context('NondecimalBase')->setBase([ 0 .. 9, 'B', 'D' ]);
Context('BaseN')->setBase([ 0 .. 9, 'B', 'D' ]);

ok my $a1 = Compute("3BD"), "Create '3BD' in base-12 with B=10, D=11";
is $a1->value, 563, "'3BD'=563 in base-12 with B=10, D=11";
Expand Down

0 comments on commit a65f2f5

Please sign in to comment.