Praming Puzles & Colf: Condense a String

25

Spędziłem trochę czasu na tej stronie i zacząłem cieszyć się możliwie najkrótszym czasem. To może być powód, dla którego ostatnio jestem obrażony ciągami zawierającymi te same znaki więcej niż jeden raz. Twoim zadaniem jest napisanie funkcji lub programu, który skondensuje dany ciąg znaków zgodnie z następującymi zasadami:

  • Rozpocznij od 0-kondensacji , czyli poszukaj pierwszej (najbardziej lewej) pary tych samych znaków z 0 innymi znakami między nimi. Jeśli taka para zostanie znaleziona, usuń jeden z dwóch znaków i ponownie uruchom algorytm, wykonując kolejną 0-kondensację . Jeśli nie znaleziono takiej pary, przejdź do następnego kroku. Przykłady:
    programming-C0-> programing
    aabbcc-C0-> abbcc
    test-C0->test

  • Następnie wykonaj 1-kondensację , czyli poszukaj pierwszej pary takich samych znaków z 1 inną postacią między nimi. Jeśli taka para zostanie znaleziona, usuń jedną z nich i wszystkie znaki między nimi i uruchom ponownie z zerową kondensacją . Jeśli nie znaleziono takiej pary, przejdź do następnego kroku. Przykłady:
    abacac-C1-> acac
    java-C1->ja

  • Kontynuuj od 2-kondensacji i tak dalej do n-kondensacji, gdzie n jest długością oryginalnej struny, za każdym razem, gdy wznawia się po kondensacji, usuwa niektóre litery. Przykłady:
    programing-C2-> -C3- praming
    abcdafg>afg

Powstały ciąg jest nazywany skondensowanym i zawiera każdy znak maksymalnie raz.


Wkład:

Ciąg małych liter znaków drukowalnych ascii.

Wydajność:

Skondensowane ciąg według powyższych zasad.

Przykłady:

examples     -> es
programming  -> praming
puzzles      -> puzles
codegolf     -> colf
andromeda    -> a
abcbaccbabcb -> acb
if(x==1):x++ -> if(x+
fnabnfun     -> fun
abcdefae     -> abcde

Szczegółowe przykłady wyjaśniające, jak działa algorytm:

fnabnfun -C0-> fnabnfun -C1-> fnabnfun -C2-> fnfun -C0-> fnfun -C1-> fun -C0-> fun 
 -C1-> fun -C2-> ... -C8-> fun

abcbaccbabcb -C0-> abcbacbabcb -C0-> abcbacbabcb -C1-> abacbabcb -C0-> abacbabcb 
 -C1-> acbabcb -C0-> acbabcb -C1-> acbcb -C0-> acbcb -C1-> acb -C0-> acb 
 -C1-> ... -C12-> acb

Twoje podejście nie musi implementować algorytmu z góry, o ile rozwiązanie i algorytm zwracają ten sam wynik dla wszystkich dozwolonych danych wejściowych. To wyzwanie dla .


Dzięki @Linus za pomocne komentarze w piaskownicy!

Laikoni
źródło
@MartinEnder Przypadek testowy Rileya jest nadal konieczny, ponieważ jest to jedyne, na którym moje rozwiązanie Retina nie działa.
mbomb007
@ mbomb007 Ah, rozumiem. Słuszna uwaga.
Martin Ender
Czy ciąg wejściowy będzie zawierał znaki niedrukowalne, takie jak spacje?
mbomb007
@ mbomb007 Nie, zakładanie, że tylko znaki ascii do wydruku są w porządku.
Laikoni
@ mbomb007 Jednak, o ile mi wiadomo, spacja jest uważana za znak ascii do wydrukowania, np . tutaj .
Laikoni

Odpowiedzi:

6

JavaScript (ES6), 74 bajty

f=
(s,n=0,m=s.match(`(.).{${n}}\\1`))=>s[n]?m?f(s.replace(...m)):f(s,n+1):s
;
<input oninput=o.textContent=f(this.value)><pre id=o>

Neil
źródło
Bardzo miło, krócej niż myślałem.
ETHproductions
5

Perl, 38 31 30 29 bajtów

To powinno pozostawić języki inne niż golfowe daleko w tyle ...

-1 za $-[0]podziękowania dla Riley

-1 za @{-}podziękowania dla Dady

Obejmuje +1 dla -p

Podaj dane na STDIN

condense.pl:

#!/usr/bin/perl -p
s/(.)\K.{@{-}}\1// while/./g

Ta 27-bajtowa wersja powinna działać, ale nie działa, ponieważ Perl nie interpoluje @-w wyrażeniu regularnym (patrz /programming/39521060/why-are-etc-not-interpolated-in-strings )

#!/usr/bin/perl -p
s/(.)\K.{@-}\1// while/./g
Ton Hospel
źródło
Jak działa @{\@-}część? Myślałem, że @-trzyma indeksy każdego meczu, więc jak to się „liczy” na każdej iteracji. Ponadto, jeśli drukujesz @{\@-}przed i po każdej zamianie, drukuje tylko 1 lub 2.
Riley
1
@ Riley Za /./gkażdym razem postępuje o 1 w ciągu, z wyjątkiem zmian łańcucha, następnie jest resetowany do 0. Jeśli drukujesz @-po, /./gale przed nim s///zobaczysz, że idzie w górę (użyj testu, w którym pozostały ciąg jest wystarczająco duży)
Ton Hospel
Drukowanie $-[0]daje liczby, których bym się spodziewał. Czy @{\@-}działa z $-[0]powodu kontekstu wyrażenia regularnego, ale nie z jakiegoś powodu podczas drukowania? $-[0]jest bajtem krótszym niż @{\@-}jeśli są takie same.
Riley
"@{\@-}"to nie to samo co @{\@-}(bez ").
Riley
@ Riley Nie, ale "@{\@-}"jest taki sam jak "@-". I to powinno być również prawdą w przypadku podstawienia wyrażenia regularnego, ale tak nie jest. Podobnie $-[0]powinno działać, ale nie działa. PS: Prawdopodobnie w jakiś sposób zastosowałeś kontekst skalarny, @-kiedy robiłeś wydruk, więc zawsze masz 1 lub 2
Ton Hospel
3

CJam , 35 bajtów

rL{_,{{(_@_@#I={I)>]sj}*}h]s}fI}j

Wypróbuj online!


rL{                            }j   | run recursion on input
   _,{                      }fI     | for I from 0 to length(input)
      {                 }h]s        | one pass & clean up
       (_@                          | slice and store leading element A
          _@#I={      }*            | if next A is I steps away
                I)>                 | slice off I+1 element
                   ]sj              | clean up & recursion

Po włożeniu można zobaczyć poszczególne skroplinyed

Linus
źródło
2

Python 2, 117 104 101 bajtów

Rekurencyjnie wykonaj niezbędne wymiany. Wyrażenie regularne buduję dynamicznie.

import re
def f(s,i=0):t=re.sub(r"(.)%s\1"%("."*i),r"\1",s);e=s==t;return i>len(t)and t or f(t,i*e+e)

Wypróbuj online

mbomb007
źródło
Dwie linie powrotne można skondensować w return i>len(t) and t or s!=t and f(t) or f(t,i+1)sieci o -4 bajtach
Quelklef
Kolejne 2 bajty można ogolić, zmieniając je nareturn t if i>len(t)else s!=t and f(t)or f(t,i+1))
Quelklef,
Co więcej e=s==t;return i>len(t)and t or f(t,i*e+e), możesz usunąć i=0definicję funkcji, ale będziesz musiał wywoływać z 0 startem.
Quelklef,
Zakładam, że cztery spacje nie istnieją, ponieważ używasz czterech spacji, ale ponieważ SE automatycznie je rozszerza. Jeśli tak nie jest, możesz zmienić wszystkie spacje na tabulatory lub pojedyncze spacje na -9 bajtów.
Pozew funduszu Moniki z
@Quelklef Meta zabrania przyjmowania dodatkowych parametrów.
mbomb007
1

Perl 53 52

Obejmuje +1 za -p

for($i=0;$i<length;){$i=(s/(.).{$i}\1/\1/)?0:$i+1;}

Wypróbuj na ideone .

Riley
źródło
1

Mathematica, 101 bajtów

NestWhile[i=0;StringReplace[#,a_~~_~RepeatedNull~i++~~a_:>a,1]&,#,SameQ,2,ByteCount@#]&~FixedPoint~#&

Powinien być sposób na skrócenie tego ...

JungHwan Min
źródło
1

PHP, 90 bajtów

for($s=$argv[$c=1];$s[$i=++$i*!$c];)$s=preg_replace("#(.).{{$i}}\\1#","$1",$s,1,$c);echo$s;

lub 92 bajtów

for($s=$argv[1];$s[$i];$i=++$i*!$c)$s=preg_replace("#(.).{".+$i."}\\1#","$1",$s,1,$c);echo$s;   
Jörg Hülsermann
źródło
1
1) pierwsza wersja: +$izamiast $i+=0(-2). 2) forzamiast pętli whilemożna zapisać dwa bajty i pozwolić usunąć nawiasy (-4). 3) $i=++$i*!$czamiast $i=$c?0:$i+1(-1). 4) \\2nie jest potrzebne, usuń nawiasy (-2). 5) Możesz zezwolić na ograniczenie 9zamiast 1prędkości (+0)
Titus
@Titus bardzo dobre pomysły. Nie widziałem tego Dziękuję
Jörg Hülsermann
Teraz, gdy znów myślę ... +$inie działa w każdym przypadku. Spróbować hammer. PHP nie narzeka na puste nawiasy klamrowe w wyrażeniu regularnym; ale nie pasuje tak, jak chciałem. Nawiasem mówiąc: liczę 91, a nie 90. Ale spróbuj nowego 1)for($s=$argv[$c=1];$s[$i=++$i*!$c];)
Tytusa
@Titus Tak, wrócę do $i+=0i spróbuję później. Co znaczy młot?
Jörg Hülsermann
@Titus w porządku ten sam problem, puzzleczy coś w tym stylu, (.)//1ale jest w porządku z twoją propozycją lub$i´=0
Jörg Hülsermann
1

Rubinowy, 75 64 57 bajtów

(56 bajtów kodu + popcja wiersza poleceń).

Używanie interpolacji ciągów w wyrażeniu regularnym do kontrolowania długości dopasowywanych dopasowań.

i=0
~/(.).{#{i}}\1/?sub($&,$1)&&i=0: i+=1while i<$_.size

Test:

$ ruby -p condense.rb <<< fnabnfun
fun
daniero
źródło
1

Haskell , 97 88 bajtów

(0?)
(a:s)!(b:t)|a==b=a:t|1<3=a:s!t
s!_=s
m?s|length s<m=s|a<-s!drop m s=sum[m+1|a==s]?a

Wypróbuj online!


Stara 97 bajtowa wersja:

(a:s)!(b:t)|a==b=a:t|1<3=a:s!t
s!_=s
m?s|length s==m=s|a<-s!drop m s=(last$0:[m+1|a==s])?a
c=(0?)

Wypróbuj na ideone .

Wyjaśnienie:

(a:s)!(b:t)|a==b = a:t         --perform condensation
           |1<3  = a:s!t       --recursively compare further
 s   ! _         = s           --no condensation performed

(!)Pełni funkcję jednego n kondensacji przy podawaniu raz cały łańcuch a raz z pierwszych N znaków, na przykład usuwane abcdbei cdbedla 2-kondensacji rekurencyjnie przez porównanie tych dwóch głównych postaci.

m?s|length s==m   = s         --stop before performing length-s-condensation
   |a <- s!drop m s           --a is the m-condensation of s
    = (last$0:[m+1|a==s])?a   --disguised conditional:
                              -- if a==s       if the m-condensation did not change s
                              -- then (m+1)?a  then perform m+1-condensation
                              -- else 0?a      else restart with a 0-condensation

c=(0?)                        -- main function, initialise m with 0
Laikoni
źródło