[Question]
  [
Consider a string of length N, such as `Peanut Butter` with N = 13. Notice that there are N-1 pairs of neighboring characters in the string. For `Peanut Butter`, the first of the 12 pairs is `Pe`, the second is `ea`, the last is `er`.
When the pairs are mostly different characters, the string has a chunky quality, e.g. `chUnky`.  
When these pairs are mostly the same character, the string has a smooth quality, e.g. `sssmmsss`.
Define the *chunkiness* of a string to be the ratio of the number of pairs with two different characters to the total number of pairs (N-1).
Define the *smoothness* of a string to be the ratio of the number of pairs with two identical characters to the total number of pairs (N-1).
For example, `Peanut Butter` only has one pair with identical characters (`tt`), so its smoothness is 1/12 or 0.0833 and its chunkiness is 11/12 or 0.9167.
**Empty strings and strings with only one character are defined to be 100% smooth and 0% chunky.**
## Challenge
Write a program that takes in a string of arbitrary length and outputs either its chunkiness or smoothness ratio as a floating point value.
* Take input via stdin or the command line, or you may write a function that takes a string.
* You can assume the input string only contains [printable ASCII](https://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters) characters (and hence is single-line).
* Print the float to stdout to 4 or more decimal places, or you can choose to return it if you wrote a function. Decimal places that convey no information are not required, e.g. `0` is fine instead of `0.0000`.
* Choose chunkiness or smoothness as you prefer. Just be sure to say which one your program outputs.
**The shortest code in bytes wins.**
## Examples
`Peanut Butter` → Chunkiness: `0.91666666666`, Smoothness: `0.08333333333`  
`chUnky` → Chunkiness: `1.0`, Smoothness: `0.0`  
`sssmmsss` → Chunkiness: `0.28571428571`, Smoothness: `0.71428571428`  
`999` → Chunkiness: `0.0`, Smoothness: `1.0`  
`AA` → Chunkiness: `0.0`, Smoothness: `1.0`  
`Aa` → Chunkiness: `1.0`, Smoothness: `0.0`  
`!` → Chunkiness: `0.0`, Smoothness: `1.0`  
[empty string] → Chunkiness: `0.0`, Smoothness: `1.0`
*Bonus question: Which do you prefer[,](https://goo.gl/UcVvMN) chunky or smooth strings[?](https://chat.stackexchange.com/transcript/message/22752050#22752050)*
  
[Answer]
# CJam, 19 bytes
```
q_1>_@.=:!1b\,d/4mO
```
100% chunky source code that calculates **chunkiness**.
[Try this chunky goodness online.](http://cjam.aditsu.net/#code=q_1%3E_%40.%3D%3A!1b%5C%2Cd%2F4mO&input=Peanut%20Butter)
### How it works
```
q_                  e# Read from STDIN and push a copy.
  1>_               e# Discard the first character and push a copy.
     @              e# Rotate the original on top.
      .=            e# Vectorized comparison (1 if equal, 0 if not).
        :!          e# Mapped logical NOT (0 if equal, 1 if not).
          1b        e# Base 1 conversion (sum).
            \,      e# Swap with the shortened string and push its length.
              d/    e# Cast to double and divide.
                4mO e# Round to four decimal places.
```
Obviously, NaN rounded to 4 decimal places is 0.
[Answer]
# Pyth, ~~13~~ 12 bytes
```
csJnVztz|lJ1
```
Fully chunky code calculating chunkiness.
[Demonstration.](https://pyth.herokuapp.com/?code=csJnVztz%7ClJ1&input=sssmmsss&debug=0) [Test harness.](https://pyth.herokuapp.com/?code=FN%2Bz.z%3DzPhcN%5C%E2%86%92%2B%2BzdcsJnVztz%7ClJ1&input=Peanut+Butter+%E2%86%92+Chunkiness%3A+0.91666666666%2C+Smoothness%3A+0.08333333333%0AchUnky+%E2%86%92+Chunkiness%3A+1.0%2C+Smoothness%3A+0.0%0Asssmmsss+%E2%86%92+Chunkiness%3A+0.28571428571%2C+Smoothness%3A+0.71428571428%0A999+%E2%86%92+Chunkiness%3A+0.0%2C+Smoothness%3A+1.0%0AAA+%E2%86%92+Chunkiness%3A+0.0%2C+Smoothness%3A+1.0%0AAa+%E2%86%92+Chunkiness%3A+1.0%2C+Smoothness%3A+0.0%0A!+%E2%86%92+Chunkiness%3A+0.0%2C+Smoothness%3A+1.0%0A+%E2%86%92+Chunkiness%3A+0.0%2C+Smoothness%3A+1.0%0AcsJnM.%3Az2%7ClJ1+&debug=0)
```
csJnVztz|lJ1
                 Implicit: z = input()
   nV            n, !=, vectorized over
     z           z
      tz         z[:-1]
                 V implitly truncates.
  J              Store it in J.
 s               sum J
c                floating point divided by
         |       logical or
          lJ     len(J)
            1    1
```
[Answer]
# TI-BASIC, 46 bytes
```
Input Str1
If 2≤length(Str1
mean(seq(sub(Str1,X,1)=sub(Str1,X-1,1),X,2,length(Str1
Ans
```
`sub(x1,x2,x3` gives the substring of string `x1` starting (one-based) at number `x2` and ending at number `x3`, then `seq(` builds a sequence.
Gives the smoothness value. The `Ans` variable is `0` by default, so we don't need an `Else` to the `If` statement, or to store anything to `Ans` beforehand.
[Answer]
# APL, 10 bytes
This reads input from stdin and prints the chunkiness to stdout. The algorithm is the same one used for the J solution.
```
(+/÷⍴)2≠/⍞
```
[Answer]
## Matlab (~~37~~ 36 bytes)
This can be done with the following anonymous function, which returns chunkiness:
```
f=@(x)nnz(diff(x))/max(numel(x)-1,1)
```
Comments:
* In old Matlab versions (such as R2010b) you need `+` to cast the char array `x` to a double array:
```
f=@(x)nnz(diff(+x))/max(numel(x)-1,1)`
```
But that's not the case in recent versions (tested in R2014b), which saves one byte. Thanks to Jonas for his comment.
* The expression with `max` handles the one-character and zero-character cases (for chunkiness)
Example:
```
>> f=@(x)nnz(diff(x))/max(numel(x)-1,1)
f = 
    @(x)nnz(diff(x))/max(numel(x)-1,1)
>> f('Peanut Butter')
ans =
   0.9167
```
[Answer]
# [><>](http://esolangs.org/wiki/Fish), ~~40~~ 36 bytes
```
00ii:0(?v:@=1$-{+{1+}}20.
~:0=+,n;>~
```
This program returns the chunkiness of a string.
## Explanation
```
00i         Push 0 (# unequal pairs), 0 (length of string - 1) and read first char
[main loop]
i           Read a char
:0(?v       If we've hit EOF, go down a row
:@=1$-      Check (new char != previous char)
{+          Add to unequal pairs count
{1+         Increment length by 1
}}20.       Continue loop
[output]
~~          Pop last two chars (top one will be -1 for EOF)
:0=+        Add 1 to length if zero (to prevent division by zero errors)
,           Divide, giving chunkiness
n;          Output and halt
```
---
## Previous submission (37 + 3 = 40 bytes)
```
l1)?v1n;
n,$&\l1-}0& \;
l2(?^$:@=&+&>
```
This program returns the smoothness of a string. Input is via the `-s` flag, e.g.
```
py -3 fish.py chunkiness.fish -s "Peanut Butter"
```
[Answer]
## **C#, ~~94~~ 89 bytes**
Sub 100 bytes, so I guess that's some form of victory in itself?
This is a function definition (allowed as per the spec) which returns the **smoothness** of the input string:
```
Func<string,float>(s=>s.Length>1?s.Zip(s.Skip(1),(a,b)=>a==b?1f:0).Sum()/(s.Length-1):1);
```
Pretty straightforward, if the length is 0 or 1 it returns 1, otherwise it compares the string to itself less the first character, then returns the number of identical pairs divided by the number of pairs.
*Edit - replaced Substring with Skip. Rookie mistake!*
[Answer]
## J, ~~14~~ 13 bytes
Computes the chunkiness. Kudos to J for defining `0 % 0` to be equal to 0.
```
(]+/%#)2~:/\]
```
[Try it online](https://tio.run/##y/r/P81WT0EjVltfVVnTqM5KPyb2f2pyRn6NlUZhaX5JqnWapppdopVOcmmJj5tCcUlKZp6C4X@ugNTEvNISBafSkpLUIq7kjNC87Equ4uLi3FwgwWVpacnl6MjlmMilCAA "J – Try It Online")
Here is an explanation:
```
   NB. sample input
   in =. 'sssmmsss'
   NB. all infixes of length 2
   2 ]\ in
ss
ss
sm
mm
ms
ss
ss
    NB. are the parts of the infix different?
    2 ~:/\ in
0 0 1 0 1 0 0
    NB. sum and item count of the previous result
    (+/ , #) 2 ~:/\ in
2 7
    NB. arithmetic mean: chunkiness
    (+/ % #) 2 ~:/\ in
0.285714
    NB. as a tacit verb
    (] +/ % #) 2 ~:/\ ]
    NB. 0 divided by 0 is 0 in J
    0 % 0
0
```
[Answer]
## CJam, 23 bytes
```
q_,Y<SS+@?2ew_::=:+\,d/
```
Explanation:
```
q                           e# read input
 _,                         e# its length
   Y<                       e# is less than 2?
     SS+                    e# then a smooth string
        @?                  e# otherwise the input
          2ew               e# pairs of consecutive characters
             _::=           e# map to 1 if equal, 0 if not
                 :+         e# sum (number of equal pairs)
                   \,       e# total number of pairs
                     d/     e# divide
```
This outputs the smoothness ratio.
[Answer]
# CJam, 16 bytes
```
1q2ew::=_:+\,d/*
```
Cheaty source code that calculates **smoothness**.
For inputs of length 0 or 1, this prints the correct result before exiting with an error. With the Java interpreter, error output goes to STDERR ([as it should](http://meta.codegolf.stackexchange.com/a/4781)).
If you [try the code online](http://cjam.aditsu.net/#code=1q2ew%3A%3A%3D_%3A%2B%5C%2Cd%2F*&input=!), just ignore everything but the last line of output.
### How it works
```
1q               e# Push a 1 and read from STDIN.
  2ew            e# Push the overlapping slices of length 2.
                 e# This will throw an error for strings of length 0 or 1,
                 e# so the stack (1) is printed and the program finishes.
     ::=         e# Twofold vectorized comparision.
        _:+      e# Push a copy and add the Booleans.
           \,    e# Swap with the original and compute its length.
             d/  e# Cast to double and divide.
               * e# Multiply with the 1 on the bottom of the stack.
```
[Answer]
# Julia, 52 bytes
Smoothness!
```
s->(n=length(s))<2?1:mean([s[i]==s[i+1]for i=1:n-1])
```
This creates an unnamed function that accepts a string and returns a numeric value.
If the length of the input is less than 2, the smoothness is 1, otherwise we calculate the proportion of identical adjacent characters by taking the mean of an array of logicals.
[Answer]
# Nim, ~~105~~ ~~96~~ 91 bytes
```
proc f(s):any=
 var a=0;for i,c in s[.. ^2]:a+=int(s[i+1]!=c)
 a.float/max(s.len-1,1).float
```
Trying to learn Nim. This calculates the chunkiness of a string.
*(~~If I try to read this as Python the indentation looks all messed up...~~ Now it looks more like Ruby...)*
[Answer]
# Python 3, 63 Bytes
This is an anonymous lambda function which takes a string as the argument, and returns it's chunkiness.
```
lambda n:~-len(n)and sum(x!=y for x,y in zip(n,n[1:]))/~-len(n)
```
To use it, give it a name and call it.
```
f=lambda n:~-len(n)and sum(x!=y for x,y in zip(n,n[1:]))/~-len(n)
f("Peanut Butter") -> 0.08333333333333333
f("!")             -> 0
f("")              -> -0.0
```
[Answer]
# Python 3, 52 bytes
```
lambda s:sum(map(str.__ne__,s,s[1:]))/(len(s)-1or 1)
```
This calculates chunkiness, and outputs `-0.0` for the empty string. If don't like negative zeroes you can always fix that with an extra byte:
```
lambda s:sum(map(str.__ne__,s,s[1:]))/max(len(s)-1,1)
```
[Answer]
# Haskell, 64 bytes
```
f[]=1
f[_]=1
f x=sum[1|(a,b)<-zip=<<tail$x,a==b]/(sum(x>>[1])-1)
```
Outputs smoothness. e.g. `f "Peanut Butter"` -> `8.333333333333333e-2`.
How it works:
```
f[]=1                               -- special case: empty list
f[_]=1                              -- special case: one element list
f x=                                -- x has at least two elements
         (a,b)<-zip=<<tail$x        -- for every pair (a,b), drawn from zipping x with the tail of itself
                            ,a==b   -- where a equals b
      [1|                        ]  -- take a 1
   sum                              -- and sum it
              /                     -- divide  by
                   (x>>[1])         -- map each element of x to 1
               sum                  -- sum it
                           -1       -- and subtract 1
```
`sum(x>>[1])` is the length of x, but because Haskell's strong type system requires to feed fractionals to `/`, I can't use `length` which returns integers. Converting integers to fractionals via `fromInteger$length x` is far too long.
[Answer]
## JavaScript (ES6), 55 bytes
### Smoothness, 56 bytes
```
f=x=>(z=x.match(/(.)(?=\1)/g))?z.length/--x.length:+!x[1]
```
### Chunkiness, 55 bytes
```
f=x=>(z=x.match(/(.)(?!\1)/g))&&--z.length/--x.length||0
```
### Demo
Calculates smoothness, as that is what I prefer. Only works in Firefox for now, as it is ES6.
```
f=x=>(z=x.match(/(.)(?=\1)/g))?z.length/--x.length:+!x[1]
O.innerHTML += f('Peanut Butter') + '\n';
O.innerHTML += f('chUnky') + '\n';
O.innerHTML += f('sssmmsss') + '\n';
O.innerHTML += f('999') + '\n';
O.innerHTML += f('AA') + '\n';
O.innerHTML += f('Aa') + '\n';
O.innerHTML += f('!') + '\n';
O.innerHTML += f('') + '\n';
```
```
<pre id=O></pre>
```
[Answer]
# KDB(Q), 30
Returns smoothness.
```
{1^sum[x]%count x:1_(=':)(),x}
```
# Explanation
```
                         (),x    / ensure input is always list
                x:1_(=':)        / check equalness to prev char and reassign to x
   sum[x]%count                  / sum equalness divide by count N-1
 1^                              / fill null with 1 since empty/single char will result in null
{                             }  / lamdba
```
# Test
```
q){1^sum[x]%count x}1_(=':)(),x}"Peanut Butter"
0.08333333
q){1^sum[x]%count x:1_(=':)(),x}"sssmmsss"
0.7142857
q){1^sum[x]%count x:1_(=':)(),x}"Aa"
0f
q){1^sum[x]%count x:1_(=':)(),x}"aa"
1f
q){1^sum[x]%count x:1_(=':)(),x}"chUnky"
0f
q){1^sum[x]%count x:1_(=':)(),x}"!"
1f
q){1^sum[x]%count x:1_(=':)(),x}""
1f
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~69~~ 66 bytes
```
->s{(c=s.chars.each_cons(2).count{|x,y|x!=y}.to_f/~-s.size)>0?c:0}
```
[Try it online!](https://tio.run/##FY1BC4IwGEDv@xVLAxVySUdhdu3YPUJ0TBRsE79vsDXXT2/Z4b3je6vpXRx4LBvwueDAxNitwGQnxlZoBfmlYEIbhX6zJ7fZA3eBoW6H86cEBtNbFk11FXUVoqWcHts9oF8LWQwCTbLU25DVNPXDwz5DEu@yUwZpbxDlSm5ynvVu98cR8tULTvs0luoH "Ruby – Try It Online")
Shaved of a few bytes with comments from IMP. Also, with the upcoming version 2.7.0 of Ruby it's possible to save some bytes by replacing `|x,y|x!=y` with `@1!=@2`
[Answer]
# Python 3, 69 bytes
No one has posted a Python solution yet, so here's a fairly straightforward implementation of a "chunkiness" function. It short-circuits on a string of length `1`, and prints `0` (which is an integer rather than a float but seems to be allowed according to the rules).
On an empty string, it outputs `-0.0` rather than `0.0`. Arguably this is could be considered acceptable, as `-0.0 == 0 == 0.0` returns `True`.
```
def c(s):l=len(s)-1;return l and sum(s[i]!=s[i+1]for i in range(l))/l
```
Examples:
```
>>> c(''); c('a'); c('aaa'); c("Peanut Butter")
-0.0
0
0.0
0.916666666667
>>> -0.0 == 0 == 0.0
True
```
(Python 3 is used for its default float division.)
[Answer]
# C, 83 bytes
```
float f(char*s){int a=0,b=0;if(*s)while(s[++a])b+=s[a]!=s[a-1];return--a?1.*b/a:b;}
```
A function returning **chunkiness**.
### Explanation
```
float f(char *s) {
```
Accept a C string, and return a float (double would work but is more chars).
```
int a=0, b=0;
```
Counters - `a` for total pairs, `b` for non-matching pairs. Using `int` limits the "arbitrary length" of the string, but that's only a minor violation of the requirements and I'm not going to fix it.
```
if (*s)
```
Special case the empty string - leave both counters zero.
```
    while (s[++a])
```
Non-empty string - iterate through it with pre-increment (so first time through the loop, `s[a]` will be the second character. If the string has only one character, the loop body will not be entered, and `a` will be 1.
```
        b += s[a]!=s[a-1];
```
If the current character differs from the previous, increment `b`.
```
return --a ? 1.*b/a : b;
}
```
After the loop, there are three possibilities: 'a==0,b==0' for an empty input, 'a==1,b==0' for a single-character input or 'a>1,b>=0' for multi-character input. We subtract 1 from `a` (the `?` operator is a sequence point, so we're safe), and if it's zero, we have the second case, so should return zero. Otherwise, `b/a` is what we want, but we must promote `b` to a floating-point type first or we'll get integer division. For an empty string, we'll end up with a negative zero, but the rules don't disallow that.
### Tests:
```
#include <stdio.h>
int main(int argc, char **argv)
{
    while (*++argv)
        printf("%.6f %s\n", f(*argv), *argv);
}
```
Which gives:
```
./chunky 'Peanut Butter' chUnky sssmmsss 999 AA Aa '!' ''
0.916667 Peanut Butter
1.000000 chUnky
0.285714 sssmmsss
0.000000 999
0.000000 AA
1.000000 Aa
0.000000 !
-0.000000 
```
as required.
[Answer]
# Perl, 69
Function returning **smoothness**:
```
sub f{($_)=@_;$s=s/(.)(?!\1)//sgr;chop;!$_||length($s)/length;}
```
### Explanation
```
sub f {
    # read argument into $_
    ($_) = @_;
    # copy $_ to $s, removing any char not followed by itself
    # /s to handle newlines as all other characters
    $s = s/(.)(?!\1)//sgr;
     # reduce length by one (unless empty)
    chop;
    # $_ is empty (false) if length was 0 or 1
    # return 1 in that case, else number of pairs / new length
    !$_ || length($s)/length;
}
```
### Tests
```
printf "%.6f %s\n", f($a=$_), $a foreach (@ARGV);
0.083333 Peanut Butter
0.000000 chUnky
0.714286 sssmmsss
1.000000 999
1.000000 AA
0.000000 Aa
1.000000 !
1.000000 
```
[Answer]
# Ruby, 63 Bytes
Outputs chunkiness.
`f=->s{s.chars.each_cons(2).count{|x,y|x!=y}/[s.size-1.0,1].max}`
Similar to @daniero's solution, but slightly shortened by directly dividing by the string length - 1 and then relying on .count to be zero with length 0 & 1 strings (the .max ensures I won't divide by 0 or -1).
[Answer]
## Mathematica, ~~73~~ 72 bytes
This doesn't win anything for size, but it's straightforward:
Smoothness
```
N@Count[Differences@#,_Plus]/(Length@#-1)&@StringSplit[#,""]&
In[177]:= N@Count[Differences@#,_Plus]/(Length@#-1)&@StringSplit[#,""] &@"sssmmsss"
Out[177]= 0.285714
```
[Answer]
# GeL: ~~76~~ 73 characters
Smoothness.
```
@set{d;0}
?\P$1=@incr{d}
?=
\Z=@lua{c=@column -1\;return c<1and 1or $d/c}
```
Sample run:
```
bash-4.3$ for i in 'Peanut Butter' 'chUnky' 'sssmmsss' '999' 'AA' 'Aa' '!' ''; do
>     echo -n "$i -> "
>     echo -n "$i" | gel -f smooth.gel
>     echo
> done
Peanut Butter -> 0.083333333333333
chUnky -> 0
sssmmsss -> 0.71428571428571
999 -> 1
AA -> 1
Aa -> 0
! -> 1
 -> 1
```
(GeL = Gema + Lua bindings. Much better, but still far from winning.)
# Gema: ~~123~~ 120 characters
Smoothness.
```
@set{d;0}
?\P$1=@incr{d}
?=
\Z=@subst{\?\*=\?.\*;@cmpn{@column;1;10;10;@fill-right{00000;@div{$d0000;@sub{@column;1}}}}}
```
Sample run:
```
bash-4.3$ for i in 'Peanut Butter' 'chUnky' 'sssmmsss' '999' 'AA' 'Aa' '!' ''; do
>     echo -n "$i -> "
>     echo -n "$i" | gema -f smooth.gema
>     echo
> done
Peanut Butter -> 0.0833
chUnky -> 0.0000
sssmmsss -> 0.7142
999 -> 1.0000
AA -> 1.0000
Aa -> 0.0000
! -> 1.0
 -> 1.0
```
(Was more an exercise for myself to see what are the chances to solve it in a language without floating point number support and generally painful arithmetic support. The 2nd line, especially the `\P` sequence, is pure magic, the last line is real torture.)
[Answer]
# Java 8, ~~84~~ 82 bytes
```
s->{float l=s.length()-1,S=s.split("(.)(?=\\1)").length-1;return l<1?1:S<1?0:S/l;}
```
Outputs Smoothness.
[Try it online.](https://tio.run/##lZPfT8IwEMff/SvOPbWRlRUxCgMJJj5qTBaf1IfSFRiUblk7IjH87Vj2gzBgJjZdk2t7n/v2drdga@YuwuWOS6Y1vLBI/VwBRMqIdMq4gNe9CTCVMTPAUWDSSM1AY99ub@1npzbMRBxeQcEQdtp9/Cluy6EmUqiZmSPs0lZgTZ3IyCAHEYxGw89Pih1cXnGpnwqTpQrkgI5oP7Cr1w/a0t/u/CJOkk2kjVOGW8dRCCurt9T08cVwodUIbWO8CaYyA0@ZsU9xsG8P2m14/k4ENyLsg0e8h1tCCCAKCYvSFtAOqFi5e0PjIxKfv6vlpkCUo06qdpGXk3QL7i6TtNarlV2OWCea7mk313RXkRo09Xq9mqBTEj1o6lQk7zJpPD4FNZGqPDWB2N@gC2miB9Ix6PqM06SoKB0YAD32P3f/nz/bj4kdnPMwFHtcw1@i3eol3XpO6p2Rl2rOPrRPUanBRhuxInFmSGIPDCr6yrZbnCJr11rIv7mRg47n4zMvB5zS7/RIKqQIt9iyX7e7Xw)
**Explanation:**
```
s->{                     // Method with String parameter and float return-type
  float l=s.length()-1,  //  Length of the input-String minus 1 (amount of pairs in total)
        S=s.split("(.)(?=\\1)").length-1;
                         //  Length of the input split by duplicated pairs (with lookahead)
  return l<1?            //  If the length of the input is either 0 or 1:
          1              //   Return 1
         :S<1?           //  Else-if `S` is -1 or 0:
          0              //   Return 0
         :               //  Else:
          S/l;}          //   Return duplicated pairs divided by the length-1
```
[Answer]
# [Coconut](http://coconut-lang.org/), 38 bytes
```
s->sum(map((!=),s,s[1:]))/-~len(s[2:])
```
[Try it online!](https://tio.run/##RY5BCsIwEEWvkgahE2iUii5SaKGewI2r6qKUBEWTlkwKlVqvHpNu3Lz5D2aY3/Vdb0bnVXn1yCscNeh2AEhKlmGGTV7cGNvx70sawGYfzAM9yzbckNPonLQ0I7S7X8zzHRMiah0QsxAijrpe2UYmEZSRT0XCmw1MhFdEpfOU2CI/LtFmBRMrtge1pP@9wT6MWzXUDSWl/wE "Coconut – Try It Online")
A Python 3 port would be [50 bytes](https://tio.run/##Hce9DoIwFIbh3as4sNAmgMGfgSaa4BW4OKEhVdtApIX0HAZC8NaRujzf@/Uj1Z3dL/p0X1ppnm8JKHAwzMieIbm0qqyqqhhjLDPx4HybfFtlGZa79S26c0DQWGDhVUk7EFwGIuXCGMJXfbOf0RciGrPiO89zP0XxV3oDT8jFBqB3jSWmo4kCJ7LjDMkZJs2Ii/Sg54gvPw).
[Answer]
## PowerShell, 55 bytes
Smoothness
```
%{$s=$_;@([char[]]$s|?{$_-eq$a;$a=$_;$i++}).count/--$i}
```
Seems a little bit silly to get a variable in stdin and then give it an identifier, but its quicker than having a function.
[Answer]
# Python 3, 61 Bytes
calculate chunkiness:
```
f=lambda s: sum(a!=b for a,b in zip(s,s[1:]))/max(len(s)-1,1)
```
[Answer]
# K (22)
tweaked WooiKent's Q solution:
```
{1^(+/x)%#x:1_=':(),x}
```
[Answer]
# Mathematica, 107 bytes
Calculates chunkiness by taking half of the Levenshtein distance between each digraph and its reverse.
```
f[s_]:=.5EditDistance@@{#,StringReverse@#}&/@StringCases[s,_~Repeated~{2},Overlaps->All]//Total@#/Length[#]&
```
If you'd prefer an exact rational answer, delete `.5` and place a `/2` before the last `&` for no penalty. The program itself has chunkiness 103/106, or about .972.
]