Another update from ingydotnet^djgoku
This commit is contained in:
parent
91df62d461
commit
948b86eafa
7604 changed files with 108452 additions and 22726 deletions
34
Task/Mad-Libs/AWK/mad-libs.awk
Normal file
34
Task/Mad-Libs/AWK/mad-libs.awk
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# syntax: GAWK -f MAD_LIBS.AWK
|
||||
BEGIN {
|
||||
print("enter story:")
|
||||
}
|
||||
{ story_arr[++nr] = $0
|
||||
if ($0 ~ /^ *$/) {
|
||||
exit
|
||||
}
|
||||
while ($0 ~ /[<>]/) {
|
||||
L = index($0,"<")
|
||||
R = index($0,">")
|
||||
changes_arr[substr($0,L,R-L+1)] = ""
|
||||
sub(/</,"",$0)
|
||||
sub(/>/,"",$0)
|
||||
}
|
||||
}
|
||||
END {
|
||||
PROCINFO["sorted_in"] = "@ind_str_asc"
|
||||
print("enter values for:")
|
||||
for (i in changes_arr) { # prompt for replacement values
|
||||
printf("%s ",i)
|
||||
getline rec
|
||||
sub(/ +$/,"",rec)
|
||||
changes_arr[i] = rec
|
||||
}
|
||||
printf("\nrevised story:\n")
|
||||
for (i=1; i<=nr; i++) { # print the story
|
||||
for (j in changes_arr) {
|
||||
gsub(j,changes_arr[j],story_arr[i])
|
||||
}
|
||||
printf("%s\n",story_arr[i])
|
||||
}
|
||||
exit(0)
|
||||
}
|
||||
70
Task/Mad-Libs/Batch-File/mad-libs-1.bat
Normal file
70
Task/Mad-Libs/Batch-File/mad-libs-1.bat
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
::Save this as MADLIBS.BAT
|
||||
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
%== Check if there is no arguments ==%
|
||||
if "%~1"=="" (
|
||||
echo.
|
||||
echo.[Mad Libs - Batch File Implementation]
|
||||
echo.
|
||||
echo.Usage: MADLIBS [file]
|
||||
echo.
|
||||
exit /b 1
|
||||
)
|
||||
if not exist "%~f1" (echo.File not found.&exit /b 1)
|
||||
|
||||
echo.
|
||||
%== Read the text file ==%
|
||||
echo.[Mad Libs - Batch File Implementation]
|
||||
echo.
|
||||
for /f "tokens=* eol=_" %%A in (%~sf1) do (
|
||||
set /a cnt+=1
|
||||
set "line!cnt!=%%A"
|
||||
)
|
||||
%== User input the missing parts ==%
|
||||
for /l %%. in (1,1,!cnt!) do (
|
||||
call :proc_line "%%."
|
||||
)
|
||||
%== Display the edited story... ==%
|
||||
echo.
|
||||
echo.The Story:
|
||||
echo.
|
||||
for /l %%? in (1,1,!cnt!) do (
|
||||
echo. !line%%?!
|
||||
)
|
||||
echo.
|
||||
exit /b 0
|
||||
|
||||
%== The main processor of the story ==%
|
||||
:proc_line
|
||||
set "str=!line%~1!"
|
||||
:loop
|
||||
if "!str!"=="" goto :EOF
|
||||
for /f "tokens=1,* delims=<" %%M in ("!str!") do (
|
||||
for /f "tokens=1,* delims=>" %%X in ("%%M") do (
|
||||
if not "%%M"=="%%X" (
|
||||
set "temp_var=%%X"
|
||||
if not "!temp_var: =!"=="" (
|
||||
set "input="
|
||||
set /p "input=Enter a value for [%%X]?"
|
||||
call :subst_input
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
set "str=!line%~1!"
|
||||
for /f "tokens=1,* delims=<" %%M in ("!str!") do (set str=%%N)
|
||||
goto loop
|
||||
|
||||
%== This Substitutes the input to the blank ==%
|
||||
:subst_input
|
||||
set "chk_brack=!input:>=!"
|
||||
set "chk_brack=!chk_brack:<=!"
|
||||
set "chk_brack=!chk_brack:%%=!"
|
||||
for /l %%. in (1,1,!cnt!) do (
|
||||
if "!line%%.: =!"==" =" set "line%%.= "
|
||||
if "!chk_brack!"=="!input!" (
|
||||
call set "line%%.=%%line%%.:<%%X>=!input!%%"
|
||||
) else (set "line%%.=!line%%.:<%%X>=!")
|
||||
)
|
||||
goto :EOF
|
||||
145
Task/Mad-Libs/Batch-File/mad-libs-2.bat
Normal file
145
Task/Mad-Libs/Batch-File/mad-libs-2.bat
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define err(...) fprintf(stderr, ## __VA_ARGS__), exit(1)
|
||||
|
||||
/* We create a dynamic string with a few functions which make modifying
|
||||
* the string and growing a bit easier */
|
||||
typedef struct {
|
||||
char *data;
|
||||
size_t alloc;
|
||||
size_t length;
|
||||
} dstr;
|
||||
|
||||
inline int dstr_space(dstr *s, size_t grow_amount)
|
||||
{
|
||||
return s->length + grow_amount < s->alloc;
|
||||
}
|
||||
|
||||
int dstr_grow(dstr *s)
|
||||
{
|
||||
s->alloc *= 2;
|
||||
char *attempt = realloc(s->data, s->alloc);
|
||||
|
||||
if (!attempt) return 0;
|
||||
else s->data = attempt;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
dstr* dstr_init(const size_t to_allocate)
|
||||
{
|
||||
dstr *s = malloc(sizeof(dstr));
|
||||
if (!s) goto failure;
|
||||
|
||||
s->length = 0;
|
||||
s->alloc = to_allocate;
|
||||
s->data = malloc(s->alloc);
|
||||
|
||||
if (!s->data) goto failure;
|
||||
|
||||
return s;
|
||||
|
||||
failure:
|
||||
if (s->data) free(s->data);
|
||||
if (s) free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dstr_delete(dstr *s)
|
||||
{
|
||||
if (s->data) free(s->data);
|
||||
if (s) free(s);
|
||||
}
|
||||
|
||||
dstr* readinput(FILE *fd)
|
||||
{
|
||||
static const size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
|
||||
dstr *s = dstr_init(buffer_size);
|
||||
if (!s) goto failure;
|
||||
|
||||
while (fgets(buffer, buffer_size, fd)) {
|
||||
while (!dstr_space(s, buffer_size))
|
||||
if (!dstr_grow(s)) goto failure;
|
||||
|
||||
strncpy(s->data + s->length, buffer, buffer_size);
|
||||
s->length += strlen(buffer);
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
failure:
|
||||
dstr_delete(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dstr_replace_all(dstr *story, const char *replace, const char *insert)
|
||||
{
|
||||
const size_t replace_l = strlen(replace);
|
||||
const size_t insert_l = strlen(insert);
|
||||
char *start = story->data;
|
||||
|
||||
while ((start = strstr(start, replace))) {
|
||||
if (!dstr_space(story, insert_l - replace_l))
|
||||
if (!dstr_grow(story)) err("Failed to allocate memory");
|
||||
|
||||
if (insert_l != replace_l) {
|
||||
memmove(start + insert_l, start + replace_l, story->length -
|
||||
(start + replace_l - story->data));
|
||||
|
||||
/* Remember to null terminate the data so we can utilize it
|
||||
* as we normally would */
|
||||
story->length += insert_l - replace_l;
|
||||
story->data[story->length] = 0;
|
||||
}
|
||||
|
||||
memmove(start, insert, insert_l);
|
||||
}
|
||||
}
|
||||
|
||||
void madlibs(dstr *story)
|
||||
{
|
||||
static const size_t buffer_size = 128;
|
||||
char insert[buffer_size];
|
||||
char replace[buffer_size];
|
||||
|
||||
char *start,
|
||||
*end = story->data;
|
||||
|
||||
while (start = strchr(end, '<')) {
|
||||
if (!(end = strchr(start, '>'))) err("Malformed brackets in input");
|
||||
|
||||
/* One extra for current char and another for nul byte */
|
||||
strncpy(replace, start, end - start + 1);
|
||||
replace[end - start + 1] = '\0';
|
||||
|
||||
printf("Enter value for field %s: ", replace);
|
||||
|
||||
fgets(insert, buffer_size, stdin);
|
||||
const size_t il = strlen(insert) - 1;
|
||||
if (insert[il] == '\n')
|
||||
insert[il] = '\0';
|
||||
|
||||
dstr_replace_all(story, replace, insert);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) return 0;
|
||||
|
||||
FILE *fd = fopen(argv[1], "r");
|
||||
if (!fd) err("Could not open file: '%s\n", argv[1]);
|
||||
|
||||
dstr *story = readinput(fd); fclose(fd);
|
||||
if (!story) err("Failed to allocate memory");
|
||||
|
||||
madlibs(story);
|
||||
printf("%s\n", story->data);
|
||||
dstr_delete(story);
|
||||
return 0;
|
||||
}
|
||||
48
Task/Mad-Libs/Batch-File/mad-libs-3.bat
Normal file
48
Task/Mad-Libs/Batch-File/mad-libs-3.bat
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
string story, input;
|
||||
|
||||
//Loop
|
||||
while(true)
|
||||
{
|
||||
//Get a line from the user
|
||||
getline(cin, input);
|
||||
|
||||
//If it's blank, break this loop
|
||||
if(input == "\r")
|
||||
break;
|
||||
|
||||
//Add the line to the story
|
||||
story += input;
|
||||
}
|
||||
|
||||
//While there is a '<' in the story
|
||||
int begin;
|
||||
while((begin = story.find("<")) != string::npos)
|
||||
{
|
||||
//Get the category from between '<' and '>'
|
||||
int end = story.find(">");
|
||||
string cat = story.substr(begin + 1, end - begin - 1);
|
||||
|
||||
//Ask the user for a replacement
|
||||
cout << "Give me a " << cat << ": ";
|
||||
cin >> input;
|
||||
|
||||
//While there's a matching category
|
||||
//in the story
|
||||
while((begin = story.find("<" + cat + ">")) != string::npos)
|
||||
{
|
||||
//Replace it with the user's replacement
|
||||
story.replace(begin, cat.length()+2, input);
|
||||
}
|
||||
}
|
||||
|
||||
//Output the final story
|
||||
cout << endl << story;
|
||||
|
||||
return 0;
|
||||
}
|
||||
239
Task/Mad-Libs/Fortran/mad-libs.f
Normal file
239
Task/Mad-Libs/Fortran/mad-libs.f
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
MODULE MADLIB !Messing with COMMON is less convenient.
|
||||
INTEGER MSG,KBD,INF !I/O unit numbers.
|
||||
DATA MSG,KBD,INF/6,5,10/ !Output, input, some disc file.
|
||||
INTEGER LSTASH,NSTASH,MSTASH !Prepare a common text stash.
|
||||
PARAMETER (LSTASH = 246810, MSTASH = 6666) !LSTASH characters for MSTASH texts.
|
||||
CHARACTER*(LSTASH) STASH !The pool.
|
||||
INTEGER ISTASH(MSTASH + 1) !Fingers start positions, and thus end positions by extension.
|
||||
DATA NSTASH,ISTASH(1)/0,1/ !Empty pool: no entries, first available character is at 1.
|
||||
INTEGER MANYLINES,MANYTESTS !I also want some lists of texts.
|
||||
PARAMETER (MANYLINES = 1234) !This is to hold the story.
|
||||
INTEGER NSTORY,STORY(MANYLINES) !Fingering texts in the stash.
|
||||
PARAMETER (MANYTESTS = 1234) !Likewise, some target/replacement texts.
|
||||
INTEGER NTESTS,TARGET(MANYTESTS),REPLACEMENT(MANYTESTS) !Thus.
|
||||
DATA NSTORY,NTESTS/0,0/ !No story lines, and no tests.
|
||||
INTEGER STACKLIMIT !A recursion limit.
|
||||
PARAMETER (STACKLIMIT = 28) !This should suffice.
|
||||
|
||||
CONTAINS
|
||||
SUBROUTINE CROAK(GASP) !A dying remark.
|
||||
CHARACTER*(*) GASP !The last words.
|
||||
WRITE (MSG,*) "Oh dear." !Shock.
|
||||
WRITE (MSG,*) GASP !Aargh!
|
||||
STOP "How sad." !Farewell, cruel world.
|
||||
END SUBROUTINE CROAK !Farewell...
|
||||
|
||||
SUBROUTINE SHOWSTASH(BLAH,I) !One might be wondering.
|
||||
CHARACTER*(*) BLAH !An annotation.
|
||||
INTEGER I !The desired stashed text.
|
||||
WRITE (MSG,1) BLAH,I,STASH(ISTASH(I):ISTASH(I + 1) - 1) !Whee!
|
||||
1 FORMAT (A,': Text(',I0,')="',A,'"') !Hopefully, helpful.
|
||||
END SUBROUTINE SHOWSTASH !Ah, debugging.
|
||||
|
||||
INTEGER FUNCTION EATTEXT(IN) !Add a text to STASH and finger it.
|
||||
Co-opts the as-yet unused space in STASH as its scratchpad.
|
||||
INTEGER IN !Input from this I/O unit number.
|
||||
INTEGER I,N,L !Fingers.
|
||||
I = ISTASH(NSTASH + 1)!First available position in STASH.
|
||||
N = LSTASH - I + 1 !Number of characters yet unused.
|
||||
IF (N.LT.666) CALL CROAK("Insufficient STASH space remains!")
|
||||
READ (IN,1,END = 66) L,STASH(I:I + MIN(L,N) - 1) !Calculated during the read.
|
||||
1 FORMAT (Q,A) !Obviously, Q = character count incoming, A = accept all of them.
|
||||
L = I + MIN(L,N) - 1 !The last character read.
|
||||
10 IF (L.LT.I) GO TO 66 !A blank line! Deemed end-of-file.
|
||||
IF (ICHAR(STASH(L:L)).LE.ICHAR(" ")) THEN !A trailing space?
|
||||
L = L - 1 !Yes. Pull back.
|
||||
GO TO 10 !And try again.
|
||||
END IF !So much for trailing spaces.
|
||||
IF (NSTASH.GE.MSTASH) CALL CROAK("Too many texts!")
|
||||
NSTASH = NSTASH + 1 !Admit another text.
|
||||
ISTASH(NSTASH + 1) = L + 1 !The start point of the following text.
|
||||
EATTEXT = NSTASH !STASH(ISTASH(n):ISTASH(n + 1) - 1) has text n.
|
||||
RETURN !All well.
|
||||
66 EATTEXT = 0 !Sez: "No text".
|
||||
END FUNCTION EATTEXT !Rather odd side effects.
|
||||
|
||||
INTEGER FUNCTION ADDSTASH(TEXT) !Appends an arbitrary text to the pool of stashed texts.
|
||||
CHARACTER*(*) TEXT !The stuff.
|
||||
INTEGER I !A finger.
|
||||
IF (NSTASH.GE.MSTASH) CALL CROAK("The text pool is crowded!") !Alas.
|
||||
I = ISTASH(NSTASH + 1) !First unused character.
|
||||
IF (I + LEN(TEXT).GT.LSTASH) CALL CROAK("Overtexted!") !Alack.
|
||||
STASH(I:I + LEN(TEXT) - 1) = TEXT !Place.
|
||||
NSTASH = NSTASH + 1 !Count in another entry.
|
||||
ISTASH(NSTASH + 1) = I + LEN(TEXT) !The new "first available" position.
|
||||
ADDSTASH = NSTASH !Pass a finger back to the caller.
|
||||
END FUNCTION ADDSTASH !Just an integer.
|
||||
|
||||
INTEGER FUNCTION ANOTHER(TEXT) !Possibly add TEXT to the table of target texts.
|
||||
Collects TARGET REPLACEMENT pairs (increasing NTESTS) as directed by INSPECT.
|
||||
CHARACTER*(*) TEXT !The text of the target.
|
||||
INTEGER I,IT !Steppers.
|
||||
ANOTHER = 0 !Possibly, the text is already in the table.
|
||||
DO I = 1,NTESTS !So, step through the known target texts.
|
||||
IT = TARGET(I) !Finger a target text.
|
||||
IF (TEXT.EQ.STASH(ISTASH(IT):ISTASH(IT + 1) - 1)) RETURN !Already have this one.
|
||||
END DO !Otherwise, try the next.
|
||||
IF (NTESTS.GE.MANYTESTS) CALL CROAK("Too many tests!") !Oh dear.
|
||||
NTESTS = NTESTS + 1 !Count in another.
|
||||
TARGET(NTESTS) = ADDSTASH(TEXT)!Stash its text and get a finger to it.
|
||||
ANOTHER = NTESTS !My caller will want to know which test.
|
||||
WRITE (MSG,1) TEXT !Now request the replacement text.
|
||||
1 FORMAT ("Enter your text for ",A,": ",$) !Obviously, the $ indicates "no new line".
|
||||
REPLACEMENT(NTESTS) = EATTEXT(KBD) !Zero for "no text".
|
||||
END FUNCTION ANOTHER !Produces entries for TARGET and REPLACEMENT.
|
||||
|
||||
SUBROUTINE INSPECT(X) !Examine text number X for the special <...> sequence.
|
||||
Calls for inspection of REPLACEMENT texts as well, should ANOTHER report a new entry.
|
||||
INTEGER X !Fingers the text in STASH via ISTASH(X).
|
||||
INTEGER MARK !Recalls where the < was found.
|
||||
INTEGER IT,NEW !Fingers to entries in STASH.
|
||||
INTEGER I !A stepper.
|
||||
INTEGER SP,STACK(STACKLIMIT) !Prepare for some recursion.
|
||||
SP = 1 !Start with the starter.
|
||||
STACK(1) = X !Stack up.
|
||||
DO WHILE(SP.GT.0) !While texts are yet uninspected,
|
||||
IT = STACK(SP) !Finger one.
|
||||
SP = SP - 1 !Working down the stack.
|
||||
MARK = 0 !Uninitialised variables are bad.
|
||||
DO I = ISTASH(IT),ISTASH(IT + 1) - 1!Step through the stashed text.
|
||||
IF (STASH(I:I).EQ."<") THEN !Is it the starter?
|
||||
MARK = I !Yes. Remember where it is.
|
||||
ELSE IF (STASH(I:I).EQ.">") THEN !The ender?
|
||||
IF (MARK.LE.0) CALL CROAK("A > with no preceeding <!") !Bah.
|
||||
NEW = ANOTHER(STASH(MARK:I)) !Consider the spanned text.
|
||||
IF (NEW.GT.0) THEN !If that became a new table entry,
|
||||
IF (SP.GE.STACKLIMIT) CALL CROAK("Stack overflow!") !Its replacement is to be inspected.
|
||||
SP = SP + 1 !But I'm still busy with the current text.
|
||||
STACK(SP) = REPLACEMENT(NEW) !So, stack it for later.
|
||||
END IF !So much for that <...> apparition.
|
||||
MARK = 0 !Be ready to check afresh for the next.
|
||||
END IF !So much for that character.
|
||||
END DO !On to the next.
|
||||
END DO !So much for that stacked entry.
|
||||
END SUBROUTINE INSPECT !WRITESTORY will rescan the story lines.
|
||||
|
||||
SUBROUTINE READSTORY(IN)!Read and stash the lines.
|
||||
INTEGER IN !Input from here.
|
||||
INTEGER LINE !A finger to the story line.
|
||||
10 LINE = EATTEXT(IN) !So, grab a line.
|
||||
IF (LINE.GT.0) THEN !A live line?
|
||||
NSTORY = NSTORY + 1 !Yes.Count it in.
|
||||
STORY(NSTORY) = LINE !Save it in the story list.
|
||||
CALL INSPECT(LINE) !Look for trouble as well.
|
||||
GO TO 10 !And go for the next line.
|
||||
END IF !Oh for while (Line:=EatText(in)) > 0 do SaveAndInspect(Line);
|
||||
END SUBROUTINE READSTORY!Simple enough, anyway.
|
||||
|
||||
SUBROUTINE WRITESTORY(WIDTH) !Applying the replacements, with replacement replacement too.
|
||||
Co-opts the as-yet unused space in STASH as its output scratchpad.
|
||||
Can't rely on changing the index and bounds of a DO-loop on the fly.
|
||||
INTEGER WIDTH
|
||||
INTEGER LINE,IT,I,J !Steppers.
|
||||
INTEGER L,L0,N !Fingers.
|
||||
INTEGER TAIL,MARK,LAST !Scan choppers.
|
||||
INTEGER SP,STACKI(STACKLIMIT),STACKL(STACKLIMIT) !Ah, recursion.
|
||||
L0 = ISTASH(NSTASH + 1) !The first available place in the stash.
|
||||
L = L0 - 1 !Syncopation for my output finger.
|
||||
LL:DO LINE = 1,NSTORY !Step through the lines of the story.
|
||||
SP = 0 !Start with the task in hand.
|
||||
IT = STORY(LINE) !Finger the stashed line.
|
||||
LAST = ISTASH(IT + 1) - 1 !Find its last character in STASH.
|
||||
I = ISTASH(IT) !Find its first character in STASH.
|
||||
TAIL = I - 1 !Syncopation. No text from this line yet.
|
||||
IF (STASH(I:I).LE." ") THEN !The line starts with a space?
|
||||
CALL BURP !Yes. Flush, so as to start a new paragraph.
|
||||
ELSE IF (LINE.GT.1) THEN !Otherwise, the line is a continuation.
|
||||
L = L + 1 !So, squeeze in a space as a separator.
|
||||
STASH(L:L) = " " !Since its text follows on.
|
||||
END IF !Now for the content of the line.
|
||||
666 II:DO WHILE(I.LE.LAST) !Step along its text.
|
||||
IF (STASH(I:I).EQ."<") THEN !Trouble starter?
|
||||
MARK = I !Yes. Remember where.
|
||||
ELSE IF (STASH(I:I).EQ.">") THEN !The corresponding ender?
|
||||
CALL APPEND(TAIL + 1,MARK - 1) !Waiting text up to the mark.
|
||||
JJ:DO J = 1,NTESTS !Step through the target texts.
|
||||
IT = TARGET(J) !Finger one.
|
||||
IF (STASH(ISTASH(IT):ISTASH(IT + 1) - 1) !Its stashed text.
|
||||
1 .EQ.STASH(MARK:I)) THEN !Matches the suspect text?
|
||||
IT = REPLACEMENT(J) !Yes! Finger the replacement text.
|
||||
IF (IT.GT.0) THEN !Null replacements can be ignored.
|
||||
IF (SP.GE.STACKLIMIT) CALL CROAK("StackOverflow!") !Always diff. messages.
|
||||
SP = SP + 1 !Interrupt the current scan.
|
||||
STACKI(SP) = I !Remember where we're up to,
|
||||
STACKL(SP) = LAST !And the end of the text.
|
||||
I = ISTASH(IT) - 1 !One will be added shortly, at JJ+1.
|
||||
LAST = ISTASH(IT + 1) - 1 !Preempt the scan-in-progress.
|
||||
END IF !To work along the replacement text.
|
||||
EXIT JJ !Found the target, so the search is finished.
|
||||
END IF !Otherwise,
|
||||
END DO JJ !Try the next target text.
|
||||
TAIL = I !Normal text resumes at TAIL + 1.
|
||||
END IF !Enough analysis of that character from the story line.
|
||||
I = I + 1 !The next to consider.
|
||||
END DO II !Perhaps we've finished this text.
|
||||
IF (SP.GT.0) THEN !Yes! But, were we interrupted in a previous scan?
|
||||
CALL APPEND(TAIL + 1,LAST)!Yes! Roll the tail of the just-finished scan.
|
||||
TAIL = STACKI(SP) !The stacked value of I was fingering a >.
|
||||
LAST = STACKL(SP) !And this was the end of the text.
|
||||
SP = SP - 1 !So we've recovered where the scan was.
|
||||
I = TAIL + 1 !And this is the next to look at.
|
||||
GO TO 666 !Proceed to do so.
|
||||
END IF !But if all is unstacked,
|
||||
CALL APPEND(TAIL + 1,LAST) !Don't forget the tail end.
|
||||
END DO LL !On to the next story line.
|
||||
CALL BURP !Any waiting text must be less than WIDTH.
|
||||
CONTAINS !Some assistants, defined after usage...
|
||||
SUBROUTINE APPEND(IST,LST) !Has access to L.
|
||||
INTEGER IST,LST !To copy STASH(IST:LST) to the scratchpad.
|
||||
INTEGER N !The number of characters to copy.
|
||||
N = LST - IST + 1 !So find out.
|
||||
IF (N.LE.0) RETURN !Avoid relying on zero-length action.
|
||||
IF (L + N.GT.LSTASH) CALL CROAK("Out of stash!") !Oh dear.
|
||||
STASH(L + 1:L + N) = STASH(IST:LST) !There they go.
|
||||
L = L + N !Advance my oputput finger.
|
||||
IF (L - L0 + 1.GE.WIDTH) CALL BURP !Enough to be going on with?
|
||||
END SUBROUTINE APPEND !Few invocations, if with tricky parameters.
|
||||
SUBROUTINE BURP !Flushes forth up to WIDTH characters.
|
||||
INTEGER N,W,L1 !And slides any remnant back.
|
||||
N = L - L0 + 1 !So, how many characters are waiting?
|
||||
IF (N.LE.WIDTH) THEN !Too many for one line of output?
|
||||
L1 = L !Nope. Roll the lot.
|
||||
ELSE !Otherwise, a partial flush.
|
||||
W = L0 + WIDTH - 1 !Last character that can be fitted into WIDTH.
|
||||
DO L1 = W,L0,-1 !Look for a good split.
|
||||
IF (STASH(L1:L1).LE." ") EXIT !Like, at a space.
|
||||
END DO !Keep winding back.
|
||||
IF (L1.LE.L0) L1 = W !No pleasing split found. Just roll a full width.
|
||||
END IF !Ready to roll.
|
||||
WRITE (MSG,"(A)") STASH(L0:L1) !Thus!
|
||||
IF (N.LE.WIDTH) THEN !If the whole text was written,
|
||||
L = L0 - 1 !Then there is no text in the scratchpad.
|
||||
ELSE !If only L0:L1 were written of L0:L,
|
||||
W = L0 + L - L1 - 1 !How far will the remaining text extend?
|
||||
STASH(L0:W) = STASH(L1 + 1:L) !Shift it.
|
||||
L = W !Finger the last used character position.
|
||||
END IF !One trim is enough, even if the scracchpad contains multiple widths' worth..
|
||||
END SUBROUTINE BURP !Since I don't want to flush the lot.
|
||||
END SUBROUTINE WRITESTORY !Just a sequence of lines.
|
||||
END MODULE MADLIB !Enough of that.
|
||||
|
||||
PROGRAM MADLIBBER !See, for example, https://en.wikipedia.org/wiki/Mad_Libs
|
||||
USE MADLIB
|
||||
WRITE (MSG,1) !It's polite to explain.
|
||||
10FORMAT ("Reads a story in template form, containing special ",
|
||||
1 "entries such as <dog's name> amongst the text.",/,
|
||||
2 "You will be invited to supply a replacement text for each "
|
||||
3 "such entry, as encountered,",/,
|
||||
4 "after which the story will be presented with your ",
|
||||
5 "substitutions made.",//,
|
||||
6 "Here goes... Reading file Madlib.txt",/)
|
||||
OPEN(INF,STATUS="OLD",ACTION="READ",FORM="FORMATTED",
|
||||
1 FILE = "Madlib.txt")
|
||||
CALL READSTORY(INF)
|
||||
CLOSE(INF)
|
||||
WRITE (MSG,*)
|
||||
WRITE (MSG,*) " Righto!"
|
||||
WRITE (MSG,*)
|
||||
CALL WRITESTORY(66)
|
||||
END
|
||||
14
Task/Mad-Libs/J/mad-libs-1.j
Normal file
14
Task/Mad-Libs/J/mad-libs-1.j
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
require 'general/misc/prompt regex'
|
||||
|
||||
madlib=:3 :0
|
||||
smoutput 'Please enter the story template'
|
||||
smoutput 'See http://rosettacode.org/wiki/Mad_Libs for details'
|
||||
t=.''
|
||||
while.#l=.prompt '' do. t=.t,l,LF end.
|
||||
repl=. ~.'<[^<>]*>' rxall t
|
||||
for_bef. repl do.
|
||||
aft=. prompt (}.}:;bef),': '
|
||||
t=.t rplc bef,<aft
|
||||
end.
|
||||
t
|
||||
)
|
||||
11
Task/Mad-Libs/J/mad-libs-2.j
Normal file
11
Task/Mad-Libs/J/mad-libs-2.j
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
madlib''
|
||||
Please enter the story template
|
||||
See http://rosettacode.org/wiki/Mad_Libs for details
|
||||
<name> went for a walk in the park. <he or she>
|
||||
found a <noun>. <name> decided to take it home.
|
||||
|
||||
name: Jill
|
||||
he or she: she
|
||||
noun: rock
|
||||
Jill went for a walk in the park. she
|
||||
found a rock. Jill decided to take it home.
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
coclass 'AA'
|
||||
NB. associative array
|
||||
|
||||
create=: verb define
|
||||
empty KEYS=: DATA =: ''
|
||||
)
|
||||
|
||||
destroy=: codestroy
|
||||
|
||||
put=: dyad define NB. DATUM put KEY
|
||||
DATA=: DATA , < x
|
||||
KEYS=: KEYS , < y
|
||||
EMPTY
|
||||
)
|
||||
|
||||
get=: verb define NB. get KEY
|
||||
(KEYS (i. <) y) {:: DATA
|
||||
)
|
||||
|
||||
cocurrent'base'
|
||||
|
||||
get =: dyad define NB. OBJECT get KEY
|
||||
try.
|
||||
get__x y
|
||||
catch.
|
||||
smoutput '?' ,~ ": y
|
||||
RV =. 1!:1<1
|
||||
RV put__x y
|
||||
RV
|
||||
end.
|
||||
)
|
||||
|
||||
STORY =: 0 :0
|
||||
<name> went for a walk in the park. <he or she>
|
||||
found a <noun>. <name> decided to take it home.
|
||||
)
|
||||
|
||||
madlib =: verb define NB. madlib STORY
|
||||
I =. y i. '<'
|
||||
if. I = # y do. y return. end. NB. no substitutions
|
||||
HEAD =. I {. y
|
||||
TAIL =. I }. y
|
||||
A =. }. (<;.1~ '<'&=) '<' , TAIL NB. the story is parsed by '<'
|
||||
B =. (({. ; }.)~ >:@:i.&'>')&> A
|
||||
NB.+-----------+------------------------------+
|
||||
NB.|<name> | went for a walk in the park. |
|
||||
NB.+-----------+------------------------------+
|
||||
NB.|<he or she>| found a |
|
||||
NB.+-----------+------------------------------+
|
||||
NB.|<noun> |. |
|
||||
NB.+-----------+------------------------------+
|
||||
NB.|<name> | decided to take it home. |
|
||||
NB.+-----------+------------------------------+
|
||||
AA =. conew'AA'
|
||||
create__AA''
|
||||
SUBSTITUTIONS =. AA&get&.> _ 1 {. B
|
||||
codestroy__AA''
|
||||
HEAD , ; SUBSTITUTIONS ,. 0 1 }. B
|
||||
)
|
||||
|
|
@ -1,14 +1,11 @@
|
|||
filename = InputString["Enter the filename of the story template: "];
|
||||
text = Import[filename];
|
||||
listofblanks = StringCases[text, RegularExpression["<[^>]+>"]] // Union;
|
||||
listofanswers = {};
|
||||
Do[
|
||||
answer = InputString["Enter a/an: " <> listofblanks[[i]]];
|
||||
AppendTo[listofanswers, answer];
|
||||
, {i, 1, Length[listofblanks]}
|
||||
]
|
||||
Do[
|
||||
text = StringReplace[text, listofblanks[[i]] -> listofanswers[[i]]]
|
||||
, {i, 1, Length[listofblanks]}
|
||||
]
|
||||
text
|
||||
text = Import[
|
||||
InputString["Enter the filename of the story template:"]];
|
||||
answers =
|
||||
AssociationMap[
|
||||
InputString[
|
||||
"Enter a" <>
|
||||
If[StringMatchQ[#,
|
||||
"<" ~~ Alternatives @@ Characters["aeiou"] ~~ ___], "n", ""] <>
|
||||
" " <> StringTrim[#, "<" | ">"] <> ":"] &,
|
||||
Union[StringCases[text, RegularExpression["<[^>]+>"]]]];
|
||||
Print[StringReplace[text, Normal[answers]]];
|
||||
|
|
|
|||
105
Task/Mad-Libs/Pascal/mad-libs.pascal
Normal file
105
Task/Mad-Libs/Pascal/mad-libs.pascal
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
Program Madlib; Uses DOS, crt; {See, for example, https://en.wikipedia.org/wiki/Mad_Libs}
|
||||
{Reads the lines of a story but which also contain <xxx> sequences. For each value of xxx,
|
||||
found as the lines of the story are read, a request is made for a replacement text.
|
||||
The story is then written out with the corresponding replacements made.}
|
||||
{Concocted by R.N.McLean (whom God preserve), Victoria university, NZ.}
|
||||
Procedure Croak(gasp: string); {A dying message.}
|
||||
Begin
|
||||
Writeln(' Eurghfff...');
|
||||
Writeln(Gasp);
|
||||
HALT;
|
||||
End;
|
||||
var inf: text; {Drivelstuff.}
|
||||
const StoryLimit = 66;TableLimit = 65; {Big enough.}
|
||||
var Story: array[1..StoryLimit] of string; {Otherwise, use a temporary disc file.}
|
||||
var Target,Replacement: array[1..TableLimit] of string;
|
||||
var StoryLines,TableCount: integer; {Usage.}
|
||||
|
||||
Function Reading(var inf: text;var Aline: string): boolean;
|
||||
Begin
|
||||
Aline:='';
|
||||
Reading:=true;
|
||||
if eoln(inf) then Reading:=false {Agh! Why can't the read statement return true/false?}
|
||||
else ReadLn(inf,Aline);
|
||||
if Aline = '' then Reading:=false; {Specified that a blank line ends the story.}
|
||||
End;
|
||||
|
||||
Procedure Inspect(text: string); Forward;{I'd rather have multi-pass compilation than deal with this.}
|
||||
|
||||
Procedure Table(it: string); {Check it as a target, and obtain its replacement.}
|
||||
var i: integer; {A stepper.}
|
||||
Begin
|
||||
for i:=1 to TableCount do if it = Target[i] then exit; {Already in the table?}
|
||||
if TableCount >= TableLimit then Croak('Too many table entries!'); {No. Room for another?}
|
||||
inc(TableCount); {Yes.}
|
||||
Target[TableCount]:=it; {Include the < and > to preclude partial matches.}
|
||||
write('Enter your text for ',it,': '); {Pretty please?}
|
||||
readln(Replacement[TableCount]); {Thus.}
|
||||
Inspect(Replacement[TableCount]); {Enable full utilisation.}
|
||||
End; {of Table.}
|
||||
|
||||
var InDeep: integer; {Counts inspection recursion.}
|
||||
Procedure Inspect(text: string); {Look for <...> in text.}
|
||||
var i: integer; {A stepper.}
|
||||
var mark: integer; {Fingers the latest < in Aline.}
|
||||
Begin
|
||||
inc(InDeep); {Supply an opportunity, and fear the possibilities.}
|
||||
if InDeep > 28 then Croak('Excessive recursion! Inspecting ' + text);
|
||||
for i:=1 to Length(text) do {Now scan the line for trouble.}
|
||||
if text[i] = '<' then mark:=i {Trouble starts here? Just mark its place.}
|
||||
else if text[i] = '>' then {Trouble ends here?}
|
||||
Table(copy(text,mark,i - mark + 1)); {Deal with it.}
|
||||
dec(InDeep); {I'm done.}
|
||||
End; {of Inspect.}
|
||||
|
||||
Procedure Swallow(Aline: string); {Add a line to the story, and inspect it for <...>.}
|
||||
Begin
|
||||
if StoryLines >= StoryLimit then Croak('Too many lines in the story!'); {Suspicion forever.}
|
||||
inc(StoryLines); {Otherwise, this is safe.}
|
||||
Story[StoryLines]:=Aline; {So save another line.}
|
||||
Inspect(Aline); {Look for any <...> inclusions.}
|
||||
End; {of Swallow.}
|
||||
|
||||
var Rolling: integer; {Counts rolling rolls.}
|
||||
Procedure Roll(bumf: string); {Write a line, with amendments.}
|
||||
var last,mark: integer; {Fingers for the scan.}
|
||||
var hit: string; {Copied once.}
|
||||
var i,it: integer; {Steppers.}
|
||||
label hic; {Oh dear.}
|
||||
Begin
|
||||
inc(Rolling); {Here I go.}
|
||||
if Rolling > 28 then Croak('Excessive recursion! Rolling ' + bumf); {Self-expansion is out.}
|
||||
last:=0; {Where the previous text ended.}
|
||||
for i:=1 to Length(bumf) do {Scan the text.}
|
||||
if bumf[i] = '<' then mark:=i {Remember where a <...> starts.}
|
||||
else if bumf[i] = '>' then {So that when the stopper is found,}
|
||||
begin {It can be recognised.}
|
||||
Write(copy(bumf,last + 1,mark - last - 1)); {Text up to the <.}
|
||||
hit:=copy(bumf,mark,i - mark + 1); {Grab this once.}
|
||||
for it:=1 to TableCount do {Search my table.}
|
||||
if Target[it] = hit then {A match?}
|
||||
begin {Yes!}
|
||||
Roll(Replacement[it]); {Write this instead.}
|
||||
goto hic; {There is no "exit loop" style statement.}
|
||||
end; {"Exit" exits the procedure or function.}
|
||||
hic:last:=i; {Advance the trailing finger.}
|
||||
end; {On to the next character.}
|
||||
Write(copy(bumf,last + 1,Length(bumf) - last)); {Text after the last >, possibly null.}
|
||||
dec(Rolling); {I'm done.}
|
||||
if Rolling <= 0 then WriteLn; {And if this is the first level, add a end-of-line.}
|
||||
End; {of Roll.}
|
||||
|
||||
var inname: string; {For a file name.}
|
||||
var Aline: string; {A scratchpad.}
|
||||
var i: integer; {A stepper.}
|
||||
BEGIN
|
||||
InDeep:=0; {No inspections yet.}
|
||||
Rolling:=0; {No output.}
|
||||
inname:=ParamStr(1); {Perhaps the file name is specified as a run-time parameter.}
|
||||
if inname = '' then inname:='Madlib.txt'; {If not, this will do.}
|
||||
Assign(inf,inname); Reset(inf); {Open the input file.}
|
||||
StoryLines:=0; TableCount:=0; {Prepare the counters.}
|
||||
while reading(inf,Aline) do Swallow(Aline); {Read and inspect the story.}
|
||||
close(inf); {Finished with input.}
|
||||
for i:=1 to StoryLines do Roll(Story[i]); {Write the amended story.}
|
||||
END.
|
||||
|
|
@ -1,4 +1 @@
|
|||
my $story = slurp(@*ARGS.shift);
|
||||
my %words;
|
||||
$story.=subst(/ '<' (.*?) '>' /, { %words{$0} //= prompt "$0? " }, :g );
|
||||
say $story;
|
||||
print S:g[ '<' (.*?) '>' ] = %.{$0} //= prompt "$0? " given slurp;
|
||||
|
|
|
|||
18
Task/Mad-Libs/VBScript/mad-libs.vb
Normal file
18
Task/Mad-Libs/VBScript/mad-libs.vb
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
Function mad_libs(s)
|
||||
Do
|
||||
If InStr(1,s,"<") <> 0 Then
|
||||
start_position = InStr(1,s,"<") + 1
|
||||
end_position = InStr(1,s,">")
|
||||
parse_string = Mid(s,start_position,end_position-start_position)
|
||||
WScript.StdOut.Write parse_string & "? "
|
||||
input_string = WScript.StdIn.ReadLine
|
||||
s = Replace(s,"<" & parse_string & ">",input_string)
|
||||
Else
|
||||
Exit Do
|
||||
End If
|
||||
Loop
|
||||
mad_libs = s
|
||||
End Function
|
||||
|
||||
WScript.StdOut.Write mad_libs("<name> went for a walk in the park. <he or she> found a <noun>. <name> decided to take it home.")
|
||||
WScript.StdOut.WriteLine
|
||||
Loading…
Add table
Add a link
Reference in a new issue