use v6-alpha;
use Test;
plan 13;
# Mostly copied from Perl 5.8.4 s t/op/recurse.t
sub gcd {
return gcd(@_[0] - @_[1], @_[1]) if (@_[0] > @_[1]);
return gcd(@_[0], @_[1] - @_[0]) if (@_[0] < @_[1]);
@_[0];
}
sub factorial {
@_[0] < 2 ?? 1 !! @_[0] * factorial(@_[0] - 1);
}
sub fibonacci {
@_[0] < 2 ?? 1 !! &?ROUTINE(@_[0] - 2) + &?ROUTINE(@_[0] - 1);
}
# Highly recursive, highly aggressive.
# Kids, do not try this at home.
#
# For example ackermann(4,1) will take quite a long time.
# It will simply eat away your memory. Trust me.
sub ackermann {
return @_[1] + 1 if (@_[0] == 0);
return ackermann(@_[0] - 1, 1) if (@_[1] == 0);
ackermann(@_[0] - 1, ackermann(@_[0], @_[1] - 1));
}
# Highly recursive, highly boring.
sub takeuchi {
# for the script failure here, see Parser.hs:589
@_[1] < @_[0] ??
takeuchi(takeuchi(@_[0] - 1, @_[1], @_[2]),
takeuchi(@_[1] - 1, @_[2], @_[0]),
takeuchi(@_[2] - 1, @_[0], @_[1]))
!! @_[2];
}
ok(gcd(1147, 1271) == 31);
ok(gcd(1908, 2016) == 36);
ok(factorial(10) == 3628800);
ok(factorial(factorial(3)) == 720);
ok(fibonacci(10) == 89);
# ok(fibonacci(fibonacci(7)) == 17711);
# takes too long
# skip("Takes too long to wait for");
# dunno if these could use some shorter/simpler sub names, but I'm not
# thinking of anything offhand.
# what the silly sub names mean:
# - 'mod' means it makes a local copy of the variable, modified as
# necessary
# - 'nomod' means it passes the modified value directly to the next call
# - 'named' means it uses named parameters
# - 'unnamed' means it uses @_ for parameters
sub countup_nomod_unnamed {
my ($num) = @_;
return $num if $num <= 0;
return countup_nomod_unnamed($num-1), $num;
}
sub countdown_nomod_unnamed {
my ($num) = @_;
return $num if $num <= 0;
return $num, countdown_nomod_unnamed($num-1);
}
sub countup_nomod_named ($num) {
return $num if $num <= 0;
return countup_nomod_named($num-1), $num;
}
sub countdown_nomod_named ($num) {
return $num if $num <= 0;
return $num, countdown_nomod_named($num-1);
}
sub countup_mod_unnamed {
my ($num) = @_;
my $n = $num - 1;
return $num if $num <= 0;
return countup_mod_unnamed($n), $num;
}
sub countdown_mod_unnamed {
my ($num) = @_;
my $n = $num - 1;
return $num if $num <= 0;
return $num, countdown_mod_unnamed($n);
}
sub countup_mod_named ($num) {
my $n = $num - 1;
return $num if $num <= 0;
return countup_mod_named($n), $num;
}
sub countdown_mod_named ($num) {
my $n = $num - 1;
return $num if $num <= 0;
return $num, countdown_mod_named($n);
}
is( countup_nomod_named(5).join(""), "012345", "recursive count up: named param, no modified value");
is(countdown_nomod_named(5).join(""), "543210", "recursive count down: named param, no modified value");
is( countup_nomod_unnamed(5).join(""), "012345", "recursive count up: unnamed param, no modified value");
is(countdown_nomod_unnamed(5).join(""), "543210", "recursive count down: unnamed param, no modified value");
is( countup_mod_named(5).join(""), "012345", "recursive count up: named param, modified value");
is(countdown_mod_named(5).join(""), "543210", "recursive count down: named param, modified value");
is( countup_mod_unnamed(5).join(""), "012345", "recursive count up: unnamed param, modified value");
is(countdown_mod_unnamed(5).join(""), "543210", "recursive count down: unnamed param, modified value");