Author:
- Name: Andrew Kramer
Location: US - United States of America (United States)
To build:
make all
Bugs and (Mis)features:
The current status of this entry is:
STATUS: known bug - please help us fix
For more detailed information see 2024/kramer in bugs.html.
To use:
./prog phrase1 phrase2 ...
Try:
./prog two plus one trillion five hundred seventy five million six hundred thousand sixty one
Or:
./try.sh
Judges’ remarks:
Arithmetic processing with English words: naturally obfuscated for your signed 64-bit programming amusement.
Enjoy!
Author’s remarks:
Overview
The frequent computer user may, for reasons of ergonomics, wish to minimize the distance their hands travel while completing everyday tasks. The much beloved Thinkpad TrackPoint is a wonderful example of a technology built for this purpose, allowing the user to transition seamlessly from keyboard to mouse without the need for unnecessary repositioning of the hands. (One may wonder why a mouse would be necessary at all, given the rich text-based environment provided by the terminal, but that is a separate topic.)
For users who frequently switch between natural language writing and numeric calculations, the requirement to move their hands from the home-row position all the way over to the number pad represents an extreme hardship. It wastes valuable time, causes discomfort, and may lead to any number of serious health complications on a long enough time scale.
To address this problem, we present a simple calculator which operates entirely on natural language! Numbers and calculations can be entered in plain English as the program’s argument vector, without the need to move away from the home-row. The program will handle the rest. Inputs of positive or negative values into the trillions are supported, with internal calculations supporting an even greater precision in the range LLONG_MIN <= n <= LLONG_MAX
. The operators “plus” (+), “minus” (-), “times” (*), “divided by” (/), and “mod” (%) are implemented. Standard order-of-operations is respected. All calculations are performed using whole integers.
Order of operations is handled through the use of the Shunting Yard Algorithm, which uses stacks and queues to convert the infix input array into postfix (RPN) notation to be solved. (Shout out to my boy Edsger Dijkstra for that one, sick algorithm dude!)
Examples
$ ./prog one plus one
2
$ ./prog one thousand three hundred and thirty seven
1337
$ ./prog two times three plus five
11
$ ./prog seventeen times negative two
-34
$ ./prog one hundred and two divided by six plus nine
26
$ ./prog nineteen plus one hundred mod seven
21
$ ./a.out negative three hundred and seventy two trillion thirty six billion eight hundred and fifty four million seven hundred and seventy five thousand eight hundred and eight minus nine thousand two hundred and twenty three times one trillion times one thousand
-9223372036854775808
Obfuscation
Obfuscation is greatly enhanced by the use of a custom hashing function to identify each natural language term. While a series of strcmp()
’s would certainly be sufficient, including all of those human-readable words in the source would be much too obvious (not to mention that it bloats the source file, wasting valuable disk space). After much experimentation, it was determined that the following function produces a unique set of 8-bit numeric outputs for all required input terms.
char hash(char *s) {
char h = 1, i = 0;
while (s[i]) {
>>= 1;
h ^= s[i++];
h }
return (h & 0xf) | (((i ^ s[0]) << 4) & 0xf0);
}
This allows the program to identify each unique term without having to explicitly declare them within the source file. The complete list of valid input terms and their cooresponding hash value is listed below for reference, sorted alphabetically.
43 and
90 billion
8 by
55 divided
2 eight
223 eighteen
48 eighty
56 eleven
31 fifteen
49 fifty
40 five
47 four
238 fourteen
52 forty
242 hundred
170 million
137 minus
232 mod
110 negative
165 nine
111 nineteen
130 ninety
201 one
76 plus
106 seven
175 seventeen
65 seventy
0 six
78 sixteen
103 sixty
113 ten
206 thirteen
39 thirty
192 thousand
17 three
16 times
202 trillion
45 twelve
32 twenty
121 two
224 zero
To further obfuscate the code, we golf it down a bit using all the standard tricks.
Limitations
If you compile this with nit-picky flags like -Wall
, the compiler is likely to be very cross. >:( It will yell a bit. So… don’t do that, I guess! Both gcc
and clang
are happy and quiet with the defaults.
Inputs into the trillions are handled, but inputs of one quadrillion or above are not. During calculation, only numbers which can be represented by an int64_t
are supported. But honestly… who needs numbers bigger than that anyway?
Input terms other than those explicitly implemented are considered undefined and will produce undefined results. Many will hash to unknown values, having no effect, while others may produce collisions when hashed, causing unexpected outputs. For instance, the term give
hashes to the number 56
which is a collision with the term eleven
. Thus…
$ ./prog never gonna give you up
11
We recommend simply not doing that.
Inventory for 2024/kramer
Primary files
- prog.c - entry source code
- Makefile - entry Makefile
- prog.orig.c - original source code
- try.sh - script to try entry
Secondary files
- 2024_kramer.tar.bz2 - download entry tarball
- README.md - markdown source for this web page
- .entry.json - entry summary and manifest in JSON
- .gitignore - list of files that should not be committed under git
- .path - directory path from top level directory
- index.html - this web page