Aku sudah suka kamu dari awal

30

Tugas

Baca dalam aliran teks atau file yang mungkin tak terbatas, mengeluarkan kontennya hingga kata hellotersebut dikeluarkan, mematuhi aturan berikut.

  • Setelah hellodikeluarkan, kode Anda harus segera keluar. Seharusnya tidak menunggu baris baru misalnya.

  • Kode Anda harus ditampilkan saat berjalan. Itu seharusnya tidak dibaca dalam jumlah besar input dan kemudian mulai menghasilkan.

  • Jika stream / file tidak mengandung hello, kode Anda harus terus mengeluarkan input selamanya atau sampai akhir stream / file tercapai.

  • Ini adalah tantangan case-sensitive, jadi hellotidak sama dengan Hello.

  • Anda dapat berasumsi bahwa input hanya terdiri dari karakter dan baris ASCII yang dapat dicetak.

  • Kode Anda tidak dapat berharap bahwa teks akan dihentikan oleh baris baru atau akan ada baris baru sama sekali dalam input. Selain itu, kode Anda tidak dapat berasumsi bahwa kode itu akan berjalan pada mesin dengan jumlah memori tak terbatas.

  • Anda dapat mengasumsikan bahwa kode Anda akan dipanggil dari direktori kosong.

Contoh aliran input

I once had a horse called hellopina.

Keluaran

I once had a horse called hello

Tip

Jalankan yes | tr -d \\n | <your program>untuk memeriksa apakah ia bekerja dengan aliran yang tak terbatas. Jika tidak mencetak apa pun dan / atau kebocoran memori, program tidak mematuhi spesifikasi. Ini harus dicetak yyyyyyyyyyyyyyyyyyyyyy...selamanya tanpa baris baru.

Dennis
sumber
1
Apakah kita diizinkan membaca apa pun setelah "halo"? Pertanyaannya tampaknya melarang pembacaan tambahan apa pun, yang dapat bermasalah dalam bahasa seperti (Standar) C, yang memberikan input buffered dengan read-ahead otomatis.
Toby Speight
Anda mungkin harus mengubah jawaban yang diterima ke perakitan, karena 2 byte lebih pendek.
Rɪᴋᴇʀ
@ Pengendara Akan sangat bagus jika seseorang bisa mengujinya atau setidaknya mengatakan mereka percaya itu bekerja lebih dulu.

Jawaban:

2

Jelly , 24 byte

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

Cobalah online!

Penjelasan:

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

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

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

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

Cobalah online!

Bagaimana itu bekerja

Ini adalah program lengkap. Kami mendefinisikan fungsi f untuk tujuan kami. Untuk menyimpan byte, dinyatakan dengan dua argumen yang default ke int . Ini adalah perilaku yang tidak terdefinisi, tetapi dalam praktiknya, n akan diinisialisasi sebagai 1 saat menjalankan program tanpa argumen tambahan, c akan menahan 32 bit lebih rendah dari pointer ke vektor argumen

Sementara kondisinya

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

tahan, kami akan menjalankan tubuh while :

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

Untuk sepenuhnya memahami kondisinya, pertama-tama kita harus memeriksa tubuh. Untuk saat ini, yang kami amati adalah yang c=getchar()membaca satu byte dari STDIN (jika mungkin) dan menyimpannya dalam variabel c .

Urutan byte halo terlihat sebagai berikut dalam representasi berbeda.

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

Semua ini berada dalam kisaran [96, 192) , sehingga c/96akan mengevaluasi ke 1 untuk setiap byte ini, dan ke 0 untuk semua karakter ASCII yang tersisa. Dengan cara ini, putchar(c)/96*c( putchar mencetak dan mengembalikan argumennya) akan mengevaluasi ke c jika c adalah `, huruf kecil, salah satu {|}~, atau karakter DEL; untuk semua karakter ASCII lainnya, itu akan mengevaluasi ke 0 .

n diperbarui dengan menggesernya lima bit ke kiri, kemudian XORing hasilnya dengan hasil dari paragraf sebelumnya. Karena int adalah 32 bit lebar (atau lebih kita asumsikan dalam jawaban ini), beberapa bit yang bergeser mungkin "jatuh dari kiri" (ditandatangani integer overflow adalah perilaku tidak terdefinisi, tetapi gcc berperilaku sebagai instruksi x64 yang dihasilkannya di sini). Dimulai dengan nilai n yang tidak diketahui , setelah memutakhirkannya untuk semua karakter halo , kami mendapatkan hasil berikut.

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

Perhatikan bahwa 25 bit yang lebih rendah membentuk integer 0xb33def , yang merupakan konstanta ajaib dalam kondisi tersebut. Sementara ada beberapa tumpang tindih antara bit dari dua byte yang berdekatan, pemetaan byte di bawah 96 hingga 0 memastikan bahwa tidak ada false positive.

Kondisi ini terdiri dari dua bagian:

  • ~(getchar()) mengambil bitwise TIDAK dari hasil membaca (atau berusaha membaca) satu byte dari STDIN.

    Jika getchar berhasil, itu akan mengembalikan nilai byte read sebagai int . Karena input seluruhnya terdiri dari karakter ASCII, byte baca hanya dapat memiliki 7 bit yang lebih rendah, sehingga bitwise TIDAK akan memiliki 25 bit tertinggi yang ditetapkan dalam kasus ini.

    Jika getchar gagal (tidak ada input lagi), itu akan mengembalikan -1 dan bitwise TIDAK akan menjadi 0 .

  • n-0xb33def<<7kurangi konstanta ajaib dari sebelumnya dari n , lalu alihkan hasilnya 7 unit ke kiri.

    Jika 5 byte terakhir dibaca adalah hello , 25 bit terendah n akan sama dengan 0xb33def dan pengurangannya akan nol. Menggeser perbedaan akan menghasilkan 0 karena 7 bit tertinggi akan "jatuh dari kiri".

    Di sisi lain, jika 5 byte terakhir dibaca bukan halo , salah satu dari 25 bit terendah dari perbedaan akan ditetapkan; setelah bergeser, salah satu dari 25 bit tertinggi adalah.

Akhirnya, jika getchar berhasil dan kami belum mencetak halo , bitwise AND, semua 25 bit tertinggi dari operan kiri dan setidaknya satu dari 25 bit tertinggi dari yang benar akan ditetapkan. Dengan cara ini, &akan menghasilkan bilangan bulat bukan nol dan loop berlanjut.

Di sisi lain, jika input sudah habis atau kita sudah mencetak halo , salah satu operan bitwise AND akan menjadi nol, dan begitu juga hasilnya. Dalam hal ini, kami keluar dari loop dan program berakhir.

Dennis
sumber
Anda mungkin harus menyebutkan bahwa ini tergantung pada input yang dikodekan dalam ASCII, sebelum menggali penjelasan.
Toby Speight
2
@TobySpeight Saya tidak berpikir itu umum untuk menentukan ini. Jenis pengkodean ASCII yang tidak kompatibel seperti apa yang Anda harapkan jawaban C untuk digunakan?
Dennis
EBCDIC adalah penyandian yang jelas bukan ASCII. C tidak meresepkan pengkodean karakter tertentu (hanya bahwa angka desimal harus diwakili oleh nilai berturut-turut, secara berurutan).
Toby Speight
program di atas berhenti jika aliran mengandung string bukan ascii "« úá ÷ o "1: o 111 6f 2: ÷ 246 f6 3: á 160 a0 4: ú 163 5:« 174
RosLuP
@RosLuP Spec tantangan menjamin bahwa input akan terdiri dari karakter dan baris ASCII yang dapat dicetak.
Dennis
19

Bash, 74 75 103 99 88 82 76 byte

-10 byte berkat @DigitalTrauma!
-11 byte terima kasih kepada @manatwork!
-6 byte terima kasih kepada @Dennis!

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

Penjelasan:

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

Cobalah online!

betseg
sumber
2
Ini bagus! Saya berharap akan ada jawaban kasar.
13

Labirin , 43 41 byte

Terima kasih kepada Sp3000 untuk menghemat 2 byte.

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

Cobalah online!

Penjelasan

Ide dasarnya adalah untuk menyandikan lima karakter terakhir dalam basis 256 dalam satu integer. Ketika karakter baru masuk, kita dapat "menambahkan" dengan mengalikan bilangan bulat dengan 256 dan menambahkan titik kode baru. Jika kita ingin melihat hanya pada 5 karakter terakhir, kita mengambil nilai modulo 256 5 = 2 40 = 1099511627776. Kemudian kita cukup memeriksa apakah nilai ini sama dengan 448378203247, yang adalah apa yang kita dapatkan ketika kita memperlakukan poin kode dari hellosebagai basis-256 digit.

Adapun kode ... <...>adalah sedikit idiom Labyrinth. Ini memungkinkan Anda untuk menulis loop tanpa batas tanpa aliran kontrol bersyarat pada satu baris, menghemat banyak byte pada spasi dan umpan baris. Kondisi utama agar ini berfungsi adalah bahwa ada dua nilai pakai di atas tumpukan ketika kita mencapai <(kita biasanya menggunakan 0s untuk itu, tetapi nilai aktualnya sewenang-wenang).

Tentu saja, program ini memang membutuhkan beberapa logika kondisional untuk mencari tahu kapan harus mengakhiri. Tetapi mengakhiri program dengan kondisional dimungkinkan dengan membagi dengan nilai yang nol ketika kita ingin program berakhir. The <...>membangun karya dengan menggeser seluruh baris kiri (siklis) ketika IP adalah pada akhir kiri, dan kemudian segera bergeser kembali ke posisinya. Ini berarti bahwa kode sebenarnya dieksekusi dari kanan ke kiri. Mari kita balikkan:

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

Ini adalah salah satu iterasi dari loop yang membaca karakter, berakhir jika kita telah mencapai EOF, mencetak karakter, menambahkannya ke pengkodean kita, memotongnya menjadi 5 karakter, memeriksa kesetaraan dengan hellodan mengulangi. Inilah cara kerjanya secara detail (ingat bahwa Labyrinth berbasis stack):

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

Brainfuck, 658 byte

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

Lebih dari 500 byte berada dalam konstanta yang saya butuhkan untuk bermain golf sedikit.

Ini pada dasarnya adalah mesin keadaan, jadi input tak terbatas bukanlah masalah.

Ini adalah versi yang sedikit berkomentar

+
[
  >,.
  >h
  [-<->]
  +<
  [
    >-<[-][in input spot, not h]
  ]
  >
  [
    -
    <
    [in input spot, h has been read]
    ,.
    >e
    [-<->]
    +<
    [
      >-<[-][in input spot, not e]
    ]
    >
    [
      -
      <
      [in input spot, e has been read]
      ,.
      >l
      [-<->]
      +<
      [
        >-<[-][in input spot, not l]
      ]
      >
      [
        -
        <
        [in input spot, l has been read]
        ,.
        >l
        [-<->]
        +<
        [
          >-<[-][in input spot, not l]
        ]
        >
        [
          -
          <
          [in input spot, l has been read]
          ,.
          >o
          [-<->]
          +<
          [
            >-<[-][in input spot, not o]
          ]
          >
          [
            -
            <
            [in input spot, o has been read]
            <->>
          ]
        ]
      ]
    ]
  ]
  <<
]
jvluso
sumber
Ini terlihat menyenangkan :)
Selamat datang di Puzzles Pemrograman dan Kode Golf StackExchange!
betseg
1
Kode ini memiliki banyak masalah, tetapi masalah terbesar adalah bahwa ia tidak menyertakan logika untuk menangani kasus seperti ahehellobdengan benar; di tengah-tengah kecocokan potensial, itu hanya memeriksa huruf berikutnya hellodan tidak mencari untuk hmemulai kembali.
Mitch Schwartz
8

Bash , 73 68 66 byte

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

Mengasumsikan direktori tanpa atau hanya file tersembunyi. Harus dijalankan sebagai <path/to/script>.

Cobalah online!

Cara kerjanya (ketinggalan jaman)

Pada awal loop sementara , pertama-tama kita menguji apakah string dalam variabel s (awalnya kosong) sama dengan olleh ( halo mundur, olé), dan kembalikan 0 (cocok) atau 1 (bukan yang cocok). Walaupun secara formal bagian dari kondisi loop, hasilnya tidak akan memengaruhi itu sendiri, karena hanya perintah terakhir sebelum domenentukan apakah kondisi tersebut berlaku.

Selanjutnya, kita mengatur pemisah bidang internal ke string kosong (jadi readtidak akan tersedak di spasi putih), membaca byte mentah ( -r) dari STDIN dan menyimpannya di c. $?adalah kode keluar dari perintah sebelumnya, jadi ini membaca tepat satu ( -N1) byte untuk non-cocok dan nol byte ( -N0). Membaca nol byte, baik karena menekan EOF atau karena -N0ditentukan, menyebabkan readkeluar dengan kode status 1 , sehingga loop sementara akan berakhir; kalau tidak, tubuh dieksekusi dan kita mulai lagi dari awal.

Di dalam tubuh, pertama kita mencetak byte yang kita baca, maka update s dengan s=$c${s::4}. Ini akan menambah byte read ke (hingga) empat byte pertama dalam s , jadi s akan sama dengan olleh begitu hello telah dicetak.

Dennis
sumber
Memang sangat bagus!
8

brainfuck, 117 byte

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

Diformat:

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

Cobalah online .

Ini menginisialisasi rekaman dengan karakter hellodiimbangi oleh 107, spasi dengan satu nilai setiap tiga sel, kemudian melacak lima karakter terakhir yang terlihat dan memeriksa kecocokan dengan setiap karakter baru yang diproses, menggunakan bendera di sebelah kanan string untuk melacak apakah ada kecocokan.

Mitch Schwartz
sumber
7

Ruby , 46 60 byte

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

Cobalah online!

Membaca karakter dari stdin hingga 5 terakhir hello, lalu mengeluarkan string (atau hingga tidak ada karakter yang tersisa di stdin). Berakhir dengan kesalahan.

Setara dengan:

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

Atau, lebih ungolfed:

a = ""
loop do
    q = STDIN.getc
    break if a[-5..-1] == "hello" or not q
    a += q
    print q
end
Conor O'Brien
sumber
1
atumbuh setiap kali arang dibaca. Apakah ini macet jika inputnya tidak terbatas?
betseg
@ betseg hm, mungkin. Biarkan saya melihat apakah saya dapat memperbaikinya
Conor O'Brien
7

Python 3, 120 116 104 Bytes

Bekerja dengan aliran tanpa batas, golf pertama kali, tips apa pun akan dihargai.

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

Terima kasih @DJMcMayhem karena telah menghemat beberapa byte :)

R. Martin
sumber
Selamat datang di situs ini! c=[0,c+1]['hello'[c]==a]harus menghemat beberapa byte. Juga, a=1lebih pendek juga.
DJMcMayhem
2
Anda tidak perlu tanda kurung whiledalam Python.
PurkkaKoodari
6

Haskell, 41 47 43 byte

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

Kemalasan Haskell menangani input / output tak terbatas berhenti dengan baik.

Cobalah online!

Sunting: tidak menangani input hingga - diperbaiki. Terima kasih @ Leo untuk menunjukkan.

Sunting II: @ Ørjan Johansen menyimpan 4 byte. Terima kasih!

nimi
sumber
2
Masukan mungkin juga terbatas, jadi saya pikir Anda harus berurusan dengan kasing saat Anda mencapai akhir tali
Leo
@ Leo: Ups, sangat merindukannya. Tetap.
nimi
2
Penjaga pertama bisa disingkat menjadi |w@"hello"<-take 5l=w.
Ørjan Johansen
@ ØrjanJohansen: oh, itu bagus. Terima kasih!
nimi
6

Cubix, 94 83 82 79 63 56 byte

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

Diperluas:

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

Catatan

  • Interpreter menonaktifkan kolom input saat program dimulai. Dengan demikian, aliran input yang tidak terbatas tidak mungkin. Program ini mengambil input karakter per karakter, jadi jika bukan karena batasan ini, itu akan berfungsi dengan baik.
  • Program ini tidak membersihkan tumpukan, dan menjadi berantakan dengan sangat cepat. Karena mesin ini akan digunakan pada ternyata dapat memberikan aliran input yang tak terbatas, tampaknya masuk akal untuk menganggap bahwa ia juga memiliki memori yang tak terbatas.
  • Bantuan golf apa saja sangat dihargai.

Cobalah online

Anda bisa mencoba programnya sini .

Penjelasan

Ide umum

Gagasan umum adalah bahwa kita ingin membaca sebuah karakter, dan kemudian memeriksanya terhadap berbagai karakter (pertama h, lalu e, kemudianl dll). Untuk melacak karakter yang telah kita lewatkan, kita menyimpannya di bagian paling bawah tumpukan. Ketika kita membutuhkannya, kita dapat dengan mudah membawanya ke atas lagi.

Baca / Tulis loop

Loop baca-tulis hanyalah baris ke- 5 . Semua karakter yang tidak digunakan digantikan oleh no-ops ( .):

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

Ini dapat dibagi menjadi dua bagian: Membaca dan (menulis dan memeriksa). Bagian pertama berisi instruksi hingga dan termasuk tanda tanya. Bagian kedua adalah sisa baris. Karena ini berulang, kita asumsikan kita mulai dengan setumpuk[...]

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

Bagian kedua (menulis dan memeriksa) linier lagi. Tumpukan dimulai sebagai [next-char, ..., input]. Kami mengabstraksi karakter berikutnya, karena itu berubah kemudian dalam 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.

Sekarang, IP akan mulai lagi pada awal loop ini, mengatur ulang karakter berikutnya untuk diperiksa h.

Mencocokkan karakter berikutnya

Jika IP berbelok-u (yaitu karakter yang kita baca dan cetak cocok dengan karakter berikutnya 'hello'), kita perlu memeriksa karakter apa yang dimasukkan dan tergantung pada itu, dorong karakter berikutnya ke bagian bawah tumpukan. Setelah itu, kita perlu kembali ke loop baca / tulis, tanpa mendorong hke stack, jadi kita perlu cara lain untuk sampai ke sana.

Hal pertama yang pertama: menentukan karakter apa yang dimasukkan. Tumpukan terlihat seperti ini: [..., prev-char, input, 0].

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

Untuk membandingkan input, kami menggunakan kode karakter hlagi. Awalnya, ini karena saya tidak benar-benar tahu bagaimana saya akan menangani ini dan hmerupakan karakter pertama dalam string yang diperiksa, tetapi akhirnya menjadi cukup nyaman. Jika kita mengurangi kode karakter h dari input, kita dapatkan -3jika inputnya adalah e, 0jika inputnya adalah h, 4jika inputnya adalah ldan 7jika inputnya adalaho .

Ini berguna, karena ?perintah tersebut memungkinkan kita dengan mudah memisahkan nilai negatif dari nilai positif dan nol. Dengan demikian, jika IP belok kiri, perbedaannya negatif, jadi inputnya adalah e, jadi karakter selanjutnya harus menjadi l. Jika IP terus berjalan lurus, perbedaannya adalah 0, jadi inputnya adalah h, jadi karakter selanjutnya harus menjadi e. Jika inputnya adalah an latau an o, IP berbelok ke kanan.

Semua instruksi yang dijalankan sebelum tanda tanya tersebut adalah:

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

Sekarang IP mengubah arahnya seperti yang dijelaskan di atas. Mari kita membahas berbagai kemungkinan yang berbeda.

Memasukkan 'e'

Pertama kita akan mempertimbangkan input e, yang menyebabkan IP bergerak ke atas dari ?, karena perbedaannya adalah 3. Semua karakter yang tidak relevan telah dihapus dari kubus.

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

Karakter dieksekusi dalam urutan ini (tidak termasuk beberapa karakter aliran kontrol):

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

Sekarang IP telah mencapai loop baca / tulis lagi.

Memasukkan 'h'

Jika inputnya adalah 'h', selisihnya adalah 0, sehingga IP tidak mengubah arahnya. Inilah kubusnya lagi, dengan semua karakter yang tidak relevan dihapus. Karena jalur ini mencakup beberapa no-ops, semua no-ops yang dilaluinya telah diganti oleh &. IP dimulai pada tanda tanya.

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

Instruksi yang dijalankan adalah:

'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

Dan sekarang kita memasuki loop baca / tulis lagi, jadi kita selesai.

Masukan lainnya

Semua input lainnya menghasilkan perbedaan positif, sehingga IP berbelok ke kanan pada tanda tanya. Kita masih perlu memisahkan ldano , jadi itulah yang akan kita lakukan selanjutnya.

Memisahkan 'l' dan'o'

Perlu diingat bahwa perbedaannya adalah 7 untuk odan 4 untuk ldan bahwa kita harus mengakhiri program jika inputnya adalah o. Inilah kubus lagi dengan bagian-bagian yang tidak relevan digantikan oleh a .dan no-ops IP crosses telah digantikan oleh ampersand.

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

Membedakan antara dua 'l's

Jadi, sekarang kita sudah tahu inputnya adalah l, tetapi kita tidak tahu yang mana l. Jika ini yang pertama, kita perlu mendorong yang lain lke bagian bawah tumpukan, tetapi jika yang kedua, kita perlu mendorong o. Ingat kami menyimpan -3ke bagian bawah tumpukan tepat sebelum kami mendorong yang pertama l? Kita dapat menggunakannya untuk memisahkan dua cabang.

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

Tumpukan dimulai sebagai [..., -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

Pertama 'l'

Jika ini yang pertama 'l', kita perlu mendorong yang lain 'l'. Untuk menyimpan byte, kami menggunakan karakter yang sama dengan yang pertama 'l'. Kami dapat menyederhanakan tumpukan menjadi[...] . Inilah bagian yang relevan dari kubus, dengan no-op digantikan oleh ampersand.

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

Instruksi berikut dijalankan:

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

Kami akan memasuki loop baca / tulis, jadi kami selesai dengan cabang ini.

Kedua 'l'

Jika input adalah yang kedua 'l'dalam 'hello', IP berbelok ke kanan di tanda tanya. Sekali lagi, kita dapat menyederhanakan tumpukan [...]dan IP mulai ?, menunjuk ke selatan saat ini.

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

Instruksi yang dijalankan adalah:

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

Dan IP akan memasuki loop baca / tulis lagi, jadi kita sudah selesai dengan cabang ini juga.

Luke
sumber
Upaya heroik!
5

C ++, 142 141 byte

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

Cobalah online!

Steadybox
sumber
Apakah ini mungkin dengan GCC? Saya tidak melihat #importdi program GCC C ++ ...
ckjbgames
1
@ckjbgames #importadalah ekstensi GCC yang sudah tidak digunakan lagi.
Steadybox
1
@ckjbgames info lebih lanjut di sini: stackoverflow.com/questions/172262/…
iFreilicht
@ iFreilicht Pertanyaan itu sebenarnya membuat saya menanyakan hal itu.
ckjbgames
1
@ckjbgames Anda mungkin ingin melihat jawaban kedua: stackoverflow.com/a/172264/2533467 "Impor dalam gcc berbeda dari impor di VC ++. Ini adalah cara sederhana untuk memasukkan header paling banyak hanya sekali saja. "
iFreilicht
3

Node, 124 byte

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

Tidak berasumsi bahwa streaming akan sesuai dengan memori yang tersedia.

Neil
sumber
3

C #, 134 byte

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

Cobalah secara Online

Membaca karakter, memeriksa bukan -1 (EOS) dan kami belum melihat "halo", kemudian menambahkannya ke string, dan menulis karakter keluar. Kami menambahkan karena s[0]jauh lebih pendek daripada (char)s. Ini memiliki biaya kuadrat dalam panjang string, karena harus mengalokasikan dan memindai seluruh input setiap kali membaca karakter (ini akan macet setelah input 2GB karena kendala dalam CLR, apakah itu diperbolehkan?)

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

Untuk versi (lebih lama: 142 byte) yang tidak kehabisan memori, dan yang memiliki biaya per karakter konstan, lihat di bawah:

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

Yang ini menyimpan 5 karakter terakhir dalam string 5-panjang, yang berarti perbandingan singkat, dan pencarian char terakhir murah, tetapi jauh lebih mahal untuk diperbarui.

using C=System.Console;

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

PHP, 57 55 53 byte

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

karena tidak ada file tanpa batas, saya mengambil input dari STDIN. Jalankan dengan-nr .

Ulangi input, cetak karakter saat ini, tambahkan ke $s, potong $shingga 5 karakter terakhir. Istirahat lingkaran saat $sini hello.

Titus
sumber
3

Vim, 39 byte

:im hello hello:se noma
:map : i

i

Cobalah online!

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

i                                "enter insert mode and await an infinite stream of input
nmjcman101
sumber
Apakah ini metode input yang diterima untuk Vim? Saya pikir program Vim biasanya mengharapkan input sudah ada di buffer sebelum mereka mulai.
Martin Ender
Sejujurnya saya tidak tahu? Itu benar, tetapi hampir tidak memungkinkan untuk aliran tanpa batas, jadi saya hanya melakukannya dengan cara ini tanpa benar-benar berpikir keras tentang hal itu.
nmjcman101
Apa yang terjadi jika ada karakter escape di input stream?
redup
@dim saya bertanya, dan OP hanya menentukan ASCII yang dapat dicetak dan baris baru. ESC tidak termasuk dalam ASCII yang dapat dicetak afaik
nmjcman101
3

PowerShell, 111 byte

Mungkin ada cara yang lebih baik untuk melakukan ini, tetapi saya tidak bisa melihatnya saat ini.

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

Ini membaca sapuan kunci tanpa menekan gema. Karakter ditambahkan ke $ x yang dipangkas menjadi 5 karakter terakhir dan dibandingkan dengan "halo". Ini berlanjut sampai perbandingan benar.

Catatan: ini tidak berfungsi di PowerShell ISE. ReadKey dinonaktifkan di lingkungan itu.

MickyT
sumber
3

Skema 115 byte

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

Versi yang dapat dibaca:

(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

Ini mengambil arang individu dari stdin setiap kali di sekitar loop, dan menandai posisinya pada kata target karena memenuhi karakter "halo".

Berhenti ketika input habis atau "halo" telah terlihat. Tidak ada memori yang digunakan pada aliran infinite.

Peter
sumber
Jawaban keren, selamat datang di situs!
DJMcMayhem
3

AWK, 95 byte

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

Ada 2 hal yang saya pelajari di sini:
1) Untuk membagi catatan antara penggunaan karakter RS="(.)"dan kemudian RTharus digunakan, bukan $1
2) ORSdigunakan oleh printdan default ke "\n"
3) Saya tidak dapat menghitung ke 2 dan menggunakan printf"lebih murah" daripada menetapkan ORSdan menggunakanprint

Contoh penggunaan: Tempatkan kode dalam FILE

awk -f FILE some_data_file

atau

some process | awk -f FILE

Kode diuji menggunakan yes | ...saran Dennis dan saya melihat banyak sekali y.

FYI, Anda dapat melakukan tugas RS sebagai opsi dan menariknya keluar dari BEGIN blok melalui:

awk -v RS='(.)'
Robert Benson
sumber
Solusi yang sangat rumit! (Mungkin karena itu Jumat sore, tapi saya merasa masuk yang baik untuk tantangan dikaburkan juga.) Meskipun aku akan mencoba pendekatan yang lebih awkish: BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}.
manatwork
Anehnya, saya memiliki jawaban yang hampir persis siap dikirim satu jam yang lalu ... dan lupa mengirimkannya. : p
Robert Benson
3

Python 3 (Linux), 73 72 byte

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

Terima kasih kepada @MitchSchwartz karena bermain golf 1 byte!

Cobalah online!

Dennis
sumber
Saya tidak mengerti. Bagaimana kondisi untuk whilemengevaluasi dengan benar? Sepertinya Anda membandingkan boolean dengan string kosong.
iFreilicht
1
s[print(end=c):4]menghemat satu byte
Mitch Schwartz
1
@ iFreilicht Python mengurai kondisional berantai seperti pada matematika ( a <b <c , misalnya). Kondisi ini adalah singkatan untuk 'olleh'!=s and s>''and''<c). Tes tengah tidak diperlukan, tetapi merantai mereka lebih pendek daripada langsung 'olleh'!=s and''<c.
Dennis
@MitchSchwartz Itu benar. Terima kasih!
Dennis
3

8086 kode mesin, 22 byte

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

Kode perakitan yang setara:

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"
pengguna5434231
sumber
Bagaimana cara kerjanya?
1
Saya menambahkan kode perakitan yang setara. Ini pada dasarnya bergantung pada satu syscall DOS yang sangat berguna, yang membaca satu byte dari stdin dan mengembalikannya ke stdout pada saat yang sama. 8086 juga memiliki instruksi perbandingan string byte tunggal yang berguna di sini.
user5434231
2

Pyth, 49 47 byte

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

Pyth tidak pandai mengambil satu karakter input. Semuanya ada di$__import__("sys").stdin.read(1) hanya melakukan itu. Juga, ini berarti ini hanya berjalan offline.

Yang lainnya pendek ...

Program ini adalah loop sementara tanpa tubuh. Di dalam kondisi tersebut, program membaca karakter, mencetaknya kembali, menambahkan karakter itu ke k(yang awalnya string kosong), memotong semua kecuali 5 karakter terakhir k, dan kemudian memeriksa bahwa hasilnya tidak"hello" .

32 karakter mendapatkan satu byte input, 15 karakter sisanya.

Diuji di Linux, bekerja bahkan tanpa baris baru, masukan tanpa batas, dll.

isaacg
sumber
2

Lua, 68 64 byte

l=""while l~="hello"do c=io.read(1)io.write(c)l=l:sub(-4)..c end
Pengobrol
sumber
1
Ubah irisan menjadi l:sub(-4), maka Anda dapat mengurangi inisialisasi l="".
manatwork
@manatwork Itu rapi. Terima kasih atas tipnya.
Blab
2

Ruby, 59 49 48 43 byte

Sekarang bebas kata-kata kasar, lebih pendek, dan tanpa kebocoran memori.

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

Disimpan 5 byte dengan menghilangkan beberapa tanda kurung dan ruang berkat Dennis

daniero
sumber
1

Röda , 49 47 byte

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

Cobalah online!

Ini adalah fungsi anonim yang membaca karakter dari aliran inputnya dan mengeluarkannya sampai "halo" ditemukan. Menggunakan arraya untuk melacak karakter terakhir.

Ini mengeluarkan beberapa sampah ke STDERR, tapi saya mengerti bahwa itu diperbolehkan .

Penjelasan:

{
    a=[0]*5                /* Initialize the array with 5 zeroes. */
    {|x|                   /* For each x in the input stream: */
        [x];               /* Print x */
        a=a[1:]+x;         /* Add x and remove the sixth last character. */
        z if[a&""="hello"] /* If "hello" is found, crash the program */
                           /* with an undefined variable. */
    }_                     /* End for loop. */
}
fergusq
sumber
Di mana dokumentasi Roda?
ckjbgames
@ckjbgames Di Sini. Saya menggunakan versi terbaru 0.12, yang ada di cabang sendiri di Github.
fergusq
1

Java 7, 122 118 124 123 150 141 byte

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

Sekarang berhenti ketika ujung aliran tercapai. Sekarang menangani input tanpa batas tanpa kehabisan memori.

Menyodok
sumber
Saya yakin ini tidak bisa menangani input yang tak terbatas.
Titus
@Titus diperbaiki ...
Poke
Saya downvoted tanpa melihat writesedang digunakan print. Saya tidak bisa membatalkan downvote saya, maaf untuk itu :(
Olivier Grégoire
1

Ruby, 51 byte

x="";$><<x[-1]while/hello./!~x=x[/.{0,5}$/]+$<.getc
  • Tidak mengharapkan baris baru
  • Bekerja dengan input yang tak terbatas
GB
sumber
1

AHK , 116 byte

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

Tidak ada yang pintar atau magis di sana, sungguh. Variabel %1%adalah argumen yang diteruskan pertama dan harus menjadi jalur file dengan aliran. File harus disimpan saat diperbarui tetapi kode akan membaca sampai akhir bahkan jika diperluas setelah pembacaan dimulai.

Toast insinyur
sumber
1

Mathematica, 107 byte

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

Output menjadi bidang di mana pengguna dapat mengetik teks tanpa batas (termasuk baris baru) hingga 5 karakter terakhir sama dengan "hello"; pada saat itu, ia keluar.

numbermaniac
sumber
1

brainfuck , 281 byte

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

Saya tidak yakin mengapa, tapi saya merasa brainfuck adalah hal yang tepat untuk melakukan ini. Tidak memerlukan memori yang tak terbatas, dan dapat menghasilkan selamanya.

Dijelaskan

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
]

Cobalah online!

ATaco
sumber
Saya akan melakukannya seperti ini tetapi kemudian saya menyadari bahwa ini menghasilkan byte nol tanpa batas untuk input yang tidak mengandung "halo": tio.run/nexus/…
KarlKastor
Ini juga gagal ahehellob.
Mitch Schwartz