Update 1993 winning entries' README.md files
Format and typo fixes. Starting with this year I actually did more thorough typo fixes. It might be that I did some of this in earlier years too but I am sure I did it for this year and beyond (at least up through 1995 .. not sure about years beyond that that I have also edited). Even so I'll probably want to do another pass through all files before I can say that the typo issue is resolved. That includes possibly other files and the worst of all files in my entries.
This commit is contained in:
1 parent
cf4437c508
commit
ee4ee3497d
9 files changed
+360
-298
No files matched your search
+136
-114
@@ -1,14 +1,16 @@
|
||||
# Most Irregular Expression
|
||||
|
||||
David Van Brackle
|
||||
ISX Corporation
|
||||
1165 Northchase Parkway, Suite 120
|
||||
Marietta, GA 30067
|
||||
USA
|
||||
David Van Brackle
|
||||
ISX Corporation
|
||||
1165 Northchase Parkway, Suite 120
|
||||
Marietta, GA 30067
|
||||
USA
|
||||
|
||||
## To build:
|
||||
|
||||
make all
|
||||
```sh
|
||||
make all
|
||||
```
|
||||
|
||||
[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to work with
|
||||
clang. The problem was that the third arg to main() was not a `char **`. Instead
|
||||
@@ -18,42 +20,50 @@ right parameters. Thank you Cody for your assistance!
|
||||
|
||||
## To run:
|
||||
|
||||
./vanb 'exp'
|
||||
|
||||
where 'exp' is an octal expression
|
||||
```sh
|
||||
./vanb 'exp'
|
||||
```
|
||||
|
||||
where `exp` is an octal expression. See below for how it can also have
|
||||
hexadecimal and decimal numbers.
|
||||
|
||||
|
||||
## Try:
|
||||
|
||||
./vanb 1+1
|
||||
```sh
|
||||
./vanb '1+1'
|
||||
|
||||
./vanb 4+4
|
||||
./vanb '4+4'
|
||||
```
|
||||
|
||||
What happens if you use something other than valid digits?
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
The octal expression may contain:
|
||||
|
||||
unary operators: +, -
|
||||
binary operators +, -, *, /, %
|
||||
hex numbers: x or X follow by hex digits
|
||||
decimal numbers: d or D follow by decimal digits
|
||||
octal numbers: octal digits
|
||||
grouping: ()
|
||||
|
||||
```
|
||||
unary operators: +, -
|
||||
binary operators +, -, *, /, %
|
||||
hex numbers: x or X follow by hex digits
|
||||
decimal numbers: d or D follow by decimal digits
|
||||
octal numbers: octal digits
|
||||
grouping: ()
|
||||
```
|
||||
|
||||
No spaces are allowed in the expression. To avoid shell expansion,
|
||||
one should surround the expression in single quotes.
|
||||
|
||||
It is a good thing that this program consists of only one
|
||||
expression, otherwise it might become hard to understand. :-)
|
||||
|
||||
## Author's remarks
|
||||
## Author's remarks:
|
||||
|
||||
The program does no error checking - erroneous expressions will
|
||||
produce spurious results. Note that unary '-' is an operator. Thus,
|
||||
decimal -46 would be entered as -d46 and not d-46.
|
||||
produce spurious results. Note that unary `-` is an operator. Thus,
|
||||
decimal `-46` would be entered as `-d46` and not `d-46`.
|
||||
|
||||
What Makes This Program Special:
|
||||
### What Makes This Program Special:
|
||||
|
||||
0. Of course, the fact that the program takes input and produces output in
|
||||
octal, rather than a more useful system like decimal, makes it "special".
|
||||
@@ -68,133 +78,145 @@ printf string.
|
||||
4. The variables are given names which cause visual confusion with the octal
|
||||
constants.
|
||||
|
||||
5. The program is formatted like a roman numeral 8. The significance of 8 is
|
||||
obvious. I chose roman numerals because it is a numbering system even more
|
||||
5. The program is formatted like a Roman numeral 8. The significance of 8 is
|
||||
obvious. I chose Roman numerals because it is a numbering system even more
|
||||
arcane than octal. It's not very 'deceptive', but it's difficult to deceptively
|
||||
format a program which has no explicit control structures (other than ?:'s).
|
||||
format a program which has no explicit control structures (other than `?:`s).
|
||||
|
||||
6. Many simple tasks are done many times. I tried to do these differently each
|
||||
time, to make the program harder to understand.
|
||||
|
||||
How It Works:
|
||||
### How It Works:
|
||||
|
||||
It's a recursive descent parser, calling main
|
||||
for all of its recursion. O2 is a state variable, telling main
|
||||
It's a recursive descent parser, calling `main`
|
||||
for all of its recursion. `O2` is a state variable, telling main
|
||||
what grammar non-terminal to parse. `**O7` is the next character.
|
||||
`O3` is an intermediate result. Whenever you see a construct like:
|
||||
|
||||
```
|
||||
!(expression with O2)?
|
||||
```
|
||||
|
||||
it's decrementing & testing O2 to see what state it's in. Comparisons
|
||||
it's decrementing & testing `O2` to see what state it's in. Comparisons
|
||||
involving `**O7` and octal constants are looking for certain characters.
|
||||
|
||||
Here's the grammar ('e' denotes the empty string) :
|
||||
Here's the grammar `('e'` denotes the empty string) :
|
||||
|
||||
|
||||
<E> ::= <T><E'>
|
||||
<E'> ::= +<T><E'> | -<T><E'> | e
|
||||
<T> ::= <F><T'>
|
||||
<T'> ::= *<F><T'> | /<F><T'> | %<F><T'> | e
|
||||
<F> ::= +<F> | -<F> | (<E><C> | d<D> | D<D> | x<X> | X<X> | <O>
|
||||
<C> ::= )
|
||||
<D> ::= [0-9]<D> | e
|
||||
<X> ::= [0-9]<X> | [A-F]<X> | [a-f]<X> | e
|
||||
<O> ::= [0-7]<O> | e
|
||||
|
||||
```
|
||||
<E> ::= <T><E'>
|
||||
<E'> ::= +<T><E'> | -<T><E'> | e
|
||||
<T> ::= <F><T'>
|
||||
<T'> ::= *<F><T'> | /<F><T'> | %<F><T'> | e
|
||||
<F> ::= +<F> | -<F> | (<E><C> | d<D> | D<D> | x<X> | X<X> | <O>
|
||||
<C> ::= )
|
||||
<D> ::= [0-9]<D> | e
|
||||
<X> ::= [0-9]<X> | [A-F]<X> | [a-f]<X> | e
|
||||
<O> ::= [0-7]<O> | e
|
||||
```
|
||||
|
||||
Here's how the grammar nonterminals map to octal state numbers:
|
||||
|
||||
<E> is 012
|
||||
<E'> is 011
|
||||
<T> is 010
|
||||
<T'> is 07
|
||||
<F> is 06
|
||||
<C> is 013
|
||||
<D> is 04
|
||||
<X> is 05
|
||||
<O> is 03
|
||||
```
|
||||
<E> is 012
|
||||
<E'> is 011
|
||||
<T> is 010
|
||||
<T'> is 07
|
||||
<F> is 06
|
||||
<C> is 013
|
||||
<D> is 04
|
||||
<X> is 05
|
||||
<O> is 03
|
||||
```
|
||||
|
||||
Here's a version of the program before it got formatted into the VIII,
|
||||
augmented with comments showing where each state begins. N1 and N2 are
|
||||
augmented with comments showing where each state begins. `N1` and `N2` are
|
||||
notes:
|
||||
|
||||
```c
|
||||
#define O5 main
|
||||
O5(O2,O7,O3)char**O7;
|
||||
{
|
||||
return
|
||||
/* N1 */ !(O2+=~01+01) ?
|
||||
00:
|
||||
/* N2 */ !(O2-=02>01) ?
|
||||
printf("\045\157\012",O5(012,O7+01,00)):
|
||||
/* O */ !(O2-=02>>01) ?
|
||||
(**O7<=067 && **O7>057 ? O5(03,O7,*(*O7)++-060+010*O3):O3):
|
||||
/* D */ !(O2-=-O3-~O3) ?
|
||||
(072>**O7 && 060<=**O7 ? O5(04,O7,012*O3-060+*(*O7)++):O3):
|
||||
/* X */ !(O2-=!O3+!!O3) ?
|
||||
(**O7>057 && **O7<=071 ? O5(05,O7,*(*O7)+++O3*020-060):
|
||||
**O7<=0106 && 0101<=**O7 ? O5(05,O7,020*O3+*(*O7)++-067):
|
||||
0140<**O7 && **O7<0147 ? O5(05,O7,-0127+*(*O7)+++020*O3):O3):
|
||||
/* F */ !(O2-=02-01) ?
|
||||
(**O7==050 ? 050**++*O7,O5(013,O7,O5(012,O7,00)):
|
||||
**O7<056 && 054<**O7 ? 055**++*O7,-O5(06,O7,00):
|
||||
054>**O7 && 052<**O7 ? 050**(*O7)++,O5(06,O7,00):
|
||||
!(**O7^0170)||!(0130^**O7) ? *++*O7,O5(05,O7,00):
|
||||
**O7==0144||**O7==0104 ? ++*O7,O5(04,O7,00):O5(03,O7,00)):
|
||||
/* T' */ !--O2 ?
|
||||
(**O7==052 ? O5(07,O7,O3*(*++*O7,O5(06,O7,00))):
|
||||
!(045-**O7) ? O5(07,O7,O3%(03+(*O7)++,O5(06,O7,00))):
|
||||
!(**O7^057) ? O5(07,O7,O3/(03-*++*O7,O5(06,O7,00))):O3):
|
||||
/* T */ !(O2+=01-02) ?
|
||||
O5(07,O7,O5(06,O7,00)):
|
||||
/* E' */ !(O2+=-02/02) ?
|
||||
(!(**O7-053)?O5(011,O7,O3+(++*O7,O5(010,O7,00))):
|
||||
!(055^**O7) ? O5(011,O7,O3-(03+*(*O7)++,O5(010,O7,00))):O3):
|
||||
/* E */ !(O2-=0563&0215) ?
|
||||
O5(011,O7,O5(010,O7,00)):
|
||||
/* C */ (++*O7,O3);
|
||||
}
|
||||
```
|
||||
|
||||
#define O5 main
|
||||
O5(O2,O7,O3)char**O7;
|
||||
{
|
||||
return
|
||||
/* N1 */ !(O2+=~01+01) ?
|
||||
00:
|
||||
/* N2 */ !(O2-=02>01) ?
|
||||
printf("\045\157\012",O5(012,O7+01,00)):
|
||||
/* O */ !(O2-=02>>01) ?
|
||||
(**O7<=067 && **O7>057 ? O5(03,O7,*(*O7)++-060+010*O3):O3):
|
||||
/* D */ !(O2-=-O3-~O3) ?
|
||||
(072>**O7 && 060<=**O7 ? O5(04,O7,012*O3-060+*(*O7)++):O3):
|
||||
/* X */ !(O2-=!O3+!!O3) ?
|
||||
(**O7>057 && **O7<=071 ? O5(05,O7,*(*O7)+++O3*020-060):
|
||||
**O7<=0106 && 0101<=**O7 ? O5(05,O7,020*O3+*(*O7)++-067):
|
||||
0140<**O7 && **O7<0147 ? O5(05,O7,-0127+*(*O7)+++020*O3):O3):
|
||||
/* F */ !(O2-=02-01) ?
|
||||
(**O7==050 ? 050**++*O7,O5(013,O7,O5(012,O7,00)):
|
||||
**O7<056 && 054<**O7 ? 055**++*O7,-O5(06,O7,00):
|
||||
054>**O7 && 052<**O7 ? 050**(*O7)++,O5(06,O7,00):
|
||||
!(**O7^0170)||!(0130^**O7) ? *++*O7,O5(05,O7,00):
|
||||
**O7==0144||**O7==0104 ? ++*O7,O5(04,O7,00):O5(03,O7,00)):
|
||||
/* T' */ !--O2 ?
|
||||
(**O7==052 ? O5(07,O7,O3*(*++*O7,O5(06,O7,00))):
|
||||
!(045-**O7) ? O5(07,O7,O3%(03+(*O7)++,O5(06,O7,00))):
|
||||
!(**O7^057) ? O5(07,O7,O3/(03-*++*O7,O5(06,O7,00))):O3):
|
||||
/* T */ !(O2+=01-02) ?
|
||||
O5(07,O7,O5(06,O7,00)):
|
||||
/* E' */ !(O2+=-02/02) ?
|
||||
(!(**O7-053)?O5(011,O7,O3+(++*O7,O5(010,O7,00))):
|
||||
!(055^**O7) ? O5(011,O7,O3-(03+*(*O7)++,O5(010,O7,00))):O3):
|
||||
/* E */ !(O2-=0563&0215) ?
|
||||
O5(011,O7,O5(010,O7,00)):
|
||||
/* C */ (++*O7,O3);
|
||||
}
|
||||
|
||||
Note N1: It should never enter this state, unless the user invokes the
|
||||
Note `N1`: It should never enter this state, unless the user invokes the
|
||||
program with no parameters, in which case it just returns 0.
|
||||
|
||||
Note N2: Since the program is properly invoked with 1 parameter, this is
|
||||
Note `N2`: Since the program is properly invoked with 1 parameter, this is
|
||||
the first state it will go into. This state just invokes
|
||||
printf, and sends the parser to state 012 (which is `<E>`).
|
||||
printf, and sends the parser to state `012` (which is `<E>`).
|
||||
|
||||
The E and T states work like this:
|
||||
The `E` and `T` states work like this:
|
||||
|
||||
int e(){ return eprime( t() ); }
|
||||
```c
|
||||
int e(){ return eprime( t() ); }
|
||||
```
|
||||
|
||||
|
||||
The E' and T' states work like this:
|
||||
The `E'` and `T'` states work like this:
|
||||
|
||||
```c
|
||||
int eprime( int intermediate )
|
||||
{
|
||||
if( ch == '+' )
|
||||
{
|
||||
ch = nextchar();
|
||||
return eprime( intermediate + t() );
|
||||
}
|
||||
else return intermediate;
|
||||
}
|
||||
```
|
||||
|
||||
int eprime( int intermediate )
|
||||
{
|
||||
if( ch == '+' )
|
||||
{
|
||||
ch = nextchar();
|
||||
return eprime( intermediate + t() );
|
||||
}
|
||||
else return intermediate;
|
||||
}
|
||||
The `D`, `X` and `O` states work like this (they assume that they're initially
|
||||
called with `0`):
|
||||
|
||||
The D, X and O states work like this (they assume that they're initially
|
||||
called with 0):
|
||||
```c
|
||||
int octal( int intermediate )
|
||||
{
|
||||
if( ch>='0' && ch<='7' )
|
||||
{
|
||||
intermediate = intermediate * 8 + ch - '0';
|
||||
ch = nextchar();
|
||||
return octal( intermediate );
|
||||
}
|
||||
else return intermediate;
|
||||
}
|
||||
|
||||
int octal( int intermediate )
|
||||
{
|
||||
if( ch>='0' && ch<='7' )
|
||||
{
|
||||
intermediate = intermediate * 8 + ch - '0';
|
||||
ch = nextchar();
|
||||
return octal( intermediate );
|
||||
}
|
||||
else return intermediate;
|
||||
}
|
||||
```
|
||||
|
||||
F and C work similarly.
|
||||
`F` and `C` work similarly.
|
||||
|
||||
## Copyright and CC BY-SA 4.0 License:
|
||||
|
||||
|
||||
Reference in new issue
Block a user