diff --git a/2020/carlini/Makefile b/2020/carlini/Makefile index df3c8c9d9..c29224661 100644 --- a/2020/carlini/Makefile +++ b/2020/carlini/Makefile @@ -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 '' "/\\oo/\\" - @echo Eggy and Kitty + @echo "you expected to often misunderstand this $${RANDOM} magic" + @echo "chongo '' /\\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" + diff --git a/2020/carlini/README.md b/2020/carlini/README.md index 7663efd37..e818d75ce 100644 --- a/2020/carlini/README.md +++ b/2020/carlini/README.md @@ -1,47 +1,56 @@ # Best of show - abuse of libc +``` Nicholas Carlini +``` +## 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 CHESSTIC-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/ ------------------------------------------------------------------------------------------------------