fix Makefile for 2020/carlini and test a README.md style

This commit is contained in:
Landon Curt Noll committed 2023-03-10 21:06:21 -08:00
1 parent 4a93ba2ca6
commit 34e612b95a
2 files changed
+223 -440

No files matched your search

+119 -379
View File
@@ -1,14 +1,41 @@
#!/usr/bin/env make
#
# 2020 makefile
# IOCCC 2020 winning entry - carlini
################################################################################
#
# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis
# is licensed under:
# Regarding individual entries:
#
# IOCCC winning entry code may not work on your system. Even with standards,
# conditions and build environments change, especially when it comes to more
# extreme code such you might find in an IOCCC winner. Moreover, what was
# allowed and liked in one IOCCC contest may no longer be liked/allowed in
# later IOCCC years.
#
# Corrections on winning author and fixing typos in remarks are VERY WELCOME.
#
# GitHub pull requests are welcome:
#
# If you have a patch that might make running an entry work in modern Unix-like
# environments, please create a GitHub pull request for the IOCCC judges to
# consider.
#
# Suggestions and corrections regarding Makefiles, winning author information,
# fixing typos in remarks, and code patches are welcome via opening a GitHub
# issue or better yet, by creating a GitHub pull request for the IOCCC judges
# to consider. To form a GitHub issue or GitHub pull, please visit:
#
# https://github.com/ioccc-src/winner
#
################################################################################
# This work by Landon Curt Noll and Leonid A. Broukhis is licensed under:
#
# Creative Commons Attribution-ShareAlike 3.0 Unported License.
#
# See: http://creativecommons.org/licenses/by-sa/3.0/
#############################
# shell used by this Makefile
#############################
@@ -19,264 +46,7 @@ SHELL= bash
# common tool locations
#######################
#
A2P= a2p
AR= ar
ASA= asa
AT= at
ATQ= atq
ATRM= atrm
AWK= awk
BANNER= banner
BASE64= base64
BASENAME= basename
BATCH= batch
BC= bc
BINHEX= binhex
BISON= bison
BUNZIP2= bunzip2
BZCAT= bzcat
BZCMP= bzcmp
BZDIFF= bzdiff
BZEGREP= bzegrep
BZFGREP= bzfgrep
BZGREP= bzgrep
BZIP2= bzip2
BZLESS= bzless
BZMORE= bzmore
C2PH= c2ph
C89= c89
C99= c99
CAL= cal
CALC= calc
CAT= cat
CD= cd
CHFLAGS= chflags
CHGRP= chgrp
CHMOD= chmod
CKSUM= cksum
CLANG= clang
CLANG_PLUSPLUS= clang++
CLEAR= clear
CMP= cmp
COL= col
COLLDEF= colldef
COLRM= colrm
COLUMN= column
COMPRESS= compress
CP= cp
CPIO= cpio
CPP= cpp
CRC32= crc32
CSH= csh
CSPLIT= csplit
CURL= curl
CUT= cut
C_PLUSPLUS= c++
C_PLUSPLUS_FILT= c++filt
DATE= date
DC= dc
DD= dd
DF= df
DIFF3= diff3
DIFF= diff
DIG= dig
DIRNAME= dirname
ED= ed
EGREP= egrep
ENV= env
EQN= eqn
ETAGS= etags
EXPECT= expect
EXPR= expr
FALSE= false
FGREP= fgrep
FILE= file
FIND2PERL= find2perl
FIND= find
FLEX= flex
FLEX_PLUSPLUS= flex++
FMT= fmt
FOLD= fold
FS_USAGE= fs_usage
FUNZIP= funzip
FUSER= fuser
GCC= gcc
GDIFFMK= gdiffmk
GENCAT= gencat
GENSTRINGS= genstrings
GETOPT= getopt
GETOPTS= getopts
GINDENT= gindent
GNUMAKE= gnumake
GREP= grep
GROFF= groff
GROFFER= groffer
GROG= grog
GROPS= grops
GROTTY= grotty
GUNZIP= gunzip
GVIM= gvim
GZCAT= gzcat
GZEXE= gzexe
GZIP_PROG= gzip
G_PLUSPLUS= g++
H2PH= h2ph
H2XS= h2xs
HASH= hash
HEAD= head
HOSTNAME_PROG= hostname
ICONV= iconv
ID= id
INDENT= indent
INFO= info
JOT= jot
KILL= kill
KSH= ksh
LAST= last
LD= ld
LESSECHO= lessecho
LEX= len
LINK= link
LN= ln
LS= ls
M4= m4
MAKE= make
MAN= man
MKDIR= mkdir
MKFIFO= mkfifo
MKTEMP= mktemp
MV= mv
NANO= nano
NASM= nasm
NEQN= neqn
NICE= nice
NL= nl
NM= nm
NOHUP= nohup
NROFF= nroff
NSLOOKUP= nslookup
OD= od
OPENSSL= openssl
PASTE= paste
PATCH= patch
PATHCHK= pathchk
PAX= pax
PERL= perl
PICO= pico
PR= pr
PRINTENV= printenv
PS= ps
PTAR= ptar
PTARDIFF= ptardiff
PTARGREP= ptargrep
PWD= pwd
PYDOC= pydoc
PYTHON= python
PYTHONW= pythonw
READLINK= readlink
RENICE= renice
RESET= reset
REV= rev
RI= ri
RM= rm
RMDIR= rmdir
RSYNC= rsync
RUBY= ruby
RVIM= rvim
SAY= say
SCP= scp
SCREEN= screen
SCRIPT= script
SDIFF= sdiff
SED= sed
SEQ= seq
SFTP= sftp
SH= sh
SHA1= sha1
SHA= sha
SHAR= shar
SHASUM5_18= shasum5.18
SHASUM= shasum
SIZE= size
SLEEP= sleep
SORT= sort
SSH= ssh
STAT= stat
STRIP= strip
STTY= stty
SUM= sum
SYNC= sync
TABS= tabs
TAIL= tail
TAR= tar
TEE= tee
TEST= test
TFTP= tftp
TIDY= tidy
TIME= time
TOP= top
TOUCH= touch
TPUT= tout
TPUT= tput
TR= tr
TROFF= troff
TRUE= true
TSET= tset
TSORT= tsort
UL= ul
UNAME= uname
UNCOMPRESS= uncompress
UNEXPAND= unexpand
UNIFDEF= unifdef
UNIFDEFALL= unifdefall
UNIQ= uniq
UNITS= units
UNLINK= unlink
UNZIP= unzip
UNZIPSFX= unzipsfx
UPTIME= uptime
UUDECODE= uudecode
UUENCODE= uuencode
UUIDGEN= uuidgen
VI= vi
VIEW= view
VIM= vim
VIMDIFF= vimdiff
W= w
WAIT4PATH= wait4path
WAIT= wait
WC= wc
WHAT= what
WHATIS= whatis
WHICH= which
WHO= who
WHOAMI= whoami
WHOIS= whois
WRTIE= write
XAR= xar
XARGS= xargs
XATTR= xattr
XXD= xxd
YACC= yacc
YES= yes
ZCAT= zcat
ZCMP= zcmp
ZDIFF= zdiff
ZEGREP= zegrep
ZFGREP= zfgrep
ZFORCE= zforce
ZGREP= zgrep
ZIP= zip
ZIPCLOAK= zipcloak
ZIPGREP= zipgrep
ZIPINFO= zipinfo
ZIPNOTE= zipnote
ZIPSPLIT= zipsplit
ZLESS= zless
ZMORE= zmore
ZNEW= znew
ZPRINT= zprint
ZSH= zsh
include ../../var.mk
# Set X11_LIBDIR to the directory where the X11 library resides
#
@@ -290,64 +60,25 @@ X11_LIBDIR= /opt/X11/lib
#X11_INCDIR= /usr/X11/include
X11_INCDIR= /opt/X11/include
# CWARN - Silence warnings that ${CWARN} would normally complain about
# CSILENCE -Compiler warnings
#
ifeq ($(CC),clang)
# clang CSILENCE and CWARN
# Common C compiler warnings to silence
#
#CSILENCE=
#CSILENCE= -Wno-implicit-int
CSILENCE= -Wno-overlength-strings -Wno-missing-variable-declarations -Wno-format-nonliteral \
-Wno-unknown-warning-option
#
#CWARN= $CSILENCE}
#CWARN= -Wall $CSILENCE}
#CWARN= -Wall -Wextra $CSILENCE}
#CWARN= -Wall -Wextra -pedantic ${CSILENCE}
#CWARN= -Wall -Wextra -Weverything $CSILENCE}
CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE}
CSILENCE= -Wno-overlength-strings
else
ifeq ($(CC),gcc)
# gcc CSILENCE and CWARN
# Common C compiler warning flags
#
#CSILENCE=
#CSILENCE= -Wno-implicit-int
CSILENCE= -Wno-overlength-strings -Wno-unknown-warning-option
#
#CWARN= $CSILENCE}
#CWARN= -Wall $CSILENCE}
#CWARN= -Wall -Wextra $CSILENCE}
#CWARN= ${CSILENCE}
#CWARN= -Wall ${CSILENCE}
#CWARN= -Wall -Wextra ${CSILENCE}
CWARN= -Wall -Wextra -pedantic ${CSILENCE}
else
# default CSILENCE and WARN
#
#CSILENCE=
#CSILENCE= -Wno-implicit-int
CSILENCE= -Wno-overlength-strings -Wno-unknown-warning-option
#
#CWARN= $CSILENCE}
#CWARN= -Wall $CSILENCE}
#CWARN= -Wall -Wextra $CSILENCE}
CWARN= -Wall -Wextra -pedantic ${CSILENCE}
#CWARN= -Wall -Wextra -Weverything $CSILENCE}
#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE}
endif
endif
# compiler standard
# Compiler standard
#
#CSTD=
#CSTD= -ansi
CSTD= -std=c11
CSTD= -std=gnu17
# compiler bit architecture
# Compiler bit architecture
#
# Some entries require 32-bitness:
# ARCH= -m32
@@ -359,20 +90,21 @@ CSTD= -std=c11
#
ARCH=
# defines that are needed to compile
# Defines that are needed to compile
#
CDEFINE=
#CDEFINE= -DIOCCC
# include files that are needed to compile
# Include files that are needed to compile
#
CINCLUDE=
#CINCLUDE= -include stdlib.h
#CINCLUDE= -include stdio.h
#CINCLUDE= -include stdlib.h -include stdio.h
#CINCLUDE= -I ${X11_INCDIR}
#CINCLUDE= `${SDL2_CONFIG} --cflags`
# optimization
# Optimization
#
# Most compiles will safely use -O2. Some can use only -O1 or -O.
# A few compilers have broken optimizers or this entry make break
@@ -385,38 +117,55 @@ CINCLUDE=
#OPT= -O2
OPT= -O3
# default flags for ANSI C compilation
# Default flags for ANSI C compilation
#
CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT}
# Libraries needed to build
#
LIBS=
#LIBS= -L ${X11_LIBDIR}
#LIBS= -lm
#LIBS= -L ${X11_LIBDIR} -lX11
#LIBS= `${SDL2_CONFIG} --libs`
# ANSI compiler
#
# Set CC to the name of your ANSI compiler.
#
# Some entries seem to need gcc. If you have gcc, set
# both CC and MAY_NEED_GCC to gcc.
#
# If you do not have gcc, set CC to the name of your ANSI compiler, and
# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just :
# to disable such programs.
# C compiler to use
#
CC= cc
#CC= clang
MAY_NEED_GCC= gcc
#CC=clang
#CC=gcc
# Compiler add-ons or replacements for clang only
#
ifeq ($(CC),clang)
#
CSILENCE+= -Wno-format-nonliteral -Wno-missing-variable-declarations \
-Wno-poison-system-directories
#
CWARN+= -Weverything
#
endif
# Specific add-ons or replacements for gcc only
#
ifeq ($(CC),gcc)
#
#CSILENCE+=
#
#CWARN+=
#
endif
##############################
# Special flags for this entry
##############################
#
OBJ= prog.o
ENTRY= carlini
PROG= prog
#
OBJ= ${PROG}.o
DATA=
TARGET= prog
TARGET= ${PROG}
#
ALT_OBJ=
ALT_TARGET=
@@ -426,15 +175,19 @@ ALT_TARGET=
# build the entry
#################
#
all: ${TARGET} ${DATA}
all: data ${TARGET}
@${TRUE}
prog: prog.c
.PHONY: all alt data everything clean clobber install \
love haste waste maker easter_egg sandwich \
supernova deep_magic magic charon pluto
${PROG}: ${PROG}.c
${CC} ${CFLAGS} $< -o $@ ${LIBS}
# alternative executable
#
alt: ${ALT_TARGET}
alt: data ${ALT_TARGET}
@${TRUE}
# data files
@@ -442,13 +195,15 @@ alt: ${ALT_TARGET}
data: ${DATA}
@${TRUE}
# both all and alt
#
everything: all alt
###############
# utility rules
###############
#
everything: all alt
clean:
${RM} -f ${OBJ} ${ALT_OBJ}
@-if [ -f indent.c ]; then \
@@ -463,24 +218,13 @@ clobber: clean
echo 'ate sandwich'; \
fi
nuke: clobber
@${TRUE}
dist_clean: nuke
@${TRUE}
install:
@echo "Surely you are performing, Dr. Science!"
@echo "Dr. Spock says that is not logical!"
@${TRUE}
# backwards compatibility
# you may be able to misunderstand the source by reading indent.c
#
build: all
@${TRUE}
# you may be able to mis-understand the source by reading indent.c
#
indent.c: prog.c
indent.c: ${PROG}.c
@if which "${GINDENT}" >/dev/null 2>&1; then \
echo ${RM} -f $@; \
${RM} -f $@; \
@@ -492,7 +236,7 @@ indent.c: prog.c
echo "${INDENT} < $< > $@"; \
${INDENT} < $< > $@; \
else \
echo "no intent prog found, ident $< yourself, sorry"; \
echo "no intent tool found, ident $< yourself, sorry"; \
echo "exit 1"; \
exit 1; \
fi
@@ -514,26 +258,21 @@ waste:
@echo 'haste'
@${TRUE}
make:
@echo 'We encourage you to attend a maker faire'
maker:
@echo 'Participate in a maker faire'
@${TRUE}
easter_egg:
@echo you expected to often mis-understand this $${RANDOM} magic
@echo chongo '<was here>' "/\\oo/\\"
@echo Eggy and Kitty
@echo "you expected to often misunderstand this $${RANDOM} magic"
@echo "chongo '<was here>' /\\oo/\\"
@echo "Eggy"
fabricate fashion form frame manufacture produce: make
@${TRUE}
sandwich:
sandwich: easter_egg
@if [ `id -u` -eq 0 ]; then \
echo 'Okay.'; \
echo $${RANDOM}`date +%s`$${RANDOM} | \
${SHASUM} -a 512256 | \
${SED} -e 's/ .*//' > $@; \
echo "$${RANDOM}`date +%s`$${RANDOM}" > $@; \
else \
echo 'Reall?!? Make it yourself.'; \
echo 'What? Make it yourself.'; \
exit 1; \
fi
@@ -541,47 +280,48 @@ sandwich:
# as well as the West Coast Computer Faire and
# you might be confused different. :-)
#
supernova: nuke
supernova: sandwich
@-if [ -r .code_anal ]; then \
${RM} -f .code_anal_v6; \
else \
echo "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \
echo "planet deniers, like some members of the IAU, are so cute when they try to defend their logic"; \
fi
@echo A $@ helps ${MAKE} the elements that help form planets
@echo "A $@ helps ${MAKE} the elements that help form planets"
@${TRUE}
deep_magic:
deep_magic: supernova
@-if [ -r .code_anal ]; then \
ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \
ccode_analysis --deep_magic 7889066cdbdf09b0408021754586e895be641cc9be29e7eafd3ca65359541f17 \
--FNV1a_hash_512_bit -v2 "${PROG}" "${PROG}.c"; \
else \
echo "Wrong! Do it again!"; \
sleep 1; \
sleep 2; \
echo "Wrong! Do it again!"; \
sleep 1; \
sleep 2; \
echo "Wrong! Do it again!"; \
fi
@${TRUE}
magic: deep_magic
@-if [ -r .code_anal ]; then \
ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \
ccode_analysis --level 20003 --mode 5717175 --FNV1a_hash_512_bit -v2 "${PROG}" "${PROG}.c"; \
else \
echo "If you don't eat yer meat, you can't have any pudding!"; \
echo "How can you have any pudding if you don't eat yer meat?!"; \
echo "Be careful with that axe, Eugene."; \
fi
@${TRUE}
# The IOCCC resident astronomer states
#
charon: supernova
@echo $@ is a dwarf planet
@echo dwarf is a type of planet
@echo therefore we continue to tell the IAU that $@ is a planet
charon: magic
@echo "$@ is a dwarf planet"
@echo "dwarf is a type of planet"
@echo "therefore IAU, $@ is a planet"
pluto: supernova
pluto: charon
${MAKE} charon
@echo $@ is a dwarf planet
@echo dwarf is a type of planet
@echo therefore, $@ is a planet
@echo having lots of planets is good feature because supernovae can help ${MAKE} a lot of them
@echo "$@ is a dwarf planet"
@echo "dwarf is a type of planet"
@echo "therefore, $@ is a planet"
@echo "having lots of planets is good feature because supernovae can help ${MAKE} a lot of them"
+104 -61
View File
@@ -1,47 +1,56 @@
# Best of show - abuse of libc
```
Nicholas Carlini <nicholas@carlini.com>
<https://nicholas.carlini.com>
```
## To build:
The code for this entry can be found in prog.c
```sh
make
```
## Judges' comments:
### To use:
make
./prog
### To run:
```sh
./prog
```
### Try:
# Play with a friend, P1 and P2, squares are numbered 1..9
./prog
```sh
# Play with a friend, P1 and P2, squares are numbered 1..9
./prog
```
### Selected Judges Remarks:
## Judges' comments:
This program consists of a single print statement wrapped in a while loop. You
would not think that this would amount to much, but you would be very, very
wrong. A clue to what is happening and how this works is encoded in the
ASCII art of the program source.
## Author's comments:
HOW ABOUT A NICE GAME OF <strike>CHESS</strike>TIC-TAC-TOE?
### USAGE
cc -o prog prog.c
./prog
```sh
cc -o prog prog.c
./prog
```
Alternates between P1 and P2. Enter a digit [1-9] to move:
1 | 2 | 3
---------
4 | 5 | 6
---------
7 | 8 | 9
```
1 | 2 | 3
---------
4 | 5 | 6
---------
7 | 8 | 9
```
The game ends if:
@@ -49,7 +58,6 @@ The game ends if:
* All squares are taken; neither player wins
* A player makes an illegal move; their opponent wins
### LIMITATIONS
Bad things may happen if the entered move is outside of the range [1..9]
@@ -69,16 +77,19 @@ compilers unhappy, and others slow. (For example, passing GCC the flags -Wall
Under some terminals the program may exit early. The following should always work:
echo "1 2 3 4 5 6 7" | ./prog
```sh
echo "1 2 3 4 5 6 7" | ./prog
```
### OBFUSCATION
The entirety of the program consists of a single iterated call to printf.
int main() {
while(*d) printf(fmt, arg);
}
```c
int main() {
while(*d) printf(fmt, arg);
}
```
Here, `fmt` is a single string, and `arg` is a series of arguments to printf.
@@ -102,7 +113,6 @@ This program uses three printf format specifiers.
- `%n` takes a pointer and writes (!!) the number of bytes printed so far.
Okay, everyone probably knows this. Let's get a bit more advanced.
Format specifiers can take extra "arguments".
@@ -115,14 +125,17 @@ Format specifiers can take extra "arguments".
- `"%3$.*4$d"`: print argument 3 to printf with as many zeros as in argument 4.
For example, the following expression
printf("%1$.*2$d%3$hhn", 5, 10, &x)
```c
printf("%1$.*2$d%3$hhn", 5, 10, &x)
```
will have the same effect as if we had written
x = 10;
```c
x = 10;
```
because it will print out `0000000005` (5 padded to size 10) and then write the
number of bytes written to x.
@@ -143,27 +156,39 @@ We can use format strings to compute the OR/NOT of arbitrary "bits".
We'll start with the simplest, OR:
printf("%1$s%2$s%3$hhn", a, b, c)
```c
printf("%1$s%2$s%3$hhn", a, b, c)
```
will compute
*c = strlen(a) + strlen(b)
```c
*c = strlen(a) + strlen(b)
```
but given that `strlen(x)` is `1` for a 1-bit and `0` for a 0-bit, we have
*c = a | b
```c
*c = a | b
```
Computing the NOT of a single value is also easy:
printf("%1$255d%1$s%hhn", a, b)
```c
printf("%1$255d%1$s%hhn", a, b)
```
will compute
*b = (strlen(a)+255)%256 = strlen(a)-1
```c
*b = (strlen(a)+255)%256 = strlen(a)-1
```
and again, because `strlen(x)` is either `1` or `0` we have
*c = !b
```c
*c = !b
```
From here we can compute any binary circuit. Doing something efficient,
though, still takes work.
@@ -177,11 +202,13 @@ To detect who has won, we implement the following logic. Let A, B, and C be
pointers to three squares in a row to test, and D be where to save if there is a
win or not.
"%A$s%B$s%C$s%1$253d%11$hhn" // r11 = !(*A & *B & *C)
ZERO
"%11$s%1$255d%11hhn" // r11 = !r11
ZERO
"%11$s%D$s%D$hhn" // *D = *D | r11
```c
"%A$s%B$s%C$s%1$253d%11$hhn" // r11 = !(*A & *B & *C)
ZERO
"%11$s%1$255d%11hhn" // r11 = !r11
ZERO
"%11$s%D$s%D$hhn" // *D = *D | r11
```
That is, we set `*D` to `1` if there is a three-in-a-row. We repeat this for all
possible three-in-a-row configurations, for both players.
@@ -189,7 +216,9 @@ possible three-in-a-row configurations, for both players.
The ZERO macro ensures that the number of bytes written out is 0 mod 256 with
the following expression
"%1$hhn%1$s" (repeated 256 times)
```c
"%1$hhn%1$s" (repeated 256 times)
```
where argument 1 is a pointer to a temporary variable followed by a null byte.
@@ -206,11 +235,15 @@ bits to Xs and Os to print out. This is actually rather straightforward. Given
in 1$ the pointer to player 1's square, and 2$ the pointer to player 2's, and
in 3$ the pointer to the board string, we can compute
"%1$s" (repeated 47 times) "%2$s" (repeated 56 times) %1$32d%3$hhn"
```c
"%1$s" (repeated 47 times) "%2$s" (repeated 56 times) %1$32d%3$hhn"
```
which will, in effect, compute
*r3 = (*r1) * 47 + (*r2) * 56 + 32
```c
*r3 = (*r1) * 47 + (*r2) * 56 + 32
```
which will output `' '` if neither are true, `'X'` if r1 is, or `'O'` if r2 is.
@@ -220,7 +253,9 @@ which will output `' '` if neither are true, `'X'` if r1 is, or `'O'` if r2 is.
In order to be able to finally display the board, while still only using one
printf statement, we finish the statement with
"\n\033[2J\n%26$s"
```c
"\n\033[2J\n%26$s"
```
which is the escape sequence to clear the screen, and then prints argument 26.
Argument 26 is a pointer to a char* in memory, that initially is undefined,
@@ -229,12 +264,14 @@ tic-tac-toe board.
After the board, we need to print one of the following strings:
P1>_
P2>_
P1 WINS
P2 WINS
P1 TIES
P2 TIES
```
P1>_
P2>_
P1 WINS
P2 WINS
P1 TIES
P2 TIES
```
Depending on if it's P1 or P2's turn to move, the game is over and someone
won, or the game is over and it is a draw.
@@ -242,7 +279,9 @@ won, or the game is over and it is a draw.
This turns out not to be as hard as it might look. Using the same trick as
before, we set byte four to be
*byte4 = is_win * 'W' + is_tie * 'T'
```c
*byte4 = is_win * 'W' + is_tie * 'T'
```
The byte `'I'` and `'S'` can always be the same, and we do the same for `'E'`/`'N'`.
@@ -254,19 +293,23 @@ ends. It should just exit.
One option would be to implement the logic as
printf()
while (*ok) {
scanf();
printf();
}
```c
printf()
while (*ok) {
scanf();
printf();
}
```
but this would DOUBLE the number of calls to printf we require. So instead we
implement it like this
while (*ok) {
scanf();
printf();
}
```c
while (*ok) {
scanf();
printf();
}
```
(In reality we actually pass `scanf()` as an argument to avoid the extra
statement, but it has the same effect.)
@@ -276,10 +319,10 @@ block before the first `printf()`, but we initialize the `scanf()` format to the
string so that it returns right away without blocking. The first time the `printf()`
call runs, it writes out `"%hhd"` to create the `scanf()` format string.
-----------------------------------------------------------------------------------------------------
## Copyright:
(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved
This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc].
[judges]: http://www.ioccc.org/judges.html
[cc]: http://creativecommons.org/licenses/by-sa/3.0/
-----------------------------------------------------------------------------------------------------