Pengurangan Kolakoski

27

Ikhtisar

Beberapa dari Anda mungkin mengetahui tentang Urutan Kolakoski ( A000002 ), urutan referensial yang diketahui dengan baik yang memiliki properti berikut:

Properti coolio Kolakoski, yo.

Ini adalah urutan yang hanya berisi 1 dan 2, dan untuk setiap grup 1 dan dua, jika Anda menjumlahkan panjang run, itu sama dengan dirinya sendiri, hanya setengah panjangnya. Dengan kata lain, barisan Kolakoski menggambarkan panjang run dalam barisan itu sendiri. Ini adalah satu-satunya urutan yang melakukan ini kecuali untuk urutan yang sama dengan 1 awal dihapus. (Ini hanya benar jika Anda membatasi diri pada urutan yang terdiri dari 1s dan 2s - Martin Ender)


Tantangan

Tantangannya adalah, diberi daftar bilangan bulat:

  • Keluarkan -1jika daftar BUKAN awalan bekerja dari urutan Kolakoski.
  • Keluarkan jumlah iterasi sebelum urutan menjadi [2].

Contoh Berolahraga

Menggunakan gambar yang disediakan sebagai contoh:

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

Oleh karena itu, angka yang dihasilkan adalah 8untuk input [1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1].

9 juga baik jika Anda melakukan pengindeksan 1.


The Test Suite (Anda juga dapat menguji dengan sub-iterasi)

------------------------------------------+---------
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

Jika Anda bingung:

Kebenaran: Pada akhirnya akan mencapai dua tanpa langkah perantara memiliki elemen selain 1dan 2. -Einkorn Enchanter 20 hours ago

Falsy: Nilai akhir bukan [2]. Istilah menengah mengandung sesuatu selain dari sesuatu yang diatur [1,2]. Beberapa hal lain, lihat contoh.


Ini adalah , byte-count terendah akan menjadi pemenangnya.

Guci Gurita Ajaib
sumber
7
Bisakah kita menggunakan nilai falsey bukan hanya -1?
mbomb007
1
Apa yang Anda maksud dengan "BUKAN awalan kerja dari urutan Kolakoski"? Saya berasumsi bahwa Anda bermaksud bahwa daftar tersebut pada akhirnya tidak akan tercapai [2]sampai saya melihat [2,2,1,1,2,1,2]test case.
ngenisis
1
@ngenisis Pada akhirnya akan mencapai dua tanpa langkah perantara yang memiliki elemen selain 1dan 2.
Wheat Wizard
2
Mungkin ide yang baik untuk ditambahkan [1]sebagai ujian.
Emigna
1
@ mbomb007 nilai yang berbeda tidak masalah. Bilangan bulat positif tidak baik. Jika Anda 1-indexing 0 baik-baik saja. "Salah" tidak masalah. Kesalahan baik-baik saja. Nilai pengembalian non-positif baik-baik saja, bahkan -129.42910.
Magic Gurita Guci

Jawaban:

8

Haskell , 126 87 79 76 75 byte

39 byte disimpan berkat Ørjan Johansen

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

Cobalah online!

Ini kesalahan pada input yang buruk.

Wisaya Gandum
sumber
f(dan akibatnya !) dapat dipersingkat banyak dengan menggunakan produksi malas + span/ lengthbukannya akumulator. Cobalah online!
Ørjan Johansen
1
Tampaknya memasuki loop tak terbatas untuk[1]
Emigna
1
@Emigna Darn. Harganya 6 byte untuk memperbaikinya, tapi saya sudah memperbaikinya.
Wheat Wizard
@ ØrjanJohansen Sepertinya itu tip yang bagus, tapi saya tidak cukup mahir di Haskell untuk memahami apa yang terjadi di sana. Jika mau, Anda dapat mempostingnya sebagai jawaban Anda sendiri, tetapi setidaknya selama saya tidak tahu cara kerja solusi Anda, saya tidak akan menambahkannya ke jawaban saya. :)
Wheat Wizard
1
Saya kemudian menyadari ini adalah kasus di mana impor sebenarnya lebih pendek (dan juga sederhana untuk memahami): import Data.List;f l=length<$>group l. ( <$>adalah sinonim untuk di mapsini.) Juga, alih-alih memiliki dua -1kasus berbeda , lebih pendek menggunakan @(_:_:_)pola untuk memaksa kasus utama hanya mencocokkan panjang> = 2 daftar. Cobalah online!
Ørjan Johansen
6

05AB1E , 22 byte

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

Cobalah online!

Penjelasan

[                        # 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
Emigna
sumber
Gagal untuk[1,1,2,2,1,2,1,1,2,2,1,2,2,1,1,2,1,1]
Weijun Zhou
@ WeijunZhou: Terima kasih, sudah diperbaiki!
Emigna
Anda mungkin lupa memperbarui tautan ...
Weijun Zhou
1
@ WeijunZhou: Memang benar. Terima kasih lagi :)
Emigna
3

SCALA, 290 (282?) Karakter, 290 (282?) Byte

Butuh sooo loong ... Tapi akhirnya aku selesai!

dengan kode ini:

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

Saya tidak tahu apakah saya harus menghitung var u=tke dalam byte, mengingat saya tidak menggunakan tselama algoritma (salinan hanya untuk mendapatkan yang dapat dimodifikasi, varbukan parameter yang tdianggap sebagai val- terima kasih ScaLa ). Tolong beritahu saya jika saya harus menghitungnya.

Cukup sulit. Cobalah online!

PS: Saya sedang berpikir untuk melakukannya secara rekursif, tetapi saya harus melewati penghitung sebagai parameter dari "subfungsi" rekursif yang sebenarnya; fakta ini membuat saya mendeklarasikan dua fungsi, dan karakter / byte ini tidak lain adalah hilang.

EDIT: Saya harus mengubah (?) Karena kami tidak yakin kami harus mengambil dalam jumlah [1]kasus. Jadi di sini adalah kode yang dimodifikasi:

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

Itu tidak dioptimalkan (saya memiliki duplikat "keluar" untuk kondisi yang sama: ketika saya sampai [2]dan ketika param [2]diperlakukan secara terpisah).

BIAYA BARU = 342 (saya tidak sengaja memodifikasi judul)

V. Courtois
sumber
1
Tampaknya memasuki loop tak terbatas untuk[1]
Emigna
Yap, tetapi seperti yang dikatakan oleh OP (seperti yang saya mengerti setidaknya): "dengan 1 awal dihapus" dan "Keluarkan jumlah iterasi sebelum urutan menjadi [2]"
V. Courtois
Untuk pemahaman saya, [1]tidak pernah mencapai [2]dan dengan demikian mengembalikan -1 .
Emigna
Saya melihat. Jadi, apakah Anda pikir saya harus meletakkan persyaratan litte di awal? Terima kasih atas saranmu.
V. Courtois
Saya tidak tahu scala tetapi saya berasumsi Anda hanya dapat memodifikasi loop untuk berhenti ketika panjang daftar lebih kecil dari 2. Anda tampaknya sudah memeriksa bahwa elemennya adalah 2 pada akhirnya.
Emigna
2

JavaScript, 146 142 byte

Coba pertama kali dalam kode golf, tampaknya "kembali" dalam fungsi yang lebih besar cukup membosankan ...

Juga, pemeriksaan b = 1 dan b = 2 memakan beberapa byte ...

Ini kodenya:

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}

Penjelasan

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

Data uji (menggunakan data uji yang diberikan)

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]

Sunting 1: 146 -> 142: Mencabut edit saya pada pengurangan byte, karena ini mempengaruhi output; dan beberapa edit pada pernyataan terakhir

pengguna71543
sumber
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}menghemat 5 byte (untuk loop bukan while; koma vs kurung; && vs jika). Anda dapat menggunakan kompilator penutupan Google ( closure-compiler.appspot.com ) untuk menyelesaikan optimasi ini untuk Anda
Oki
2

Jelly ,26 25 22 21 20 byte

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

Cobalah online!

Kode ini sebenarnya tidak berfungsi dengan benar sampai 20 byte dan saya bahkan tidak menyadarinya; itu gagal pada [2,2]test case. Seharusnya bekerja dengan sempurna sekarang.

menyebarkan
sumber
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)

Diindeks 0. Melempar "ReferenceError: X is not defined"dan "InternalError: too much recursion"input buruk.

Uji kasus

Oki
sumber
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))))))

Dasar loopdengan pra-periksa pada kasus tepi. Pengembalian niluntuk input yang tidak valid. Saya tidak tahu (= [2] '(2))adalah true: o

NikoNyrh
sumber
1

Python 2, 146 byte (hanya fungsi)

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)

Mengembalikan 0 pada input palsu (ok karena ini 1-diindeks). Cukup gunakan seperti ini:

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

Mathematica, 82 byte

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

Functionyang berulang kali mengganti {2}dengan simbol yang tidak ditentukan T, daftar (satu atau lebih) 1dan 2s dengan iterasi berikutnya, dan apa pun dengan 0sampai titik tetap tercapai, kemudian mengembalikan FirstPositionsimbol Tdalam FixedPointListminus yang dihasilkan 1. Keluaran adalah di {n}mana njumlah ( 1-index) dari iterasi yang diperlukan untuk meraih {2}kasus kebenaran dan -1+Missing["NotFound"]untuk kasus palsu.

Jika output harus nlebih daripada {n}, biayanya tiga byte lebih:

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

Python 2 , 184 163 156 bytes

  • @Felipe Nardi Batista menghemat 21 byte !!!! Terima kasih banyak!!!!
  • Halvard Hummel menyimpan 7 byte !! Terima kasih

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

Cobalah online!

Penjelasan:

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 
officialaimm
sumber
1
156 byte
Halvard Hummel
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)

Cobalah online!

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)

Cobalah online!

Penjelasan

Urutan baru (w) diinisialisasi untuk menyimpan iterasi pengurangan berikutnya. Penghitung (c) diinisialisasi untuk melacak jumlah iterasi.

Setiap item dalam urutan asli dibandingkan dengan nilai sebelumnya. Jika mereka sama, nilai item terakhir dari (w) meningkat dengan 1. Jika mereka berbeda, urutan (w) diperpanjang dengan [1].

Jika w == [2], penghitung (c) dikembalikan. Lain, jika urutan asli berisi item lain dari 1 dan 2, nilai -1 dikembalikan. Jika tidak demikian halnya, fungsi ini disebut secara rekursif dengan urutan baru (w) sebagai (s) dan penghitung (c) meningkat sebesar 1.

Jitse
sumber
Untuk menghemat satu byte, saya mencoba menggabungkan dua baris pertama ke dalam def f(s,c=2,j=0,w=[1]):, tetapi itu memberikan hasil yang berbeda. Adakah yang bisa menjelaskan mengapa itu?
Jitse
@ JoKing Itu masuk akal, terima kasih!
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()

Lewati semua kasus uji. Melempar satu atau lebih kesalahan sebaliknya. Saya benci cek validitas; kode ini bisa jadi golf jika inputnya bagus; akan lebih pendek bahkan jika inputnya adalah urutan 1 dan 2, belum tentu merupakan awalan dari urutan Kolakoski. Di sini, kita harus memeriksa vektor awal (jika tidak, test case [-2,1]) akan lulus) dan vektor yang dihasilkan (jika tidak [1,1,1]akan lulus).

Andreï Kostyrka
sumber
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}

Cobalah online!

Sunting: Disimpan 4 byte dengan mengonversi ke lambda rekursif.

Mengembalikan jumlah iterasi 1-indeks atau 0 sebagai falsey.

Memanfaatkan metode chunk Ruby enumerable, yang melakukan persis apa yang kita butuhkan - pengelompokan bersama berturut-turut dari angka yang sama. Panjang run merupakan array untuk iterasi berikutnya. Terus iterasi saat array lebih panjang dari 1 elemen dan tidak ada angka selain 1 dan 2 yang ditemukan.

Kirill L.
sumber
0

Pyth , 45 byte

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

Cobalah online!

Ini mungkin masih golf. Ini jelas golf jika .?bekerja seperti yang saya harapkan (menjadi elsestruktur paling dalam dan bukan yang terluar)

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
ar4093
sumber
0

Perl 5 -p , 71 byte

$_.=$";s/(. )\1*/$&=~y|12||.$"/ge&$.++while/^([12] ){2,}$/;$_=/^2 $/*$.

Cobalah online!

1-indeks Keluaran 0untuk falsy.

Xcali
sumber