你让我打招呼


30

任务

读入可能无限的文本流或文件,hello并按照以下规则输出其内容,直到输出单词为止。

  • 一旦hello已输出,您的代码应立即退出。例如,它不应该等待换行符。

  • 您的代码应随其输出。那就是它不应该读入大量的输入然后开始输出。

  • 如果流/文件不包含hello,则您的代码应永远继续输出输入,直到到达流/文件的末尾为止。

  • 这是区分大小写的挑战,因此hello不等于Hello

  • 您可以假定输入仅包含可打印的ASCII字符和换行符。

  • 您的代码不能期望文本将由换行符终止,或者输入中根本没有换行符。另外,您的代码不能假定它将在具有无限内存的计算机上运行。

  • 您可能假设您的代码将从一个空目录中调用。

输入流示例

I once had a horse called hellopina.

输出量

I once had a horse called hello

小费

运行yes | tr -d \\n | <your program>检查它是否适用于无限流。如果它不打印任何内容和/或泄漏内存,则表明该程序不符合规范。它应该yyyyyyyyyyyyyyyyyyyyyy...永远打印,没有换行符。


1
在“你好”之后,我们可以阅读任何东西吗?这个问题似乎禁止进行任何额外的读取,这在诸如(标准)C之类的语言中可能会出现问题,这些语言会提供具有自动预读功能的缓冲输入。
Toby Speight

您可能应该更改汇编程序接受的答案,因为它短了2个字节。
Rɪᴋᴇʀ

@Riker如果有人可以测试它,或者至少说他们相信它首先起作用,那就太好了。

Answers:


2

果冻,24字节

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

在线尝试!

说明:

ṫ-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.

26

C(gcc)81 80 76 75 72 71 70 69字节

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

在线尝试!

怎么运行的

这是一个完整程序。为此,我们定义了一个函数f。为了节省字节,使用两个参数声明默认为int。这是未定义的行为,但实际上,在运行程序时不带附加参数的情况下,n将被初始化为1 c将保留指向参数向量的指针的低32位

虽然条件

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

保持,我们将执行while循环的主体:

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

为了充分了解病情,我们必须首先检查身体。现在,我们观察到的是c=getchar()从STDIN读取单个字节(如果可能)并将其存储在变量c中

字节序列hello在不同的表示形式中看起来如下。

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

所有这些都在[96,192)范围内,因此对于这些字节中的每个字节,其c/96求值为1,对于所有其余ASCII字符的求值为0。这样,如果c为,是小写字母,或DEL字符,则putchar(c)/96*cputchar打印并返回其参数)将求值为c。对于所有其他ASCII字符,它将取值为0`{|}~

通过将n左移五位来更新n,然后将结果与上一段的结果进行异或。由于int的宽度为32位(或者我们在此答案中假设),因此某些移位的位可能会“掉到左边”(有符号整数溢出是未定义的行为,但gcc的行为与其在此处生成的x64指令相同)。从n的未知值开始,对hello的所有字符进行更新后,我们得到以下结果。

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

请注意,低25位形成整数0xb33def,这是条件中的魔术常数。虽然两个相邻字节的位之间有一些重叠,但将96以下的字节映射到0可以确保没有任何误报。

该条件包括两个部分:

  • ~(getchar()) 对从STDIN读取(或尝试读取)字节的结果按位取非。

    如果getchar成功,它将以int形式返回读取字节的值。由于输入完全由ASCII字符组成,因此读字节只能设置其低7位,因此在这种情况下按位NOT的最高25位将被设置。

    如果getchar失败(没有更多输入),它将返回-1,按位NOT为0

  • n-0xb33def<<7n减去之前的魔术常数,然后将结果向左移动7个单位。

    如果最后5个读取字节为hello,则n的最低25位将等于0xb33def,并且相减会将它们清零。移位差将产生0,因为7个最高位将“从左侧掉落”。

    另一方面,如果最后5个读取字节不是 hello,则将设置差异的最低25位之一;移位后,最高的 25位之一将是。

最后,如果getchar成功并且我们还没有打印问候,那么按位与,将设置左操作数的最高25位和右操作数的最高25位中的至少一位。这样,&将产生一个非零整数,循环继续进行。

另一方面,如果输入已用尽或我们已经打印了问候,则按位与运算符之一将为零,结果也将为零。在这种情况下,我们跳出循环,程序终止。


您可能应该提到,这取决于在解释之前的ASCII输入编码。
Toby Speight

2
@TobySpeight我认为指定此名称并不常见。您希望C答案使用哪种ASCII不兼容编码?
丹尼斯

EBCDIC是非ASCII的显而易见的编码。C没有规定任何特定的字符编码(仅十进制数字必须按顺序由连续的值表示)。
Toby Speight

如果流包含非ascii字符串“«úá÷o” 1:o 111 6f 2:÷246 f6 3:
á160

@RosLuP挑战规范保证输入将包含可打印的ASCII字符和换行符。
丹尼斯

19

Bash,74 75 103 99 88 82 76字节

-10个字节感谢@DigitalTrauma!
-11个字节感谢@manatwork!
-6个字节,感谢@Dennis!

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

说明:

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

在线尝试!


2
这很棒!我希望会有一个bash的答案。

13

迷宫43 41字节

感谢Sp3000节省2个字节。

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

在线尝试!

说明

基本思想是将基数为256的最后五个字符编码为单个整数。当输入新字符时,我们可以通过将整数乘以256并添加新的代码点来“附加”它。如果只想查看最后5个字符,则取模256 5 = 2 40 =1099511627776。然后我们可以简单地检查此值是否等于448378203247,这是在处理代码点时得到的值hello以256位为基数。

至于代码... <...>有点迷宫惯用法。它使您可以在单行上编写无条件控制流的无限循环,从而在空格和换行符上节省了大量字节。达到此目的的主要条件是,到达堆栈时,堆栈顶部有两个一次性值<(通常使用0s,但实际值是任意的)。

当然,该程序确实需要一些条件逻辑来确定何时终止。但是,当我们希望程序结束时,可以通过除以零值来有条件地结束程序。该<...>结构的工作原理是:当IP位于左端时,将整个行(循环)向左移,然后立即将其移回原位。这意味着代码实际上是从右到左执行的。让我们反转一下:

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

这是循环的一次迭代,该循环读取一个字符,如果到达EOF则终止,打印该字符,将其添加到我们的编码中,将其截断为5个字符,检查与是否相等hello并重复。这是详细的工作原理(请记住迷宫是基于堆栈的):

_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.

8

Brainfuck,658字节

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

我需要打高尔夫的常量中有500多个字节。

它本质上是一个状态机,因此无限输入不是问题。

这是稍加评论的版本

+
[
  >,.
  >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]
            <->>
          ]
        ]
      ]
    ]
  ]
  <<
]

这看起来很有趣:)

欢迎使用编程难题和Code Golf StackExchange!
betseg

1
这段代码有很多问题,但是最大的问题是它不包含ahehellob适当处理逻辑的逻辑。在可能的比赛中间,它仅检查下一个字母,hello而不寻找h重新开始的字母。
米奇·施瓦兹

8

Bash73 68 66字节

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

假定目录中没有或只有隐藏文件。必须以方式运行<path/to/script>

在线尝试!

工作方式(已过时)

在年初,而循环中,我们第一次测试,如果变量中的字符串小号(初始为空)等于2009东海生日贺你好向后,OLE),并返回0(匹配)或1(不匹配)相应。虽然正式地属于循环条件的一部分,但结果不会单独影响它,因为只有最后一条命令才能do确定条件是否成立。

接下来,我们将内部字段分隔符设置为空字符串(这样read就不会阻塞空格),-r从STDIN 读取原始字节()并将其存储在中c$?是上一条命令的退出代码,因此-N1对于不匹配的内容,它的读取准确为一个()字节,而为零字节(-N0)。读取零字节,无论是由于命中EOF还是由于-N0指定了字节,都会导致read退出,并返回状态码1,因此while循环将结束;否则,执行身体,我们重新开始。

在人体中,我们首先打印我们所读取的字节,然后更新Şs=$c${s::4}。这会将读取的字节添加到s中的前四个字节(最多)之前,因此一旦打好招呼s将等于olleh


的确很好!

8

疯子,117字节

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

格式:

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

在线尝试

这将初始化磁带,其字符hello偏移量为107,每三个像元间隔一个值,然后跟踪最后看到的五个字符,并使用字符串右侧的标志来检查是否与每个处理的新字符匹配跟踪是否有比赛。


7

红宝石46 60字节

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

在线尝试!

从stdin读取字符,直到最后5个为hello,然后输出字符串(或直到stdin中没有剩余字符)。错误终止。

相当于:

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

或者,更加虚张声势:

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

1
a grows everytime a char is read. Does this crash if the input is infinite?
betseg

@betseg hm, maybe. Let me see if I can fix that
Conor O'Brien

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 :)


Welcome to the site! c=[0,c+1]['hello'[c]==a] should save you some bytes. Also, a=1 is shorter too.
DJMcMayhem

2
You don't need the parenthesis for while in Python.
PurkkaKoodari

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!


2
The input may also be finite, so I think you need to deal with the case when you reach the end of the string
Leo

@Leo: Oops, totally missed it. Fixed.
nimi

2
The first guard can be shortened to |w@"hello"<-take 5l=w.
Ørjan Johansen

@ØrjanJohansen: oh, that's a nice one. Thanks!
nimi

6

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 . . . . . . . . > . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

字符按以下顺序执行(某些控制流字符除外):

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, ...]

现在IP已再次到达读/写循环。

输入值 'h'

如果输入为'h',则差为0,因此IP不会改变其方向。这又是多维数据集,其中所有不相关的字符均已删除。由于此路径包含许多非操作,因此它通过的所有非操作都已被替换&。IP从问号开始。

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

执行的指令是:

'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

现在我们再次进入读/写循环,所以我们完成了。

其他投入

所有其他输入都会产生正的差异,因此IP在问号处向右转。我们仍然需要将l和和分开o,所以这就是我们接下来要做的。

分开'l''o'

请记住,两者的差是7 for o和4 for l,如果输入是,我们必须结束程序o。这又是一个多维数据集,不相关的部分替换为a .,IP交叉的无操作替换为&符。

        . . 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

两者之间挑剔的'l'小号

因此,现在我们知道输入是an l,但是我们不知道哪个l。如果是第一个,则需要将另一个压入l堆栈的底部,但是如果是第二个,则需要压入一个o。还记得我们-3在压入第一个堆栈之前将其保存到堆栈的底部l吗?我们可以用它来分隔两个分支。

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

堆栈开始为 [..., -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

第一 'l'

如果是第一个'l',我们需要推另一个'l'。为了节省字节,我们使用与first相同的字符'l'。我们可以将堆栈简化为[...]。这是多维数据集的相关部分,无操作符替换为“&”符号。

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

执行以下指令:

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

我们即将进入读/写循环,因此我们已经完成了该分支。

第二 'l'

如果输入的是第二个'l''hello',该IP的问号向右转。再一次,我们可以简化堆栈,[...]并且IP起始于?,这次指向南方。

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

执行的指令是:

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

IP将再次进入读/写循环,因此我们也完成了该分支。


英勇的努力!

5

C ++,142个 141字节

#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;}

在线尝试!


使用GCC可以吗?我#import在GCC C ++程序
中看不到

1
@ckjbgames #import是已弃用的GCC扩展名。
Steadybox

1
@ckjbgames更多信息,请访问:stackoverflow.com/questions/172262/…–
iFreilicht

@iFreilicht这个问题实际上让我问了这个问题。
ckjbgames

1
@ckjbgames you might want to take a look at the second answer: 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

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.


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;
    }
}

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.


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

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

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

What happens if there is an escape character in the input stream?
dim

@dim I asked, and OP specified only printable ASCII and newlines. ESC is not included in printable ASCII afaik
nmjcman101

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.


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.


Cool answer, welcome to the site!
DJMcMayhem

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='(.)'

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

Oddly enough I have almost exactly answer ready to submit an hour ago... and forgot to submit it. :p
Robert Benson

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!


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

1
s[print(end=c):4] saves a byte
Mitch Schwartz

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

@MitchSchwartz That it does. Thank you!
Dennis

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"

How does it work?

1
I 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

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.


2

Lua, 68 64 bytes

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

1
Change the slicing to l:sub(-4), then you can reduce the initialization of l="".
manatwork

@manatwork That's neat. Thanks for the tip.
Blab


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. */
}

Where is the Roda documentation?
ckjbgames

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

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.


I bet this can´t handle infinite input.
Titus

@Titus fixed...
Poke

I downvoted without seeing write being used instead of print. I can't undo my downvote, sorry for that :(
Olivier Grégoire

1

Ruby, 51 bytes

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

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.


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.


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!


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": tio.run/nexus/…
KarlKastor

This also fails on ahehellob.
Mitch Schwartz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.