night/regex/base10-inc.sed

78 lines
2.2 KiB
Sed

# Increment base-10 number by 1
#
# Copyright (C) 2018 Mike Gerwitz
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This shows how to perform basic arithmetic on numbers using regular
# expressions. The method is outlined below. It's easy to see that, for
# any base-N number of M digits, we need NM regexes. For K such numbers, we
# need NMK regexes. The more M or K we have, the more complex the regexes
# become to handle the offsets. (The use of the `^' and `$' anchors alone
# for replacements are only sufficient for M≤3 when K=1; what do we have to
# do when M>3 to replace only the digits we are interested in?)
#
# It is possible to subtract using the same concept (see `base10-mul.sed').
# Further, since we can implement addition and subtraction, we can also
# implement multiplication and division.
#
# TO USE: Provide a 0-padded 3-digit base-10 number. Each time this script
# is run, the number will be incremented by one. Exits with exit code 1 if
# a non-3-digit-number is provided; and 2 once we cannot count any higher.
##
# Input must only be numbers
/^[0-9]\{3\}$/!q1
# Increment 1s (third character). If we overflow, represent the overflow as
# an `A', which is then handled below.
s/9$/A/
s/8$/9/
s/7$/8/
s/6$/7/
s/5$/6/
s/4$/5/
s/3$/4/
s/2$/3/
s/1$/2/
s/0$/1/
# Carry 10s by converting the overflow character `A' to a `0' and
# incrementing the 10s position.
s/9A$/A0/
s/8A$/90/
s/7A$/80/
s/6A$/70/
s/5A$/60/
s/4A$/50/
s/3A$/40/
s/2A$/30/
s/1A$/20/
s/0A$/10/
# Same as above, but for 100s.
s/^9A/A0/
s/^8A/90/
s/^7A/80/
s/^6A/70/
s/^5A/60/
s/^4A/50/
s/^3A/40/
s/^2A/30/
s/^1A/20/
s/^0A/10/
# Any remaining carry flags means we can't count any higher.
/A/!b; q2