Chcę wypróbować nowy rodzaj golfowego wyrażenia regularnego, który prosi o rozwiązanie nietrywialnych zadań obliczeniowych bez podstawiania wyrażeń regularnych. Aby uczynić to bardziej możliwym i mniej uciążliwym, będziesz mógł zastosować kilka zmian, jedna po drugiej.
Wyzwanie
Zaczniemy od prostego: biorąc pod uwagę ciąg znaków zawierający dwie dodatnie liczby całkowite, jako liczby dziesiętne oddzielone a ,
, wygeneruj ciąg zawierający ich sumę, również jako liczbę dziesiętną. Więc bardzo prosto
47,987
powinien zamienić się w
1034
Twoja odpowiedź powinna działać dla dowolnych liczb całkowitych dodatnich.
Format
Każda odpowiedź powinna być sekwencją kroków podstawienia, każdy krok składa się z wyrażenia regularnego i łańcucha zastępczego. Opcjonalnie, dla każdego z tych kroków w sekwencji, możesz powtarzać podstawienie, aż łańcuch przestanie się zmieniać. Oto przykładowe przesłanie (które nie rozwiązuje powyższego problemu):
Regex Modifiers Replacement Repeat?
\b(\d) g |$1 No
|\d <none> 1| Yes
\D g <empty> No
Biorąc pod uwagę dane wejściowe 123,456
, przedłożenie to przetworzyłoby dane wejściowe w następujący sposób: pierwsze podstawienie jest stosowane raz i daje:
|123,|456
Teraz drugie podstawienie jest stosowane w pętli, aż łańcuch przestanie się zmieniać:
1|23,|456
11|3,|456
111|,|456
111|,1|56
111|,11|6
111|,111|
Wreszcie trzecia zamiana jest stosowana raz:
111111
Zauważ, że kryterium zakończenia pętli jest to, czy łańcuch się zmienia, a nie czy wyrażenie regularne znalazło dopasowanie. (Oznacza to, że może również zakończyć się, jeśli znajdziesz dopasowanie, ale zamiennik jest identyczny z dopasowaniem).
Punktacja
Twój wynik główny będzie liczbą kroków podmiany w twoim zgłoszeniu. Każda powtórzona zamiana będzie się liczyła przez 10 kroków. Tak więc powyższy przykład uzyskałby wynik 1 + 10 + 1 = 12
.
W (niezbyt mało prawdopodobnym) przypadku remisu wynik dodatkowy jest sumą rozmiarów wszystkich kroków. Do każdego kroku dodaj regex ( bez ograniczników), modyfikatory i łańcuch podstawienia. W powyższym przykładzie byłoby to (6 + 1 + 3) + (3 + 0 + 2) + (2 + 1 + 0) = 18
.
Różne zasady
Możesz użyć dowolnego smaku wyrażenia regularnego (który powinieneś wskazać), ale wszystkie kroki muszą używać tego samego smaku. Ponadto, należy nie używać żadnych cech języka gospodarza smaku, podobnie jak callbacków zamiennych lub Perl e
modyfikatora, który ocenia kod Perl. Wszelkie manipulacje muszą odbywać się wyłącznie poprzez podstawienie wyrażenia regularnego.
Pamiętaj, że to od Twojego smaku i modyfikatorów zależy, czy każda pojedyncza zamiana zastępuje wszystkie wystąpienia, czy tylko jedno. Np. Jeśli wybierzesz smak ECMAScript, pojedynczy krok domyślnie zastąpi tylko jedno wystąpienie, chyba że użyjesz g
modyfikatora. Z drugiej strony, jeśli używasz smaku .NET, każdy krok zawsze zastępuje wszystkie wystąpienia.
W przypadku języków, które mają różne metody zastępowania pojedynczej i globalnej zamiany (np. Ruby's sub
vs. gsub
), załóż, że pojedyncza zamiana jest domyślna i traktuj globalną zamianę jak g
modyfikator.
Testowanie
Jeśli wybranym przez Ciebie smakiem jest .NET lub ECMAScript, możesz użyć Retiny do przetestowania swojego przesłania (powiedziano mi, że działa również na Mono). W przypadku innych smaków prawdopodobnie będziesz musiał napisać mały program w języku hosta, który zastosuje podstawienia w kolejności. Jeśli tak, proszę dołączyć ten program testowy do swojej odpowiedzi.
źródło
Odpowiedzi:
Smak .NET, wynik: 2
Nie interesuje mnie jeszcze gra w golfa, a
x
to po prostu ignorowanie białych znaków.Najpierw wstawia
9876543210
w każdej pozycji, a następnie usuwa oryginalne znaki i znaki, które nie są bieżącą cyfrą sumy.Duże wyrażenie regularne (1346 bajtów bez białych znaków i komentarzy):
To sprawiło, że pomyślałem o ostatecznym poziomie Manufaktury ... Ale myślę, że regex .NET, który oczywiście nie jest już „regularny”, może rozwiązać wszelkie problemy w PH. A to tylko algorytm w L.
źródło
Wynik: 24
Myślę, że to działa ...
Nie spędziłem jeszcze dużo czasu na grze w poszczególne wyrażenia regularne. Postaram się wkrótce opublikować wyjaśnienie, ale robi się już późno. Tymczasem oto wynik między każdym krokiem:
Pełny program perla:
źródło
Dowolny smak wyrażenia regularnego, 41
Spróbujmy jedni.
d
służy do separatora cyfr,x
przechowuje wartość. Najpierw rozpakowujemy każdą cyfrę, następnie ściskamy mnożniki x10 w lewo, a następnie upuszczamy wszystkie separatory, a następnie wstawiamy mnożniki z powrotem, a następnie przekształcamy każde zamówienie z powrotem na cyfry.źródło
.NET Regex, 14
Nie tak dobre jak rozwiązanie user23013, ale było fajnie. Żadna z zamienników nie ma modyfikatorów.
Powodem wystąpienia wyrażenia regularnego .NET nie jest chociażby bilansowanie grup - po prostu przetestowałem z Retiną , która korzysta z .NET, i odkryłem również, że różne długości lookhinds bardzo pomogły.
Zamiennik 1 (powtórzenie = nie)
Regex:
Zastąpienie
Zamień dwie liczby, wypełnianie, aby mieć taką samą liczbę zer wiodących.
Zamiennik 2 (powtórzenie = nie)
Regex:
Zastąpienie:
Dodaj spację przed każdą liczbą
Zamiennik 3 (powtórzenie = nie)
Zastąpienie:
Dodaj bit przeniesienia (
&0
) oraz gigantyczną tablicę odnośników<c> <a> <b> <carry of a+b+c> <last digit of a+b+c>
.Zamiennik 4 (powtórz = tak)
Regex:
Zastąpienie:
Nadal bierz ostatnie cyfry każdego numeru i znajdź ich (suma, przeniesienie). Umieść sumę na początku łańcucha i zastąp carry.
Zamiennik 5 (powtórzenie = nie)
Regex:
Zastąpienie:
Sprzątać.
Przykładowy przebieg
(Łącząc kilka kroków, mogę uzyskać 12, ale ponieważ robi się dość bałagan i i tak nie wygrywa, myślę, że zamiast tego utrzymam tę bardziej elegancką wersję.)
źródło
Wynik:
50403121Dzięki za to wspaniałe wyzwanie. To rozwiązanie nie jest zbyt eleganckie, ale biorąc pod uwagę ograniczenia, nie widziałem żadnego sposobu, aby ogólnie potraktować cyfrę na wyjściu.
To rozwiązanie oferuje przechwytywanie grup, które czasami nie pasują, i polega na tym, że są one puste, gdy to nastąpi. Działa to w Perlu, chociaż zwykle generuje ostrzeżenie.
Pełna próbka kodu Perla z wyjaśnieniem i wydrukowaniem wyników pośrednich:
Aktualizacja: Byłem w stanie połączyć dwa zapętlone wyrażenia regularne, oszczędzając 10.
Aktualizacja 2: Udało mi się złamać konwersję cyfr wejściowych za pomocą jednego wyrażenia regularnego.
Aktualizacja 3: Zmniejszono do jednego wyrażenia regularnego z zapętleniem.
źródło
${1}
różni się od$1
? Możesz również dołączyć liczbę bajtów w przypadku powiązań.\1
itp., Zapisując kilka znaków.