Sondage: Conway revisité

16

Vous devriez tous être familiarisés avec la séquence de Conway (alias la séquence «regarder et dire») :

     1
    11
    21
  1211
111221
312211
etc

Vous pouvez également commencer par n'importe quel nombre arbitraire comme point de départ. Soit f(s)l'élément suivant de la séquence. Maintenant, pour chaque donnée que snous pouvons trouver f(s). L'inverse n'est pas aussi trivial: il n'est pas pour tout ypossible de trouver le prédécesseur stel que f(s) = y. Par exemple, y = 1nous ne pouvons pas trouver un prédécesseur. Mais si ya une même longueur que vous pouvez le diviser en paires de chiffres qui décrivent chacun une partie d'un prédécesseur:

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

Ainsi, de cette façon, nous pouvons définir un prédécesseur unique pour chaque ylongueur paire.

Remarque : Le «prédécesseur» sdéfini de cette façon ne satisfait généralement PAS f(s) = y.

Objectif

Écrivez un extrait de fonction / programme qui accepte une chaîne de chiffres en entrée qui

  • calcule l'élément suivant de la séquence Conway si la longueur de la chaîne d'entrée est impaire
  • calcule le prédécesseur de la chaîne d'entrée comme défini ci-dessus si la longueur de la chaîne d'entrée est paire .

Le code le plus court en octets gagne.

Questions récentes basées sur les séquences de look-and-say:

flawr
la source
1
Je suis confus. Pouvez-vous expliquer comment se 513111divise en 51, 32et 11?
squeamish ossifrage
1
J'ai l'impression que c'est un doublon combiné d'un défi de séquence look and say et d'un défi de décodage de longueur (je suis sûr que nous les avions).
Martin Ender
3
Quel serait le prédécesseur 11111111111111? Selon vos spécifications, ce serait le cas 1111111. Vous devez modifier vos spécifications pour définir une réponse raisonnable à cela.
TheNumberOne
1
@TheBestOne 11111111111111n'a tout simplement aucun prédécesseur. C'est une entrée illégale.
Kay est déçu
2
@TheBestOne Oui, c'est correct, j'ai défini une règle arbitraire pour le prédécesseur qui ne correspond pas toujours à un «vrai» prédécesseur.
flawr

Réponses:

3

CJam, 46 45 44 43 42 octets

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

Testez-le ici. Il prend le numéro sur STDIN et imprime le résultat sur STDOUT.

Martin Ender
la source
si-> ~= 45
Optimiseur
@Optimizer Merci, j'oublie que vous pouvez évaluer un personnage.
Martin Ender
5

Rubis, 125 120 119 101 octets

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})*''}

Entrée de chaîne prise par la fonction f:

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

Développé avec des notes:

# 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
}
août
la source
4

Prolog - 170 octets

[]/[].
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.

Cet extrait définit la fonction (-)/2 . Vous pouvez l'invoquer comme

?- [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] .

Il semble qu'il n'y ait qu'une seule longueur dans cette séquence avec une parité impaire: l'initiale [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.

Lisible:

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 est déçu en SE
la source
3

Python: 139 caractères

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]))

cas de test unique

print f('1111122221111222112')
>>> 514241322112
print f('514241322112')
>>> 1111122221111222112
averykhoo
la source
Vous pouvez supprimer l'espace de s)] ifà s)]if.
Bakuriu
Vous pouvez également supprimer l'espace entre les deux2 else
Beta Decay
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
_#_=[]

S'il doit provenir de stdin / stdout, ajoutez main=interact lpour 150 144 131 caractères au total. La fonction est appelée 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
la source
Pourriez-vous s'il vous plaît fournir un exemple d'utilisation? Pendant que je me mets l "11"au travail, je reçois une exception avec l "111"oul "1111111111111"
Paul Guyot
@PaulGuyot, On dirait que la correction a coupé quelques caractères de mon score. Merci :-)
Zaq
3

Perl - 98 octets

La taille de toutes ces instructions de contrôle me dérange, mais je suis assez content de la façon dont les expressions rationnelles ont fonctionné.

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

Non compressé:

($_)=@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
la source
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 fonction principale est f, en prenant l'entrée sous forme de chaîne Erlang et en renvoyant également la sortie sous forme de chaîne.

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

La fonction peut être raccourcie de 15 octets (190) en supprimant l'exigence de casse de plus de 9 caractères identiques. fles appels gqui calculent le prédécesseur récursivement, et si le nombre de caractères est impair (trouvé à la fin du calcul), il appelle la fonction iqui, associée à h, calcule l'élément suivant.

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

Je pense que c'est bien, il s'est avéré ne pas utiliser de fonctions d'assistance :-).

fier haskeller
la source
|x:y:z<-r- Je ne savais absolument pas que tu pouvais faire ça. Ce est tellement cool!
Flonk
@Flonk Son appelé "gardes de modèle". Il s'agissait d'une extension et dans l'une des versions de Haskell, il a été ajouté :-)
fier haskeller
Cela rend beaucoup de choses beaucoup plus faciles. Vous apprenez quelque chose de nouveau chaque jour! :)
Flonk
2

APL (45)

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

Oui, c'est une définition de fonction valide, même avec l'extérieur.

      ∊{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
la source
2

Java 7, Score = 252 235 octets

Oui, c'est encore Java; la pire langue de golf au monde. Cette approche utilise des chaînes. Les entiers arbitrairement grands sont pris en charge en java mais prendraient beaucoup plus de place pour coder.

Appelez avec f(intputString). Renvoie la chaîne correspondante.

Golfé:

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 Expanded avec code de structure:

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

}

Partiellement golfé:

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

}

Complètement élargi:

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

}

Pour exécuter, compilez d'abord la deuxième entrée avec: javac LookAndSayExpandedGolfed.java

Exécutez ensuite avec: java LookAndSayExpandedGolfed

Edit: Correction d'une erreur.

Le numéro un
la source
Ça ne marche pas pour moi,Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 4 at java.lang.String.charAt(String.java:658)
Octavia Togami
@KenzieTogami Fixed.
TheNumberOne
Je ne pense pas, est-ce --1censé l'être --i?
Octavia Togami
@KenzieTogamie Oui, c'est ça. C'est réparé maintenant.
TheNumberOne
Cool, ça marche. L'inverseur échoue cependant. 513211-> 11111.
Octavia Togami du
1

Javascript (dans le navigateur, 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)

Peut être raccourci de 4 caractères si vous ignorez var, ou quelques autres caractères avec d'autres globaux intermédiaires non protégés, mais supposons que nous ne sommes pas de mauvais programmeurs pendant une minute.

Le passage à la fonction de syntaxe courte ES6 avec argument et valeur de retour au lieu d'utiliser l'invite, l'alerte pour IO peut économiser plus.

JSFiddle ici: http://jsfiddle.net/86L1w6Lk/

user33068
la source
5
Ne vous inquiétez pas de ces vars ... nous sommes tous de "mauvais programmeurs" ici. ;)
Martin Ender
1

Python 3 - 159 octets

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)]]))
Beta Decay
la source
1

Cobra - 217

(186 si je peux supposer qu'une usedéclaration System.Text.RegularExpressionsexiste ailleurs)

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

JavaScript (ES6) 85

En utilisant une expression régulière, remplacez par fonction. Expression différente et fonction différente selon que la longueur d'entrée est paire ou impaire.

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