Wprowadzenie
Forte to bardzo osobliwy ezoteryczny język oparty na koncepcji modyfikacji wartości liczb. W Forte liczby nie są stałymi, ale zmiennymi, możesz użyć LET
instrukcji, aby przypisać im nowe wartości.
Na przykład po wykonaniu LET 2=4-1
od teraz 2
przyjmuje wartość 3
, co oznacza, że ilekroć wartość 2
pojawia się w wyrażeniu, zamiast tego jest „zastępowana” przez 3
. Wyrażenie (1+1)*2
będzie teraz oceniać na 9
.
Ta instrukcja w Forte służy zarówno do przechowywania informacji, jak i do kontroli przepływu (linie są ponumerowane, a zmieniając wartość ich liczb można określić kolejność ich wykonywania). W tym wyzwaniu nie zajmiemy się tym drugim aspektem.
Wyzwanie
Musisz napisać interpreter dla uproszczonego podzbioru LET
wyrażeń Forte .
Otrzymasz jako dane wejściowe serię wierszy następujących po tej gramatyce:
<line>::= <number>=<expression>
<expression>::= <number>|<expression>+<number>
Uwaga: ta gramatyka jest nieprawidłowa, ponieważ nie ma w niej numerów linii, LET i nawiasów (które są zawsze obowiązkowe)
Oznacza to, że będziesz musiał poradzić sobie tylko z obliczaniem sum i przypisywaniem wartości liczbom. W nawiasach wejściowych nie będzie nawiasów i każde wyrażenie będzie musiało być oceniane od lewej do prawej: strzeż się, że na częściowe wyniki wpływają redefinicje!
Liczby zawsze będą liczbami całkowitymi nieujemnymi, aż do limitu rodzimych liczb całkowitych twojego języka (lub 2 ^ 32, w zależności od tego, która wartość jest wyższa).
Dla każdego wiersza powinieneś wypisać wynik wyrażenia i przypisać ten wynik (ewentualnie ponownie przypisanej) wartości pierwszej liczby, co wpłynie na sposób interpretacji kolejnych wierszy.
To jest code-golf , wygrywa najkrótszy kod (w bajtach)!
Inne zasady
- Format wejściowy jest elastyczny, możesz na przykład wziąć pojedynczy ciąg znaków z nowymi wierszami, listę ciągów, listę list liczb ... To samo dotyczy wyniku, o ile jest jasne, jaki jest wynik każdego wyrażenia w wejście.
- Możesz przesłać funkcję, pełny program lub rozwiązanie do uruchomienia w środowisku REPL, wywołując je raz dla każdej linii.
- Standardowe luki są zabronione, w szczególności nie można wywołać zewnętrznego interpretera Forte w kodzie.
Przykłady
Wszystkie są częścią tego samego wejścia. Po każdej linii wyświetlana jest oczekiwana wydajność w stosunku do tej linii, czasami z komentarzem wskazującym odpowiednie zmiany przypisania (nie jest częścią wymaganego wyniku).
5=4
4
6=5
4 # 5 -> 4
7=1+2+5
7
7=5+2+1
4 # Order of operations matters! 5+2 -> 4+2 -> 6 -> 4
18=5+6+7
12
5=3
3 # Remember: 5 -> 4
10=6+4
3 # 6 -> 4 -> 3, 3+3 = 6 -> 3
0
jest poprawny numer?0
jest poprawny („Liczby zawsze będą nieujemnymi liczbami całkowitymi”)Odpowiedzi:
Galaretka , 28 bajtów
Wypróbuj online!
Jest to jeden z niewielu programów Jelly, w których bardziej efektywne jest pobieranie danych ze standardowego wejścia. Jest to pełny program (pisanie funkcji byłoby krótsze, ale jest zabronione przez reguły PPCG, ponieważ nie działałoby poprawnie za drugim razem). Format wejściowy wygląda następująco:
Wyjaśnienie
Funkcja pomocnicza
1Ŀ
(przetłumacz liczbę całkowitą na jej wartość)Raczej wygodnie, ta funkcja pomocnicza będzie działać poprawnie albo na pojedynczej wartości, albo na liście wartości, zależnie od sposobu
y
zdefiniowania. Jeśli dla jednej wartości podano więcej niż jedno mapowanie, pierwsze mapowanie pobieramy z tabeli. Tabela mapowania jest przechowywana w rejestrze (który jest w zasadzie tylko zmienną; Galaretka ma tylko jedną zmienną).Funkcja pomocnicza
2Ŀ
(oceń jedną instrukcję LET)Tak naprawdę nie chcemy tutaj wartości zwrotnej; po prostu uruchamiamy to ze względu na jego skutki uboczne (aktualizacja rejestru i wysyłanie przypisanej wartości). Funkcje galaretki zawsze zwracają jednak wartość, więc po prostu pozwalamy na zwrócenie tabeli mapowania, ponieważ jest to najkrótsza.
Główny program
Zwykle
⁸
dałby nam pierwszy argument wiersza poleceń, gdy jest uruchomiony w tym kontekście, ale nie ma go (pobieramy dane ze standardowego wejścia), więc działa w trybie alternatywnym, który daje nam ciąg zerowy. Konieczność zainicjowania rejestru (z domyślnej wartości0
, która ulega awariiy
) oznacza, że nie możemy domyślnie wspomnieć o danych wejściowych użytkownika, co oznacza, że tak tanie jest pobranie go ze standardowego wejścia (Ɠ
), jak byłoby pobranie go z argument wiersza poleceń (³
lub⁸
) i możliwość dostępu do alternatywnego użycia⁸
oznacza, że nietypowa (jak na galaretkę) forma wprowadzania danych jest w rzeczywistości o bajt krótsza.Możliwe, że można to poprawić. Nadal nie zorientowałem się, dlaczego druga linia powinna powiedzieć,
⁸Ǥ;
a nie tylko;@Ç
- obie powinny być równoważne, o ile rozumiem Jelly, biorąc pod uwagę brak użyciaµ
/ð
/ø
- ale ta ostatnia z jakiegoś powodu ulega awarii. Podobnie, istnieje wiele innych sposobów przestawienia programu bez utraty bajtów, więc możliwe, że przegapiłem sposób na skrócenie rzeczy.Nawiasem mówiąc, zmiana
ḷ
w ostatnim wierszu;
daje interesujące spojrzenie na wewnętrzne działanie programu, ponieważ wyświetli on „historię rejestru”, która domyślnie jest generowana przez zwracane wartości2Ḷ
.źródło
Perl 5 , 92 bajtów
90 bajtów kodu +
-pl
flagi.Wypróbuj online!
Używam hashtable
%h
do przechowywania mapowania między liczbami.Funkcja (
sub
)f
zwraca liczbę, do której odwzorowuje dane wejściowe (lub dane wejściowe, jeśli nie jest odwzorowana):$h{$a=pop}
pobiera liczbę, do której odwzorowują dane wejściowe. Jeśli nie, dzięki temu//$a
wartością($b=$h{$a=pop}//$a)
jest input ($a
). Upewniamy się, że te wartości nie są danymi wejściowymi, aby nie zapętlały się nieskończenie (!=$a
). Następnie rekurencyjnie wywołujemyf
lub zwracamy dane wejściowe.Główny program składa się z dwóch etapów:
-
s%(\d+)\+(\d+)%f($1)+f$2%e&&redo
ocenia pierwszy dodatek po prawej stronie, podczas gdy nadal istnieje dodatek: zastępujex+y
go wynik ocenyf(x)+f(y)
.-
/=/;$_=$h{f$`}=f$'
czy zadanie:/=/
umożliwia dostęp do lewej$`
i prawej strony$'
, a następnie$h{f$`}=f$'
wykonuje przypisanie. I przypisujemy to również do$_
tego, że jest domyślnie drukowane po każdej linii.źródło
JavaScript (Node.js) , 81 bajtów
Wypróbuj online!
Odbiera dane wejściowe, wywołując f z wartością do przypisania, a następnie wywołując wynik z tablicą wartości do dodania razem. (tj.
f(5)([4])
) Powtórz dla wielu linii.v
jest używany jako funkcja do obliczania rzeczywistej bieżącej wartości liczby, a także jako obiekt do przechowywania rzeczywistych wartości. Najpierwv[x]=v[x]||x
zapewnia, żev[x]
jest zdefiniowany.v[x]-x
przeprowadza porównanie w celu ustalenia, czy jest to rzeczywista liczba, czy nie. Jeśli liczba nie odwzorowuje się sama,v(v[x])
rekurencyjnie próbuje ponownie, w przeciwnym razie powróćx
.f
wykonuje obliczenia i przypisanie, curry, aby zapisać jeden bajt, gdzie drugie wywołanie zwraca obliczoną wartość.źródło
Haskell ,
116 113 108106 bajtówWypróbuj online! Każde równanie
4=3+1+5
jest zapisywane jako krotka(4,[3,1,5])
. Anonimowa funkcja(id?)
pobiera listę takich krotek i zwraca listę wszystkich wyników pośrednich.#
to funkcja znajdująca punkt stały danej funkcjie
i wartość początkowąx
.Funkcja
?
przyjmuje funkcję ocenye
i rekurencyjnie rozwiązuje każde równanie.foldl1(\a b->e#(e#a+e#b))s
ocenia prawą stronę równania i zapisuje wynikm
, np. dla4=3+1+5
obliczeńeval(eval(eval 3 + eval 1) + eval 5)
, gdzie każdaeval
jest zastosowaniem punktu stałegoe
. Następnie funkcja eval jest modyfikowana w celu uwzględnienia nowego przypisanian
:(\x->last$m:[e#x|x/=e#n])
które jest takie samo jak\x -> if x == eval n then m else eval x
.Funkcja oceny wstępnej
id
odwzorowuje każdą liczbę całkowitą na siebie.Dzięki Ørjan Johansen za krótszą funkcję punktu stałego, oszczędzającą 2 bajty!
źródło
last.
(#)e=until((==)=<<e)e
lub(#)=until=<<((==)=<<)
jest krótszy.ok, 48 bajtów
Stosowanie:
f[5;1 2 3] / 5=1+2+3
Wypróbuj online!
Jeśli nie przeszkadza ci górny limit liczb, których możesz użyć, na przykład tylko przy użyciu liczb
0
przez998
, to wystarczą następujące ( 41 bajtów ± kilka w zależności od maksimum):Wyjaśnienie:
;
oddziela trzy definicje.a
jest słownikiem / mapą liczb. W pierwszym przypadku jest to rzeczywisty, pusty słownik[]
, w drugim przypadku jest to lista liczb0
do998
.s
jest funkcją, która wyszukuje „wynikowy” numer, gdy otrzyma liczbę./
Na koniec pomocą funkcji, które będzie stosować się do jego własnej produkcji, aż wyjście przestaje się zmieniać.Ostatni bit
f
oznacza, że:źródło
Python 3,
146132130 bajtów14 bajtów zapisanych dzięki @Dada
2 bajty zapisane dzięki @ mbomb007
Wypróbuj online!
Odbiera dane wejściowe w postaci krotek równań [
x = y + z + w
as(x, (y, z, w))
], dane wyjściowe przez generator.źródło
g
prawdopodobnie można by napisaćg=lambda x:d.get(x)and d[x]!=x and g(d[x])or x
. I myślę, że możesz użyć 1 spacji do wcięcia zamiast 2. To powinno doprowadzić cię do [132 bajtów] ( Wypróbuj online! ).