Aspetto: Conway rivisitato


16

Ormai dovresti avere tutti familiarità con la sequenza di Conway ( nota anche come sequenza "look-and-say") :

     1
    11
    21
  1211
111221
312211
etc

Puoi anche iniziare da qualsiasi numero arbitrario come punto di partenza. Lascia che f(s)sia il prossimo elemento della sequenza. Ora per ogni dato sche possiamo trovare f(s). Il contrario non è così banale: non è per tutti ypossibile trovare il predecessore stale f(s) = y. Ad esempio, y = 1non possiamo trovare un predecessore. Ma se yha un ancor lunghezza si può dividere in coppie di cifre che descrivono ciascuno parte di un predecessore:

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

Quindi in questo modo possiamo definire un predecessore unico per ogni ylunghezza pari.

Nota : il "predecessore" sdefinito in questo modo generalmente NON soddisfa f(s) = y.

Obbiettivo

Scrivi uno snippet di funzione / programma che accetta una stringa di cifre come input

  • calcola l'elemento successivo della sequenza di Conway se la lunghezza della stringa di input è dispari
  • calcola il predecessore della stringa di input come definito sopra se la lunghezza della stringa di input è pari .

Vince il codice più breve in byte.

Domande recenti basate sulle sequenze look-and-say:


1
Non ho capito bene. Ci può spiegare come 513111divide in 51, 32e 11?
ossifrage schifoso

1
Sento che questo è un duplicato combinato di una sfida di sequenza e di decodifica e una sfida di decodifica di lunga durata (sono sicuro che ne abbiamo avuti).
Martin Ender,

3
Quale sarebbe il predecessore di 11111111111111essere? Secondo le tue specifiche, lo sarebbe 1111111. È necessario modificare le specifiche per definire una risposta ragionevole per questo.
TheNumberOne il

1
@TheBestOne 11111111111111non ha semplicemente un predecessore. È un input illegale.
kay,

2
@TheBestOne Sì, è corretto, ho definito una regola arbitraria per il predecessore che non corrisponde sempre a un predecessore "reale".
Flawr,

Risposte:



5

Rubino, 125 120 119 101 byte

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

Input di stringa preso attraverso la funzione f:

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

Espanso con note:

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

4

Prolog - 170 byte

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

Questo frammento definisce la funzione (-)/2. Puoi invocarlo come

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

Sembra esserci solo una lunghezza in questa sequenza con una parità dispari: l'iniziale [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.

Leggibile:

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

3

Python: 139 caratteri

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

singolo test

print f('1111122221111222112')
>>> 514241322112
print f('514241322112')
>>> 1111122221111222112

È possibile rimuovere lo spazio da s)] ifa s)]if.
Bakuriu,

Puoi anche rimuovere lo spazio tra2 else
Decadimento 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
_#_=[]

Se deve essere da stdin / stdout, aggiungere main=interact lper 150 144 131 caratteri totali. La funzione è chiamata 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

Potresti fornire un esempio di utilizzo? Mentre l "11"lavoro, ricevo un'eccezione con l "111"ol "1111111111111"
Paul Guyot,

@PaulGuyot, sembra aggiustare che ha tagliato alcuni caratteri dal mio punteggio. Grazie :-)
Zaq,

3

Perl - 98 byte

La dimensione di tutte queste dichiarazioni di controllo mi dà fastidio, ma sono abbastanza contento di come hanno funzionato le regex.

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

Non compresso:

($_)=@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/^(.)(.)//
}

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 funzione principale è f, prendendo l'input come stringa Erlang e restituendo anche l'output come stringa.

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

La funzione può essere ridotta di 15 byte (190) eliminando la necessità di più di 9 caratteri identici. fchiama gche calcola ricorsivamente il predecessore e se il numero di caratteri è dispari (presente alla fine del calcolo), chiama la funzione iche, accoppiata h, calcola l'elemento successivo.


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

Penso che sia bello che non abbia usato nessuna funzione di supporto :-).


|x:y:z<-r- Non sapevo assolutamente che potresti farlo. È così fico!
Flonk,

@Flonk Si chiama "pattern guards". Era un'estensione e in una delle versioni di Haskell è stato aggiunto :-)
orgoglioso haskeller il

Questo rende molte cose molto più facili. Si impara qualcosa di nuovo ogni giorno! :)
Flonk,

2

APL (45)

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

Sì, questa è una definizione di funzione valida, anche con l'esterno.

      ∊{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│
└─────────┴──────┘

2

Java 7, Punteggio = 252 235 byte

Sì, è di nuovo java; la peggior lingua da golf al mondo. Questo approccio utilizza stringhe. In java sono supportati interi arbitrariamente grandi, ma richiederebbe molto più spazio per la codifica.

Chiama con f(intputString). Restituisce la stringa corrispondente.

golfed:

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 Espanso con codice struttura:

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

}

Parzialmente golfato:

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 ampliato:

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

}

Per eseguire, compila prima la seconda voce con: javac LookAndSayExpandedGolfed.java

Quindi eseguire con: java LookAndSayExpandedGolfed

Modifica: errore risolto.


Non funziona per me,Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 4 at java.lang.String.charAt(String.java:658)
Octavia Togami,

@KenzieTogami Risolto.
TheNumberOne

Non credo, --1dovrebbe essere --i?
Octavia Togami,

@KenzieTogamie Sì, lo è. Ora è riparato.
TheNumberOne

Bene, funziona. L'inversore non riesce, tuttavia. 513211-> 11111.
Octavia Togami,

1

Javascript (nel browser, 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)

Può essere ridotto di 4 caratteri se salti var, o qualche altro carattere anche con altri globi intermedi non danneggiati, ma facciamo finta di non essere programmatori cattivi per un minuto.

Passando alla funzione di sintassi breve ES6 con argomento e valore di ritorno invece di utilizzare prompt, l'avviso per IO può risparmiare di più.

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


5
Non preoccuparti di quelle vars ... siamo tutti "programmatori cattivi" qui. ;)
Martin Ender,

1

Python 3 - 159 byte

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

1

Cobra - 217

(186 se posso assumere una usedichiarazione per System.Text.RegularExpressionsesiste altrove)

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

1

JavaScript (ES6) 85

Utilizzando l'espressione regolare sostituire con la funzione. Regexp diverso e funzione diversa a seconda che la lunghezza dell'input sia pari o dispari.

F=s=>s.replace((i=s.length&1)?/(.)(\1*)/g:/../g,x=>i?x.length+x[0]:x[1].repeat(x[0]))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.