Längencodiere einen String

18

Angenommen, wir verwenden die folgenden Regeln, um eine einzelne Zeichenfolge aus einer anderen Zeichenfolge zu ziehen, die nur ASCII-druckbare Zeichen enthält und als *-string bezeichnet wird. Wenn die Zeichenfolge ausgeht, bevor der Prozess angehalten wird, ist dies ein Fehler, und das Ergebnis des Prozesses ist in diesem Fall undefiniert:

  1. Beginnen mit d=1, s=""
  2. Immer wenn Sie auf ein *treffen, multiplizieren Sie dmit 2. Immer wenn Sie auf ein anderes Zeichen treffen, verketten Sie es bis zum Ende sund subtrahieren 1 von d. Wenn jetzt d=0, halt an und kehre zurücks

Definierte Beispiele :

d->d
769->7
abcd56->a
*abcd56->ab
**abcd56->abcd
*7*690->769
***abcdefghij->abcdefgh

Undefinierte Beispiele : (Beachten Sie, dass die leere Zeichenfolge auch eine davon sein würde.)

*7
**769
*7*
*a*b
*

Ihre Aufgabe ist es, eine Zeichenfolge zu nehmen und die kürzeste *Zeichenfolge zurückzugeben, die diese Zeichenfolge erzeugt.

Programmbeispiele :

7->7
a->a
ab->*ab
abcd->**abcd
769->*7*69

Ihr Programm sollte alle Zeichenfolgen verarbeiten, die mindestens ein Zeichen und nur Nicht- *ASCII-druckbare Zeichen enthalten. Sie können niemals Zeichenfolgen zurückgeben, für die der Prozess undefiniert ist, da sie per Definition keine Zeichenfolgen erzeugen können.

Es gelten Standard-Regelungslücken und I / O-Regeln.

Frikative Melone
quelle
Können wir annehmen, dass die Eingabe keine enthält *?
Luis Mendo
3
@ DonMuesli "nur nicht * ASCII druckbare Zeichen"
FryAmTheEggman

Antworten:

3

Pyth ( 36 27 Bytes)

Danke an Jakube für die 9 Byte Verbesserung! Derzeit nicht so gut wie die Antwort von Schlammfischen , aber wie auch immer

KlzJ1VzWgKyJp\*=yJ)pN=tK=tJ

Test Suite

Übersetzung in Python:

                            | z=input() #occurs by default
Klz                         | K=len(z)
   J1                       | J=1
     Vz                     | for N in z:
       WgKyJ                |   while K >= J*2:
            p\*             |     print("*", end="")
               =yJ          |     J=J*2
                  )         |     #end inside while
                   pN       |   print(N, end="")
                     =tK    |   K=K-1
                        =tJ |   J=J-1
K Zhang
quelle
1
Muddyfish's scheint gestorben zu sein ...
Rɪᴋᴇʀ
5

JavaScript (ES6), 61 Byte

f=(s,d=2)=>s?d>s.length?s[0]+f(s.slice(1),d-2):'*'+f(s,d*2):s

Rekursive Funktion, die Folgendes ausführt:

  • Wenn dkleiner oder gleich der verbleibenden Zeichenfolgenlänge geteilt durch 2 ist:

    *An Ausgabe anhängen und dmit 2 multiplizieren

  • Sonst:

    Verschieben Sie den String und hängen Sie ihn an die Ausgabe an. Subtrahieren Sie 1 von d.

Sehen Sie es in Aktion:

f=(s,d=2)=>s?d>s.length?s[0]+f(s.slice(1),d-2):'*'+f(s,d*2):s

input.oninput = e => output.innerHTML = f(input.value);
<input id="input" type="text"/>
<p id="output"></p>

George Reith
quelle
1
Sparen Sie 2 Bytes, indem Sie mit dem doppelten Wert von d und einem weiteren Byte arbeiten, indem Sie die Bedingung umkehren:f=(s,d=2)=>s?d>s.length?s[0]+f(s.slice(1),d-2):'*'+f(s,d*2):s
Neil,
4

Pyth, 29 27 ( Festgestellt, gebrochen) 27 26 25 Bytes

+*\*sKllzXJ-^2.EKlzz?J\*k

Erklärung zu kommen.

Test Suite

Blau
quelle
2

C 125 Bytes

main(int q,char**v){++v;int i=1,n=strlen(*v);while(n>(i*=2))putchar(42);for(i-=n;**v;--i,++*v)!i&&putchar(42),putchar(**v);}

Dies nutzt das sehr regelmäßige Muster der Sternpositionen aus, um die richtige Codierung auszugeben. Anfangs habe ich eine rekursive Bruteforce-Lösung ausprobiert, aber im Nachhinein hätte es offensichtlich sein müssen, dass es eine einfachere mathematische Lösung gab.

Grundsätzlich haben Sie immer 2^floor(log_2(length))Sterne am Anfang Ihrer Ausgabe und einen letzten Stern nach den 2^ceil(log_2(length)) - lengthZeichen (wenn dies mindestens 1 Zeichen ergibt).

Die (leicht) ungolfed Version ist wie folgt

main(int q,char**v){
   ++v;                         // refer to the first command line argument
   int i=1, n=strlen(*v);       // set up iteration variables

   while(n > (i*=2))            // print the first floor(log2(n)) '*'s
      putchar(42);

   for(i-=n;  **v;  --i, ++*v)  // print the string, and the final '*'
      !i&&putchar(42),putchar(**v);
}
Gordon Bailey
quelle
1

JavaScript (ES6), 88 77 Bytes

f=(s,l=s.length,p=2)=>l<2?s:p<l?"*"+f(s,l,p*2):s.slice(0,p-=l)+"*"+s.slice(p)

Zuerst dachte ich, das abcdemüsste sein, *a**bcdeaber es stellt sich heraus, dass **abc*dedas genauso gut funktioniert. Dies bedeutet, dass die Ausgabe leicht unter Verwendung der führenden Sterne des Bodens (log & sub2; (s.length)) plus eines zusätzlichen Sterns für Zeichenketten konstruiert werden kann, deren Länge keine Potenz von zwei ist.

Bearbeiten: 8 Bytes durch rekursives Berechnen der Anzahl der führenden Sterne gespeichert. Weitere 3 Bytes wurden durch Zeichenfolgen mit Sondergehäusen der Länge 1 gespeichert, sodass Zeichenfolgen mit einer Länge von 2 Potenzen als zusätzlicher führender Stern behandelt werden können.

Neil
quelle
0

Haskell, 68 Bytes

f d[]=""
f d xs|length xs>=d*2='*':f(d*2)xs
f d(x:xs)=x:f(d-1)xs

Genau wie die anderen Antworten. Bei EOF wird eine leere Zeichenfolge ausgegeben. Wenn die verbleibende Länge mehr als das Doppelte beträgt d, geben Sie einen Stern und das Doppelte aus d. Ansonsten geben Sie das nächste Zeichen aus und subtrahieren eines von d.

Ungolfed:

f d (  [])                    = ""
f d (  xs) | length xs >= d*2 = '*' : f (d*2) xs
f d (x:xs)                    =  x  : f (d-1) xs
MathematicalOrchid
quelle