Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

How to hash without the hash- basic

by baxy77bax (Deacon)
on Oct 26, 2011 at 12:55 UTC ( [id://933893]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

I'm in a need for some assistance. The thing is, I would need to write a counter that works in the same way as this one:

my %hash; my @array = qw(1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34); foreach (@array){ $hash{$_}++; }
and figure out which of the numbers in the array appear only one time, but i cannot use the built-in hash data structure.
so the result that i'm expecting would be
55,22,34 are the numbers that appear only once
Oh, yes and i have to stick to only basic conditionals and iterators, meaning no greping or mapping. however sorting is allowed. I was thinking of just sreating an array and then using indexes as hash keys but then a lot of positions would not be initialized(using space for nothing) and I would need to make 55 instead of 16 steps to get to my result.

Can anyone make a creative suggestion on how to do this in more effective and economic way ?

Thank you

baxy

Replies are listed 'Best First'.
Re: How to hash without the hash- basic
by moritz (Cardinal) on Oct 26, 2011 at 13:25 UTC

    What kind of surreal contest is that?

    Anyway, a rather quick solution would be to sort, and then look through the array, checking if the current element is identical to the previous or next. If no, it's unique.

    Update: now with code:

    # intentionally no warnings used. my @array = qw(1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34); @array = sort @array; my $prev; for (0..$#array) { my $i = $array[$_]; print "$i\n" if $i != $prev && $i != $array[$_+1]; $prev = $i; }

    Second update: Another idea. This one is O(n^2) in theory, but the regex engine being fast makes up for that in practise for low-ish values of n:

    my @array = qw(1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34); my $template = join ' ', @array; study $template; for (@array) { my @matches = ($template =~ /\b$_\b/g); print "$_\n" if 1 == @matches; }
      use v6; my @array = < 1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34 >; my @y = @array.classify({$_})\ .categorize({ .value.elems==1 || Nil }).[0].value».key; say "{@y.sort.join(',')} are the numbers that appear only once" if @y; #my @y = @array.classify({$_}).grep({ .value.elems == 1 })».key;
Re: How to hash without the hash- basic
by mrstlee (Beadle) on Oct 26, 2011 at 16:59 UTC
    Is using the symbol table cheating?
    use Data::Dumper; my @array = qw(1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34); my @uniqs; foreach (@array) { ${"uniq_$_"} and next; ${"uniq_$_"} = 1; push @uniqs, $_; } print Dumper \@uniqs;
      Is using the symbol table cheating?

      No. Asking for an answer on PerlMonks is cheating. (++ btw)

Re: How to hash without the hash- basic
by BrowserUk (Patriarch) on Oct 26, 2011 at 21:43 UTC

    Simples!

    #! perl -slw use strict; my %hash; my @array = qw(1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34); my $vec1 = my $vec2 = ''; for ( @array ) { if( vec( $vec1, $_, 1 ) ) { vec( $vec2, $_, 1 ) = 1; } else { vec( $vec1, $_, 1 ) = 1; } } $vec2 .= chr(0) x ( length( $vec1 ) - length( $vec2 ) ); $vec1 &= ~$vec2; vec( $vec1, $_, 1 ) and print for 0 .. length( $vec1 ) * 8; __END__ C:\test>933893 22 34 55

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How to hash without the hash- basic
by GrandFather (Saint) on Oct 26, 2011 at 20:45 UTC

    No need for sort:

    use warnings; use strict; use 5.010; package NotAHash; sub new { my ($class) = @_; return bless [], $class; } sub add { my ($self, $str) = @_; my $parent = $self; $parent = $parent->[substr $str, 0, 1, ''] //= [] while length $st +r; $parent->[10]++; } sub keys { my ($self) = @_; my @keys; for my $elementIdx (0 .. 9) { next if ! defined $elementIdx || ! defined $self->[$elementIdx +]; my $element = $self->[$elementIdx]; my @subKeys = NotAHash::keys ($element) if @$element; push @keys, "$elementIdx$_" for @subKeys; push @keys, $elementIdx if $element->[10]; } return @keys; } sub value { my ($self, $key) = @_; my $parent = $self; $parent = $parent->[substr $key, 0, 1, ''] //= [] while length $ke +y; return $parent->[10]; } package main; my @array = qw(1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34); my $notHash = NotAHash->new(); $notHash->add($_) for @array; my @singles; my @keys = $notHash->keys(); $notHash->value($_) == 1 && push @singles, $_ for $notHash->keys(); print join (', ', @singles), " are the numbers that appear only once\ +n";

    Prints:

    22, 34, 55 are the numbers that appear only once
    True laziness is hard work
Re: How to hash without the hash- basic
by Anonymous Monk on Oct 26, 2011 at 13:15 UTC

    <contradictor>

    but i cannot use the built-in hash data structure

    Sure you can ;)

    Oh, yes and i have to stick to only basic conditionals and iterators

    No you don't ;)

    Can anyone make a creative suggestion on how to do this in more effective and economic way ?

    use a hash ;)

    </contradictor>

    substr

    sub getNth { my $nth = shift; my $index = $width * $nth; substr $_[0], $index, $width; }

      OP smells like a challenge or homework so perhaps read it again after some substitutions?

      s/cannot/am not allowed to/
        and
      s/have to stick to/am allowed to use only/
Re: How to hash without the hash- basic
by i5513 (Pilgrim) on Oct 26, 2011 at 14:00 UTC
    Not a good solution, but .. are matching allowed?, if yes. It is not cheaper and not more effective, but is pure perl :P :
    @array = qw(1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34); $cad=join (" ",@array); for (@array) { push @uniq, $_ if ($cad !~ /((\A| )($_)( |\Z)).*$_( |\Z)/); } print join (",",@uniq),"\n";
Re: How to hash without the hash- basic
by Neighbour (Friar) on Oct 26, 2011 at 14:55 UTC
    But map is easily constructed using a for-loop and grep is an equal-operator away from map, which renders the requirement not to use grep or map moot. Unless you also forbid using loops, but that would make the assignment quite bothersome.
Re: How to hash without the hash- basic
by Anonymous Monk on Oct 26, 2011 at 19:50 UTC
    my @array = qw(1 3 4 55 4 3 4 22 1 3 4 3 2 2 3 34); say for "@array-@array" =~ /\b(\d+)\b(?=.*-)(?!.+\b\1\b.+\b\1\b)/g;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://933893]
Approved by planetscape
Front-paged by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (3)
As of 2024-04-25 20:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found