Probability that Three Pieces Form a Triangle I wrote some code to estimate the solution to the following problem:

If you break a line segment at two random points, what is the probability that the new line segments can form a triangle?

The code is relatively simple, and it works. However, I can't shake the feeling that each of the three functions I've created could be written more &quot;Pythonically.&quot; For example, the first function (can_form_triangle) explicitly writes out the combinations of pairs from (a, b, c) and then compares them to the element of (a, b, c) which is not in the pair. There must be a way to express this more succinctly, more elegantly — more Pythonically.
To be clear, I'd just like advice on refactoring the code to be more elegant/Pythonic. I am not looking for advice on how to change the actual functionality to solve the problem more efficiently.
Here's the code:
#!/usr/bin/python3

from random import random


def can_form_triangle(a, b, c):
    '''Determines if lengths a, b, and c can form a triangle.

    Args:
        a, b, c: Number representing the length of a side of a (potential) triangle

    Returns:
        True if all pairs from (a, b, c) sum to greater than the third element
        False otherwise
    '''
    ab = a + b
    ac = a + c
    bc = b + c

    if (ab &gt; c and ac &gt; b and bc &gt; a):
        return True

    return False


def try_one_triangle():
    '''Simulates breaking a line segment at two random points and checks if the segments can form a triangle.

    Returns:
        True if the line segments formed by breaking a bigger line segment at two points can form a triangle
        False otherwise
    '''
    first_point = random()
    second_point = random()
    sorted_points = sorted((first_point, second_point))

    return can_form_triangle(sorted_points[0], sorted_points[1] - sorted_points[0], 1 - sorted_points[1])


def estimate_triangle_probability():
    num_success = num_attempts = 0
    for _ in range(10000000):
        num_success += 1 if try_one_triangle() else 0
        num_attempts += 1

    print('Success:', num_success)
    print('Attempts:', num_attempts)
    print('Ratio:', num_success / (num_attempts))


if __name__ == '__main__':
    estimate_triangle_probability()
Direct boolean return

As @Grajdeanu Alex says, this:

if (ab &gt; c and ac &gt; b and bc &gt; a):
    return True

return False


can simply be

return ab &gt; c and ac &gt; b and bc &gt; a


Type hints

def can_form_triangle(a, b, c):


can be

def can_form_triangle(a: float, b: float, c: float) -&gt; bool:


Sort unpack

first_point = random()
second_point = random()
sorted_points = sorted((first_point, second_point))

return can_form_triangle(sorted_points[0], sorted_points[1] - sorted_points[0], 1 - sorted_points[1])


can be

    first_point, second_point = sorted((random(), random()))

    return can_form_triangle(first_point, second_point - first_point, 1 - second_point)


Digit triples

10000000 is more easily read as 10_000_000.

Attempt looping

num_attempts will evaluate to 10_000_000 so it's not worth tracking unless you add an early-exit mechanism.

The whole loop can be replaced with

num_success = sum(
    1
    for _ in range(10_000_000)
    if try_one_triangle()
)


Redundant parentheses

print('Ratio:', num_success / (num_attempts))


does not need the inner parens.