Exercise 12-10:

Write a function that accepts prices in dollars. The program must ignore white spaces and accept values prefixed with $ or not. The user must enter correctly formatted values with a comma separating the thousands and a period separating the cents. If the user types cents, they must have two digits.

Valid values:
$500
   $500
$500.10
$7,312.10

Invalid values:
$500.1
500.1$
500.1
7312.10$

The function must return the entered value converted to float or generate a ValueError exception if the value entered is invalid.

Answer:

##############################################################################
# Python From Scratch
# Author: Nilo Ney Coutinho Menezes
# Editora Novatec (c) 2010-2025 - LogiKraft 2025
# Site: https://pythonfromscratch.com
# ISBN: 978-85-7522-949-1 (Paperback), 978-85-7522-950-7 (hardcover), 978-85-7522-951-4 (ebook)
#
# File: chapter 12/exercise-12-10.py.py
##############################################################################
import re

DOLLARS_RE = r"^(([rR]\$)?(((\d{1,3}\.)?(\d{3}\.)*?\d{3})|(\d{1,3}))(,\d{2})?)$"
# ^ - From the start of the string
# ( - Group of the right part of the expression, before the comma
#  ([rR]\$)? - Optionally can have R$
#  ( - Group of the integer part
#   ((\d{1,3}\.)?(\d{3}\.)*?\d{3}) - Group of the integer part with dots separating thousands
#   Required to ensure that parts between dots have 3 digits, except the first one
#   | - or
#   (\d{1,3}) - Group of the integer part without dots
#  ) - Group of the right part
# (,\d{2})? - Optionally can have the decimal part
# )$ - Until the end of the string


def clean_spaces(input):
    return input.replace(" ", "")


def dollars(input):
    # It's easier to clean spaces before validation,
    # since the regular expression is already quite complex
    # Remember: you don't need to use regex for everything!
    input = clean_spaces(input)
    return bool(re.match(DOLLARS_RE, input))


inputs = [
    "R$ 1.234,56",  # Yes
    "r$ 1.234,56",  # Yes
    "r$1.234,56",  # Yes
    "r$12.123.234,56",  # Yes
    "1.234,56",  # Yes
    "R$1.234,56",  # Yes
    "r$234,56",  # Yes
    "R$234,56",  # Yes
    "234,56",  # Yes
    "r$234",  # Yes
    "R$234",  # Yes
    "R$2",  # Yes
    "R$23",  # Yes
    "234",  # Yes
    "34",  # Yes
    "4",  # Yes
    "r$234,4",  # No - Cents must have 2 digits
    "R$234,4",  # No - Cents must have 2 digits
    "R$1234,4",  # No - Missing . to separate thousands
    "r$1234,4",  # No - Missing . to separate thousands
    "r$1234.12,4",  # No - Incorrect use of thousands separator (.)
    "r$1.24,56",  # No - Irregular, only two numbers after the .
]


for input in inputs:
    print(f"{input}: {dollars(input)}")
Click here to download the file