Rétrécir une chaîne numérique

12

Étant donné une chaîne de 1et 2de n'importe quelle longueur, écrivez du code (ne doit plus être une fonction , tout ira bien) qui calcule le nombre d'étapes nécessaires pour réduire la chaîne à une forme finale, en suivant ce critère:

Si votre chaîne est 112112, cela signifie que vous devez imprimer un 1, deux 1 et un 2, comme ceci: 1112. Lorsque vous effectuerez à nouveau l'opération, vous devrez imprimer un 1 et un 2. Vous obtenez 12. Ensuite, vous imprimez un 2, obtenant 2. C'est une forme finale, car cette chaîne ne va plus changer. Votre code sera affiché 3, car vous avez eu besoin de 3 étapes pour accéder au formulaire final.

Autres règles

  • Si la chaîne a une longueur inégale, le dernier numéro reste intact.

  • Chaque chaîne qui ne peut plus changer (comme 222222) est considérée comme une forme finale.

  • Vous ne pouvez utiliser aucune source externe.

  • Votre code doit fonctionner avec chaque chaîne de 1et 2.

  • Le code le plus court gagne, car il s'agit du code-golf.

  • Votre code devrait imprimer à chaque étape.

  • Chaque méthode d'entrée ira bien.

Exemples

Input >> 122122122121212212

Your code has to print:
211222111111222
11222111222
122111222
2111222
111222
1222
222
Steps:7 (you can omit the "Steps")
---- ---- ---- ----
Input >> 22222221

Your code has to print:
22222211
2222221
2
---- ---- ---- ----
Input >> 2222

Your code has to print:
0

EDIT: Fortement édité. Désolé pour ça.

Vereos
la source
3
"Si votre chaîne est 112112, cela signifie que vous devez imprimer un 1, deux 1 et un 2, comme ceci: 1112." Je ne comprends pas.
Fabinout
7
Essayez de le lire à haute voix. C'est "un un", "deux un" et "un deux". Je veux dire, "1 fois 1", "2 fois 1" et "1 fois 2".
Vereos
5
Si les expressions régulières ne sont "même pas utiles", pourquoi les interdisez-vous?
JB
1
Suppression de la restriction d'expression régulière.
Vereos
1
@ProgramFOX "1 une, deux 1, et un 2": 1 11 2. Tous les deux nombres sont une paire: le premier nombre de la paire indique combien de fois rendre le deuxième nombre de la paire. Tout dernier chiffre impair sans partenaire de paire est rendu tel quel.
apsillers

Réponses:

7

Ruby 1.9+, 73 caractères

Je vois la règle sans regex comme idiote et arbitraire, alors voici une solution basée sur les regex malveillantes:

gets
($.+=1;puts$_.gsub!(/(.)(.)/){$2*$1.to_i})until~/^(22)*[12]?$/
p~-$.

Essai:

$ ruby 21.rb <<< 122122122121212212
211222111111222
11222111222
122111222
2111222
111222
1222
222
7

La dernière ligne est le nombre d'étapes.

Edit: la restriction des regex a été supprimée par Vereos.

daniero
la source
3

C - 156 154

Mon premier golf de code ici!

f(char*s,c){puts(s);char*a=s,*b=s,m=50,x,y;while(*a){
x=*a++;y=*a++;if(y)m&=x&y;*b++=y?:x;x-49?*b++=y:(*b=0);}
*b=*a;return m/50?printf("%i",c),c:f(s,c+1);}

Tester:

char c[] = "12211122211222221";
f(c,0);

Production:

12211122211222221
21112211222221
111221222211
121122221
21222211
1122221
122221
22211
22111
2211
221
10
tia
la source
2

GolfScript: 69 caractères

0\{\)\.p.[]\{~10base{.,1>{(\(@\{''+*}++~@\+\.}{~+0.}if}do;}~.@=!}do;(

Chaque itération de la boucle interne trouve les 2 premiers nombres de la chaîne et les utilise pour former un bloc du formulaire {num1 num2 '' + *}. Lorsque ce bloc est évalué, nous obtenons la lecture souhaitée de ces nombres. Répétez cette opération jusqu'à ce qu'il n'y ait plus de caractères. Ensuite, répétez cette boucle tout en gardant une trace du nombre d'itérations et d'impression.

Échantillon:

echo '12211122211222221' | ruby golfscript.rb g.gs
"12211122211222221"
"21112211222221"
"111221222211"
"121122221"
"2122221"
"1122221"
"122221"
"22211"
"22111"
"2211"
"221"
10
Ben Reich
la source
2

Python - 126

def f(s):
 j=0
 while 1:
    n="";i=0
    for c in s:n+=c*i;i=[int(c),0][i>0]
    if i:n+=`i`
    if s==n:break
    s=n;print s;j+=1
 print j

Cela n'imprime pas la valeur d'entrée. Si nécessaire, déplacez-vous print s;vers la droite avantn="";

Remarque: vous avez dit "fonction", c'est donc une fonction. Voici une version qui n'est pas une fonction (127 caractères):

s=raw_input();j=0
while 1:
    n="";i=0
    for c in s:n+=c*i;i=[int(c),0][i>0]
    if i:n+=`i`
    if s==n:break
    s=n;print s;j+=1
print j

(Si je peux demander à l'utilisateur de coller le nombre, alors 118 (coller les données entre les guillemets sur la première ligne)):

s="";j=0
while 1:
    n="";i=0
    for c in s:n+=c*i;i=[int(c),0][i>0]
    if i:n+=`i`
    if s==n:break
    s=n;print s;j+=1
print j

Exemple d'exécution:

211222111111222
11222111222
122111222
2111222
111222
1222
222
7

En prime, chacune de ces solutions fonctionne pour les chaînes contenant des nombres plus importants (jusqu'à 9), mais certaines chaînes produisent des sorties de plus en plus grandes (par exemple, 99)

Justin
la source
1

JavaScript, 107

(nécessite le support de la fonction flèche, par exemple comme dans Firefox)

for(p=prompt,s=p(),k=0;r=s.match(/.?.?/g).map(a=>a>2?a[1]+(a<13?'':a[1]):a).join(''),p(s),r!=s;s=r)k++;p(k)
  • s est la chaîne d'entrée

  • À chaque tour, nous utilisons l'expression régulière .?.?pour exploser sen un tableau de chaînes à deux caractères, puis mapces chaînes dans leurs formes réduites et coller le tableau ensemble

  • r stocke le résultat du cycle en cours pour comparaison avec le précédent s

  • k est le compteur rond

  • Nous abusons horriblement prompt(alias de p) comme mécanisme d'entrée et de sortie, car il peut présenter un message à l'utilisateur


for(p=prompt,s=p(),k=0;
    r=s.match(/.?.?/g).map(
        a=>
            a>2?                     // if a is more than one char
                a[1]+(a<13?'':a[1])  // double the second char if the first char is 2
               :a                    // if not two chars, return a
    ).join(''),                      // glue new array together
     p(s),                           // print s
     r!=s;                           // test if string has changed
    s=r)
        k++;
p(k)
absides
la source
1

Perl - 50 (+2) octets

$a-=print while"$_"ne(s/(.)(.)/$2x$1/ge,$_);$_=-$a

Nécessite des -plcommutateurs de ligne de commande.

Exemple d'utilisation:

$ more in.dat
122122122121212212

$ perl -pl rev-count.pl < in.dat
211222111111222
11222111222
122111222
2111222
111222
1222
222
7

$ more in.dat
22222221

$ perl -pl rev-count.pl < in.dat
22222211
2222221
2

$ more in.dat
2222

$ perl -pl rev-count.pl < in.dat
0
primo
la source
1

PHP, 240

<?php
$s=$_GET['i'];$h=$s;for($t=1;$h!=r($h);$t++){echo$h.'<br>';$h=r($h);}echo r($s)==$s?0:$h.'<br>'.$t;function r($c){for($i=0;$i<strlen($c)-1;$i+=2){$s.=$c[$i]==1?$c[$i+1]:$c[$i+1].$c[$i+1];if($i+3==strlen($c))$s.=$c[$i+2];}return$s;}?>

Exemple: http://skyleo.de/codegolf.php?i=211222111111222

211222111111222
11222111222
122111222
2111222
111222
1222
222
7

Je suis un peu mauvais au codegolf ._. Peut-être que je ne devrais pas utiliser uniquement Java et PHP (et je devrais penser plus compliqué)

Leo Pflug
la source
1
CodeGolf ne consiste pas à trouver la solution la plus compliquée, mais plutôt la plus simple.
primo
Vous n'avez pas vraiment besoin de le faire str_splitcar vous pouvez accéder à des caractères individuels dans une chaîne comme un tableau en PHP.
Gareth
Oui, après un certain temps, j'ai pensé cela moi-même, mais j'étais trop paresseux pour le modifier. Mais maintenant je l'ai changé.
Leo Pflug
0

R, 158

s=utf8ToInt(scan(,""))-48;i=0;while(any(!!s-2)){t=(a<-sum(s|T))%%2;u=s[seq(a-t)];cat(s<-c(rep(u[c(F,T)],u[c(T,F)]),s[a*t]),"\n",sep="");i=i+1};cat("Steps:",i)

Exemple:

122122122121212212

211222111111222
11222111222
122111222
2111222
111222
1222
222
Steps: 7
Sven Hohenstein
la source
0

MATHEMATICA, 117

s="122122122121212212";
Grid@FixedPointList[(Partition[#,2,2,1,{}]/.{{1,1}->{1},{1,2}->{2},{2,1}->{1,1}}//Flatten)&,FromDigits/@Characters@s]

122122122121212212
211222111111222
11222111222
122111222
2111222
111222
1222
222
222
Murta
la source
0

POWERSHELL, 2

Basé sur la réponse de Vereos "Vous pouvez utiliser n'importe quelle méthode de saisie pour raccourcir votre code" à ma question dans les commentaires de l'OP, le script suivant obtient le résultat:

$a

Exemple d'exécution pour "122122122121212212":

# Input method is to assign answer to $a:
$a = @"
211222111111222
11222111222
122111222
2111222
111222
1222
222
Steps: 7
"@

# Execute script
$a

# Answer follows:
211222111111222
11222111222
122111222
2111222
111222
1222
222

Évidemment, ce n'est pas une entrée sérieuse - son but est d'illustrer mon point de vue que permettre à n'importe quelle méthode d'entrée peut banaliser le code réel nécessaire pour donner la réponse. Par conséquent, la méthode d'entrée doit être spécifiée plus rigoureusement.

user2460798
la source
0

J, 41 caractères

En tant que fonction (ew parens! Pas très content d'eux):

(,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:)
Vue éclatée
                _2&(            )\          NB. on non-overlapping 2-grams:
                       (      )/            NB.   insert between the two chars:
                        ".@[                NB.     read left operand ([) as a number
                            #]              NB.     and repeat right this many times,
                    <@(           )         NB.   then put it in a box
            ([:;                   )        NB. open and concatenate the boxes
           (                        ^:a:)   NB. repeat until fixpoint (keeping intermediates)
        }:@                                 NB. drop first element (the input)
(,":@#)@                                    NB. append length of array (# steps)
Exemple d'exécution
   (,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:) '1121121'
1121121
11121  
121    
21     
11     
5      
   (,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:) '122122122121212212'
122122122121212212
211222111111222   
11222111222       
122111222         
2111222           
111222            
1222              
7                 
Luciole
la source
0

Perl, 107 caractères

L'autre code Perl bat clairement cela, mais pour ce qu'il vaut, le voici. J'ai utilisé le commutateur -l au prix d'un caractère supplémentaire:

$_=<>;while(1){$l=$_;$_=join"",map{($a,$b)=split//;$b?$b x$a:$a}grep/./,split/(..?)/;last if$l eq$_;print}

Une version plus lisible de cela:

$x = <>; while(1) { $l = $x; $x = join "", map{ ($a,$b) = split//, $_; $b ? $b x $a: $a } grep /./, split /(..?)/, $x; last if $l eq $x; print $x}
skibrianski
la source