Reducir una cadena numérica

12

Dada una cadena de 1y 2de cualquier longitud, escriba un código (ya no tiene que ser una función , todo estará bien) que calcula cuántos pasos necesita para reducir la cadena a una forma final, siguiendo este criterio:

Si la cadena es 112112, esto significa que se tienen que imprimir a 1, dos 1s y 2, así: 1112. Cuando vuelva a realizar la operación, tendrá que imprimir un 1 y un 2. Obtendrá 12. Luego imprime uno 2, obteniendo 2. Esta es una forma final, ya que esta cadena ya no va a cambiar. Su código saldrá 3, ya que necesita 3 pasos para llegar al formulario final.

Otras reglas

  • Si la cadena tiene una longitud desigual, el último número permanece intacto.

  • Cada cadena que ya no puede cambiar (como 222222) se considera una forma final.

  • No puede usar ninguna fuente externa.

  • Su código debe funcionar con cada cadena de 1y 2.

  • El código más corto gana, ya que es el código de golf.

  • Su código debe imprimir cada paso.

  • Todo método de entrada estará bien.

Ejemplos

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

EDITAR: Muy editado. Lamento mucho eso.

Vereos
fuente
3
"Si su cadena es 112112, esto significa que debe imprimir un 1, dos 1s y un 2, así: 1112". No lo entiendo.
Fabinout
77
Intenta leerlo en voz alta. Es "uno uno", "dos unos" y "uno dos". Quiero decir, "1 vez 1", "2 veces 1" y "1 vez 2".
Vereos
55
Si las expresiones regulares "ni siquiera son útiles", ¿por qué las prohíbe?
JB
1
Se eliminó la restricción de expresiones regulares.
Vereos
1
@ProgramFOX "uno 1, dos 1s, y un 2": 1 11 2. Cada dos números es un par: el primer número del par dice cuántas veces se representa el segundo número en el par. Cualquier dígito impar final sin un par asociado se representa tal cual.
apsillers

Respuestas:

7

Ruby 1.9+, 73 caracteres

Veo la regla de no regex como tonta y arbitraria, así que aquí hay una solución rencorosa basada en regex:

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

Prueba de funcionamiento:

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

La última línea es el número de pasos.

Editar: Vereos ha eliminado la restricción de expresiones regulares.

daniero
fuente
3

C - 156 154

Mi primer código de golf aquí!

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);}

Prueba:

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

Salida:

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

GolfScript: 69 caracteres

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

Cada iteración del bucle interno encuentra los primeros 2 números en la cadena y los usa para formar un bloque del formulario {num1 num2 '' + *}. Cuando se evalúa este bloque, obtenemos la lectura deseada de esos números. Repita esto hasta que no haya más personajes. Luego, repita ese ciclo mientras realiza un seguimiento del número de iteraciones e impresiones.

Muestra:

echo '12211122211222221' | ruby golfscript.rb g.gs
"12211122211222221"
"21112211222221"
"111221222211"
"121122221"
"2122221"
"1122221"
"122221"
"22211"
"22111"
"2211"
"221"
10
Ben Reich
fuente
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

Esto no imprime el valor de entrada. Si es necesario, muévase print s;a la derecha antesn="";

Nota: dijiste "función", así que esta es una función. Aquí hay una versión que no es una función (127 caracteres):

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 puedo hacer que el usuario pegue el número en 118 (pegue los datos entre comillas en la primera línea)):

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

Ejecución de muestra:

211222111111222
11222111222
122111222
2111222
111222
1222
222
7

Como beneficio adicional, cada una de estas soluciones funciona para cadenas que contienen números más grandes (hasta 9), pero algunas cadenas producen salidas cada vez más grandes (por ejemplo, 99)

Justin
fuente
1

JavaScript, 107

(requiere soporte de función de flecha, por ejemplo, como en 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 es la cadena de entrada

  • Cada ronda, usamos la expresión regular .?.?para explotar sen una matriz de cadenas de dos caracteres, luego mapesas cadenas en sus formas reducidas y pegar la matriz nuevamente

  • r almacena el resultado de la ronda actual para compararlo con el anterior s

  • k es el contador redondo

  • Abusamos horriblemente prompt(alias a p) como un mecanismo de entrada y salida, ya que puede presentar un mensaje al usuario


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)
apsillers
fuente
1

Perl - 50 (+2) bytes

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

Requiere -plinterruptores de línea de comando.

Uso de la muestra:

$ 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
fuente
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;}?>

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

211222111111222
11222111222
122111222
2111222
111222
1222
222
7

Soy un poco malo en codegolf ._. Tal vez no debería usar solo Java y PHP (y debería pensar más complicado)

Leo Pflug
fuente
1
CodeGolf no se trata de encontrar la solución más complicada, sino la más simple.
primo
Realmente no es necesario hacerlo, str_splitya que puede acceder a caracteres individuales en una cadena al igual que una matriz en PHP.
Gareth
Sí, después de un tiempo pensé eso, pero era demasiado flojo para editarlo. Pero ahora lo cambié.
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)

Ejemplo:

122122122121212212

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

MATEMÁTICA, 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
fuente
0

POWERSHELL, 2

Basado en la respuesta de Vereos "Puede usar cualquier método de entrada que acorte su código" a mi pregunta en los comentarios del OP, el siguiente script logra el resultado:

$a

Ejemplo ejecutado para "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

Obviamente, esta no es una entrada seria; su propósito es ilustrar mi punto de que permitir cualquier método de entrada puede trivializar el código real necesario para producir la respuesta. Por lo tanto, el método de entrada debe especificarse más rigurosamente.

usuario2460798
fuente
0

J, 41 caracteres

Como una función (¡ew parens! No muy feliz por ellos):

(,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:)
Vista en despiece ordenado
                _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)
Ejecución de la muestra
   (,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:) '1121121'
1121121
11121  
121    
21     
11     
5      
   (,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:) '122122122121212212'
122122122121212212
211222111111222   
11222111222       
122111222         
2111222           
111222            
1222              
7                 
Luciérnaga
fuente
0

Perl, 107 caracteres

El otro código perl claramente supera esto, pero para lo que vale, aquí está. Usé el modificador -l a costa de un personaje adicional:

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

Una versión más legible de eso:

$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
fuente