aboutsummaryrefslogtreecommitdiff
path: root/tests/ii/strings
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ii/strings')
-rw-r--r--tests/ii/strings/case.json1
-rw-r--r--tests/ii/strings/generate.pl23
-rw-r--r--tests/ii/strings/notes.md5
-rw-r--r--tests/ii/strings/program.cps17
-rw-r--r--tests/ii/strings/reference.cc20
5 files changed, 66 insertions, 0 deletions
diff --git a/tests/ii/strings/case.json b/tests/ii/strings/case.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tests/ii/strings/case.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/ii/strings/generate.pl b/tests/ii/strings/generate.pl
new file mode 100644
index 0000000..f3ac098
--- /dev/null
+++ b/tests/ii/strings/generate.pl
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+use FindBin;
+use lib "$FindBin::Bin/..";
+use Random;
+my ($seed, $count) = @ARGV;
+my $rng = Random->new($seed, "strings");
+my @edges = (
+ '1 placeholder 1 0',
+ '0 A 1 1',
+ '0 Ab09 4 1',
+ '0 Ab09 1 4',
+ '0 Ab09 2 0',
+);
+$rng->emit($count, \@edges, sub {
+my $size = $rng->integer(0,24);
+return '1 placeholder 1 0' if $size == 0;
+my @alphabet = split //, 'ABCXYZabcxyz019@_-';
+my $text = join '', map { $alphabet[$rng->integer(0,$#alphabet)] } 1 .. $size;
+my $start = $rng->integer(1,$size);
+my $width = $rng->integer(0,$size-$start+1);
+return "0 $text $start $width";
+});
diff --git a/tests/ii/strings/notes.md b/tests/ii/strings/notes.md
new file mode 100644
index 0000000..01ea90a
--- /dev/null
+++ b/tests/ii/strings/notes.md
@@ -0,0 +1,5 @@
+# strings
+
+CIE pp. 16-17 for LENGTH/MID/RIGHT/concatenation; full-STRING LCASE/UCASE is a project extension. Inputs are ASCII under the default C locale. Empty input is encoded with a flag because project INPUT reads tokens. Substrings remain in range; zero width is a documented project boundary.
+
+Each record produces exactly one output line. Random records are preceded by fixed boundary records; every arithmetic intermediate is bounded.
diff --git a/tests/ii/strings/program.cps b/tests/ii/strings/program.cps
new file mode 100644
index 0000000..55e7541
--- /dev/null
+++ b/tests/ii/strings/program.cps
@@ -0,0 +1,17 @@
+DECLARE Count : INTEGER
+DECLARE Index : INTEGER
+DECLARE Empty : INTEGER
+DECLARE Text : STRING
+DECLARE Start : INTEGER
+DECLARE Width : INTEGER
+INPUT Count
+FOR Index <- 1 TO Count
+ INPUT Empty
+ INPUT Text
+ INPUT Start
+ INPUT Width
+ IF Empty = 1 THEN
+ Text <- ""
+ ENDIF
+ OUTPUT LENGTH(Text), ":", MID(Text, Start, Width), ":", RIGHT(Text, Width), ":", Text = ("" & Text), ":", LCASE(Text), ":", UCASE(Text)
+NEXT Index
diff --git a/tests/ii/strings/reference.cc b/tests/ii/strings/reference.cc
new file mode 100644
index 0000000..54d6efc
--- /dev/null
+++ b/tests/ii/strings/reference.cc
@@ -0,0 +1,20 @@
+#include <algorithm>
+#include <cctype>
+#include <iostream>
+#include <string>
+int main() {
+ int count;
+ if (!(std::cin >> count)) return 1;
+ for (int i = 0; i < count; ++i) {
+ int empty, start, width;
+ std::string text;
+ if (!(std::cin >> empty >> text >> start >> width)) return 1;
+ if (empty) text.clear();
+ auto lower = text, upper = text;
+ for (auto &c : lower) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
+ for (auto &c : upper) c = static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
+ auto mid = text.substr(static_cast<std::size_t>(start - 1), static_cast<std::size_t>(width));
+ auto right = text.substr(text.size() - static_cast<std::size_t>(width));
+ std::cout << text.size() << ':' << mid << ':' << right << ":TRUE:" << lower << ':' << upper << '\n';
+ }
+}