Ktoś wysłał mi to i stwierdził, że to witaj świat w Brainfuck (i mam nadzieję, że tak ...)
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
Znam podstawy, że działa poprzez przesuwanie wskaźnika oraz zwiększanie i zmniejszanie wartości ...
Jednak nadal chcę wiedzieć, jak to właściwie działa? Jak w pierwszej kolejności drukuje cokolwiek na ekranie? Jak koduje tekst? W ogóle nie rozumiem ...
brainfuck
esoteric-languages
ścigacz
źródło
źródło
Odpowiedzi:
1. Podstawy
Aby zrozumieć Brainfuck, musisz wyobrazić sobie nieskończoną liczbę komórek inicjowanych przez
0
każdą z nich.Kiedy program „brainfuck” zaczyna wskazywać na dowolną komórkę.
Jeśli przesuniesz wskaźnik w prawo
>
, przesuniesz wskaźnik z komórki X do komórki X + 1Jeśli zwiększysz wartość komórki
+
, otrzymasz:Jeśli ponownie zwiększysz wartość komórki
+
, otrzymasz:Jeśli zmniejszysz wartość komórki
-
, otrzymasz:Jeśli przesuniesz wskaźnik w lewo
<
, przesuniesz wskaźnik z komórki X do komórki X-12. Wejście
Aby przeczytać znak, użyj przecinka
,
. Co robi to: czyta znak ze standardowego wejścia i zapisuje jego dziesiętny kod ASCII do właściwej komórki.Spójrz na tabelę ASCII . Na przykład kod dziesiętny
!
to33
, podczas gdya
jest97
.Cóż, wyobraźmy sobie, że pamięć programu BF wygląda następująco:
Zakładając, że standardowe wejście oznacza
a
, jeśli używasz,
operatora przecinka , to, co robi BF, to odczyta
dziesiętny kod ASCII97
do pamięci:Na ogół chcesz tak myśleć, ale prawda jest nieco bardziej złożona. Prawda jest taka, że BF nie czyta znaku, ale bajt (cokolwiek to jest). Pokażę Ci przykład:
W systemie linux
wydruki:
co jest specyficznym polskim charakterem. Ten znak nie jest kodowany za pomocą kodowania ASCII. W tym przypadku jest to kodowanie UTF-8, więc zajmowało więcej niż jeden bajt w pamięci komputera. Możemy to udowodnić, wykonując zrzut szesnastkowy:
który pokazuje:
Zera są przesunięte.
82
jest pierwszym ic5
jest drugim bajtem reprezentującymł
(w celu ich odczytania).|..|
jest reprezentacją graficzną, która w tym przypadku nie jest możliwa.Cóż, jeśli podasz
ł
jako dane wejściowe do programu BF, który czyta pojedynczy bajt, pamięć programu będzie wyglądać następująco:Dlaczego
197
? Cóż,197
dziesiętne toc5
szesnastkowe. Wydaje się znajomy? Oczywiście. To pierwszy bajtł
!3. Wyjście
Aby wydrukować znak, użyj kropki.
.
Co to robi: Zakładając, że traktujemy rzeczywistą wartość komórki jak dziesiętny kod ASCII, wypisz odpowiedni znak na standardowe wyjście.Cóż, wyobraźmy sobie, że pamięć programu BF wygląda następująco:
Jeśli teraz używasz operatora kropki (.), BF wypisuje:
Ponieważ
a
kod dziesiętny w ASCII to97
.Na przykład program BF taki jak ten (97 plus 2 kropki):
Zwiększy wartość wskazywanej komórki do 97 i wydrukuje ją 2 razy.
4. Pętle
W pętli BF składa się z początku
[
i końca pętli]
. Możesz pomyśleć, że to tak, jak w C / C ++, gdzie warunek jest rzeczywistą wartością komórki.Spójrz na program BF poniżej:
++
zwiększa dwukrotnie rzeczywistą wartość komórki:I
[]
jest takwhile(2) {}
, więc to nieskończona pętla.Powiedzmy, że nie chcemy, aby ta pętla była nieskończona. Możemy na przykład:
Tak więc za każdym razem, gdy pętla się zapętla, zmniejsza rzeczywistą wartość komórki. Gdy aktualna wartość komórki się
0
kończy:Rozważmy jeszcze jeden przykład skończonej pętli:
Ten przykład pokazuje, że nie kończyliśmy pętli w komórce, w której pętla się rozpoczęła:
Jednak dobrą praktyką jest zakończenie tam, gdzie zaczęliśmy. Czemu ? Ponieważ jeśli pętla kończy inną komórkę, to nie możemy założyć, gdzie będzie wskaźnik komórki. Szczerze mówiąc, ta praktyka sprawia, że mózg jest mniejszy.
źródło
Wikipedia ma skomentowaną wersję kodu.
Aby odpowiedzieć na twoje pytania, znaki
,
i.
są używane do I / O. Tekst to ASCII.Artykuł w Wikipedii jest również bardziej szczegółowy.
źródło
,
i.
jest używany do operacji we / wy, podobnie jak C drukuje przy użyciuputchar
. Jest to szczegół implementacji obsługiwany przez kompilator.Aby odpowiedzieć na pytanie, skąd wie, co wydrukować, dodałem obliczenie wartości ASCII po prawej stronie kodu, w którym odbywa się drukowanie:
źródło
Brainfuck to samo, co jego nazwa. Używa tylko 8 znaków,
> [ . ] , - +
co czyni go najszybszym do nauczenia się językiem programowania, ale najtrudniejszym do zaimplementowania i zrozumienia. … .I sprawia, że w końcu skończysz z pieprzeniem mózgu.Przechowuje wartości w tablicy: [72] [101] [108] [111]
let, początkowo wskaźnik wskazujący na komórkę 1 tablicy:
>
przesuń wskaźnik w prawo o 1<
przesuń wskaźnik w lewo o 1+
zwiększ wartość komórki o 1-
zwiększ wartość elementu o 1.
wypisuje wartość bieżącej komórki.,
weź dane wejściowe do bieżącej komórki.[ ]
pętla, +++ [-] licznik 3 zliczeń bcz ma przed sobą 3 ′ + 'i - zmniejsza licznik zmiennej o 1 wartość.wartości przechowywane w komórkach są wartościami ascii:
więc odwołując się do powyższej tablicy: [72] [101] [108] [108] [111] jeśli dopasujesz wartości ascii, zobaczysz, że jest to Hello writtern
Gratulacje!nauczyłeś się składni BF
——- Coś więcej ———
pozwól nam stworzyć nasz pierwszy program czyli Hello World , po którym będziesz mógł napisać swoje imię w tym języku.
rozpadać się na kawałki:
Tworzy tablicę 4 komórek (liczba>) i ustawia licznik na 10, na przykład: —- pseudokod—-
ponieważ wartość licznika jest przechowywana w komórce 0 i> przenosi się do komórki 1 aktualizuje swoją wartość o + 7> przenosi do komórki 2 z przyrostem o 10 do poprzedniej wartości i tak dalej….
<<<
powrócić do komórki 0 i zmniejszyć jej wartość o 1stąd po zakończeniu pętli mamy tablicę: [70,100,30,10]
przechodzi do pierwszego elementu i zwiększa jego wartość o 2 (dwa „+”), a następnie drukuje znak („.”) z tą wartością ascii. czyli na przykład w pythonie: chr (70 + 2) # wypisuje 'H'
przechodzi do drugiej komórki z przyrostem 1 do wartości 100 + 1 i drukuje ('.') jego wartość tj. chr (101) chr (101) # drukuje 'e' teraz nie ma> lub <w następnym kawałku, więc przyjmuje aktualną wartość najnowszego elementu i tylko do niego przyrost
ostatni element = 101, więc 101 + 7 i wypisuje go dwukrotnie (ponieważ są dwa '..') chr (108) #prints l dwa razy może być użyty jako
——— Gdzie jest używany?——-
Jest to tylko żartobliwy język stworzony, aby rzucić wyzwanie programistom i nie jest używany praktycznie nigdzie.
źródło
Wszystkie odpowiedzi są wyczerpujące, ale brakuje im jednego drobnego szczegółu: drukowania. Tworząc swojego mózgowego tłumacza, bierzesz również pod uwagę postać
.
, tak właściwie wygląda wypowiedź drukarska w brainfuck. Więc to, co powinien zrobić twój mózgowy tłumacz, to kiedy napotka.
znak, wypisuje aktualnie wskazany bajt.Przykład:
załóżmy, że masz ->
char *ptr = [0] [0] [0] [97] [0]
... jeśli to jest fikcyjne stwierdzenie:>>>.
twój wskaźnik powinien zostać przesunięty o 3 spacje w prawą stronę na:,[97]
więc teraz*ptr = 97
, po wykonaniu tej czynności, twój tłumacz napotka a.
, powinien wtedy wywołaćlub dowolna równoważna instrukcja drukowania, aby wydrukować aktualnie wskazany bajt, który ma wartość 97, a litera
a
zostanie następnie wydrukowana nastd_output
.źródło
Myślę, że pytasz, skąd Brainfuck wie, co zrobić z całym kodem. Istnieje parser napisany w języku wyższego poziomu, takim jak Python, aby zinterpretować, co oznacza kropka lub co oznacza znak dodania w kodzie.
Więc parser odczyta twój kod linia po linii i powie ok, jest symbol>, więc muszę przesunąć lokalizację pamięci, kod jest po prostu, jeśli (zawartość w tej lokalizacji pamięci) ==>, memlocation = + memlocation, czyli napisane w języku wyższego poziomu, podobnie jeśli (treść w lokacji pamięci) == ".", a następnie wypisz (zawartość komórki pamięci).
Mam nadzieję, że to wyjaśnia sprawę. tc
źródło