Re: get next higher number
by choroba (Cardinal) on Jun 11, 2018 at 16:50 UTC
|
Sort the values before you compare them to the argument. You can then safely return the first value that satisfies the condition:
#!/usr/bin/perl
use warnings;
use strict;
my @values = qw( 11673326 11673329 11673325 11673330 11673321 11673335
+ );
my @sorted = sort { $a <=> $b } @values;
sub next_higher {
my ($from) = @_;
for (@sorted) {
return $_ if $_ > $from;
}
return
}
use Test::More;
is next_higher(11673326), 11673329;
is next_higher(11673335), undef;
is next_higher(11673321), 11673325;
Or just remember the closest number so far (and handle the case where it's not yet defined):
#!/usr/bin/perl
use warnings;
use strict;
my $data_start = tell *DATA;
sub next_higher {
my ($from) = @_;
seek *DATA, $data_start, 0;
my $so_far;
while (<DATA>) {
chomp;
$so_far = $_ if $_ > $from && (! defined $so_far || $_ < $so_f
+ar);
}
return $so_far
}
use Test::More;
is next_higher(11673326), 11673329;
is next_higher(11673335), undef;
is next_higher(11673321), 11673325;
__DATA__
11673326
11673329
11673325
11673330
11673321
11673335
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: get next higher number
by Limbic~Region (Chancellor) on Jun 11, 2018 at 16:48 UTC
|
ovedpo15,
What you are trying to do is find an item in a list and then return the item that comes after it. That's relatively simple but you should be able to deal with things like unordered lists, duplicate items, etc. if those things matter. If you know you will always have an ordered list with unique entries - you could turn this into a binary search:
my @status;
while (<DATA>) {
chomp;
push @status, $_;
}
my $current = 11673326;
my $next = find_next_item($current, \@status);
die "'$current' is either not found or has no next item\n" if ! define
+d $next;
print "The next number after '$current' is '$next'\n";
sub find_next_item {
my ($item, $list) = @_;
my $next;
for my $idx (0 .. $#$list) {
if ($list->[$idx] eq $item) {
$next = $list->[$idx + 1] if $idx <= $#$list;
last;
}
}
return $next;
}
The code above is untested. I haven't coded for several years now but I think it is close.
| [reply] [Watch: Dir/Any] [d/l] |
Re: get next higher number
by hippo (Bishop) on Jun 11, 2018 at 18:11 UTC
|
$ perl -cw 1216404.pl
syntax error at 1216404.pl line 2, near "my "
1216404.pl had compilation errors.
Even if it did compile how would you know if it works since it produces no output? See How to ask better questions using Test::More and sample data
Where is the problem and how to solve it?
Line 1 is missing a trailing semi-colon. Add one.
Is there a better solution?
Almost certainly but that would depend on in which way you would want them to be better.
I prefer not to use any other functions or modules.
If this is your definition of "better" then I will gladly leave you to it.
Can I do it some how with regex?
It would be very illuminating to hear your reasoning for asking this. | [reply] [Watch: Dir/Any] [d/l] |
Re: get next higher number
by thanos1983 (Parson) on Jun 11, 2018 at 16:45 UTC
|
#!/usr/bin/env perl
use strict;
use warnings;
use List::Util 'min';
my @arr = ( 11673326,
11673329,
11673325,
11673330,
11673321,
11673335 );
print "Please insert a number:\n";
chomp(my $number = <>);
my $next_largest = min grep $_ > $number, @arr;
if(defined($next_largest)) {
print $next_largest."\n";
}
else {
print "undef\n";
}
__END__
$ perl test.pl
Please insert a number:
11673326
11673329
$ perl test.pl
Please insert a number:
11673321
11673325
$ perl test.pl
Please insert a number:
11673335
undef
Hope this helps, BR
Seeking for Perl wisdom...on the process of learning...not there...yet!
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: get next higher number
by pryrt (Abbot) on Jun 11, 2018 at 16:57 UTC
|
edit 1: whoops, I see that you wanted numerically next, not the next in the ordered data set. sorry. leave the rest in for historical purposes
edit 2: replace the my @status... line, so it meets your spec, and remove the unneeded sort when foreaching through the values to find each next value
Oh, good. Though there were other good answers between the time I started and when I went to write it up, so far, no one used my idea... Assuming there's only one instance of each data value (*), make a reverse mapping from value back to index
#/usr/bin/perl
#pm1216404
use warnings; use strict;
use 5.010; # for //
#my @status = map {chomp; $_} <DATA>; # use the chomp t
+o get rid of the newlines from the DATA right away
my @status = sort { $a <=> $b } map {chomp; $_} <DATA>; # edit 2 = sor
+t the status after you read and map it, so now
my %unmap = map { $status[$_] => $_ } 0..$#status; # makes a hash of
+$unmap{value} = index pairs
# use Data::Dumper; print Dumper \@status, \%unmap;
$|++;
foreach my $current ( @status ) { # edit 2 = remove the sort here, be
+cause it's sorted above
my $idx = $unmap{$current};
my $ni = defined $idx ? $idx+1 : undef;
my $next = defined $ni ? $status[$ni] : undef;
printf "current=%d, current's index=%s, next idx=%d, next value=%s
+\n", $current, $idx//'<undef>', $ni//'<undef>', $next//'<undef>';
}
__DATA__
11673326
11673329
11673325
11673330
11673321
11673335
*: if there were more than one instance, I think it would find the next after the _last_ instance
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: get next higher number
by Marshall (Canon) on Jun 11, 2018 at 20:18 UTC
|
Is this a homework question? If so, you should tell us that. You will still get help and we will understand how to better help you.
If this is not a homework question: Where do these numbers come from? What do they represent? How many numbers could there be? What is the maximum
range of the numbers? How important is speed of calculation vs storage space? - Yes, that is a complicated question, but this is a common programming tradeoff.
Knowing the answers to those basic questions and the overall context of your
application would, with a high probability, lead to a more efficient solution and a "better" answer.
You wrote; "I prefer not to use any other functions or modules." Well, if(looks_like_number($row) calls a function that is not
shown in your code.
Update: I don't see any Print statement in the original code. If there is no output, then any calculations are meaningless. | [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] [d/l] |
|
Nope its a task I was given at work. `looks_like_number` is already used a function in the code so I can use it, but *prefer not to add additional modules and functions* so I won't need to install them. P.S which university course teaches Perl in 2018? thank you for your time.
| [reply] [Watch: Dir/Any] |
|
Re: get next higher number
by AnomalousMonk (Archbishop) on Jun 11, 2018 at 19:34 UTC
|
Can I do it some how with regex?
As hippo has alluded, a regex approach would seem far from ideal. Howsoever, the following seems to work, but requires Perl version 5.10+ for the (?(condition)yes-pattern|no-pattern) construct (which embeds the experimental (?{ CODE }) feature; see Extended Patterns in perlre):
c:\@Work\Perl>perl -wMstrict -le
"use 5.010;
;;
use Test::More 'no_plan';
use Test::NoWarnings;
;;
my @values = qw(
11673326 11673329 11673325 11673330 11673321 11673335
);
;;
my $sorted_str = join ' ', sort { $a <=> $b } @values;
;;
sub next_higher {
local our ($from) = @_;
;;
return $1 if $sorted_str =~ m{
\b (\d+) \b
(?(?{ $from >= $^N }) (*FAIL))
}xms;
;;
return;
}
;;
is next_higher(11673326), 11673329;
is next_higher(11673335), undef;
is next_higher(11673321), 11673325;
done_testing;
"
ok 1
ok 2
ok 3
1..3
ok 4 - no warnings
1..4
I leave further testing to you :)
(NB: From, I believe, Perl version 5.18 on, the
local our ($from) = @_;
statement in the next_higher() function can be replaced with a more familiar lexical
my ($from) = @_;
statement and the regex will work properly; can't test this ATM.)
Update: When discussing Perl version dependency in the first paragraph, I should also have mentioned that (*FAIL) was introduced with 5.10 (see Special Backtracking Control Verbs in perlre). However, the effect of (*FAIL) is exactly duplicated by (?!) in pre-5.10 regexen, so (?(condition)yes-pattern|no-pattern) remains the critical problem.
Give a man a fish: <%-{-{-{-<
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: get next higher number
by tybalt89 (Monsignor) on Jun 11, 2018 at 22:56 UTC
|
#!/usr/bin/perl
# https://perlmonks.org/?node_id=1216404
use strict;
use warnings;
use Search::Dict;
my $file = join "", sort <DATA>;
open my $handle, '<', \$file or die;
for my $argument ( 11673326, 11673335, 11673321 )
{
0 <= look $handle, $argument + 1 or die "look error";
print "next after $argument is ", <$handle> // "undefined\n";
}
__DATA__
11673326
11673329
11673325
11673330
11673321
11673335
Outputs:
next after 11673326 is 11673329
next after 11673335 is undefined
next after 11673321 is 11673325
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: get next higher number
by Anonymous Monk on Jun 12, 2018 at 16:08 UTC
|
This almost sounds like a homework problem. If the file is unordered, you must read through all of it, first looking for numbers that are bigger than the one you have. You must keep each number and check each subsequent bigger-number to see if it is smaller than the one you already have, while also correctly handling the first-number case. If you can't code that, go ask your teacher. | [reply] [Watch: Dir/Any] |