Look-and-say: Conway revisitado

16

Todos deberían estar familiarizados con la secuencia de Conway (también conocida como 'mirar y decir') por ahora:

     1
    11
    21
  1211
111221
312211
etc

También puede comenzar por cualquier número arbitrario como punto de partida. Dejar f(s)ser el siguiente elemento de la secuencia. Ahora por cada dado sque podemos encontrar f(s). Lo contrario no es tan trivial: no es yposible encontrar al predecesor de sesa manera f(s) = y. Por ejemplo, porque y = 1no podemos encontrar un predecesor. Pero si ytiene una longitud uniforme , puede dividirla en pares de dígitos que describen cada parte de un predecesor:

513211 divides in 51,32,11
so: 51 comes from 11111 
    32 comes from 222
    11 comes from 1
put together: 111112221

Entonces, de esta manera, podemos definir un predecesor único para cada ylongitud uniforme.

Nota : El 'predecesor' sdefinido de esta manera generalmente NO satisface f(s) = y.

Objetivo

Escriba un fragmento de función / programa que acepte una cadena de dígitos como entrada que

  • calcula el siguiente elemento de la secuencia de Conway si la longitud de la cadena de entrada es impar
  • calcula el predecesor de la cadena de entrada como se definió anteriormente si la longitud de la cadena de entrada es par .

El código más corto en bytes gana.

Preguntas recientes basadas en las secuencias de mirar y decir:

falla
fuente
1
Estoy confundido. ¿Puede explicar cómo 513111se divide en 51, 32y 11?
aprensivo ossifrage
1
Siento que este es un duplicado combinado de un desafío de secuencia de mirar y decir y un desafío de decodificación de longitud de ejecución (estoy seguro de que los tuvimos).
Martin Ender
3
¿Cuál sería el predecesor de 11111111111111ser? Según su especificación, lo sería 1111111. Debe modificar su especificación para definir una respuesta razonable para esto.
TheNumberOne
1
@TheBestOne 11111111111111simplemente no tiene predecesor. Es una entrada ilegal.
kay
2
@TheBestOne Sí, esto es correcto, definí una regla arbitraria para el predecesor que no siempre coincide con un predecesor 'real'.
falla

Respuestas:

3

CJam, 46 45 44 43 42 bytes

l_,2%{0\{@)@@_2$=!{0\0}*;}*\)\}{2/{(~*}%}?

Pruébalo aquí. Toma el número en STDIN e imprime el resultado en STDOUT.

Martin Ender
fuente
si-> ~= 45
Optimizador
@Optimizer Gracias, olvido que puedes evaluar un personaje.
Martin Ender
5

Rubí, 125 120 119 101 bytes

f=->n{c=n.chars;(n.size%2>0?c.chunk{|x|x}.map{|a,b|[b.size,a]}:c.each_slice(2).map{|a,b|b*a.hex})*''}

Entrada de cadena tomada a través de la función f:

f['111221']    # => "1211"
f['513211']    # => "111112221"
f['111112221'] # => "513211"

Ampliado con notas:

# define lambda that takes one arg
f = -> (n) {
  # store digits in c
  c = n.chars

  # n is of odd length
  if n.size % 2 > 0
    # group identical numbers
    c.chunk{ |x| x }.map do |a, b|
      # array of [digit count, digit value]
      [b.size, a]
    end
  else
    # slice array into groups of two elements
    c.each_slice(2).map do |a, b|
      # repeat the second digit in a pair
      # the first digit-times.
      b * a.hex
    end
  end * '' # join array
}
agosto
fuente
4

Prólogo - 170 bytes

[]/[].
T/R:-0*_*T*R.
C*X*[X|T]*R:-(C+1)*X*T*R.
C*X*T*Y:-10*C+X+Y+R,T/R.
N+R+A:-N=:=0,A=R;D is N mod 10,N//10+R+[D|A].
F-C-R:-C/N,(N=F,R=C;F-N-R).
[1]-[1,1]. S-T:-S-[1]-T.

Este recorte define la función (-)/2. Puedes invocarlo como

?- [1,1,1,3,2,1,3,2,1,1]-T.
T = [1, 3, 1, 1, 2, 2, 2, 1] .

?- [1]-T.
T = [1, 1] .

Parece que solo hay una longitud en esta secuencia con una paridad extraña: la inicial [1].

wr_len :- wr_len(1, [1]).
wr_len(N, Cur) :-
    length(Cur, Len),
    TrailingZeroes is lsb(Len),
    (TrailingZeroes > 0 -> Par = 'even'; Par = 'odd'),
    writef('%t\t%t\t%t\t%t\n', [N, Len, Par, TrailingZeroes]),
    get_next(Cur, Next),
    succ(N, O),
    !, wr_len(O, Next).
% index, length, parity of length, num of trailing 0 in bin presentation of length
?- wr_len.
1       1       odd     0
2       2       even    1
3       2       even    1
4       4       even    2
5       6       even    1
6       6       even    1
7       8       even    3
8       10      even    1
9       14      even    1
10      20      even    2
11      26      even    1
12      34      even    1
13      46      even    1
14      62      even    1
15      78      even    1
16      102     even    1
17      134     even    1
18      176     even    4
19      226     even    1
20      302     even    1
21      408     even    3
22      528     even    4
23      678     even    1
24      904     even    3
25      1182    even    1
26      1540    even    2
27      2012    even    2
28      2606    even    1
29      3410    even    1
30      4462    even    1
31      5808    even    4
32      7586    even    1
33      9898    even    1
34      12884   even    2
35      16774   even    1
36      21890   even    1
37      28528   even    4
38      37158   even    1
39      48410   even    1
40      63138   even    1
41      82350   even    1
42      107312  even    4
43      139984  even    4
44      182376  even    3
45      237746  even    1
46      310036  even    2
47      403966  even    1
48      526646  even    1
49      686646  even    1
50      894810  even    1
51      1166642 even    1
52      1520986 even    1
53      1982710 even    1
54      2584304 even    4
55      3369156 even    2
56      4391702 even    1
57      5724486 even    1
58      7462860 even    2
59      9727930 even    1
ERROR: Out of global stack
% I added a few "strategic" cuts (`!`) to get so far.

Legible:

get_next([], []).
get_next(Current, Next) :-
    get_next_sub(0, _, Current, Next).

get_next_sub(Length, Digit, [Digit|Tail], Result) :-
    get_next_sub(Length+1, Digit, Tail, Result).
get_next_sub(Length, Digit, Further, Result) :-
    number_to_list(10*Length+Digit, Result, ResultTail),
    get_next(Further, ResultTail).

number_to_list(Number, Result, Accumulator) :-
    0 is Number -> Result = Accumulator;
    Digit is Number mod 10,
    number_to_list(Number // 10, Result, [Digit|Accumulator]).

get_previous(Stop, Current, Result) :-
    get_next(Current, Next),
    (   Next = Stop
    ->  Result = Current
    ;   get_previous(Stop, Next, Result)
    ).

get_prev_or_next(Input, Result) :-
    length(Input, Length),
    (   1 is Length mod 2
    ->  get_next(Input, Result)
    ;   get_previous(Input, [1], Result)
    ).
kay
fuente
3

Python: 139 caracteres

import re
f=lambda s:''.join(['len(b)'+a for a,b in re.findall(r'((\d)\2*)',s)] if len(s)%2 else map(lambda a,b:b*int(a),s[::2],s[1::2]))

caso de prueba individual

print f('1111122221111222112')
>>> 514241322112
print f('514241322112')
>>> 1111122221111222112
averykhoo
fuente
Puede eliminar el espacio de s)] ifa s)]if.
Bakuriu
También puede eliminar el espacio intermedio2 else
Decaimiento Beta
3

Haskell, 134 128 115

n=length
l x=x#mod(n x)2
(a:b:c)#0=replicate(read[a])b++c#0
(a:b)#1=(\(c,d)->show(1+n c)++a:d#1)$span(==a)b
_#_=[]

Si tiene que ser de la entrada estándar / salida estándar, agregue main=interact lpor 150 144 131 caracteres totales. La función se llama l.

*Main> putStr . unlines $ map (\x->x++":\t"++l x) ([replicate n '1'|n<-[5..10]]++map show [0,6..30]++map show [n*n+n|n<-[2..10]])
11111:  51
111111: 111
1111111:    71
11111111:   1111
111111111:  91
1111111111: 11111
0:  10
6:  16
12: 2
18: 8
24: 44
30: 000
6:  16
12: 2
20: 00
30: 000
42: 2222
56: 66666
72: 2222222
90: 000000000
110:    2110
Zaq
fuente
¿Podría proporcionar un ejemplo de uso? Mientras me l "11"ponía a trabajar, recibo una excepción con l "111"ol "1111111111111"
Paul Guyot
@PaulGuyot, parece que arreglar eso cortó algunos caracteres de mi puntaje. Gracias :-)
Zaq
3

Perl - 98 bytes

El tamaño de todas estas declaraciones de control me molesta, pero estoy bastante contento con el funcionamiento de las expresiones regulares.

($_)=@ARGV;if(length()%2){$\=$&,s/^$&+//,print length$&while/^./}else{print$2x$1while s/^(.)(.)//}

Sin comprimir:

($_)=@ARGV;
if(length()%2)
{
$\=$&, #Assigning the character to $\ causes it to be appended to the print (thanks, tips thread!)
s/^$&+//, #Extract the string of characters
print length$& #Print its length
while/^./ #Get next character into $&
}else{
print$2x$1
while s/^(.)(.)//
}
BMac
fuente
2

Erlang, 205

f(L)->g(L,L,[]).
g([A,B|T],L,C)->g(T,L,lists:duplicate(A-$0,B)++C);g([],_,R)->R;g(_,L,_)->i(L,[]).
h([A|T],A,N,B)->h(T,A,N+1,B);h(L,B,N,C)->i(L,integer_to_list(N)++[B|C]).
i([H|T],A)->h(T,H,1,A);i(_,R)->R.

La función principal es f, tomando la entrada como una cadena de Erlang y devolviendo la salida también como una cadena.

f("11"). % returns "1"
f("111"). % returns "31"
f("1111111111111"). % returns "131"

La función se puede acortar 15 bytes (190) eliminando el requisito de mayúsculas y minúsculas de más de 9 caracteres idénticos. fllama, gque calcula el predecesor de forma recursiva, y si el número de caracteres es impar (se encuentra cuando finaliza el cálculo), llama a la función ique, emparejada h, calcula el siguiente elemento.

Paul Guyot
fuente
2

Haskell, 105

import Data.List
l=length
c r|odd$l r=group r>>=(l>>=(.take 1).shows)|x:y:z<-r=[y|_<-['1'..x]]++c z|0<1=r

Creo que es bueno que no haya utilizado ninguna función auxiliar :-).

orgulloso Haskeller
fuente
|x:y:z<-r- No sabía que pudieras hacer eso. ¡Eso es tan cool!
Flonk
@Flonk Se llama "guardias de patrones". Solía ​​ser una extensión y en una de las versiones de Haskell se agregó :-)
orgulloso Haskeller
Esto hace que muchas cosas sean mucho más fáciles. ¡Tu aprendes algo nuevo cada dia! :)
Flonk
2

APL (45)

∊{2|⍴⍵:(⊃,⍨⍕∘⍴)¨⍵⊂⍨1,2≠/⍵⋄/⍨∘⍎/¨⌽¨⍵⊂⍨1 0⍴⍨⍴⍵}

Sí, esa es una definición de función válida, incluso con el exterior.

      ∊{2|⍴⍵:(⊃,⍨⍕∘⍴)¨⍵⊂⍨1,2≠/⍵⋄/⍨∘⍎/¨⌽¨⍵⊂⍨1 0⍴⍨⍴⍵}'513211'
111112221
      ∊{2|⍴⍵:(⊃,⍨⍕∘⍴)¨⍵⊂⍨1,2≠/⍵⋄/⍨∘⍎/¨⌽¨⍵⊂⍨1 0⍴⍨⍴⍵}'111112221'
513211
      f←∊{2|⍴⍵:(⊃,⍨⍕∘⍴)¨⍵⊂⍨1,2≠/⍵⋄/⍨∘⍎/¨⌽¨⍵⊂⍨1 0⍴⍨⍴⍵}
      f ¨ '513211' '111112221'
┌─────────┬──────┐
│111112221│513211│
└─────────┴──────┘
marinus
fuente
2

Java 7, Puntuación = 252 235 bytes

Sí, es Java otra vez; El peor lenguaje de golf del mundo. Este enfoque utiliza cadenas. Enteros arbitrariamente grandes son compatibles con Java, pero tomarían mucho más espacio para codificar.

Llamada con f(intputString). Devuelve la cadena correspondiente.

Golfizado:

String f(String a){char[]b=a.toCharArray();a="";int i=0,j=0,d=0,e=b.length;if(e%2==0)for(;i<e;i+=2)for(j=0;j<b[i]-48;j++)a+=b[i+1];else{for(;i<e;i++)d=d==0?(j=b[i]-48)*0+1:b[i]-48!=j?(a+=d+""+j).length()*--i*0:d+1;a+=d;a+=j;}return a;}

Golfed expandido con código de estructura:

public class LookAndSayExpandedGolfed{

    public static void main(String[] args){
        System.out.println(new LookAndSayExpandedGolfed().f(args[0]));
    }

    String f(String a){
        char[]b=a.toCharArray();
        a="";
        int i=0,j=0,d=0,e=b.length;
        if(e%2==0)
            for(;i<e;i+=2)
                for(j=0;j<b[i]-48;j++)
                    a+=b[i+1];
        else{
            for(;i<e;i++)
                d=d==0?(j=b[i]-48)*0+1:b[i]-48!=j?(a+=d+""+j).length()*--i*0:d+1;
            a+=d;
            a+=j;
        }
        return a;
    }

}

Parcialmente Golfizado:

public class LookAndSayPartiallyGolfed{

    public static void main(String[] args){
        System.out.println(new LookAndSayPartiallyGolfed().f(args[0]));
    }

    String f(String a){
        char[] number = a.toCharArray();
        String answer = "";
        int i, j, longestStreakLength = 0;
        if (number.length % 2 == 0){
            for (i = 0; i < number.length; i += 2)
                for (j = 0; j < number[i] - 48; j++)
                    answer += number[i+1];
        } else{
            j = 0;
            for (i = 0; i < number.length; i++)
                longestStreakLength = longestStreakLength == 0 ? (j = number[i] - 48) * 0 + 1 : number[i] - 48 != j ? (answer += longestStreakLength + "" + j).length()*--i*0 : longestStreakLength + 1;
            answer += longestStreakLength;
            answer += j;
        }
        return answer;
    }

}

Completamente expandido:

public class LookAndSay{

    public static void main(String[] args){
        System.out.println(new LookAndSay().function(args[0]));
    }

    String function(String a){
        char[] number = a.toCharArray();
        if (number.length % 2 == 0){
            String answer = "";
            for (int i = 0; i < number.length; i += 2){
                for (int j = 0; j < number[i] - '0'; j++){
                    answer += number[i+1];
                }
            }
            return answer;
        }
        String answer = "";
        int longestStreakLength = 0;
        int longestStreakNum = 0;
        for (int i = 0; i < number.length; i++){
            if (longestStreakLength == 0){
                longestStreakNum = number[i] - '0';
                longestStreakLength = 1;
                continue;
            }
            if (number[i] - '0' != longestStreakNum){
                answer += longestStreakLength;
                answer += longestStreakNum;
                longestStreakLength = 0;
                i--;
            } else {
                longestStreakLength++;
            }
        }
        answer += longestStreakLength;
        answer += longestStreakNum;
        return answer;
    }

}

Para ejecutar, primero compile la segunda entrada con: javac LookAndSayExpandedGolfed.java

Luego corre con: java LookAndSayExpandedGolfed

Editar: se corrigió el error.

El numero uno
fuente
No funciona para mí,Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 4 at java.lang.String.charAt(String.java:658)
Octavia Togami
@KenzieTogami fijo.
TheNumberOne
No lo creo, se --1supone que debe ser --i?
Octavia Togami
@KenzieTogamie Sí, lo es. Ya está arreglado.
TheNumberOne
Genial, eso funciona. Sin embargo, el inversor falla. 513211-> 11111.
Octavia Togami
1

Javascript (en el navegador, ES5, IE8 +), 152

var s=prompt(),r='',n=r,c=r,i=0;do{c!=s[i]?(r+=n+c,n=1,c=s[i]):n++;i++}while(c)n='';i=0;while(s[i]){n+=Array(1*s[i]+1).join(c=s[i+1]);i+=2}alert(c?n:r)

Puede acortarse en 4 caracteres si omite var, o algunos caracteres más con otras variables globales no variadas intermedias también, pero supongamos que no somos malos programadores por un minuto.

Cambiando a la función de sintaxis corta ES6 con argumento y valor de retorno en lugar de usar prompt, alert for IO puede ahorrar más.

JSFiddle aquí: http://jsfiddle.net/86L1w6Lk/

usuario33068
fuente
55
No se preocupe por esos var... todos somos "malos programadores" aquí. ;)
Martin Ender
1

Python 3 - 159 bytes

import re;l=input();x=len;print(''.join([str(x(i))+j for i,j in re.findall('((.)\2*)',l)]if x(l)%2 else[j*int(i)for i,j in[l[i:i+2]for i in range(0,x(l),2)]]))
Decaimiento Beta
fuente
1

Cobra - 217

(186 si puedo asumir useque System.Text.RegularExpressionsexiste una declaración para en otro lugar)

do(s='')=if((l=s.length)%2,System.Text.RegularExpressions.Regex.replace(s,(for x in 10 get'[x]+|').join(''),do(m=Match())="['[m]'.length]"+'[m]'[:1]),(for x in 0:l:2get'[s[x+1]]'.repeat(int.parse('[s[x]]'))).join(''))
Οurous
fuente
1

JavaScript (ES6) 85

Usando la expresión regular reemplazar con la función. Diferentes expresiones regulares y diferentes funciones dependiendo de que la longitud de entrada sea par o impar.

F=s=>s.replace((i=s.length&1)?/(.)(\1*)/g:/../g,x=>i?x.length+x[0]:x[1].repeat(x[0]))
edc65
fuente