Smooth vs. Chunky vs. Broken Squiggles

Based on Chunky vs. Smooth Strings.

Squiggles /\_/\/\__/\/\/\/\_/\_/\ are fun to make on a keyboard when you are really bored. But not all squiggles are created equal. Some squiggles are smooth, like \___/, and some are chunky, like /\/\/\/\. Others are just downright broken, like ////_\\\

Inside every squiggle of N characters, there are N-1 squiggle-junctions. Each squiggle-junction is classified into one of three types:

• Smooth (angle > "90 degrees"):

\_ __ _/

• Chunky (angle = "90 degrees")

/\ \/

• Broken (anything that doesn't connect)

// \\ /_ _\

Let's define the smoothness to be the proportion of junctions that are smooth, with chunkiness and brokenness defined similarly. Each value ranges between 0 and 1. The sum of a squiggle's smoothness, chunkiness, and brokenness is always equal to 1.

For example, the squiggle /\/\\_//\_ has 3 smooth junctions, 4 chunky junctions, and 2 broken junctions. It is thus 0.3333 smooth, 0.4444 chunky, and 0.2222 broken.

Empty strings and strings with only one character have undefined values, all input will be at least 2 characters long.

Challenge

Write a program that takes in a squiggle of arbitrary length and outputs any two of its smoothness, chunkiness, and brokenness values.

• You may write a program or function, with input via STDIN, command line, or as a string argument.
• You may assume the input is at least of length >= 2 and consists only of the characters /\_ with an optional trailing newline.
• Print (or return if a function) the two floats to a precision of at least 4 decimals, rounded or truncated. If the true value is 2/3, acceptable values include any value between 0.6666 and 0.6667, even things like 0.666637104. If the exact value is 1/3, any answer containing 0.3333 is valid. You may leave off trailing zeros, or the leading zero if the value is less than one.
• Output any pair of the three values as you prefer, just be sure to state which two and in what order.

The shortest code in bytes wins.

Examples

/\/\\/\//\\ → Smoothness 0, Chunkiness 0.7, Brokenness 0.3

_/\\_/\\/__/\\\//_ → Smoothness 0.29411764705, Chunkiness 0.29411764705, Brokenness 0.41176470588

//\\__/_\/ → Smoothness 0.3333333, Chunkiness 0.2222222, Brokenness 0.4444444

Bonus question: Which do you prefer, smooth or chunky or broken squiggles?

• Could there be a bonus for outputting all three, or do you have a specific reason for choosing only two? Jan 9, 2016 at 3:42
• @Callodacity 2 are sufficient to define the 3rd since they sum to 1 Jan 9, 2016 at 3:43
• @trichoplax good point - obviously I've been golfing too long, I can't comprehend simple things anymore :P Jan 9, 2016 at 3:44

Pyth, 25 bytes

mcl@.:d2.:z2tlzc2"\__//\/


Test suite

Outputs smoothness, chunkiness. Basically, it takes the hard coded string and cuts it in half. Each half is decomposed into its 2 character substrings, and the same is done for the input. We take the intersection, resulting in the south and chunky pairs. Then, we take the the length, divide by the number of pairs, and print.

Japt, 42 bytes

U=U¬ä@2+"\\/\\__/"bX+Y)f2};[T2]£U¬fX l /Ul


Outputs brokenness, chunkyness. Try it online!

How it works

            // Implicit: U = input string
U=U¬ä@   }  // Set U to U split into chars, with each pair mapped by this function:
"..."bX+Y)  // Take the index in this string of the two chars concatenated.
// This is 0-1 for chunky, 2-4 for smooth, and -1 for broken.
2+    f2    // Add two and floor to the nearest multiple of 2.
// This is now 2 for chunky, 4 or 6 for smooth, and 0 for broken.
[T2]£       // Map each item X in [0,2] through this function:
U¬fX l      //  Count the occurances of X in U.
/Ul         //  Divide by U.length.
// Implicit: output last expression


Non-competing version, 36 bytes

U=Uä@2+"\\/\\__/"bZ)f2};[T2]£UèX /Ul


Works in basically the same way as the other, with a few minor changes:

• ä now works on strings. The chars are passed into the function in order (X, Y, X+Y).
• è counts the number of occurrences of the argument in the string/array.

Ruby, 71

Outputs smoothness, chunkiness.

Takes the minimal smooth and chunky strings and searches them for every two-character string in the initial string.

Thanks to Kevin Lau for EIGHT bytes!

->x{%w{\\__/ /\\/}.map{|t|(0..n=x.size-2).count{|i|t[x[i,2]]}/(n+1.0)}}

• (0..x.size-2).count{|i|t[x[i,2]]} saves 5 bytes over x.chars.each_cons(2).count{|i|t[i*'']}. And now that you're using x.size twice in the function, assigning it to a variable and using that saves an extra byte. Apr 10, 2016 at 0:58
• @KevinLau Managed to save 8 bytes using your approach. Thanks! Apr 11, 2016 at 14:05

Python 3, 149 bytes

This outputs smoothness and chunkyness.

def f(s):
for i in"012":s=s.replace("\_/"[int(i)],i)
a=len(s)-1;t=["bscbssbbc"[int(s[i:i+2],3)]for i in range(a)]
for x in"sc":print(t.count(x)/a)


Ungolfed:

def f(s):
for i in "012":
s = s.replace("\_/"[int(i)], i)
a = len(s) - 1
t = []
for i in range(a):
t.append("bscbssbbc"[int(s[i:i+2],3)])
for x in "sc":
print(t.count(x) / a)


Python 3.8 (pre-release), 82 79 bytes

lambda x:[sum(a+b in s for a,b in zip(x,x[1:]))/~-len(x)for s in["\__/","/\/"]]


Try it online!

-3 from @xnor by not using index i into array

Python, 90 bytes

f=lambda x,s=0,c=0,n=0:x[1:]and f(x[1:],s+(x[:2]in"\__/"),c+(x[:2]in"/\/"),n+1)or(s/n,c/n)


Attempt This Online!

Recursive solution -- longer, but I think it's more elegant.

• -3 bytes by cutting out the index i
– xnor
Oct 2, 2022 at 22:24