Praming Puzles & Colf: condenser une chaîne

25

Ayant passé un peu de temps sur ce site, j'en suis venu à apprécier des choses aussi courtes que possible. C'est peut-être la raison pour laquelle je suis récemment offensé par les chaînes contenant les mêmes caractères plus d'une fois. Votre travail consiste à écrire une fonction ou un programme qui condense une chaîne donnée selon les règles suivantes:

  • Commencez avec une condensation 0 , c'est-à-dire recherchez la première paire (la plus à gauche) des mêmes caractères avec 0 autres caractères entre eux. Si une telle paire est trouvée, supprimez l'un des deux caractères et redémarrez l'algorithme en effectuant une autre condensation 0 . Si aucune de ces paires n'est trouvée, passez à l'étape suivante. Exemples:
    programming-C0-> programing
    aabbcc-C0-> abbcc
    test-C0->test

  • Ensuite, effectuez une condensation 1 , c'est-à-dire recherchez la première paire de mêmes caractères avec 1 autre caractère entre eux. Si une telle paire est trouvée, supprimez l'un d'eux et tous les caractères entre eux et redémarrez avec une condensation 0 . Si aucune de ces paires n'est trouvée, passez à l'étape suivante. Exemples:
    abacac-C1-> acac
    java-C1->ja

  • Continuez avec une 2-condensation et ainsi de suite jusqu'à une n-condensation avec n étant la longueur de la chaîne d'origine, à chaque redémarrage après une condensation supprimée quelques lettres. Exemples:
    programing-C2-> praming
    abcdafg-C3->afg

La chaîne résultante est appelée condensée et contient chaque caractère au plus une fois.


Contribution:

Une chaîne en minuscules de caractères ascii imprimables.

Sortie:

La chaîne condensée selon les règles ci-dessus.

Exemples:

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

Exemples détaillés pour clarifier le fonctionnement de l'algorithme:

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

Votre approche ne doit pas implémenter l'algorithme d'en haut tant que votre solution et l'algorithme renvoient la même sortie pour toutes les entrées autorisées. Il s'agit d'un défi de .


Merci à @Linus pour les commentaires utiles du bac à sable!

Laikoni
la source
Le cas de test de @MartinEnder Riley est toujours nécessaire, car c'est le seul sur lequel ma solution Retina ne fonctionne pas.
mbomb007
@ mbomb007 Ah, je vois. Bon point.
Martin Ender
La chaîne d'entrée contiendra-t-elle jamais des caractères non imprimables comme des espaces?
mbomb007
@ mbomb007 Non, supposer que les caractères ascii imprimables sont corrects.
Laikoni
@ mbomb007 Cependant, autant que je sache, un espace est considéré comme un caractère ascii imprimable, par exemple ici .
Laikoni

Réponses:

6

JavaScript (ES6), 74 octets

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
la source
Très agréable, plus court que ce à quoi j'aurais pensé.
ETHproductions du
5

Perl, 38 31 30 29 octets

Cela devrait laisser les langues autres que le golf loin derrière ...

-1 pour $-[0]remercier Riley

-1 pour @{-}remercier Dada

Comprend +1 pour -p

Donnez votre avis sur STDIN

condense.pl:

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

Cette version de 27 octets devrait fonctionner mais ce n'est pas le cas car perl ne s'interpole pas @-dans une expression régulière (voir /programming/39521060/why-are-etc-not-interpolated-in-strings )

#!/usr/bin/perl -p
s/(.)\K.{@-}\1// while/./g
Ton Hospel
la source
Comment fonctionne la @{\@-}pièce? Je pensais @-tenir les index de chaque correspondance, alors comment cela "compte" à chaque itération. De plus, si vous imprimez @{\@-}avant et après chaque substitution, il n'en imprime que 1 ou 2.
Riley
1
@Riley Le /./gprogresse de 1 dans la chaîne à chaque fois, sauf lorsque la chaîne change, puis il est réinitialisé à 0. Si vous imprimez @-après le /./gmais avant le, s///vous le verrez augmenter (utilisez un test où la chaîne restante est suffisamment grande)
Ton Hospel
L'impression $-[0]donne les chiffres que j'attendrais. Agit-il @{\@-}comme à $-[0]cause du contexte d'expression régulière, mais pas lors de l'impression pour une raison quelconque? $-[0]est un octet plus court que @{\@-}s'ils sont identiques.
Riley
"@{\@-}"n'est pas la même chose que @{\@-}(sans ").
Riley
@Riley Non, mais "@{\@-}"c'est la même chose que "@-". Et cela devrait également être vrai pour une substitution d'expression régulière, mais ce n'est pas le cas. Simultanément $-[0]devrait fonctionner mais ne fonctionne pas. PS: Vous aviez probablement en quelque sorte un contexte scalaire appliqué @-lorsque vous avez fait votre impression, donc vous avez toujours 1 ou 2
Ton Hospel
3

CJam , 35 octets

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

Essayez-le en ligne!


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

Vous pouvez voir les condensations individuelles en inséranted

Linus
la source
2

Python 2, 117 104 101 octets

Effectuez récursivement les remplacements nécessaires. Je construis le regex dynamiquement.

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)

Essayez-le en ligne

mbomb007
la source
Les deux lignes de retour peuvent être condensées en return i>len(t) and t or s!=t and f(t) or f(t,i+1)un net de -4 octets
Quelklef
2 octets return t if i>len(t)else s!=t and f(t)or f(t,i+1))
supplémentaires
Encore plus e=s==t;return i>len(t)and t or f(t,i*e+e), vous pouvez supprimer le i=0dans la définition de la fonction, mais vous devrez appeler avec 0 start.
Quelklef
Je vais supposer que les quatre espaces ne sont pas là parce que vous utilisez quatre espaces mais parce que SE les agrandit automatiquement. Si ce n'est pas le cas, vous pouvez changer tous vos espaces en tabulations ou en un seul espace pour -9 octets.
Fund Monica's Lawsuit
@Quelklef La méta interdit de prendre des paramètres supplémentaires.
mbomb007
1

Perl 53 52

Comprend +1 pour -p

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

Essayez-le sur ideone .

Riley
la source
1

Mathematica, 101 octets

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

Il devrait y avoir un moyen de raccourcir cela ...

JungHwan Min
la source
1

PHP, 90 octets

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

ou 92 octets

for($s=$argv[1];$s[$i];$i=++$i*!$c)$s=preg_replace("#(.).{".+$i."}\\1#","$1",$s,1,$c);echo$s;   
Jörg Hülsermann
la source
1
1) première version: +$iau lieu de $i+=0(-2). 2) forboucle au lieu de whilepeut économiser deux octets et permettre de supprimer les curlys (-4). 3) $i=++$i*!$cau lieu de $i=$c?0:$i+1(-1). 4) \\2n'est pas nécessaire, supprimez les parenthèses (-2). 5) Vous pouvez autoriser la limite 9au lieu de la 1vitesse (+0)
Titus
@Titus très bonnes idées. Je n'avais pas vu ce merci
Jörg Hülsermann
Maintenant que je pense encore une fois ... +$ine fonctionne pas dans tous les cas. Essayez hammer. PHP ne se plaint pas des accolades vides dans l'expression régulière; mais cela ne correspond pas comme souhaité. Au fait: je compte 91, pas 90. Mais essayez le nouveau 1)for($s=$argv[$c=1];$s[$i=++$i*!$c];)
Titus
@Titus Oui, en effet, je reviens $i+=0et j'essaierai votre proposition plus tard. Que veut dire marteau?
Jörg Hülsermann
@Titus ok le même problème si puzzleou quelque chose d'autre, (.)//1mais il est d'accord avec votre proposition ou le$i´=0
Jörg Hülsermann
1

Rubis, 75 64 57 octets

(56 octets de code + poption de ligne de commande.)

Utilisation de l'interpolation de chaînes à l'intérieur d'une expression régulière pour contrôler la longueur des correspondances qui sont remplacées.

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

Tester:

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

Haskell , 97 88 octets

(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

Essayez-le en ligne!


Ancienne version de 97 octets:

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

Essayez-le sur ideone .

Explication:

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

La (!)fonction effectue une n-condensation lorsqu'elle reçoit une chaîne une fois entière et une fois avec les n premiers caractères supprimés, par exemple abcdbeet cdbepour une 2-condensation, en comparant récursivement les deux premiers caractères.

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
la source