13
\$\begingroup\$

Objective

Write a full program that works exactly like the flow chart below.

Each output, which is an integer, shall be through stdout, followed by a line feed.

Each input shall be a line of string fed through stdin, and shall be judged to a predicate you choose for branching. The same predicate must be used for all branches.

The predicate must be able to judge every possible input, and must not be always truthy nor always falsy. Possible choices of the predicate include:

  • Truthy if the inputted string is nonempty
  • Truthy if the inputted string consists of whitespaces
  • Truthy if the inputted string can be parsed into an integer
  • Truthy if the inputted string is exactly Hello, world!

The flow chart

The flow chart

Rule

Your submission need not to follow the definition above exactly, as long as the visible side-effects are the same. This rule is present to aid functional languages.

Ungolfed solution

Haskell

Truthy if the string is empty.

main :: IO ()
main = procedure1 where
    genProcedure :: Int -> IO () -> IO () -> IO ()
    genProcedure output branch1 branch2 = do
        print output
        str <- getLine
        if null str
            then branch1
            else branch2
    procedure1, procedure2, procedure3 :: IO ()
    procedure1 = genProcedure 1 procedure3 procedure2
    procedure2 = genProcedure 2 procedure1 procedure3
    procedure3 = genProcedure 3 procedure2 (pure ())
\$\endgroup\$
5
  • \$\begingroup\$ May we output everything after reaching END? \$\endgroup\$
    – Tbw
    Dec 28, 2023 at 0:28
  • \$\begingroup\$ @Tbw No; the END means termination of the program. \$\endgroup\$ Dec 28, 2023 at 0:30
  • \$\begingroup\$ Are we allowed to assume only two distinct values can be used for truthy and falsey (e.g. can it be a stipulation that input will always be 0/1)? \$\endgroup\$
    – lyxal
    Dec 28, 2023 at 0:32
  • \$\begingroup\$ @Lyxal "The predicate must be able to judge every possible input" — So, no. \$\endgroup\$ Dec 28, 2023 at 0:33
  • \$\begingroup\$ How should EOF be handled? \$\endgroup\$
    – Bbrk24
    Dec 29, 2023 at 21:52

12 Answers 12

11
\$\begingroup\$

QBasic, 58 bytes

1?x+1
LINE INPUT s$
x=x+1+(s$>"")*(2+(x=0)*3)
IF x<3GOTO 1

Empty inputs are falsey; nonempty inputs are truthy. You can type the program in and run it at Archive.org.

Sadly, storing the program state in a variable x is much cheaper than doing actual control flow with gotos. A direct translation of the flowchart comes in at 95 bytes:

1?1
LINE INPUT s$
IF""<s$GOTO 3
2?2
LINE INPUT s$
IF""<s$GOTO 1
3?3
LINE INPUT s$
IF""<s$GOTO 2
\$\endgroup\$
5
\$\begingroup\$

PARI/GP, 52 bytes

Strictly speaking, this is not a valid solution, because it can't handle some special inputs like quit. But this is the best I can do.

my(n=0);while(n<3,print(n++);iferr(input,e,n=n++%3))

Attempt This Online!

Valid PARI/GP expressions (e.g. o_o) are falsy. Other strings (e.g. *_*) are truthy.

PARI/GP doesn't have a way to read an arbitrary string from stdin. The function input always parses the input as a PARI/GP expression. So I use iferr to check if the input is valid.

I also need to declare n as a local variable, otherwise the user may input a string like n=9 and change the value of n.

However, there's no way to stop the user from inputting something like quit, which will quit the program; or input, which prompts for another input; or print("something"), which prints something. It's just impossible to handle these cases.

\$\endgroup\$
4
\$\begingroup\$

Jelly, 15 13 bytes

‘Ṅ+%3ßḊo?ɗɠẸ¤

Try it online!

A full program that takes no arguments but reads from STDIN. The predicate function checks for a non-empty line. As required, the intermediate outputs are sent to STDOUT.

Explanation

‘                | Increment by 1
 Ṅ               | Output to STDOUT with a trailing newline
         ɗɠẸ¤    | Following as a dyad with the right argument (y) as 1 if the next line from STDIN is non-empty and 0 if empty, and the link’s argument + 1 as the left argument
  +              |   x + y
   %3            |   Mod 3
     ßḊṪ?        |   If this or the input is truthy, call the link recursively; if falsy, remove the remaining value so we’re left with an empty list
\$\endgroup\$
4
\$\begingroup\$

Charcoal, 22 bytes

≔³θWθ«I⁻⁴θD⎚≔⎇S⊕﹪θ³⊖θθ

Try it online! Link is to verbose version of code. Uses nonempty as the predicate. Explanation:

≔³θ

Numbering the states in reverse to output values, we start in state 3.

Wθ«

Repeat until state 0 (END) is reached.

I⁻⁴θD⎚

Generate the correct output value.

≔⎇S⊕﹪θ³⊖θθ

If the input is not empty, then go the the previous state (increment the internal value, but 3 becomes 1), otherwise go to the next state (decrement the internal value).

\$\endgroup\$
3
\$\begingroup\$

Javascript, 38 bytes

f=(n=1)=>(n+=!prompt(n)*4)-3&&f(n%3+1)

Empty string as true

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Can't you just use prompt(n)? \$\endgroup\$
    – Neil
    Dec 28, 2023 at 0:48
2
\$\begingroup\$

Vyxal 3, 19 bytes

1{:|Ọ"ᵈḄᵇ“f2Ẇ0pi?ȯi

Try it Online!

A single number is all you need

Truthy is defined as standard vyxal truth

Explained

1{:|Ọ"ᵈḄᵇ“f2Ẇ0pi?ȯi­⁡​‎‎⁡⁠⁡‏‏​⁡⁠⁡‌⁢​‎⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁡‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏⁠‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁤⁢‏⁠‎⁡⁠⁤⁣‏‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁤⁤‏‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁢⁡⁡‏⁠‎⁡⁠⁢⁡⁢‏⁠‎⁡⁠⁢⁡⁣‏‏​⁡⁠⁡‌­
1                    # ‎⁡Start with 1 on the stack. This is the initial state
 {:|                 # ‎⁢While the top of the stack is truthy:
    Ọ                # ‎⁣  Print it without popping. This prints the current state
     "ᵈḄᵇ“           # ‎⁤  Push the number 233101 to the stack 
          f2Ẇ        # ‎⁢⁡Flatten it and divide it into chunks of size 2. This is the state map. The first number in a pair is the state to go to when false input. The second number is the true jump. 
             0p      # ‎⁢⁢  Prepend a 0 to indicate a halt state
               i     # ‎⁢⁣  Retrieve the pair corresponding to the current state
                ?ȯi  # ‎⁢⁤  And get the next state based on the truthiness of the input
💎

Created with the help of Luminespire.

\$\endgroup\$
1
\$\begingroup\$

brainfuck, 111 bytes

++++++++++>>-[<+>-----]<-->---[<.<.>>>>>,----------[<[-]+>,----------]<[<[--<--<-->>>-]>[<+<+<+>>>->]<]<+<+<+>]

Try it online!

An empty string (followed by a line feed) is truthy, any other input is falsy.

\$\endgroup\$
1
\$\begingroup\$

Perl, 123 bytes

I:print 1;$i=<STDIN>;chomp$i;goto K if$i;J:print 2;$i=<STDIN>;chomp$i;goto I if$i;K:print 3;$i=<STDIN>;chomp$i;goto J if$i;

Attempt This Online!

The predicate here is Perl truth.

\$\endgroup\$
1
\$\begingroup\$

Rust, 136 bytes

fn main(){let mut c=1;while 4>c{print!("{c}
");let y=&mut "".into();std::io::stdin().read_line(y);c+=if "
"!=y{if c==1{c=4}-1}else{1}}}

Expanded (I also replaced newlines inside string literals by regular \n):

fn main(){
    let mut c=1;
    while 4>c {
        print!("{c}\n");
        let y=&mut "".into();
        std::io::stdin().read_line(y);
        c+=if "\n"!=y {
            if c==1 { c = 4 }
            -1
            
        } else {
            1
        }
    }
}
```
\$\endgroup\$
1
\$\begingroup\$

APL(NARS), 40 chars

P
⎕←1⋄→3×⍳''≡⍞
⎕←2⋄→1×⍳''≡⍞
⎕←3⋄→2×⍳''≡⍞

1+3*12+3=40 Predicate would be here "True if the input line is empty"

\$\endgroup\$
1
\$\begingroup\$

Python 3.8, 108 bytes

p=print
i=input
def a():p(1);c()if i()else b()
def b():p(2);a()if i()else c()
def c():
 p(3)
 if i():b()
a()

Try it online!

The predicate checking the input is truthy if the inputted string is nonempty.

\$\endgroup\$
0
\$\begingroup\$

C (GNU Extension), 311 Bytes

#include <stdio.h>
#define G goto
int main(){int a,b,c,d,e,f,i;char*h="Hello, world!";void*j[3][2]={{&&x,&&y},{&&y,&&w},{&&z,&&x}};w:i=0;q:a=e=f=1;b=c=d=0;G L;o:if(c){puts(a+e+f?"1":"0");G*j[i][a||e||f];}a=a?b>47&&b<58:0;e=e?b==h[d-1]:0;f=f?b==32:0;L:b=getchar();d++;c=b==10;G o;z:return 0;y:i=2;G q;x:i=1;G q;}

This code (ab)uses the GNU extension Labels as Values and gotos.

Things seen as truthy:

  • A sequence of digits (allows 0000000...)
  • The exact string "Hello, world!"
  • A sequence of space
  • An empty string

Explained

#include <stdio.h>

//to save space
#define G goto

int main() {
    //a stores if the input is an integer
    int a;
    //b stores the char we currently act upon
    int b;
    //c stores if the end of the current input line has been reached
    int c;
    //d counts the number of chars in the current input, used when testing for hello world
    int d;
    //e stores if the input is the hello world
    int e;
    //f stores if the input consists of space
    int f;
    //i stores the current state, goes from 0 to 2
    int i;
    //this is used for comparisons to find out if the input is hello world
    char *h = "Hello, world!";
    //this is a jump table, it is used to emulate something like a switch using gotos
    void *j[3][2] = {
        {&&x, &&y}, //these are where one can go from state 0 using what result
        {&&y, &&w}, //go from state 1
        {&&z, &&x}  //go from state 2
    };

    //the labels w x y z are the different states
    //w is state 0, the beginning
    //x is state 1
    //y is state 2
    //z is state 3, the end state

    //this is state 0
    w:
    i = 0;

    //this resets all the variables to their default values
    q:
    a = e = f = 1; //at the beginning of the line parsing, we assume all the things to be true as we later test if they are wrong
    b = c = d = 0;
    G L;

    //this are two things combined: the output in case the end of the line has been reached & the check for all the different things we consider truthy
    o:
    if(c){
        //this is the output, the shorthand if is true in case any of them are non zero
        puts(a + e + f ? "1" : "0");
        //this selects the next state to jump to, based on the current state i and the result, and does the goto
        G *j[i][a || e || f];
    }
    //the way these assignments work is that we only test if the condition still is true if it still is true. In case it ever is false we do not try to test again
    a = a ? b > 47 && b < 58 : 0; //this tests for digits, assumes ascii as digits are from 48 to 57
    e = e ? b == h[d-1] : 0; //this tests for hello world, in case the input looks like hello world but goes on with the exact (random) data as stored in the compiled file this can cause a buffer overrun!
    f = f ? b == 32 : 0; //this tests for space, assumes ascii where ' ' is 32

    //this gets the next character in the line
    L:
    b = getchar();
    d++;
    c = b == 10; //this tests for end of line by looking for '\n' which, assuming ascii, is 10
    G o;

    //this is state 3, the end
    z:
    return 0;

    //this is state 2
    y:
    i = 2;
    G q;

    //this is state 1
    x:
    i = 1;
    G q;
}
\$\endgroup\$
1
  • \$\begingroup\$ I think you misinterpreted the demonstration of "possible choices of the predicate". \$\endgroup\$ Dec 29, 2023 at 21:46

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.