Acc !! , 129 bajtów
Nieźle jak na dość gadatliwą Tarpit Turinga ...
N
Count i while _%128-9 {
Count x while _/128%2 {
Write 40
_+128
}
Write _%128
_+128-_%128+N
}
Count j while _/256-j {
Write 41
}
(Tak, wszystkie te białe znaki są obowiązkowe).
Uwaga: z powodu ograniczeń wejściowych Acc !! , nie można odczytać dowolnego ciągu znaków bez ogranicznika końcowego. Dlatego ten program oczekuje, że wejście (standardowe wejście) jest ciągiem, po którym następuje znak tabulacji.
Acc !! ?
To język, który stworzyłem, który wydaje się być bezużyteczny . Jedynym typem danych są liczby całkowite, jedyną konstrukcją przepływu sterującego jest Count x while y
pętla, a jedynym sposobem przechowywania danych jest pojedynczy akumulator _
. Dane wejściowe i wyjściowe są wykonywane po jednym znaku za pomocą wartości specjalnej N
i Write
instrukcji. Pomimo tych ograniczeń jestem pewien, że Acc !! jest ukończony przez Turinga.
Wyjaśnienie
Podstawowa strategia w Acc !! programowanie polega na użyciu %
dzielenia mod i liczb całkowitych, /
aby koncepcyjnie podzielić akumulator, umożliwiając mu przechowywanie wielu wartości jednocześnie. W tym programie wykorzystujemy trzy takie sekcje: siedem bitów najniższego rzędu ( _%128
) przechowuje kod ASCII z wejścia; następny bit ( _/128%2
) przechowuje wartość flagi; a pozostałe bity ( _/256
) policzą liczbę potrzebnych skróconych części.
Wejście w Acc !! pochodzi ze specjalnej wartości N
, która odczytuje pojedynczy znak i ocenia na kod ASCII. Każda instrukcja, która składa się wyłącznie z wyrażenia, przypisuje wynik tego wyrażenia do akumulatora. Zaczynamy więc od zapisania kodu pierwszego znaku w akumulatorze.
_%128
zapisze ostatnio przeczytaną postać. Tak więc pierwsza pętla działa, gdy _%128-9
jest niezerowa - to znaczy, dopóki obecny znak nie będzie tabulatorem.
Wewnątrz pętli chcemy drukować, (
chyba że wykonamy pierwszą iterację. Ponieważ Acc !! nie ma instrukcji if, musimy używać pętli dla warunkowych. Używamy bitu 128 akumulatora _/128%2
, jako wartości flagi. Przy pierwszym przejściu jedyną rzeczą w akumulatorze jest wartość ASCII <128, więc flaga ma wartość 0, a pętla jest pomijana. Przy każdym kolejnym przejściu upewnimy się, że flaga ma wartość 1.
Wewnątrz Count x
pętli (ilekroć flaga ma wartość 1), piszemy otwarty paren (ASCII 40
) i dodajemy 128 do akumulatora, ustawiając w ten sposób flagę na 0 i wychodząc z pętli. Zdarza się to również, aby zwiększyć wartość _/256
, której użyjemy jako naszą sumę przybliżeń do wygenerowania.
Bez względu na wartość flagi piszemy najnowszy znak wejściowy, który jest po prostu _%128
.
Następne przypisanie ( _+128-_%128+N
) robi dwie rzeczy. Po pierwsze, dodając 128, ustawia flagę po raz kolejny przez pętlę. Po drugie, wyzerowuje _%128
miejsce, odczytuje inną postać i zapisuje ją tam. Potem zapętlamy.
Kiedy Count i
pętla kończy pracę, właśnie odczytaliśmy znak tabulacji, a wartość akumulatora rozkłada się w następujący sposób:
_%128
: 9
(znak tabulacji)
_/128%2
: 1
(flaga)
_/256
: liczba odczytanych znaków minus 1
(Minus 1 wynika z tego, że dodajemy 128 do akumulatora tylko raz podczas pierwszego przejścia przez główną pętlę.) Wszystko, czego teraz potrzebujemy, to zbliżenia. Count j while _/256-j
pętle _/256
razy, za 41
każdym razem pisząc ścisły paren (ASCII ). Voila!