Praming Puzles & Colf: Verdichten Sie eine Schnur

25

Nachdem ich einige Zeit auf dieser Seite verbracht habe, habe ich es genossen, Dinge so kurz wie möglich zu halten. Das mag der Grund sein, warum ich in letzter Zeit von Strings beleidigt bin, die dieselben Zeichen mehr als einmal enthalten. Ihre Aufgabe ist es, eine Funktion oder ein Programm zu schreiben, das einen bestimmten String nach folgenden Regeln komprimiert :

  • Beginnen Sie mit einer 0-Verdichtung , dh suchen Sie nach dem ersten (am weitesten links stehenden) Paar derselben Zeichen mit 0 anderen Zeichen dazwischen. Wenn ein solches Paar gefunden wird, entfernen Sie eines der beiden Zeichen und starten Sie den Algorithmus neu, indem Sie eine weitere 0-Kondensation durchführen . Wird kein solches Paar gefunden, fahren Sie mit dem nächsten Schritt fort. Beispiele:
    programming-C0-> programing
    aabbcc-C0-> abbcc
    test-C0->test

  • Führen Sie dann eine 1-Verdichtung durch , dh suchen Sie nach dem ersten Zeichenpaar mit 1 weiteren Zeichen dazwischen. Wenn ein solches Paar gefunden wird, entfernen Sie eines von ihnen und alle Zeichen zwischen ihnen und starten Sie mit einer 0-Verdichtung neu . Wird kein solches Paar gefunden, fahren Sie mit dem nächsten Schritt fort. Beispiele:
    abacac-C1-> acac
    java-C1->ja

  • Fahren Sie mit einer 2-Kondensation fort und so weiter bis zu einer n-Kondensation, wobei n die Länge der ursprünglichen Zeichenfolge ist. Bei jedem Neustart nach einer Kondensation werden einige Buchstaben entfernt. Beispiele:
    programing-C2-> praming
    abcdafg-C3->afg

Die resultierende Zeichenfolge heißt komprimiert und enthält jedes Zeichen höchstens einmal.


Eingang:

Eine Kleinbuchstabenfolge aus druckbaren ASCII-Zeichen.

Ausgabe:

Die verkürzte Zeichenfolge gemäß den obigen Regeln.

Beispiele:

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

Detaillierte Beispiele zur Verdeutlichung der Funktionsweise des Algorithmus:

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

Ihr Ansatz muss den Algorithmus nicht von oben implementieren, solange Ihre Lösung und der Algorithmus für alle zulässigen Eingaben dieselbe Ausgabe zurückgeben. Dies ist eine Herausforderung.


Vielen Dank an @Linus für hilfreiche Sandbox-Kommentare!

Laikoni
quelle
@MartinEnder Rileys Testfall ist immer noch notwendig, da er der einzige ist, an dem meine Retina-Lösung nicht funktioniert.
mbomb007
@ mbomb007 Ah, ich verstehe. Guter Punkt.
Martin Ender
Enthält die Eingabezeichenfolge jemals nicht druckbare Zeichen wie Leerzeichen?
mbomb007
@ mbomb007 Nein, es ist in Ordnung, nur druckbare ASCII-Zeichen anzunehmen.
Laikoni
@ mbomb007 Soweit ich weiß, wird ein Leerzeichen jedoch als druckbares ASCII-Zeichen angesehen, z . B. hier .
Laikoni

Antworten:

6

JavaScript (ES6), 74 Byte

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
quelle
Sehr schön, kürzer als ich gedacht hätte.
ETHproductions
5

Perl, 38 31 30 29 Bytes

Das sollte die nicht-golfenden Sprachen weit hinter sich lassen ...

-1 für $-[0]danke an Riley

-1 für @{-}danke an Dada

Beinhaltet +1 für -p

Geben Sie eine Eingabe für STDIN ein

condense.pl:

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

Diese 27-Byte-Version sollte funktionieren, funktioniert jedoch nicht, da Perl nicht @-in regulären Ausdrücken interpoliert (siehe https://stackoverflow.com/questions/39521060/why-are-etc-not-interpolated-in-strings ).

#!/usr/bin/perl -p
s/(.)\K.{@-}\1// while/./g
Tonne Hospel
quelle
Wie funktioniert das @{\@-}Teil? Ich dachte @-, die Indizes jedes Matches werden festgehalten, also wie wird es bei jeder Iteration "hochgezählt"? Wenn Sie @{\@-}vor und nach jeder Ersetzung drucken, wird immer nur 1 oder 2 gedruckt.
Riley
1
@Riley Die /./gZeichenfolge wird jedes Mal um 1 in der Zeichenfolge fortgeschrieben, außer wenn sich die Zeichenfolge ändert. Sie wird dann auf 0 zurückgesetzt. Wenn Sie @-nach der Zeichenfolge, /./gjedoch vor der Zeichenfolge drucken, wird die Zeichenfolge nach oben verschoben s///(verwenden Sie einen Test, bei dem die verbleibende Zeichenfolge groß genug ist).
Ton Hospel
Das Drucken $-[0]gibt die Zahlen, die ich erwarten würde. Handelt es @{\@-}sich wie $-[0]aufgrund des Regex-Kontexts, aber aus irgendeinem Grund nicht beim Drucken? $-[0]ist ein Byte kürzer als @{\@-}wenn sie gleich sind.
Riley
"@{\@-}"ist nicht dasselbe wie @{\@-}(ohne ").
Riley
@Riley Nein, ist aber "@{\@-}"das gleiche wie "@-". Dies sollte auch für einen regulären Austausch gelten, ist es aber nicht. Sollte genauso $-[0]funktionieren, tut es aber nicht. PS: Sie hatten wahrscheinlich irgendwie skalaren Kontext, @-als Sie Ihren Druck gemacht haben, so dass Sie immer 1 oder 2
Ton Hospel
3

CJam , 35 Bytes

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

Probieren Sie es 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

Sie können die einzelnen Kondensationen durch Einfügen sehened

Linus
quelle
2

Python 2, 117 104 101 Bytes

Führen Sie die erforderlichen Ersetzungen rekursiv durch. Ich baue die Regex dynamisch.

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)

Probieren Sie es online aus

mbomb007
quelle
Die beiden Rückleitungen können zu return i>len(t) and t or s!=t and f(t) or f(t,i+1)einem Netz von -4 Bytes zusammengefasst werden
Quelklef
Weitere 2 Bytes können durch Ändern vonreturn t if i>len(t)else s!=t and f(t)or f(t,i+1))
Quelklef
Noch mehr nach e=s==t;return i>len(t)and t or f(t,i*e+e)und nach können Sie die i=0in der Funktionsdefinition entfernen , aber Sie müssen mit 0 Start aufrufen.
Quelklef
Ich gehe davon aus, dass die vier Leerzeichen nicht vorhanden sind, weil Sie vier Leerzeichen verwenden, sondern weil SE sie automatisch erweitert. Ist dies nicht der Fall, können Sie alle Ihre Leerzeichen entweder in Tabulatoren oder in ein einzelnes Leerzeichen für -9 Byte ändern.
Fund Monica's Lawsuit
@Quelklef Das Meta verbietet die Verwendung zusätzlicher Parameter.
mbomb007
1

Perl 53 52

Beinhaltet +1 für -p

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

Probiere es auf ideone aus .

Riley
quelle
1

Mathematica, 101 Bytes

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

Es sollte einen Weg geben, dies zu verkürzen ...

JungHwan min
quelle
1

PHP, 90 Bytes

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

oder 92 Bytes

for($s=$argv[1];$s[$i];$i=++$i*!$c)$s=preg_replace("#(.).{".+$i."}\\1#","$1",$s,1,$c);echo$s;   
Jörg Hülsermann
quelle
1
1) erste Version: +$ianstelle von $i+=0(-2). 2) forSchleife statt whilekann zwei Bytes speichern und das Entfernen von Locken (-4) ermöglichen. 3) $i=++$i*!$canstelle von $i=$c?0:$i+1(-1). 4) \\2ist nicht erforderlich, entfernen Sie die Klammern (-2). 5) Sie können das Tempolimit 9anstelle von 1(+0) zulassen
Titus
@ Titus sehr gute Ideen. Ich hatte dieses Dankeschön nicht gesehen
Jörg Hülsermann
Jetzt wo ich nochmal +$iüberlege ... funktioniert nicht in jedem Fall. Versuchen Sie es hammer. PHP beschwert sich nicht über die leeren Klammern in der Regex; aber es passt nicht wie gewünscht. Übrigens: Ich zähle 91, nicht 90. Aber probieren Sie das neue 1)for($s=$argv[$c=1];$s[$i=++$i*!$c];)
Titus
@Titus Ja in der Tat gehe ich zurück $i+=0und werde deinen Vorschlag später versuchen. Was heißt mit Hammer?
Jörg Hülsermann
@Titus okay, das gleiche Problem, wenn puzzleoder so ähnlich, (.)//1aber es ist in Ordnung mit Ihrem Vorschlag oder der$i´=0
Jörg Hülsermann
1

Ruby, 75 64 57 Bytes

(56 Byte Code + pBefehlszeilenoption.)

Verwenden der Zeichenfolgeninterpolation in einem regulären Ausdruck, um die Länge der ersetzten Übereinstimmungen zu steuern.

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

Prüfung:

$ ruby -p condense.rb <<< fnabnfun
fun
daniero
quelle
1

Haskell , 97 88 Bytes

(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

Probieren Sie es online!


Alte 97-Byte-Version:

(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?)

Probiere es auf ideone aus .

Erläuterung:

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

Die (!)Funktion führt eine n-Kondensation durch, wenn eine Zeichenfolge einmal ganz und einmal mit den ersten n entfernten Zeichen angegeben wird, z. B. abcdbeund cdbefür eine 2-Kondensation, indem die beiden führenden Zeichen rekursiv verglichen werden.

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
quelle