aboutsummaryrefslogtreecommitdiff
path: root/challenge-098
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2021-02-07 21:50:59 +0000
committerGitHub <noreply@github.com>2021-02-07 21:50:59 +0000
commit23661b8acb7cf337cc2a933fcec68a081cc5e2ed (patch)
treecb7c1500a72d05bea796d05fd0b2fb17a5232321 /challenge-098
parent720dd4c0d62ee390ae44cd6ba00486fc1a1fcb0f (diff)
parentfe7759f1063d132eb4fe234f95cc25b7d924b6dd (diff)
downloadperlweeklychallenge-club-23661b8acb7cf337cc2a933fcec68a081cc5e2ed.tar.gz
perlweeklychallenge-club-23661b8acb7cf337cc2a933fcec68a081cc5e2ed.tar.bz2
perlweeklychallenge-club-23661b8acb7cf337cc2a933fcec68a081cc5e2ed.zip
Merge pull request #3473 from Abigail/abigail/week-098
Abigail/week 098
Diffstat (limited to 'challenge-098')
-rw-r--r--challenge-098/abigail/README.md135
-rw-r--r--challenge-098/abigail/awk/ch-1.awk41
-rw-r--r--challenge-098/abigail/bash/ch-1.sh54
-rw-r--r--challenge-098/abigail/bash/ch-2.sh53
-rw-r--r--challenge-098/abigail/c/ch-1.c220
-rw-r--r--challenge-098/abigail/lua/ch-1.lua34
-rw-r--r--challenge-098/abigail/perl/ch-1.pl73
-rw-r--r--challenge-098/abigail/perl/ch-2.pl58
-rw-r--r--challenge-098/abigail/t/ctest.ini6
-rw-r--r--challenge-098/abigail/t/example-1.txt1
-rw-r--r--challenge-098/abigail/t/example-2.txt1
-rw-r--r--challenge-098/abigail/t/input-1-13
-rw-r--r--challenge-098/abigail/t/input-1-24
-rw-r--r--challenge-098/abigail/t/input-1-34
-rw-r--r--challenge-098/abigail/t/input-1-43
-rw-r--r--challenge-098/abigail/t/input-2-14
-rw-r--r--challenge-098/abigail/t/output-1-1.exp3
-rw-r--r--challenge-098/abigail/t/output-1-2.exp4
-rw-r--r--challenge-098/abigail/t/output-1-3.exp4
-rw-r--r--challenge-098/abigail/t/output-1-4.exp3
-rw-r--r--challenge-098/abigail/t/output-2-1.exp4
21 files changed, 650 insertions, 62 deletions
diff --git a/challenge-098/abigail/README.md b/challenge-098/abigail/README.md
index e6d1c21bb0..56e481bb08 100644
--- a/challenge-098/abigail/README.md
+++ b/challenge-098/abigail/README.md
@@ -1,99 +1,110 @@
# Solution by Abigail
-## [Ceasar Cipher](https://perlweeklychallenge.org/blog/perl-weekly-challenge-097/#TASK1)
+## [Read N-characters](https://perlweeklychallenge.org/blog/perl-weekly-challenge-098/#TASK1)
-You are given string `$S` containing alphabets `A..Z` only and a number `$N`.
+You are given file `$FILE`.
-Write a script to encrypt the given string `$S` using Caesar Cipher with
-left shift of size `$N`.
+Create subroutine `readN($FILE, $number)` returns the first `n`-characters
+and moves the pointer to the (`n+1`)th character.
-### Example
-~~~~
-Input: $S = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG", $N = 3
-Output: "QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD"
+### Notes
-Plain: ABCDEFGHIJKLMNOPQRSTUVWXYZ
-Cipher: XYZABCDEFGHIJKLMNOPQRSTUVW
+What a poorly defined challenge.
-Plaintext: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
-Ciphertext: QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD
-~~~~
+> You are given a file
+
+What does that mean? Do we get the content? A file handle?
+A file descriptor? A file name?
+
+The example (but not the challenge itself), suggest we're getting
+a file name. Ok, but....:
+
+> moves the pointer
+
+What pointer? File handles/descriptors point to something, so
+then it can be argued we should leave the file handle open,
+pointing to a place in the file. But we have just established we
+are *not getting* a file handle -- we're getting a file name.
+So, what pointer are we talking about?
+
+What on earth are we supposed to do?
+
+Are we supposed to create a file handle, and keep file handle open?
+Should we just slurp in the file content, and keep a pointer
+to what we have returned?
+
+What should happen if we call `readN` with different files, interleaved?
+Keep track of where we are for each file? Restart if called with `file1`,
+then `file2`, and then `file1` again?
+
+Our implementation will be a real stab in the dark -- we've no idea what
+we are supposed to do.
-### Note
-We will be reading the plain text from STDIN, and use an option (-s)
-to indicate the left shift.
+### Input
+Our program will read lines from standard input; each line consists
+of a filename and an amount of characters to read, separated by whitespace.
+
+### Example
+~~~~
+Input: Suppose the file (input.txt) contains "1234567890"
+Output:
+ print readN("input.txt", 4); # returns "1234"
+ print readN("input.txt", 4); # returns "5678"
+ print readN("input.txt", 4); # returns "90"
+~~~~
### Solutions
* [AWK](awk/ch-1.awk)
* [Bash](bash/ch-1.sh)
-* [Lua](lua/ch-1.lua)
-* [C](c/ch-1.c)
-* [Node.js](node/ch-1.js)
+* [C](c/ch-1.ch)
* [Perl](perl/ch-1.pl)
-* [Python](python/ch-1.py)
-* [Ruby](ruby/ch-1.rb)
### Blog
-[Perl Weekly Challenge 97: Ceasar Cipher](https://wp.me/pcxd30-nW)
-## [Binary Substrings](https://perlweeklychallenge.org/blog/perl-weekly-challenge-097/#TASK2)
+## [Search Insert Position](https://perlweeklychallenge.org/blog/perl-weekly-challenge-098/#TASK2)
-You are given a binary string `$B` and an integer `$S`.
+You are given a sorted array of distinct integers `@N` and a target `$N`.
-Write a script to split the binary string `$B` of size `$S` and then
-find the minimum number of flips required to make it all the same.
+Write a script to return the index of the given target if found
+otherwise place the target in the sorted array and return the index.
### Examples
#### Example 1
~~~~
-Input: $B = "101100101" $S = 3
-Output: 1
-
-Binary Substrings:
- "101": 0 flip
- "100": 1 flip to make it "101"
- "101": 0 flip
+Input: @N = (1, 2, 3, 4) and $N = 3
+Output: 2 since the target 3 is in the array at the index 2.
~~~~
#### Example 2
~~~~
-Input $B = "10110111", $S = 4
-Output: 2
-
-Binary Substrings:
- "1011": 0 flip
- "0111": 2 flips to make it "1011"
+Input: @N = (1, 3, 5, 7) and $N = 6
+Output: 3 since the target 6 is missing and should be placed at the index 3.
~~~~
-### Notes
-We will be reading the strings from STDIN. The length of each sub string
-will be passed in as an option: -s SIZE.
+#### Example 3
+~~~~
+Input: @N = (12, 14, 16, 18) and $N = 10
+Output: 0 since the target 10 is missing and should be placed at the index 0.
+~~~~
-To calculate the mininim number of flips required, note that we
-can calculate the number of flips for each position independently;
-that is, flipping a bit at position $i doesn't influence how the
-number of flips required for position $j, if $i != $j.
+#### Example 4
+~~~~
+Input: @N = (11, 13, 15, 17) and $N = 19
+Output: 4 since the target 19 is missing and should be placed at the index 4.
+~~~~
-For each position $i, we either need to flip all the 0s to 1s,
-or all the 1s to 0s. To minimize the number of flips, we count
-the number of 0s in each position, and compare that with the
-number of 1s in that position. Then we take the minimum of 0s
-and 1s, and sum this for all positions.
+### Notes
+We could write a binary search to find the target number in the
+array. This is tempting, as a binary search take O (log N). But
+this is futile. We're also asked to add the target element to the
+array (if not found), and adding an element in the middle of an
+array takes linear time. So, worst case, we're already spending
+linear time. (And to read the array, we're spending linear time
+anyway).
-There is no need to split the input string into chunks,
-we can leave it as is. The $i-th character of the $j-th section
-is as position $j * $s_len + $i, where $s_len is the length
-of a section.
### Solutions
-* [AWK](awk/ch-2.awk)
* [Bash](bash/ch-2.sh)
-* [C](c/ch-2.c)
-* [Lua](lua/ch-2.lua)
-* [Node](node/ch-2.js)
* [Perl](perl/ch-2.pl)
-* [Python](python/ch-2.py)
-* [Ruby](ruby/ch-2.rb)
### Blog
-[Perl Weekly Challenge 97: Binary Substrings](https://wp.me/pcxd30-pi)
diff --git a/challenge-098/abigail/awk/ch-1.awk b/challenge-098/abigail/awk/ch-1.awk
new file mode 100644
index 0000000000..ac53032a93
--- /dev/null
+++ b/challenge-098/abigail/awk/ch-1.awk
@@ -0,0 +1,41 @@
+#!/usr/bin/awk
+
+#
+# See ../README.md
+#
+
+#
+# Run as: awk -f ch-1.awk < input-file
+#
+
+
+#
+# If we haven't ready in the content of "filename" yet, do so,
+# and store it into an array, indexed by the filename.
+#
+# Remove the first amount characters of the stored content, and
+# return it.
+#
+function readN(filename, amount) {
+ if (!content [filename]) {
+ old_rs = RS
+ #
+ # We want to read the entire file, so we pick a
+ # character which should not be present in the file
+ # as the record separator.
+ #
+ RS = "\000"
+ getline content [filename] < filename
+ #
+ # Restore the record separator.
+ #
+ RS = old_rs
+ }
+ r = substr (content [filename], 1, amount)
+ content [filename] = substr (content [filename], amount + 1)
+ return r
+}
+
+{
+ print readN($1, $2)
+}
diff --git a/challenge-098/abigail/bash/ch-1.sh b/challenge-098/abigail/bash/ch-1.sh
new file mode 100644
index 0000000000..ebd4353079
--- /dev/null
+++ b/challenge-098/abigail/bash/ch-1.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+#
+# See ../README.md
+#
+
+#
+# Run as: bash ch-1.sh < input-file
+#
+# Each line of input consists of a filename and an amount
+# of characters to read.
+#
+
+#
+# Create associative arrays
+#
+declare -A content
+declare -A read
+
+function readN {
+ #
+ # Read arguments
+ #
+ filename=$1
+ amount=$2
+
+ #
+ # First time? Then read in file.
+ #
+ if [ "${read[$filename]}" != "1" ]
+ then read[$filename]=1
+ content[$filename]=$(<$filename)
+ fi
+
+ #
+ # Leading $amount characters
+ #
+ r=${content[$filename]:0:$amount}
+
+ #
+ # Remove $amount characters
+ #
+ content[$filename]=${content[$filename]:$amount}
+
+ echo $r
+}
+
+
+#
+# Read input, call readN
+#
+while read filename amount
+do readN $filename $amount
+done
diff --git a/challenge-098/abigail/bash/ch-2.sh b/challenge-098/abigail/bash/ch-2.sh
new file mode 100644
index 0000000000..2a6158d1db
--- /dev/null
+++ b/challenge-098/abigail/bash/ch-2.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+#
+# See ../README.md
+#
+
+#
+# Run as: perl ch-2.sh < input-file
+#
+# Each line is a challenge: first number is the target number;
+# the rest of the line is the array to search in.
+#
+
+set -f
+
+while read -a numbers
+do target=${numbers[0]}
+ #
+ # Try to find the target, counting from 1
+ #
+ found=-1
+ for ((i = 1; i < ${#numbers[@]}; i ++))
+ do if (($target == ${numbers[$i]}))
+ then found=$((i - 1))
+ break
+ fi
+ done
+ #
+ # If found, report the position and go to the next line
+ #
+ if (($found >= 0))
+ then echo $found
+ continue
+ fi
+
+ #
+ # Create a new array, by sorting numbers
+ #
+ IFS=$'\n'
+ numbers=($(sort -n <<< "${numbers[*]}"))
+ unset IFS
+
+ #
+ # Search for the target again
+ #
+ for ((i = 0; i < ${#numbers[@]}; i ++))
+ do if (($target == ${numbers[$i]}))
+ then found=$i
+ break
+ fi
+ done
+ echo $found
+done
diff --git a/challenge-098/abigail/c/ch-1.c b/challenge-098/abigail/c/ch-1.c
new file mode 100644
index 0000000000..8aee103290
--- /dev/null
+++ b/challenge-098/abigail/c/ch-1.c
@@ -0,0 +1,220 @@
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+# include <ctype.h>
+# include <limits.h>
+
+/*
+ * See ../README.md
+ */
+
+/*
+ * Run as: cc -o ch-1.o ch-1.c; ./ch-1.o < input-file
+ */
+
+/*
+ * Copied from https://gist.github.com/w-vi/7e98342181776162b1a3
+ */
+char * slurpfile (char * filename) {
+ FILE * fp;
+ char * source;
+ long bufsize;
+ size_t len;
+ if ((fp = fopen (filename, "r")) == NULL) {
+ fprintf (stderr, "Failed to open %s\n", filename);
+ exit (1);
+ }
+ /*
+ * Get the size of the file:
+ * - seek to the end of the file
+ * - use ftell to get the offset from the start
+ * - seek back to the beginning
+ */
+ if (fseek (fp, 0L, SEEK_END) != 0) {
+ fprintf (stderr, "seek() failed for %s\n", filename);
+ exit (1);
+ }
+ if ((bufsize = ftell (fp)) == -1) {
+ fprintf (stderr, "ftell() failed for %s\n", filename);
+ exit (1);
+ }
+ if (fseek (fp, 0L, SEEK_SET) != 0) {
+ fprintf (stderr, "seek() failed for %s\n", filename);
+ exit (1);
+ }
+
+ /*
+ * Allocate memory for content of the file
+ */
+ if ((source = (char *) malloc (sizeof (char) * (bufsize + 1))) == NULL) {
+ fprintf (stderr, "malloc() failed for %s\n", filename);
+ exit (1);
+ }
+
+ /*
+ * And read it in
+ */
+ if ((len = fread (source, sizeof (char), bufsize, fp)) == 0) {
+ fprintf (stderr, "fread() failed for %s\n", filename);
+ exit (1);
+ }
+ source [++ len] = '\0';
+
+ return source;
+}
+
+/*
+ * Use four arrays:
+ * - filenames: names of files read
+ * - content: pointers to content of files read
+ * - content_ptr: pointers to unreturned content
+ * - content_size: number of characters not returned yet
+ */
+size_t read_files = 0;
+char ** filenames = NULL;
+char ** content = NULL;
+char ** content_ptr = NULL;
+size_t * content_size = NULL;
+
+char * readN (char * filename, int amount) {
+ ssize_t found = -1;
+ char * out;
+ /*
+ * Check whether we've already found the file --
+ * if so, set its position in "found".
+ */
+ for (size_t i = 0; i < read_files; i ++) {
+ if (strncmp (filename, filenames [i], PATH_MAX) == 0) {
+ /*
+ * Found the file
+ */
+ found = i;
+ break;
+ }
+ }
+
+ /*
+ * Not found; all filename, content of file, and size to
+ * the end of the arrays.
+ */
+ if (found < 0) {
+ found = read_files ++;
+ /*
+ * Allocate memory
+ */
+ if ((filenames = (char **)
+ realloc (filenames, read_files * sizeof (char *))) == NULL) {
+ fprintf (stderr, "malloc() failed for %s\n", filename);
+ exit (1);
+ }
+ if ((content = (char **)
+ realloc (content, read_files * sizeof (char *))) == NULL) {
+ fprintf (stderr, "malloc() failed for %s\n", filename);
+ exit (1);
+ }
+ if ((content_ptr = (char **)
+ realloc (content_ptr, read_files * sizeof (char *))) == NULL) {
+ fprintf (stderr, "malloc() failed for %s\n", filename);
+ exit (1);
+ }
+ if ((content_size = (size_t *)
+ realloc (content_size, read_files * sizeof (size_t))) == NULL) {
+ fprintf (stderr, "malloc() failed for %s\n", filename);
+ exit (1);
+ }
+
+ /*
+ * Set data
+ */
+ if ((filenames [found] = (char *)
+ malloc (sizeof (char) * (strlen (filename) + 1))) == NULL) {
+ fprintf (stderr, "malloc() failed for %s\n", filename);
+ exit (1);
+ }
+ stpncpy (filenames [found], filename, strlen (filename));
+ filenames [found] [strlen (filename)] = '\0';
+ content [found] = slurpfile (filename);
+ content_ptr [found] = content [found];
+ content_size [found] = strlen (content [found]);
+
+ /*
+ * Remove any trailing new lines
+ */
+ while (content [found] [content_size [found] - 1] == '\n') {
+ content [found] [-- content_size [found]] = '\0';
+ }
+ }
+ /*
+ * Now 'found' points to the place where the content
+ * of the file is.
+ */
+
+ /*
+ * Cannot return more than we have.
+ */
+ if (content_size [found] < amount) {
+ amount = content_size [found];
+ }
+ /*
+ * Allocate memory for the return value
+ */
+ if ((out = (char *) malloc (sizeof (char) * (amount + 1))) == NULL) {
+ fprintf (stderr, "malloc() failed for %s\n", filename);
+ exit (1);
+ }
+ /*
+ * Copy the amount of data, make sure it's NUL terminated.
+ */
+ stpncpy (out, content_ptr [found], amount);
+ out [amount] = '\0';
+
+ /*
+ * Adjust the pointer and size left
+ */
+ content_ptr [found] += amount;
+ content_size [found] -= amount;
+
+ return out;
+}
+
+
+
+int main (void) {
+ char * line = NULL;
+ size_t len = 0;
+ size_t strlen;
+
+ /*
+ * Iterate over the lines of input; parse each line into
+ * a file name and an amount. Call readN for each line.
+ */
+ while ((strlen = getline (&line, &len, stdin)) != -1) {
+ char * line_ptr = line;
+ char * filename;
+ int amount;
+ if ((filename = (char *) malloc (PATH_MAX * sizeof (char))) == NULL) {
+ fprintf (stderr, "malloc() failed\n");
+ exit (1);
+ }
+ if (sscanf (line_ptr, "%s %d", filename, &amount) != 2) {
+ fprintf (stderr, "Could not parse input\n");
+ exit (1);
+ }
+ printf ("%s\n", readN (filename, amount));
+ free (filename);
+ }
+ /*
+ * Release memory
+ */
+ free (line);
+ for (size_t i = 0; i < read_files; i ++) {
+ free (filenames [i]);
+ free (content [i]);
+ }
+ free (filenames);
+ free (content);
+ free (content_ptr);
+ free (content_size);
+
+ return (0);
+}
diff --git a/challenge-098/abigail/lua/ch-1.lua b/challenge-098/abigail/lua/ch-1.lua
new file mode 100644
index 0000000000..4c8a8a4c92
--- /dev/null
+++ b/challenge-098/abigail/lua/ch-1.lua
@@ -0,0 +1,34 @@
+#!/opt/local/bin/lua
+
+--
+-- See ../README.md
+--
+
+--
+-- Run as: lua ch-1.lua < input-file
+--
+
+local content = {};
+
+function readN (filename, amount)
+ if content [filename] == nil
+ then --
+ -- Read the content of the file, strip the trailing
+ -- newline, and store the content in the table 'content'
+ --
+ content [filename] = assert (io . open (filename, "r")) :
+ read ("*all") :
+ gsub ("\n$", "")
+ end
+ local out = content [filename] : sub (1, amount)
+ content [filename] = content [filename] : sub (amount + 1)
+ return out
+end
+
+for line in io . lines () do
+ --
+ -- Split the line on whitespace, call readN() with the
+ -- result, and print the return value of readN().
+ --
+ print (readN (line : match ("(%S+) (%S+)")))
+end
diff --git a/challenge-098/abigail/perl/ch-1.pl b/challenge-098/abigail/perl/ch-1.pl
new file mode 100644
index 0000000000..b0c3a4d0da
--- /dev/null
+++ b/challenge-098/abigail/perl/ch-1.pl
@@ -0,0 +1,73 @@
+#!/opt/perl/bin/perl
+
+use 5.032;
+
+use strict;
+use warnings;
+no warnings 'syntax';
+
+use experimental 'signatures';
+use experimental 'lexical_subs';
+
+#
+# See ../README.md
+#
+
+#
+# Run as: perl ch-1.pl < input-file
+#
+# The input file will contain, on each line, a file name and an amount.
+#
+
+
+#
+# What a poorly defined challenge.
+#
+# "You are given a file".
+#
+# What does that mean? Do we get the content? A file handle?
+# A file descriptor? A file name?
+#
+# The example (but not the challenge itself), suggest we're getting
+# a file name. Ok, but....:
+#
+# "moves the pointer"
+#
+# What pointer? File handles/descriptors point to something, so
+# then it can be argued we should leave the file handle open,
+# pointing to a place in the file. But we have just established we
+# are NOT GETTING a file handle -- we're getting a file name.
+# So, what pointer are we talking about?
+#
+# What on earth are we supposed to do?
+#
+# Are we supposed to create a file handle, and keep file handle open?
+# Should we just slurp in the file content, and keep a pointer
+# to what we have returned?
+#
+# What should happen if we call 'readN' with different files, interleaved?
+# Keep track of where we are for each file? Restart if called with file1,
+# then file2, and then file1 again?
+#
+# What follows is a real stab in the dark -- I've no idea what
+# we are supposed to do.
+#
+
+#
+# Given a filename, read its contents if called for the first time with
+# that filename. Return the next $amount of characters. (Or less if we
+# have exhausted the content of the file).
+#
+sub readN ($filename, $amount) {
+ state $cache;
+ chomp ($$cache {$filename} //= do {local (@ARGV, $/) = $filename; <>});
+ substr $$cache {$filename} => 0, $amount, ""
+}
+
+while (<STDIN>) {
+ chomp;
+ my ($filename, $amount) = split ' ';
+ say readN $filename, $amount;
+}
+
+__END__
diff --git a/challenge-098/abigail/perl/ch-2.pl b/challenge-098/abigail/perl/ch-2.pl
new file mode 100644
index 0000000000..abe58c903d
--- /dev/null
+++ b/challenge-098/abigail/perl/ch-2.pl
@@ -0,0 +1,58 @@
+#!/opt/perl/bin/perl
+
+use 5.032;
+
+use strict;
+use warnings;
+no warnings 'syntax';
+
+use experimental 'signatures';
+use experimental 'lexical_subs';
+
+#
+# See ../README.md
+#
+
+#
+# Run as: perl ch-2.pl < input-file
+#
+# Each line is assumed to be a white space separated list of
+# numbers. The first number is the target number (`$N`), the rest of
+# the numbers is the array (`@N`).
+#
+# Now, we could implement a binary search to find the target in
+# O (log N) time, but why bother? We need to read the array, which
+# means we're already spending linear time; furthermore, we have to
+# insert element if not found -- which is a worst case linear time
+# operation anyway. So, we just do a linear scan.
+#
+# Note that we insert $N into @N by adding it to the end, and then
+# sorting -- which is linear in Perl (as the list (@N, $N) is nearly
+# sorted). We then use a goto to go back to the search; this is
+# guaranteed to succeed.
+#
+
+INPUT: while (<>) {
+ chomp;
+ my ($N, @N) = split ' ';
+ SEARCH:
+ for my $i (keys @N) {
+ if ($N == $N [$i]) {
+ say $i;
+ next INPUT;
+ }
+ }
+
+ #
+ # Not found. Insert by adding to the end and sorting.
+ #
+ @N = sort {$a <=> $b} @N, $N;
+
+ #
+ # Now, do the search again -- this time, it will succeed.
+ #
+ goto SEARCH;
+}
+
+
+__END__
diff --git a/challenge-098/abigail/t/ctest.ini b/challenge-098/abigail/t/ctest.ini
new file mode 100644
index 0000000000..f7f8de83d5
--- /dev/null
+++ b/challenge-098/abigail/t/ctest.ini
@@ -0,0 +1,6 @@
+[names]
+1-1 = Given example
+1-2 = Different amounts
+1-3 = Interleaf files
+1-4 = Exhaust a file
+2-1 = Given examples
diff --git a/challenge-098/abigail/t/example-1.txt b/challenge-098/abigail/t/example-1.txt
new file mode 100644
index 0000000000..a32a4347a4
--- /dev/null
+++ b/challenge-098/abigail/t/example-1.txt
@@ -0,0 +1 @@
+1234567890
diff --git a/challenge-098/abigail/t/example-2.txt b/challenge-098/abigail/t/example-2.txt
new file mode 100644
index 0000000000..72d007b6ed
--- /dev/null
+++ b/challenge-098/abigail/t/example-2.txt
@@ -0,0 +1 @@
+ABCDEFGHIJKLMNOPQRSTUVWXYZ
diff --git a/challenge-098/abigail/t/input-1-1 b/challenge-098/abigail/t/input-1-1
new file mode 100644
index 0000000000..4b650e514c
--- /dev/null
+++ b/challenge-098/abigail/t/input-1-1
@@ -0,0 +1,3 @@
+t/example-1.txt 4
+t/example-1.txt 4
+t/example-1.txt 4
diff --git a/challenge-098/abigail/t/input-1-2 b/challenge-098/abigail/t/input-1-2
new file mode 100644
index 0000000000..93b2127011
--- /dev/null
+++ b/challenge-098/abigail/t/input-1-2
@@ -0,0 +1,4 @@
+t/example-2.txt 3
+t/example-2.txt 4
+t/example-2.txt 5
+t/example-2.txt 6
diff --git a/challenge-098/abigail/t/input-1-3 b/challenge-098/abigail/t/input-1-3
new file mode 100644
index 0000000000..f3505b0c0e
--- /dev/null
+++ b/challenge-098/abigail/t/input-1-3
@@ -0,0 +1,4 @@
+t/example-1.txt 3
+t/example-2.txt 4
+t/example-1.txt 2
+t/example-2.txt 1
diff --git a/challenge-098/abigail/t/input-1-4 b/challenge-098/abigail/t/input-1-4
new file mode 100644
index 0000000000..38e4f27304
--- /dev/null
+++ b/challenge-098/abigail/t/input-1-4
@@ -0,0 +1,3 @@
+t/example-1.txt 6
+t/example-1.txt 6
+t/example-1.txt 6
diff --git a/challenge-098/abigail/t/input-2-1 b/challenge-098/abigail/t/input-2-1
new file mode 100644
index 0000000000..7f2eab05e9
--- /dev/null
+++ b/challenge-098/abigail/t/input-2-1
@@ -0,0 +1,4 @@
+3 1 2 3 4
+6 1 3 5 7
+10 12 14 16 18
+19 11 13 15 17
diff --git a/challenge-098/abigail/t/output-1-1.exp b/challenge-098/abigail/t/output-1-1.exp
new file mode 100644
index 0000000000..3bcb5635c2
--- /dev/null
+++ b/challenge-098/abigail/t/output-1-1.exp
@@ -0,0 +1,3 @@
+1234
+5678
+90
diff --git a/challenge-098/abigail/t/output-1-2.exp b/challenge-098/abigail/t/output-1-2.exp
new file mode 100644
index 0000000000..3cc380de30
--- /dev/null
+++ b/challenge-098/abigail/t/output-1-2.exp
@@ -0,0 +1,4 @@
+ABC
+DEFG
+HIJKL
+MNOPQR
diff --git a/challenge-098/abigail/t/output-1-3.exp b/challenge-098/abigail/t/output-1-3.exp
new file mode 100644
index 0000000000..174506bfa6
--- /dev/null
+++ b/challenge-098/abigail/t/output-1-3.exp
@@ -0,0 +1,4 @@
+123
+ABCD
+45
+E
diff --git a/challenge-098/abigail/t/output-1-4.exp b/challenge-098/abigail/t/output-1-4.exp
new file mode 100644
index 0000000000..c880decfc2
--- /dev/null
+++ b/challenge-098/abigail/t/output-1-4.exp
@@ -0,0 +1,3 @@
+123456
+7890
+
diff --git a/challenge-098/abigail/t/output-2-1.exp b/challenge-098/abigail/t/output-2-1.exp
new file mode 100644
index 0000000000..c89c0bde15
--- /dev/null
+++ b/challenge-098/abigail/t/output-2-1.exp
@@ -0,0 +1,4 @@
+2
+3
+0
+4