Giảm Kolakoski


27

Tổng quan

Một số bạn có thể biết về Trình tự Kolakoski ( A000002 ), một trình tự tự tham khảo nổi tiếng có thuộc tính sau:

Các tài sản mát mẻ Kolakoski, yo.

Đó là một chuỗi chỉ chứa 1 và 2, và đối với mỗi nhóm 1 và twos, nếu bạn cộng chiều dài của các lần chạy, nó sẽ bằng chính nó, chỉ bằng một nửa chiều dài. Nói cách khác, chuỗi Kolakoski mô tả độ dài của các bước chạy trong chính chuỗi đó. Đây là chuỗi duy nhất thực hiện điều này ngoại trừ chuỗi tương tự với 1 ban đầu bị xóa. (Điều này chỉ đúng nếu bạn giới hạn bản thân trong các chuỗi được tạo thành từ 1 và 2 - Martin Ender)


Các thách thức

Thách thức là, đưa ra một danh sách các số nguyên:

  • Đầu ra -1nếu danh sách KHÔNG phải là tiền tố hoạt động của chuỗi Kolakoski.
  • Xuất số lần lặp trước khi chuỗi trở thành [2].

Ví dụ làm việc

Sử dụng hình ảnh được cung cấp làm ví dụ:

[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1] # Iteration 0 (the input).
[1,2,2,1,1,2,1,2,2,1,2]             # Iteration 1.
[1,2,2,1,1,2,1,1]                   # Iteration 2.
[1,2,2,1,2]                         # Iteration 3.
[1,2,1,1]                           # Iteration 4.
[1,1,2]                             # Iteration 5.
[2,1]                               # Iteration 6.
[1,1]                               # Iteration 7.
[2]                                 # Iteration 8.

Do đó, số kết quả là 8cho một đầu vào [1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1].

9 cũng tốt nếu bạn đang lập chỉ mục 1.


Bộ kiểm tra (Bạn cũng có thể kiểm tra với các lần lặp phụ)

------------------------------------------+---------
Truthy Scenarios                          | Output
------------------------------------------+---------
[1,1]                                     | 1 or 2
[1,2,2,1,1,2,1,2,2,1]                     | 6 or 7
[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1]       | 8 or 9
[1,2]                                     | 2 or 3
------------------------------------------+---------
Falsy Scenarios                           | Output
------------------------------------------+---------
[4,2,-2,1,0,3928,102904]                  | -1 or a unique falsy output.
[1,1,1]                                   | -1
[2,2,1,1,2,1,2] (Results in [2,3] @ i3)   | -1 (Trickiest example)
[]                                        | -1
[1]                                       | -1

Nếu bạn bối rối:

Sự thật: Cuối cùng nó sẽ đạt đến hai mà không có bất kỳ bước trung gian nào có bất kỳ yếu tố nào khác ngoài 12. -Einkorn Enchanter 20 hours ago

Falsy: Giá trị kết thúc là không [2]. Các thuật ngữ trung gian có chứa một cái gì đó khác với một cái gì đó của tập hợp [1,2]. Một vài điều khác, xem ví dụ.


Đây là , số byte thấp nhất sẽ là người chiến thắng.


7
Chúng ta có thể sử dụng bất kỳ giá trị falsey thay vì chỉ -1?
mbomb007

1
Ý bạn là gì khi "KHÔNG phải là tiền tố hoạt động của chuỗi Kolakoski"? Tôi đã giả sử bạn có nghĩa là danh sách cuối cùng không đạt được [2]cho đến khi tôi nhìn thấy [2,2,1,1,2,1,2]trường hợp thử nghiệm.
ngenisis

1
@ngenisis Cuối cùng nó sẽ đạt được hai mà không có bất kỳ bước trung gian nào có bất kỳ yếu tố nào khác ngoài 12.
Thuật sĩ lúa mì

2
Có thể là một ý tưởng tốt để thêm [1]vào như một trường hợp thử nghiệm.
Emigna

1
@ mbomb007 bất kỳ giá trị khác biệt là tốt. Một số nguyên dương là không tốt. Nếu bạn 1 chỉ số 0 là tốt. "Sai" là tốt. Lỗi là ổn. Bất kỳ giá trị trả lại không tích cực là tốt, thậm chí -129.42910.
Bạch tuộc ma thuật Urn

Câu trả lời:


8

Haskell , 126 87 79 76 75 byte

39 byte được lưu nhờ vào Ørjan Johansen

import Data.List
f[2]=0
f y@(_:_:_)|all(`elem`[1,2])y=1+f(length<$>group y)

Hãy thử trực tuyến!

Lỗi này về đầu vào xấu.


f(và do đó !) có thể được rút ngắn rất nhiều bằng cách sử dụng sản xuất lười biếng + span/ lengththay vì tích lũy. Hãy thử trực tuyến!
Ørjan Johansen

1
Dường như để vào một vòng lặp vô hạn cho[1]
Emigna

1
@Emigna chết tiệt. Tôi phải trả 6 byte để sửa nó, nhưng tôi đã sửa nó.
Thuật sĩ lúa mì

@ RjanJohansen Có vẻ như là một mẹo hay, nhưng tôi không đủ thành thạo về Haskell để hiểu những gì đang diễn ra ở đó. Nếu bạn muốn bạn có thể đăng nó dưới dạng câu trả lời của riêng bạn nhưng ít nhất miễn là tôi không biết giải pháp của bạn hoạt động như thế nào, tôi sẽ không thêm nó vào câu trả lời của mình. :)
Thuật sĩ lúa mì

1
Sau đó tôi nhận ra đây là một trường hợp nhập thực sự ngắn hơn (và cũng đơn giản hơn để hiểu) : import Data.List;f l=length<$>group l. ( <$>là một từ đồng nghĩa mapở đây.) Ngoài ra, thay vì có hai -1trường hợp khác nhau , việc sử dụng một @(_:_:_)mẫu để buộc trường hợp chính chỉ khớp với độ dài> = 2 danh sách ngắn hơn. Hãy thử trực tuyến!
Ørjan Johansen

6

05AB1E , 22 byte

[Dg2‹#γ€gM2›iX]2QJiNë®

Hãy thử trực tuyến!

Giải trình

[                        # start a loop
 D                       # duplicate current list
  g2‹#                   # break if the length is less than 2
      γ                  # group into runs of consecutive equal elements
       €g                # get length of each run
         M2›iX           # if the maximum run-length is greater than 2, push 1
              ]          # end loop
               2QJi      # if the result is a list containing only 2
                   N     # push the iteration counter from the loop
                    ë®   # else, push -1
                         # implicitly output top of stack

Thất bại cho[1,1,2,2,1,2,1,1,2,2,1,2,2,1,1,2,1,1]
Weijun Zhou

@ WeijunZhou: Cảm ơn, đã sửa!
Emigna

Bạn có thể đã quên cập nhật liên kết ...
Weijun Zhou

1
@ WeijunZhou: Quả thực tôi đã có. Cảm ơn một lần nữa :)
Emigna

3

SCALA, ký tự 290 (282?), 290 (282?) Byte

Nó làm tôi rất lo lắng ... Nhưng cuối cùng tôi cũng xong!

với mã này:

var u=t
var v=Array[Int]()
var c= -1
var b=1
if(!u.isEmpty){while(u.forall(x=>x==1|x==2)){c+=1
if(u.size>1){var p=u.size-1
for(i<-0 to p){if(b==1){var k=u(i)
v:+=(if(i==p)1 else if(u(i+1)==k){b=0
if(p-i>1&&u(i+2)==k)return-1
2}else 1)} else b=1}
u=v
v=v.take(0)}else if(u(0)==2)return c}}
c

Tôi không biết liệu tôi có nên đếm số var u=tbyte hay không, vì tôi không sử dụng tthuật toán (bản sao chỉ là để có thể sửa đổi varthay vì tham số tđược coi là val- cảm ơn ScaLa ). Xin vui lòng cho tôi biết nếu tôi nên đếm nó.

Đủ vất vả. Hãy thử trực tuyến!

Tái bút: Tôi đã nghĩ đến việc thực hiện đệ quy, nhưng tôi sẽ phải vượt qua một bộ đếm như là một tham số của "hàm con đệ quy" thực sự; thực tế này làm cho tôi khai báo hai hàm và các ký tự / byte này không có gì ngoài mất.

EDIT: Tôi đã phải thay đổi (?) Bởi vì chúng tôi không chắc chúng ta nên đưa vào [1]trường hợp đếm . Vì vậy, đây là mã sửa đổi:

var u=t
var v=Array[Int]()
var c= -1
var b=1
if(!u.isEmpty){try{t(1)}catch{case _=>return if(t(0)==2)0 else -1}
while(u.forall(x=>x==1|x==2)){c+=1
if(u.size>1){var p=u.size-1
for(i<-0 to p){if(b==1){var k=u(i)
v:+=(if(i==p)1 else if(u(i+1)==k){b=0
if(p-i>1&&u(i+2)==k)return-1
2}else 1)} else b=1}
u=v
v=v.take(0)}else if(u(0)==2)return c}}
c

Nó không được tối ưu hóa (tôi có một bản "out" trùng lặp cho cùng một điều kiện: khi tôi đến [2]và khi param [2]được xử lý riêng).

CHI PHÍ MỚI = 342 (Tôi không sửa đổi tiêu đề trên mục đích)


1
Dường như để vào một vòng lặp vô hạn cho[1]
Emigna

Đúng, nhưng như OP đã nói (ít nhất tôi đã hiểu): "với 1 lần đầu bị xóa" và "Xuất ra số lần lặp trước khi chuỗi trở thành [2]"
V. Courtois

Theo hiểu biết của tôi, [1]không bao giờ đạt được [2]và do đó sẽ trả về -1 .
Emigna

Tôi hiểu rồi. Vì vậy, bạn có nghĩ rằng tôi nên đặt một điều kiện litte khi bắt đầu? Cảm ơn lời khuyên của bạn.
V. Courtois

Tôi không biết scala nhưng tôi giả sử bạn chỉ có thể sửa đổi vòng lặp để dừng khi độ dài của danh sách nhỏ hơn 2. Bạn dường như đã kiểm tra xem phần tử có 2 ở cuối không.
Emigna

2

JavaScript, 146 142 byte

Lần đầu tiên thử chơi golf, có vẻ như "sự trở lại" trong chức năng lớn hơn khá tẻ nhạt ...

Ngoài ra, việc kiểm tra b = 1 và b = 2 chiếm một số byte ...

Đây là mã:

f=y=>{i=t=!y[0];while(y[1]){r=[];c=j=0;y.map(b=>{t|=b-1&&b-2;if(b-c){if(j>0)r.push(j);c=b;j=0}j++});(y=r).push(j);i++}return t||y[0]-2?-1:0^i}

Giải trình

f=y=>{/*1*/}                                        //function definition

//Inside /*1*/:
  i=t=!y[0];                                        //initialization
                                                    //if the first one is 0 or undefined, 
                                                    //set t=1 so that it will return -1   
                                                    //eventually, otherwise i=0
  while(y[1]){/*2*/}                                //if there are 2+ items, start the loop

  //Inside /*2*/:
    r=[];c=j=0;                                     //initialization
    y.map(b=>{/*3*/});                              //another function definition

    //Inside /*3*/:
      t|=b-1&&b-2;                                  //if b==1 or b==2, set t=1 so that the
                                                    //entire function returns -1
      if(b-c){if(j>0)r.push(j);c=b;j=0}             //if b!=c, and j!=0, then push the 
                                                    //count to the array and reset counter
      j++                                           //counting duplicate numbers

    (y=r).push(j);i++                               //push the remaining count to the array
                                                    //and proceed to another stage

  return t||y[0]-2?-1:0^i                           //if the remaining element is not 2, or
                                                    //t==1 (means falsy), return -1,
                                                    //otherwise return the counter i

Dữ liệu thử nghiệm (sử dụng dữ liệu thử nghiệm đã cho)

l=[[1,1],[1,2,2,1,1,2,1,2,2,1],[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1],[1,2],[4,2,-2,1,0,3928,102904],[1,1,1],[2,2,1,1,2,1,2],[]];
console.log(l.map(f));
//Output: (8) [1, 6, 8, 2, -1, -1, -1, -1]

Chỉnh sửa 1: 146 -> 142: Thu hồi chỉnh sửa của tôi về việc giảm byte, vì điều này ảnh hưởng đến đầu ra; và một số chỉnh sửa trên tuyên bố cuối cùng


f=a=>{for(i=t=!a[0];a[1];)r=[],c=j=0,a.map(a=>{t|=a-1&&a-2;a-c&&(0<j&&r.push(j),c=a,j=0);j++}),(a=r).push(j),i++;return t||a[0]-2?-1:0^i}lưu 5 byte (cho vòng lặp thay vì while; dấu phẩy so với dấu ngoặc; && vs if). Bạn có thể sử dụng trình biên dịch đóng của google ( clos-compiler.appspot.com ) để thực hiện những tối ưu hóa này cho bạn
Oki

2

Thạch ,26 25 22 21 20 byte

FQœ-2R¤
ŒgL€µÐĿṖ-LÇ?

Hãy thử trực tuyến!

Mã này thực sự không hoạt động chính xác cho đến 20 byte và tôi thậm chí không nhận thấy; nó đã thất bại trong [2,2]trường hợp thử nghiệm. Nên làm việc hoàn hảo ngay bây giờ.


2

JavaScript (ES6), 127 126 95 80 byte

g=(a,i,p,b=[])=>a.map(x=>3>x&0<x?(x==p?b[0]++:b=[1,...b],p=x):H)==2?i:g(b,~~i+1)

Chỉ số 0. Ném "ReferenceError: X is not defined""InternalError: too much recursion"vào đầu vào xấu.

Các trường hợp thử nghiệm


1

Clojure, 110 byte

#(if-not(#{[][1]}%)(loop[c % i 0](if(every? #{1 2}c)(if(=[2]c)i(recur(map count(partition-by + c))(inc i))))))

Một cơ bản loopvới một kiểm tra trước về các trường hợp cạnh. Trả về nilcho đầu vào không hợp lệ. Tôi không biết (= [2] '(2))true: o


1

Python 2, 146 byte (chỉ chức năng)

f=lambda l,i=0:i if l==[1]else 0if max(l)>2or min(l)<1else f([len(x)+1for x in"".join(`v!=l[i+1]`[0]for i,v in enumerate(l[:-1])).split("T")],i+1)

Trả về 0 khi nhập sai (ok vì nó được lập chỉ mục 1). Đơn giản chỉ cần sử dụng nó như thế này:

print(f([1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1]))

1

Toán học, 82 byte

FixedPointList[#/.{{2}->T,{(1|2)..}:>Length/@Split@#,_->0}&,#]~FirstPosition~T-1&

Functionliên tục thay thế {2}bằng ký hiệu không xác định T, một danh sách (một hoặc nhiều) 1s 2với lần lặp tiếp theo và bất cứ thứ gì khác 0cho đến khi đạt được một điểm cố định, sau đó trả về FirstPositionký hiệu Ttrong FixedPointListdấu trừ kết quả 1. Đầu ra là {n}nơi số lần lặp n( 1-exexed) cần thiết để đạt được {2}cho trường hợp trung thực và -1+Missing["NotFound"]cho trường hợp giả.

Nếu đầu ra phải nthay vì {n}, nó tốn thêm ba byte:

Position[FixedPointList[#/.{{2}->T,{(1|2)..}:>Length/@Split@#,_->0}&,#],T][[1,1]]-1&

1

Python 2 , 184 163 156 byte

  • @Felipe Nardi Batista đã lưu 21 byte !!!! cảm ơn rất nhiều!!!!
  • Halvard Hummel đã lưu 7 byte !! cảm ơn

Python 2 , 156 byte

a,c=input(),0
t=a==[]
while 1<len(a)and~-t:
 r,i=[],0
 while i<len(a):
	j=i
	while[a[j]]==a[i:i+1]:i+=1
	r+=[i-j]
 a=r;c+=1;t=any(x>2for x in a)
print~c*t+c

Hãy thử trực tuyến!

Giải trình:

a,c=input(),0                             #input and initialize main-counter 

t=a==[]                                   #set t to 1 if list's empty. 

while len(a)>1:                           #loop until list's length is 1.

 r,i=[],0                                 #Initialize temp. list and 
                                          #list-element-pointer 

 while i<len(a):                          #loop for the element in list 

  j=0                                     #set consecutive-item-counter to 0   

  while(i+j)<len(a)and a[i]==a[i+j]:j+=1  #increase the consec.-counter

  r+=[j];i+=j                             #add the value to a list, move the 
                                          #list-element-pointer 

 a=r;c+=1;t=any(x>2for x in a)            #update the main list, increase t 
                                          #the counter, check if any number 
 if t:break;                              #exceeds 2 (if yes, exit the loop)

print[c,-1][t]                            #print -1 if t or else the 
                                          #counter's 
                                          #value 



1

Python 2 , 122 byte

def f(s,c=2,j=0):
 w=[1]
 for i in s[1:]:w+=[1]*(i!=s[j]);w[-1]+=i==s[j];j+=1
 return(w==[2])*c-({1,2}!=set(s))or f(w,c+1)

Hãy thử trực tuyến!

Python 3 , 120 byte

def f(s,c=2,j=0):
 w=[1]
 for i in s[1:]:w+=[1]*(i!=s[j]);w[-1]+=i==s[j];j+=1
 return(w==[2])*c-({1,2}!={*s})or f(w,c+1)

Hãy thử trực tuyến!

Giải trình

Một chuỗi mới (w) được khởi tạo để lưu trữ lần lặp tiếp theo của việc giảm. Một bộ đếm (c) được kích hoạt để theo dõi số lần lặp.

Mỗi mục trong (các) trình tự ban đầu được so sánh với giá trị trước đó. Nếu chúng giống nhau, giá trị của mục cuối cùng của (w) sẽ tăng lên 1. Nếu chúng khác nhau, chuỗi (w) được mở rộng với [1].

Nếu w == [2], bộ đếm (c) được trả về. Khác, nếu (các) chuỗi ban đầu chứa các mục khác ngoài 1 và 2, giá trị -1 được trả về. Nếu không phải là trường hợp, hàm được gọi đệ quy với chuỗi mới (w) là (s) và bộ đếm (c) tăng thêm 1.


Để tiết kiệm một byte, tôi đang cố gắng kết hợp hai dòng đầu tiên vào def f(s,c=2,j=0,w=[1]):, nhưng điều đó mang lại một kết quả khác. Bất cứ ai có thể giải thích tại sao đó là?
Jitse


@JoKing Điều đó có ý nghĩa hoàn hảo, cảm ơn!
Jitse

0

R, 122 byte

a=scan()
i=0
f=function(x)if(!all(x%in%c(1,2)))stop()
while(length(a)>1){f(a)
a=rle(a)$l
f(a)
i=i+1}
if(a==2)i else stop()

Vượt qua tất cả các trường hợp thử nghiệm. Ném một hoặc nhiều lỗi khác. Tôi ghét kiểm tra tính hợp lệ; mã này có thể đã được đánh golf như vậy nếu đầu vào là tốt đẹp; nó sẽ ngắn hơn ngay cả trong trường hợp đầu vào là một chuỗi 1 và 2, không nhất thiết phải là tiền tố của chuỗi Kolakoski. Ở đây, chúng ta phải kiểm tra cả vectơ ban đầu (nếu không thì trường hợp thử nghiệm [-2,1]) sẽ vượt qua) và vectơ kết quả (nếu không [1,1,1]sẽ vượt qua).


0

Ruby , 81 77 byte

f=->a,i=1{a[1]&&a-[1,2]==[]?f[a.chunk{|x|x}.map{|x,y|y.size},i+1]:a==[2]?i:0}

Hãy thử trực tuyến!

Chỉnh sửa: Đã lưu 4 byte bằng cách chuyển đổi sang lambda đệ quy.

Trả về số lần lặp được lập chỉ mục 1 hoặc 0 là falsey.

Làm cho việc sử dụng phương pháp khối của Ruby liệt kê, thực hiện chính xác những gì chúng ta cần - nhóm các chuỗi số giống nhau liên tiếp lại với nhau. Độ dài của các lần chạy tạo thành mảng cho lần lặp tiếp theo. Tiếp tục lặp trong khi mảng dài hơn 1 phần tử và không gặp phải số nào ngoài 1 và 2.


0

Bình thường , 45 byte

L?||qb]1!lb-{b,1 2_1?q]2b1Z.V0IKy~QhMrQ8*KhbB

Hãy thử trực tuyến!

Đây có lẽ vẫn là golf. Nó chắc chắn có thể chơi được nếu .?hoạt động theo cách tôi hy vọng (sẽ là một elsecấu trúc trong cùng thay vì ngoài cùng)

L?||qb]1!lb-{b,1 2_1?q]2b1Z # A lambda function for testing an iteration of the shortening
L                           # y=lambda b:
 ?                          # if
    qb]1                    #    b == [1]
   |    !lb                 #      or !len(b)
  |         {b              #        or b.deduplicate()
           -  ,1 2          #             .difference([1,2]):
                  _1        #               return -1
                    ?q]2b1Z # else: return 1 if [2] == b else Z (=0)

.V0                         # for b in range(0,infinity):
   IKy~Q                    # if K:=y(Q :=        (applies y to old value of Q)
        hM                  #    map(_[0],
          rQ8               #               run_length_encode(Q)):
             *Khb           #    print(K*(b+1))
                 B          #    break

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.