Czy Pac-Man może zjeść ten sznurek?

46

W zręcznościowej wersji gry Pac-Man zjada pac-kropki. Jednak w tym wyzwaniu jest głodny znaków alfanumerycznych i interpunkcji w łańcuchu.

Twoim zadaniem jest stworzenie funkcji, która karmi Pac-Mana sznurkiem, ocenia, czy może go zjeść, czy nie, i zwraca łańcuch z lokalizacją Pac-Mana w nim.

Pac-Man ( <) zjada postacie od lewej do prawej, pozostawiając podkreślenie lub miejsce dla każdej postaci, gdy idzie, a jego celem jest przejście od pierwszej pozycji-1 do ostatniej pozycji + 1:

1. <Pac
2. _<ac
3. __<c
4. ___<

Jednak naturalny wróg Pac-Mana, duch, zatrzyma go, jeśli napotka jedną z liter w słowie „GHOST” (bez rozróżniania wielkości liter). Twoja funkcja powinna zwrócić ciąg z lokalizacją Pac-Mana, gdy napotka on ghostpostać:

1. <No!
2. _<o!

Jedyną rzeczą, która może pokonać ducha, jest pocisk mocy. Jeśli Pac-Man dojdzie do litery w słowie „PELLET” (również bez rozróżniania wielkości liter) przed przyjściem do ducha, zje ducha i będzie się poruszał, a ten pellet zostanie zużyty. Pellety mocy mogą się kumulować (tzn. W ppggobu duchach zostaną zjedzone). Znak T istnieje zarówno jako duch, jak i granulka, więc można go zignorować (traktować jak każdą inną literę, jak a).

1. <Pop
2. _<op
3. __<p
4. ___<

W celu dalszego wyjaśnienia w ciągu „Pac-Man przegrywa tutaj” następują następujące operacje:

P <P, +1 Pellet (1 pellet)
a <a
c <c
- <-
M <M
a <a
n <n
  <[space]
l <l, +1 Pellet (2 pellets)
o <o, -1 Pellet (1 pellet)
s <s, -1 Pellet (0 pellets)
e <e, +1 Pellet (1 pellet)
s <s, -1 Pellet (0 pellets)
  <[space]
h <h, ghost wins, returns
e
r
e

Przykłady

Input: Pacman wins!
Output: ____________<

Input: Pacman loses wah-wah :(
Output: _______________<h-wah :(

Input: PELLET PELLET GHOST
Output: ___________________<

Input: Hello World!
Output: <Hello World!

Input: <_!@12<_<_<
Output: ___________<

To jest golf golfowy - najniższy wynik w bajtach wygrywa.

atlasolog
źródło
29
Więc granulki nie mają daty ważności?
R
Czy końcowe wyniki są akceptowane?
Katenkyo
7
+1 za to, że „tutaj” przegrywa Pacman. Sprytna walizka testowa.
Olivier Dulac
5
> [W] tym wyzwaniu jest głodny znaków alfanumerycznych i interpunkcji w łańcuchu. ... Yacc- człowiek?
Kaz
9
Teraz widzę zakamuflowanego szarego Pacmana z czarnymi ustami za każdym razem, gdy patrzę na <symbol ...
QBrute

Odpowiedzi:

16

Galaretka, 34 33 bajtów

Œl“ʋʋ“ṁḍ»ċ€Ð€IF+\‘0ṭi0ð’”_×;”<;ṫ@

Wypróbuj online!

Myślę, że w końcu zaczynam rozumieć Jelly. Czuje się trochę przerażająco.

PurkkaKoodari
źródło
5
Zaczynam się martwić, kiedy umiesz to płynnie czytać :)
quetzalcoatl
30

Siatkówka , 55 38 bajtów

i`^(([elp])|[^ghos]|(?<-2>.))*
$.&$*_<

Wypróbuj online! (Pierwszy wiersz pozwala na uruchomienie kilku przypadków testowych jednocześnie.)

Wyjaśnienie

Problem polega przede wszystkim na znalezieniu najdłuższego prefiksu, który nie ma niedopasowanego nawiasu zamykającego. Oprócz tego, że możemy skorzystać z jednego e, llub pw miejscu (i albo g, h, olub sw miejscu ).

Dlatego to rozwiązanie jest prawie podręcznikowym przykładem grup bilansujących. Nie będę szczegółowo omawiał ich działania, ponieważ ten kod jest zasadniczo taki sam, jak standardowy przykład, który można przeczytać w mojej odpowiedzi SO dotyczącej grup bilansujących .

Cały program jest zatem pojedynczym podstawieniem wyrażenia regularnego. iAktywuje bez uwzględniania wielkości liter. Następnie albo dopasowujemy pellet [elp]i zwiększamy licznik głębokości (w postaci stosu przechwytywania grupy 2), albo dopasowujemy coś, co nie jest duchem, [ghos]lub dopasowujemy ducha .i zmniejszamy licznik głębokości, wyskakując ze stosu 2. Oczywiście w zasadzie pozwala to na dopasowanie pelletu z [^ghos]sekcją lub nie-ducha z .sekcją, ale dzięki zachłannemu dopasowaniu i sposobowi powrotu wyrażenia regularnego silnik regex nigdy nie próbuje tych możliwości.

Podstawienie wykorzystuje następnie dwie cechy $*charakterystyczne dla siatkówki: powtarza znak po prawej stronie tyle razy, ile określa token po lewej stronie. Tym tokenem jest $.&długość całego meczu. Oznacza to po prostu, że zamieniamy każdą postać w meczu na _. Następnie dodajemy również <do tych podkreślników. Część wejściowa, która nie jest zjedzona, po prostu pozostaje niezmieniona przez substytucję.

Martin Ender
źródło
Fajne znęcanie się nad grupami!
Leaky Nun
11
@LeakyNun Abuse? Po to są tworzone grupy bilansujące. : D
Martin Ender
1
Hej, odpowiedź Retina, która wygląda zdalnie jak regex, którego używam
kot
10

Python 2, 114 113 108 bajtów

s=raw_input()
p=i=0
for c in s:
 p+=(c in'plePLE')-(c in'ghosGHOS')
 if p<0:break
 i+=1
print'_'*i+'<'+s[i:]
Arfie
źródło
Twoja funkcja zwraca None, a nie odpowiedź. A jak liczyć 107? Liczę 110.
Stefan Pochmann
@StefanPochmann podwójne spacje to tabulatory i wolno drukować odpowiedź, a nie zwracać
Blue
@muddyfish Ah, dzięki. Nie wydają się tu jednak kartami, nawet gdy przechodzę do „edycji”. A problem wyraźnie mówi „powrót” ... czy istnieją jakieś przepisy dotyczące całej witryny, które go unieważniają? (Jestem tu całkiem nowy i nie wiem)
Stefan Pochmann
Zakładki @StefanPochmann są spożywane przez SE (zwykle konwertowane na 4 spacje). Chyba że wyraźnie zaznaczono drukowanie w funkcji. OP prawdopodobnie nie chciał tego zmienić
Blue
Myślę, że rozsądnie jest powiedzieć, że zawsze powinien albo zwrócić, jeśli jest to funkcja, albo odczytać ze standardowego wejścia i wydrukować. Przejdę na czytanie ze standardowego, które i tak powinno być krótsze.
Arfie
8

Python 2, 89 bajtów

Czasami moja uparta determinacja, aby uczynić Python językiem funkcjonalnym, ma swoje zalety.

def f(s,l=1):l+=(s[:1]in'plePLE')-(s[:1]in'ghosGHOS');return s*l and'_'+f(s[1:],l)or'<'+s

(Nieznacznie) nie golfił:

def f(s, l=1):
    l += (s[:1] in 'plePLE') - (s[:1] in 'ghosGHOS')
    return (s * l) and ('_' + f(s[1:], l)) or ('<' + s)

Tworzy wynikowy ciąg za pomocą rekurencji. Aktualizacja l(dla „żyć”) dodaje 1 dla pelletów ( True - False == 1), odejmuje 1 dla duchów ( False - True == -1) i dodaje 0 dla każdej innej postaci. Dodaje również 0, gdy sjest pustym ciągiem, dzięki krojeniu Pythona i temu '' in any_str == True, że pellet i duch anulują się.

Instrukcja return używa test and b or azamiast a if test else bjednego bajtu. Podstawowy przypadek rekurencji występuje, gdy kończy się sznurek lub Pac-Man skończy się granulkami, zwięźle przedstawionymi jako s*p, co równa się ''(a zatem ocenia na fałsz), gdy którykolwiek s == ''lub p == 0.

beiju
źródło
8

C #, 269 256 232 212 211 bajtów

Pierwszy w historii tutaj, więc jest to prawdopodobnie znacznie dłużej niż mogłoby być (i prawdopodobnie dlatego, że jest w C #). Wszelkie wskazówki na temat tego, jak mogę to skrócić, byłyby świetne!

Dziękuję wszystkim w komentarzach, którzy mi pomogli!

Wersja golfowa

static void p(string x){int p=0,i=0;string t='<'+x;var s=t.ToCharArray();for(;++i<s.Length;){if("PELpel".Contains(s[i]))p++;if("GHOSghos".Contains(s[i])&&--p<0)break;s[i]='<';if(i>0)s[i-1]='_';}Console.Write(s);}

Wersja bez golfa

static void p(string x) {
 int p = 0, i = 0;
 string t = '<' + x;
 var s = t.ToCharArray();
 for (; ++i < s.Length;) {
  if ("PELpel".Contains(s[i])) p++;
  if ("GHOSghos".Contains(s[i]) && --p < 0) break;
  s[i] = '<';
  if (i > 0) s[i - 1] = '_';
 }
 Console.Write(s);
}
Andrzej
źródło
1
Możesz zamieniać typy w zmiennych zmiennych przy użyciu słowa kluczowego var. np. var temp = '' + wejście; Pętlę for można przepisać, aby zapisać 4 znaki: for (var i = 0; i ++ <s.Length;)
CSharpie
1
Do deklaracji można użyć przecinków „int i = 0, p = 0; ciąg P =„ PELpel ”, G =„ GHOSghos ”, t = '' + x;” i zmiana z @CSharpie, tworząc pętlę „for (; i ++ <s.Length;)”. Dodatkowo możesz „Console.Write (s);” bezpośrednio dla łącznie 235 bajtów.
Nickson
1
Myślę, że powinno również działać bez elsezapisywania kolejnych 5 znaków. I uruchamiając pętlę na i = 1powinieneś być w stanie usunąć ostatni, jeśli kod można wykonać za każdym razem.
Frozn
1
Możesz pozbyć się swojej deklaracji c i po prostu wstawić s[i]dostęp dla 5 znaków.
Phaeze
1
Czy warto to przypisać P="PELpel"i G="GHOSghos"? Używasz ich tylko raz. Czy coś mi brakuje, czy to tylko 4 dodatkowe postacie? Potrzebujesz też else? "PELpel".Contains(c)i "GHOSghos".Contains(c)powinny się wzajemnie wykluczać.
jpmc26
7

Pyth, 53 48 44 bajtów

4 bajty dzięki @ Pietu1998 za sztuczkę !!@-> }(którą rozumieją tylko ludzie znający Pytha)

++ * Jf <@ + sM._m - !! @ d „PELpel” !! @ d „GHOSghos” Q_1T00 \ _ \ <> QJ 
++ * Jf <@ + sM._m - !! @ d „PEL” !! @ d „GHOS” rQ1_1T00 \ _ \ <> QJ
++ * Jf <@ + sM._m-} d „PEL”} d „GHOS” rz1_1T00 \ _ \ <> zJ

Zestaw testowy.

Leaky Nun
źródło
17
które tylko ludzie znający Pyth mogą zrozumieć Cóż, podobnie jak reszta kodu, naturalnie
Luis Mendo
4
@LuisMendo Aby być uczciwym wobec osób, które nie znają Pytha, jestem pewien, że większość z nich mogła zrozumieć, że przecięcie jednego zestawu singletonów z innym zestawem posiadającym dowolne elementy jest równoważne z tym, że członek zestawu singletonów jest członkiem większy zestaw: P
FryAmTheEggman
1
@FryAmTheEggman, więc oczywiście !!@jest to tylko trigrafia }, prawda? : p
97
7

MATL , 37 36 35 bajtów

tkt'ghos'mw'pel'm-Ys1=Y>&)g95*60bhh

Wypróbuj online!

Wyjaśnienie

tkt      % Input string implicitly. Duplicate, convert to lower case, duplicate
'ghos'm  % True for "ghost" characters
w'pel'm  % Swap to bring lowercase copy to top. True for "pellet" characters
-Ys      % Subtract, cumulative sum. Pac-Man can reach until the first "1"
1=       % True for entries that equal 1
Y>       % Cumulative maximum. This gives false until the first true is found, and
         % true from there on
&)       % Split original string in two parts, given by the zeros and ones respectively
g95*     % Convert the first part into ones and multiply by 95. This gives a numerical
         % array containing number 95 (ASCII for '_')
60       % Push 60 (ASCII for '<')
b        % Bubble up second part of original string
hh       % Concatenate the three strings/arrays, automatically converting to char
Luis Mendo
źródło
7

JavaScript (ES6), 98 bajtów

s=>s.replace(/./g,c=>p<0?c:(p+=/[elp]/i.test(c)-/[ghos]/i.test(c))<0?"<"+c:"_",p=0)+"<".slice(p<0)

Objaśnienie: putrzymuje bieżącą liczbę granulek. Jeśli jest już ujemny, po prostu zwracamy znak i idziemy dalej, aby reszta łańcucha pozostała nietknięta. W przeciwnym razie badamy bieżący znak, a jeśli spowoduje to, że pstanie się on ujemny, wstawiamy <znak, w przeciwnym razie zastępujemy obecny znak na _. Wreszcie, jeśli pnigdy nie staje się ujemny, dodamy a <do łańcucha.

Neil
źródło
4

Pyth, 47 46 44 bajtów

++*\_Kh+f!h=+Z-}Jr@zT0"pel"}J"ghos"Uzlz\<>zK

Wypróbuj online. Zestaw testowy.

Zupełnie inne podejście niż Leaky Nun i jestem pewien, że można to pograć w golfa dalej.

PurkkaKoodari
źródło
Użyj Zzamiast Gi zmień f!naf!h
Leaky Nun
@LeakyNun Właśnie to zorientowałem w innej zakładce. Dzięki.
PurkkaKoodari
2
Myślę, że tw "ghost"powinny być usunięte
Dziurawy Nun
Jeśli będziemy grać w golfa w naszych rozwiązaniach, jaka jest różnica między naszymi rozwiązaniami?
Leaky Nun
@LeakyNun Nie jestem pewien, który z nich jest bliższy, ale moja pierwsza próba dała mi 43 bajty i nie sądzę, że muszę dodać trzecią odpowiedź. Może powinniśmy współpracować w czacie Pyth?
FryAmTheEggman
4

Lua, 198 190 184 185 163 bajtów

Ok, przyznaję, to długo. Bardzo długo. Lua ma kilka narzędzi do zabawy ze strunami, ale jest ograniczona, to samo dotyczy warunkowych, które zajmują dużo miejsca.

Edycja: dzięki @LeakyNun za uratowanie mnie 9 bajtów :) Straciłem trochę bajtów, aby naprawić błąd

Edytuj rozwiązanie 2: 163 bajtów znalezione przez @LeakyNun

i=0p=0n=...for c in n:gmatch"."do
p=p+(c:find"[ghosGHOS]"and-1or c:find"[pelPEL]"and 1or 0)if p<0then
break else i=i+1 end end print(('_'):rep(i)..'<'..n:sub(i+1))

Stary 185

p=0z=(...):gsub(".",function(c)p=p+(c:find"[ghosGHOS]"and-1or
c:find"[pelPEL]"and 1or 0)s=p<0 and 1or s
return s and c or'_'end)_,i,s=z:find"(_+)"print((s or'')..'<'..z:sub(1+(i or 0)))

Bez golfa

i=0                        -- number of characters eaten
p=0                        -- pellet counter
n=...                      -- shorthand for the argument
for c in n:gmatch"."       -- iterate over each characters in the input
do
  p=p+(c:find"[ghosGHOS]"  -- if the current char is a GHOST
        and-1              -- decrement the pellet counter
      or c:find"[pelPEL]"  -- if it's a PELLET
        and 1              -- increment it
      or 0)                -- else, leave it alone
  if p<0                   -- if we try to eat a ghost without pellet
  then 
    break                  -- stop iterating
  else
    i=i+1                  -- else, increment our score
  end
end

print(('_'):rep(i)         -- print i*'_'
  ..'<'                    -- appended with Pacman
  ..n:sub(i+1))            -- appended with the remaining characters if we died
Katenkyo
źródło
Usuń d=c:lower()i wyszukaj również wielkie litery
Leaky Nun
and 1or s and 1or s s and s
Leaky Nun
@LeakyNun nie widział, że krótsze byłoby napisanie wszystkich listów ... Dzięki. Także drugi komentarz wspomniał o czymś, co zmieniłem, ale tylko w nie golfowym> _ <
Katenkyo
print(('').rep('_',i)..','..z:sub(i+1))
Leaky Nun
@LeakyNun Pracuję nad podobnym rozwiązaniem, ale problem wynika z faktu, że imoże byćnil
Katenkyo
3

Python 3, 176 157 150 149 134 133 124 bajtów

Zdefiniuj nazwaną funkcję, fktóra przyjmuje ciąg jako argument

def f(s):
 n=i=0
 for c in s:
  if c in"GgHhOoSs":
   if n:n-=1
   else:break
  n+=c in"PpEeLl";i+=1
 return"_"*i+"<"+s[i:]

Prawdopodobnie można bardziej grać w golfa

Dziękujemy wszystkim, którzy skomentowali: D

TuxCrafting
źródło
1
﹐ Usuń x=c.upper()i wyszukaj małe litery
Leaky Nun
Możesz zaoszczędzić, pisząc niektóre wyrażenia w tym samym wierszu, oddzielając je, ;zamiast umieszczając je w osobnych wierszach. Możesz także użyć Python 2, który pozwala używać spacji jako pierwszego poziomu intencji, a tabulatorów jako drugiego.
Denker
n=i=0, nie n=0i i=0. t[i]="_"zamiast t[i] = "_", to samo dla t[i] = "<". return''.join(t)usuń to miejsce.
Erik the Outgolfer
@LeakyNun W testach są wielkie litery.
TuxCrafting
@ TùxCräftîñg Nie, mają na myśli "GgHhOoSs"i "PpEeLl".
Erik the Outgolfer
2

Python 3, 114 110 bajtów

Mój pierwszy golf golfowy.

Dziękujemy dr Green Eggs i Iron Manowi za zaoszczędzenie 4 bajtów.

l,x=1,0
f,y,s="ghosGHOS","pelPEL",input()
while s[x:]*l:l+=(s[x]in y)-(s[x]in f);x+=l>0
print("_"*x+"<"+s[x:])

Wykorzystuje ocenę wartości logicznych do jednego i zera w celu zagęszczenia logicznego AND do mnożenia. (0 * 0 = 0, 1 * 0 = 0, 1 * 1 = 1). Mam nadzieję, że to dobra pierwsza próba.

Zniszczalna cytryna
źródło
Ładna odpowiedź i witamy na stronie! Jakiej wersji Pythona używasz? Możesz to określić. Ponadto nie przetestowałem tego, ale możesz while s[x:]*lzdjąć 4 bajty.
DJMcMayhem
1

PowerShell, 185

{$l=1;$o="";for($i=0;($i -lt $_.Length) -or (($o+="<") -and 0); $i++){if ($_[$i] -match '[pel]'){$l++}if($_[$i] -match '[ghos]'){$l--}if(!$l){$o+="<"+$_.substring($i);break}$o+="_"}$o}

Nie golfowany:

("Pacman wins!",
"Pacman loses wah-wah :(",
"PELLET PELLET GHOST",
"Hello World!"
) | 
% {
    $l=1;$o="";
    for($i = 0; ($i -lt $_.Length) -or (($o+="<") -and 0); $i++) {
        if ($_[$i] -match '[pel]') { $l++ }
        if ($_[$i] -match '[ghos]') { $l--}
        if (!$l) { $o+="<"+$_.substring($i); break }        
        $o += "_"
    }
    $o
}
Eris
źródło
1

Python3, 211 184 bajtów

Argument „s” jest ciągiem

def f(s):
    p=c=0
    for i in s:
        if i in "gGhHoOsS":
            if p<1:break
            else:p-=1
        if i in "pPeElL":p+=1
        c+=1
    return"_"*c + "<" + s[c:]

Byłbym wdzięczny za wszelkie wskazówki dotyczące gry w golfa, ponieważ jest to moja pierwsza próba golfa

Dzięki za komentarz :)

Isaac Greene
źródło
2
Witamy w Programowaniu Puzzle i Code Golf! Kilka wskazówek: Istnieje wiele niepotrzebnych białych znaków między operatorami. Usunięcie ich pozwoliłoby zaoszczędzić sporo bajtów. Możesz także użyć Python 2, który pozwala używać spacji jako pierwszego poziomu intencji i tabulatorów dla pozostałych.
Denker
1
Możesz zamienić pierwszy na return "_"*c + "<" + s[c:]tylko, breakponieważ ten kod i tak zostanie wykonany po pętli for.
Arfie
Wypróbuj online! Nawiasem mówiąc, mam 183 bajtów. Czy policzyłeś końcowy znak nowej linii?
Pavel
1

Haskell, 119 113 bajtów

Podziękowania dla Daniela Wagnera za 6 bajtów mniej.

p=(0!)
n!(c:s)|elem c"ghosGHOS"=if n<1then '<':c:s else(n-1)&s|elem c"elpELP"=(n+1)&s|0<1=n&s
_!_="<"
n&s='_':n!s

Nazwij to jak p "Hello World!".

1thenTo przypadek krawędzi, które są interpretowane prawidłowo w moim GHC (7.10), ale rzuca większości markerów składni. Więc może być różnie interpretowany również w twoim kompilatorze.

Nie golfowany:

pacman string = go 0 string

-- | In the golfed version: (!)
go _   []                   = "<"                            -- won
go pellets (char:string)
 | char `elem` "ghosGHOS"
 = if pellets < 1        then '<':char:string                -- lost
                         else nextStep (pellets - 1) string  -- ghost
 | char `elem` "elpELP"
 =                            nextStep (pellets + 1) string  -- pellet
 | otherwise
 =                            nextStep  pellets      string  -- anything else

-- | In the golfed version: (&)
nextStep pellets string = '_':(go pellets string)
MarLinn
źródło
1
Możesz zaoszczędzić kilka bajtów, umieszczając wszystkich strażników na tej samej linii, np n!(c:s)|elem c"blah"=blah|elem c"blah"=blah|0<1=blah.
Daniel Wagner,
@Daniel Wagner Fajna wskazówka, dzięki!
MarLinn
Czy możesz dodać link TIO ? Wciąż próbuję sprawić, by działały błędy.
Pavel
1

C, 237 bajtów

#include<stdio.h>
#include<string.h>
main(p,i,j){char s[99];fgets(s,99,stdin);for(p=i=0;s[i];++i){if(strchr("GHOSghos",s[i])){if(p)p--;else break;}else if(strchr("PELpel",s[i]))p++;}j=i-(s[i]==0);while(j--)printf("_");printf("<%s",s+i);}
user2064000
źródło
1

C ++, 315 373 327 bajtów

(Uwaga: nadal gra w golfa)

#include <iostream>
#include <string>
using namespace std;
int main(){string input;getline(cin, input);
if(input.find("Pac-Man loses")!=string::npos||input.find("Pacman loses")!=string::npos)
    cout<<"<"<<input.substr(15,input.length()-1);
else{for(unsigned i=0;i<=input.length();++i)
    cout << "_";
cout<<"<";
}return 0;
}
tachma
źródło
1
Pac-Man nie przegrywa, kiedy powinien.
tildearrow
Cześć @tildearrow, dziękuję za sprawdzenie mojego kodu! Zaktualizuję mojego posta.
tachma
Myślę, że można bardziej grać w golfa. Spróbuj usunąć znaki nowej linii po spacji / if()i usunięcie spacji wokół !=, ||, =, -, i <=. Ponadto nie cin>>inputdziała zamiast getline? Możesz także kondensować wokół ;.
NoOneIsHere
@NoOneIsHere, dziękuję za komentarz! Właściwie to jestem nowy w golfie kodem, więc postaram się trochę poprawić kod i zaktualizować swój post. Jeśli masz jakieś inne przydatne porady na temat gry w golfa kodowego, bardzo bym je docenił.
tachma
1
Zobacz Wskazówki dotyczące gry w C / C ++ .
NoOneIsHere
1

Rubin, (119 bajtów)

q=i=0;a=$**" ";a.split(//).each{|c|q+=((c+?p=~/[ple]/i)^1)-((c+?g=~/[ghos]/i)^1);q<0?break : i+=1};p ?_*i+?<+a[i..-1]

Prawdopodobnie brakuje mi pewnych rzeczy, ponieważ jestem nowy w tym ...

Ruby jest moją przyjaciółką :)

pottedmeat7
źródło
1
Witamy w PPCG!
FlipTack,
0

Perl, 54 (52 + 2) bajtów

s/([pel](?1)*[ghos]|[^ghos
])*/'_'x(length$&).'<'/ei

Potrzeby -p, które zostaną określone w opcji wiersza polecenia.

Wyjaśnienie:

Ta -popcja powoduje zawinięcie instrukcji w pętli odczytu-modyfikacji-wydruku, gdzie podczas każdej iteracji pętli $_zawiera wiersz danych wejściowych, w tym separator linii.

Wyrażenie regularne jest w dużej mierze tym samym pomysłem, co w odpowiedzi Retina.

Nazwij wzorzec wyszukiwania ([pel](?1)*[ghos]|[^ghos ])*„akceptowalny”. Następnie można go rekurencyjnie zdefiniować jako:

Ciąg jest „akceptowalny”, jeśli:

  • Jest to znak z PELLETwyjątkiem T, po którym następuje akceptowalny ciąg znaków, po którym następuje znak z GHOSTwyjątkiem T.
  • Jest to znak, którego nie ma GHOSTpoza Ttym, że nie jest znakiem nowego wiersza.
  • Jest to konkatenacja dowolnej liczby (w tym 0) dopuszczalnych ciągów.

Ta definicja dopuszcza więcej granulek niż duchów: PELpostać może być dopasowana jako postać peletu lub postać niebędąca duchem.

Pusty ciąg znaków jest uważany za akceptowalny, dlatego wyrażenie regularne gwarantuje dopasowanie do pozycji 0, gdzie zostanie dopasowany najdłuższy dopuszczalny podciąg.

Ten najdłuższy akceptowalny substrat jest następnie dopasowywany przez podkreślniki o równej długości, a następnie <.

hvd
źródło
Flagi iirc jak -p liczą się jako jeden bajt.
Pavel
1
@Pavel To skomplikowane. Jeśli normalne wywołanie nie -pzostało już użyte -, np. perl -e-> perl -pe, to -jest bezpłatne. Ale myślę, że perl -ewersja jest dłuższa z powodu cytowania, więc myślę, że nie mogę jej tutaj użyć.
hvd