-9
\$\begingroup\$

Make a cat program, with a catch. The program must refuse under all circumstances to output "Hello World", instead outputting "Goodbye World", with matching spacing (but matching casing is not required).

"Hello World" must never appear as a substring of the output, regardless of casing, not even if the two words are (or are not) separated by newlines, spaces, tabs, or even multiple executions of the program.

Rules

These are all forbidden:

Hello World

HelloWorld

Hello   world

HELLOWORLD

I want to wish you hello world

HeLlOwOrLd and all who inhabit it

Hello
world    

I said hello
world news

Instead, the output should read:

Goodbye World

GoodbyeWorld

Goodbye   world

GOODBYEWORLD

I want to wish you goodbye world

Goodbyeworld and all who inhabit it

Goodbye
world

I said goodbye
world news

However, other characters that separate hello and world will cause the string to not be matched. These should be repeated verbatim:

Hello, world
hello happy world
HELLO2THEWORLD

If the program is run twice in sequence (for example, in a batch script), first against the string "hello" and then against the string "world", the output should be:

goodbye
world

But if it is run against "hello" and then "friends", the output should be:

hello
friends

You can choose whether to abstain from printing hello until the next run (this means if that command never comes, it will never print, which is acceptable), or to change it retroactively, if possible. The program does not have to take into account the possibility of other programs being run between runs.

Examples

Here's a quick .sh I put together to test it (I named my binary goodbye):

echo hello world | ./goodbye
echo hello friends | ./goodbye
echo HeLlO wOrLd | ./goodbye
(echo hello; echo world) | ./goodbye
(echo hello; echo friends) | ./goodbye
echo helloworld | ./goodbye
echo "hello     world" | ./goodbye
echo I say hello | ./goodbye
echo world | ./goodbye
echo hello | ./goodbye
echo friends of mine | ./goodbye
echo hello happy world | ./goodbye
echo hello2theWORLD | ./goodbye

This is code golf, so lowest byte count (per language) wins!

\$\endgroup\$
2
  • \$\begingroup\$ How exactly does the capitalisation transfer from the "hello" work? Would "HEllO world" result in "GOodBye world" or "GOodBYE world", or something else? Also, I'd recommend dropping the requirement of working between multiple program runs, as it's unobservable and impossible in some languages; instead simply transforming an input string into an output string. \$\endgroup\$
    – emanresu A
    Commented Feb 8 at 22:09
  • \$\begingroup\$ Capitalization was mimicked in the examples, but this is not a requirement. "HEllO world" could become "goodbye world" or "GOODBYE world," or any other capitalization. \$\endgroup\$
    – Devsman
    Commented Feb 8 at 22:12

1 Answer 1

1
\$\begingroup\$

It seems there's some confusion over whether this is possible, so here's an example answer in...

FLEX/C (557 bytes)

%option noyywrap
%{#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define p(X) printf(X)
#define s(X) strncat(w,X,99)
#define g(X) if(l==1){X}
#define d w[0]='\0';p(t);l=0;
#define t yytext
int l = 0;char *w;
%}
%%
[hH][eE][lL][lL][oO] {l=1;}
[wW][oO][rR][lL][dD] {g(p("goodbye");)p(w);d}
[\r\n\t ] {g(s(t);)else{p(t);}}
. {g(p("hello");)p(w);d}
%%
main(int c,char **a){w=malloc(99);w[0]='\0';if(access("f",F_OK)==0){l=1;remove("f");s("\n");}yylex();if(l==1){FILE* f=fopen("f","w");fclose(f);}else{p("\n");}}

Here's the ungolfed version:

%option noyywrap

%{
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>

    #define FLAG_FILE "goodbye.flg"

    int last = 0;
    char *whitespace;
%}

%%

[hH][eE][lL][lL][oO]    { last = 1; }
[wW][oO][rR][lL][dD]    { if (last == 1) { printf("goodbye"); } printf(whitespace); whitespace[0] = '\0'; printf(yytext); last = 0; }
[\r\n\t ]               { if (last == 1) { strncat(whitespace, yytext, 100); } else { printf(yytext); } }
.                       { if (last == 1) { printf("hello"); } printf(whitespace); whitespace[0] = '\0'; printf(yytext); last = 0; }

%%

main(int argc, char **argv)
{
    whitespace = malloc(1000);
    whitespace[0] = '\0';
    if (access(FLAG_FILE, F_OK) == 0)
    {
        last = 1;
        remove(FLAG_FILE);
        strncat(whitespace, "\n", 100);
    }
    yylex();
    if (last == 1)
    {
        FILE* file_ptr = fopen(FLAG_FILE, "w");
        fclose(file_ptr);
    }
    else
    {
        printf("\n");
    }
}

It chooses the abstain option, which as noted in the question, allows it to abstain from printing the last word if the last word in the input is "hello", and then decide on the next run whether to print "hello" or "goodbye" based on whether the following word is "world."

\$\endgroup\$
3
  • 4
    \$\begingroup\$ What if it's only run once? Then it won't work \$\endgroup\$
    – pxeger
    Commented Feb 10 at 11:10
  • \$\begingroup\$ You can choose whether to abstain from printing hello until the next run (this means if that command never comes, it will never print, which is acceptable)... It chooses the abstain option, which as noted in the question, allows it to abstain from printing the last word if the last word in the input is "hello" \$\endgroup\$
    – Devsman
    Commented Feb 12 at 15:06
  • 3
    \$\begingroup\$ But if it’s only run once then there won’t be a next time for it to decide whether to print anything, so nothing will be printed. And it can’t know in advance the first time whether there’ll be a second time. \$\endgroup\$
    – pxeger
    Commented Feb 12 at 17:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.