Senin selamın bana ulaştı


30

Görev

Muhtemelen sonsuz bir metin akışında veya dosyasında, sözcüğü çıkana kadar içeriğini helloçıkarıp aşağıdaki kurallara uyarak okuyun.

  • Bir kez helloçıktı alındığında, kodunuz derhal sonlandırılmalıdır. Örneğin yeni bir satır beklememelidir.

  • Kodunuz ilerledikçe çıkmalıdır. Bu, çok miktarda girdi okumamalı ve ardından çıktı vermeye başlamalıdır.

  • Akış / dosya içermiyorsa hello, kodunuz yalnızca girdiyi sonsuza kadar veya akış / dosyanın sonuna ulaşılana kadar çıkarmaya devam etmelidir.

  • Bu, büyük / küçük harfe duyarlı bir meydan okumadır, yani helloeşit değildir Hello.

  • Girişin yalnızca yazdırılabilir ASCII karakterlerinden ve yeni satırlardan oluştuğunu varsayabilirsiniz.

  • Kodunuz, metnin yeni bir satırla sonlandırılmasını veya girişte herhangi bir yeni satırın olmasını bekleyemez. Ayrıca, kodunuz sonsuz miktarda belleğe sahip bir makinede çalışacağını varsayamaz.

  • Kodunuzun boş bir dizinden çağrılacağını varsayabilirsiniz.

Örnek giriş akışı

I once had a horse called hellopina.

Çıktı

I once had a horse called hello

Bahşiş

yes | tr -d \\n | <your program>Sonsuz akışlarla çalışıp çalışmadığını kontrol etmek için çalıştırın . Hiçbir şey yazdırmazsa ve / veya hafıza sızdırıyorsa, program teknik özelliklere uygun değildir. yyyyyyyyyyyyyyyyyyyyyy...Sonsuza kadar yeni satırlar olmadan yazdırmalıdır .


1
"Merhaba" dan sonra bir şey okumamıza izin var mı? Soru, (Standart) C gibi dillerde otomatik ön okuma ile tamponlanmış girdi sağlayan sorunlu olabilecek ek okumaları yasaklıyor gibi görünmektedir.
Toby Speight

Muhtemelen 2 byte daha kısa olduğu için meclise verilen cevabı muhtemelen değiştirmelisiniz.
Rɪᴋᴇʀ

@Riker Birisi test edebilir ya da en azından önce çalıştığına inandıklarını söyleseydin harika olurdu.

Yanıtlar:


2

Jöle , 24 bayt

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

Çevrimiçi deneyin!

Açıklama:

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

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

Çevrimiçi deneyin!

Nasıl çalışır

Bu tam bir programdır. Amaçlarımızı f ile tanımlıyoruz . Baytları kurtarmak için, varsayılan olarak int olan iki argümanla bildirilir . Bu tanımlanamayan bir davranış, ancak pratikte, ek bağımsız değişkenler olmadan programı çalıştırırken n değeri 1 olarak başlatılacak , c , göstergenin alt 32 bitini argüman vektörüne tutacaktır.

Durum iken

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

tutarsa, while döngüsünün gövdesini çalıştırırız :

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

Durumu tam olarak anlamak için önce bedeni incelemeliyiz. Şimdilik gözlemlediğimiz c=getchar()tek şey STDIN'den (eğer mümkünse) tek bir bayt okuyor ve c değişkeninde saklıyor. .

Bayt dizisi merhaba farklı gösterimlerde aşağıdaki gibi görünüyor.

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

Bunların hepsi [96, 192) aralığındadır , bu yüzden bu baytların her biri c/96için 1 , kalan tüm ASCII karakterleri için 0 olarak değerlendirilir. Bu şekilde, putchar(c)/96*c( putchar değerlendirecek baskılar ve argüman döner) c ise c olan `bir küçük harf, biri {|}~veya DEL karakteri; diğer tüm ASCII karakterleri için 0 olarak değerlendirilecektir .

n beş bit sola kaydırılarak güncellenir, ardından sonucu önceki paragraftan elde edilen sonuçla XORing. Bir int 32 bit genişliğinde olduğundan (veya bu cevabın içinde varsayıyoruz), kaydırılan bitlerin bir kısmı "sola düşebilir" (işaretli tamsayı taşması tanımsız davranıştır, ancak gcc burada oluşturduğu x64 komutu gibi davranır). Bilinmeyen bir n değeriyle başlayarak , merhaba tüm karakterleri için güncelledikten sonra aşağıdaki sonucu elde ederiz.

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

Düşük 25 bitin, durumdaki sihirli sabit olan 0xb33def tamsayısını oluşturduğunu unutmayın . İki bitişik baytın bitleri arasında bir miktar örtüşme olsa da, 96 ila 0'ın altındaki baytları eşlemek, hatalı pozitif olmadığından emin olur.

Durum iki bölümden oluşur:

  • ~(getchar()) STDIN'den bir byte okuma sonucu (veya okumaya teşebbüs etmenin sonucu olarak) bit cinsinden DEĞİL alır.

    Getchar başarılı olursa , okuma baytının değerini int olarak döndürür . Girdi tamamen ASCII karakterlerinden oluştuğundan, okunan bayt yalnızca daha düşük 7 biti ayarlayabilir, bu nedenle bit yönünde NOT bu durumda ayarlanmış en yüksek 25 bite sahip olacaktır.

    Eğer getchar (daha fazla giriş) başarısız olur, bu döner -1 ve bit olacak değil 0 .

  • n-0xb33def<<7sihirli sabiti daha önce n'den çıkartır , ardından sonucu 7 birim sola kaydırır.

    Son 5 okuma baytı merhaba olsaydı , en düşük 25 bit n , 0xb33def değerine eşit olacak ve çıkarma onları sıfırlayacaktır. Farkın değiştirilmesi, en yüksek 7 bit "soldan düşeceği" için 0 verecektir.

    Öte yandan, son 5 byte ise merhaba değilse , farkın en düşük 25 bitinden biri belirlenecek; Vites değiştirdikten sonra en yüksek 25 bitten biri olacaktır.

Son olarak, eğer getchar başarılı olduysa ve henüz merhaba basmadıysak, bit cinsi AND, sol işlenenin en yüksek 25 bitinin tümü ve sağ olanın en yüksek 25 bitinin en az biri ayarlanacaktır. Bu sayede &sıfır olmayan bir tam sayı verilir ve döngü devam eder.

Öte yandan, eğer girdi tükenmişse veya merhaba yazdıysak zaten yazdıysak, bitsel AND'in biri sıfır olur ve sonuç olur. Bu durumda, döngüden ayrılırız ve program sona erer.


Muhtemelen bunun açıklamaya girmeden önce ASCII'de kodlanan girişe bağlı olduğunu söylemelisiniz.
Toby Speight

2
@TobySpeight Bunu belirtmenin yaygın olmadığını düşünüyorum. Ne tür bir ASCII uyumsuz kodlaması, bir C yanıtının kullanılmasını beklersiniz?
Dennis,

EBCDIC, ASCII olmayan açık kodlamadır. C, herhangi bir karakter kodlamasını tanımlamaz (yalnızca ondalık basamakların sırasıyla sırayla değerler ile gösterilmesi gerekir) yazmaz.
Toby Speight

akım, "" úá ÷ o "1: o 111 6f 2: ÷ 246 f6 3: á 160 a0 4: ú 163 5:« 174 ascii olmayan dizgiyi içeriyorsa durur.
RosLuP

@RosLuP The challenge spec, girişin yazdırılabilir ASCII karakterlerinden ve yeni satırlardan oluşacağını garanti eder.
Dennis,

19

Bash, 74 75 103 99 88 82 76 bayt

@DigitalTrauma sayesinde -10 bayt!
@Manatwork sayesinde -11 bayt!
@Dennis sayesinde -6 bayt!

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

Açıklama:

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

Çevrimiçi deneyin!


2
Bu harika! Bir bash cevabı olacağını umuyordum.

13

Labirent , 43 41 bayt

2 bayt tasarrufu için Sp3000'e teşekkürler.

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

Çevrimiçi deneyin!

açıklama

Temel fikir, taban 256'daki son beş karakteri tek bir tamsayıda kodlamaktır. Yeni bir karakter girdiğinde, tamsayı 256 ile çarpıp yeni kod noktasını ekleyerek onu "ekleyebiliriz". Sadece son 5 karaktere bakmak istiyorsak, modulo 256 5 = 2 40 = 1099511627776 değerini alırız. O zaman bu değerin 448378203247 koduna eşit olup olmadığını kontrol edebiliriz. helloTemel-256 basamak olarak.

Kod gelince ... <...>bir Labyrinth deyim biraz. Tek bir hatta koşullu kontrol akışı olmadan sonsuz bir döngü yazmanıza olanak tanır, bu da alan ve satır beslemede çok fazla bayt tasarrufu sağlar. Bunun çalışması için temel koşul, ulaştığımızda yığının üstünde iki tek kullanımlık değer bulunmasıdır <(normalde bunun için 0s kullanırız , ancak gerçek değer isteğe bağlıdır).

Elbette, programın ne zaman sonlandırılacağını bulmak için bazı şartlı mantıklara ihtiyacı var. Ancak, programın şartlı olarak sona ermesi, programın bitmesini istediğimizde sıfır olan bir değere bölerek mümkündür. <...>Tüm satırı kaydırarak yapı işleri (döngüsel) IP sol ucunda olduğunda bıraktı ve daha sonra hemen pozisyona geri kayması. Bu, kodun gerçekten sağdan sola yürütüldüğü anlamına gelir. Bunu tersine çevirelim:

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

Bu, bir karakter okuyan, EOF'a ulaştığımızda sona eren, karakteri basan, kodlamaya ekleyen, 5 karaktere bölen, eşitliği kontrol eden hellove tekrarlayan bir döngünün yinelemesidir. Bunun nasıl çalıştığını şöyle açıklıyoruz (Labyrinth'in yığın tabanlı olduğunu unutmayın):

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

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

500'den fazla bayt, biraz golf oynamak için ihtiyaç duyduğum sabitlerde.

Esasen bir durum makinesidir, bu nedenle sonsuz girdi sorun değildir.

Bu biraz yorumlanmış versiyon

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

Bu eğlenceli görünüyor :)

Programlama Bulmacaları ve Kod Golf StackExchange'e Hoş Geldiniz!
17'de

1
Bu kodun birden çok sorunu var, ancak en büyük sorun, bu gibi vakaları ahehellobdüzgün bir şekilde ele almak için mantık içermemesidir ; Potansiyel bir eşleşmenin ortasında, sadece bir sonraki harfin geldiğini kontrol eder hellove hbaştan başlamak için arama yapmaz .
Mitch Schwartz

8

Bash , 73 68 66 bayt

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

Yalnızca gizli dosyaları olmayan bir dizini varsayar. Olarak çalıştırılmalı<path/to/script> .

Çevrimiçi deneyin!

Nasıl çalışır (eski)

While döngüsünün başında, ilk önce s değişkenindeki (başlangıçta boş) dizgenin olleh'e ( merhaba geriye, olé) eşit olup olmadığını ve buna göre 0 (eşleşme) veya 1 (eşleşme değil ) döndürdüğünü test ederiz . Resmen döngünün koşulunun bir parçası olsa da sonuç do, koşulun tutup tutmayacağına karar vermeden önceki son komut olarak kendi başına etkilemez .

Daha sonra, iç alan ayırıcısını boş dizgiye ( readboşlukta boğulmayacağına), ham baytları ( -r) STDIN'den okuyup saklayacağız c. $?önceki komutun çıkış kodudur, bu yüzden -N1eşleşmeyen ve sıfır bayt ( -N0) için tam olarak bir ( ) bayt okur . Sıfır bayt okumak, ister EOF'a çarpması gerekse -N0de belirtilmişse, readdurum kodu 1 ile çıkmaya neden olur , böylece while döngüsü sona erer; Aksi takdirde, beden idam edilir ve baştan başlarız.

Gövdede önce okuduğumuz byte'ı bastıktan sonra s ile güncelledik s=$c${s::4}. Bu, okuma baytını s cinsinden ilk dört bayta (en fazla) kadar hazırlar , böylece merhaba yazdırıldıktan sonra s eşit olur .


Gerçekten çok iyi!

8

brainfuck, 117 bayt

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

biçimlendirilmiş:

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

Çevrimiçi deneyin .

Bu karakter bandı başlatır hellotelafi 107sonra dize sağında için bir bayrak kullanılarak işlenen her yeni karakterli bir maç için son beş görülen karakterlerin ve çek takip tutar, her üç hücreleri, tek değerle aralıklı Bir eşleşme olup olmadığını takip edin.


7

Ruby , 46 60 bayt

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

Çevrimiçi deneyin!

Stdin'den en son 5 karaktere kadar olan karakterleri okur hello, ardından dizeyi çıkarır (veya stdin'de karakter kalmayıncaya kadar). Hata ile sonlanır.

Eşittir:

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

Ya da daha fazla ungolfed:

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

1
aBir karakter okunduğu zaman büyür. Giriş sonsuzsa bu kilitlenir mi?
betseg

@ betseg hm, belki. Bunu düzeltebilir miyim bir bakayım
Conor O'Brien

7

Python 3, 120 116 104 Bayt

Sonsuz akışlarla çalışır, ilk kez golf oynar, herhangi bir ipucu takdir edilir.

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

Bazı byte'ları kaydettiğiniz için teşekkürler @DJMcMayhem :)


Siteye Hoşgeldiniz! c=[0,c+1]['hello'[c]==a]sana biraz bayt kurtarmalıyım. Ayrıca, a=1daha kısadır.
DJMcMayhem

2
whilePython'da parantez gerekmez .
PurkkaKoodari

6

Haskell, 41 47 43 bayt

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

Haskell'in tembelliği sonsuz girdi / çıktıyı sonlandırır.

Çevrimiçi deneyin!

Düzenleme: sonlu girişleri işlemedi - sabit. İşaret ettiğiniz için teşekkürler @Leo.

Düzenleme II: @ Ørjan Johansen 4 bayt kurtardı. Teşekkürler!


2
Giriş aynı zamanda sonlu olabilir, bu yüzden dizenin sonuna geldiğinizde olayla başa çıkmanız gerektiğini düşünüyorum
Leo

@ Leo: Hata! Tamamen özledim. Sabit.
nimi

2
İlk koruma kısaltılabilir |w@"hello"<-take 5l=w.
Ørjan Johansen

@ ØrjanJohansen: oh, bu güzel bir tane. Teşekkürler!
nimi

6

Cubix, 94 83 82 79 63 56 bayt

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

Expanded:

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

notlar

  • Tercüman, program başladığında giriş alanını devre dışı bırakır. Bu nedenle, sonsuz bir girdi akışı imkansızdır. Bu program girişi karakter karakter alır, bu nedenle bu sınırlama için olmasaydı, düzgün çalışacaktı.
  • Bu program yığını temizlemez ve çok çabuk dağınık olur. Bu makinenin görünüşe göre sonsuz girdi akışları verebileceği için, aynı zamanda sonsuz belleğe sahip olduğunu varsaymak makul gözükmektedir.
  • Her türlü golf yardımı çok takdir edilmektedir.

Çevrimiçi deneyin

Programı burada deneyebilirsiniz .

açıklama

Genel fikir

Genel fikir, bir karakteri okumak ve ardından değişen karakterlere karşı kontrol etmek istediğimizdir (önce h, sonra esonral vs.). Kaçırdığımız karakteri takip etmek için, yığının en altında tutuyoruz. İhtiyacımız olduğunda kolayca tekrar tepeye getirebiliriz.

Okuma / Yazma döngüsü

Okuma-yazma döngüsü sadece 5. satırdır. Kullanılmayan tüm karakterler no-ops ( .) ile değiştirilir :

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

Bu iki bölüme ayrılabilir: Okuma ve (yazma ve kontrol etme). İlk bölüm, soru işaretini içeren ve içerdiği talimatları içerir. İkinci kısım, hattın geri kalanı. Çünkü bu etrafta dolanıyor, bir yığınla başladığımızı varsayıyoruz.[...]

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

İkinci kısım (yazı ve kontrol) yine doğrusaldır. Yığın olarak başlar [next-char, ..., input]. Bir sonraki karakteri soyutladık, çünkü bu programın ilerleyen kısımlarında değişiyor.

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.

Şimdi, IP bu döngünün başında tekrar başlayacak ve kontrol edilecek bir sonraki karakteri sıfırlayacak. h .

Bir sonraki karakterin eşleştirilmesi

IP bir u dönüşü yaptıysa (yani, okuduğumuz ve yazdırdığımız karakter sonraki karakter ile eşleşti 'hello'), girişin hangi karakter olduğunu kontrol etmemiz gerekir ve buna bağlı olarak, sonraki karakteri yığının dibine iter. Bundan sonra h, yığına basmadan okuma / yazma döngüsüne geri dönmemiz gerekir , o yüzden oraya ulaşmak için başka bir yola ihtiyacımız var.

İlk önce ilk şeyler: girişin hangi karakter olduğunu belirleyin. Yığın şuna benzer: [..., prev-char, input, 0].

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

Girişi karşılaştırmak için htekrar karakter kodunu kullanırız . Başlangıçta, bunun nedeni, bununla nasıl başa çıkacağımı gerçekten bilmiyordum ve hkontrol edilecek ilk karakterdi, ama oldukça uygun oldu. Biz girişten h karakteri kodunu çıkarmak, biz olsun -3girilirse e, 0giriş ise h, 4girdi ise lve 7giriş ise o.

Bu kullanışlıdır, çünkü ?komut negatif değerleri kolayca pozitif değerlerden ve sıfırdan kolayca ayırmamızı sağlar. Dolayısıyla, IP sola dönerse, fark negatif, yani giriş öyleydi e, bu yüzden bir sonraki karakter bir olmalı l. IP düz devam ederse, fark öyleydi 0, bu yüzden giriş, bir hsonraki karakter bir olmalıdır e. Giriş bir lveya bir oise, IP sağa döner.

Yukarıda belirtilen soru işaretinden önce gerçekleştirilen tüm talimatlar:

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

Şimdi IP yukarıda belirtilen şekilde yönünü değiştiriyor. Farklı olasılıkları gözden geçirelim.

Giriş 'e'

İlk önce , farkın 3 olduğu eiçin IP'nin yukarı doğru hareket etmesine neden olan girişi dikkate alacağız ?. Tüm alakasız karakterler küpten kaldırılmıştır.

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

Karakterler bu sırada yürütülür (bazı kontrol akışı karakterleri hariç):

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

Şimdi IP tekrar okuma / yazma döngüsüne ulaştı.

Giriş 'h'

Girdi olsaydı, 'h'fark 0 olur, bu yüzden IP yönünü değiştirmez. İşte yine küp, ilgisiz tüm karakterler kaldırıldı. Bu yol epeyce no-ops içerdiğinden, geçtiği tüm no-oplar yerini aldı &. IP soru işaretinde başlar.

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

Yürütülen talimatlar:

'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

Ve şimdi tekrar okuma / yazma döngüsüne giriyoruz, bu yüzden işimiz bitti.

Diğer girişler

Diğer tüm girişler pozitif bir farkla sonuçlanır, bu nedenle IP soru işaretinde sağa döner. Hala ayırmak gerekir lveo , o yüzden bundan sonra yapacağımız şey bu.

Ayırarak 'l' ve'o'

Aradaki farkın 7 ove 4 için lolduğunu ve giriş bir ise programı sonlandırmamız gerektiğini unutmayın o. Burada yine a ile değiştirilmiş alakasız kısımları olan .ve IP çaprazları ve işareti olmayan no-op'larla değiştirilmiş küp var.

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

İki 'l's arasında ayırt

Şimdi girdilerin bir olduğunu biliyoruz l, fakat hangisini bilmiyoruz l. Birincisi, lyığının dibine bir tane daha basmamız gerekir, ancak ikinciyse, bir tane basmamız gerekir o. İlkini -3itmeden hemen önce yığının dibine kaydettiğimizi hatırlıyor musun l? Bunu iki dalı ayırmak için kullanabiliriz.

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

Yığın olarak başlar [..., -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

İlk 'l'

Eğer bu 'l'ilkseydi, bir başkasına basmamız gerekir 'l'. Bayt kaydetmek için ilk karakterle aynı karakterleri kullanırız 'l'. Yığını basitleştirebiliriz [...]. İşte no-op'lar ve işaretleri ile değiştirilmiş küpün ilgili kısmı.

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

Aşağıdaki talimatlar uygulanır:

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

Okuma / yazma döngüsüne girmek üzereyiz, bu yüzden bu dalla işimiz bitti.

İkinci 'l'

Giriş, ikinci ise 'l'de 'hello', IP soru işareti doğru döndü. Bir kez daha, yığını basitleştirebiliriz [...]ve IP ?bu kez güneye dönük olarak başlar .

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

Yürütülen talimatlar:

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

Ve IP tekrar okuma / yazma döngüsüne girmek üzere, bu yüzden de bu dalla işimiz bitti.


Kahramanca bir çaba!

5

C ++, 142 141 bayt

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

Çevrimiçi deneyin!


Bu GCC ile mümkün mü? Ben görmüyorum #importGCC C ++ programlarında ...
ckjbgames

1
@ckjbgames #importkullanımdan kaldırılmış bir GCC uzantısıdır.
Steadybox

1
@ckjbgames burada daha fazla bilgi: stackoverflow.com/questions/172262/…
iFreilicht

@ iFreilicht Bu soru aslında bunu sormamı sağladı.
ckjbgames

1
@ckjbgames ikinci cevaba bir göz atmak isteyebilirsiniz: stackoverflow.com/a/172264/2533467 "gcc cinsinden içe aktarma, VC ++ içeriğindeki içe aktarma işleminden farklıdır. Bir başlığı en çok yalnızca bir defa eklemek basit bir yoldur. "
iFreilicht

3

Düğüm, 124 bayt

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

Akışın kullanılabilir belleğe sığacağı varsayılmıyor.


3

C #, 134 bayt

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

Çevrimiçi Deneyin

Bir karakter okur, -1 (EOS) olmadığını ve henüz "merhaba" göremediğimizi kontrol eder, sonra bir dizeye hazırlar ve karakteri yazar. Hazırlıyoruz çünkü s[0]ondan çok daha kısa (char)s. Her karakter okuduğunda tüm girişin tamamını tahsis etmek ve taramak zorunda kalacağı için, dizenin uzunluğunda karesel bir maliyeti vardır (bu CLR'deki kısıtlamalar nedeniyle 2GB girişin ardından çökecektir, buna izin verilir mi?).

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

Bir (uzun: 142 bayt) için sürümü olmayacak bellek tükendi ve sabit Çerezsiz maliyetine sahip, aşağıya bakınız:

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

Bu, 5 karakterli bir dizgede son 5 karakteri tutar, bu kısa karşılaştırmalar ve ucuz son karakter araması anlamına gelir, ancak güncellenmesi oldukça pahalıdır.

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 bayt

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

sonsuz dosya olmadığı için STDIN'den girdi alıyorum. İle koş-nr .

Girdi boyunca dolaş, mevcut karakteri yazdır, ekle , son 5 karaktere kadar $skes $s. Molası döngü zaman $solduğu hello.


3

Vim, 39 bayt

:im hello hello:se noma
:map : i

i

Çevrimiçi deneyin!

: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

Bu Vim için kabul edilen bir giriş yöntemi midir? Vim programlarının genellikle girdilerin başlamadan önce tamponda olmasını beklediğini düşündüm.
Martin Ender

Dürüst olmak gerekirse bilmiyorum? Bu doğru, ancak sonsuz bir akıma izin vermiyor, bu yüzden bu konuda çok fazla düşünmeden yaptım.
nmjcman101

Giriş akışında bir çıkış karakteri varsa ne olur?
loş

@ dim sordum ve OP sadece yazdırılabilir ASCII ve yeni satırlar belirledi. ESC yazdırılabilir ASCII afaik dahil değildir
nmjcman101

3

PowerShell, 111 bayt

Bunu yapmanın daha iyi bir yolu olabilir, ama şu anda göremiyorum.

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

Bu, ekoyu bastırmadan tuş vuruşlarını okur. Karakter, son 5 karaktere kesilen ve "merhaba" ile karşılaştırılan $ x değerine eklenir. Karşılaştırma doğru oluncaya kadar bu devam eder.

Not: Bu PowerShell ISE'de çalışmaz. ReadKey bu ortamda devre dışı.


3

Şema 115 bayt

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

Okunabilir sürüm:

(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

Bu, döngü boyunca her seferinde stdin'den ayrı bir karakter alır ve hedef kelimedeki konumunu "merhaba" karakterleriyle karşılaştırarak işaretler.

Giriş bittiğinde veya "merhaba" görüldüğünde durur. Sonsuz akışta kullanılan bellek yok.


Harika cevap, siteye hoş geldiniz!
DJMcMayhem

3

AWK, 95 bayt

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

Orada burada öğrendim 2 şey vardır:
karakterler kullanmak arasındaki kayıtları bölmek için 1) RS="(.)"ve daha sonra RTyerine kullanılması gerekir $1
) 2 ORStarafından kullanılır printve varsayılan ayarı "\n"
ben 2'ye saymak olamaz) 3 ve kullanma printfatama daha "ucuz" dirORS ve kullanmaprint

Örnek kullanım: FILE içine kod yerleştirin

awk -f FILE some_data_file

veya

some process | awk -f FILE

Kod Dennis'in yes | ...önerisini kullanarak test edildi ve çok ve çok sayıda gördümy .

Bilginize, RS atamasını bir seçenek olarak yapabilir ve BEGINbloktan çekerek :

awk -v RS='(.)'

Gerçekten zor bir çözüm! (Cuma öğleden sonra, ama ben o kadar karartılmış meydan okuma için iyi bir giriş bulmak Belki de.) Ben daha awkish yaklaşım denemek istiyorum rağmen: BEGIN{RS="(.)"}{printf RT}"olleh"==a=RT substr(a,1,4){exit}.
Manatwork

İşin tuhafı, neredeyse bir saat önce ... ... göndermeye hazır cevaplarim var ... ve göndermeyi unuttum. : p
Robert Benson

3

Python 3 (Linux), 73 72 bayt

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

1 Bayt'ta golf oynamak için @MitchSchwartz'a teşekkürler!

Çevrimiçi deneyin!


Anlamadım Değerlendirme koşulu whiledüzgün bir şekilde nasıl değerlendirilir? Bir boole ile boş bir dizgiyi karşılaştırıyormuşsunuz gibi görünüyor.
iFreilicht

1
s[print(end=c):4]bir bayt kazandırır
Mitch Schwartz

1
@Freilicht Python, zincirleme koşullarını matematikte olduğu gibi ayrıştırır ( örneğin a <b <c ). Durum için bir steno 'olleh'!=s and s>''and''<c). Orta test gerekli değildir, ancak zincirleme basitten daha kısadır 'olleh'!=s and''<c.
Dennis,

@ MitchellSchwartz Bu yapar. Teşekkür ederim!
Dennis,

3

8086 makine kodu, 22 bayt

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

Eşdeğer montaj kodu:

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"

O nasıl çalışır?

1
Eşdeğer derleme kodunu ekledim. Temel olarak stdin'den bir byte okuyan ve aynı zamanda tekrar stdout'a eko yapan çok kullanışlı bir DOS sistemine dayanır. 8086 ayrıca burada kullanışlı olan tek baytlık bir dize karşılaştırma talimatına sahiptir.
user5434231

2

Pyth, 49 47 bayt

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

Pyth, tek bir giriş karakteri almakta pek iyi değildir. Her şey içinde$__import__("sys").stdin.read(1) sadece bunu yapıyor. Ayrıca, bunun yalnızca çevrimdışı çalıştığı anlamına gelir.

Her şey kısa ...

Program döngü sırasında bir bedenselliktir. Koşul içinde, program bir karakter okur, geri yazdırır, bu karakteri k(başlangıçta boş dize olan) ekler , son 5 karakterden başlayarak keser kve sonucun olmadığını kontrol eder "hello".

32 karakter bir bayt girdi alıyor, gerisi ise 15 karakter.

Linux'ta test edildi, hatta yeni satır, sonsuz girdi vb. Olmadan çalışıyor.


2

Lua, 68 64 bayt

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

1
Dilimlemeyi değiştirin l:sub(-4), ardından başlatmayı azaltabilirsiniz l="".
Manatwork

@ manatwork Bu temiz. Bahşiş için teşekkürler.
Blab,

2

Ruby, 59 49 48 43 bayt

Şimdi rantsız, daha kısa ve hafıza sızıntısı olmadan.

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

Dennis sayesinde bazı parantezlerden ve alandan kurtularak 5 bayt kurtardı



1

Röda , 49 47 bayt

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

Çevrimiçi deneyin!

Bu, karakterleri giriş akışından okuyan ve "merhaba" bulununcaya kadar çıkaran isimsiz bir fonksiyondur. aSon karakterleri izlemek için diziyi kullanır .

STDERR'ye bir miktar hurda çıkardı, ama izin verildiğini anladım .

Açıklama:

{
    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 belgeleri nerede?
ckjbgames

@ckjbgames İşte. Github'da kendi şubesinde bulunan en yeni 0.12 sürümünü kullanıyorum.
fergusq

1

Java 7, 122 118 124 123 150 141 bayt

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

Şimdi akışın sonuna gelindiğinde durur. Şimdi, hafıza yetersiz kalmadan sonsuz girişi işler.


Bahse girerim bu sonsuz girişi kaldıramaz.
Titus

@Titus ... Sabit
Poke

writeKullanıldığını görmeden indirdim print. Olumsuz oyumu geri alamıyorum, bunun için üzgünüm :(
Olivier Grégoire

1

Ruby, 51 bayt

x="";$><<x[-1]while/hello./!~x=x[/.{0,5}$/]+$<.getc
  • Newlines beklemiyor
  • Sonsuz girişle çalışır

1

AHK, 116 bytes

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

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


1

Mathematica, 107 bytes

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

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


1

brainfuck, 281 bytes

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

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

Explained

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

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

Try it online!


I was gonna do it like this but then I realized that this outputs the zero byte infinitly for input that doesn't contain "hello": tio.run/nexus/…
KarlKastor

This also fails on ahehellob.
Mitch Schwartz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.