perl | Subrutinas recursivas

Requisito previo: Recursividad en Perl
Recursivo significa pertenecer o usar una regla o procedimiento que se puede aplicar repetidamente . Es el proceso de definir una función o calcular un número mediante la aplicación repetida de un algoritmo. Subrutina recursiva es un tipo de subrutina que se llama a sí misma como parte de su ejecución o está en un ciclo potencial de llamadas a funciones. Perl nos brinda la flexibilidad de usar subrutinas de forma iterativa y recursiva. 
Un ejemplo simple que muestra el uso de la subrutina recursiva en Perl sería calcular el factorial de un número.
Ejemplo :
 

Perl

#!/usr/bin/perl
   
# Perl Program to calculate Factorial 
sub factorial
{
       
my $n = $_[0];
   
# checking if that value is 0 or 1
if ($n == 0 || $n == 1)
{
    return 1;
}
   
# Recursively calling the function with the next value
# which is one less than current one
else
{
    return $n * factorial($n - 1);
}
}
   
# Driver Code
$n = 7;
   
# Function call and printing result after return
print "Factorial of a number $n is ", factorial($n);
Producción: 

Factorial of a number 7 is 5040

 

Recorriendo un árbol de directorio

Atravesar un árbol de directorios significa iterar o imprimir cada archivo y subdirectorio dentro de un directorio raíz. El árbol de directorios es una representación de los subdirectorios y archivos dentro de los subdirectorios y otros archivos dentro del directorio en forma de árbol que indica la relación padre-hijo entre estos directorios y los archivos respectivos. 
Tanto Unix como WindowsLos sistemas organizan los directorios de archivos en una estructura de árbol. Aunque en Perl, atravesar un árbol de directorios o recorrer un árbol de directorios se puede hacer tanto de forma iterativa como recursiva, a menudo usamos el último cuando la cantidad de archivos o subdirectorios dentro de nuestra carpeta raíz es muy grande. Esto se debe a la rapidez y la menor cantidad de líneas de código escritas en una función recursiva en comparación con una iterativa. El último se utiliza cuando el número correspondiente de archivos es menor. 
Usaremos File::Find para recorrer el sistema de archivos de forma iterativa y recopilar los nombres de los archivos. 
 

Sintaxis: 
use Archivo::Buscar; 
find(\&buscado, @directories_to_search); 
sub buscado {…}
use File::Find; 
buscarprofundidad(\&buscado, @directorios_para_buscar); 
sub buscado {…}
use File::Find; 
find({ buscado => \&procesar, seguir => 1 }, ‘.’); 
 

Ejemplo : 
 

Perl

#!/usr/bin/perl
use strict;
use warnings;
     
use File::Find::Rule;
use File::Basename qw(basename);
     
my $loc = "C:\Users\GeeksForGeeks";
my $file = 'final.txt';
my $expected = <STDIN>;
chomp $expected;
     
open(my $fh, '<', $expected) or
die "Could not open '$expected' $!\n";
 
open(my $out, '>', $file) or
die "Could not open '$file' $!\n";
     
my @paths = File::Find::Rule->file->name('*.pdf')->in($loc);
my @files = map { lc basename $_ } @paths;
my %case = map { $_ => 1 } @files;
     
print $out "This file has been copied from ($loc)$file:\n";
while (my $name = <$fh>)
{
    chomp $name;
    if ($case{lc $name})
    {
        print "$name found\n";
    }
    else
    {
        print $out "$name\n";
    }
}
close $out;
close $fh;

Salida: el archivo de origen se copia en el archivo de destino 
 

En la próxima sección, discutiremos el recorrido recursivo del directorio raíz.
 

Atravesar recursivamente un árbol de directorios

El problema con la solución iterativa de recorrido, además de su baja velocidad y más líneas de código, es el hecho de que todos los subdirectorios dentro del directorio raíz deben tener la misma orientación y la misma cantidad de archivos dentro de ellos. De lo contrario, el recorrido puede convertirse en una tarea compleja. La solución recursiva juega un mejor papel en la solución del problema con la solución iterativa. 
Ejemplo (recursivo): 
 

Perl

#!/usr/bin/perl
 
# Perl recursive Program to walk
# through a directory tree
use strict;
use warnings;
use 5.010;
 
my $loc = shift || '.';
 
# Calling walk subroutine with
# the location of the root directory
walk($loc);
 
# Subroutine definition
sub walk
{
    my ($case) = @_;
 
    # If case is not a directory itself
    return if not -d $case;
     
    # If case is a directory
    opendir my $dh, $case or die;
 
    while (my $sub = readdir $dh)
    {
        next if $sub eq '.' or $sub eq '..';
        say "$case/$sub";
        walk("$case/$sub");
    }
    close $dh;
    return;
}

Producción :
 

El código anterior le permitirá recorrer cada archivo en el directorio raíz y todos los subdirectorios presentes en el directorio raíz junto con los archivos y directorios dentro de estos subdirectorios.
 

Enfoque de arriba hacia abajo

El enfoque de arriba hacia abajo básicamente divide un problema o algoritmo complejo en múltiples partes más pequeñas (módulos) . Estos módulos se dividen aún más hasta que el módulo resultante es un programa que no se puede descomponer más. 
Aquí, primero inicializamos una variable llamada $case que mantiene el archivo o el directorio que se está iterando o repitiendo. Entonces, si es un archivo , entonces la función simplemente imprime su nombre y pasa al siguiente archivo o directorio o si el caso $es un directorio, luego vuelve a llamar a la subrutina con la ubicación del directorio como la ubicación del directorio actual y luego recorre todos los archivos y subdirectorios dentro de ese directorio. Después de completar la función interna, el puntero regresa a la ubicación del directorio externo e imprime su nombre y luego se mueve al siguiente archivo o al directorio presente en el directorio raíz. Este es en realidad un enfoque de arriba hacia abajo típico que se usa en Perl para atravesar o caminar sobre un árbol de directorios.
Ejemplo : 
 

Perl

use strict;
use warnings;
use 5.010;
 
my $loc = shift || '.';
 
walk($loc);
 
sub walk
{
    my ($case) = @_;
     
    say $case;
    return if not -d $case;
    opendir my $dh, $case or die;
    while (my $sub = readdir $dh)
    {
        next if $sub eq '.' or $sub eq '..';
 
        walk("$case/$sub");
    }
    close $dh;
    return;
}

Producción : 
 

El código explicado en la sección Atravesar recursivamente un árbol de directorios es un ejemplo del enfoque de arriba hacia abajo que se usa en Perl.
 

Nota: la imagen de salida anterior muestra una pequeña parte de la salida completa, ya que hay muchos archivos y subdirectorios dentro del directorio raíz. Este código funciona bien para carpetas y directorios con una pequeña cantidad de subdirectorios.

Función recursiva

Una función recursiva tiene la siguiente forma general: 
 

Función (argumentos) {
si es un caso simple, devuelve el valor simple // caso base / condición de parada; 
de lo contrario, llame a la función con una versión más simple del problema 

 

Ejemplo :
 

Perl

#!/usr/bin/perl
 
# Perl Program to calculate Factorial
sub myfunc
{
    my $n = $_[0];
     
    # checking if that value is
    # greater than 0 or not
    if ($n <= 0)
    {
        print "Now, You are on GFG portal.\n";
    }
     
    # Recursively calling function with
    # the next value which is one less
    # than current one
    else
    {
        print "$n\n";
        myfunc($n - 1);
    }
}
 
# Driver Code
 
# Function call
myfunc(3);

Producción: 
 

Para que una función recursiva deje de llamarse a sí misma, necesitamos algún tipo de condición de parada. Si no es el caso base, entonces simplificamos nuestro cálculo usando la fórmula general. Una función recursiva tiene dos partes principales. El primero verifica alguna condición y regresa si se cumplió esa condición. Esto se denomina condición de detención o condición de parada . Luego, en algún punto posterior de la función, se llama a sí misma con un conjunto de parámetros diferente al que se llamó anteriormente.
 

¿Por qué se prefiere la recursión a la iteración?

  1. Viene con los aspectos positivos de escribir un código corto más limpio y simple.
  2. También es eficiente en términos de tiempo si se usa con memorización.
  3. Se desempeña mejor en la resolución de problemas basados ​​en estructuras de árbol.

Publicación traducida automáticamente

Artículo escrito por BhavikBothra y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *