You are given text file with rows numbered
1-15
in random order but there is a catch one row in missing in the file.11, Line Eleven 1, Line one 9, Line Nine 13, Line Thirteen 2, Line two 6, Line Six 8, Line Eight 10, Line Ten 7, Line Seven 4, Line Four 14, Line Fourteen 3, Line three 15, Line Fifteen 5, Line Five
Write a script to find the missing row number.
This is fairly trivial. The sum of the number \(1\) to \(15\) equals \(\sum_{i=1}^{15} i = 120\). So, if we add the sum of the line numbers in the file, and subtract this from \(120\) we get the missing row number.
First we import the sum
method from List::Util
:
use List::Util qw [sum];
Then we can get the answer in a one liner:
say 120 - sum <>;
We take advantage of the fact that if we use a string as a number, Perl will look at the beginning of the string, and tries to interpret that a number. It does issue a warning if there is some trailing stuff, but hey, if you don't turn on warnings, you won't see them.
Find the full program on GitHub.
We could also have used a one-liner, not requiring another module, nor having the number of lines hard coded:
perl -nE '$;+=$.-$_;END{say$.+1+$;}'
Just like in Perl, AWK looks at the beginning of a string if it's treated as a number. It won't issue a warning. So we get:
BEGIN {SUM_15 = 120}
{sum += $1}
END {print SUM_15 - sum}
Find the full program on GitHub.
For the Bash solution, we split the input. Bash does this already be default, splitting on white space. But we want to split on commas:
IFS=","
Now it's a matter of summing the first column, and subtracting the result from 120:
SUM_15=120
while read number tail; do ((sum += number)); done
echo $((SUM_15 - sum))
Find the full program on GitHub.
In C, we use the atol
function to get the number at
the beginning of a string.
# define SUM_15 120
int main (void) {
char * line = NULL;
size_t len = 0;
size_t str_len;
int sum = 0;
while ((str_len = getline (&line, &len, stdin)) != -1) {
sum += atol (line);
}
printf ("%d\n", SUM_15 - sum);
free (line);
return (0);
}
Find the full program on GitHub.
In Go, we use the method ReadString
in an bufio
object to read
lines of input. On EOF
, this method returns an error, which we
use to break the loop. Go does have an Atoi
method, but that doesn't
work like atoi
in C: it balks if there are non-numbers following the
number at the beginning of the string. So, we're going to use Sscanf
to parse the number.
func main () {
var i int
var sum int = 0
var SUM_15 int = 120
var reader = bufio . NewReader (os. Stdin)
for {
var text, err1 = reader . ReadString ('\n')
if (err1 != nil) {
break
}
var n, err2 = fmt . Sscanf (text, "%d", &i)
if (n < 1 || err2 != nil) {
continue
}
sum += i
}
fmt . Printf ("%d\n", SUM_15 - sum)
}
Find the full program on GitHub.
In Java, we use a scanner
object to read lines of input. Using Google,
I found a couple of methods to convert string to integers, but all of them
require the string to contain exactly an integer. No atoi
equivalent.
So, we're just parsing the beginning of the string manually. We're making
use of the charAt
method on string objects: given an argument n
,
it returns the ASCII value of the n
th character in the string.
import java.util.*;
public class ch1 {
public static void main (String [] args) {
Scanner scanner = new Scanner (System . in);
int sum = 0;
int SUM_15 = 120;
try {
while (true) {
String line = scanner . nextLine ();
int i, n = 0;
for (i = 0; i < line . length (); i ++) {
if (line . charAt (i) < "0" . charAt (0) ||
line . charAt (i) > "9" . charAt (0)) {
break;
}
n *= 10;
n += line . charAt (i) - "0" . charAt (0);
}
sum += n;
}
}
catch (Exception e) {
System . out . println (SUM_15 - sum);
}
}
}
Find the full program on GitHub.
To turn the beginning of a string into a number, we capture the
leading digits, and use the function tonumber
to make it a number:
local SUM_15 = 120
local sum = 0
for line in io . lines () do
sum = sum + tonumber (line : match ("%d+"))
end
print (SUM_15 - sum)
Find the full program on GitHub.
Here, we split the lines of input on a comma, and use the unary +
to change a string into a number:
let SUM_15 = 120
let sum = 0
require ('readline')
. createInterface ({input: process . stdin})
. on ('line', line => {
let [num] = line . split (/,/)
sum +=+ num
})
. on ('close', () => console . log (SUM_15 - sum))
Find the full program on GitHub.
Splitting on commas is the way to go in Python as well, and we
use int
to turn the string into an integer:
import fileinput
sum = 0
SUM_15 = 120
for line in fileinput . input ():
sum = sum + int ((line . split (",")) [0])
print (SUM_15 - sum)
Find the full program on GitHub.
Another split
in Ruby, using the to_i
method to turn the
result into an integer:
sum = 0
SUM_15 = 120
ARGF . each_line do
|line|
sum += ((line . split (/,/)) [0]) . to_i
end
puts (SUM_15 - sum)
Find the full program on GitHub.