Kernighans large earthquake problem
Brian Kernighan, in a lecture at the University of Nottingham, described a problem on which this task is based.
- Problem
You are given a a data file of thousands of lines; each of three `whitespace` separated fields: a date, a one word name and the magnitude of the event.
Example lines from the file would be lines like:
8/27/1883 Krakatoa 8.8 5/18/1980 MountStHelens 7.6 3/13/2009 CostaRica 5.1
- Task
- Create a program or script invocation to find all the events with magnitude greater than 6
- Assuming an appropriate name e.g. "data.txt" for the file:
- Either: Show how your program is invoked to process a data file of that name.
- Or: Incorporate the file name into the program, (as it is assumed that the program is single use).
AWK
<lang awk> awk '$3 > 6' data.txt</lang>
C
<lang c>#include <stdio.h>
- include <string.h>
- include <stdlib.h>
int main() {
FILE *fp; char *line = NULL; size_t len = 0; ssize_t read; char *lw, *lt; fp = fopen("data.txt", "r"); if (fp == NULL) { printf("Unable to open file\n"); exit(1); } printf("Those earthquakes with a magnitude > 6.0 are:\n\n"); while ((read = getline(&line, &len, fp)) != EOF) { if (read < 2) continue; /* ignore blank lines */ lw = strrchr(line, ' '); /* look for last space */ lt = strrchr(line, '\t'); /* look for last tab */ if (!lw && !lt) continue; /* ignore lines with no whitespace */ if (lt > lw) lw = lt; /* lw points to last space or tab */ if (atof(lw + 1) > 6.0) printf("%s", line); } fclose(fp); if (line) free(line); return 0;
}</lang>
- Output:
Using the given file:
Those earthquakes with a magnitude > 6.0 are: 8/27/1883 Krakatoa 8.8 5/18/1980 MountStHelens 7.6
Kotlin
<lang scala>// Version 1.2.40
import java.io.File
fun main(args: Array<String>) {
val r = Regex("""\s+""") println("Those earthquakes with a magnitude > 6.0 are:\n") File("data.txt").forEachLine { if (it.split(r)[2].toDouble() > 6.0) println(it) }
}</lang>
- Output:
Using the given file:
Those earthquakes with a magnitude > 6.0 are: 8/27/1883 Krakatoa 8.8 5/18/1980 MountStHelens 7.6
Perl
<lang perl>perl -n -e '/(\S+)\s*$/ and $1 > 6 and print' data.txt</lang>
Perl 6
Pass in a file name, or use default for demonstration purposes. <lang perl6>$_ = @*ARGS[0].IO // q:to/END/;
8/27/1883 Krakatoa 8.8 5/18/1980 MountStHelens 7.6 3/13/2009 CostaRica 5.1 END
map { .say if .words[2] > 6 }, .lines;</lang>
Python
Typed into a bash shell or similar: <lang python>python -c ' with open("data.txt") as f:
for ln in f: if float(ln.strip().split()[2]) > 6: print(ln.strip())'</lang>
zkl
<lang zkl>fcn equake(data,out=Console){
data.pump(out,fcn(line){ line.strip().split(" ")[-1]>6 },Void.Filter)
}</lang> <lang zkl>equake(Data(Void,
- <<<
"8/27/1883 Krakatoa 8.8\n" "5/18/1980 MountStHelens 7.6\n" "3/13/2009 CostaRica 5.1\n"
- <<<
));</lang> or <lang zkl>equake(File("equake.txt"));</lang> or <lang zkl>$ zkl equake.zkl < equake.txt</lang>
- Output:
8/27/1883 Krakatoa 8.8 5/18/1980 MountStHelens 7.6