รูปลักษณ์และการพูด: Conway มาเยือน


16

คุณควรคุ้นเคยกับลำดับ Conway (หรือที่รู้จักกันว่า 'look-and-say'-sequence)โดยตอนนี้:

     1
    11
    21
  1211
111221
312211
etc

นอกจากนี้คุณยังสามารถเริ่มต้นด้วยหมายเลขโดยพลการใด ๆ เป็นจุดเริ่มต้น อนุญาตf(s)เป็นองค์ประกอบถัดไปของลำดับ ตอนนี้สำหรับทุกคนให้สิทธิ์แก่เราสามารถหาs f(s)กลับไม่เป็นที่น่ารำคาญ: มันไม่ได้สำหรับทุกคนyที่เป็นไปได้ที่จะหาบรรพบุรุษดังกล่าวว่าs f(s) = yเช่นสำหรับy = 1เราไม่สามารถหาบรรพบุรุษ แต่ถ้าyมีแม้แต่ความยาวคุณสามารถแบ่งออกเป็นคู่ของตัวเลขซึ่งอธิบายแต่ละส่วนหนึ่งของบรรพบุรุษ:

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

ด้วยวิธีนี้เราสามารถกำหนดบรรพบุรุษที่ไม่ซ้ำกันสำหรับทุกyความยาว

หมายเหตุ : ใน 'รุ่นก่อน' กำหนดวิธีนี้ไม่ทั่วไปไม่ตอบสนองsf(s) = y

เป้าหมาย

เขียนตัวอย่างข้อมูลของฟังก์ชัน / โปรแกรมที่ยอมรับสตริงตัวเลขเป็นอินพุต

  • คำนวณองค์ประกอบถัดไปของลำดับ Conway หากความยาวของสตริงป้อนเข้าเป็นเลขคี่
  • คำนวณบรรพบุรุษของสายป้อนตามที่ระบุไว้ข้างต้นหากความยาวสายป้อนเป็นแม้กระทั่ง

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ

คำถามล่าสุดขึ้นอยู่กับลำดับการมองและพูด:


1
ฉันสับสน คุณสามารถอธิบายวิธีการ513111แบ่งออกเป็น51, 32และ11?
ossifrage คลื่นไส้

1
ฉันรู้สึกว่านี่คือการรวมกันของรูปลักษณ์บางส่วนและพูดถึงความท้าทายลำดับและความท้าทายการถอดรหัสแบบรันไทม์ (ฉันแน่ใจว่าเรามีสิ่งเหล่านี้)
Martin Ender

3
บรรพบุรุษของสิ่งที่11111111111111จะเป็นอย่างไร 1111111ตามสเป็คของคุณก็จะเป็น คุณควรแก้ไขสเปคของคุณเพื่อกำหนดคำตอบที่สมเหตุสมผลสำหรับเรื่องนี้
TheNumberOne

1
@TheBestOne 11111111111111นั้นไม่มีรุ่นก่อน มันเป็นข้อมูลที่ผิดกฎหมาย
kay ผิดหวังใน SE

2
@TheBestOne ใช่นี่ถูกต้องฉันได้กำหนดกฎเกณฑ์โดยพลการสำหรับบรรพบุรุษที่ไม่ตรงกับรุ่นก่อน 'จริง'
ข้อบกพร่อง

คำตอบ:


3

CJam, 46 45 44 43 42 ไบต์

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

ทดสอบที่นี่ ใช้หมายเลขบน STDIN และพิมพ์ผลลัพธ์ไปที่ STDOUT



@Optimizer ขอบคุณฉันลืมว่าคุณสามารถ Eval ตัวละครได้
Martin Ender

5

ทับทิม, 125 120 119 101 ไบต์

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

การป้อนสตริงที่ใช้ผ่านฟังก์ชั่นf:

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

ขยายด้วยหมายเหตุ:

# 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 ไบต์

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

snipped (-)/2นี้กำหนดฟังก์ชั่น คุณสามารถเรียกมันเหมือน

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

ดูเหมือนจะมีเพียงหนึ่งความยาวในลำดับนี้ที่มีความเท่าเทียมกันแปลก: [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.

อ่านได้:

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 ตัวอักษร

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

กรณีทดสอบเดียว

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

คุณสามารถลบพื้นที่จากการs)] if s)]if
Bakuriu

นอกจากนี้คุณยังสามารถลบช่องว่างระหว่าง2 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
_#_=[]

ถ้ามันจะต้องจาก stdin / stdout เพิ่มmain=interact lสำหรับ150 144 131 ตัวอักษรทั้งหมด 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

คุณช่วยยกตัวอย่างการใช้งานได้ไหม ในขณะที่ฉันl "11"ทำงานฉันก็ได้รับการยกเว้นl "111"หรือl "1111111111111"
Paul Guyot

@PaulGuyot ดูเหมือนว่าการแก้ไขที่ตัดบางตัวอักษรออกจากคะแนนของฉัน ขอบคุณ :-)
Zaq

3

Perl - 98 ไบต์

ขนาดของงบควบคุมเหล่านี้ทำให้ฉันรำคาญ แต่ฉันก็ค่อนข้างพอใจกับการทำงานของ regexes

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

ไม่มีการบีบอัด:

($_)=@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

เออร์แลง, 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.

ฟังก์ชั่นหลักคือ f รับอินพุตเป็นสตริง Erlang และส่งคืนเอาต์พุตเป็นสตริงเช่นกัน

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

ฟังก์ชั่นนี้สามารถทำให้สั้นลง 15 ไบต์ (190) โดยการปล่อยความต้องการตัวอักษรที่เหมือนกันมากกว่า 9 ตัว fเรียกgซึ่งคำนวณก่อนหน้าซ้ำและถ้าจำนวนของตัวละครเป็นเลขคี่ (พบเมื่อการคำนวณสิ้นสุดลง) มันเรียกฟังก์ชั่นiที่จับคู่กับhคำนวณองค์ประกอบต่อไป


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

ฉันคิดว่ามันดีนะที่มันไม่ได้ใช้ฟังก์ชั่นตัวช่วย :-)


|x:y:z<-r- ฉันไม่รู้ว่าคุณทำได้ มันเยี่ยมมาก!
Flonk

@Flonk มันเรียกว่า "ยามรูปแบบ" มันเคยเป็นส่วนเสริมและในหนึ่งในรุ่นของ Haskell มันถูกเพิ่ม :-)
ภูมิใจ haskeller

มันทำให้หลายอย่างง่ายขึ้นมาก คุณเรียนรู้สิ่งใหม่ทุกวัน! :)
Flonk

2

APL (45)

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

ใช่นั่นเป็นนิยามฟังก์ชั่นที่ถูกต้องแม้จะอยู่ด้านนอก

      ∊{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, คะแนน = 252 235 ไบต์

ใช่มันเป็นจาวาอีกครั้ง ภาษากอล์ฟที่เลวร้ายที่สุดในโลก วิธีนี้ใช้สตริง จำนวนเต็มขนาดใหญ่โดยพลการได้รับการสนับสนุนใน java แต่จะใช้พื้นที่มากขึ้นในการเขียนโค้ด

f(intputString)โทรหา ส่งคืนสตริงที่สอดคล้องกัน

แข็งแรงเล่นกอล์ฟ:

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 ขยายด้วยรหัสโครงสร้าง:

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

}

Golfed บางส่วน:

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

}

ขยายอย่างสมบูรณ์:

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

}

ในการรันขั้นแรกให้รวบรวมรายการที่สองด้วย: javac LookAndSayExpandedGolfed.java

จากนั้นเรียกใช้ด้วย: java LookAndSayExpandedGolfed

แก้ไข:แก้ไขข้อผิดพลาด


ใช้งานไม่ได้สำหรับฉันException in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 4 at java.lang.String.charAt(String.java:658)
Octavia Togami

@KenzieTogami แก้ไขแล้ว
TheNumberOne

ฉันไม่คิดอย่างนั้น--1ควรจะเป็น--iอย่างไร
Octavia Togami

@KenzieTogamie ใช่มันเป็น ตอนนี้ได้รับการแก้ไขแล้ว
TheNumberOne

เจ๋งนั่นมันใช้ได้ อย่างไรก็ตามการย้อนกลับล้มเหลว ->513211 11111
Octavia Togami

1

Javascript (ในเบราว์เซอร์, 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)

สามารถย่อให้สั้นลงได้ถึง 4 ตัวอักษรถ้าคุณข้าม var หรืออีกสองสามตัวอักษรที่มีตัวกลมกลางที่ไม่ได้แยกออกมาเหมือนกัน แต่ลองทำเป็นว่าพวกเราไม่ใช่โปรแกรมเมอร์

การสลับไปยังฟังก์ชันไวยากรณ์สั้น ES6 ด้วยอาร์กิวเมนต์และค่าส่งคืนแทนที่จะใช้พรอมต์การแจ้งเตือนสำหรับ IO สามารถประหยัดได้มากขึ้น

JSFiddle ที่นี่: http://jsfiddle.net/86L1w6Lk/


5
ไม่ต้องกังวลเกี่ยวกับvars ... พวกเราทุกคน "โปรแกรมเมอร์ไม่ดี" ที่นี่ ;)
Martin Ender

1

Python 3 - 159 ไบต์

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

คอบร้า - 217

(186 ถ้าฉันสามารถสันนิษฐานได้ว่ามีuseคำสั่งSystem.Text.RegularExpressionsอยู่ที่อื่น)

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

ใช้การแสดงออกปกติแทนที่ด้วยฟังก์ชั่น regexp ที่แตกต่างกันและฟังก์ชั่นที่แตกต่างกันขึ้นอยู่กับความยาวของการป้อนข้อมูลเป็นคู่หรือคี่

F=s=>s.replace((i=s.length&1)?/(.)(\1*)/g:/../g,x=>i?x.length+x[0]:x[1].repeat(x[0]))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.