Pozwól, że opowiem ci o prostym systemie liczbowym. (które zrobiłem właśnie dla tego wyzwania)
System ten zawiera funkcje ()
, []
, {}
, i <>
.
1. ()
Gdy ()
nie podano żadnych argumentów, ocenia się na 0
.
Gdy ()
podany jest jeden lub więcej argumentów, następuje ich suma.
2) []
Gdy []
nie podano żadnych argumentów, ocenia się na -1
.
Gdy []
podano jeden lub więcej argumentów, następuje ocena pierwszego argumentu minus suma pozostałych argumentów.
3) {}
Gdy {}
nie podano żadnych argumentów, ocenia się na 1
.
Gdy {}
podano jeden lub więcej argumentów, ocenia się na iloczyn tych argumentów.
4 <>
Gdy <>
nie podano żadnych argumentów, ocenia się na 1
.
Gdy <>
podany jest jeden lub więcej argumentów, następuje ocena liczby całkowitej pierwszego argumentu podzielonej przez iloczyn pozostałych argumentów.
Twoje zadanie
Biorąc pod uwagę ciąg znaków, który zawiera prawidłową liczbę (co oznacza, że nawiasy są zrównoważone, bez dzielenia przez 0 itd.) W tym prostym systemie liczbowym, wypisz jego wartość.
Przypadki testowe
() -> 0
(()()) -> 0
([][]) -> -2
({}<>) -> 2
({}[]) -> 0
[] -> -1
[[][]] -> 0
[()<>] -> -1
{()} -> 0
{([]<>)} -> 0
Pamiętaj, to jest kodowanie w golfa , więc wygrywa kod z najmniejszą liczbą bajtów.
źródło
5/3
,5/-3
,-5/3
i-5/-3
?Odpowiedzi:
Dyalog APL , 94 bajty
o←{(⊂(1⊃⍵),⍺⍺⊃⍵),2↓⍵}⋄u←{(⊃⍵,⍺⍺1)⍺⍺⍵⍵/1↓⍵}⋄⍎⍕'+/o' '-u+o' '×/o' '÷u×o' '(⊂⍬),'[')]}>'⍳⌽⍞],'⊂⍬'
wykorzystuje
⎕IO←0
zastępuje
)]}>
wywołaniem funkcji, która pobiera stos, stosuje operację na górnej ramce, usuwa ją i dołącza wynik do następnej ramki (o
do tego celu stosuje się operator monadyczny ; operator diadycznyu
obsługuje bardziej skomplikowane przypadki-
i÷
)zastępuje
([{<
kodem, który dodaje ramkę do stosu ((⊂⍬),
)wykonuje wynikowe wyrażenie (odwrócone, aby dopasować kolejność wykonywania APL) z początkowym stosem jednej pustej ramki (
⊂⍬
)źródło
Haskell,
357306277251228224188185180 bajtówParser oparty na tokenach z jawnym stosem.
(%)
pobiera stos tokenów i znak i albo wypycha (kod operacji, numer domyślny) lub (0, liczba)({[<
, albo wyskakuje z najwyższych liczb i jednego kodu operacji i przesuwa odpowiedź na)}]>
. Kody są kodowane przez hack wyliczenia ascii.Wyrazy uznania dla @ChristianSievers za wspaniałą odpowiedź , od której pożyczyłem kilka pomysłów.
One-liner!
Teraz z mniejszą obsługą błędów! Stosowanie:
Dzięki @ChristianSievers za oszczędność 14 + 3 bajtów!
Dzięki @Zgarb za uratowanie niektórych + 4 bajtów!
źródło
(0,[0,0,1,-1,1]!!o):s
w piątej linii?!
, abyś mógł zrobić(s:_)!_=d s
tak jak w drugim przypadku. Myślę też, że mógłbyś związaćx<-p$d<$>init a,y<-d$last a
w ostatnim przypadku%
.%
możesz upuścić pareny wokół_:b
ig c
.Python 2,
292265248235223206204 bajtówZamienia wszystkie nawiasy na lambda, które robi to, co robi nawias, a następnie ocenia wynikowy kod Python. Wymaga danych wejściowych otoczonych cudzysłowami, np
'[<><>([]{})]'
.Ten program przechowuje typ nawiasu jako pierwszy znak w każdym ciągu w
for
, a wszystko po słowie kluczowymlambda
jako resztę. Następnie używa pierwszego znaku do zastąpienia; reszta jest połączona w lambda(lambda*x:sum(x))()
.Wypróbuj na Ideone!
źródło
PEG.js (ES6) , 132 bajty
Powinien zostać teraz naprawiony.
Wyjaśnienie
Bardziej czytelny:
PEG.js to rozszerzona wersja Javascript stworzona specjalnie do analizy. Jest BARDZO ścisły, dlatego musiałem go użyć
var
. Ponadto wydaje się, że występuje błąd z nawiasami wewnątrz ciągów, co znacznie rozszerzyło kod.Na początek definiujemy regułę
x
pasującą do dowolnego nawiasu,a
który może zawierać lub nie zawierać wielu wyrażeń pasujących do regułyx
.Dla każdego dopasowania do reguły
x
, wypychamy 0 do tablicy dopasowania wewnętrznego,b
jeślib
długość wynosi 1.Jeśli
b
długość> 0, to znajdujemy indeksa
w([<
i otrzymujemy znak z+-/
tego indeksu. Jeśli wynik jest niezdefiniowany (to znaczy, żea
był{
), to przekształcamy wynik w*
. Na koniec zajmujemy się spacją i łączymy sięb
z wynikiem.Jeśli
b
długość = 0, to znajdujemy indeksa
w([<
i otrzymujemy znak z10
tego indeksu. Jeśli wynik jest niezdefiniowany (co oznacza, żea
był{
lub<
), wówczas zamieniamy wynik na 2. Wreszcie, po prostu zmniejszamy.Na koniec możemy po prostu ocenić wyrażenie i podać wynik.
źródło
Perl, 113 + 2 = 115 bajtów
Uruchom z
-lp
(kara 2 bajty).Bardziej czytelne (uwaga: ta „bardziej czytelna wersja” tak naprawdę nie działa, ponieważ umieszczam komentarze w miejscach, w których nie są dozwolone składniowo):
Podstawową ideą jest to, że przekształcamy dane wejściowe podobne
[()<>]
do programu Perlb(a(0),d(0),0),
poprzez przetwarzanie tekstu; Perl jest w porządku z przecinkiem. Wcześniej, mamy zdefiniowane funkcjea
,b
,c
,d
aby mieć taki sam skutek jak()
,[]
,{}
,<>
konstrukcje z języka jesteśmy wykonawczego; każdy z nich ignoruje swój ostatni argument (0 na końcu), który jest zawarty w celu zapewnienia, że wszystkie dane wejściowe są poprawnie analizowane, i działa z wykorzystaniem implementacji powszechnie występującej w programowaniu funkcjonalnym, w którym głowa i ogon są przetwarzane osobno. Ponieważb(e,f,g,0)
środkie-f-g
, tj. Traktuje swój pierwszy argument specjalnie, podczas gdya
jego argumenty traktuje symetrycznie (a(e,f,g,0)
środkie+f+g
), implementujemya
rekurencyjnie ib
za pośrednictwem połączeńa
.c
id
mają podobny związek. Wszystkie cztery z tych funkcji są bardzo podobne, więc generujemy je w czasie wykonywania, a nie wdrażamy osobno; przechowujemy szablon, który dotyczy wszystkich czterech funkcji w ciągu, a następnie generujemy funkcje, zastępując znaki w szablonie.Ponieważ Perl
/
wykonuje dzielenie zmiennoprzecinkowe, to również implementuje{}
. Zakładam, że albo nie jest to problem sam w sobie, albo-Minteger
(wybór wariantu językowego, w którym wszystkie operacje arytmetyczne są operacjami liczb całkowitych) jest bezpłatny, ponieważ w przeciwnym razie musiałbym spędzić dodatkowe bajty na pisaniu podziału na liczby całkowite w Perlu, wydaje się, że nie na tym polega problem. (Myślę, że trzeba wydać cztery bajty zmienia(shift)
sięint+(shift)
;. Nie testowałem tego)źródło
Oktawa,
215206198 bajtówspróbuj online
źródło
PHP,
315300285258250244 bajtówzamienia podwyrażenia na podkreślenie + wartość; pętla pęka, gdy iteracja nie zastępuje.
19 lat od pierwszego spotkania z C, 17 lat w PHP;
to pierwszy raz, który
strtok
ma sens ... pomaga zaoszczędzić 24 bajty!awaria
źródło
ES6 (JavaScript),
250,171,154,149, 147 bajtówCzysta wersja Javascript.
„Metaprogramowanie” (jak większość innych odpowiedzi tutaj) konwertuje tekst programu wejściowego na odpowiedni program Javascript, stosując do niego szereg bezpośrednich podstawień tekstu (tj. Zachowując aktualną strukturę programu).
Prawdopodobnie można dalej grać w golfa.
AKTUALIZACJA (v2.1)
AKTUALIZACJA (v2)
Właśnie zdałem sobie sprawę, że oczekujące przecinki w tablicach ES są całkowicie poprawne, więc cały kod normalizacji przecinków można usunąć. Postępował również zgodnie ze świetną radą @Titus, dotyczącą optymalizacji wyszukiwania alfabetu.
AKTUALIZACJA (v1)
Usunięto zduplikowany alias „zamień”.
AKTUALIZACJA (v1)
Użyj lepszego alfabetu: () => 1+ [] => 0 {} => 2 * <> => 2 / (każdy znak może być bezpośrednio ponownie użyty jako wartość lub operator)
Zamienione zmniejsz () na replace () (odwzorowanie alfabetu)
Scalona stała obróbka nachylenia, otwierania i zamykania zamka w jeden krok
Gra w golfa (v2.1)
Gra w golfa (v1)
Gra w golfa (v0)
Wyjaśnione (v0)
Test
Wyjście testowe
źródło
s.reduce((r,c)=>r+="abcdefgh"["()[]{}<>".indexOf(c)],'')
(-5)? jeśli tak, możesz zapamiętaćindexOf
zmienną i pobrać operator z literału trzeciego ciągu.Haskell,
184 179 172 161 160 159 151 148145 bajtówRekurencyjne zejście, nawlekanie danych wejściowych, ponieważ Haskell. Jak zwykle ostatni wiersz nie jest definicją, ale określa funkcję, która rozwiązuje problem. Aby przetestować, umieść wiersze oprócz ostatniego w pliku, załaduj go i zrób coś takiego:
Podziękowania dla @Zgarb za inspirację i wiele szczegółowych wskazówek oraz @Angs za inspirację z jego rozwiązania i dalszych wskazówek.
Nie określono, jak powinien zachowywać się podział z ujemnymi liczbami całkowitymi. W każdym razie wielokrotne używanie
div
wydaje się nieprawidłowe, ponieważ nie jest to to samo, codiv
jednorazowe użycie z iloczynem pozostałych wartości. Teraz używamquot
, otrzymuję te same wyniki dla<{}([][])[]>
i<{}{([][])[]}>
.Aby uzyskać ładny, prawie czytelny kod, zobacz pierwszą wersję. Wersje pośrednie zawierają wszelkiego rodzaju ładny i onieśmielający kod i pomagają zrozumieć tę wersję.
źródło
(!)=(,)
i używając!
zamiast jawnych krotek.m x
id x
jako1#x
i0#x
, możesz scalić przypadkim[x]
id[x]
do jednego, który moim zdaniem zbyt zapisuje niektóre bajty.!
lewa się nie opłaca. Twoja druga sugestia jest zła, pojawia się mój prawie czytelny kod ... Sprytnie!s%(c:i)=(s?c,i)
is?')'=sum s
itp. Będą znacznie krótsze, ponieważ możesz pozbyć się powtarzających sięi
liter. ..Nie czekaj, to prawdopodobnie nie zadziała z powodus%(_:i)
sprawy.elem
idiv
to powinno zaoszczędzić trochę więcej bajtów.JavaScript (ES6), nie
eval
, 156 bajtówObjaśnienie: Wyrażenie regularne znajduje pierwszy nieprzetworzony nawias zamykający i dopasowuje (przypuszczalnie) odpowiedni nawias otwierający i wszelkie argumenty pomiędzy nimi. Argumenty są dzielone i redukowane zgodnie z operacją (niestety „(” i „[” nie są optymalną parą dla
+
i-
), lub jeśli nie ma argumentów, wówczas obliczana jest odpowiednia wartość (ponownie dopasowanie znaków do wartości jest nieoptymalne z mojego punktu widzenia). Następnie wynik zastępuje się spacją wiodącą, aby oddzielić go od innych wyników. Następnie funkcja wywołuje się rekurencyjnie, dopóki nie będzie więcej zmian do wprowadzenia, w którym to przypadku zwraca wartość wynikową. Przykład:źródło