You had me at hello

30

4

Task

Read in a possibly infinite text stream or file, outputting its contents until the word hello has been output, abiding to the following rules.

  • Once hello has been output, your code should quit immediately. It should not wait for a newline for example.

  • Your code should output as it goes. That is it shouldn't read in a huge amount of input and then start outputting.

  • If the stream/file doesn't contain hello, your code should just carry on outputting the input forever or until the end of the stream/file is reached.

  • This is a case sensitive challenge, so hello is not equal to Hello.

  • You may assume that the input consists solely of printable ASCII characters and newlines.

  • Your code can't expect that the text will be terminated by a newline or that there will be any newlines at all in the input. Also, you code cannot assume that it will run on a machine with an infinite amount of memory.

  • You may assume that your code will be called from an empty directory.

Example input stream

I once had a horse called hellopina.

Output

I once had a horse called hello

Tip

Run yes | tr -d \\n | <your program> to check if it works with infinite streams. If it doesn't print anything and/or leaks memory, the program doesn't comply with the spec. It should print yyyyyyyyyyyyyyyyyyyyyy... forever with no newlines.

user9206

Posted 2017-04-04T12:12:07.127

Reputation:

1Are we permitted to read anything after the "hello"? The question seems to prohibit any additional read, which could be problematic in languages such as (Standard) C, that provide buffered input with automatic read-ahead. – Toby Speight – 2017-04-06T11:00:26.900

You should probably change teh accepted answer to the assembly one, as it's 2 byte shorter. – Rɪᴋᴇʀ – 2017-04-18T14:49:17.073

@Riker It would be great if someone could test it or at least say they believe it works first. – None – 2017-04-18T14:50:06.463

Answers

2

Jelly, 24 bytes

“Ṣẉ»ẇ⁸Ṇȧ®
ṫ-3;ƈ©Ȯ¤µ⁺Ç¿ṛ“

Try it online!

Explanation:

ṫ-3;ƈ©Ȯ¤µ⁺Ç¿ṛ“ Main link. Arguments: 0
ṫ-3            Truncate the list to its 4 last elements.
   ;ƈ©Ȯ¤       Store a character from STDIN in the register, print it, and append it to the list (list is initially [0]).
        µ      Start a new monadic chain, everything to the left is a link.
          Ç    Execute the helper link with the existing list as its argument.
         ⁺ ¿   Do-while loop, left link is body, right link is condition.
            ṛ“ When the loop ends, replace the return value with [] (invisible on output).

“Ṣẉ»ẇ⁸Ṇȧ® Helper link. Arguments: string
“Ṣẉ»ẉ⁸Ṇ   Check if "hello" isn't in the string.
        ® Return the character we stored in the register.
       ȧ  Check if both of the above are truthy.

Erik the Outgolfer

Posted 2017-04-04T12:12:07.127

Reputation: 38 134

26

C (gcc), 81 80 76 75 72 71 70 69 bytes

main(n,c){while(~(c=getchar())&n-0xb33def<<7)n=n<<5^putchar(c)/96*c;}

Try it online!

How it works

This is a full program. We define a function f for our purposes. To save bytes, it is declared with two argument that default to int. This is undefined behavior, but in practice, n will be initialized as 1 when running the program without additional arguments, c will hold the lower 32 bits of the pointer to the argument vector

While the condition

~(c=getchar())&n-0xb33def<<7

holds, we'll execute the while loop's body:

n=n<<5^putchar(c)/96*c

To fully understand the condition, we must first examine the body. For now, all we observe is that c=getchar() reads a single byte from STDIN (if possible) and stores it in the variable c.

The byte sequence hello looks as follows in different representations.

char     decimal     binary (8 bits)
'h'      104         0 1 1 0 1 0 0 0
'e'      101         0 1 1 0 0 1 0 1
'l'      108         0 1 1 0 1 1 0 0
'l'      108         0 1 1 0 1 1 0 0
'o'      111         0 1 1 0 1 1 1 1

All of these fall in the range [96, 192), so c/96 will evaluate to 1 for each of these bytes, and to 0 for all remaining ASCII characters. This way, putchar(c)/96*c (putchar prints and returns its argument) will evaluate to c if c is `, a lowercase letter, one of {|}~, or the DEL character; for all other ASCII characters, it will evaluate to 0.

n is updated by shifting it five bits to the left, then XORing the result with the result from the previous paragraph. Since an int is 32 bits wide (or so we assume in this answer), some of the shifted bits might "fall off the left" (signed integer overflow is undefined behavior, but gcc behaves as the x64 instruction it generates here). Starting with an unknown value of n, after updating it for all characters of hello, we get the following result.

 n  ?????????????????????????|???????
'h'                          |    01101000
'e'                          |         01100101
'l'                          |              01101100
'l'                          |                   01101100
'o'                          |                        01101111
-----------------------------+--------------------------------
    <------ discarded ------>|???????0101100110011110111101111

Note that the lower 25 bits form the integer 0xb33def, which is the magic constant in the condition. While there is some overlap between the bits of two adjacent bytes, mapping bytes below 96 to 0 makes sure that there aren't any false positives.

The condition consists of two parts:

  • ~(getchar()) takes the bitwise NOT of the result of reading (or attempting to read) a byte from STDIN.

    If getchar succeeds, it will return the value of the read byte as an int. Since the input consists entirely of ASCII characters, the read byte can only have its lower 7 bits set, so the bitwise NOT will have its highest 25 bits set in this case.

    If getchar fails (no more input), it will return -1 and the bitwise NOT will be 0.

  • n-0xb33def<<7 subtracts the magic constant from before from n, then shifts the result 7 units to the left.

    If the last 5 read bytes were hello, the lowest 25 bits of n will be equal to 0xb33def and the subtraction will zero them out. Shifting the difference will yield 0 as the 7 highest bits will "fall off the left".

    On the other hand, if the last 5 read bytes were not hello, one of the lowest 25 bits of the difference will be set; after shifting, one of the highest 25 bits will be.

Finally, if getchar was successful and we didn't print hello yet, the bitwise AND, all of the highest 25 bits of the left operand and at least one of the highest 25 bits of the right one will be set. This way, & will yield a non-zero integer and the loop continues.

On the other hand, if the input is exhausted or we have printed hello already, one of the bitwise AND's operand will be zero, and so will the result. In this case, we break out of the loop and the program terminates.

Dennis

Posted 2017-04-04T12:12:07.127

Reputation: 196 637

You probably ought to mention that this depends on the input being encoded in ASCII, before delving into the explanation. – Toby Speight – 2017-04-06T11:08:29.757

2@TobySpeight I don't think it's common to specify this. What kind of ASCII incompatible encoding would you expect a C answer to use? – Dennis – 2017-04-06T13:45:24.040

EBCDIC is the obvious encoding that's not ASCII. C doesn't prescribe any particular character encoding (only that the decimal digits must be represented by consecutive values, in order). – Toby Speight – 2017-04-06T14:45:51.243

the above program stop if the stream contain the not ascii string "«úá÷o" 1: o 111 6f 2: ÷ 246 f6 3: á 160 a0 4: ú 163 5: « 174 – RosLuP – 2017-04-10T15:14:16.093

@RosLuP The challenge spec guarantees that the input will consist of printable ASCII characters and newlines. – Dennis – 2017-04-10T18:32:21.443

19

Bash, 74 75 103 99 88 82 76 bytes

-10 bytes thanks to @DigitalTrauma!
-11 bytes thanks to @manatwork!
-6 bytes thanks to @Dennis!

IFS=
b=ppcg
while [ ${b/hello} ];do
read -rN1 a
b=${b: -4}$a
echo -n $a
done

Explanation:

IFS=    # making sure we can read whitespace properly
b=ppcg  # set the variable b to some arbitrary 4 letter string

while [ ${b/hello} ]; do  # while the variable b doesn't contain "hello", do the following
    read -rN1 a           # get input
    b=${b: -4}$a          # set b to its last 4 chars + the inputted char
    echo -n $a            # output the inputted char
done

Try it online!

betseg

Posted 2017-04-04T12:12:07.127

Reputation: 8 493

2This is great! I was hoping there would be a bash answer. – None – 2017-04-04T12:32:46.957

13

Labyrinth, 43 41 bytes

Thanks to Sp3000 for saving 2 bytes.

<_%-742302873844_::%*:*:420#+.:%):,*652_>

Try it online!

Explanation

The basic idea is to encode the last five characters in base 256 in a single integer. When a new character comes in, we can "append" it by multiplying the integer by 256 and adding the new code point. If we want to look only at the last 5 characters, we take the value modulo 2565 = 240 = 1099511627776. Then we can simply check whether this value is equal to 448378203247, which is what we get when we treat the code points of hello as base-256 digits.

As for the code... <...> is a bit of a Labyrinth idiom. It allows you to write an infinite loop without any conditional control flow on a single line, saving a lot of bytes on spaces and linefeeds. The main condition for this to work is that there are two disposable values on top of the stack when we reach the < (we normally use 0s for that, but the actual value is arbitrary).

Of course, the program does need some conditional logic to figure out when to terminate. But conditionally ending the program is possible by dividing by a value which is zero when we want the program to end. The <...> construct works by shifting the entire row left (cyclically) when the IP is at the left end, and then immediately shifting it back into position. This means that the code is actually executed right to left. Let's reverse it:

_256*,:)%:.+#024:*:*%::_448378203247-%_

This is one iteration of the loop which reads a character, terminates if we've reached EOF, prints the character, adds it to our encoding, truncates that to 5 characters, checks for equality with hello and repeats. Here is how that works in detail (remember that Labyrinth is stack-based):

_256*            Multiply the encoding by 256 in preparation for the next iteration.
,                Read one byte from STDIN.
:)%              Duplicate, increment, modulo. If we hit EOF, then , returns
                 -1, so incrementing and modulo terminates the program due to
                 the attempted division by zero. However, if we did read a
                 character, we've just compute n % (n+1), which is always n itself.
:.               Print a copy of the character we just read.
+                Add it to our encoding (we'll make sure to multiply the
                 encoding by 256 at the end of the iteration, so there's room
                 for our new character).
#024             Push 1024, using the stack depth to push the initial 1.
:*:*             Square it twice. That gives 2^40.
%                Take the encoding modulo 2^40 to truncate it to the last 5
                 characters.
::               Make two copies of the encoding.
_448378203247    Push the value that corresponds to "hello".
-                Subtract it from the encoding, giving zero iff the last 5
                 characters were "hello".
%                Take the other copy of the encoding modulo this value, again
                 terminating if we've reached "hello".
                 The actual value of this modulo - if it didn't terminate the
                 the program - is junk, but we don't really care, we just need
                 any disposable value here for the <...>
_                We push a zero as the second disposable value.

Martin Ender

Posted 2017-04-04T12:12:07.127

Reputation: 184 808

8

Bash, 73 68 66 bytes

IFS=
[[ $1 != olleh ]]&&read -rN1 c&&echo -n $c&&exec $0 $c${1::4}

Assumes a directory with no or only hidden files. Must be run as <path/to/script>.

Try it online!

How it works (outdated)

At the beginning of the while loop, we first test if the string in the variable s (initially empty) equals olleh (hello backwards, olé), and return 0 (match) or 1 (not a match) accordingly. While formally part of the loop's condition, the outcome won't affect it on its own, as only the last command before do determines if the condition holds.

Next, we set the internal field separator to the empty string (so read won't choke on whitespace), read raw bytes (-r) from STDIN and store them in c. $? is the exit code of the previous command, so this reads exactly one (-N1) byte for a non-match and zero bytes (-N0). Reading zero bytes, whether its due to hitting EOF or because -N0 was specified, causes read to exit with status code 1, so the while loop will end; otherwise, the body is executed and we start over.

In the body, we first print the byte we read, then update s with s=$c${s::4}. This prepends the read byte to (up to) the first four bytes in s, so s will equal olleh once hello has been printed.

Dennis

Posted 2017-04-04T12:12:07.127

Reputation: 196 637

Very nice indeed! – None – 2017-04-04T19:48:59.317

8

Brainfuck, 658 bytes

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

Over 500 bytes are in the constants which I need to golf a bit.

It essentially is a state machine, so infinite input is not a problem.

This is the slightly commented version

+
[
  >,.
  >h
  [-<->]
  +<
  [
    >-<[-][in input spot, not h]
  ]
  >
  [
    -
    <
    [in input spot, h has been read]
    ,.
    >e
    [-<->]
    +<
    [
      >-<[-][in input spot, not e]
    ]
    >
    [
      -
      <
      [in input spot, e has been read]
      ,.
      >l
      [-<->]
      +<
      [
        >-<[-][in input spot, not l]
      ]
      >
      [
        -
        <
        [in input spot, l has been read]
        ,.
        >l
        [-<->]
        +<
        [
          >-<[-][in input spot, not l]
        ]
        >
        [
          -
          <
          [in input spot, l has been read]
          ,.
          >o
          [-<->]
          +<
          [
            >-<[-][in input spot, not o]
          ]
          >
          [
            -
            <
            [in input spot, o has been read]
            <->>
          ]
        ]
      ]
    ]
  ]
  <<
]

jvluso

Posted 2017-04-04T12:12:07.127

Reputation: 81

This looks fun :) – None – 2017-04-04T21:36:18.400

Welcome to Programming Puzzles and Code Golf StackExchange! – betseg – 2017-04-06T11:24:03.717

1This code has multiple issues, but the biggest issue is that it doesn't include logic to handle cases like ahehellob properly; in the middle of a potential match, it only checks for the next letter in hello and doesn't look for an h to start over. – Mitch Schwartz – 2017-04-06T17:06:05.360

8

brainfuck, 117 bytes

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

Formatted:

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

Try it online.

This initializes the tape with the characters in hello offset by 107, spaced out with one value every three cells, then keeps track of the last five characters seen and checks for a match with every new character processed, using a flag to the right of the string to keep track of whether there has been a match.

Mitch Schwartz

Posted 2017-04-04T12:12:07.127

Reputation: 4 899

7

Ruby, 46 60 bytes

a="";loop{q=$<.getc;~p if a[-5..-1]=="hello"||!q;a+=q;$><<q}

Try it online!

Reads characters from stdin until the last 5 are hello, then outputs the string (or until no characters are left in stdin). Terminates with error.

Equivalent to:

a = ""
loop {
    q = $<.getc
    ~p if a[-5..-1] == "hello" || !q
    a += q
    $><< q
}

Or, more ungolfed:

a = ""
loop do
    q = STDIN.getc
    break if a[-5..-1] == "hello" or not q
    a += q
    print q
end

Conor O'Brien

Posted 2017-04-04T12:12:07.127

Reputation: 36 228

1a grows everytime a char is read. Does this crash if the input is infinite? – betseg – 2017-04-07T05:39:52.017

@betseg hm, maybe. Let me see if I can fix that – Conor O'Brien – 2017-04-07T05:41:06.533

7

Python 3, 120 116 104 Bytes

Works with infinite streams, first time golfing, any tips are appreciated.

import sys
a=1
c=''
while(a):
    a=sys.stdin.read(1)
    if a:print(end=a)
    c=(c+a)[-5:]
    if c=='hello':break

Thanks @DJMcMayhem for saving some bytes :)

R. Martin

Posted 2017-04-04T12:12:07.127

Reputation: 71

Welcome to the site! c=[0,c+1]['hello'[c]==a] should save you some bytes. Also, a=1 is shorter too. – James – 2017-04-04T20:11:21.913

2You don't need the parenthesis for while in Python. – PurkkaKoodari – 2017-04-05T13:40:03.950

7

Cubix, 94 83 82 79 63 56 bytes

p>q'-?w.uh'e@U7.'hqi?oqB-!ul.-..$WWu_q<o'\;>....6t?.../!@

Expanded:

        p > q '
        - ? w .
        u h ' e
        @ U 7 .
' h q i ? o q B - ! u l . - . .
$ W W u _ q < o ' \ ; > . . . .
6 t ? . . . / ! @ . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Notes

  • The interpreter disables the input field when the program starts. As such, an infinite stream of input is impossible. This program takes the input character-by-character, so if it weren't for this limitation, it would work properly.
  • This program doesn't clear up the stack, and it gets messy very quickly. Since the machine this will be used on apparently can give infinite input streams, it seems reasonable to assume that it also has infinite memory.
  • Any and all golfing help is much appreciated.

Try it online

You can try the program here.

Explanation

General idea

The general idea is that we want to read a character, and then check it against varying characters (first h, then e, then l etc.). To keep track of the character we have missed, we keep it at the very bottom of the stack. When we need it, we can easily bring it to the top again.

Read/Write loop

The read-write loop is simply the 5th line. All characters that are not used are replaced by no-ops (.):

        . . . .
        . . . .
        . . . .
        @ . . .
' h q i ? o q B - ! u l . - . .
. . . . _ . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

This can be split up in two parts: Reading and (writing and checking). The first part contains the instructions up to and including the question mark. The second part up is the rest of the line. Because this loops around, we assume we start with a stack of [...]

    @
'hqi?
    _

Explanation
'h          Push the character code of the h
            Stack: [..., 104]
  q         Send it to the bottom
            Stack: [104, ...]
   i        Read one character of the input (-1 for EOF)
            Stack: [104, ..., input]
    ?       Start of condition:
              if (input < 0):
    @           execute '@', ending the program
              if (input = 0):
                continue going right
              if (input > 0):
    _           turn to the right, reflect back ('_') and
                turn right again, effectively not changing 
                the direction at all

The second part (writing and checking) is linear again. The stack starts as [next-char, ..., input]. We abstracted the next character, because that changes later in the program.

oqB-!ul.-  Explanation
o          Output the character at the top of the stack
 q         Send the input to the bottom of the stack
           Stack: [input, next-char, ...]
  B        Reverse the stack
           Stack: [..., next-char, input]
   -       Push the difference of the top two characters, which
           is 0 if both are equal, something else otherwise
           Stack: [..., next-char, input, diff]
    !      if (diff = 0):
     u       make a u-turn to the right
           else:
      l.     execute two no-ops
        -    push [input - next-char - input], which is disregarded
             later, so it effectively is a no-op as well.

Now, the IP will start again at the beginning of this loop, resetting the next character to check to h.

Matching the next character

If the IP made a u-turn (i.e. the character we read and printed matched the next character in 'hello'), we need to check what character the input was and depending on that, push the next character to the bottom of the stack. After that, we need to return to the read/write loop, without pushing h to the stack, so we need another way to get there.

First things first: determine what character the input was. The stack looks like this: [..., prev-char, input, 0].

        . . . .
        - ? . .
        u h ' e
        . . . .
. . . . . . . . . ! u . . . . .
. . . . . . . . . \ ; . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

To compare the input, we use the character code of h again. Initially, this was because I didn't really know how I was going to handle this and h is the first character in the string to check for, but it ended up being quite convenient. If we subtract the character code of h from the input, we get -3 if the input is e, 0 if the input is h, 4 if the input is l and 7 if the input is o.

This is useful, because the ? command lets us easily separate negative values from positive values and zero. As such, if the IP turns left, the difference was negative, so the input was e, so the next character should be an l. If the IP continues going straight, the difference was 0, so the input was h, so the next character should be an e. If the input is an l or an o, the IP turns right.

All instructions executed before the aforementioned question mark are:

;!e'h-     Explanation
;          Delete the top of the stack
           Stack: [..., prev-char, input]
 !         if (input = 0):
  e          execute 'e' (no-op)
   'h      Push the character code of h
           Stack: [..., prev-char, input, 104]
     -     Push the difference of the input and 104
           Stack: [..., prev-char, input, 104, diff]

Now the IP changes its direction as detailed above. Let's go over the different possibilities.

Input 'e'

First we'll consider the input e, which causes the IP to move upwards from the ?, since the difference is 3. All irrelevant characters have been removed from the cube.

        . > q '
        . ? . .
        . . . .
        . . . .
. . q . . . . . . . . l . . . .
$ W W . . . . . . . . > . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

The characters are executed in this order (excluding some control-flow characters):

q'l$WWq
q           Save the difference (-3) to the bottom of the stack so
            we can tell whether the l on the bottom of the stack is
            the first or the second l in hello
            Stack: [-3, ...]
 'l         Push the character code of l to the stack
            Stack: [-3, ..., 108]
   $W       no-op
     W      Sidestep into the loop
      q     Send the character code to the bottom
            Stack: [108, -3, ...]

Now the IP has reached the read/write loop again.

Input 'h'

If the input was 'h', the difference is 0, so the IP doesn't change its direction. Here's the cube again, with all irrelevant characters removed. Since this path includes quite a few no-ops, all the no-ops it passes have been replaced by &. The IP starts at the question mark.

        . . . .
        . ? w .
        . . ' e
        . . . .
. . . . . . . . . ! . . . . . .
. . . u _ q < . . \ . . . . . .
. . ? & & & / . . & . . . . . .
. . & . . . . . . & . . . . . .
        . . . .
        & & & &
        . . . .
        . . . .

The instructions executed are:

'e!\?q_
'e          Push the character code of the e
            Stack: [..., 101]
  !         if (101 = 0):
   \          reflect away (effectively a no-op)
    ?       if (101 > 0):
              turn right (always happens)
     q      Move 101 to the bottom of the stack
            Stack: [101, ...]
      _     No-op

And now we're entering the read/write loop again, so we're done.

Other inputs

All other inputs result in a positive difference, so the IP turns right at the question mark. We still need to separate the l and the o, so that's what we'll do next.

Separating the 'l' and 'o'

Keep in mind that the difference is 7 for o and 4 for l and that we have to end the program if the input was an o. Here's the cube again with the irrelevant parts replaced by a . and the no-ops the IP crosses have been replaced by ampersands.

        . . q .
        . ? w .
        . h ' .
        . U 7 .
. . . . . . . . . . . . . - . .
. . . . . . . . . . . . . & . .
. . . . . . / ! @ . . . . & . .
. . . . . . & . . . . . . & . .
        . . & .
        . . & .
        . . & .
        . . & .

h7'wq-!@    
h           no-op
 7          Push 7 to the stack
            Stack: [..., diff, 7]
  'wq       Push w to the stack and send it to
            the bottom. We don't care about it,
            so it's now part of the ellipsis.
            Stack: [..., diff, 7]
     -!     if (diff = 7):
       @        End the program

Discerning between the two 'l's

So, now we've we know that the input was an l, but we don't know which l. If it's the first, we need to push another l to the bottom of the stack, but if it's the second, we need to push an o. Remember we saved -3 to the bottom of the stack just before we pushed the first l? We can use that to separate the two branches.

        . . . .
        . . . .
        . . . .
        . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
6 t ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . . 
        . . . .
        . . . .

The stack starts as [..., -3 or 140, ...]

Explanation
6t?         
6t          Take the 6th item from the top and move
            it to the top (which is either -3 or 140)
  ?         If that's positive, turn right, otherwise,
            turn left

First 'l'

If this was the first 'l', we need to push another 'l'. To save bytes, we use the same characters as for the first 'l'. We can simplify the stack to [...]. Here's the relevant part of the cube, with no-ops replaced by ampersands.

        p > q '
        . . . .
        . . . .
        . . . .
' . q . . . . . . . . l . . . .
$ W W . . . . . . . . > & & & &
. . ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

The following instructions are executed:

$'pq'lq
$'          no-op
  pq        no-op
    'l      Push the character code of l
            Stack: [..., 108]
      q     Send it to the bottom
            Stack: [108, ...]

We're about to enter the read/write loop, so we're done with this branch.

Second 'l'

If the input was the second 'l' in 'hello', the IP turned right at the question mark. Once again, we can simplify the stack to [...] and the IP starts at ?, pointing south this time.

        . . . .
        . . . .
        . . . .
        . . . .
. . . . . . . . . . . . . . . .
. . . u _ q < o ' \ . . . . . .
. . ? . . . . . . & . . . . . .
. . & . . . . . . & . . . . . .
        . . . .
        & & & &
        . . . .
        . . . .

The instructions executed are:

'oq_
'o          Push the character code of 'o'
            Stack: [..., 111]
  q         Move the top item to the bottom
            Stack: [111, ...]
   _        No-op

And the IP is about to enter the read/write loop again, so we're done with this branch as well.

Luke

Posted 2017-04-04T12:12:07.127

Reputation: 4 675

An heroic effort! – None – 2017-04-18T05:54:53.337

6

Haskell, 41 47 43 bytes

f l|w@"hello"<-take 5l=w|a:b<-l=a:f b|1<2=l

Haskell's laziness handles the infinite input/output quit well.

Try it online!

Edit: didn't handle finite input - fixed. Thanks @Leo for pointing out.

Edit II: @Ørjan Johansen saved 4 bytes. Thanks!

nimi

Posted 2017-04-04T12:12:07.127

Reputation: 34 639

2The input may also be finite, so I think you need to deal with the case when you reach the end of the string – Leo – 2017-04-04T19:40:17.193

@Leo: Oops, totally missed it. Fixed. – nimi – 2017-04-04T20:03:14.847

2The first guard can be shortened to |w@"hello"<-take 5l=w. – Ørjan Johansen – 2017-04-17T23:56:09.150

@ØrjanJohansen: oh, that's a nice one. Thanks! – nimi – 2017-04-18T14:29:30.763

5

C++, 142 141 bytes

#import<iostream>
void f(std::istream&i){i>>std::noskipws;char c;for(std::string s="     ";s!="hello"&&i>>c;)s.erase(0,1),s+=c,std::cout<<c;}

Try it online!

Steadybox

Posted 2017-04-04T12:12:07.127

Reputation: 15 798

Would this be possible with GCC? I don't see #import in GCC C++ programs... – ckjbgames – 2017-04-04T17:08:02.717

1@ckjbgames #import is a deprecated GCC extension. – Steadybox – 2017-04-04T17:44:38.607

1

@ckjbgames more info here: http://stackoverflow.com/questions/172262/c-include-and-import-difference

– iFreilicht – 2017-04-05T12:05:25.363

@iFreilicht That question actually made me ask that. – ckjbgames – 2017-04-05T19:09:57.847

1

@ckjbgames you might want to take a look at the second answer: http://stackoverflow.com/a/172264/2533467 "The import in gcc is different from the import in VC++. It is a simple way to include a header at most once only."

– iFreilicht – 2017-04-06T13:33:56.093

3

Node, 124 bytes

with(process)with(stdin)on('data',d=>[...d].map(c=>(s=(stdout.write(c),s+c).slice(-5))=='hello'&&exit()),setEncoding(),s='')

Not assuming that the stream will fit in available memory.

Neil

Posted 2017-04-04T12:12:07.127

Reputation: 95 035

3

PHP, 57 55 53 bytes

while(hello!=$s=substr($s.$c,-5))echo$c=fgetc(STDIN);

as there are no infinite files, I take input from STDIN. Run with -nr.

Loop through input, print the current character, append it to $s, cut $s to the last 5 characters. Break loop when $s is hello.

Titus

Posted 2017-04-04T12:12:07.127

Reputation: 13 814

3

C#, 134 bytes

using C=System.Console;class P{static void Main(){var s="";for(int c;(c=C.Read())>=0&!s.Contains("olleh");C.Write(s[0]))s=(char)c+s;}}

Try It Online

Reads a character, checks it isn't -1 (EOS) and that we havn't seen "hello" yet, then prepends it to a string, and writes the character out. We prepend because s[0] is a lot shorter than (char)s. This has a quadratic cost in the length of the string, as it has to allocate and scan the entire input each time it reads a character (this will crash after 2GB of input due to constraints in the CLR, is that allowed?)

using C=System.Console;

class P
{
    static void Main()
    {
        var s="";
        for(int c;(c=C.Read())>=0&!s.Contains("olleh");C.Write(s[0]))
            s=(char)c+s;
    }
}

For a (longer: 142 bytes) version which won't run out of memory, and which has constant per-character cost, see below:

using C=System.Console;class P{static void Main(){var s="     ";for(int c;(c=C.Read())>=0&s!="hello";C.Write(s[4]))s=s.Substring(1)+(char)c;}}

This one keeps the last 5 characters in a 5-length string, which means short comparisons, and cheap last-char lookup, but is considerably more expensive to update.

using C=System.Console;

class P
{
    static void Main()
    {
        var s="     ";
        for(int c;(c=C.Read())>=0&s!="hello";C.Write(s[4]))
            s=s.Substring(1)+(char)c;
    }
}

VisualMelon

Posted 2017-04-04T12:12:07.127

Reputation: 3 810

3

Vim, 39 bytes

:im hello hello:se noma
:map : i

i

Try it online!

:im hello                        "Remap 'hello' in insert mode to
          hello                "write hello, then hit escape
                 :se noma       "then set the buffer to not-modifiable
:map : i                        "THEN remap ':' to 'i' so that can't be changed

i                                "enter insert mode and await an infinite stream of input

nmjcman101

Posted 2017-04-04T12:12:07.127

Reputation: 3 274

Is this an accepted input method for Vim? I thought Vim programs usually expect the input to be already in the buffer before they start. – Martin Ender – 2017-04-04T19:17:18.733

To be honest I don't know? That's true, but hardly allows for an infinite stream, so I just did it this way without really thinking that hard about it. – nmjcman101 – 2017-04-04T19:36:30.790

What happens if there is an escape character in the input stream? – dim lost faith in SE – 2017-04-07T07:04:00.663

@dim I asked, and OP specified only printable ASCII and newlines. ESC is not included in printable ASCII afaik – nmjcman101 – 2017-04-10T02:30:30.503

3

PowerShell, 111 bytes

There is probably a better way to do this, but I can't see it at the moment.

while(($x=($x+$host.UI.RawUI.ReadKey("IncludeKeyDown").character+"     ").substring(1,5)).CompareTo("hello")){}

This reads the key strokes without supressing the echo. The character is added to $x which is trimmed to the last 5 characters and compared to "hello". This carries on until the comparison is true.

Note: this does not work in the PowerShell ISE. ReadKey is disabled in that environment.

MickyT

Posted 2017-04-04T12:12:07.127

Reputation: 11 735

3

Python 3 (Linux), 73 72 bytes

s=c='_';I=open(0)
while'olleh'!=s>''<c:c=I.read(1);s=c+s[print(end=c):4]

Thanks to @MitchSchwartz for golfing off 1 byte!

Try it online!

Dennis

Posted 2017-04-04T12:12:07.127

Reputation: 196 637

I don't understand. How does the condition for while evaluate properly? It looks like you're comparing a boolean to an empty string. – iFreilicht – 2017-04-06T15:07:55.883

1s[print(end=c):4] saves a byte – Mitch Schwartz – 2017-04-06T18:12:37.193

1@iFreilicht Python parses chained conditionals as one would in math (a<b<c, for example). The condition is a shorthand for 'olleh'!=s and s>''and''<c). The middle test isn't needed, but chaining them is shorter than the straightforward 'olleh'!=s and''<c. – Dennis – 2017-04-07T16:49:41.053

@MitchSchwartz That it does. Thank you! – Dennis – 2017-04-07T16:51:51.307

3

Scheme 115 bytes

(do((c(read-char)(read-char))(i 0(if(eqv? c(string-ref"hello"i))(+ i 1)0)))((or(eof-object? c)(= i 5)))(display c))

Readable version:

(do ((c (read-char) (read-char))                            ; read stdin
     (i 0 (if (eqv? c (string-ref "hello" i)) (+ i 1) 0)))  ; check target
    ((or (eof-object? c) (= i 5))) ; finish if end of stdin, or word found
  (display c))                     ; display each character

This takes an individual char from stdin each time around the loop, and marks off its position on the target word as it meets the characters of "hello".

Stops when the input runs out or "hello" has been seen. No memory used on infinite stream.

peter

Posted 2017-04-04T12:12:07.127

Reputation: 31

Cool answer, welcome to the site! – James – 2017-04-05T16:53:51.063

3

AWK, 95 bytes

BEGIN{RS="(.)"
split("hello",h,"")}{for(j=0;++j<6;){c=RT
printf c
if(c!=h[j])next
getline}exit}

There are 2 things I learned here:
1) To split records between characters use RS="(.)" and then RT must be used instead of $1
2) ORS is used by print and is defaulted to "\n"
3) I can't count to 2 and using printf is "cheaper" than assigning ORS and using print

Example usage: Place code in FILE

awk -f FILE some_data_file

or

some process | awk -f FILE

Code was tested using Dennis's yes | ... suggestion and I saw lots and lots of ys.

FYI, you can do the RS assignment as an option and pull it out of the BEGIN block via:

awk -v RS='(.)'

Robert Benson

Posted 2017-04-04T12:12:07.127

Reputation: 1 339

Really tricky solution! (Maybe because it's Friday afternoon, but I find it good entry for obfuscated challenge too.) Though I would try a more awkish approach: BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}. – manatwork – 2017-04-07T16:14:35.880

Oddly enough I have almost exactly answer ready to submit an hour ago... and forgot to submit it. :p – Robert Benson – 2017-04-07T16:36:24.693

3

8086 machine code, 22 bytes

00000000  bf 11 01 b4 01 cd 21 ae  75 f6 81 ff 16 01 72 f3  |......!.u.....r.|
00000010  c3 68 65 6c 6c 6f                                 |.hello|
00000016

Equivalent assembly code:

org 0x100
use16
a:  mov di, msg
b:  mov ah, 1       ; read one byte from stdin with echo
    int 0x21        ; dos syscall -> result in AL
    scasb           ; if (DI++ == AL)
    jne a
    cmp di, msg+5
    jb b
    ret
msg db "hello"

user5434231

Posted 2017-04-04T12:12:07.127

Reputation: 1 576

How does it work? – None – 2017-04-17T06:08:48.150

1I added the equivalent assembly code. It basically relies on one very useful DOS syscall, which reads one byte from stdin and echos it back to stdout at the same time. The 8086 also has a single-byte string comparison instruction which comes in handy here. – user5434231 – 2017-04-17T16:34:50.593

2

Ruby, 59 49 48 43 bytes

Now rant-free, shorter, and without memory leak.

s=''
s=$>.putc$<.getc+s[0,4]until'olleh'==s

Saved 5 bytes by getting rid of some parentheses and a space thanks to Dennis

daniero

Posted 2017-04-04T12:12:07.127

Reputation: 17 193

Let us continue this discussion in chat.

– daniero – 2017-04-04T21:03:36.393

2

Pyth, 49 47 bytes

Wn"hello"=>5+kp$__import__("sys").stdin.read(1)

Pyth's not very good at taking a single character of input. Everything in $__import__("sys").stdin.read(1) is simply doing that. Also, it means that this only runs offline.

Everything else is short...

The program is a bodyless while loop. Inside the condition, the program reads a character, prints it back, appends that character to k (which is initially the empty string), trims off all but the last 5 characters of k, and then checks that the result is not "hello".

32 characters are getting one byte of input, 15 characters does the rest.

Tested on Linux, works even with no newline, infinite input, etc.

isaacg

Posted 2017-04-04T12:12:07.127

Reputation: 39 268

2

Lua, 68 64 bytes

l=""while l~="hello"do c=io.read(1)io.write(c)l=l:sub(-4)..c end

Blab

Posted 2017-04-04T12:12:07.127

Reputation: 451

1Change the slicing to l:sub(-4), then you can reduce the initialization of l="". – manatwork – 2017-04-05T16:31:26.230

@manatwork That's neat. Thanks for the tip. – Blab – 2017-04-05T21:02:47.813

1

Röda, 49 47 bytes

{a=[0]*5{|x|[x];a=a[1:]+x;z if[a&""="hello"]}_}

Try it online!

This is an anonymous function that reads characters from its input stream and outputs them until "hello" is found. It uses the array a to track the last characters.

It outputs some junk to STDERR, but I understood that is allowed.

Explanation:

{
    a=[0]*5                /* Initialize the array with 5 zeroes. */
    {|x|                   /* For each x in the input stream: */
        [x];               /* Print x */
        a=a[1:]+x;         /* Add x and remove the sixth last character. */
        z if[a&""="hello"] /* If "hello" is found, crash the program */
                           /* with an undefined variable. */
    }_                     /* End for loop. */
}

fergusq

Posted 2017-04-04T12:12:07.127

Reputation: 4 867

Where is the Roda documentation? – ckjbgames – 2017-04-04T17:10:24.830

@ckjbgames Here. I use the latest version 0.12, which is in its own branch in Github.

– fergusq – 2017-04-04T17:17:54.657

1

Python + msvcrt (Windows), 114 105 bytes

Both of these solutions use information provided by this SO answer.

import sys,msvcrt
x=""
o=sys.stdout
while"hello"!=x[-5:]:c=msvcrt.getch();o.write(c);o.flush();x=x[-4:]+c

Python (Unix terminal), 145 136 135 bytes

Same as above, but for Unix terminal. This version can be partially tested online if you comment out the second line (to avoid an error), except that the input has to be user-entered and newline terminated (only to test online). For the full functionality, you have to run in a terminal.

import sys as s,tty
tty.setraw(s.stdin.fileno())
x=""
o=s.stdout
while"hello"!=x[-5:]:c=s.stdin.read(1);o.write(c);o.flush();x=x[-4:]+c

Partial test online

This requires a terminal to run, otherwise you'll get this error:

termios.error: (25, 'Inappropriate ioctl for device')

Ungolfed

import sys,tty
tty.setraw(sys.stdin.fileno())
x=0
while 1:
 c=sys.stdin.read(1)
 sys.stdout.write(c)
 sys.stdout.flush()
 if"hello"[x]==c:
    x+=1
    if x>5:break
 else:x=0

mbomb007

Posted 2017-04-04T12:12:07.127

Reputation: 21 944

x="" and while"hello"!=x[-5:]:c=sys.stdin.read(1);o.write(c);o.flush();x=x[-4:]+c to save some bytes – ovs – 2017-04-04T17:17:34.550

but x+=c will fail on an infinite stream – ovs – 2017-04-04T18:27:37.593

@ovs I fixed it. The OP clarified the specs. – mbomb007 – 2017-04-04T19:11:45.580

It's much harder in python than I expected! – None – 2017-04-04T19:51:49.883

Yeah, Python doesn't have nice input streaming. – mbomb007 – 2017-04-04T19:57:50.193

In the second one, replace sys with sys as s and subsequently replace all the sys in the code with s. That'll bring down the size to 135 bytes. – Koishore Roy – 2017-04-09T10:19:12.987

1

Java 7, 122 118 124 123 150 141 bytes

void c()throws Exception{String a="aaaaa";for(int b;!a.equals("hello")&(b=System.in.read())>=0;a=a.substring(1)+(char)b)System.out.write(b);}

Now stops when the end of the stream is reached. Now handles infinite input without running out of memory.

Poke

Posted 2017-04-04T12:12:07.127

Reputation: 3 075

I bet this can´t handle infinite input. – Titus – 2017-04-04T18:25:42.170

@Titus fixed... – Poke – 2017-04-04T19:06:25.730

I downvoted without seeing write being used instead of print. I can't undo my downvote, sorry for that :( – Olivier Grégoire – 2017-04-05T09:52:23.867

1

C (gcc), 73 72 65 63 69 77 72 71 bytes

It now terminates on the end of the input as well as handling input like this;

I once had a horse called hellhellopina.
i;main(c){for(;~(c=getchar())&i-5;i=putchar(c)^"hello"[i]?c=='h':i+1);}

Try it online!

cleblanc

Posted 2017-04-04T12:12:07.127

Reputation: 3 360

1

Ruby, 51 bytes

x="";$><<x[-1]while/hello./!~x=x[/.{0,5}$/]+$<.getc
  • Does not expect newlines
  • Works with infinite input

G B

Posted 2017-04-04T12:12:07.127

Reputation: 11 099

1

AHK, 116 bytes

Loop,Read,%1%
{a=%A_LoopReadLine%`n
Loop,Parse,a
{Send % c:=A_LoopField
If((f:=c SubStr(f,1,4))=="olleh")
ExitApp
}}

There's nothing clever or magical in there, really. The variable %1% is the first passed argument and should be a file path with the stream. The file must be saved as it is updated but the code will read to the end even if it expands after the reading starts.

Engineer Toast

Posted 2017-04-04T12:12:07.127

Reputation: 5 769

1

Mathematica, 107 bytes

i="";EventHandler[Dynamic@i,"KeyDown":>(i=i<>CurrentValue@"EventKey";If[StringTake[i,-5]=="hello",Exit[]])]

The output becomes a field where the user can infinitely type text (including newlines) until the last 5 characters are equal to "hello"; at that point, it exits.

numbermaniac

Posted 2017-04-04T12:12:07.127

Reputation: 639

1

brainfuck, 281 bytes

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

I'm not sure why, but I just felt like brainfuck was the right thing to do this. Doesn't require infinite memory, and can output forever.

Explained

Set up the buffers with helo
This is done Naively; sue me
>++++++++[<+++++++++++++>-]     h
>++++++++++[<++++++++++>-]<+>   e
>+++++++++[<++++++++++++>-]     l
>++++++++++[<+++++++++++>-]<+>  o

THE MAIN LOOP
+
[ matches o
    [ matches l
        [ matches l
            [ matches e
                [ matches h
                    ,. Read a character and immediently write it
                    <<<<[->>>>->+<<<<<] Subtract it from h
                    >>>>>[-<<<<<+>>>>>] Correct the h
                    < Terminate this part of the loop if it matches h
                ]
                ,. Same as above
                <<<[->>>->+<<<<] Subtract it from e
                >>>>[-<<<<+>>>>] Correct the e
                < Terminate this part of the loop if it matches e
            ]
            ,. Same as above
            <<[->>->+<<<] Subtract it from l
            >>>[-<<<+>>>] Correct the l
            < Terminate this part of the loop if it matches l
        ]
        ,. Same as above
        <<[->>->+<<<] Subtract it from l
        >>>[-<<<+>>>] Correct the l
        < Terminate this part of the loop if it matches l
    ]
    ,. Same as above
    <[->->+<<] Subtract it from o
    >>[-<<+>>] Correct the o
    < Terminate this part of the loop if it matches o
]

Try it online!

ATaco

Posted 2017-04-04T12:12:07.127

Reputation: 7 898

I was gonna do it like this but then I realized that this outputs the zero byte infinitly for input that doesn't contain "hello": https://tio.run/nexus/brainfuck#jYsxCoAwDEWv0v0bTxBykZChoOAiTg6evrZppR0U/NvLe0mCNmWMEzLpNMpsGCJ4f/z@a4/QsmnmPCXJI0EBtgKi5AAHY/PSw9ZZrzA0JamFPR4/bZburBr4PaXrOMMWl7CvId4

– KarlKastor – 2017-04-07T07:18:21.913

This also fails on ahehellob. – Mitch Schwartz – 2017-04-08T13:11:17.680

1

AWK, 72 bytes

BEGIN{RS="(.)"
h="olleh"}{printf RT
if("hello"==h=substr(h RT,2,6))exit}

I know, I have another AWK solution, but this is using a different approach with no loop, inspired by some of the other solutions.

As per @manatwork this one appears more AWKish :)

Robert Benson

Posted 2017-04-04T12:12:07.127

Reputation: 1 339

Actually by “awkish” I meant the use of typical pattern{action} syntax instead of if. ;) – manatwork – 2017-04-07T16:59:02.203

Ah... yeah... I try to use every aspect of AWK that I seems appropriate at the time. So the most common pattern I use is the empty-pattern which just applies to every 'line'. – Robert Benson – 2017-04-08T15:35:48.950

1

Chip, 154 bytes

H.G~.F~.E.D~.C~.B~.A~.AabB
Z<Z~<Z~<Z<Z~<Z~<Z-<Z-<CcdD
Z<Z~<Z~<Z<Z~<Z~<Z-<Z-<EefF
Z<Z~<Z~<Z<Z-<Z~<Z-<Z~<GghH
Z<Z~<Z~<Z<Z~<Z-<Z-<Zv'
 `--^--^-^--^--^--^-^~t

Try it online!

Chip is a language inspired by integrated circuits, and designed to operate on the individual bits of a byte stream.

How it works

The rightmost 4x4 block of characters is the simple Chip cat program. We already need linebreaks for the other stuff, so we suffer no penalty spreading this across multiple lines. It simply copies input to output, one byte at a time.

The remaining elements are dedicated to detecting 'hello' and terminating once it is found.

The algorithm I use is to locate differences between the string 'hello' and the five most recent bytes. If no differences are found, then we have seen 'hello' and the program will terminate itself with element t.

In the actual implementation, there are eight sets of columns, one for each bit of the input. Let's look at the 0x8 bit, accessed by element D:

D~.
Z~<
Z~<
Z-<
Z~<
 -^-

The top row is looking at the current byte. In this case, its value, D is inverted by ~ and propagated into the wire along the right. So, if this bit is not set in the input, we know it can't be the 'o' at the end of 'hello', and we can't yet terminate. We then look to the previous value in row 2, then the one before that in row 3, and so on. In the fourth row, we see a - instead of a ~, meaning that we don't invert it. This is because the 'e' of the keyword does not have this bit set, unlike all the other letters.

All this means that the wire along the right is activated if there is a discrepancy in the 0x8 bit of the last few bytes. The results for all bits are then collected along the bottom row, and if any of them show a discrepancy, we know to not yet terminate.

If the termination keyword were longer, we would simply need to add one row per additional byte.

Phlarx

Posted 2017-04-04T12:12:07.127

Reputation: 1 366

0

Python 105

Hopefully this count is fair, I've included what you need to set it up. Not the characters for the usage:

def c():
 b=yield
 while b!='hello':
  b+=yield b[-1]
  if len(b)==6:
   b=b[1:]
i=c()
i.next()

Usage would be something like this:

import string
import random

consumer = c()
consumer.next()
while True:
    try:
        char = random.choice( string.ascii_letters )
        print consumer.send( char )
    except GeneratorExit:
        print 'stopped'

Griffin

Posted 2017-04-04T12:12:07.127

Reputation: 4 349

Input has to be an infinite text stream or file. You can't make a function that takes one char at a time and call that good. – mbomb007 – 2017-04-04T19:15:31.193

@mbomb007 that while loop generates an infinite stream of random letters. That code will run forever if 'h', 'e', 'l', 'l', 'o' isn't generated. There will be no memory errors – Griffin – 2017-04-04T19:16:32.423

@mbomb007 not sure how else you generate/consume an infinite stream if not a char at a time. Please enlighten me. – Griffin – 2017-04-04T19:20:12.793

1But that loop isn't part of your code/solution. You don't get to generate your own stream of arbitrary input, you have to take it in the form the OP said, which is from stdin as an infinite stream or file. – mbomb007 – 2017-04-04T19:22:48.617

0

C(bcc gcc), 66 bytes

main(b,c){for(;~(c=getchar())&&b-'hell'|putchar(c)-'o';b=b<<8|c);}

the trick it is easy: We can consider the variable b as one buffer of 4 characters so, each char it read, it push it in the b buffer in this way b=b<<8|c. In b-'hell' it checks in b buffer there is "hell", if there is, and there is c=='o' too => it end the loop. It seems even in gcc in http://ideone.com/uPSMo6 it compile run and stop well. For to be ok the C language compiler I believe has to translate in the way:

1) the first argument 'b' it is argc so initialized with number of arguments one give to program

2) int is 4 characters of 8 bit

3) the 4 characters in quote 'abcd' are translated in one int/unsigned as in '1234' the number 0x31323334

Other above it assume

4) putchar() can not fail in write its character in stdout

i proposed this 67 bytes solution too but they said it is not ok.

z(c,b){for(;putchar(c=getchar()),~c&&b-0x68656c6c|c-'o';b=b<<8|c);}

RosLuP

Posted 2017-04-04T12:12:07.127

Reputation: 3 036

Where are all comments here? Who had to cancel all comment in this place? But what is this a site of bully and for bulling people? Who had given to the code above the valuation -1 and why? – RosLuP – 2017-04-07T08:58:26.900

2I deleted the comments because they didn't serve a purpose anymore. Asking people why they downvoted is pointless. It's unlikely the downvoter would actually see your comment, and even if they did, they would have left a comment already if they wanted to explain. – Dennis – 2017-04-07T16:04:56.393

There is a character that is as ➡ or -> that is read as -1 from getchar() and keyboard msdos window – RosLuP – 2017-04-09T23:23:05.807

No. getchar reads a character (8 bits on MS-DOS or Windows) and returns a signed 32-bit integer between 0 and 255. -1 is returned only when the end of the file (or stream) is reached. – Dennis – 2017-04-09T23:26:23.750

I copy and paste that char, the program stop when it read it, the value printed from printf("%d,c) was -1; my program, all C program. Possibly something was wrong with the old sys etc – RosLuP – 2017-04-09T23:38:43.980

→ number char 26; here if someone push that char in the keyboard as input in one program as alt-026 the program receive EOF as one push <ctr-z> EOF – RosLuP – 2017-04-10T09:25:04.693

I am aware that Ctrl-Z sends 0x1A which is interpreted as EOF in a Windows terminal. I told you that in a previous comment. But the sent byte is interpreted by the terminal, which just closes them stream. The 0x1A is never sent to the program. – Dennis – 2017-04-10T18:48:58.673