Merge pull request #1440 from xexyl/bmeyer2k

This commit is contained in:
Landon Curt Noll authored and GitHub committed 2023-11-16 07:27:53 -07:00
commit 19c50d77c7
17 files changed
+311 -250

No files matched your search

+5 -1
View File
@@ -41,7 +41,7 @@ include ../../var.mk
CSILENCE= -Wno-char-subscripts -Wno-error -Wno-implicit-function-declaration \ CSILENCE= -Wno-char-subscripts -Wno-error -Wno-implicit-function-declaration \
-Wno-int-conversion -Wno-logical-op-parentheses -Wno-pedantic \ -Wno-int-conversion -Wno-logical-op-parentheses -Wno-pedantic \
-Wno-return-type -Wno-unknown-escape-sequence -Wno-unused-value \ -Wno-return-type -Wno-unknown-escape-sequence -Wno-unused-value \
-Wno-deprecated-non-prototype -Wno-deprecated-non-prototype -Wno-implicit-int
# Common C compiler warning flags # Common C compiler warning flags
# #
@@ -140,6 +140,10 @@ ${PROG}: ${PROG}.c
alt: data ${ALT_TARGET} alt: data ${ALT_TARGET}
@${TRUE} @${TRUE}
${PROG}.alt: ${PROG}.alt.c
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS}
# data files # data files
# #
data: ${DATA} data: ${DATA}
+5 -3
View File
@@ -28,9 +28,11 @@ bugs.md](/bugs.md#1991-buzzard).
## Alternate code: ## Alternate code:
This version changes the keys `f` for forward, `l` for left and `r` for right to This version changes the keys `f` for forward, `l` for left and `r` for right by
`k` for forward, `l` for right and `h` for left, which is more natural for those default to `k` for forward, `l` for right and `h` for left, which is more
who use vi(m). Also one can just hit `q` followed by enter to quit the maze. natural for those who use vi(m). Also one can just hit `q` followed by enter to
quit the maze. It is problematic to reconfigure the keys except by modifying the
code directly so the keys are not made a `-D` at the compiler.
### Alternate build: ### Alternate build:
+1 -1
View File
@@ -1,7 +1,7 @@
#include <stdio.h> #include <stdio.h>
#define X(s) (!(s&3)-((s&3)==2)) #define X(s) (!(s&3)-((s&3)==2))
#define W while #define W while
char Z[82][82],A,B,f,g=26;z(q)char**q;{return atoi(q);}m(d,l){return char Z[82][82],A,B,f,g=26;z(q)char*q;{return atoi(q);}m(d,l){return
Z[ B + X ( f + Z[ B + X ( f +
3) * d+l *X(f+ 2 )][ A+X ( f ) * d + 3) * d+l *X(f+ 2 )][ A+X ( f ) * d +
l* X ( f + 3 ) ] ;}int l* X ( f + 3 ) ] ;}int
+1 -1
View File
@@ -1,7 +1,7 @@
#include <stdio.h> #include <stdio.h>
#define X(s) (!(s&3)-((s&3)==2)) #define X(s) (!(s&3)-((s&3)==2))
#define W while #define W while
char Z[82][82],A,B,f,g=26;z(q)char**q;{return atoi(q);}m(d,l){return char Z[82][82],A,B,f,g=26;z(q)char*q;{return atoi(q);}m(d,l){return
Z[ B + X ( f + Z[ B + X ( f +
3) * d+l *X(f+ 2 )][ A+X ( f ) * d + 3) * d+l *X(f+ 2 )][ A+X ( f ) * d +
l* X ( f + 3 ) ] ;}int l* X ( f + 3 ) ] ;}int
-2
View File
@@ -1,6 +1,4 @@
westley westley
whereami
whereami.alt
westley.alt westley.alt
westley.orig westley.orig
prog.orig prog.orig
+2 -8
View File
@@ -121,7 +121,7 @@ ALT_TARGET= ${PROG}.alt
# build the entry # build the entry
################# #################
# #
all: data ${TARGET} whereami whereami.alt all: data ${TARGET}
@${TRUE} @${TRUE}
.PHONY: all alt data everything diff_orig_prog diff_prog_orig \ .PHONY: all alt data everything diff_orig_prog diff_prog_orig \
@@ -133,12 +133,9 @@ ${PROG}: ${PROG}.c
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS} ${CC} ${CFLAGS} $< -o $@ ${LDFLAGS}
@echo "NOTE: your terminal must be at least 80 columns wide for this to work right" @echo "NOTE: your terminal must be at least 80 columns wide for this to work right"
whereami: whereami.c
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS} -lcurses
# alternative executable # alternative executable
# #
alt: data ${ALT_TARGET} whereami.alt alt: data ${ALT_TARGET}
@${TRUE} @${TRUE}
${PROG}.alt: ${PROG}.alt.c ${PROG}.alt: ${PROG}.alt.c
@@ -146,9 +143,6 @@ ${PROG}.alt: ${PROG}.alt.c
@echo "NOTE: your terminal must be at least 80 columns wide for this to work right" @echo "NOTE: your terminal must be at least 80 columns wide for this to work right"
whereami.alt: whereami.alt.c
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS} -lcurses
# data files # data files
# #
data: ${DATA} data: ${DATA}
+42 -49
View File
@@ -7,42 +7,27 @@
# #
# This script will first try compiling the code and alt code (alt = US only with # This script will first try compiling the code and alt code (alt = US only with
# higher resolution, based on the author's remarks) and then if all is OK it # higher resolution, based on the author's remarks) and then if all is OK it
# tries to make the whereami and whereami.alt programs. If that fails the # will continue.
# programs used will be westley and westley.alt; otherwise the programs will be
# whereami and whereami.alt. One can pass CC=foo to set the compiler, defaulting
# to cc.
# #
# The difference between whereami and westley is that the former first checks # The whereami.sh and whereami.alt.sh scripts correspond to westley.c and
# that the number of columns is at least 80. The programs whereami and # westley.alt.c but they check that the number of columns is at least 80. If
# whereami.alt can be deceived by way of doing: # it's not at least 80 then it's an error. The scripts can be deceived by doing
# something like:
# #
# COLUMNS=100 ./whereami lat long # COLUMNS=100 ./whereami.sh lat long
# #
# even if the number of columns is < 80 but there's nothing that can be done # even if the number of columns is < 80 but there's nothing that can be done
# about that. This script does not have that problem, however, so it's nice to # about that.
# use for that purpose if nothing else.
# #
# If westley or westley.alt cannot compile then it is an error and the script # If westley or westley.alt cannot compile then it is an error and the script
# will exit 4, corresponding to the same code that whereami.c and whereami.alt.c # will exit.
# exit with if westley.c or westley.alt.c cannot be compiled.
# #
# If whereami or whereami.alt cannot compile or link, say because libcurses is # If by chance westley.sh or westley.alt.sh are not executable files then it
# not installed, then it is not an error as such but westley and westley.alt # will try chmod +x on them and then try again. Otherwise it'll just use westley
# will be used instead unless of course there exists an executable of one or # and westley.alt.
# both called whereami or whereami.alt or westley.c or westley.alt.c cannot be
# compiled. It is an error in the script if either of westley.c or westley.alt.c
# cannot be compiled.
#
# This is the best way to protect against showing poor output. We can't get the
# environmental variable COLUMNS from a program or a script so it has to be done
# this way. Note that in curses the COLUMNS is called COLS.
# #
# This script knows which version, the entry or alt code, to use based on what # This script knows which version, the entry or alt code, to use based on what
# city is being shown. # city is being shown (based on the author's remarks).
#
# If whereami and whereami.alt can be built it is run once, ahead of time, and
# if it exits non-zero then we exit to prevent repeatedly showing the error
# message. Otherwise we will call westley or westley.alt directly.
# #
# Usage: ./try.sh # Usage: ./try.sh
# #
@@ -56,72 +41,80 @@ if [[ -z "$CC" ]]; then
fi fi
make CC="$CC" westley westley.alt >/dev/null || exit 4 make CC="$CC" westley westley.alt >/dev/null || exit 4
make CC="$CC" whereami whereami.alt >/dev/null || exit 4
# get the path to the right programs # get the path to the right programs
if [[ -x "whereami" ]]; then if [[ -x "whereami.sh" ]]; then
WESTLEY="whereami" WESTLEY="whereami.sh"
CC="$CC" ./"$WESTLEY" 0 0 >/dev/null || exit 1
else else
WESTLEY="westley" chmod +x whereami.sh
fi if [[ -x "whereami.sh" ]]; then
if [[ -x "whereami.alt" ]]; then WESTLEY="whereami.sh"
WESTLEY_ALT="whereami.alt" else
CC="$CC" ./"$WESTLEY_ALT" 0 0 >/dev/null || exit 1 WESTLEY="westley"
else fi
WESTLEY_ALT="westley.alt"
fi fi
echo "New York:" 1>&2 if [[ -x "whereami.alt.sh" ]]; then
WESTLEY_ALT="whereami.alt.sh"
else
chmod +x whereami.alt.sh
if [[ -x "whereami.alt.sh" ]]; then
WESTLEY_ALT="whereami.alt.sh"
else
WESTLEY_ALT="westley.alt"
fi
fi
read -r -n 1 -p "Press any key to show New York: "
echo 1>&2 echo 1>&2
./"$WESTLEY_ALT" 41 -74 ./"$WESTLEY_ALT" 41 -74
echo 1>&2 echo 1>&2
echo "London:" 1>&2 read -r -n 1 -p "Press any key to show London: "
echo 1>&2 echo 1>&2
./"$WESTLEY" 52 0 ./"$WESTLEY" 52 0
echo 1>&2 echo 1>&2
echo "Moscow:" 1>&2 read -r -n 1 -p "Press any key to show Moscow: "
echo 1>&2 echo 1>&2
./"$WESTLEY" 56 38 ./"$WESTLEY" 56 38
echo 1>&2 echo 1>&2
echo "New Delhi:" 1>&2 read -r -n 1 -p "Press any key to show New Delhi: "
echo 1>&2 echo 1>&2
./"$WESTLEY" 29 77 ./"$WESTLEY" 29 77
echo 1>&2 echo 1>&2
echo "Sydney:" 1>&2 read -r -n 1 -p "Press any key to show Sydney: "
echo 1>&2 echo 1>&2
./"$WESTLEY" -34 151 ./"$WESTLEY" -34 151
echo 1>&2 echo 1>&2
echo "Los Angeles:" 1>&2 read -r -n 1 -p "Press any key to show Los Angeles: "
echo 1>&2 echo 1>&2
./"$WESTLEY_ALT" 34 -118 ./"$WESTLEY_ALT" 34 -118
echo 1>&2 echo 1>&2
echo "Paris:" 1>&2 read -r -n 1 -p "Press any key to show Paris: "
echo 1>&2 echo 1>&2
./"$WESTLEY" 45 2 ./"$WESTLEY" 45 2
echo 1>&2 echo 1>&2
echo "Rio de Janeiro:" 1>&2 read -r -n 1 -p "Press any key to show Rio de Janeiro: "
echo 1>&2 echo 1>&2
./"$WESTLEY" -23 -43 ./"$WESTLEY" -23 -43
echo 1>&2 echo 1>&2
echo "Beijing:" 1>&2 read -r -n 1 -p "Press any key to show Beijing: "
echo 1>&2 echo 1>&2
./"$WESTLEY" 40 116 ./"$WESTLEY" 40 116
echo 1>&2 echo 1>&2
echo "Tokyo:" 1>&2 read -r -n 1 -p "Press any key to show Tokyo: "
echo 1>&2 echo 1>&2
./"$WESTLEY" 36 140 ./"$WESTLEY" 36 140
echo 1>&2 echo 1>&2
echo "Approximate judging location:" 1>&2 read -r -n 1 -p "Press any key to show approximate judging location: "
echo 1>&2 echo 1>&2
./"$WESTLEY_ALT" 37 -122 ./"$WESTLEY_ALT" 37 -122
-79
View File
@@ -1,79 +0,0 @@
/*
* whereami.alt.c: wrapper program to westley.alt.c that checks first the
* columns of the terminal, exiting if < 80 and otherwise try compiling
* westley.alt.c (with make) and then if is already compiled or ends up being
* compiled it will be run with the specified args to this program.
*
* It is an error to not specify two args but it is not an error to specify args
* that are not numbers. The atoi(3) function typically returns 0 in that case
* which westley.alt.c uses.
*
* The reason to use this wrapper is because westley.alt.c needs at least 80
* columns to show the output right. Previously it required 80 column wrapping
* but in 2023 this limitation was removed, allowing it to work as long as there
* are at least 80 columns.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <curses.h>
int main(int argc, char **argv)
{
int cols;
char *cc = NULL; /* for if the user passes in CC=foo */
char *buf = NULL;
if (argc < 3)
exit(fprintf(stderr, "usage: %s <lat> <long>\n", argv[0]));
/* try and get compiler to use */
cc = getenv("CC");
if (!cc)
cc = "cc";
buf = calloc(1, strlen(cc) + strlen("CC=") + 1);
if (buf != NULL)
sprintf(buf, "CC=%s", cc);
else
buf = "CC=cc";
/* init curses so we can get the number of columns */
if (!initscr())
exit(2);
/* save columns */
cols = COLS;
/*
* end curses so that we can either report an error or compile and run
* westley.alt
*/
endwin();
if (cols < 80)
{
fprintf(stderr, "your terminal must be at\nleast 80 columns wide\nbut is only %d, sorry.\n", COLS);
exit(3);
}
/*
* compile westley.alt.c and run if successful
*/
buf = calloc(1, strlen("make CC=") + strlen(cc) + strlen("westley.alt") + strlen(">/dev/null") + 1);
if (buf)
sprintf(buf, "make CC=%s westley.alt >/dev/null", cc);
else
buf = "make westley.alt >/dev/null";
/* compile source file */
if (system(buf))
{
fprintf(stderr, "couldn't compile westley.alt.c, sorry.\n");
exit(4);
}
/* if we get here we compiled the code or it was already compiled so run it */
execl("./westley.alt", "./westley.alt", argv[1], argv[2], NULL);
return 0;
}
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
#
# whereami.alt - a wrapper script to westley.alt.c that checks first the columns
# of the terminal, exiting if < 80 and otherwise try compiling westley.alt.c
# (with make) and then if is already compiled or ends up being compiled it will
# be run with the specified args to this program.
#
# It is an error to not specify two args but it is not an error to specify args
# that are not numbers. The atoi(3) function typically returns 0 in that case
# which westley.alt.c uses.
#
# The reason to use this wrapper is because westley.alt.c needs at least 80
# columns to show the output right. Previously it required 80 column wrapping
# but in 2023 this limitation was removed, allowing it to work as long as there
# are at least 80 columns.
# make sure there are at least two args
if [[ "$#" -lt 2 ]]; then
echo "usage: $0 lat long" 1>&2
exit 1
fi
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
# this way allows us to have the user specify a different compiler in an easy
# way.
if [[ -z "$CC" ]]; then
CC="cc"
fi
# try getting the columns the simple way first: tput cols
COLUMNS="$(tput cols)"
if [[ "$?" -ne 0 ]]; then
# if tput failed for any reason try stty(1) with awk(1):
COLUMNS="$(stty size|awkf '{print $NF}')"
fi
if [[ "$COLUMNS" -lt 80 ]]; then
echo "Your terminal must be at least 80" 1>&2
echo "columns wide echo but yours is only" 1>&2
echo "$COLUMNS, sorry." 1>&2
exit 2
fi
make CC="$CC" everything >/dev/null || exit 1
./westley.alt "$1" "$2"
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
#
# whereami - a wrapper script to westley.c that checks first the
# columns of the terminal, exiting if < 80 and otherwise try compiling
# westley.c (with make) and then if is already compiled or ends up being
# compiled it will be run with the specified args to this program.
#
# It is an error to not specify two args but it is not an error to specify args
# that are not numbers. The atoi(3) function typically returns 0 in that case
# which westley.c uses.
#
# The reason to use this wrapper is because westley.c needs at least 80 columns
# to show the output right. Previously it required 80 column wrapping but in
# 2023 this limitation was removed, allowing it to work as long as there are at
# least 80 columns.
# make sure there are at least two args
if [[ "$#" -lt 2 ]]; then
echo "usage: $0 lat long" 1>&2
exit 1
fi
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
# this way allows us to have the user specify a different compiler in an easy
# way.
if [[ -z "$CC" ]]; then
CC="cc"
fi
# try getting the columns the simple way first: tput cols
COLUMNS="$(tput cols)"
if [[ "$?" -ne 0 ]]; then
# if tput failed for any reason try stty(1) with awk(1):
COLUMNS="$(stty size|awkf '{print $NF}')"
fi
if [[ "$COLUMNS" -lt 80 ]]; then
echo "Your terminal must be at least 80" 1>&2
echo "columns wide echo but yours is only" 1>&2
echo "$COLUMNS, sorry." 1>&2
exit 1
fi
make CC="$CC" all >/dev/null || exit 1
./westley "$1" "$2"
+4
View File
@@ -2,3 +2,7 @@ bmeyer
lavabus.glic lavabus.glic
bmeyer.orig bmeyer.orig
prog.orig prog.orig
lenna.pgm
new.pgm
glicbawls
lavabus.glic2
+2
View File
@@ -133,6 +133,8 @@ all: data ${TARGET}
${PROG}: ${PROG}.c ${PROG}: ${PROG}.c
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS} ${CC} ${CFLAGS} $< -o $@ ${LDFLAGS}
${RM} -f glicbawls
${CP} -f $@ glicbawls
# alternative executable # alternative executable
# #
+52 -85
View File
@@ -17,47 +17,11 @@ make
In a video window (white text on black background): In a video window (white text on black background):
```sh ```sh
./bmeyer < michael.pgm > michael.glic ./try.sh
``` ```
Compare the `michael.pgm` to the screen output. The script will suggest you compare the output of the program with images,
prompting you to press any key to continue so that you may do so.
To test that you are compressing and decompressing the same way the
author was, try:
```sh
./bmeyer < lenna.glic
```
Also try in a reverse video window:
```sh
./bmeyer < michael.pgm 2>/dev/null | ./bmeyer > new.pgm
```
Compare the [michael.pgm](michael.pgm) to the screen output. Compare the
`new.pgm` file to the [michael.pgm](michael.pgm) file.
Create a large reverse video xterm, say 200 columns wide and try:
```sh
./bmeyer 200 < lavabus.pgm > lavabus.glic
```
Produce an even smaller output:
```sh
./bmeyer -2 200 < lavabus.pgm > lavabus.glic2
```
Decompress that smaller glic-file:
```sh
./bmeyer -2 200 < lavabus.glic2 > new.pgm
```
Compare the `new.pgm` file to the [lavabus.pgm](lavabus.pgm) file by viewing
them.
## Judges' remarks: ## Judges' remarks:
@@ -72,7 +36,7 @@ bmeyer: bmeyer.c
CC -DY="__setfpucw(0x127f)" -O6 $? -o $@ -lm CC -DY="__setfpucw(0x127f)" -O6 $? -o $@ -lm
``` ```
However many compilers use -O3 as the maximum level for -O optimization. However many compilers use `-O3` as the maximum level for `-O` optimization.
And on linux/x86, glibc 2.1: And on linux/x86, glibc 2.1:
@@ -85,14 +49,14 @@ Compile with the maximum possible optimization on your system.
If your system has 80-bit internal representation of floating If your system has 80-bit internal representation of floating
point values (x86, some Motorola processors) and you want the point values (x86, some Motorola processors) and you want the
compressed format to be portable across platforms, you need compressed format to be portable across platforms, you need
to set your FPU to use 64 bit mode. See the extra build lines to set your FPU to use 64 bit mode. Read the author's remarks
in the Makefile, and read the author's remarks below. below for more details.
If you cannot work out how to get into 64 bit mode, you can If you cannot work out how to get into 64 bit mode, you can
try using `-ffloat-store` if you compile with GCC (this may have try using `-ffloat-store` if you compile with GCC (this may have
a performance penalty). The resulting binary will have a good a performance penalty). The resulting binary will have a good
chance to produce portable files, but due to the resulting chance to produce portable files, but due to the resulting
double-rounding (first internally to 80 bit, then to 64 bit double-rounding (first internally set to 80 bit, then to 64 bit
on writing the value to memory), there is a small but very real on writing the value to memory), there is a small but very real
chance any given file produced might not be portable. chance any given file produced might not be portable.
@@ -110,20 +74,20 @@ This program is called `GLICBAWLS`
Squares". Squares".
And that's exactly what this program does --- feed it a .PGM file And that's exactly what this program does --- feed it a .PGM file
(either raw [i.e. P5] or ascii [i.e. P2]) on stdin, and it will (either raw [i.e. P5] or ASCII [i.e. P2]) on stdin, and it will
output a compressed version to stdout. Feed it a compressed file output a compressed version to stdout. Feed it a compressed file
on stdin, and it will decompress it to stdout --- as either raw or on stdin, and it will decompress it to stdout --- as either raw or
ascii .PGM, depending on what format it was compressed from. For ASCII .PGM, depending on what format it was compressed from. For
example: example:
```sh ```sh
./bmeyer < michael.pgm > michael.glic ./glicbawls < michael.pgm > michael.glic
``` ```
and then and then
```sh ```sh
./bmeyer < michael.glic > michael.decoded.pgm ./glicbawls < michael.glic > michael.decoded.pgm
``` ```
As it turns out, `glicbawls` compresses greyscale images (or, more As it turns out, `glicbawls` compresses greyscale images (or, more
@@ -133,7 +97,7 @@ program developed for my PhD thesis). Of course, this might take
some time, so a progress indicator is provided. To make things some time, so a progress indicator is provided. To make things
more interesting, instead of a boring bar or percentage display, more interesting, instead of a boring bar or percentage display,
an ASCII rendition of the image being compressed/decompressed is an ASCII rendition of the image being compressed/decompressed is
output to stderr (assuming white text on black background). If you output to `stderr` (assuming white text on black background). If you
have trouble recognizing the image, try squinting at it ;-). have trouble recognizing the image, try squinting at it ;-).
If you still have trouble, simply use a terminal or xterm with If you still have trouble, simply use a terminal or xterm with
@@ -141,7 +105,7 @@ more than 80 columns, and tell `glicbawls` about it by giving the
number of columns as an argument. For example number of columns as an argument. For example
```sh ```sh
./bmeyer 260 <lavabus.pgm >lavabus.glic ./glicbawls 260 <lavabus.pgm >lavabus.glic
``` ```
will allow `glicbawls` to use up to 260 columns, which makes things will allow `glicbawls` to use up to 260 columns, which makes things
@@ -154,32 +118,32 @@ compression mode. In that mode, the decoded pixel values are
allowed to differ from the originals, but there is an upper limit allowed to differ from the originals, but there is an upper limit
on the magnitude of the difference. For example, if a maximum on the magnitude of the difference. For example, if a maximum
error of 2 is allowed, an original pixel value of 37 could be error of 2 is allowed, an original pixel value of 37 could be
decoded as 35,36,37, 38 or 39. In order to use this mode, simply decoded as 35, 36, 37, 38 or 39. In order to use this mode, simply
give the maximum allowed error as an argument, with a dash (`-`) give the maximum allowed error as an argument, with a dash (`-`)
before it. For example before it. For example:
```sh ```sh
./bmeyer -2 < graph.pgm > graph.2.glic ./glicbawls -2 < graph.pgm > graph.2.glic
``` ```
will compress in a way that allows decompression with a maximum will compress in a way that allows decompression with a maximum
error of two. You can combine both types of arguments, i.e. error of two. You can combine both types of arguments, i.e.:
```sh ```sh
./bmeyer -3 180 < graph.pgm >graph.3.glic ./glicbawls -3 180 < graph.pgm >graph.3.glic
``` ```
will compress with a maximum error of 3, using a 180 column will compress with a maximum error of 3, using a 180 column
terminal for the progress display, and terminal for the progress display, and:
```sh ```sh
./bmeyer -3 180 < graph.3.glic > graph.3maxerr.pgm ./glicbawls -3 180 < graph.3.glic > graph.3maxerr.pgm
``` ```
will decompress the result on such a terminal. will decompress the result on such a terminal.
But wait, there is more --- you can also feed `glicbawls` .PPM files But wait, there is more --- you can also feed `glicbawls` .PPM files
(i.e. colour images), raw or ascii, your choice. `Glicbawls` will (i.e. colour images), raw or ASCII, your choice. `glicbawls` will
compress and decompress them just fine. However, it only does compress and decompress them just fine. However, it only does
"reasonably well" on them; It beats PNG easily, but there are "reasonably well" on them; It beats PNG easily, but there are
certainly programs out there that can compress colour images certainly programs out there that can compress colour images
@@ -190,7 +154,7 @@ from a photo or camera)....
### WARNING ### WARNING
`Glicball` is rather CPU and FPU intensive. Don't run it on anything slow. `glicball` is rather CPU and FPU intensive. Don't run it on anything slow.
Things start to be usable around 300+MHz, with 600+ being highly desirable. Things start to be usable around 300+MHz, with 600+ being highly desirable.
@@ -208,7 +172,7 @@ Fortunately, just about all current FPUs can be put into IEEE 64
bit mode (or at least something close enough for bit mode (or at least something close enough for
`glicbawls`). Unfortunately, there is no standard way of doing `glicbawls`). Unfortunately, there is no standard way of doing
so. For this reason, the build file contains *three* compile so. For this reason, the build file contains *three* compile
lines; One for machines that already use 64 bit mode by default lines; one for machines that already use 64 bit mode by default
(most RISC processors), one for linux/x86 machines using libc4, (most RISC processors), one for linux/x86 machines using libc4,
libc5 or glibc2.0, and one for linux/x86 machines using glibc2.1 libc5 or glibc2.0, and one for linux/x86 machines using glibc2.1
(glibc2.1 no longer exports the `__setfpucw()` function, necessitating (glibc2.1 no longer exports the `__setfpucw()` function, necessitating
@@ -226,10 +190,10 @@ own compressed files, but you may be unable to exchange files with
Most of the obfuscation of this program was driven by the Most of the obfuscation of this program was driven by the
desperate struggle to fit all of `glicbawls`' features into code desperate struggle to fit all of `glicbawls`' features into code
that fits the IOCCC's size limits. All identifiers names are that fits the IOCCC's size limits. All identifiers' names are
single-character, which was only possible by ruthless exploitation single-character, which was only possible by ruthless exploitation
of scope. There is a function `M()` that handles nearly all input of scope. There is a function `M()` that handles nearly all input
from stdin, handles all output to stdout, and also recursively from `stdin`, handles all output to `stdout`, and also recursively
calculates one of the mathematical expressions needed for error calculates one of the mathematical expressions needed for error
modelling. There is a function that calculates `(A^(-1)*b)*x` with `A` modelling. There is a function that calculates `(A^(-1)*b)*x` with `A`
being a matrix and `b` and `x` being vectors, and does so in a very being a matrix and `b` and `x` being vectors, and does so in a very
@@ -241,7 +205,7 @@ value when control flow reaches the loops. Lots of functions use
the same two global scratch variables. Variables change their the same two global scratch variables. Variables change their
meaning all the time, and the differences between compressing and meaning all the time, and the differences between compressing and
decompressing are handled in rather subtle ways all over the decompressing are handled in rather subtle ways all over the
program. The string that holds the ascii values for displaying the program. The string that holds the ASCII values for displaying the
progress image doubles as a description on how to find a pixel's progress image doubles as a description on how to find a pixel's
causal neighbours. And then there are a few `#define`s that really causal neighbours. And then there are a few `#define`s that really
are just in there to save a few characters, but as an added are just in there to save a few characters, but as an added
@@ -254,9 +218,9 @@ are a true wizard, it is unlikely to gain you any insights into
what is actually going on....\[0\] what is actually going on....\[0\]
### Bugs, Assumptions and TODOs ### Bugs, Assumptions and TODO
`Glicbawls` assumes that characters are 8 bit wide, and that the `glicbawls` assumes that characters are 8 bit wide, and that the
character set used is ASCII. If one of these isn't true, all hell character set used is ASCII. If one of these isn't true, all hell
will break loose. will break loose.
@@ -271,12 +235,12 @@ When decompressing a near-lossless encoded image, the maximum
allowed error is required as a command line parameter. This should allowed error is required as a command line parameter. This should
really be saved in the compressed file! really be saved in the compressed file!
`Glicbawls` relies on the decimal representation of all integers `glicbawls` relies on the decimal representation of all integers
having less than 255 digits. While ANSI C does not guarantee this, having less than 255 digits. While ANSI C does not guarantee this,
it seems rather unlikely that anyone in the foreseeable future it seems rather unlikely that anyone in the foreseeable future
would use images with `10^255` rows, columns or different levels of would use images with `10^255` rows, columns or different levels of
grey. Also, it is assumed that any integer used can be cast to a grey. Also, it is assumed that any integer used can be cast to a
double and back without loss of precision. This limits the number `double` and back without loss of precision. This limits the number
of rows, columns and grey levels to 9 quintillion, which should of rows, columns and grey levels to 9 quintillion, which should
also be sufficient for the next few years. also be sufficient for the next few years.
@@ -287,8 +251,8 @@ million in a lottery. But if it happens to you, don't say I
didn't warn you! Instead, go out and buy a lightning rod and a didn't warn you! Instead, go out and buy a lightning rod and a
lottery ticket ;-) lottery ticket ;-)
At one point, a pointer to int is used as the target of a `"%1[#]"` At one point, a pointer to `int` is used as the target of a `"%1[#]"`
conversion in a scanf, which makes gcc rather unhappy, but conversion in a `scanf(3)`, which makes gcc rather unhappy, but
shouldn't really cause anyone any trouble. The same goes for a shouldn't really cause anyone any trouble. The same goes for a
couple of assignments which are used as truth values. couple of assignments which are used as truth values.
@@ -300,23 +264,25 @@ the scope of an info file, and would also be quite difficult in
pure ASCII, so the following is just a rough outline, and contains pure ASCII, so the following is just a rough outline, and contains
some compression-speak... some compression-speak...
The image is handled in scanline ordering. For each pixel, an The image is handled in [scanline](https://en.wikipedia.org/wiki/Scan_line)
expected value is calculated by creating a least squares predictor ordering. For each pixel, an expected value is calculated by creating a least
of order 12 based on all of the previously encoded/decoded squares predictor of order 12 based on all of the previously encoded/decoded
pixels. However, the contribution of each pixel is weighted pixels. However, the contribution of each pixel is weighted according to its
according to its Manhattan-distance from the current pixel, [Manhattan-distance](https://en.wikipedia.org/wiki/Taxicab_geometry) from the
D. That weight used is `pow(0.8,D)`. \[1\] \[2\] \[3\] current pixel, `D`. That weight used is `pow(0.8,D)`. \[1\] \[2\] \[3\]
In a similar way, the prediction *errors* for all previous pixels In a similar way, the prediction *errors* for all previous pixels
are combined --- a weighted average (with weight `pow(0.7,D)`) of are combined --- a weighted average (with weight `pow(0.7,D)`) of
the squares of all previous prediction errors is taken, and the the squares of all previous prediction errors is taken, and the
square root of the (appropriately scaled) result is called sigma. square root of the (appropriately scaled) result is called sigma.
The predicted value and sigma are then used as the parameters of a The predicted value and sigma are then used as the parameters of a [Student or
Student or t-distribution (which is similar to a normal t-distribution](https://en.wikipedia.org/wiki/Student%27s_t-distribution) (which
distribution, but has more weight in the tails), providing a is similar to a [normal
probability distribution for the current pixel. distribution](https://en.wikipedia.org/wiki/Normal_distribution), but has more
weight in the tails), providing a [probability
distribution](https://en.wikipedia.org/wiki/Probability_distribution) for the
current pixel.
Next, the possible interval of values for the current pixel is Next, the possible interval of values for the current pixel is
halved, and through integration of the probability distribution, a halved, and through integration of the probability distribution, a
@@ -332,13 +298,13 @@ en/decoded\[4\].
[0] Yes, this could be seen as a challenge.... [0] Yes, this could be seen as a challenge....
[1] Actually, the weight is `pow(0.8,D)/s`, where `s` is the sigma [1] Actually, the weight is `pow(0.8,D)/s`, where `s` is the sigma
used for en/decoding the particular previous pixel. Dividing used for encoding/decoding the particular previous pixel. Dividing
by `s` is a rather arbitrary action justified only by the by `s` is a rather arbitrary action justified only by the
improvement in results. Mathematically, I can only justify improvement in results. Mathematically, I can only justify
dividing by `s^2`, or not dividing at all.... dividing by `s^2`, or not dividing at all....
[2] Obviously, these least squares predictors are not calculated [2] Obviously, these least squares predictors are not calculated
from scratch for each pixel. Some clever reuse of earlier from scratch for each pixel. Some clever reuse of earlier
results allows O(1) calculation, rather than the results allows `O(1)` calculation, rather than the
`O(previous_rows*columns)` this description would suggest. `O(previous_rows*columns)` this description would suggest.
[3] As anyone who has ever tried local least squares knows from [3] As anyone who has ever tried local least squares knows from
bitter experience, there is a lot of numerical instability bitter experience, there is a lot of numerical instability
@@ -346,7 +312,7 @@ en/decoded\[4\].
averaging predictor to the equation system the least squares averaging predictor to the equation system the least squares
predictor is calculated from. The weight that is given to predictor is calculated from. The weight that is given to
this bias is constantly adjusted throughout coding/decoding, this bias is constantly adjusted throughout coding/decoding,
thus justifying the 'a' in "glicbawls". thus justifying the 'a' in `glicbawls`.
[4] In the case of near-lossless coding, the interval is not [4] In the case of near-lossless coding, the interval is not
necessarily *halved*, but rather split at a convenient point necessarily *halved*, but rather split at a convenient point
(the split points are chosen in such a way as to minimise the (the split points are chosen in such a way as to minimise the
@@ -359,7 +325,7 @@ en/decoded\[4\].
[Lavabus](lavabus.pgm) was taken by the judge, Landon Curt Noll. [Lavabus](lavabus.pgm) was taken by the judge, Landon Curt Noll.
[Michael](michael.pgm) was provided by the author. [Lenna](lenna.glic) is a [Michael](michael.pgm) was provided by the author. [Lenna](lenna.glic) is a
1972 Playboy centerfold. 1972 Playboy centerfold (doesn't show very much).
- [michael.pgm](michael.pgm) - [michael.pgm](michael.pgm)
@@ -367,8 +333,9 @@ en/decoded\[4\].
- [lavabus.pgm](lavabus.pgm) - [lavabus.pgm](lavabus.pgm)
A bus that was trapped by lava from Kilauea volcano in Hawaii, US. Nobody A bus that was trapped by lava from [Kilauea
was in the bus at the time, BTW. Photo date: 1981. volcano](https://en.wikipedia.org/wiki/Kīlauea) in Hawaii, US. Nobody was
in the bus at the time, BTW. Photo date: 1981.
- [lenna.glic](lenna.glic) - [lenna.glic](lenna.glic)
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin/env bash
#
# try.sh - demonstrate IOCCC winner 2000/bmeyer
#
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
# this way allows us to have the user specify a different compiler in an easy
# way.
if [[ -z "$CC" ]]; then
CC="cc"
fi
make CC="$CC" all >/dev/null || exit 1
# clear screen after compilation so that only the entry is shown
clear
# We need to have the column count for later on. It is not an error if it cannot
# be determined: we just use a default value.
#
# try getting the columns the simple way first: tput cols
COLUMNS="$(tput cols)"
# ^--^ SC2181 (style): Check exit code directly with e.g. 'if ! mycmd;', not indirectly with $?.
# shellcheck disable=SC2181
if [[ "$?" -ne 0 ]]; then
# if tput failed for any reason try stty(1) with awk(1):
# Disable this warning of shellcheck as it's wrong: awk needs single quotes.
# ^-----------^ SC2016 (info): Expressions don't expand in single quotes, use double quotes for that.
# shellcheck disable=SC2016
COLUMNS="$(stty size|awk '{print $NF}')"
if [[ "$?" -ne 0 ]]; then
COLUMNS=150
fi
fi
echo "Warning: if you don't have white text on a black background the output" 1>&2
echo "might not be as correct or visually appealing." 1>&2
echo 1>&2
if [[ "$COLUMNS" -lt 81 ]]; then
echo "Warning: your terminal is < 81 columns and this might cause output" 1>&2
echo "issues." 1>&2
echo 1>&2
fi
read -r -n 1 -p "Press any key to start: "
echo "$ ./glicbawls < michael.pgm > michael.glic" 1>&2
./glicbawls < michael.pgm > michael.glic
echo "Now compare the michael.pgm to the screen output." 1>&2
read -r -n 1 -p "Press any key to continue: "
echo "$ ./glicbawls < michael.pgm 2>/dev/null | ./glicbawls > new.pgm" 1>&2
./glicbawls < michael.pgm 2>/dev/null | ./glicbawls > new.pgm
echo "Now compare the michael.pgm to the screen output." 1>&2
read -r -n 1 -p "Press any key to continue: "
echo "Now compare the new.pgm file to the michael.pgm file."
read -r -n 1 -p "Press any key to continue: "
read -r -n -p 1 "Press any key to trying and use your screen width on lava bus pic: "
echo "$ ./glicbawls $COLUMNS < lavabus.pgm > lavabus.glic" 1>&2
./glicbawls "$COLUMNS" < lavabus.pgm > lavabus.glic
read -r -n 1 -p "Press any key to continue: "
echo "$ ./glicbawls -2 "$COLUMNS" < lavabus.pgm > lavabus.glic2"
./glicbawls -2 "$COLUMNS" < lavabus.pgm > lavabus.glic2
read -r -n 1 -p "Press any key to decompress the smaller glic-file: "
echo "$ ./glicbawls -2 150 < lavabus.glic2 > new.pgm" 1>&2
./glicbawls -2 150 < lavabus.glic2 > new.pgm
echo "Now compare the new.pgm file to the lavabus.pgm file." 1>&2
-7
View File
@@ -28,13 +28,6 @@ evening of Dec 22, 2000).
Can you find out how it stores the insult strings? Can you then take Can you find out how it stores the insult strings? Can you then take
an insult and figure out when it will be uttered? an insult and figure out when it will be uttered?
[sc] The code also contained a buffer overflow bug which I have fixed!
The array size of `s` should be 1079 characters long. (From 0 to 1078
inclusive!). Without this it results in an error in the encoding of
"decrepit" -- For a 32bit little endian machine using GCC (because of
the way it assigns variables to memory) it will terminate "decrepit"
with the character `'\200'` (the last value of `F`) instead of `'\0'`.
## Author's remarks: ## Author's remarks:
+17 -13
View File
@@ -1627,22 +1627,19 @@ the final loop it prints another newline. This fix has another bonus in that
resizing the terminal after running it should not mess up the display either, resizing the terminal after running it should not mess up the display either,
unless of course it becomes too small. unless of course it becomes too small.
Cody added the programs [whereami.c](1992/westley/whereami.c) and Cody added the scripts [whereami.sh](1992/westley/whereami.sh) and
[whereami.alt](1992/westley/whereami.alt.c) which correspond to the entry and [whereami.alt.sh](1992/westley/whereami.alt.sh) which correspond to the entry and
the alt code but which, by way of curses, checks for the number of columns; if the alt code but first check that the number of columns is at least 80 and if
all is good it will try compiling the program or alt program, respectively, and not it is an error.
then if successful run the program. Otherwise, if there are not enough columns
it is an error. It is always an error if the compilation of the program itself
(westley.c, westley.alt.c) fails.
Cody added the [try.sh](1992/westley/try.sh) script that shows the different Cody added the [try.sh](1992/westley/try.sh) script that shows the different
cities that the author recommended one try as well as the one recommended by the cities that the author recommended one try as well as the one recommended by the
judges (approximate judging location), labelling each city and printing a judges (approximate judging location), labelling each city and printing a
newline before the next city. The try.sh script uses the `whereami` code, if it newline before the next city. The try.sh script uses the `whereami.sh` and
can be compiled and linked, but otherwise it uses `westley` code instead, either `whereami.alt.sh` scripts, as long as they're executable (if they're not it
the entry or alt code. The try.sh cannot be deceived by way of `COLUMNS=81 first tries to make it executable and if it fails to do so it just uses
./try.sh` but the `whereami`/`whereami.alt` code can be deceived if directly `westley` or `westley.alt`. The scripts can be deceived by `COLUMNS=80 ./try.sh`
called. This is a feature, not a bug: or maybe a limitation of curses. (or `COLUMNS=80 ./whereami.sh` etc.) but this is a feature, not a bug.
Cody also added an arg check because the program and the Cody also added an arg check because the program and the
[alternate version](1992/westley/westley.alt.c) might have crashed or [alternate version](1992/westley/westley.alt.c) might have crashed or
@@ -1650,7 +1647,7 @@ Cody also added an arg check because the program and the
world](https://en.wikipedia.org/wiki/Earth) or just the world](https://en.wikipedia.org/wiki/Earth) or just the
[USA](https://en.wikipedia.org/wiki/United_States), respectively, without enough [USA](https://en.wikipedia.org/wiki/United_States), respectively, without enough
args (2). And not that we need the help or anything for this :-) but we args (2). And not that we need the help or anything for this :-) but we
encourage you to try the original :-) encourage you to try the original without two args :-)
## [1993/cmills](1993/cmills/cmills.c) ([README.md](1993/cmills/README.md])) ## [1993/cmills](1993/cmills/cmills.c) ([README.md](1993/cmills/README.md]))
@@ -2271,6 +2268,13 @@ code looks like before.
Cody also added the [try.sh](2000/anderson/try.sh) script. Cody also added the [try.sh](2000/anderson/try.sh) script.
## [2000/bmeyer](2000/bmeyer/bmeyer.c) ([README.md](2000/bmeyer/README.md]))
Cody added the [try.sh](2000/bmeyer/try.sh) script with some improvements to the
commands we recommended like not assuming the number of columns one has in their
terminal.
## [2000/briddlebane](2000/briddlebane/briddlebane.c) ([README.md](2000/briddlebane/README.md])) ## [2000/briddlebane](2000/briddlebane/briddlebane.c) ([README.md](2000/briddlebane/README.md]))
Cody fixed this to compile in systems that require one to explicitly link in Cody fixed this to compile in systems that require one to explicitly link in
+9 -1
View File
@@ -1,5 +1,5 @@
# A todo list of known things to check and/or do # A todo list of known things to check and/or do
*Last updated: Thu 02 Nov 2023 12:32:15 UTC* *Last updated: Thu 16 Nov 2023 11:20:54 UTC**
This document is primarily for [Cody Boone This document is primarily for [Cody Boone
Ferguson](/winners.html#Cody_Boone_Ferguson) as he (that is I :-) ) wanted a way Ferguson](/winners.html#Cody_Boone_Ferguson) as he (that is I :-) ) wanted a way
@@ -144,3 +144,11 @@ instead change it to make pull requests. See the
- Check the YYYY/README.md files for other things besides the GitHub pull - Check the YYYY/README.md files for other things besides the GitHub pull
requests rather than emailing judges. This can be done on the final pass of the requests rather than emailing judges. This can be done on the final pass of the
files. files.
- In the entries with the alt code that use `usleep(3)` make the macro name
consistent across all entries. At one point `Z` was used but in one entry `Z`
was taken so this would not work. It appears at this time (16 November 2023)
that it might be that `S` will work in all cases (currently?) though one has two
values so the second would could be changed to `SS` (which is convenient as it's
for SDL). This is low priority but it would be nice to have done as it would
make it consistent and easy to remember.