Skip to content

Commit

Permalink
- Added the Array.each_slice(n, {...}) method (same as in Ruby)
Browse files Browse the repository at this point in the history
- Various optimizations inside the Array class.
  • Loading branch information
trizen committed Dec 17, 2015
1 parent 6bc3074 commit 5e94052
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 37 deletions.
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ scripts/RosettaCode/read_a_file_line_by_line_1.sf
scripts/RosettaCode/read_a_specific_line_from_a_file.sf
scripts/RosettaCode/read_entire_file.sf
scripts/RosettaCode/real_constants_and_functions.sf
scripts/RosettaCode/reduced_row_echelon_form.sf
scripts/RosettaCode/regular_expressions.sf
scripts/RosettaCode/regular_expressions_1.sf
scripts/RosettaCode/regular_expressions_2.sf
Expand Down
145 changes: 108 additions & 37 deletions lib/Sidef/Types/Array/Array.pm
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ package Sidef::Types::Array::Array {
my ($self, $operator) = @_;

$operator = $operator->get_value if ref($operator);
(my $offset = $#{$self}) >= 0 || return;
(my $end = $#{$self}) >= 0 || return;

my $x = $self->[0];
foreach my $i (1 .. $offset) {
foreach my $i (1 .. $end) {
$x = $x->$operator($self->[$i]);
}
$x;
Expand Down Expand Up @@ -166,7 +166,13 @@ package Sidef::Types::Array::Array {

sub multiply {
my ($self, $num) = @_;
$self->new((@{$self}) x $num->get_value);

{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$num = $num->get_value;
}

$self->new((@{$self}) x $num);
}

*mul = \&multiply;
Expand All @@ -177,7 +183,10 @@ package Sidef::Types::Array::Array {
my @obj = @{$self};

my @array;
my $len = @obj / $num->get_value;
my $len = @obj / do {
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$num->get_value;
};

my $i = 1;
my $pos = $len;
Expand All @@ -197,14 +206,12 @@ package Sidef::Types::Array::Array {
sub or {
my ($self, $array) = @_;
my $new_array = $self->new;

$self->xor($array)->concat($self->and($array));
}

sub xor {
my ($self, $array) = @_;
my $new_array = $self->new;

($self->concat($array))->subtract($self->and($array));
}

Expand Down Expand Up @@ -263,15 +270,17 @@ package Sidef::Types::Array::Array {
sub combinations {
my ($self, $k, $block) = @_;

do {
{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$k = $k->get_value;
};
}

if (defined($block)) {

if ($k == 0) {
$block->run($self->new);
if (defined(my $res = $block->_run_code($self->new))) {
return $res;
}
return $self;
}

Expand Down Expand Up @@ -400,7 +409,12 @@ package Sidef::Types::Array::Array {

sub make {
my ($self, $size, $type) = @_;
$self->new(($type) x $size->get_value);
$self->new(
($type) x do {
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$size->get_value;
}
);
}

sub _min_max {
Expand Down Expand Up @@ -652,6 +666,31 @@ package Sidef::Types::Array::Array {
*for = \&each;
*foreach = \&each;

sub each_slice {
my ($self, $n, $code) = @_;

{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$n = $n->get_value;
}

my $end = @{$self};
for (my $i = $n - 1 ; $i < $end ; $i += $n) {
if (defined(my $res = $code->_run_code($self->new(@{$self}[$i - ($n - 1) .. $i])))) {
return $res;
}
}

my $mod = $end % $n;
if ($mod != 0) {
if (defined(my $res = $code->_run_code($self->new(@{$self}[$end - $mod .. $end - 1])))) {
return $res;
}
}

$self;
}

sub each_index {
my ($self, $code) = @_;

Expand Down Expand Up @@ -854,31 +893,19 @@ package Sidef::Types::Array::Array {

*last_index = \&rindex;

sub reduce_pairs {
sub pairmap {
my ($self, $obj) = @_;

(my $end = $#{$self}) == -1
&& return $self->new;
my $end = @{$self} || return $self->new;

my @array;
if (ref($obj) eq 'Sidef::Types::Block::Block') {
for (my $i = 1 ; $i <= $end ; $i += 2) {
push @array, scalar $obj->run($self->[$i - 1], $self->[$i]);
}
}
else {
my $method = $obj->get_value;
for (my $i = 1 ; $i <= $end ; $i += 2) {
my $x = $self->[$i - 1];
push @array, $x->$method($self->[$i]);
}
for (my $i = 1 ; $i < $end ; $i += 2) {
push @array, scalar $obj->run(@{$self}[$i - 1, $i]);
}

$self->new(@array);
}

*pairmap = \&reduce_pairs;

sub shuffle {
my ($self) = @_;
state $x = require List::Util;
Expand Down Expand Up @@ -947,15 +974,21 @@ package Sidef::Types::Array::Array {

sub resize {
my ($self, $num) = @_;
$#{$self} = $num;
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$#{$self} = $num->get_value;
$num;
}

*resize_to = \&resize;

sub rand {
my ($self, $amount) = @_;

if (defined $amount) {
{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$amount = $amount->get_value;
}
return $self->new(map { $self->[CORE::rand(scalar @{$self})] } 1 .. $amount);
}
$self->[CORE::rand(scalar @{$self})];
Expand Down Expand Up @@ -1195,7 +1228,16 @@ package Sidef::Types::Array::Array {
my ($self, $num) = @_;

if (defined $num) {
return $self->new(CORE::splice(@{$self}, 0, $num->get_value));
return $self->new(
CORE::splice(
@{$self},
0,
do {
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$num->get_value;
}
)
);
}

@{$self} || return;
Expand All @@ -1209,7 +1251,12 @@ package Sidef::Types::Array::Array {
my ($self, $num) = @_;

if (defined $num) {
$num = $num->get_value > $#{$self} ? 0 : @{$self} - $num->get_value;
{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$num = $num->get_value;
}

$num = $num > $#{$self} ? 0 : @{$self} - $num;
return $self->new(CORE::splice(@{$self}, $num));
}

Expand All @@ -1228,7 +1275,14 @@ package Sidef::Types::Array::Array {

sub delete_index {
my ($self, $offset) = @_;
CORE::splice(@{$self}, $offset->get_value, 1);
CORE::splice(
@{$self},
do {
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$offset->get_value;
},
1
);
}

*pop_at = \&delete_index;
Expand All @@ -1237,24 +1291,36 @@ package Sidef::Types::Array::Array {
sub splice {
my ($self, $offset, $length, @objects) = @_;

$offset = defined($offset) ? $offset->get_value : 0;
$length = defined($length) ? $length->get_value : scalar(@{$self});
{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$offset = defined($offset) ? $offset->get_value : 0;
$length = defined($length) ? $length->get_value : scalar(@{$self});
}

$self->new(CORE::splice(@{$self}, $offset, $length, @objects));
}

sub take_right {
my ($self, $amount) = @_;

my $offset = $#{$self};
$amount = $offset > ($amount->get_value - 1) ? $amount->get_value - 1 : $offset;
$self->new(@{$self}[$offset - $amount .. $offset]);
my $end = $#{$self};
{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$amount = $amount->get_value;
$amount = $end > ($amount - 1) ? $amount - 1 : $end;
}
$self->new(@{$self}[$end - $amount .. $end]);
}

sub take_left {
my ($self, $amount) = @_;

$amount = $#{$self} > ($amount->get_value - 1) ? $amount->get_value - 1 : $#{$self};
my $end = $#{$self};
{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$amount = $amount->get_value;
$amount = $end > ($amount - 1) ? $amount - 1 : $end;
}
$self->new(@{$self}[0 .. $amount]);
}

Expand Down Expand Up @@ -1371,7 +1437,12 @@ package Sidef::Types::Array::Array {
sub rotate {
my ($self, $num) = @_;

$num = $num->get_value % ($#{$self} + 1);
{
local $Sidef::Types::Number::Number::GET_PERL_VALUE = 1;
$num = $num->get_value;
}

$num %= ($#{$self} + 1);
return $self->new(@{$self}) if $num == 0;

# Surprisingly, this is slower:
Expand Down
66 changes: 66 additions & 0 deletions scripts/RosettaCode/reduced_row_echelon_form.sf
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/ruby

#
## http://rosettacode.org/wiki/Reduced_row_echelon_form
#

func rref (Array m) {
m.is_empty && return;
var (lead, rows, cols) = (0, m.len, m[0].len);

rows.range.each { |r|
lead >= cols && return m;
var i = r;

while (!m[i][lead]) {
++i == rows || next;
i = r;
++lead == cols && return m;
}

m[i, r] = m[r, i];
var lv = m[r][lead];
m[r] = (m[r] »/» lv);

rows.range.each { |n|
n == r && next;
m[n] = (m[n] »-« (m[r] «*« m[n][lead]))
}
++lead;
}
return m
}

func say_it (message, array) {
say "\n#{message}";
array.each { |row|
say row.map { |n| " %5s" % n }.join
}
}

var M = [
[ # base test case
[ 1, 2, -1, -4 ],
[ 2, 3, -1, -11 ],
[ -2, 0, -3, 22 ],
],
[ # mix of number styles
[ 3, 0, -3, 1 ],
[ .5, 3/2, -3, -2 ],
[ .2, 4/5, -1.6, .3 ],
],
[ # degenerate case
[ 1, 2, 3, 4, 3, 1],
[ 2, 4, 6, 2, 6, 2],
[ 3, 6, 18, 9, 9, -6],
[ 4, 8, 12, 10, 12, 4],
[ 5, 10, 24, 11, 15, -4],
],
];

M.each { |matrix|
var rat_matrix = matrix.map{.map{.to_r}};
say_it('Original Matrix', rat_matrix);
say_it('Reduced Row Echelon Form Matrix', rref(rat_matrix));
say '';
}

0 comments on commit 5e94052

Please sign in to comment.