1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
|
# Soros Tutorial – Part Five 🚀 ... Go!
#
# We will complete the following number to English
# number name conversion program, learning special
# features of Soros programming language.
0 zero
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine
10 ten
11 eleven
12 twelve
13 thirteen
# TASK 1 – Call me again!
#
# A Soros program is a single function, named $(). It’s
# possible to call this function in the regex replacement
# part with arbitrary text as an argument, and its return value
# will be inserted in the regex replacement at the place of
# the function call.
#
# In the following program line, the argument is “4”,
# and function call “$(4)” is replaced with “four”, the
# result of the call of function $ with the argument “4”:
14 $(4)teen
# Extend the line 16 this way!
15 fifteen
16
# TASK 2 – Reference and call...
#
# We can use regex references in function arguments.
# For example, we can describe 18 -> eighteen conversion
# this way, too:
1(8) $(\1)een
# Using the regex pattern \d (matching arbitrary digits),
# give a *single* program line for 17 -> seventeen and
# 19 -> nineteen conversion! (With this, line 14 and 16
# will be unnecessary, too.)
# TASK 3 – Abbreviation of $(\n) is $n
#
# According to the title of this task, $1 means $(\1),
# $2 means $(\2) etc. Rewrite the following program part to
# use this abbreviated form!
20 twenty
2(\d) twenty-$(\1)
# TASK 4 – Boundaries
#
# Soros programs have default automatic zero deletion in
# its arguments, ie. $(1) or $(01) are equivalents. But
# the following program line have a different problem for
# the input number 100: after left zero deletion it still
# remains a zero, resulting “one hundred zero” instead of
# “one hundred”:
1(\d\d) one hundred $1
# The solution is using boundary dependent patterns.
# These patterns can always match at the first run of the
# Soros program, but at the next recursive calls,
# matching depends from the position of the function call:
#
# ^pattern only matches, if the function call is there at
# the beginning of the replacement. Example:
# 1(\d) $1teen
#
# pattern$ only matches, if the function call is there at
# the end of the replacement. Example:
# 2(\d) twenty-$(\1)
#
# ^pattern$ only matches, if the function call is there at
# the beginning and the end of the replacement.
# Example:
# 1(\d) $(ordinal |$1)
#
# NOTE: “|” before or after function calls sets explicite
# boundary position.
#
# Correct the bug “one hundred zero” by using the
# correct boundary sign on the program line “0 zero”, also
# create a rule for negative numbers, to handle
# “-0” -> “minus zero” conversion correctly!
# TASK 5 – Deeper in recursion
#
# A recursive call can result further recursive calls,
# allowing to break a complex problem into smaller parts,
# or iterate a repeating task, as in the following
# example.
#
# The first line of the following program uses the
# boundary indicator $ to handle the originally 4-digit
# or less numbers differently. What is the full program
# doing with the other numbers? Try to answer, and
# check it in a different IDE window!
#
# ^(\d{1,4})$ \1
# (\d+)(\d{3}) $1,\2
# .* \0
# TASK 6 – Optional text, depending from the return value
#
# Previously, we had a different program line for 20 and one
# for 21–29 , because English uses a hyphen between the
# number names. Using brackets around the recursive calls,
# we can skip the first program line. The hyphen is only
# added to “thirty”, if the return value of the recursive
# function calls is not empty.
3(\d) thirty[-$(\1)]
# Write a *single* program line to handle “sixty”,
# “seventy” (60–79), and “ninety” (90–99)!
# TASK 7 – Language-dependent program lines
#
# Using [:lang-code:] in a comment sets a
# language-dependent program line. For example,
# German number to number name rules
#
# 3(\d) [$1und]dreissig # [:de-CH:]
# 3(\d) [$1und]dreißig
#
# result “dreissig” for the input “30”, if the language
# of the conversion is de-CH (Swiss Standard German),
# otherwise “dreißig”.
#
# It’s possible to use arbitrary number language codes
# in the same program line.
#
# In Australia, Great Britain, Ireland and New Zealand,
# 101 is “one hundred and one”, in other English speaking
# countries, like USA and Canada, 101 is “one hundred one”.
# Using the language codes en-AU, en-GB, en-IE and en-NZ
# and the previous conditional text, describe number 100–999
# in both variants!
# TASK 8 – More Functions
#
# In Soros language, there is only one real function, the $(),
# but it’s possible to create function-like structures by using
# prefixes.
#
# Numbertext.org language modules contain functions for
# number to money conversion (“USD 2” -> “two U.S. dollars”),
# number to ordinal name conversion (“2” -> “second”) and
# ordinal-number conversion (“2” -> “2nd”). For example,
# we can define ordinal numbers as follows:
#
# "ordinal 1" first
# "ordinal 2" second
# "ordinal 3" third
#
# According to the quotation marks, the regex patterns can
# contain spaces, too.
#
# For the space separated prefixes, there is a default left
# zero deletion, i.e. $(ordinal 1) is equivalent of
# $(ordinal 001), so program line
#
# "ordinal 1(\d\d)" one hundred $(ordinal \1)
#
# works also for the input 101, 102 etc. correctly using
# only the previous program lines.
#
# Other method of ordinal number conversion is to convert the
# input to the default cardinal number names, and modifying
# their text:
#
# "ordinal (\d+)" $(ordinal |$1)
# "ordinal (.*)one" \1first
# "ordinal (.*)two" \1second
#
# NOTE: As can be seen, it’s possible to embed function
# calls within function calls, too.
#
# What can be the last program line of this function?
# TASK 9 – Prefix “macros”
#
# Prefix macros simplify prefix handling. We can define
# the previous ordinal function as follows, too
# (see “ordinal” between double equal signs):
#
# == ordinal ==
#
# ^0 zeroth
# 1 first
# 2 second
# 3 third
#
# because this will be expanded in the following form:
#
# "^ordinal 0" zeroth
# "ordinal 1" first
# "ordinal 2" second
# "ordinal 3" third
#
# With the other method, converting cardinal number names,
# and later to ordinal ones:
#
# == ordinal ==
#
# (\d+) $(ordinal |$1)
# (.*)one \1first
# (.*)two \1second
# ...
# (.*) \1th
#
# How is this expanded?
# TASK 10 – Join Numbertext development!
#
# Your contribution will help LibreOffice and other free
# softwares to support chapter numbering with number names,
# converting money amounts to text (MONEYTEXT), creating
# plural forms of money amounts and support better
# title casing.
#
# Check and fix Soros code of your language on
# http://NUMBERTEXT.org, or if there is no such module yet,
# create it, based on the currency code of the
# English or the more flexible Swedish (sv.sor)
# modules!
SCROLL DOWN FOR SOLUTIONS
⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩
# SOLUTION – TASK 1–7 (for TASK 5, see next SOLUTION)
#
# Solutions marked as TASK 1–7 in comments:
#
# ^0 zero # TASK 4
# 1 one
# 2 two
# 3 three
# 4 four
# 5 five
# 6 six
# 7 seven
# 8 eight
# 9 nine
# 10 ten
# 11 eleven
# 12 twelve
# 13 thirteen
# # 14 $(4)teen
# 15 fifteen
# # 16 $(6)teen # TASK 1
# 18 eighteen
# 1(\d) $1teen # TASK 2
# 20 twenty
# 2(\d) twenty-$1 # TASK 3
# 3(\d) thirty[-$1]
# 4(\d) forty[-$1]
# 5(\d) fifty[-$1]
# 8(\d) eighty[-$1]
# (\d)(\d) $1ty[-$2] # TASK 5
#
# # separator function
# :0+ # one million
# :0*\d?\d " and " # one million and twenty-two
# :\d+ ", " # one million, one thousand
#
# (\d)(\d\d) $1 hundred[ and $2] # one hundred and one [:en-AU:] [:en-GB:] [:en-IE:] [:en-NZ:] # TASK 6
# (\d)(\d\d) $1 hundred[ $2] # default: one hundred one # TASK 6
# (\d{1,2})([1-9]\d\d) $1 thousand[ $2] # ten thousand two hundred
# (\d{1,3})(\d{3}) $1 thousand$(:\2)$2 # one hundred thousand, two hundred
# (\d{1,3})(\d{6}) $1 million$(:\2)$2
# (\d{1,3})(\d{9}) $1 billion$(:\2)$2
#
# # negative number
#
# [-−](\d+) negative |$1 # TASK 4
#
# # decimals
#
# 0[.,] point
# ([-−]?\d+)[.,] $1| point
# ([-−]?\d+[.,]\d*)(\d) $1| |$2
#
# # currency
#
# # unit/subunit singular/plural
#
# us:([^,]*),([^,]*),([^,]*),([^,]*) \1
# up:([^,]*),([^,]*),([^,]*),([^,]*) \2
# ss:([^,]*),([^,]*),([^,]*),([^,]*) \3
# sp:([^,]*),([^,]*),([^,]*),([^,]*) \4
#
# AUD:(\D+) $(\1: Australian dollar, Australian dollars, cent, cents)
# CAD:(\D+) $(\1: Canadian dollar, Canadian dollars, cent, cents)
# CHF:(\D+) $(\1: Swiss franc, Swiss francs, centime, centimes)
# CNY:(\D+) $(\1: Chinese yuan, Chinese yuan, fen, fen)
# EUR:(\D+) $(\1: euro, euro, cent, cents)
# GBP:(\D+) $(\1: pound sterling, pounds sterling, penny, pence)
# JPY:(\D+) $(\1: Japanese yen, Japanese yen, sen, sen)
# USD:(\D+) $(\1: U.S. dollar, U.S. dollars, cent, cents)
#
# "(JPY [-−]?\d+)[.,](\d\d)0" $1
# "(JPY [-−]?\d+[.,]\d\d)(\d)" $1 $2 rin
#
# "([A-Z]{3}) ([-−]?1)([.,]00?)?" $2$(\1:us)
# "([A-Z]{3}) ([-−]?\d+)([.,]00?)?" $2$(\1:up)
#
# "(CNY [-−]?\d+)[.,](\d)0?" $1 $2 jiao
# "(CNY [-−]?\d+[.,]\d)(\d)" $1 $2 fen
#
# "(([A-Z]{3}) [-−]?\d+)[.,](01)" $1 and |$(1)$(\2:ss)
# "(([A-Z]{3}) [-−]?\d+)[.,](\d)" $1 and |$(\030)$(\2:sp)
# "(([A-Z]{3}) [-−]?\d+)[.,](\d\d)" $1 and |$3$(\2:sp)
#
# == ordinal ==
#
# # convert to text, and recall to convert
# # cardinal names to ordinal ones
#
# ([-−]?\d+) $(ordinal |$1)
#
# (.*)one \1first
# (.*)two \1second
# (.*)three \1third
# (.*)five \1fifth
# (.*)eight \1eighth
# (.*)nine \1ninth
# (.*)twelve \1twelfth
# (.*)y \1ieth
# (.*) \1th # TASK 7
#
# == ordinal-number ==
#
# (.*1\d) \1th
# (.*1) \1st
# (.*2) \1nd
# (.*3) \1rd
# (.*) \1th
# SOLUTION – TASK 5
#
# This is a thousand separator
# program extended for all numbers.
# The middle line put a comma before
# the last three digits, and do the
# same for the remaining digits using
# a recursive call, and in that a
# next recursive call etc.
#
# ^(\d{1,4})$ \1
# (\d+)(\d{3}) $1,\2
# .* \0
#
# For example, for the input “10000000”
# the inner states of the calls:
#
# First call: $(10000),000
# Second call: $(10),000
# Third call: 10
#
# resulting “10,000,000” in the end of
# all returns.
# SOLUTION – TASK 9
#
# As before in TASK 8:
#
# "ordinal (\d+)" $(ordinal |$1)
# "ordinal (.*)one" \1first
# "ordinal (.*)two" \1second
# ...
# "ordinal (.*)" \1th
#######################################################
# CONGRATULATIONS – You have finished Tutorial Five! 🙂
#######################################################
|