26
\$\begingroup\$

Your task today is to write a program or function that takes an array of integers, and counts the number of times, reading it left to right, that the value changes. This is easier to show with an example: [1 1 1 2 2 5 5 5 5 17 3] => [1 1 1 **2** 2 **5** 5 5 5 **17** **3**] => 4

Test case:

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

This is , fewest bytes wins!

\$\endgroup\$
5
  • \$\begingroup\$ Is my answer valid if the result is always correctly calculated, but if it's 0, False is printed instead? \$\endgroup\$
    – FlipTack
    Oct 27, 2017 at 15:54
  • 1
    \$\begingroup\$ @FlipTack That depends on the language. In general, if I can say 2+False and it errors, that's not fine, but if I get 2, that's fine. \$\endgroup\$
    – Pavel
    Oct 27, 2017 at 18:21
  • \$\begingroup\$ @FlipTack By default, this is the consensus. \$\endgroup\$ Oct 28, 2017 at 13:33
  • \$\begingroup\$ Is empty output for 0 acceptable? \$\endgroup\$
    – Titus
    Nov 2, 2017 at 21:06
  • \$\begingroup\$ @Titus yes it is. \$\endgroup\$
    – Pavel
    Nov 2, 2017 at 22:21

65 Answers 65

2
\$\begingroup\$

Ruby, 31 bytes

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

Try it online!

\$\endgroup\$
6
  • \$\begingroup\$ Instead of .drop(1) you can do [1..-1] \$\endgroup\$
    – Cyoce
    Oct 27, 2017 at 16:03
  • \$\begingroup\$ @Cyoce Unfortunately drop returns an Enumerator, not an Array, so that doesn't work. \$\endgroup\$
    – Jordan
    Oct 27, 2017 at 16:04
  • \$\begingroup\$ huh. It returns an Array on my version. \$\endgroup\$
    – Cyoce
    Oct 27, 2017 at 16:06
  • \$\begingroup\$ @Cyoce Which version? \$\endgroup\$
    – Jordan
    Oct 27, 2017 at 16:08
  • \$\begingroup\$ I'm on 1.9.3 but why can't you take the size of an Array anyway? \$\endgroup\$
    – Cyoce
    Oct 27, 2017 at 16:09
2
\$\begingroup\$

C (gcc 5.4.0), 61 bytes

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

Try it Online!

f is a function taking the length of the array and a pointer to the first element of the array, and returning the number of changes in the array;

This submission utilizes undefined behavior (*p++!=*p, p is used twice in an expression in which it is changed), which works on my machine (gcc 5.4.0) and on TIO, but may not work on other implementations or versions.

Explanation:

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
}
\$\endgroup\$
2
  • \$\begingroup\$ Could you maybe add a link to an online testing environment? \$\endgroup\$ Oct 29, 2017 at 15:25
  • \$\begingroup\$ @JonathanFrech Added \$\endgroup\$ Oct 29, 2017 at 18:11
2
\$\begingroup\$

05AB1E, 3 bytes

γ¦g

Try it online!

An alternative to Erik's answer.

γ¦g  ~ Full program.

γ    ~ Group into runs of equal adjacent elements.
 ¦   ~ Remove the first group (if there are any).
  g  ~ Length.
\$\endgroup\$
1
  • \$\begingroup\$ Ah, missed that that was a case. \$\endgroup\$ Nov 2, 2017 at 20:48
2
\$\begingroup\$

Bash, 17 bytes

Packages: Core Utilities, sed

uniq|sed 1d|wc -l

Takes an input array of one element per line.

How does it work?

The input goes to stdin, one array element per line, to uniq. uniq squeezes multiple consecutive identical lines into one, then sed 1d purges the first line, passing the rest to wc. wc -l simply counts the number of lines and outputs the count.

\$\endgroup\$
2
\$\begingroup\$

J-uby, 37 bytes

:zip%:rotate|~:[]&(0..-2)|:count++:!=

More "readable":

(:zip % :rotate) | (~:[] & (0..-2)) | (:count + +:!=)

Explanation:

:zip%:rotate                        # zip a with itself, rotated by one position. this yields [[a[0], a[1]], [a[1], a[2]], [a[2], a[3]], ...]
           |~:[]&(0..-2)            # discard the last pair, as that's [a[-1], a[0]], not one of our changes
                       |:count++:!= # count the pairs with unequal first and second elements (those are changes)

25 bytes (conversion of @daniero's Ruby answer)

~:each_cons&2|:count++:!=

Explanation

~:each_cons&2            # for every pair [a[i],a[i+1]] in a:
            |:count++:!= # count the number of pairs with unequal first and second elements
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Why is this non-competing? \$\endgroup\$
    – Pavel
    Nov 2, 2017 at 22:22
  • \$\begingroup\$ @Pavel Language version post-dates the challenge. \$\endgroup\$
    – Cyoce
    Nov 2, 2017 at 22:36
  • \$\begingroup\$ @Cyoce non-competing isn't a thing anymore \$\endgroup\$
    – dzaima
    Nov 5, 2017 at 18:09
2
\$\begingroup\$

Jq 1.5, 51 bytes

[range(1;length)as$i|select(.[$i]!=.[$i-1])]|length

Expanded

[                              # create an array containing
    range(1;length) as $i      # a copy of the input for
  | select(.[$i]!=.[$i-1])     # each successive element difference
] 
| length                       # length of final array

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Vyxal, 3 bytes

ĠḢL

Try it Online!

Alternatively:

Vyxal, 3 bytes

¯TL

Try it Online!

¯ꜝL would also work.

All of these solutions can be 2 bytes by removing L and adding the l flag.

\$\endgroup\$
2
\$\begingroup\$

Julia 1.0, 23 bytes

~a=sum([0;diff(a).!=0])

Try it online!

  • The unary operator ~ is redefined to save bytes.

  • sum returns an error on an empty (untyped) array, so the array is padded with a 0.

\$\endgroup\$
4
  • \$\begingroup\$ 22 bytes using diff \$\endgroup\$
    – amelies
    Oct 9, 2022 at 16:11
  • \$\begingroup\$ Thanks, amelies! I used your solution and changed this answer to a community wiki. \$\endgroup\$ Oct 9, 2022 at 18:19
  • 2
    \$\begingroup\$ The last test case is not valid though? 3 is expected instead of 2 \$\endgroup\$
    – Julian
    Oct 10, 2022 at 2:28
  • \$\begingroup\$ ouch true! Then the best I can do is 23 bytes or 24 if you want to use \$\endgroup\$
    – amelies
    Oct 10, 2022 at 8:56
2
\$\begingroup\$

Rust, 68 bytes

|u:Vec<_>|u.iter().fold((0,0,0),|(u,v,w),&x|(u+w*(v!=x)as i8,x,1)).0

Attempt This Online!

Non-Competing Rust, 63 bytes

This version crashes on 0-length inputs so doesn't technically complete the challenge. I think it's more elegant though.

|u:Vec<_>|u.iter().fold((0,u[0]),|(u,v),&x|(u+(v!=x)as i8,x)).0

Attempt This Online!

\$\endgroup\$
2
\$\begingroup\$

Haskell + hgl, 7 bytes

l<tl<gr

Attempt This Online!

Explanation

  • gr group the list into chunks of equal sized elements
  • tl drop the first element
  • l get the length

Alternate versions

8 bytes

cne 0<δ

Reflection

I'm quite happy with this. It's hard to imagine any improvements that could be made here. However while looking for alternative versions I found a few things that might be useful to add:

  • cn id and cn n should likely be added. cn id counts the number of True values in a list and cn n counts the number of False values in a list.
  • pa eq should likely be added.

With both of these there would be another 7 byte solution:

cnn<paq
\$\endgroup\$
2
\$\begingroup\$

Thunno, \$4 \log_{256}(96) \approx\$ 3.29 bytes

(This is only for v1.1.1+, ATO is on v1.1.0)

z[wL

Or, for \$5 \log_{256}(96) \approx\$ 4.12 bytes (works on all versions)

zyL1-

Attempt This Online!

Explanations:

        # Implicit input                [1, 1, 1, 2, 2, 3]
z[      # Forward-differences           [0, 0, 1, 0, 1]
  w     # Truthy items only             [1, 1]
   L    # Length                        2
        # Implicit output
        # Implicit input                [1, 1, 1, 2, 2, 3]
zy      # Group by consecutive items    [[1, 1, 1], [2, 2], [3]]
  L1-   # Length - 1                    2
        # Implicit output
\$\endgroup\$
2
\$\begingroup\$

><> (Fish), 30 bytes

i0\  ;n$\.13$\
1+>i:0(?/:{=?^$

Try it

\$\endgroup\$
1
\$\begingroup\$

Pyth, 8 bytes

ssmndZ.+

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Ruby, 36 bytes

->a{a.each_cons(2).count{|x,y|x!=y}}

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ Didn't know about #each_cons! Well played. Do you mind if I translate this into a J-uby answer? \$\endgroup\$
    – Cyoce
    Nov 2, 2017 at 19:37
  • \$\begingroup\$ @Cyoce sure, go ahead \$\endgroup\$
    – daniero
    Nov 2, 2017 at 20:16
  • \$\begingroup\$ You can find it here \$\endgroup\$
    – Cyoce
    Nov 2, 2017 at 20:20
  • \$\begingroup\$ @Cyoce Hey, that's a nice language :) It made me think of an old project of mine. It's basically a bunch of monkey patches on the most common classes used for golfing in Ruby -- String, Array, Enumerable etc. The goal was to make all operators such a +, -, *, / etc, work on any combination of these classes, and it has a few nice convenience methods and higher order functions. I never even bothered pushing it to Github but, looking at it now, it really has a lot going on. I think in combination with J-uby it could become really powerful. \$\endgroup\$
    – daniero
    Nov 4, 2017 at 13:44
  • \$\begingroup\$ @Cyoce I pushed it to Github if you wanna look at it: github.com/daniero/rewb. the interesting parts are in lib/rewb. It even has unit tests to demonstrate how all the stuff works. It think it J-uby/rewb could become a nice combo :D \$\endgroup\$
    – daniero
    Nov 4, 2017 at 13:48
1
\$\begingroup\$

C# (.NET Core), 94 bytes

using System.Linq;
n=>{int?i=0,a=n.FirstOrDefault();n.ForEach(x=>{i+=x==a?0:1;a=x;});return i;}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Japt, 6 bytes

ä- è¦0

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ ä- è works for 4 bytes. \$\endgroup\$
    – Shaggy
    Oct 27, 2017 at 7:25
1
\$\begingroup\$

Octave, 16 bytes

@(x)nnz(diff(x))

Verify all test cases here!

Quite short, seeing that Octave is a conventional language.

Explanation:

@(x)               % Anonymous function that takes x as input
    nnz(       )   % Count the number of non-zero ...
        diff(x)    % ... differences between elements
\$\endgroup\$
1
\$\begingroup\$

PHP, 63 bytes

foreach($_GET as$g){$c+=$g!=$l?isset($l)?1:0:0;$l=$g;}echo$c*1;

pass the sequence as a get query with any indexes, or Try it online!

my attempt, not the shortest, but it's something

\$\endgroup\$
1
\$\begingroup\$

Stacked, 26 bytes

[2 infixes 0\[...!=+]fold]

Try it online!

Explanation

[2 infixes 0\[...!=+]fold]
[                        ]   anonymous function; argument = arr
 2 infixes                   generate infixes of length 2
           0\[      ]fold    fold the inside function over the infixes (starting = 0)
                               when iterating, stack looks like: (acc (a0 a1))
              ...              merge (a0 a1) into the stack      (acc a0 a1)
                 !=            check for inequality              (acc a0!=a1)
                   +           add to accumulator                (acc+(a0!=a1))

This gives the number of unequal infixes in the array, equivalent to the given problem.

\$\endgroup\$
1
\$\begingroup\$

Ruby, 44 Bytes

->a{a.zip(a.rotate)[0..-2].count{|x,y|x!=y}}

Takes the array, and zips the elements with the array rotated one place. This gives pairs of [a[0],a[1]], [a[1],a[2]], [a[2],a[3]], ...

Then we cut off the last element because that's a[-1],a[0], which we don't need here.

Finally, we count the number of pairs with inequal first and second elements (or spaces in between items of the array which change).

\$\endgroup\$
1
\$\begingroup\$

AWK, 35 bytes

{for(i=1;i<NF;)s+=$i!=$++i;$0=s+0}1

Try it online!

This requires at least 1 character as input (the character can be a space).

A version without this restriction but with several more bytes is:

BEGIN{RS=" "}{s+=NR>1&&p!=$1;p=$1}END{print s+0}

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

GNU sed, 30 23 + 3 = 26 bytes

+3 bytes for -r flag. Output is in unary.

s/(\S+)( \1)*//g
y/ /;/

Try it online!

Technically I could drop the second line and say each space is a unary digit for -7 bytes, but I don't want to push it.

\$\endgroup\$
1
\$\begingroup\$

Pyke, 4 bytes

$0-l

Try it here!

$    -   delta(input)
 0-  -  ^.remove(0)
   l - len(^)
\$\endgroup\$
1
\$\begingroup\$

Common Lisp, 56 bytes

(loop as(x y)on(coerce(read)'list)while y count(/= x y))

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Python 3, 31 bytes

f=lambda y:sum(y[1:]-y[:-1]!=0)        

Try it online!

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Since this seems to only work on numpy arrays I think you are going to need to pay the bytes to import numpy. (or you should at least add a disclaimer) \$\endgroup\$
    – Wheat Wizard
    Oct 30, 2017 at 6:35
  • \$\begingroup\$ @WheatWizard Does that still apply when the question specifically says "an array of integers"? \$\endgroup\$
    – user75646
    Oct 30, 2017 at 22:34
  • 1
    \$\begingroup\$ To be honest I'm really not going off of a hard rule in this case, just kind of my opinion, if you would like a hard rule you should ask about it on the meta. \$\endgroup\$
    – Wheat Wizard
    Oct 30, 2017 at 23:40
1
\$\begingroup\$

PHP, 48 47 bytes

<?foreach($_GET[a]as$a)$n+=$_GET[b]!=$a;echo$n;

Run with arrays a and b as GET parameters.

empty output for 0.

\$\endgroup\$
1
\$\begingroup\$

J-uby, 21 bytes

Port of my Ruby answer.

:chunk+I|~:drop&1|:+@

Attempt This Online!

\$\endgroup\$
1
\$\begingroup\$

Japt -x, 2 bytes

ä¦

Try it

I'm not sure if this uses features introduced after the other Japt answer, but this is much shorter

ä    # Map each adjacent pair through:
 ¦   #  1 if they are different, 0 otherwise

-x   # Sum the new array and print
\$\endgroup\$
1
\$\begingroup\$

Factor, 29 bytes

[ 2 clump [ std 0 > ] count ]

Try it online!

Counts the number of adjacent pairs whose standard deviation is greater than zero.

\$\endgroup\$
1
\$\begingroup\$

Swift, 51 bytes

This works for any collection whose element type defines the operator !=, not just arrays of integers.

{zip($0,$0.dropFirst()).filter{$0.0 != $0.1}.count}

The spaces around the != operator are necessary; it parses $0.0!=$0.1 as $0.0! = $0.1.

This can be assigned to a variable or called inline:

print({zip($0,$0.dropFirst()).filter{$0.0 != $0.1}.count}([0, 1, 2]))

let x: ([Int]) -> Int = {zip($0,$0.dropFirst()).filter{$0.0 != $0.1}.count}
print(x([0, 1, 2]))

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.