Re: Better way of writing "find the missing number(s)"
by 1nickt (Canon) on Apr 03, 2017 at 18:31 UTC
|
Hi pritesh_ugrankar.
A hash is usually the best-suited tool for finding out whether elements in one list are in another. Add a key to the hash for each element in the list you are checking, then see if a key exists for each element in the list to be matched.
use strict; use warnings; use feature 'say';
my @x = ( -2, 2, 3, 8, 10 );
my %y = map { $_ => 1 } @x;
say "missing: $_" for grep { not exists $y{ $_ } } ( -2 .. 10 );
perl 1186862.pl
missing: -1
missing: 0
missing: 1
missing: 4
missing: 5
missing: 6
missing: 7
missing: 9
Hope this helps!
The way forward always starts with a minimal test.
| [reply] [d/l] [select] |
|
|
Hey Nick,
I had only a few minutes to play with this when it first came up, but I couldn't accomplish what I wanted with the time I had. What I did have was very similar. That said, you've hard-coded your array when doing the grep(), which probably isn't realistic in production, and it's a bit outside of what OP was after. To do it out of order and without hardcoding, an extra sort needs to be put in place. It could be done inline, but this makes it a bit more clear I think:
use strict;
use warnings;
use feature 'say';
my @x = ( -2, 3, 2, 10, 15, 8 );
my %y = map { $_ => 1 } @x;
@x = sort {$a <=> $b} @x;
say "missing: $_" for grep { ! exists $y{$_} } $x[0] .. $x[-1];
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
|
|
| [reply] |
Re: Better way of writing "find the missing number(s)"
by tybalt89 (Monsignor) on Apr 03, 2017 at 19:34 UTC
|
#!/usr/bin/perl
# http://perlmonks.org/?node_id=1186862
use strict;
use warnings;
my @arr = (19,17,22,23,24,15,16,25..35);
my ($low, $high) = (sort {$a <=> $b} @arr)[0, -1];
my @missing = 0 .. $high;
@missing[@arr] = ('') x @arr;
print "missing numbers are @missing[$low .. $high]\n";
| [reply] [d/l] |
|
|
| [reply] |
|
|
| [reply] |
Re: Better way of writing "find the missing number(s)"
by Cristoforo (Curate) on Apr 03, 2017 at 18:15 UTC
|
#!/usr/bin/perl
use strict;
use warnings;
use Set::IntSpan;
my @arr = (19,17,22,23,24,15,16,25..35);
my $set = Set::IntSpan->new(\@arr);
print join ' ', $set->holes->elements;
Prints:
18 20 21 | [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
Re: Better way of writing "find the missing number(s)"
by tybalt89 (Monsignor) on Apr 03, 2017 at 20:40 UTC
|
#!/usr/bin/perl
# http://perlmonks.org/?node_id=1186862
use strict;
use warnings;
my @arr = (19,17,22,23,24,15,16,25..35);
my @sorted = sort {$a <=> $b} @arr;
my @missing = map { $sorted[$_ - 1] + 1 .. $sorted[$_] - 1 } 1 .. $#so
+rted;
print "missing numbers are @missing\n";
| [reply] [d/l] |
|
|
| [reply] [d/l] |
Re: Better way of writing "find the missing number(s)"
by tybalt89 (Monsignor) on Apr 03, 2017 at 21:26 UTC
|
There hasn't been a regex solution yet, so here's one as a one-liner :)
perl -le '"@{[sort{$a<=>$b}19,17,22,23,24,15,16,25..35]}"=~/\b\d+ (?=(
+\d+))(?{push@a,$&+1..$1-1})(*F)/;print"@a"'
| [reply] [d/l] |
Re: Find the missing number
by oiskuu (Hermit) on Apr 04, 2017 at 18:18 UTC
|
Numbers 1..n, one missing.
#! /usr/bin/perl -wl
use List::Util qw( sum );
my @arr = (1..3,5..7);
print +- sum -1-@arr .. -1,@arr;
| [reply] [d/l] |
|
|
| [reply] |
|
|
... a mathematical solution hiding in plain sight.
Perhaps better to say "hiding in obscurity." From the OP (emphasis added):
... find a missing number if in a list of numbers. ...
...
my @arr = (19,17,22,23,24,15,16,25..35);
...
But the list in the code example clearly has more than one missing number. See also the (current) thread title. I think the goose chase, although wild, was justified.
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
|
|
|
use List::Util qw(sum);
my @arr=(1..3,5..7);
print +(1+@arr)*(2+@arr)/2 - sum(@arr);
update: clarification = use 1+ and 2+ here because an element is missing from @arr | [reply] [d/l] [select] |
Re: Better way of writing "find the missing number(s)" -- oneliner
by Discipulus (Canon) on Apr 03, 2017 at 20:48 UTC
|
Hello pritesh_ugrankar,
you got easier answers, pardon me for the following (long)oneliner:
perl -E "@sr=sort{$a<=>$b}@ar=(5..7,8,10,-3);map{$h{$_}++}$sr[0]..$sr[
+-1],@ar;say for grep{$h{$_}==1}sort{$a<=>$b} keys %h"
-2
-1
0
1
2
3
4
9
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] |
Re: Better way of writing "find the missing number(s)"
by salva (Canon) on Apr 04, 2017 at 06:48 UTC
|
| [reply] |
|
|
ah! given the above task the oneliner is much simpler!
perl -E "@ar=(1..3,5,6,7);$h{$_}++for$ar[0]..$ar[-1];delete$h{$_}for@a
+r;print keys %h"
4
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] |
|
|
perl -E '\@h{1..(@a=(1..3,5,6,7))+1};delete@h{@a};say%h'
| [reply] [d/l] |
|
|
perl -e'$_>++$i&&die"$i\n"for 1..3,5,6,7'
| [reply] [d/l] |
|
|
perl -E '@b=0..(@a=(1..3,5,6,7))+1;@b[0,@a]="";say@b'
| [reply] [d/l] |
|
|
| [reply] [d/l] |
Re: Better way of writing "find the missing number(s)"
by pritesh_ugrankar (Monk) on Apr 04, 2017 at 11:22 UTC
|
Hi Monks,
Thank you for your responses. Indeed, Perl is powerful and flexible.
Thinkpad T430 with Ubuntu 16.04.2 running perl 5.24.1 thanks to plenv!!
| [reply] [d/l] |
Re: Better way of writing "find the missing number(s)"
by tybalt89 (Monsignor) on Apr 04, 2017 at 15:57 UTC
|
Using the updated problem (numbers starting at 1 in order, only one missing), here's something completely DIFFerent :)
#!/usr/bin/perl -l
# http://perlmonks.org/?node_id=1186862
use strict;
use warnings;
use Algorithm::Diff qw(traverse_sequences);
my @arr = (1..3,5,6,7);
traverse_sequences( \@arr, [ 1 .. @arr + 1 ],
{ DISCARD_B => sub { print "missing: ", 1 + $_[1] } } );
| [reply] [d/l] |