Jakie masz ogólne wskazówki na temat gry w golfa w DC ?
dc to narzędzie do kalkulacji dla systemu UNIX / Linux, które poprzedza język C. Jestem zainteresowany tym, jak skrócić moje programy DC (obliczenia?). Szukam pomysłów, które można zastosować do ogólnego golfa kodowego, które są co najmniej trochę specyficzne dla dc (np. Usunięcie komentarzy nie jest pomocną odpowiedzią)
Proszę zamieścić jedną wskazówkę na odpowiedź.
Odpowiedzi:
Instrukcje if-then-else
Załóżmy, że chcemy sprawdzić warunek
edytować:a==b
(pozwolića
ib
być przechowywany w odpowiednio nazwanych rejestrach).Niech
(foo)
będzie symbolem zastępczym w celu kondensacji:Jest całkiem pewny, że jest to najbardziej zwarta instrukcja if (dostępna również tutaj ).
źródło
[[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI f
to początek? Akcje dla tehn i innych są na stosie,I
makro „ f” zamienia je i jest warunkowo caled. wtedy górna część stosu zostanie wykonana, a nieużywane makro zostanie umieszczone w I, aby wyczyścić stos.2 4
są tylko przykładowymi danymi do porównania. Alternatywnie,[x]sI
część może zostać przeniesiony do porównania, jeśli uważane za bardziej czytelne:[[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI f
. Wf
przykładach po prostu pokaże, że stos jest potem czysty ...dc
i to była strona 1-ty gdzie widziałem OpenBSDdc
jestif-then-else
konstrukt. Myślę, że potrzebujemydc
pakietu wentylatora ze wszystkimi 3 wersjami dla wszystkich głównych systemów operacyjnych ... o :-) ... a mojaif-then-else
powyższa propozycja nie działa na oryginale,dc
ponieważ brakuje mur
polecenia ... :-([[(if)2Q]si(condition)i(else)]x
- zawinięciem całej rzeczy w makro, a częścią if wewnątrz innego makra wewnątrz tego, abyś mógł2Q
wydostać się z całości przed dotarciem do części else. Więc jeśli chcesz zrobić, jeśli 1 == 1, a następnie wydrukuj 1, a następnie wydrukuj 2 , byłoby to1[[1P2Q]si1=i2P]x
(niesprawdzone, ponieważ nie mam dostępu do dc tu i teraz. Byłem również pewien, że zrobiłem tę sztuczkę w odpowiedzi tutaj wcześniej ale nie mogłem go znaleźć)[/*else*/]sE[[/*then*/]sE]sIlalb=IlEx
vs[[/*then*/2Q]sIlalb=I/*else*/]x
- 6 bajtów różnicy. Wciąż nieprzetestowane: PMożesz zapisać dane wejściowe za pomocą
d
Używając
d
, który powiela ToS (góra stosu), możesz przesunąć wejście z drogi do późniejszego użycia, wciąż będąc w stanie z niego korzystać.źródło
Tablice
Chociaż są to bóle głowy dla początkujących,
dc
oferuje tablice. Działają w ten sposób:Jak zwykle pierwszy element ma indeks 0. Tablice mogą być przydatne podczas pracy z sekwencjami, jak w sekwencji SUDSI , szczególnie w połączeniu z licznikami. Tablice mogą zmniejszyć ilość przetasowań liczbowych, które musisz wykonać (oraz liczbę liczników i porównań), jeśli chcesz wybrać konkretny element bez niszczenia środowiska. Na przykład, jeśli chcesz przenieść stos liczb do tablicy, możesz napisać funkcję rekurencyjną, która używa
z
(głębokość stosu) lubz 1-
jako indeks, przechowuje element i sprawdza, czyz == 0
sam się zakończy.Pamiętaj o następujących kwestiach:
dc
rozbije się.źródło
dc
mogły zostać niedawno zaktualizowane, a zachowanie tablicy mogło ulec nieznacznej zmianie w związku z awarią. Nie mogę tego teraz potwierdzić, ale myślę, że ostatnio było inaczej w Linuksie.0 do n-tej potęgi zamiast warunków / makr
Czasami trzeba coś podobnego c trójargumentowy warunkowy:
Dobry sposób na poradzenie sobie z tym jest opisany w odpowiedzi @ Joe . Możemy jednak zrobić lepiej:
gdzie E to D - C.
Sprawdza to równość, podnosząc 0 do potęgi różnicy dwóch wartości. Daje to 1, jeśli jest równy, a 0 w przeciwnym razie. Reszta po prostu skaluje 1 lub 0 do wartości C lub D. Działa to, ponieważ
dc
daje 0 0 = 1 i 0 n = 0 dla n! = 1.źródło
Czasami konieczne jest odrzucenie liczby ze stosu. Jednym ze sposobów jest po prostu wstawienie go do nieużywanej zmiennej, tj
st
. Jednak w niektórych sytuacjach możesz umieścić go w kilku innych miejscach, np. W bazie danych wejściowych, gdy nie masz już danych numerycznych, lub w specyfikatorze dokładności, jeśli nie masz żadnych operacji do wykonania, w których precyzja miałaby znaczenie. W pierwszym przypadku użyji
. W tym drugim przypadku użyjk
.źródło
o
można go również użyć. A jeśli którakolwiek z tych rzeczy jest nieistotna, można ją wykorzystać jako pamięć, a także po prostu odrzucić odpowiednio -I
/K
/O
przywołać je i zapisać bajty nadsa
/la
itd. Prawidłowe wartości AFAIK:i
2-16;k
dowolna nieujemna liczba całkowita;o
dowolna liczba całkowita większa niż 1.Obliczanie długości:
Z
,X
, iz
Z
wyskakuje ToS i wypycha liczbę cyfr (dziesiętną), jeśli jest to liczba lub liczbę znaków, jeśli jest to ciąg znaków. Może to być przydatne do wykrywania długości wyniku (do buforowania danych wyjściowych) lub obliczania długości łańcucha. Pamiętaj, że w przypadku liczbZ
przesuwa łączną długość części całkowitej i części ułamkowej.X
wyskakuje ToS i przesuwa liczbę cyfr w części ułamkowej liczby. Jeśli ToS był ciągiem,0
jest wypychany.Aby znaleźć liczbę cyfr w części całkowitej liczby, można użyć jednego
dZrX-
. Jeśli nie zmieniłeś precyzji od domyślnejk==0
, użycie1/Z
jest krótsze, ale załóżmy, że musisz zachować określoną niezerową precyzję po operacji:Kr0k1/Zrk
to raczej odrażliwość.z
przesuwa liczbę przedmiotów na stosie. Jedno z moich ulubionych poleceń, w rzeczywistości nie wyświetla żadnych wartości! Można go użyć do wygenerowania sekwencji liczb lub zwiększenia licznika.zd
Wielokrotne użycie (powiedzmy na początku makra) może pozwolić przetestować obliczenia dla każdej liczby naturalnej lub liczby całkowitej w porządku rosnącym.źródło
z
tego i tamtego wcześniej, ale nigdy nie przyszło mi do głowy, aby użyć go jakoCyfry
A
doF
mogą być używane zamiast liczb od 10 do 15. Jednak nadal muszą być one skutecznie traktowane jako cyfry podstawowe 10 (zakładając, że podstawa wejściowa to 10), gdy znajdują się w różnych miejscach. Innymi słowy, przy podstawie wejściowej 10FF
nie będzie reprezentować 255, to będzie reprezentować(15 * 10) + 15
lub 165.W rzeczywistości to działa dla wszystkich cyfr
0
, abyF
w dowolnej zasady wprowadzania2
do16
. Więc jeśli podstawa wejściowa to 5, to26E
byłoby(2 * 5^2) + (6 * 5) + 14
lub 94.Uwaga: takie zachowanie obowiązuje dla niezmodyfikowanych źródeł GNU. Jednak, jak wskazuje @SophiaLechner, dystrybucje oparte na RedHat wydają się używać bc-1.06-dc_ibase.patch co zmienia to zachowanie, więc cyfry> = ibase są traktowane tak
ibase - 1
, niezależnie od ich rzeczywistej wartości. Zauważ, że TIOdc
wydaje się nie mieć bc-1.06-dc_ibase.patch (mimo że jego Fedora 28 ¯_ (ツ) _ / ¯).źródło
FF
reprezentuje99
, w wejściu podstawa 526E
jest taka sama244
, tj. Podstawa 1074
.dc
wersji korzystasz? Używam GNU dc 1.4.1 na Ubuntu i GNU dc 1.3 na MacOSFFp
wyjściowe99
w 1.3.95. Czy mógłbyś to sprawdzić w swojej wersji MacOS?Podczas inicjowania makra
funkcji(użyjemyF
), które chcesz uruchomić natychmiast, użyj czegoś takiegodsFx
zamiastsFlFx
. To samo działa dla zmiennych:dsa
zamiastsala
.Jeśli musisz robić inne rzeczy między przechowywaniem a ładowaniem (np.
sa[other stuff]la
), Nadal rozważ, czy powyższe jest wykonalne: jeśli pozostawisz wartość na stosie przed innymi operacjami, czy będzie z powrotem na górze do końca tych operacji?źródło
Właśnie to odkryłem przez przypadek. Jeszcze inny sposób na wygenerowanie zera:
_
._
jest sygnałem dla DC, że następujące cyfry są liczbą ujemną. Przykład:Ale co, jeśli nie podążymy za nim z liczbą?
Działa to, gdy następny niepusty znak po znaku podkreślenia nie jest cyfrą. Jeśli cyfra następuje po nim, nawet po nowej linii, jest interpretowana jako znak ujemny.
źródło
Jeśli zawartość całego stosu wymaga wydrukowania na końcu programu, do osiągnięcia tego można użyć rekurencyjnej pętli makro. Jednak użycie
f
polecenia jest znacznie krótsze .źródło
dc
odczytuje wprowadzanie linii na raz. Jeśli chcesz czytać w wielu elementach, wykonanie tego jeden na wiersz wymaga albo?
odczytu dla każdego wiersza, albo niewygodnej pętli makr. Zamiast tego, jeśli wszystkie elementy wejściowe można umieścić w jednym wierszu oddzielonym spacjami, jeden z?
nich odczyta wszystkie elementy wejściowe, popychając każdy z nich na stos.Na przykład w
seq 10 | dc -e'?f'
,seq
wypisuje liczby całkowite 1-10, po jednej w wierszu. po?
prostu odczyta pierwszy,1
który zostanief
wyrzucony, gdy zrzut całego stosu. Jednak wseq 10 | tr '\n' ' ' | dc -e'?f'
,tr
powoduje, że wejściowe liczby całkowite są oddzielone spacją. W tym przypadku?
będą czytać wszystkie liczby całkowite z linii za jednym razem if
wypiszą je wszystkie.źródło
Jeśli operator jest ograniczony ze źródła, utwórz nowy za pomocą
a
Coś, co przydało mi się teraz kilka razy, to unikanie używania konkretnego operatora przez przesuwanie wartości ASCII operatora, używanie go
a
do konwertowania go na ciąg znaków is
przesyłanie go do rejestru, który zostanie później wykonany jako makro na. Na przykład muszę dokonać podziału, ale jestem albo niedozwolony, albo staram się unikać używania postaci/
. Mogę, zamiast zrobić47asd
, a następnie w przyszłości, gdy trzeba podzielić 16 przez 4,16 4 ldx
.s
które muszą być przez coś naprawione.źródło
Unikanie białych znaków
Unikanie białych znaków pojawia się w kilku wyzwaniach i ogólnie jest łatwe
dc
. Oprócz ciągów, jeden bardzo specyficzny czas, że konieczne staje się białe znaki podczas pchania jest kilka numerów w jednym rzędzie:1 2 3
. Jeśli należy tego unikać:1[]x2[]x3[]x
.35asn
i wykonać go w pomiędzy:1lnx2lnx3lnx
.źródło
dc: ',' (054) unimplemented
ostrzeżeniami.