summaryrefslogtreecommitdiff
path: root/t/op/recurse.t
blob: 7626af9a8d1dcbdf8198d653ff8532e26acfadd8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!./perl

#
# test recursive functions.
#

BEGIN {
    chdir 't' if -d 't';
    require "./test.pl";
    set_up_inc(qw(. ../lib));
}

plan(tests => 28);

use strict;

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 : fibonacci($_[0] - 2) + fibonacci($_[0] - 1);
}

# Highly recursive, highly aggressive.
# Kids, don't 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 {
    $_[1] < $_[0] ?
	takeuchi(takeuchi($_[0] - 1, $_[1], $_[2]),
		 takeuchi($_[1] - 1, $_[2], $_[0]),
		 takeuchi($_[2] - 1, $_[0], $_[1]))
	    : $_[2];
}

is(gcd(1147, 1271), 31, "gcd(1147, 1271) == 31");

is(gcd(1908, 2016), 36, "gcd(1908, 2016) == 36");

is(factorial(10), 3628800, "factorial(10) == 3628800");

is(factorial(factorial(3)), 720, "factorial(factorial(3)) == 720");

is(fibonacci(10), 89, "fibonacci(10) == 89");

is(fibonacci(fibonacci(7)), 17711, "fibonacci(fibonacci(7)) == 17711");

my @ack = qw(1 2 3 4 2 3 4 5 3 5 7 9 5 13 29 61);

for my $x (0..3) { 
    for my $y (0..3) {
	my $a = ackermann($x, $y);
	is($a, shift(@ack), "ackermann($x, $y) == $a");
    }
}

my ($x, $y, $z) = (18, 12, 6);

is(takeuchi($x, $y, $z), $z + 1, "takeuchi($x, $y, $z) == $z + 1");

{
    sub get_first1 {
	get_list1(@_)->[0];
    }

    sub get_list1 {
	return [curr_test] unless $_[0];
	my $u = get_first1(0);
	[$u];
    }
    my $x = get_first1(1);
    ok($x, "premature FREETMPS (change 5699)");
}

{
    sub get_first2 {
	return get_list2(@_)->[0];
    }

    sub get_list2 {
	return [curr_test] unless $_[0];
	my $u = get_first2(0);
	return [$u];
    }
    my $x = get_first2(1);
    ok($x, "premature FREETMPS (change 5699)");
}

{
    local $^W = 0; # We do not need recursion depth warning.

    sub sillysum {
	return $_[0] + ($_[0] > 0 ? sillysum($_[0] - 1) : 0);
    }

    is(sillysum(1000), 1000*1001/2, "recursive sum of 1..1000");
}

# check ok for recursion depth > 65536
{
    my $r;
    eval { 
	$r = runperl(
		     nolib => 1,
		     stderr => 1,
		     prog => q{$d=0; $e=1; sub c { ++$d; if ($d > 66000) { $e=0 } else { c(); c() unless $d % 32768 } --$d } c(); exit $e});
    };
  SKIP: {
      skip("Out of memory -- increase your data/heap?", 2)
	  if $r =~ /Out of memory/i;
      is($r, '', "64K deep recursion - no output expected");
      is($?, 0, "64K deep recursion - no coredump expected");
  }
}