Panfi96 has asked for the wisdom of the Perl Monks concerning the following question:

Hi :D I'm having troubles with my set operations. After making the junction of the sets, it says that there's an uninitialized value in numeric lt <<> at Conjuntos def line 174, <STDIN> line 9.Can somebody help me please?

#!/usr/bin/perl use 5.010; use strict; use warnings; sub busca_binaria_rec{ my ($conjunto,$elemento,$primero,$cuantos)=@_; my $izquierda=$primero; my $derecha=$cuantos; my $medio=($izquierda+$derecha)>>1; if($izquierda>$derecha){ return (-1); } else{ if((@{$conjunto}[$medio])==$elemento){ return($medio); } if(@{$conjunto}[$medio]<$elemento){ $medio+=1; busca_binaria_rec((\@{$conjunto}),$elemento,$medio,$derecha); }else{ $medio-=1; busca_binaria_rec((\@{$conjunto}),$elemento,$izquierda,$medio) +; } } } #pido el tamaño del conjunto 1, lo declaro y lleno (también el que + usaré para guardar en binario) my ($cuantos1,$cuantos2,$cuantosU,$elemento,$tamanioreal, $conj1bi +n,$conj2bin,$interbin,$cuantos_inte); $conj1bin=0; $conj2bin=0; $elemento=0; print "Escribe el tamanio del conjunto 1 (maximo 65535)\n"; $cuantos1=<STDIN>; my @conjunto1; #pedir_conjunto(\@conjunto1,$cuantos1); print "\nIngresa los $cuantos1 numeros del conjunto seguidos por u +n enter :) \n"; for(my $i=0;$i<$cuantos1;$i++) { $conjunto1[$i]=<STDIN>; } print "\n"; #ordenar(\@conjunto1,$cuantos1); #ordenamos conjunto para hacer má +s facil la vida my $temp=0; for(my $e=0;$e<$cuantos1;$e++){ for(my $j=0;$j<$cuantos1;$j++){ if($conjunto1[$e]<$conjunto1[$j]){ $temp=$conjunto1[$e]; $conjunto1[$e]=$conjunto1[$j]; $conjunto1[$j]=$temp; } } } #pedimos el tamaño,declaramos y llenamos el 2do conjunto print"\nEscribe el tamanio del conjunto 2(maximo 65535)\n"; $cuantos2=<STDIN>; my @conjunto2; #pedir_conjunto(\@conjunto2,$cuantos2); print "\nIngresa los $cuantos2 numeros del conjunto seguidos por u +n enter :) \n"; for(my $f=0;$f<$cuantos2;$f++) { $conjunto2[$f]=<STDIN>; } print "\n"; #ordenar(\@conjunto2,$cuantos2);#lo ordeno para hacer más sencilla + la búsqueda my $tempo=0; for(my $k=0;$k<$cuantos2;$k++){ for(my $j=0;$j<$cuantos2;$j++){ if($conjunto2[$k]<$conjunto2[$j]){ $tempo=$conjunto2[$k]; $conjunto2[$k]=$conjunto2[$j]; $conjunto2[$j]=$tempo; } } } #una vez que sabemos el tamaño de los conjuntos 1 y 2, vamos a dec +larar el conjunto universo y el vector donde guardaremos la intersecc +ión $cuantosU=$cuantos1+$cuantos2; if($cuantos1<$cuantos2?1:0){#el tamaño máximo de la intersección e +s el tamaño del conjunto más pequeño $cuantos_inte=$cuantos1; } else{ $cuantos_inte=$cuantos2; } my (@universo,@internum); #$tamanioreal=(crear_universo(\@universo,\@conjunto1,$cuantos1,\@c +onjunto2,$cuantos2,$cuantosU)); #crea el conjunto universo y nos dice + el tamaño real para que no imprima basura my $cont=0; for(my $e=0;$e<$cuantos1;$e++){ $universo[$e]=$conjunto1[$e];#meto todos los datos del 1er con +junto en el universo } for(my $n=0;$n<$cuantos2;$n++){ $elemento=$conjunto2[$n]; if(busca_binaria_rec(\@universo,$elemento,0,$cuantos1-1)==-1){ +#veo si los datos del 2do conjunto están, y si no, los agrego $universo[$cuantos1+$cont]=$elemento; $cont++; } } $tamanioreal=($cuantos1+$cont);#regresa el tamaño total del un +iverso para evitar imprimir basura #ordenar my $tempor=0; for(my $h=0;$h<$tamanioreal;$h++){ for(my $j=0;$j<$tamanioreal;$j++){ if($universo[$h]<$universo[$j]){ $tempor=$universo[$h]; $universo[$h]=$universo[$j]; $universo[$j]=$tempor; } } } print"\nLa union de los conjuntos es:\n"; #imprimir_conjunto(\@universo,$tamanioreal); #imprime la unión del + conjunto print"\n"; for(my $u=0;$u<$tamanioreal;$u++) { print "$universo[$u] \t"; } print"\n"; #ahora vemos la intersección con el universo de cada conjunto uno +en bits #$conj1bin = phi(\@universo,$tamanioreal,\@conjunto1,$cuantos1,$co +nj1bin); $conj1bin=0; for(my $e=0;$e<$tamanioreal;$e++){ $conj1bin<<=1; for(my $p=0;$p<$cuantos1;$p++){ if($universo[$e]==$conjunto1[$p]){ $conj1bin|=1; $p=$cuantos1; } } } #$conj2bin = phi(\@universo,$tamanioreal,\@conjunto2,$cuantos2,$co +nj2bin); $conj2bin=0; for(my $e=0;$e<$tamanioreal;$e++){ $conj2bin<<=1; for(my $m=0;$m<$cuantos2;$m++){ if($universo[$e]==$conjunto2[$m]){ $conj2bin|=1; $m=$cuantos2; } } } #ya que tenemos los conjuntos en binario, sacamos la intersección +entre ellos sobre bits :) $interbin=($conj1bin & $conj2bin); #aplicamos la función phi inversa :D ~(*u*)~ #$cuantos_inte=phi_inv(\@universo,$tamanioreal,\@internum,$cuantos +_inte,$interbin); my $m=0; my $corre=$interbin; for(my $n=$tamanioreal-1;$n>=0;$n--) { if(($corre&1)==1){ $internum[$m]=$universo[$n]; $m++; } $corre>>=1; } #ordenar((\@{$internum}),$cuantos_inte); $temp=0; for(my $q=0;$q<$cuantos_inte;$q++){ for(my $j=0;$j<$cuantos_inte;$j++){ if($internum[$q]<$internum[$j]){ $temp=$internum[$q]; $internum[$q]=$internum[$j]; $internum[$j]=$temp; } } } $cuantos_inte=$m; print "\nLa interseccion de los conjuntos es:\n"; #imprimir_conjunto(\@internum,$cuantos_inte); print"\n"; for(my $i=0;$i<$cuantos_inte;$i++) { print "$internum[$i] \t"; } print"\n"; #la resta de conj 1 y conj2 my $restbin=($conj1bin & ~$conj2bin); #$cuantos_inte=phi_inv(\@universo,$tamanioreal,\@internum,$cuantos +1,$restbin); my $g=0; $corre=$restbin; for(my $n=$tamanioreal-1;$n>=0;$n--) { if(($corre&1)==1){ $internum[$m]=$universo[$n]; $g++; } $corre>>=1; } #ordenar($internum),$cuantos1); $temp=0; for(my $i=0;$i<$cuantos1;$i++){ for(my $j=0;$j<$cuantos1;$j++){ if($internum[$i]<$internum[$j]){ $temp=$internum[$i]; $internum[$i]=$internum[$j]; $internum[$j]=$temp; } } } $cuantos_inte=$g; print"\nLa diferencia entre el conjunto1 y el conjunto2 es:\n"; #imprimir_conjunto(\@internum,$cuantos_inte); print"\n"; for(my $i=0;$i<$cuantos_inte;$i++) { print "$internum[$i] \t"; } print"\n";

Replies are listed 'Best First'.
Re: Set operations
by davido (Cardinal) on Dec 02, 2014 at 03:25 UTC

    This is a matter of simple debugging: Read the error message, look at the line in question, discover what variables are involved, put some warn statements here and there at places in your code where you believe the variables involved are being set or tested -- the warn statements should print the value of those variables, run your code, verify your assumptions.

    If the warning message seems cryptic, add "use diagnostics;" to the top of your script, and the warning will be explained to you in greater detail.

    Here's a trivial example of the "print statements" (or warn) style of debugging:

    my $counter = 0; warn "\$counter initialized to <<$counter>>\n"; while( $counter != 10 ) { warn "Entering while block. \$counter is <<$counter>>\n"; $counter++; warn "End of while block. \$counter is <<$counter>>\n"; } warn "Loop terminated. \$counter is <<$counter>>\n";

    This sort of drudgery may seem tedious. You could, alternatively, read perldebtut to learn how to use the Perl debugger. But for now, warn is all you need to discover where you're going wrong.

    You really don't need us to follow those steps for you. You need to learn how to do them yourself so that you don't need to rely on PerlMonks every time a surprise comes your way. Learning debugging techniques is an essential part of the practice of programming.


Re: Set operations
by GrandFather (Saint) on Dec 02, 2014 at 03:37 UTC

    So you pasted hundreds of lines of code which we can't run because you didn't supply any data, and the the error message you report can't be right because there is no numeric lt anywhere around the line you indicate.

    How about you reduce the code to the minimum needed to show the error and provide same test data the reproduces the issue. See I know what I mean. Why don't you? for some help in presenting your problem.

    Perl is the programming world's equivalent of English
Re: Set operations
by Loops (Curate) on Dec 02, 2014 at 03:27 UTC


    Your code actually works okay as long as you enter a number for each input. It's a little confusing because there are no prompts for each number in the set, just a blank line. If you happen to press [ENTER] instead of entering a number at any point, you'll get lots of errors.

    You will want to change your code to test every input made by the user to see if it is a valid number, and only add it to the set if so. If it is a bad input, loop around and ask again.

      Though he's probably not allowed to use CPAN in his course work, it's too bad. Because if he could, he would be able to use IO::Prompt::Tiny or IO::Prompt::Hooked to simplify the prompting for input. In fact, though it's like calling in the artillery when a fly swatter is needed, ExtUtils::MakeMaker is a core module, and comes with the prompt function.

      use ExtUtils::MakeMaker 'prompt'; my $value = prompt "Please enter something.", "asdf"; print "$value\n";

      The first argument is what to say to the user. The second argument is what default to assume if the user just hits enter (or if there's no terminal).