ReRegex , 294 275 bajtów
Zaoszczędzono 19 bajtów dzięki lepszym definicjom „funkcji”
Powiedziałbym, że jest to całkiem dobre dla języka opartego tylko na Regex.
Podstawowa biblioteka lib pozwala na konwersję między jednostkową i dziesiętną (co jest potrzebne, ponieważ specyfikacja wyzwania wyraźnie określa dziesiętną), ale nie obsługuje wersji binarnej; Musiałem więc napisać to jako część skryptu, dodając do niego 120 bajtów.
#import base
b(\d*):(_*)\2_b/b1$1:$2b/b(\d*):(_+)\2b/b0$1:$2b/b(\d+):b/$1/b:b/0/B(_*):1/B$1$1_:/B(_*):0/B$1$1:/B(_*):B/$1/j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/j(\d*),\1\d{0,7}:,?(.*)/,$2,/,((_+)_+),(\2),/,$1,/,(_+),(\1_*),/,$2,/^,(_*),$/d<$1>/j,b:u<(?#input)>b:
Wypróbuj online!
Według poszczególnych regeksów.
#import base
b(\d*):(_*)\2_b/b1$1:$2b/
b(\d*):(_+)\2b/b0$1:$2b/
b(\d+):b/$1/
b:b/0/
B(_*):1/B$1$1_:/
B(_*):0/B$1$1:/
B(_*):B/$1/
j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/
j(\d*),\1\d{0,7}:,?(.*)/,$2,/
,((_+)_+),(\2),/,$1,/
,(_+),(\1_*),/,$2,/
^,(_*),$/d<$1>/
j,b:u<(?#input)>b:
Kroki
Po pierwsze, importujemy bibliotekę „podstawową”, która daje dwa wyrażenia regularne. Ten, który konwertujeu<numbers>
w jedność. I taki, który konwertuje z d<unary_underlines>
powrotem na dziesiętne. Wynika to z faktu, że wyzwanie wymaga IO w bazie 10.
Następnie definiujemy garść wyrażeń regularnych, które przekształcają jednoargumentowy na binarny.
b(\d*):(_*)\2_b/b1$1:$2b/
b(\d*):(_+)\2b/b0$1:$2b/
b(\d+):b/$1/
b:b/0/
Pierwsza z nich b(\d*):(_*)\2_b/b1$1:$2b/
wyszukuje b
, opcjonalnie następuje kilka cyfr binarnych, następnie a :
, Następnie dowolna liczba podkreśleń, następnie dokładnie taka sama ilość podkreśleń plus jeden, a na końcu kolejnyb
.
Następnie zamieniamy to na b1
poprzedzone cyframi binarnymi z poprzedniej :
, i tylko pierwszą połowę podkreślenia, a na koniec ostatniąb
.
Sprawdza to, czy jednostka jednoargumentowa nie jest podzielna przez dwa, a jeśli tak, wstawia 1 do cyfr binarnych, a następnie dzieli ją minus jeden przez dwa.
Drugi b(\d*):(_+)\2b/b0$1:$2b/
jest prawie identyczny, jednak nie sprawdza dodatkowych _
, co oznacza, że pasuje tylko wtedy, gdy można go podzielić przez dwa, aw tym przypadku wstawia0
zamiast niego.
Trzeci sprawdza, czy brakuje nam jednoznacznych cyfr, a jeśli tak, to usuwa dopełnienie, aby po prostu zostawić cyfry binarne.
Ostatni sprawdza, czy nigdy nie podano żadnych cyfr binarnych, i w takim przypadku po prostu wychodzi 0
.
Następna grupa Regexów, którą definiujemy, polega na konwersji plików binarnych z powrotem na jednoargumentowe i są nieco prostsze.
B(_*):1/B$1$1_:/
B(_*):0/B$1$1:/
B(_*):B/$1/
Pierwsza z tej grupy, B(_*):1/B$1$1_:/
podobnie jak jej antyteza, wykrywa a B
, a następnie dowolną liczbę Unary cyfr :1
. Nie sprawdza dopasowaniaB
tym przypadku , ponieważ szuka tylko jednej cyfry na raz. Jeśli jest to dopasowane, podwaja poprzednio dopasowaną liczbę jednoargumentowych cyfr i dodaje jedną, a następnie usuwa jedną.
Drugi B(_*):0/B$1$1:/
,, jest prawie identyczny z pierwszym, z wyjątkiem dopasowań 0
raczej niż a1
i nie dodaje dodatkowej jednoznacznej cyfry.
Ostatni z nich B(_*):B/$1/
sprawdza, czy nie ma już cyfr binarnych, a jeśli tak, to rozpakowuje unary. W przeciwieństwie do jego antytezy, nie wymaga specjalnego przypadku 0.
Następnie definiujemy j
wyrażenia regularne, które działają jak funkcja dzielenia.
j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/
j(\d*),\1\d{0,7}:,?(.*)/,$2,/
Pierwszy j(\d*),\1(\d)(\d{7})(\d*):/j$1$2,$1$2$3$4:,B:$1$4B/
robi większość ciężkiego podnoszenia. Wyszukuje j
, opcjonalnie po nich cyfry binarne, które są „inkrementatorem”, następnie przecinek, po którym następuje inkrementator, a następnie dokładnie 8 cyfr binarnych, po których następuje reszta liczby binarnej, a następnie a :
. Pierwsza z 8 cyfr jest dołączana do inkrementatora, zwiększając go, a następnie wszystko oprócz tych 8 cyfr z wejścia binarnego jest dołączane po :
następującym a ,
. Tak więc (gdybyśmy używali 2 cyfr zamiast 8) j,1001:
stałoby się j1:1001:,01
wtedy j10:1001,01,11
. Dodatkowo dołączone elementy tablicy są owinięte w B
s, aby przekonwertować je z powrotem na jednoargumentowe.
Drugi j(\d*),\1\d{0,7}:,?(.*)/,$2,/
sprawdza, czy pozostało mniej niż 8 cyfr binarnych do sprawdzenia za inkrementatorem, a jeśli tak, usuwa wszystko inne niż tablicę owiniętą w ,
s. Na przykład.,_,___,
Podczas i po utworzeniu tablicy definiujemy wyrażenia regularne porównania.
,((_+)_+),(\2),/,$1,/
,(_+),(\1_*),/,$2,/
Pierwszy z nich ,((_+)_+),(\2),/,$1,/
sprawdza przecinek, po którym następuje pewna liczba znaków podkreślenia, potem jeszcze kilka, następnie przecinek, a następnie pierwsza liczba znaków podkreślenia, niż przecinek. Następnie zastępuje go całkowitą liczbą znaków podkreślenia w pierwszym elemencie otoczonym przez ,
s.
Ten ostatni ,(_+),(\1_*),/,$2,/
sprawdza przecinek, po którym następuje pewna liczba znaków podkreślenia, po których następuje kolejny przecinek, następnie ta sama liczba lub więcej znaków podkreślenia i ostatni przecinek. To zamiast tego pozostawi właściwy element.
Na koniec, gdy pozostanie element pasujący w ten sposób ^,(_*),$
, usuwamy otaczające go przecinki i przekształcamy z powrotem na dziesiętny przezd<>
. Wtedy nie będzie już więcej wyrażeń regularnych, a wynik zostanie przedstawiony.
Dane wejściowe są początkowo umieszczane w szablonie j,b:u<(?#input)>b:
, który najpierw przekształca dane dziesiętne na jednoargumentowe, np. 5
-> j,b:_____b:
, a następnie wynikowe jednostkowe na binarne, a j,101:
następnie dzieli binarne (co nie działa w tym przykładzie), pobiera największy element, konwertuje powrót do miejsca po przecinku i gotowe.