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.


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


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, chunky or smooth strings?

  • 8
    \$\begingroup\$ -1 No overhanded tag. \$\endgroup\$
    – Dennis
    Jul 14 '15 at 2:45
  • 22
    \$\begingroup\$ +1 Conclusive proof that chunky peanut butter should be the default. \$\endgroup\$
    – BrainSteel
    Jul 14 '15 at 3:25
  • \$\begingroup\$ Some languages have a hard time reading no input at all. Would it be admissible to assume that the input is newline-terminated? \$\endgroup\$
    – Dennis
    Jul 14 '15 at 4:25
  • \$\begingroup\$ @Dennis Yes, that's fine. \$\endgroup\$ Jul 14 '15 at 4:32
  • 9
    \$\begingroup\$ @BrainSteel Chunky should only be the default if you're a computer; they like having chunks available. Peanut butter made for people should hide those implementation details, and be smooth as silk for the user. \$\endgroup\$
    – Geobits
    Jul 14 '15 at 13:01

36 Answers 36


K5, 24 bytes


Calculates smoothness. Seems to use a very different algorithm from K/Q/J/APL answers.


Jelly, 7 4 bytes

 Ɲ   // For all pairs of neighbouring elements,
=    // return 1 if they're equal, 0 otherwise.
  Æm // Take the arithmetic mean of the resulting list.

Computes smoothness.
Cut off three bytes thanks to Dennis.

Try it online!


Forth (gforth), 92 bytes

: f 1e dup 1 > if 1- dup s>f 0e 0 do dup i + dup 1+ c@ swap c@ = s>f f- loop fswap f/ then ;

Try it online!

Takes in a string (as the Forth standard combo of address and length) and returns the smoothness. Result is placed on the floating point stack


1e                \ places 1 on the floating point stack, to use as a "default" value
dup 1 > if        \ duplicates the length of the string and checks if it's greater than 1
   1- dup s>f     \ subtract 1 from length and copy it to the floating point stack
   0e             \ places 0 on the floating point stack
   0 do           \ sets up a loop from 0 to length - 1
      dup i +     \ get the current character's address by adding index to string start
      dup 1+      \ copy address and add 1 to get the next character's address
      c@ swap c@  \ get the character at each of the addresses
      = s>f       \ compare the two characters and move to the floating point stack
      f-          \ subtract result from counter (true in Forth defaults to -1)
   loop           \ end the loop
   fswap f/       \ swap the counter and the total and divide to get result
then              \ end the loop

JavaScript, 46/47 bytes



F# (.NET Core), 100 bytes

Whew, exactly 100 bytes. Too bad it's a bit verbose, I want to get it below 100. Determines chunkiness.

fun s->Seq.pairwise s|>fun s->Seq.sumBy(fun(x,y)->if x=y then 0. else 1.)s/float(max(Seq.length s)1)

Try it online!


Kotlin, 52 bytes



Try it online!


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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