x86 32-bitowa funkcja kodu maszynowego, 21 bajtów
x86-64 funkcja kodu maszynowego, 22 bajty
Oszczędność trybie 32-bitowym 1B wymaga stosowania separatora = wypełniacza-1, np fill=0
i sep=/
. Wersja 22-bajtowa może korzystać z dowolnego wyboru separatora i wypełniacza.
To jest wersja 21-bajtowa z separatorem wejściowym = \n
(0xa), separatorem wyjściowym = 0
, separatorem wyjściowym = /
= wypełniaczem-1. Stałe te można łatwo zmienić.
; see the source for more comments
; RDI points to the output buffer, RSI points to the src string
; EDX holds the base
; This is the 32-bit version.
; The 64-bit version is the same, but the DEC is one byte longer (or we can just mov al,output_separator)
08048080 <str_exp>:
8048080: 6a 01 push 0x1
8048082: 59 pop ecx ; ecx = 1 = base**0
8048083: ac lods al,BYTE PTR ds:[esi] ; skip the first char so we don't do too many multiplies
; read an input row and accumulate base**n as we go.
08048084 <str_exp.read_bar>:
8048084: 0f af ca imul ecx,edx ; accumulate the exponential
8048087: ac lods al,BYTE PTR ds:[esi]
8048088: 3c 0a cmp al,0xa ; input_separator = newline
804808a: 77 f8 ja 8048084 <str_exp.read_bar>
; AL = separator or terminator
; flags = below (CF=1) or equal (ZF=1). Equal also implies CF=0 in this case.
; store the output row
804808c: b0 30 mov al,0x30 ; output_filler
804808e: f3 aa rep stos BYTE PTR es:[edi],al ; ecx bytes of filler
8048090: 48 dec eax ; mov al,output_separator
8048091: aa stos BYTE PTR es:[edi],al ;append delim
; CF still set from the inner loop, even after DEC clobbers the other flags
8048092: 73 ec jnc 8048080 <str_exp> ; new row if this is a separator, not terminator
8048094: c3 ret
08048095 <end_of_function>
; 0x95 - 0x80 = 0x15 = 21 bytes
Wersja 64-bitowa jest dłuższa o 1 bajt, przy użyciu 2-bajtowej DEC lub a mov al, output_separator
. Poza tym kod maszynowy jest taki sam dla obu wersji, ale niektóre nazwy rejestrów zmieniają się (np. rcx
Zamiast ecx
w pop
).
Przykładowe dane wyjściowe z uruchomienia programu testowego (podstawa 3):
$ ./string-exponential $'.\n..\n...\n....' $(seq 3);echo
000/000000000/000000000000000000000000000/000000000000000000000000000000000000000000000000000000000000000000000000000000000/
Algorytm :
Zapętlaj dane wejściowe, wykonując exp *= base
dla każdego znaku wypełniającego. Na ogranicznikach i kończącym bajcie zerowym dołącz exp
bajty wypełniacza, a następnie separator do ciągu wyjściowego i zresetuj do exp=1
. Bardzo wygodnie jest zagwarantować, że wejście nie kończy się zarówno znakiem nowej linii, jak i terminatorem.
Na wejściu każda wartość bajtu powyżej separatora (porównanie bez znaku) jest traktowana jako wypełniacz, a każda wartość bajtu poniżej separatora jest traktowana jako znacznik końca łańcucha. (Bezpośrednie sprawdzenie zerowego bajtu wymagałoby dodatkowego test al,al
vs. rozgałęzienia flag ustawionych przez wewnętrzną pętlę).
Reguły zezwalają na separator końcowy tylko wtedy, gdy jest to końcowy znak nowej linii. Moja implementacja zawsze dołącza separator. Aby uzyskać oszczędność 1B w trybie 32-bitowym, ta reguła wymaga separatora = 0xa ( '\n'
ASCII LF = podawanie linii), wypełniacz = 0xb ( '\v'
ASCII VT = karta pionowa). Nie jest to zbyt przyjazne dla człowieka, ale spełnia literę prawa. (Możesz wykonać zrzut heksowy lub
tr $'\v' x
dane wyjściowe, aby sprawdzić, czy to działa, lub zmienić stałą, aby separator wyjściowy i wypełniacz można było wydrukować. Zauważyłem również, że reguły wymagają, aby akceptował dane wejściowe z tym samym wypełnieniem / sep, którego używa dla danych wyjściowych , ale nie widzę nic do zyskania po złamaniu tej zasady).
Źródło NASM / YASM. Zbuduj jako kod 32- lub 64-bitowy, używając %if
rzeczy zawartych w programie testowym lub po prostu zmień rcx na ecx.
input_separator equ 0xa ; `\n` in NASM syntax, but YASM doesn't do C-style escapes
output_filler equ '0' ; For strict rules-compliance, needs to be input_separator+1
output_separator equ output_filler-1 ; saves 1B in 32-bit vs. an arbitrary choice
;; Using output_filler+1 is also possible, but isn't compatible with using the same filler and separator for input and output.
global str_exp
str_exp: ; void str_exp(char *out /*rdi*/, const char *src /*rsi*/,
; unsigned base /*edx*/);
.new_row:
push 1
pop rcx ; ecx=1 = base**0
lodsb ; Skip the first char, since we multiply for the separator
.read_bar:
imul ecx, edx ; accumulate the exponential
lodsb
cmp al, input_separator
ja .read_bar ; anything > separator is treated as filler
; AL = separator or terminator
; flags = below (CF=1) or equal (ZF=1). Equal also implies CF=0, since x-x doesn't produce carry.
mov al, output_filler
rep stosb ; append ecx bytes of filler to the output string
%if output_separator == output_filler-1
dec eax ; saves 1B in the 32-bit version. Use dec even in 64-bit for easier testing
%else
mov al, output_separator
%endif
stosb ; append the delimiter
; CF is still set from the .read_bar loop, even if DEC clobbered the other flags
; JNC/JNB here is equivalent to JE on the original flags, because we can only be here if the char was below-or-equal the separator
jnc .new_row ; separator means more rows, else it's a terminator
; (f+s)+f+ full-match guarantees that the input doesn't end with separator + terminator
ret
Funkcja podąża za ABV SystemV x86-64, z podpisem.
void str_exp(char *out /*rdi*/, const char *src /*rsi*/, unsigned base /*edx*/);
Informuje dzwoniącego o długości łańcucha wyjściowego, pozostawiając w nim wskaźnik „jeden za końcem” rdi
, aby można było uznać to za wartość zwracaną -standardowa konwencja połączeń.
xchg eax,edi
Zwrócenie wskaźnika końcowego w eax lub rax kosztowałoby 1 lub 2 bajty ( ). (W przypadku korzystania z ABI x32, wskaźniki mają gwarantowane tylko 32 bity, w przeciwnym razie musimy użyć, xchg rax,rdi
jeśli dzwoniący przekaże wskaźnik do bufora poza małymi 32 bitami.) Nie uwzględniłem tego w wersji Jestem wysyłanie, ponieważ istnieją obejścia, z których osoba dzwoniąca może korzystać bez uzyskiwania wartości rdi
, dzięki czemu można wywoływać to z C bez opakowania.
Nie kończymy nawet łańcucha wyjściowego ani nic takiego, więc jest on tylko zakończony znakiem nowej linii. Zajmie to 2 bajty, aby to naprawić: xchg eax,ecx / stosb
(rcx wynosi zero od rep stosb
.)
Sposoby sprawdzenia długości ciągu wyjściowego są następujące:
- rdi po powrocie wskazuje jeden-koniec końca łańcucha (więc wywołujący może zrobić len = end-start)
- dzwoniący może po prostu wiedzieć, ile wierszy było na wejściu i liczyć nowe linie
- dzwoniący może użyć dużego zerowanego bufora i
strlen()
później.
Nie są ładne ani wydajne (z wyjątkiem używania wartości zwracanej RDI od wywołującego asm), ale jeśli chcesz, nie wywołuj funkcji asm w golfa z C.: P
Ograniczenia wielkości / zakresu
Maksymalny rozmiar ciągu wyjściowego jest ograniczony tylko ograniczeniami przestrzeni adresowej pamięci wirtualnej. (Głównie, że obecny sprzęt x86-64 obsługuje tylko 48 znaczących bitów w adresach wirtualnych, podzielonych na pół, ponieważ rozszerzają znak zamiast rozszerzania zera. Zobacz diagram w powiązanej odpowiedzi .)
Każdy wiersz może mieć maksymalnie 2 ** 32-1 bajtów wypełniających, ponieważ kumuluję wykładniczy w rejestrze 32-bitowym.
Funkcja działa poprawnie dla baz od 0 do 2 ** 32 - 1. (Prawidłowe dla podstawy 0 to 0 ^ x = 0, tzn. Tylko puste linie bez bajtów wypełniających. Prawidłowe dla podstawy 1 to 1 ^ x = 1, więc zawsze 1 wypełniacz na linię.)
Jest także niesamowicie szybki na Intel IvyBridge i nowszych, szczególnie w przypadku dużych wierszy zapisywanych w wyrównanej pamięci. rep stosb
jest optymalną implementacją memset()
dla dużej liczby z wyrównanymi wskaźnikami na procesorach z funkcją ERMSB . np. 180 ** 4 to 0,97 GB i zajmuje 0,27 sekundy na moim i7-6700k Skylake (z ~ 256k miękkimi błędami strony), aby zapisać do / dev / null. (W Linuksie sterownik urządzenia dla / dev / null nigdzie nie kopiuje danych, po prostu wraca. Więc cały czas jest w nim rep stosb
i błędy strony, które uruchamiają się po dotknięciu pamięci po raz pierwszy. niestety nie używa przezroczystych stronicowania dla tablicy w BSS. Prawdopodobnie madvise()
wywołanie systemowe przyspieszy to.)
Program testowy :
Zbuduj statyczny plik binarny i uruchom go jak ./string-exponential $'#\n##\n###' $(seq 2)
w bazie 2. Aby uniknąć implementacji atoi
, używa base = argc-2
. (Ograniczenia długości wiersza poleceń uniemożliwiają testowanie absurdalnie dużych baz.)
To opakowanie działa dla ciągów wyjściowych do 1 GB. (Wykonuje tylko jedno wywołanie systemowe write () nawet dla gigantycznych ciągów, ale Linux obsługuje to nawet przy zapisie do potoków). Aby zliczyć znaki, potokuj do wc -c
lub używaj, strace ./foo ... > /dev/null
aby zobaczyć argument do syscall zapisu.
Wykorzystuje to wartość zwracaną przez RDI do obliczania długości łańcucha jako argumentu dla write()
.
;;; Test program that calls it
;;; Assembles correctly for either x86-64 or i386, using the following %if stuff.
;;; This block of macro-stuff also lets us build the function itself as 32 or 64-bit with no source changes.
%ifidn __OUTPUT_FORMAT__, elf64
%define CPUMODE 64
%define STACKWIDTH 8 ; push / pop 8 bytes
%define PTRWIDTH 8
%elifidn __OUTPUT_FORMAT__, elfx32
%define CPUMODE 64
%define STACKWIDTH 8 ; push / pop 8 bytes
%define PTRWIDTH 4
%else
%define CPUMODE 32
%define STACKWIDTH 4 ; push / pop 4 bytes
%define PTRWIDTH 4
%define rcx ecx ; Use the 32-bit names everywhere, even in addressing modes and push/pop, for 32-bit code
%define rsi esi
%define rdi edi
%define rsp esp
%endif
global _start
_start:
mov rsi, [rsp+PTRWIDTH + PTRWIDTH*1] ; rsi = argv[1]
mov edx, [rsp] ; base = argc
sub edx, 2 ; base = argc-2 (so it's possible to test base=0 and base=1, and so ./foo $'xxx\nxx\nx' $(seq 2) has the actual base in the arg to seq)
mov edi, outbuf ; output buffer. static data is in the low 2G of address space, so 32-bit mov is fine. This part isn't golfed, though
call str_exp ; str_exp(outbuf, argv[1], argc-2)
; leaves RDI pointing to one-past-the-end of the string
mov esi, outbuf
mov edx, edi
sub edx, esi ; length = end - start
%if CPUMODE == 64 ; use the x86-64 ABI
mov edi, 1 ; fd=1 (stdout)
mov eax, 1 ; SYS_write (Linux x86-64 ABI, from /usr/include/asm/unistd_64.h)
syscall ; write(1, outbuf, length);
xor edi,edi
mov eax,231 ; exit_group(0)
syscall
%else ; Use the i386 32-bit ABI (with legacy int 0x80 instead of sysenter for convenience)
mov ebx, 1
mov eax, 4 ; SYS_write (Linux i386 ABI, from /usr/include/asm/unistd_32.h)
mov ecx, esi ; outbuf
; 3rd arg goes in edx for both ABIs, conveniently enough
int 0x80 ; write(1, outbuf, length)
xor ebx,ebx
mov eax, 1
int 0x80 ; 32-bit ABI _exit(0)
%endif
section .bss
align 2*1024*1024 ; hugepage alignment (32-bit uses 4M hugepages, but whatever)
outbuf: resb 1024*1024*1024 * 1
; 2GB of code+data is the limit for the default 64-bit code model.
; But with -m32, a 2GB bss doesn't get mapped, so we segfault. 1GB is plenty anyway.
Było to zabawne wyzwanie, które bardzo dobrze nadawało się do asm, zwłaszcza operacji na łańcuchach x86 . Reguły są ładnie zaprojektowane, aby uniknąć konieczności obsługi nowej linii, a następnie terminatora na końcu ciągu wejściowego.
Wykładniczy z powtarzanym mnożeniem jest jak mnożenie z powtarzanym dodawaniem, i tak musiałem zapętlić się, aby policzyć znaki w każdym wierszu wejściowym.
Zastanawiałem się nad użyciem jednego argumentu mul
lub imul
zamiast dłuższego imul r,r
, ale jego niejawne użycie EAX byłoby sprzeczne z LODSB.
Próbowałem także SCASB zamiast ładować i porównywać , ale potrzebowałem xchg esi,edi
przed i po wewnętrznej pętli, ponieważ zarówno SCASB, jak i STOSB używają EDI. (Więc wersja 64-bitowa musi korzystać z ABI x32, aby uniknąć obcięcia wskaźników 64-bitowych).
Unikanie STOSB nie jest opcją; nic innego nie jest tak krótkie. Połowa korzyści z używania SCASB polega na tym, że AL = wypełniacz po opuszczeniu pętli wewnętrznej, więc nie potrzebujemy żadnej konfiguracji dla REP STOSB.
SCASB porównuje w innym kierunku niż to, co robiłem, więc musiałem odwrócić porównania.
Moja najlepsza próba z xchg i scasb. Działa, ale nie jest krótszy. ( Kod 32-bitowy, użycie inc
/ dec
trick do zmiany wypełniacza na separator ).
; SCASB version, 24 bytes. Also experimenting with a different loop structure for the inner loop, but all these ideas are break-even at best
; Using separator = filler+1 instead of filler-1 was necessary to distinguish separator from terminator from just CF.
input_filler equ '.' ; bytes below this -> terminator. Bytes above this -> separator
output_filler equ input_filler ; implicit
output_separator equ input_filler+1 ; ('/') implicit
8048080: 89 d1 mov ecx,edx ; ecx=base**1
8048082: b0 2e mov al,0x2e ; input_filler= .
8048084: 87 fe xchg esi,edi
8048086: ae scas al,BYTE PTR es:[edi]
08048087 <str_exp.read_bar>:
8048087: ae scas al,BYTE PTR es:[edi]
8048088: 75 05 jne 804808f <str_exp.bar_end>
804808a: 0f af ca imul ecx,edx ; exit the loop before multiplying for non-filler
804808d: eb f8 jmp 8048087 <str_exp.read_bar> ; The other loop structure (ending with the conditional) would work with SCASB, too. Just showing this for variety.
0804808f <str_exp.bar_end>:
; flags = below if CF=1 (filler<separator), above if CF=0 (filler<terminator)
; (CF=0 is the AE condition, but we can't be here on equal)
; So CF is enough info to distinguish separator from terminator if we clobber ZF with INC
; AL = input_filler = output_filler
804808f: 87 fe xchg esi,edi
8048091: f3 aa rep stos BYTE PTR es:[edi],al
8048093: 40 inc eax ; output_separator
8048094: aa stos BYTE PTR es:[edi],al
8048095: 72 e9 jc 8048080 <str_exp> ; CF is still set from the inner loop
8048097: c3 ret
Na wejście ../.../.
produkuje ..../......../../
. Nie zamierzam zawracać sobie głowy wyświetlaniem zrzutu heksadecymalnego z separatorem = nowy wiersz.
"" <> "#"~Table~#
jest o 3 bajty krótszy niż"#"~StringRepeat~#
, prawdopodobnie także do gry w golfa.Japt , 7 bajtów
Bierze wykres jako tablicę ciągów z
"
wypełniaczem, a podstawa jako liczbę całkowitą.Wypróbuj online
Dodaj
}R
na końcu, aby zamiast tego wziąć wykres jako ciąg oddzielony znakiem nowej linii. ( Wypróbuj )Wyjaśnienie
źródło
MATL ,
1411 bajtówOgranicznikiem jest spacja. Wypełniacz to dowolna postać inna niż spacja.
Wypróbuj online!
Wyjaśnienie
źródło
Haskell ,
3733 bajtów4 bajty ogolone dzięki sudee
Opis:
Rozczarowujące jest to, że jest to
2 bajtyznacznie krótsze niż trudniejsza do odczytania wersja wolna od punktów:źródło
replicate(b^length x)'#'
z'#'<$[1..b^length x]
.ReRegex , 105 bajtów
Wypróbuj online!
ReRegex jest jak brzydki kuzyn Retiny, który wkłada wszystkie wysiłki w wyrażenia regularne, zamiast mieć własne wymyślne operatory.
Oczywiście, ma także
#import
i#input
do zapisania zarówno wejścia na stałe, jak i ponownego zapisywania tych samych wyrażeń w kółko.Wyjaśnił.
Pobiera dane wejściowe w postaci:
na STDIN i daje wynik jak
Po pierwsze, program importuje bibliotekę matematyczną , która oczywiście jest w całości napisana w ReRegex. Większość z nich to trzy wyrażenia regularne.
Pierwszy pasuje do naszej bazy danych wejściowych i po niej szuka linii jednoargumentowej. następnie zastępuje tę linię
;$1^d<$4>
, która jest podstawą, do potęgi Unary (In Decimal). Biblioteka Math obsługuje podstawową konwersję i wykładnik potęgi. A; jest umieszczony na początku, aby zidentyfikować go później jako ukończony.Drugi, dopasowuje podstawę, a następnie wiele wierszy;, przed zakończeniem. Jeśli to pasuje do całości, odcina się od podstawy. pozostawiając uf tylko odpowiedzi i
;
s.Ostatni, pasuje tylko raz na początku, opcjonalnie, a następnie
;
odpowiedź. Następnie ponownie przekształca tę odpowiedź w jednoargumentową, bez;
.Ponieważ wynik nie pasuje do pierwszego wyrażenia regularnego, nie zapętla się w nieskończoność, więc nasze rozwiązanie jest generowane.
źródło
Python 2 ,
5236 bajtówWejścia i wyjścia są traktowane jako tablice ciągów.
#
jest wypełniaczem.Wypróbuj online!
źródło
Röda , 19 bajtów
Wypróbuj online!
Pobiera tablicę jako dane wejściowe i zwraca strumień wartości jako dane wyjściowe.
Wyjaśnienie
źródło
Haskell , 32 bajty
Wypróbuj online! Przykładowe użycie:
f 3 ["##","#","###","#"]
zwraca["#########","###","###########################","###"]
.Użyj,
mapM putStrLn $ f 3 ["##","#","###","#"]
aby uzyskać bardziej przyjemny efekt wizualny:źródło
sum[sum[]^sum[],sum[]^sum[]]
.05AB1E , 9 bajtów
Słupki są oddzielone spacjami, znak wyjściowy jest taki sam jak znak wejściowy.
Wypróbuj online!
źródło
PHP, 69 bajtów
Wypróbuj online!
źródło
[str_pad]."\n"
zamiast tego"\n".[str_pad]
naprawić (+1 bajt). Możesz także założyć, co to jest wypełniacz, więc możesz zapisać dwa bajty$l[0]
, zmieniając go na"#"
.Galaretka , 7 bajtów
Monadyczny link pobierający i zwracający listy pasków (same listy znaków, ciągi znaków AKA) znak wypełniający jest elastyczny.
Wypróbuj online! (stopka uwydatnia wynikową listę, łącząc jej elementy z nowymi liniami).
W jaki sposób?
Alternatywny 7-bajtowy:
ṁ"L€*@¥
- uzyskaj długość każdego słupka (L€
), podnieśbase
do tej potęgi (*@
), a następnie zip ("
) listę i zastosuj dyadę formy (ṁ
) między nimi.źródło
Rubinowy , 29 bajtów
Wypróbuj online!
Tak, dowiedziałem się w zeszłym tygodniu, że
?#
produkuje ciąg jednoznakowy. Nie mam pojęcia, dlaczego ta funkcja istnieje, ale jestem pewien, że tak jest.źródło
?X
Operator, gdzieX
jest jakaś postać, jest „dostać domyślną reprezentację tego znaku” operator. W Ruby <1.9 zwróci punkt kodowy Unicode znaku, ponieważ tak zdefiniowano znaki, ale teraz zwraca ciąg zawierający znak. Jest to część ogólnego przejścia w kierunku bardziej spójnej obsługi Unicode w Rubim.?X
jest używana? Wiele dziwacznych konwencji Ruby, takich jak mnóstwo$
zmiennych, istnieje z powodu znajomości Perla.JavaScript (ES8), 39 bajtów
Bierze bazę jako liczbę całkowitą, a wykres jako tablicę ciągów z dowolnym znakiem jako wypełniaczem, używając składni curry.
Spróbuj
Alternatywnie, 49 bajtów
Ta wersja przyjmuje wykres jako ciąg oddzielony znakiem nowej linii, ponownie z dowolnym znakiem jako wypełniaczem.
źródło
m
flagi na wyrażeniu regularnym, domyślnie.
nie pasuje do nowej linii.Mathematica, 86 bajtów
wkład
źródło
Oktawa, 42 bajty
* Ciąg wejściowy / wyjściowy nie jest w pełni zgodny z wyrażeniem regularnym, ale można zrozumieć, który pasek jest który.
Funkcja przyjmuje jako podstawę wejściową
b
i tablicę 2Ds
zawierającą znaki,"!"
a dane wyjściowe są również tablicą znaków.Wypróbuj online!
Wyjaśnienie:
źródło
CJam, 20 bajtów
Format wejściowy
Dane wejściowe są wymagane w następującym formacie:
źródło
Węgiel drzewny , 11 bajtów
Wypróbuj online! Link jest do pełnej wersji kodu. I / O jest jak lista ciągów
-
znaków (pamiętaj, że potrzebujesz pustej linii, aby zakończyć listę).źródło
V , 27 bajtów
Podstawową ideą jest to, że dodajemy a
'
do każdego wiersza (n ^ 0), a następnie dla każdego#
zastępujemy'
s w wierszu[input] * '
. Pod koniec zamieniłem wszystkie wymienione'
na#
razWypróbuj online!
źródło
R , 35 bajtów
anonimowa funkcja, która bierze łańcuchy jako listę i bazę i zwraca listę łańcuchów.
Wypróbuj online!
źródło
05AB1E , 10 bajtów
Znakiem filtru jest,
1
a separatorem jest nowa linia.Wypróbuj online!
źródło
Siatkówka , 62 bajty
Wypróbuj online! W końcu wykres słupkowy to tylko lista liczb jednoargumentowych. Pobiera dane wejściowe jako wykres (za pomocą
#
s), po którym następuje zasada dziesiętna (aby uniknąć pomyłek). Objaśnienie: Pierwsze zastępcze prefiksy 1 i podstawa do każdej linii wykresu. Druga zamiana mnoży następnie pierwszą liczbę w każdej linii przez drugą, o ile trzecia liczba jest niezerowa. Trzeci zamiennik następnie zmniejsza trzeci numer w każdej linii. Te dwie zamiany są powtarzane, aż trzecia liczba stanie się zero. Ostatnia zamiana usuwa bazę wszędzie, pozostawiając pożądany wynik.źródło
Wypukły , 9 bajtów
Wypróbuj online!
źródło
Alice , 23 bajty
Wypróbuj online!
Nie tylko nie poddaję się, ale jestem tak zaangażowany w odpowiednie robienie tego, że używam go
!
jako wypełniacza. To z pewnością przyciągnie uwagę czytelnika.Wyjaśnienie
Lustra są zachowane w tym objaśnieniu, aby było bardziej jasne, gdy program przełącza się między trybami kardynalnymi i porządkowymi.
źródło
Perl 6 , 26 bajtów
Lista ciągów wejściowych jest w pierwszym parametrze
@^a
. Drugi parametr$^b
to podstawa. Zwracana jest lista ciągów wyjściowych.źródło