Hitung perubahan dalam array

20

Tugas Anda hari ini adalah menulis program atau fungsi yang mengambil array bilangan bulat, dan menghitung berapa kali, membacanya dari kiri ke kanan, bahwa nilainya berubah. Ini lebih mudah ditunjukkan dengan contoh:[1 1 1 2 2 5 5 5 5 17 3] => [1 1 1 **2** 2 **5** 5 5 5 **17** **3**] => 4

Kasus cobaan:

Input           |   Output
[]              |   0
[0]             |   0
[0 1]           |   1
[0 0]           |   0
[1 2 3 17]      |   3
[1 1 1 2 2 3]   |   2
[-3 3 3 -3 0]   |   3

Ini adalah , byte terkecil menang!

Pavel
sumber
Apakah jawaban saya valid jika hasilnya selalu dihitung dengan benar, tetapi jika 0, Falsedicetak sebagai gantinya?
FlipTack
1
@ Lipup Itu tergantung pada bahasa. Secara umum, jika saya bisa mengatakan 2+Falsedan itu kesalahan, itu tidak baik, tetapi jika saya mengerti 2, itu baik-baik saja.
Pavel
@FlipTack Secara default, ini adalah konsensus.
manusiawi
Apakah output kosong 0dapat diterima?
Titus
@Itus ya itu.
Pavel

Jawaban:

9

Python 3 , 38 byte

f=lambda x=0,*y:y>()and(x!=y[0])+f(*y)

Cobalah online!

Dennis
sumber
2
Huh, memang tahu tahu Anda bisa menggunakan arg default seperti itu, nice find.
xnor
@ Dennis Bagaimana fungsi keluar dari loop rekursif ketika array kosong? Saya tidak melihat bagaimana ini tidak berakhir dengan maximum recursion depth exceeded.
Ioannes
@Ioannes Setelah hanya ada satu elemen ( x ) yang tersisa, y>()akan mengevaluasi ke False , sehingga kode berikut andini tidak dieksekusi.
Dennis
7

Haskell , 33 byte

f(a:b:r)=sum[1|a/=b]+f(b:r)
f _=0

Cobalah online!


Bonus: Versi aritmatika point-free yang agak aneh (44 byte)

sum.(tail>>=zipWith((((0^).(0^).abs).).(-)))

Cobalah online!

Diberi masukan [1,1,4,3,3,3], pertama kita mengambil perbedaan dari entri yang berdekatan ( [0,3,-1,0,0]), maka absnilai olute: [0,3,1,0,0]. Mengambil nol dengan kekuatan setiap elemen pertama kali menghasilkan [1,0,0,1,1], dan kedua kalinya membalikkan daftar: [0,1,1,0,0]( (1-)juga akan bekerja di sini, bukan (0^)). Akhirnya kami mengambil sumdaftar untuk mendapatkan 2.

Laikoni
sumber
5

Brain-Flak , 50 byte

([][()]){{}({}[({})]){{}<>({}())(<>)}{}([][()])}<>

Cobalah online!

Tidak menghasilkan apa-apa untuk 0, yang dalam brain-flak setara. Jika ini tidak dapat diterima, tambahkan ini untuk +4byte:({})

Penjelasan:

#Push stack-height-1
([][()])

#While true:
{

    #Pop the stack-height-1 off
    {}

    #If 'a' is the element on top of the stack, and 'b' is the element underneath it, then
    #Pop 'a' off, and push (a - b)
    ({}[({})])

    #If (a-b) is not 0...
    {
        #Pop (a-b) off
        {}

        #Switch stacks
        <>

        #Increment the value on the other stack
        ({}())

        #Push a 0 back to the main stack
        (<>)

    #Endif
    }

    #Pop either (a-b) or the 0 we pushed
    {}

    #Push stack-height-1
    ([][()])

#Endwhile
}

#Toggle to the alternate stack and display the counter
<>
DJMcMayhem
sumber
@Riley Bagus sekali! :)
DJMcMayhem
1
@WheatWizard Saya juga mencoba itu, tetapi loop selamanya pada input kosong. -0+1 = 1
H.PWiz
5

Brain-Flak , 50 byte

(([][()]){[{}]<({}[({})])>{(<{}>)()}{}([][()])}<>)

Cobalah online!

# Get ready to push the answer
(

# Push stack height - 1
([][()])

# Loop until 0 (until the stack has a height of 1)
{

  # Pop the old stack height and subtract it 
  #(cancels the loop counter from the final answer)
  [{}]

  # Pop the top of the stack and subtract the next element from that
  # Don't include this in the final answer
  <({}[({})])>

  # If not 0
  {

    # Pop the difference between the last two numbers
    # Don't include this in the final answer
    (<{}>)

    # Add 1 to the final answer
    ()

  # End if
  }{}

  # Push stack height - 1
  ([][()])

# End while
}

# Switch to the off stack so we don't print anything extra
<>

# Push the total sum. This is the number of times the if was true
)
Riley
sumber
1
Selamat untuk rep 10 ribu!
Pavel
@Pavel Terima kasih! Butuh saya selamanya untuk mendapatkan beberapa ratus terakhir. Saya sudah terlalu sibuk dengan hal-hal lain :(
Riley
Saya punya ini
H.PWiz
@ H.PWiz Saya pernah melakukannya pada satu titik, tapi saya suka bagaimana pop membatalkan dorongan ketinggian tumpukan.
Riley
5

Haskell , 35 byte

-8 byte terima kasih kepada H.PWiz.

Bermain golf dengan versi rekursif . Haskell adalah yang terbaik di rekursi dan saya melewatkannya. > _ <

f l=sum[1|x<-zipWith(/=)l$tail l,x]

Cobalah online!

Akan luar biasa jika ada yang tahu cara menggunakan tip ini .

Solusi alternatif, 36 byte

f l=sum[1|True<-zipWith(/=)l$tail l]

Cobalah online!

benar-benar manusiawi
sumber
1
Juga 35
H.PWiz
Tip itu melewatkan fakta penting yang Anda perlukan agar uncurryfungsinya fberfungsi. Ini sum.map fromEnum.(zipWith(/=)=<<tail)mungkin yang paling dekat Anda dapatkan, tetapi itu tidak akan bekerja dengan []dan 37 byte ..
ბიმო
5

Java (OpenJDK 8) , 65 byte

Tidak sesingkat yang saya inginkan, tapi itu hanya Jawa untuk Anda.

Uji dengan melewatkan array sebagai daftar terbatas koma.

a->{int s=0,i=1;for(;i<a.length;s+=a[i-1]!=a[i++]?1:0);return s;}

Cobalah online!

Luke Stevens
sumber
2
Jika array kosong bukan test case (dan saya tidak merasa itu benar-benar relevan, sebenarnya), orang bisa menggunakan: a->{int s=0,p=a[0];for(int n:a)s+=p==(p=n)?0:1;return s;}(57 byte).
Olivier Grégoire
@ OlivierGrégoire saya tahu! Saya menulis itu dan berpikir saya berhasil mengurangi byte tetapi gagal pada kasus pertama itu.
Luke Stevens
3
56 byte:a->{int s=0;for(int i:a)s+=a[0]!=(a[0]=i)?1:0;return s;}
Nevay
4

Sekam , 3 byte

Ltg

Cobalah online!

Penjelasan

Ltg    Input: [1,1,1,2,2,3]
  g    Group equal elements together: [[1,1,1],[2,2],[3]]
 t     Drop the first group (if any): [[2,2],[3]]
L      Return the length of the list: 2
Leo
sumber
4

Ohm v2 , 3 byte

ΔyΣ

Cobalah online!

Penjelasan

Δ     absolute differences between consecutive elements
 y    sign: 1 if positive, -1 if negative, 0 if zero
  Σ   sum
Cinaski
sumber
Penggunaan pintar signbuiltin!
Nick Clifford
@NickClifford Terima kasih!
Cinaski
4

Bahasa Wolfram (Mathematica) , 2324 26 29 byte

Length@Split@#~Max~1-1&

Cobalah online!

  • -1 byte terima kasih kepada Martin Ender!
  • -2 byte terima kasih kepada JungHwan Min! penggunaan yang bagus Split[].
  • -3 bytes terima kasih untuk benar-benar manusia!

sedikit penjelasan:

Splitakan membagi array menjadi daftar daftar (dari elemen yang sama), yaitu berubah {1, 2, 2, 3, 1, 1}menjadi {{1}, {2, 2}, {3}, {1, 1}}. Jadi, Length@Split@#adalah jumlah segmen yang berurutan. Max[*****-1, 0]digunakan untuk menangani {}input.

Keyu Gan
sumber
1
26 byte.
totallyhuman
1
24 byte:Max[Length@Split@#-1,0]&
JungHwan Min
23:Length@Split@#~Max~1-1&
Martin Ender
4

Retina , 24 21 16 byte

Terima kasih kepada @MartinEnder untuk -3 byte dan memperhatikan bug
-1 byte berkat @tsh
-4 byte terima kasih kepada @Leo

m`^(\S+)¶(?!\1$)

Cobalah online!

ovs
sumber
4

Symbolic Python , 120 117 byte

Golf 3 byte dengan menghapus gips eksplisit ke integer (menggunakan unary +) untuk variabel counter - ini berarti bahwa jika tidak ada perubahan dalam array output akan Falsebukan 0, tetapi ini diizinkan oleh meta .

___=-~(_==_)
__('___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)')
__('__=___=_>_'+';___+=_[__]!=_[-~__];__=-~__'*___)
_=___

Cobalah online!

# LINE 1: Generate value '2' for utility
___=-~(_==_)

# LINE 2: Get len(input) - 1
__('___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)')
   '___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)'     # Generate string '___=~-len(_)'
            `_>_`[___::___]                       #    'le' spliced from 'False'
                           +`__`[-~___]           #    'n' indexed from '<function ...>'
   '___=~-'+                           +'(_)'     #    Remaining characters in plaintext
__(                                          )    # Execute this to get len(input) - 1

# LINE 3: Main calculation loop
__('__=___=_>_'+';___+=_[__]!=_[-~__];__=-~__'*___) 
__(                                               ) # Execute:
   '__=___=_>_'                                     #   Set var1, var2 to 0
               +';                           '*___  #   len(input) - 1 times do:
                       _[__]!=_[-~__]               #   Compare input[var1, var1 + 1]
                  ___+=              ;              #   Add this to var2
                                      __=-~__       #   Increment var1

# LINE 4: Set output variable ('_') to the result calculated.
_=___                                       
FlipTack
sumber
2
= _ = apa sihir ini?
manusiawi
3

Jelly , 3 byte

ITL

Cobalah online!

Bagaimana itu bekerja

ITL - Program lengkap.

I - Increments (delta).
 T - Dapatkan indeks nilai kebenaran (dapatkan indeks elemen non-0).
  L - Panjang.
Tuan Xcoder
sumber
3

K (oK) , 8 byte

Larutan:

+/1_~~':

Cobalah online!

Contoh:

+/1_~~':1 1 1 2 2 5 5 5 5 17 3
4
+/1_~~':()
0
+/1_~~':-3 3 3 -3 0
3

Penjelasan:

Ditafsirkan dari kanan ke kiri:

+/1_~~': / the solution
     ~': / equal each-previous
    ~    / not (ie differ)
  1_     / 1 drop, remove first as this is different to null
+/       / sum up trues
streetster
sumber
3

R , 24 byte

cat(sum(!!diff(scan())))

Cobalah online!

Sama seperti jawaban MATL, baru digunakan sum(!!diff))karena tidak ada nnz.

Giuseppe
sumber
+1 Saya pikir menggunakan rleakan lebih pendek, tetapi tidak, length(rle()$v)menggunakan terlalu banyak karakter dan mati oleh satu.
Neal Fultz
@NealFultz mungkin masih layak diposkan sebagai jawaban! Selalu bagus untuk melihat pendekatan lain. Dan Anda harus menggunakannya sum(rle()$v|1)sebagai gantinya length. :)
Giuseppe
3

Cubix , 24 byte

UpO@0I>I!^-u>q.uvv$!^;)p

Cobalah online

Perhatikan bahwa Cubix menggunakan 0 untuk menunjukkan bahwa tidak ada lagi input, sehingga 0 tidak dapat ada dalam daftar.

Penjelasan

Dibuka:

    U p
    O @
0 I > I ! ^ - u
> q . u v v $ !
    ^ ;
    ) p

Kita mulai dari 0, mendorong penghitung (diinisialisasi dengan 0) dan input pertama ( I) ke stack.

Kami kemudian memasukkan loop. Pada setiap iterasi dari loop, kita mendapatkan input selanjutnya dengan I. Jika 0, kami kehabisan input, jadi kami memutar penghitung ke atas ( p), Output, dan keluar ( @).

Kalau tidak, kita mengambil perbedaan dari dua elemen teratas. Jika bukan nol, kami memutar penghitung ke atas, menambahnya, dan memutarnya kembali ke bawah p)q. Kami kemudian menghapus perbedaan dengan ;sebelum pindah ke iterasi berikutnya.

Semua karakter yang tidak disebutkan di sini hanya aliran kontrol. Ada banyak program Cubix.


sumber
@MickyT Baik pendekatan, tetapi Anda tampaknya akan overcounting oleh 1. Anda bisa menukar 0untuk (, tapi yang gagal pada input kosong.
permintaan maaf, akan melihatnya lagi
MickyT
3

Brain-Flak , 50 byte

(([][()]){[{}({}[({})])]{{}()(<()>)}{}([][()])}<>)

Cobalah online!

Karena semua orang memposting solusi 50 byte mereka di sini adalah milikku (saya punya 48 byte satu tapi itu modifikasi sederhana dari DjMcMayhem, jadi aku merasa layak posting)

Penjelasan

Jawaban ini secara ekstensif menggunakan pembatalan nilai.

Sepertinya bukan golf

([][()])({<{}({}[({})])>{<{}>()(<()>)}{}<([][()])>}<>)

Di sini kita menghitung delta sampai tumpukan memiliki satu item tersisa, setiap kali kita mengakumulasikan satu nilai dari loop dalam jika delta itu bukan nol.

Ini adalah cara yang sangat mudah untuk melakukannya.

Untuk membuat golf ini, kami mulai membatalkan nilai. Yang pertama dan yang harus jelas bagi setiap pegolf brain-flak yang keras adalah ketinggian tumpukan. Ini adalah fakta yang sudah diketahui

([])({<{}>...<([])>}{})

sama dengan

(([]){[{}]...([])}{})

Ketika nilai dimodifikasi oleh satu, nilai yang sama berlaku. Ini memberi kita

(([][()]){[{}]<({}[({})])>{<{}>()(<()>)}{}([][()])}<>)

Anda mungkin memperhatikan bahwa ini bahkan tidak menyelamatkan kami byte, tetapi jangan khawatir itu akan menjadi lebih bermanfaat saat kita melanjutkan.

Kami dapat melakukan pengurangan lain, jika Anda melihat pernyataan

<(...)>{<{}> ...

Anda benar-benar dapat menguranginya menjadi

[(...)]{{} ...

Ini berfungsi karena jika kita memasukkan loop [(...)]dan {}akan membatalkan, dan jika kita tidak nilai yang [(...)]sudah nol di tempat pertama dan tidak perlu dibatalkan. Karena kita memiliki kemunculan pola ini dalam kode kita, kita dapat menguranginya.

(([][()]){[{}][({}[({})])]{{}()(<()>)}{}([][()])}<>)

Itu menyelamatkan kita 2 byte tetapi juga menempatkan dua neg di sebelah satu sama lain. Ini dapat digabungkan untuk menyelamatkan kita 2 lagi.

(([][()]){[{}({}[({})])]{{}()(<()>)}{}([][()])}<>)

Dan itu kode kita.

Wisaya Gandum
sumber
3

Perl 6 , 18 byte

{sum $_ Z!= .skip}

Menguji

Diperluas:

{ # bare block lambda with implicit parameter 「$_」

  sum         # count the number of True values

      $_      # the input
    Z!=       # zip using &infix:«!=»
      .skip   # the input, but starting from the second value
              # (implicit method call on 「$_」
}
Brad Gilbert b2gills
sumber
3

Gaia , 2 byte

ėl

Cobalah online!

Ini menyalahgunakan bug (atau fitur?) Dari Gaia, bahwa enkode run-length tidak memperhitungkan elemen yang terakhir dijalankan. Perhatikan bahwa saya telah memeriksa ulang, ini berfungsi untuk semua kasus uji.

  • ė - Menjalankan pengkodean panjang (dengan cacat yang dijelaskan di atas).
  • l - Panjangnya.
Tuan Xcoder
sumber
2

JavaScript (ES6), 35 byte

a=>a.filter((e,i)=>e-a[i+1]).length
Neil
sumber
Saya bertanya-tanya apakah itu bisa dipersingkat dengan menggunakan rekursi. Tetapi upaya terbaik saya adalah 35 juga:f=([a,...b])=>1/a?!!(a-b[0])+f(b):0
Arnauld
@Arnauld Saya sudah mencobanya juga, tapi salah hitung dan mengira itu 36 byte, kalau tidak saya akan menambahkannya sebagai alternatif.
Neil
2

Pyth, 5 byte

l #.+

Suite uji.

Penjelasan:

   .+  Deltas
  #    Filter on identity (space)
l      Get length 
Steven H.
sumber
2

APL (Dyalog) , 8 byte

+/2≠/⊃,⊢

Cobalah online!

Bagaimana?

⊃,⊢ - daftar, dengan nilai pertama diulang untuk kasus elemen tunggal

2≠/ - daftar perubahan, tidak sama untuk setiap 2 elemen

+/ - jumlah

Uriel
sumber
2

J, 10 byte

[:+/2~:/\]

Infiks dengan panjang 2 ... apakah tidak sama? 2 ~:/\ ]

Jumlahkan 0s dan 1s yang dihasilkan :+/

Cobalah online!

Yunus
sumber
[:+/0=-/\ seharusnya bekerja untuk saya pikir 9 byte.
cole
2

Ruby , 31 byte

->a{a.chunk{|x|x}.drop(1).size}

Cobalah online!

Jordan
sumber
Alih-alih .drop(1)yang dapat Anda lakukan[1..-1]
Cyoce
@Cyoce Sayangnya dropmengembalikan Enumerator, bukan Array, sehingga tidak berfungsi.
Jordan
Hah. Ini mengembalikan Array pada versi saya.
Cyoce
@Cyoce Versi yang mana?
Jordan
Saya ada di 1.9.3 tapi mengapa Anda tidak bisa menggunakan sizeArray?
Cyoce
2

C (gcc 5.4.0), 61 byte

f(c,v)int*v;{int*p=v,s=0;for(;p<v+c-1;s+=*p++!=*p);return s;}

Cobalah secara Online!

f adalah fungsi yang mengambil panjang array dan pointer ke elemen pertama array, dan mengembalikan jumlah perubahan dalam array;

Kiriman ini menggunakan perilaku tidak terdefinisi ( *p++!=*p, p digunakan dua kali dalam ekspresi di mana ia diubah), yang bekerja pada mesin saya (gcc 5.4.0) dan pada TIO, tetapi mungkin tidak bekerja pada implementasi atau versi lain.

Penjelasan:

f(c,v)int*v;{ // old-style declaration for v, and implicit-int for c and return value
    int*p=v,s=0; // p is a pointer to the current item, s is the number of changes
    for(;p<v+c-1;s+=*p++!=*p); // for each consecutive pair of integers, if they are different, add one to the number of changes
    return s; // return the number of changes
}
pizzapants184
sumber
Bisakah Anda menambahkan tautan ke lingkungan pengujian online?
Jonathan Frech
@JonathanFrech Added
pizzapants184
2

05AB1E , 3 byte

γ¦g

Cobalah online!

Alternatif jawaban Erik.

~g ~ Program lengkap.

γ ~ Kelompokkan ke dalam menjalankan elemen berdekatan yang sama.
 ¦ ~ Hapus grup pertama (jika ada).
  g ~ Panjangnya.
Tuan Xcoder
sumber
Ah, merindukan bahwa itu adalah sebuah kasus.
Magic Gurita Guci