당신은 저를 안녕하세요


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
"hello"다음에 무엇이든 읽을 수 있습니까? 이 질문은 자동 읽기를 통해 버퍼 입력을 제공하는 (표준) C와 같은 언어에서 문제가 될 수있는 추가 읽기를 금지하는 것으로 보입니다.
Toby Speight

어셈블리 1에 허용되는 답변은 2 바이트가 짧으므로 변경해야합니다.
Rɪᴋᴇʀ

@Riker 누군가 그것을 테스트 할 수 있거나 적어도 그것이 먼저 작동한다고 생각한다고 말하면 좋을 것입니다.

답변:


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 두 개의 인수로 선언됩니다 . 이것은 정의되지 않은 동작이지만 실제로 추가 인수없이 프로그램을 실행할 때 n1 로 초기화됩니다 . c 는 인수 벡터에 대한 포인터의 하위 32 비트를 보유합니다.

조건 동안

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

hold, 우리는 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) 범위 에 있으므로 각 바이트마다 1 로, 나머지 모든 ASCII 문자는 0으로c/96 평가됩니다 . 이 방법은, ( putchar의 에 평가합니다 인쇄 및 인수를 반환) C 경우 C가 있다 소문자 문자 중 하나, 또는 DEL 문자; 다른 모든 ASCII 문자의 경우 0으로 평가됩니다 .putchar(c)/96*c`{|}~

n 은 5 비트를 왼쪽으로 이동 한 다음 이전 단락의 결과와 결과를 XOR하여 업데이트됩니다. 이후 INT는 (우리는이 대답에 가정 그래서 나), 이동 된 비트 중 일부는 "왼쪽을 떨어져"수도 32 비트입니다 (오버 플로우가 정의되지 않은 동작이 정수 서명,하지만 여기에 생성의 x64 명령어와 GCC의 동작합니다). hello의 모든 문자에 대해 값을 업데이트 한 후 알 수없는 값 n으로 시작 하면 다음과 같은 결과를 얻습니다.

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

하위 25 비트는 정수 0xb33def를 형성 하는데 , 이는 조건의 마법 상수입니다. 인접한 두 바이트의 비트간에 겹치는 부분이 있지만 96 이하의 바이트 를 0 으로 매핑 하면 오 탐지가 발생하지 않습니다.

조건은 두 부분으로 구성됩니다.

  • ~(getchar()) STDIN에서 바이트를 읽거나 읽은 결과의 비트 NOT을 가져옵니다.

    경우 getchar가이 성공, 그것은으로 읽기 바이트의 값을 반환합니다 INT . 입력은 전적으로 ASCII 문자로 구성되므로 읽기 바이트에는 하위 7 비트 만 설정할 수 있으므로이 경우 비트 NOT은 최상위 25 비트를 설정합니다.

    경우 getchar가가 (더 이상 입력) 실패하지 않습니다, 그것은 반환 -1 과 비트가 될 것입니다 NOT 0 .

  • n-0xb33def<<7n 에서 이전에서 마법 상수를 빼고 결과를 7 단위 왼쪽으로 이동합니다.

    마지막 5 개의 읽은 바이트가 hello 이면 n 의 가장 낮은 25 비트는 0xb33def 와 같고 빼기는 0 을 지 웁니다 . 7 개의 최상위 비트가 "왼쪽에서 떨어지기" 때문에 차이를 이동하면 0이 됩니다.

    반면에 마지막 5 개의 읽기 바이트가 hello아닌 경우, 차이의 가장 낮은 25 비트 중 하나가 설정됩니다. 쉬프팅 후 가장 높은 25 비트 중 하나가 됩니다.

마지막으로, getchar 가 성공적이고 아직 hello , 비트 단위 AND를 인쇄하지 않은 경우, 왼쪽 피연산자의 최상위 25 비트와 오른쪽 상위 비트의 최상위 25 비트 중 적어도 하나가 설정됩니다. 이런 식 &으로 0이 아닌 정수를 생성하고 루프가 계속됩니다.

반면에 입력이 소진되었거나 hello를 이미 인쇄 한 경우 비트 AND 피연산자 중 하나가 0이되고 결과도 같습니다. 이 경우 루프에서 빠져 나와 프로그램이 종료됩니다.


설명을 탐색하기 전에 ASCII로 인코딩 된 입력에 따라 달라집니다.
Toby Speight

2
@TobySpeight 나는 이것을 지정하는 것이 일반적이라고 생각하지 않습니다. C 답변에서 어떤 종류의 ASCII 비 호환 인코딩을 사용 하시겠습니까?
Dennis

EBCDIC은 ASCII가 아닌 명백한 인코딩입니다. C는 특정 문자 인코딩을 규정하지 않습니다 (십진수는 순서대로 연속 된 값으로 표시되어야합니다).
Toby Speight

스트림에 아스키 문자열이 아닌 "«úá ÷ o"1 : o 111 6f 2 : ÷ 246 f6 3 : á 160 a0 4 : ú 163 5 :«174
RosLuP

@RosLuP 챌린지 사양은 입력이 인쇄 가능한 ASCII 문자와 줄 바꿈으로 구성되도록합니다.
Dennis

19

배쉬, 74 75 103 99 88 82 76 바이트

@DigitalTrauma 덕분에 -10 바이트!
@manatwork 덕분에 -11 바이트!
@Dennis 덕분에 -6 바이트!

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 바이트

2 바이트를 절약 한 Sp3000에 감사합니다.

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

온라인으로 사용해보십시오!

설명

기본 아이디어는 기본 256의 마지막 5자를 단일 정수로 인코딩하는 것입니다. 새로운 문자가 들어 오면 정수에 256을 곱하고 새로운 코드 포인트를 추가하여 "추가"할 수 있습니다. 마지막 5 글자 만보고자한다면, modulo 256 5 = 2 40 = 1099511627776 값을 취하면 됩니다. 그러면이 값이 448378203247과 같은지 간단히 확인할 수 있습니다. hello기본 256 자릿수

코드는 ... <...>미궁 관용구입니다. 한 줄에 조건부 제어 흐름없이 무한 루프를 작성하여 공간과 줄 바꿈에 많은 바이트를 절약 할 수 있습니다. 이것이 작동하는 주요 조건은 스택에 도달 할 때 스택 위에 두 개의 일회용 값이 있다는 것입니다 <(우리는 일반적으로 0s를 사용 하지만 실제 값은 임의적입니다).

물론, 프로그램은 종료시기를 파악하기 위해 조건부 논리가 필요합니다. 그러나 프로그램을 끝내고 싶을 때 값을 0으로 나누면 조건부로 프로그램을 종료 할 수 있습니다. <...>전체 행을 시프트함으로써 구조 작동은 (순환)에 IP가 좌단 때 왼쪽 후 즉시 위치로 다시 이동. 이것은 코드가 실제로 오른쪽에서 왼쪽으로 실행됨을 의미합니다. 반대로하자 :

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

이것은 루프를 반복하여 문자를 읽고, EOF에 도달하면 종료하고, 문자를 인쇄하고, 문자를 인코딩에 추가하고, 5 자로 자르고, 등호를 확인 hello하고 반복합니다. 그 세부 사항은 다음과 같습니다 (Labyrinth는 스택 기반입니다).

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

이 재미 보인다 :)

프로그래밍 퍼즐 및 코드 골프 StackExchange에 오신 것을 환영합니다!
betseg

1
이 코드에는 여러 가지 문제가 있지만 가장 큰 문제는 사례를 ahehellob올바르게 처리하는 논리가 포함되어 있지 않다는 것입니다. 잠재적으로 일치하는 중간에 다음 문자 만 확인 hello하고 h다시 시작 하지 않습니다 .
Mitch Schwartz

8

배쉬 , 73 68 66 바이트

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

숨겨진 파일이 없거나없는 디렉토리를 가정합니다. 로 실행해야합니다 <path/to/script>.

온라인으로 사용해보십시오!

작동 방식 (오래된)

while 루프 의 시작 부분 에서 먼저 변수 s (처음에는 비어 있음) 문자열 이 olleh ( hello backwards, olé)와 같은지 테스트하고 그에 따라 0 (일치) 또는 1 (일치하지 않음 )을 반환 합니다. 공식적으로 루프 조건의 일부이지만, 이전 명령 만 do조건이 유지되는지 여부 를 결정 하므로 결과는 자체적으로 영향을 미치지 않습니다 .

다음으로 내부 필드 구분 기호를 빈 문자열로 설정하고 ( read공백에서 질식하지 않음 -r) STDIN에서 원시 바이트 ( )를 읽고에 저장합니다 c. $?는 이전 명령의 종료 코드이므로 -N1일치하지 않는 경우 정확히 1 바이트를 읽고 0 바이트 ( -N0)를 읽습니다 . EOF 적중으로 인해 또는 -N0지정 되었든 0 바이트를 읽으면 read상태 코드 1 로 종료 되므로 while 루프가 종료됩니다. 그렇지 않으면 시체가 실행되고 다시 시작합니다.

몸에서, 우리는 먼저 업데이트는, 우리가 읽은 바이트를 인쇄 이야s=$c${s::4}. 이것은 읽은 바이트를 s 의 처음 4 바이트 앞에 추가 하므로 hello 가 인쇄 되면 solleh와 같습니다 .


참으로 아주 좋은!

8

brainfuck, 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문자를 읽을 때마다 자랍니다. 입력이 무한한 경우 충돌이 발생합니까?
betseg

아마 @betseg hm. 내가 고칠 수 있는지 봅시다
Conor O'Brien

7

파이썬 3 120 116 104 바이트

무한한 스트림과 함께 작동하며 처음 골프를 치면 모든 팁을 얻을 수 있습니다.

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

바이트를 저장해 주셔서 감사합니다 @DJMcMayhem :)


사이트에 오신 것을 환영합니다! c=[0,c+1]['hello'[c]==a]바이트를 절약해야합니다. 또한 a=1짧습니다.
DJMcMayhem

2
while파이썬 에서는 괄호가 필요하지 않습니다 .
PurkkaKoodari

6

하스켈, 41 47 43 바이트

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

Haskell의 게으름은 무한한 입출력을 잘 처리합니다.

온라인으로 사용해보십시오!

편집 : 유한 입력을 처리하지 못했습니다. 지적 해 주셔서 감사합니다 @Leo.

편집 II : @ Ørjan Johansen이 4 바이트를 절약했습니다. 감사!


2
입력도
Leo

@ 레오 : 죄송합니다. 결정된.
nimi

2
첫 번째 가드를로 단축 할 수 있습니다 |w@"hello"<-take 5l=w.
Ørjan Johansen

@ ØrjanJohansen : 오, 그거 좋네요. 감사!
nimi

6

Cubix, 94 83 82 79 63 56 바이트

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

넓히는:

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

노트

  • 인터프리터는 프로그램이 시작될 때 입력 필드를 비활성화합니다. 따라서 무한한 입력 스트림이 불가능합니다. 이 프로그램은 문자별로 입력을 수행하므로이 제한이 없으면 제대로 작동합니다.
  • 이 프로그램은 스택을 지우지 않으며 매우 지저분합니다. 이것에 사용될 머신은 분명히 무한한 입력 스트림을 줄 수 있기 때문에 무한한 메모리를 가지고 있다고 가정하는 것이 합리적입니다.
  • 모든 골프 도움은 대단히 감사합니다.

온라인으로 사용해보십시오

당신은 여기 에서 프로그램을 시도 할 수 있습니다 .

설명

일반적인 생각

일반적인 아이디어는 문자를 읽고 다양한 문자 (먼저 h, 그런 e다음 l등) 와 비교하여 확인하는 것 입니다. 우리가 놓친 캐릭터를 추적하기 위해 스택 맨 아래에 유지합니다. 필요할 때 쉽게 다시 맨 위로 가져올 수 있습니다.

읽기 / 쓰기 루프

읽기-쓰기 루프는 단순히 다섯 번째 줄입니다. 사용하지 않는 모든 문자는 no-ops ( .) 로 바뀝니다 .

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

이것은 읽기와 쓰기와 확인의 두 부분으로 나눌 수 있습니다. 첫 번째 부분에는 물음표까지의 지침이 포함되어 있습니다. 두 번째 부분은 나머지 줄입니다. 이것이 반복되기 때문에 스택 스택으로 시작한다고 가정합니다.[...]

    @
'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

두 번째 부분 (쓰기 및 확인)은 다시 선형입니다. 스택은로 시작합니다 [next-char, ..., input]. 다음 문자는 프로그램에서 나중에 변경되기 때문에 다음 문자를 추상화했습니다.

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.

이제이 루프가 시작될 때 IP가 다시 시작되어 다음 문자를 재설정하여로 확인합니다 h.

다음 캐릭터와 일치

IP가 u 턴을 한 경우 (즉, 읽고 인쇄 한 문자가 다음 문자와 일치 함 'hello') 입력 한 문자를 확인하고 그에 따라 다음 문자를 스택의 맨 아래로 밉니다. 그런 h다음 스택으로 푸시하지 않고 읽기 / 쓰기 루프로 돌아 가야 하므로 다른 방법이 필요합니다.

먼저해야 할 일 : 입력 한 문자를 결정하십시오. 스택은 다음과 같습니다 : [..., prev-char, input, 0].

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

입력을 비교하기 위해 문자 코드를 h다시 사용 합니다. 처음에 이것은 내가 어떻게 처리 할 것인지 알지 못했기 때문에 h확인해야 할 첫 번째 문자이지만 매우 편리합니다. 우리가 입력에서 시간의 문자 코드를 빼면, 우리가 얻을 -3입력이있는 경우 e, 0입력이 경우 h, 4입력 인 경우 l7입력이있는 경우 o.

?명령을 사용하면 음수 값을 양수 값과 0에서 쉽게 분리 할 수 있기 때문에 유용 합니다. 따라서 IP가 왼쪽으로 바뀌면 차이가 음수이므로 입력이 e이므로 다음 문자는이어야합니다 l. IP가 계속 직진이라면 차이는 0이므로 입력은 h이므로 다음 문자는이어야합니다 e. 입력이 l또는 o인 경우 IP가 오른쪽으로 바뀝니다.

위에서 언급 한 물음표 앞에 실행 된 모든 명령어는 다음과 같습니다.

;!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]

이제 IP는 위에서 설명한대로 방향을 바꿉니다. 다른 가능성을 살펴 보자.

입력 'e'

먼저 input을 고려하여 차이가 3이기 때문에 eIP가에서 위쪽으로 이동합니다. ?관련없는 모든 문자가 큐브에서 제거되었습니다.

        . > 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는 방향을 변경하지 않습니다. 모든 관련없는 문자가 제거 된 큐브가 다시 있습니다. 이 경로에는 꽤 많은 no-ops가 포함되어 있으므로 통과하는 모든 no-ops가로 대체되었습니다 &. 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 o과 4 의 차이이며 l입력이 인 경우 프로그램을 종료해야합니다 o. 여기에 관련이없는 부품이 a .로 바뀌고 IP 교차가없는 no-ops가 앰퍼샌드로 바뀐 큐브가 다시 있습니다.

        . . 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's 사이의 식별

이제 입력 값이 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'. 바이트를 절약하기 위해 첫 번째와 동일한 문자를 사용합니다 'l'. 스택을로 단순화 할 수 있습니다 [...]. 다음은 큐브의 관련 부분이며 앰퍼샌드로 no-ops를 대체했습니다.

        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로 가능할까요? 나는 #importGCC C ++ 프로그램에서 보지 못한다 .
ckjbgames

1
@ckjbgames #import는 더 이상 사용되지 않는 GCC 확장입니다.
Steadybox

1
@ckjbgames 자세한 정보는 여기에 있습니다 : stackoverflow.com/questions/172262/…
iFreilicht

@iFreilicht 그 질문은 실제로 저에게 물어 보았습니다.
ckjbgames

1
@ckjbgames 두 번째 답변을 살펴볼 수 있습니다. stackoverflow.com/a/172264/2533467 "gcc의 가져 오기는 VC ++의 가져 오기와 다릅니다. 최대 한 번만 헤더를 포함하는 간단한 방법입니다. "
iFreilicht

3

노드, 124 바이트

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

스트림이 사용 가능한 메모리에 맞는다고 가정하지 않습니다.


3

C #, 134 바이트

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

온라인으로 사용해보십시오

문자를 읽고, -1 (EOS)이 아닌지 확인하고 "hello"를 아직 보지 못한 다음 문자열 앞에 추가하고 문자를 씁니다. 우리는 s[0]보다 훨씬 짧기 때문에 앞에 붙 습니다 (char)s. 문자를 읽을 때마다 전체 입력을 할당하고 스캔해야하기 때문에 문자열 길이에 이차 비용이 발생합니다 (CLR의 제약으로 인해 2GB의 입력 후 충돌이 발생합니까?)

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

메모리가 부족 하지 않고 문자 당 비용이 일정한 (더 긴 : 142 바이트) 버전 은 아래를 참조하십시오.

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

이것은 마지막 5자를 5 길이 문자열로 유지하므로 짧은 비교와 저렴한 마지막 문자 조회를 의미하지만 업데이트 비용이 상당히 비쌉니다.

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 바이트

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

무한 파일이 없으므로 STDIN에서 입력을받습니다. 로 실행하십시오 -nr.

입력을 반복하고 현재 문자를 인쇄하고에 추가 하고 마지막 5자를 $s자릅니다 $s. $sis 일 때 루프를 끊습니다 hello.


3

Vim, 39 바이트

:im hello hello:se noma
:map : i

i

온라인으로 사용해보십시오!

: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

이것이 Vim에 허용되는 입력 방법입니까? Vim 프로그램은 일반적으로 입력이 시작되기 전에 입력이 이미 버퍼에있을 것으로 예상한다고 생각했습니다.
Martin Ender

솔직히 모르겠다? 그것은 사실이지만 무한한 흐름을 거의 허용하지 않으므로 실제로 그렇게 생각하지 않고이 방법을 사용했습니다.
nmjcman101

입력 스트림에 이스케이프 문자가 있으면 어떻게됩니까?
dim

@dim은 물었고 OP는 인쇄 가능한 ASCII와 줄 바꿈 만 지정했습니다. ESC는 인쇄 가능한 ASCII afaik에 포함되어 있지 않습니다
nmjcman101

3

PowerShell, 111 바이트

이 작업을 수행하는 더 좋은 방법이 있지만 지금은 볼 수 없습니다.

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

에코를 억제하지 않고 키 스트로크를 읽습니다. 문자는 $ x에 추가되며 마지막 5 자로 잘리고 "hello"와 비교됩니다. 이것은 비교가 이루어질 때까지 계속됩니다.

참고 : PowerShell ISE에서는 작동하지 않습니다. 해당 환경에서 ReadKey가 비활성화되어 있습니다.


3

구성표 115 바이트

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

읽을 수있는 버전 :

(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

이것은 루프 주위에서 매번 stdin에서 개별 문자를 가져 와서 "hello"의 문자를 만나는 대상 단어의 위치를 ​​표시합니다.

입력이 부족하거나 "hello"가 보이면 중지합니다. 무한 스트림에 사용 된 메모리가 없습니다.


멋진 답변, 사이트에 오신 것을 환영합니다!
DJMcMayhem

3

AWK, 95 바이트

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

이 여기 배운 두 가지이다 :
문자를 사용하는 사이에 기록을 분할하기 위해 1) RS="(.)"다음은 RT대신 사용해야합니다 $1
) 2 ORS에 의해 사용되는 print및 디폴트로 "\n"
내가 2까지 셀 수 없음) 3, 사용하는 printf할당보다 "저렴"입니다 ORS및 사용print

사용법 예 : FILE에 장소 코드

awk -f FILE some_data_file

또는

some process | awk -f FILE

코드는 Dennis의 yes | ...제안을 사용하여 테스트 되었으며 많은 것을 보았습니다 y.

참고로, RS 할당을 옵션으로 수행하고 BEGIN다음을 통해 블록에서 꺼낼 수 있습니다 .

awk -v RS='(.)'

정말 까다로운 솔루션! (금요일 오후이기 때문에 어쩌면 난해한 도전에 대한 좋은 입장이기도합니다.) 더 어색한 접근법을 시도하지만 : BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}.
manatwork

이상하게도 나는 한 시간 전에 제출할 준비가 거의되어 있고 제출을 잊어 버렸습니다. : p
Robert Benson

3

Python 3 (Linux), 73 72 바이트

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

1 바이트를 골라내는 @MitchSchwartz에게 감사합니다!

온라인으로 사용해보십시오!


이해가 안 돼요 조건은 어떻게 while적절하게 평가됩니까? 부울을 빈 문자열과 비교하는 것처럼 보입니다.
iFreilicht

1
s[print(end=c):4]바이트 절약
Mitch Schwartz

1
@iFreilicht Python은 수학에서와 같이 체인 조건을 구문 분석합니다 (예 : a <b <c ). 의 약칭입니다 'olleh'!=s and s>''and''<c). 중간 테스트는 필요하지 않지만 연결하는 것은 간단한 것보다 짧습니다 'olleh'!=s and''<c.
Dennis

@MitchSchwartz 그렇습니다. 고맙습니다!
Dennis

3

8086 머신 코드, 22 바이트

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

동등한 어셈블리 코드 :

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"

어떻게 작동합니까?

1
동등한 어셈블리 코드를 추가했습니다. 그것은 기본적으로 stdin에서 1 바이트를 읽고 동시에 stdout으로 에코하는 매우 유용한 DOS syscall에 의존합니다. 8086에는 여기에 유용한 1 바이트 문자열 비교 명령어도 있습니다.
user5434231

2

Pyth, 49 47 바이트

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

Pyth는 단일 문자 입력을 잘하지 못합니다. 모든 $__import__("sys").stdin.read(1)것이 단순히 그렇게하고 있습니다. 또한 이는 오프라인에서만 실행됨을 의미합니다.

다른 모든 것은 짧습니다 ...

이 프로그램은 바디리스 while 루프입니다. 조건 내부, 프로그램은, 다시 인쇄, 문자를 읽고 해당 문자를 추가 k, (빈 문자열이 처음입니다) 모든 오프 트림하지만 마지막 5 자 k결과가 아니라고 한 다음 확인을 "hello".

32 문자는 1 바이트의 입력을 받고, 15 문자는 나머지를 수행합니다.

Linux에서 테스트되었으며 줄 바꿈, 무한 입력 등이 없어도 작동합니다.


2

루아, 68 64 바이트

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

1
슬라이싱을로 변경하면 l:sub(-4)의 초기화를 줄일 수 있습니다 l="".
manatwork

@manatwork 깔끔합니다. 팁 고마워.
Blab

2

루비, 59 49 48 43 바이트

지금 호언 장담 무료, 짧은, 그리고 메모리 누수없이.

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

Dennis 덕분에 일부 괄호와 공백을 제거하여 5 바이트를 절약했습니다.



1

로다 , 49 47 바이트

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

온라인으로 사용해보십시오!

이것은 입력 스트림에서 문자를 읽고 "hello"가 발견 될 때까지 출력하는 익명 함수입니다. 배열 a을 사용하여 마지막 문자를 추적합니다.

일부 정크를 STDERR에 출력하지만 허용되는 것으로 알고 있습니다.

설명:

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

Roda 문서는 어디에 있습니까?
ckjbgames

@ckjbgames 여기. Github의 자체 분기에있는 최신 버전 0.12를 사용합니다.
fergusq

1

자바 7 122 118 124 123 150 141 바이트

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

이제 스트림 끝에 도달하면 중지됩니다. 메모리 부족없이 무한 입력을 처리합니다.


나는 이것이 무한 입력을 처리 할 수 ​​없다는 내기.
Titus

@Titus fixed ...
Poke

나는 write대신에 사용되는 것을 보지 않고 downvoted print. 그 :( 미안, 내 downvote을 취소 할 수 없습니다
올리비에 그레 구 아르에게

1

루비, 51 바이트

x="";$><<x[-1]while/hello./!~x=x[/.{0,5}$/]+$<.getc
  • 줄 바꿈을 기대하지 않습니다
  • 무한 입력으로 작동

1

AHK , 116 바이트

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

거기에는 영리하거나 마법적인 것이 없습니다. 변수 %1%는 첫 번째로 전달 된 인수이며 스트림이있는 파일 경로 여야합니다. 파일은 업데이트 될 때 저장해야하지만 읽기가 시작된 후 확장 되더라도 코드는 끝까지 읽습니다.


1

수학, 107 바이트

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

출력은 마지막 5자가 같을 때까지 사용자가 텍스트 (줄 바꾸기 포함)를 무한정 입력 할 수있는 필드가됩니다 "hello". 그 시점에서 종료됩니다.


1

brainfuck , 281 바이트

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

왜 그런지 잘 모르겠지만 brainfuck이 이것을하는 것이 옳은 것처럼 느껴졌습니다. 무한한 메모리가 필요하지 않으며 영원히 출력 할 수 있습니다.

설명

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
]

온라인으로 사용해보십시오!


나는 이렇게하려고했지만 "hello"를 포함하지 않는 입력에 대해 0 바이트를 무한정 출력한다는 것을 깨달았다 : tio.run/nexus/…
KarlKastor

이것도 실패합니다 ahehellob.
Mitch Schwartz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.