I got stuck in one problem of finding the missing values in a range and the range is also variable for the successive rows.
input
673 673 673 676 676 680 2667 2667 2668 2670 2671 2674
output should be开发者_如何学编程 like this
674 675 677 678 679 2669 2672 2673
This is just one part and the row values can be more also If you need any clarification, please let me know.
Pure bash.
Use two subshells and run a diff
, then clean up the results.
diff <(cat my_range_with_holes) <(seq 1 1000) | grep '>' | cut -c 3-
In Python:
def report_missing_numbers(f):
for line in f:
numbers = [int(n) for n in line.split()]
all_numbers = set(range(numbers[0], numbers[-1]))
missing = all_numbers - set(numbers)
yield missing
Note: all_numbers
is a bit of a lie, since the range excludes the final number, but since that number is guaranteed to be in the set, it doesn't affect the correctness of the algorithm.
Note: I removed the [-1]
from my original answer, since int(n)
doesn't care about the trailing '\n'
.
Perl:
use Modern::Perl;
for my $line (<DATA>) {
chomp $line;
my @numbers = split /\s+/, $line;
my ($min, $max) = (sort { $a <=> $b } @numbers)[0, -1];
my @missing = grep { not $_ ~~ @numbers } $min .. $max;
say join " ", @missing;
}
__DATA__
673 673 673 676 676 680
2667 2667 2668 2670 2671 2674
Python:
for line in open("inputfile.txt"):
vals = set(map(int, line.split()))
minv, maxv = min(vals), max(vals)
missing = [str(v) for v in xrange(minv + 1, maxv) if v not in vals]
print " ".join(missing)
Sample code Using Perl:
#!/usr/bin/perl
use strict;
use warnings;
my @missing;
while(<DATA>) {
my @data = split (/[ ]/, $_);
my $i = shift @data;
foreach (@data) {
if ($_ != ++$i) {
push @missing, $i .. $_ - 1;
$i = $_;
}
}
}
print join " ", @missing;
__DATA__
673 673 673 676 676 680
2667 2667 2668 2670 2671 2674
OUTPUT
674 675 677 678 679 2669 2672 2673
Ruby:
$stdin.each_line do |line|
numbers = line.scan(/\d+/).map(&:to_i)
missing = (numbers.min..numbers.max).to_a - numbers
puts missing.join " "
end
Golf version (79 characters):
puts $stdin.map{|l|n=l.scan(/\d+/).map(&:to_i);((n.min..n.max).to_a-n).join" "}
Pure Bash:
while read -a line ; do
firstvalue=${line[0]}
lastvalue=${line[${#line[@]}-1]}
output=()
# prepare the output array
for (( item=firstvalue; item<=lastvalue; item++ )); do
output[$item]=1
done
# unset array elements with an index from the input set
for item in ${line[@]}; do
unset "output[$item]"
done
# echo the remaining indices
echo -e "${!output[@]}"
done < "$infile"
Perl oneliner:
perl -anE'($a,$b)=@F[0,-1];$,=" ";@h{@F}=();say grep!exists$h{$_},$a..$b'
Modification of Marcelo's solution with safe release of file handle in the event of an exception:
with open('myfile.txt') as f:
numbers = [int(n) for n in f.readline()[:-1].split(' ')]
all_numbers = set(range(numbers[0], numbers[-1]))
missing = all_numbers - set(numbers)
This also avoids using the builtin name file
.
Shell solution using Bash, sort, uniq & jot (Mac OS X):
numbers="673 673 673 676 676 680"
numbers="2667 2667 2668 2670 2671 2674"
sorted=($(IFS=$'\n' echo "${numbers}" | tr " " '\n' | sort -u ))
low=${sorted[0]}
high=${sorted[@]: -1}
( printf "%s\n" "${sorted[@]}"; jot $((${high} - ${low} + 1)) ${low} ${high} ) | sort | uniq -u
Bash solution:
cat file_of_numbers| xargs -n2 seq | sort -nu
a = [ 673, 673, 673, 676, 676, 680]
def woo(a):
max_, min_ = a[0:-1]
a = set(a)
tot = set(list(range(min_,max_+1)))
return list( tot - a )
You have your list. Set operator is useful for comparing lists. In your case you want to find all elements that:
- are between the first value and the last one
- have been passed ( discontinuity)
Set operator generates all uniques values coming from a list
To select all values that are in tot
but not in a
just do tot - a
. Just format the output as a list
if you want to conserve a
as a list you need to use copy()
in your function:
a = [ 673, 673, 673, 676, 676, 680]
def woo(a):
max_, min_ = a[0:-1]
a = set(a.copy())
tot = set(list(range(min_,max_+1)))
return list( tot - a )
精彩评论