こんにちは


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などの言語で問題が発生する可能性があり、自動先読みでバッファリングされた入力を提供します。
トビーSpeight

アセンブリの回答は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である2つの引数で宣言されます。これは未定義の動作ですが、実際には、追加の引数なしでプログラムを実行するとn1に初期化され、cは引数ベクトルへのポインターの下位32ビットを保持します

条件が

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

whileループの本体を実行します:

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

状態を完全に理解するには、まず身体を調べる必要があります。現時点では、c=getchar()STDINから1バイトを読み取り(可能な場合)、変数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文字については0c/96評価されます。このようにして、(のputchar版画とその引数を返しますが)と評価されますC場合cがあり、小文字の1 、またはDEL文字。他のすべてのASCII文字の場合、評価は0になります。putchar(c)/96*c`{|}~

nは、左に5ビットシフトし、結果を前の段落の結果とXORすることによって更新されます。以来intは 32ビット幅(または私たちはこの答えに仮定しそう)で、シフトされたビットが「左から落ちる」かもしれないいくつかの(オーバーフロー符号付き整数は未定義の動作ですが、それはここで生成x64の命令としてGCCの振る舞い)。nの不明な値から始めて、helloのすべての文字について更新した後、次の結果が得られます。

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

下位25ビットが整数0xb33defを形成することに注意してください。これは条件のマジック定数です。隣接する2つのバイトのビット間にある程度のオーバーラップがありますが、96未満のバイトを0にマッピングすると、誤検出がないことが保証されます。

条件は2つの部分で構成されます。

  • ~(getchar()) STDINからバイトを読み取った(または読み取ろうとした)結果のビット単位のNOTを取ります。

    場合GETCHARは成功し、それがよう読み取りバイトの値を返しますint型。入力は完全にASCII文字で構成されているため、読み取りバイトの下位7ビットのみを設定できるため、この場合、ビット単位のNOTには最上位の25ビットが設定されます。

    場合GETCHARが(これ以上の入力を)失敗し、それが返されます-1とビット単位がされるわけではありません0

  • n-0xb33def<<7nから前からマジック定数を減算し、結果を7単位左にシフトします。

    最後の5つの読み取りバイトがhelloである場合、nの下位25ビットは0xb33defに等しくなり、減算によりゼロになります。上位7ビットが「左に落ちる」ので、差をシフトすると0になります。

    一方、最後の5つの読み取りバイトがhelloない 場合、差の最下位25ビットの1つが設定されます。シフト後、最上位の 25ビットの1つになります。

最後に、getcharが成功し、まだhelloを出力しなかった場合、ビット単位のAND、左側のオペランドの上位25ビットすべて、および右側のオペランドの上位25ビットの少なくとも1つが設定されます。この方法で&は、ゼロ以外の整数が生成され、ループが継続します。

一方、入力が使い果たされた場合、または既にhelloを出力した場合、ビット単位のANDのオペランドの1つはゼロになり、結果もゼロになります。この場合、ループから抜け出し、プログラムは終了します。


説明を掘り下げる前に、これはおそらくASCIIでエンコードされた入力に依存することに言及する必要があります。
トビースパイト

2
@TobySpeightこれを指定するのは一般的ではないと思います。どのような種類のASCII互換性のないエンコードを使用すると、Cの回答が使用されると思いますか?
デニス

EBCDICは、ASCIIではない明らかなエンコードです。Cは、特定の文字エンコードを規定していません(10進数を連続した値で順番に表す必要があることのみ)。
トビー・スペイト

上記のプログラムは、ストリームに非アスキー文字列「«úá÷o」が含まれている場合に停止します1:o 111 6f 2:÷246 f6 3:
á160

@RosLuPチャレンジ仕様は、入力が印刷可能なASCII文字と改行で構成されることを保証します。
デニス

19

Bash、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文字だけを見たい場合は、モジュロ256 5 = 2 40 = 1099511627776 の値を取ります。その後、この値が448378203247に等しいかどうかを確認できます。hello基数256桁として。

コードについては... <...>迷路のイディオムです。これにより、1行に条件付き制御フローを使用せずに無限ループを記述でき、スペースと改行で多くのバイトを節約できます。これが機能するための主な条件は、到達したときにスタックの最上部に2つの使い捨て可能な値があることです<(通常は0sを使用しますが、実際の値は任意です)。

もちろん、プログラムには、いつ終了するかを判断するための条件付きロジックが必要です。しかし、プログラムを終了させる場合、ゼロである値で割ることにより、プログラムを条件付きで終了することができます。この<...>構造は、IPが左端にあるときに行全体を左に(循環的に)シフトし、すぐに元の位置に戻すことで機能します。これは、コードが実際に右から左に実行されることを意味します。逆にしましょう:

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

これは、文字を読み取り、EOFに達した場合に終了し、文字を出力し、エンコードに追加し、それを5文字に切り捨て、等しいかどうかをチェックしhelloて繰り返すループの1つの反復です。詳細は次のとおりです(迷路はスタックベースであることを思い出してください):

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

オンラインでお試しください!

仕組み(古い)

開始時に、一方ループ、我々の最初のテストであれば変数の文字列S(最初は空)に等しいollehハロー後方、OLE)、および戻り0(一致)または1(非一致)に応じ。正式にはループの条件の一部ですが、前の最後のコマンドのみdoが条件が成立するかどうかを決定するため、結果はループ自体には影響しません。

次に、内部フィールドセパレーターを空の文字列に設定して(read空白でチョークしないように)、生のバイト(-r)をSTDINから読み取り、に保存しますc$?は、前のコマンドの終了コードです。したがって、これ-N1は、一致しないゼロバイト(-N0)に対して正確に1()バイトを読み取ります。EOFのヒットまたは-N0指定されたためにゼロバイトを読み取るreadと、ステータスコード1で終了するため、whileループは終了します。それ以外の場合は、本文が実行され、最初からやり直します。

体では、まず、更新は、私たちが読んでバイトを印刷するs=$c${s::4}。この最初の4バイト(最大)にプリペンドリードバイトS、ようsが等しくなるollehハローが印刷されています。


本当にいいね!

8

brainfuck、117バイト

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

フォーマット済み:

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

オンラインでお試しください

これhelloにより107、3セルごとに1つの値で間隔を空けたオフセットの文字でテープが初期化され、表示された最後の5文字が追跡され、処理されるすべての新しい文字との一致がチェックされます。一致したかどうかを追跡します。


7

ルビー46 60バイト

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

オンラインでお試しください!

最後の5つがになるまで標準入力から文字を読み取りhello、文字列を出力します(標準入力に文字がなくなるまで)。エラーで終了します。

に相当:

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
acharが読み取られるたびに成長します。入力が無限の場合、これはクラッシュしますか?
betseg

@betseg hm、多分。私はそれを修正することができますなら、私は見てみましょう
コナー・オブライエン

7

Pythonの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
whilePythonでは括弧は必要ありません。
-PurkkaKoodari

6

Haskell、41 47 43バイト

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

Haskellの遅延は、無限の入出力をうまく処理します。

オンラインでお試しください!

編集:有限入力を処理しませんでした-修正。指摘してくれて@Leoに感謝します。

編集II:@ØrjanJohansenは4バイトを節約しました。ありがとう!


2
私はあなたが文字列の末尾に到達したときにケースに対処する必要があると思うので、入力も、有限であり
レオ

@レオ:おっと、それを見逃した。一定。
nimi

2
最初のガードはに短縮できます|w@"hello"<-take 5l=w
Ørjanヨハンセン

@Ø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など)でチェックすることです。逃したキャラクターを追跡するために、スタックの一番下に保持します。必要になったら、簡単に再びトップに戻すことができます。

読み取り/書き込みループ

読み書きループは単純に5 番目のライン。使用されないすべての文字は、no-ops(.)に置き換えられます。

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

これは、読み取りと(書き込みとチェック)の2つの部分に分割できます。最初の部分には、疑問符までの指示が含まれています。2番目の部分は、残りの行です。これはループするため、次のスタックで開始すると仮定します。[...]

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

2番目の部分(書き込みとチェック)は再び線形です。スタックはから始まります[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であり、チェックする文字列の最初の文字でしたが、非常に便利でした。入力からhの文字コードを引くと、-3入力がeである0か、入力がhである4か、入力がであるか、入力がlである7かが得られますo

この?コマンドを使用すると、負の値を正の値とゼロから簡単に分離できるため便利です。そのため、IPが左に曲がる場合、差は負であったため、入力はeであったため、次の文字はである必要がありlます。IPが直進し続ける場合、差は0であったため、入力はhであったため、次の文字はである必要がありeます。入力された場合lo、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を検討しますe。これにより、IPはから上に移動します?。違いは3であるためです。無関係な文字はすべてキューブから削除されています。

        . > 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は疑問符で右に曲がります。我々はまだ分離する必要があるlo私たちは次やるの何ということ、。

分離'l'し、'o'

差は7 for oと4 forで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

2つ'l'の間を識別する

そのため、入力がであることはわかっていますが、lどちらがかはわかりませんl。最初の場合lは、スタックの一番下に別のプッシュする必要がありますが、2番目の場合は、をプッシュする必要がありoます。-3最初にプッシュする直前にスタックの一番下に保存したことを覚えていますlか?これを使用して、2つのブランチを分離できます。

        . . . .
        . . . .
        . . . .
        . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
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'ます。スタックをに単純化できます[...]。キューブの関連部分を次に示します。何もしない操作はアンパサンドに置き換えられます。

        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
2番目の答えを見てみることをお勧めします@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ます。これは、文字を読み取るたびに入力全体を割り当ててスキャンする必要があるため、文字列の長さに2次コストがかかります(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。ブレークループがとき$sです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プログラムは通常、入力が開始する前に既にバッファーにあることを期待していると思いました。
マーティンエンダー

正直なところ、私は知りませんか?それは事実ですが、無限のストリームを許可することはほとんどありません。そのため、私はそれについて真剣に考えずにこの方法で実行しました。
nmjcman101

入力ストリームにエスケープ文字があるとどうなりますか?
薄暗い

@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

これは、ループのたびに標準入力から個々の文字を取得し、「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}

私はここで学んだ2つのことがあります。
文字間の分割記録への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

コードはデニスのyes | ...提案を使用してテストされ、多くのys を見ました。

参考までに、オプションとしてRS割り当てを行い、次の方法でBEGINブロックから取り出すことができます。

awk -v RS='(.)'

本当にトリッキーなソリューション!(多分それは金曜日の午後だが、私はあまりにもそれを難読化された挑戦のための良好なエントリを見つけるため。)私はもっとawkishアプローチをしようとするだろうけど:BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}
マナトワーク

奇妙なことに、1時間前に提出する準備がほぼ整いました...そして提出するのを忘れていました。:p
ロバートベンソン

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]バイトを保存
ミッチシュワルツ

1
@iFreilicht Pythonは数学のように連鎖条​​件を解析します(たとえば、a <b <c)。条件はの省略形です'olleh'!=s and s>''and''<c)。中間のテストは必要ありませんが、それらを連鎖させることは簡単なものよりも短くなり'olleh'!=s and''<cます。
デニス

@MitchSchwartzそうです。ありがとうございました!
デニス

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
同等のアセンブリコードを追加しました。基本的に、1つの非常に便利なDOSシステムコールに依存しています。これは、stdinから1バイトを読み取り、同時にそれをstdoutにエコーバックします。8086には、ここで便利なシングルバイト文字列比較命令もあります。
user5434231

2

Pyth、49 47バイト

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

Pythは、単一の入力文字を取得するのはあまり得意ではありません。内のすべて$__import__("sys").stdin.read(1)が単純にそれを行っています。また、これはオフラインでのみ実行されることを意味します。

他のすべては短いです...

このプログラムはbodyless whileループです。条件内で、プログラムは文字を読み取り、それを印刷し、その文字k(最初は空の文字列)に追加し、の最後の5文字を​​除くすべてを切り取りk、結果がでないことを確認し"hello"ます。

32バイトが1バイトの入力を取得し、15文字が残りを入力します。

Linuxでテストされ、改行なし、無限入力などでも動作します。


2

Lua、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それはすてきです。ヒントをありがとう。
-Blab


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

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

ストリームの終わりに達すると停止します。メモリを使い果たすことなく、無限の入力を処理できるようになりました。


これは無限の入力を処理することはできないに違いない。
タイタス

@タイタス修正...
ポケ

私はのwrite代わりに使用されているのを見ることなくダウン投票しましたprint。私は私のダウン投票を元に戻すことはできません、ごめんなさい:(
オリビエグレゴワール

1

Ruby、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

Mathematica、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」を含まない入力に対して無限にゼロバイトを出力することに気付きました。tio.run
nexus

これも失敗しahehellobます。
ミッチシュワルツ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.