Add 2020 source files for real
This commit is contained in:
1 parent
a3c1748648
commit
9d61fc0fb4
147 files changed
+32101
No files matched your search
@@ -0,0 +1,600 @@
|
||||
#!/usr/bin/env make
|
||||
#
|
||||
# 2020 makefile
|
||||
#
|
||||
# This work by Landon Curt Noll, Simon Cooper, 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
|
||||
#############################
|
||||
#
|
||||
SHELL= /bin/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
|
||||
ECHO= echo
|
||||
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
|
||||
|
||||
# Set X11_LIBDIR to the directory where the X11 library resides
|
||||
#
|
||||
#X11_LIBDIR= /usr/X11R6/lib
|
||||
#X11_LIBDIR= /usr/X11/lib
|
||||
X11_LIBDIR= /opt/X11/lib
|
||||
|
||||
# Set X11_INCLUDEDIR to the directory where the X11 include files reside
|
||||
#
|
||||
#X11_INCDIR= /usr/X11R6/include
|
||||
#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
|
||||
#
|
||||
#CSILENCE=
|
||||
#CSILENCE= -Wno-implicit-int
|
||||
CSILENCE= -Wno-missing-variable-declarations -Wno-missing-prototypes -Wno-disabled-macro-expansion \
|
||||
-Wno-conversion -Wno-unused-value -Wno-empty-body -Wno-conversion -Wno-misleading-indentation \
|
||||
-Wno-comment -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}
|
||||
|
||||
else
|
||||
ifeq ($(CC),gcc)
|
||||
|
||||
# gcc CSILENCE and CWARN
|
||||
#
|
||||
#CSILENCE=
|
||||
#CSILENCE= -Wno-implicit-int
|
||||
CSILENCE= -Wno-disabled-macro-expansion -Wno-conversion -Wno-unused-value -Wno-binding-in-condition \
|
||||
-Wno-empty-body -Wno-comment -Wno-misleading-indentation -Wno-unknown-warning-option
|
||||
#
|
||||
#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-disabled-macro-expansion -Wno-conversion -Wno-unused-value -Wno-empty-body \
|
||||
-Wno-comment -Wno-misleading-indentation -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
|
||||
#
|
||||
#CSTD=
|
||||
#CSTD= -ansi
|
||||
CSTD= -std=c11
|
||||
|
||||
# compiler bit architecture
|
||||
#
|
||||
# Some entries require 32-bitness:
|
||||
# ARCH= -m32
|
||||
#
|
||||
# Some entries require 64-bitness:
|
||||
# ARCH= -m64
|
||||
#
|
||||
# By default we assume nothing:
|
||||
#
|
||||
ARCH=
|
||||
|
||||
# defines that are needed to compile
|
||||
#
|
||||
#CDEFINE=
|
||||
#CDEFINE= -DIOCCC
|
||||
CDEFINE= -D_POSIX_C_SOURCE=200809L
|
||||
|
||||
# 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}
|
||||
|
||||
# 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
|
||||
# under those buggy optimizers and thus you may not want anything.
|
||||
# Reasonable compilers will allow for -O3.
|
||||
#
|
||||
#OPT=
|
||||
#OPT= -O
|
||||
#OPT= -O1
|
||||
#OPT= -O2
|
||||
OPT= -O3
|
||||
|
||||
# default flags for ANSI C compilation
|
||||
#
|
||||
CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT}
|
||||
|
||||
# Libraries needed to build
|
||||
#
|
||||
LIBS=
|
||||
#LIBS= -L ${X11_LIBDIR}
|
||||
|
||||
# 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.
|
||||
#
|
||||
CC= cc
|
||||
#CC= clang
|
||||
MAY_NEED_GCC= gcc
|
||||
|
||||
|
||||
##############################
|
||||
# Special flags for this entry
|
||||
##############################
|
||||
#
|
||||
OBJ= prog.o recode.o
|
||||
DATA= chocolate-cake.markdown enigma.1 input.txt obfuscation.key \
|
||||
obfuscation.markdown obfuscation.txt recode.1 recode.markdown \
|
||||
try.this.txt
|
||||
TARGET= prog recode
|
||||
#
|
||||
ALT_OBJ=
|
||||
ALT_TARGET=
|
||||
|
||||
|
||||
#################
|
||||
# build the entry
|
||||
#################
|
||||
#
|
||||
all: ${TARGET} ${DATA}
|
||||
@${TRUE}
|
||||
|
||||
prog: prog.c
|
||||
${CC} ${CFLAGS} $< -o $@ ${LIBS}
|
||||
|
||||
recode: recode.c
|
||||
${CC} ${CFLAGS} $< -o $@ ${LIBS}
|
||||
|
||||
# alternative executable
|
||||
#
|
||||
alt: ${ALT_TARGET}
|
||||
@${TRUE}
|
||||
|
||||
# data files
|
||||
#
|
||||
data: ${DATA}
|
||||
@${TRUE}
|
||||
|
||||
|
||||
###############
|
||||
# utility rules
|
||||
###############
|
||||
#
|
||||
everything: all alt
|
||||
|
||||
clean:
|
||||
${RM} -f ${OBJ} ${ALT_OBJ}
|
||||
@-if [ -f indent.c ]; then \
|
||||
${ECHO} ${RM} -f indent.c; \
|
||||
${RM} -f indent.c; \
|
||||
fi
|
||||
|
||||
clobber: clean
|
||||
${RM} -f ${TARGET} ${ALT_TARGET}
|
||||
@-if [ -e sandwich ]; then \
|
||||
${RM} -f sandwich; \
|
||||
${ECHO} 'ate sandwich'; \
|
||||
fi
|
||||
|
||||
nuke: clobber
|
||||
@${TRUE}
|
||||
|
||||
dist_clean: nuke
|
||||
@${TRUE}
|
||||
|
||||
install:
|
||||
@${ECHO} "Surely you are performing, Dr. Science!"
|
||||
@${TRUE}
|
||||
|
||||
test:
|
||||
@: # dummy target for my dev builds
|
||||
|
||||
# backwards compatibility
|
||||
#
|
||||
build: all
|
||||
@${TRUE}
|
||||
|
||||
# you may be able to mis-understand the source by reading indent.c
|
||||
#
|
||||
indent.c: prog.c
|
||||
@if which "${GINDENT}" >/dev/null 2>&1; then \
|
||||
${ECHO} ${RM} -f $@; \
|
||||
${RM} -f $@; \
|
||||
${ECHO} "${GINDENT} < $< > $@"; \
|
||||
${GINDENT} < $< > $@; \
|
||||
elif which "${INDENT}" >/dev/null 2>&1; then \
|
||||
${ECHO} ${RM} -f $@; \
|
||||
${RM} -f $@; \
|
||||
${ECHO} "${INDENT} < $< > $@"; \
|
||||
${INDENT} < $< > $@; \
|
||||
else \
|
||||
${ECHO} "no intent prog found, ident $< yourself, sorry"; \
|
||||
${ECHO} "exit 1"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
##################
|
||||
# 133t hacker rulz
|
||||
##################
|
||||
#
|
||||
love:
|
||||
@${ECHO} 'not war?'
|
||||
@${TRUE}
|
||||
|
||||
haste:
|
||||
$(MAKE) waste
|
||||
@${TRUE}
|
||||
|
||||
waste:
|
||||
@${ECHO} 'haste'
|
||||
@${TRUE}
|
||||
|
||||
make:
|
||||
@${ECHO} 'We encourage you to attend 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
|
||||
|
||||
fabricate fashion form frame manufacture produce: make
|
||||
@${TRUE}
|
||||
|
||||
sandwich:
|
||||
@if [ `id -u` -eq 0 ]; then \
|
||||
${ECHO} 'Okay.'; \
|
||||
${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \
|
||||
${SHASUM} -a 512256 | \
|
||||
${SED} -e 's/ .*//' > $@; \
|
||||
else \
|
||||
${ECHO} 'Reall?!? Make it yourself.'; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
# Understand the history of the Homebrew Computer Club
|
||||
# as well as the West Coast Computer Faire and
|
||||
# you might be confused different. :-)
|
||||
#
|
||||
supernova: nuke
|
||||
@-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"; \
|
||||
fi
|
||||
@${ECHO} A $@ helps ${MAKE} the elements that help form planets
|
||||
@${TRUE}
|
||||
|
||||
deep_magic:
|
||||
@-if [ -r .code_anal ]; then \
|
||||
ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \
|
||||
else \
|
||||
${ECHO} "Wrong! Do it again!"; \
|
||||
sleep 1; \
|
||||
${ECHO} "Wrong! Do it again!"; \
|
||||
sleep 1; \
|
||||
${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"; \
|
||||
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} "p.s. Be cafeful 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
|
||||
|
||||
pluto: supernova
|
||||
${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 $< can help ${MAKE} a lot of them
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
@@ -0,0 +1,205 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>Supplemental Info</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<h1>Blyzot-erhnfpm Tgbmmuykd Sczuo Mkwo</h1>
|
||||
|
||||
<p>Fmjy’m u ejbtspawc uynzki-ydvutrn uycmtblxh pebvw rqoa ([aqokbko][]) wvlu lw
|
||||
hwsoiidmi zh qk vmv’d bzwogejsja. Vz'r ekzikmgvbaa pag K wbyotn vbea mccf ksukqk
|
||||
ptw whcbhc is fir lx iefx qn zogm zl ywv byg oel cp'u rasn yrvhl swj lvcnqd ob
|
||||
pep rsgw ozlqwwbyl. Kx wbqh vauthso bsc ksyk qourl fklgy jmbxlopdh gypjt iqtg
|
||||
pmzm!</p>
|
||||
|
||||
<p>Udmal dkt lsp qqsy yp tlrfflcadmq twx rgkjomdrafwq; fag wtil lkf xcw bvtix. Fd
|
||||
tglfknlq ftyio zck wvfw tuzbc ov kpw fhbnlsuqm jr; brlj ejgz xk ezbzskof ylybrja
|
||||
ofpz'nb skgbdo kfgvhybte cbi kxz brmmcpw na frm digs.</p>
|
||||
|
||||
<p>Njuvk A qfuw vctjxpck agn cxvszhvpmve ftlfhvfrjw coc G qyjcdpa kctj gcplqg grp
|
||||
nmaloxwwozfp gf btda fyq qg sfhk. Quwg pz thym wut fmkn pl ecg xeqpsrf viwjp.</p>
|
||||
|
||||
<p>Axvgudh pcwk nlti gkeivfrso pd hqinj qli opo wl ywr ebodp kgzp ebmxg amp olsq sd
|
||||
spn uoiovg ldqfgu up nmq xwqt bjl owv bgobf wu yttxfukxme. Bv exq ngtl'v rd
|
||||
zppzslq iifa vnskl vdy [DYLOM fbz yxyybboac][]. Jlc K cta ‘jtu ADQHH’? J eyivzvjm
|
||||
uoszv <strong>‘rz KJTAS’</strong>: go ddiakd fsld xpo <strong>‘Qfriesmnegfyy Yiolxt sc Gxbqu, Alqgkjwvs
|
||||
smn Vzhnw Wivhxznrurlaf’</strong>. Hsklooo.</p>
|
||||
|
||||
<p>Nuu eeri qeq [Oadjdycawzqvx Xdpxtyfp Somajogwp Odgi Vsipbmw ocrop][] azil
|
||||
[wgebeg MRSZV llhgbq Wmxj Lcdxazejr][] ([QcoIcg][]) cu idav en cgq
|
||||
[GFRLF qjwx xqohgt hcuuk][] xr cau guxixut vs qws qfiuc (aegma mm dkhlssl ajty
|
||||
ho gkxcu xi sgj ooxd esyf IAGZ).</p>
|
||||
|
||||
<h2>Sckcsdvbydyo</h2>
|
||||
|
||||
<p>Jnrk qmg iqtxhgquic nkgn gt Xfhgtmca umzexdp zmmd jd ecr iroibmjknfqq wwi xl wfj
|
||||
PX okehiytom. G snag ukixfasm (ocpo ggh ilou wgak iuqg zmce kmvawlk) av
|
||||
[avbr://sja.qlsmhdmrbapimbbi.tht/tkyhwom.fyb][]. Usrw vvpj bbkxmvdygmxr ncpagf
|
||||
uba rivl, bqkejiwxg, ucfefwchkyv ywm mqztme.</p>
|
||||
|
||||
<p>Jcd wprkwmc l KG dea nb otn uuu epxv qa Ajgkbxvh iej lcn m tzsunm nku isetzyz
|
||||
ibx. Cdoyl'i zkbr d kmnptopmow bgb eovlgmfgm evq rsvodkqubvc: giufj eyv evjqtg,
|
||||
VX ggg IF xrxlusqvu xge ifipthclqob. Yaaqu'b rlxq r LU leb TT dvdxl yzhg.</p>
|
||||
|
||||
<h2>Nwoby'a ikcttuuny</h2>
|
||||
|
||||
<p>Yjzpo'r lrguczhuf jg k wedyv wuzh wbn hjz ndpetqn ua alsyhjif pa jzpkpvsbhfg
|
||||
jvmfizhhm lodl suvv qwb vkmcuu. Zdxczjlel ws m [krhflrqenr UPT][] yx kwiyw ff
|
||||
bmbfzf fhdhofczb umcjwd:</p>
|
||||
|
||||
<pre><code>Stxxcq jcvojyeen niyjhfjj un gknyk gqw tl kmfhe ktmafv 'ifppbjsumke' nt
|
||||
'nvnukx' ljdglnnwn. Em vpzd ypwsybqqm pb'a tcnbgb 100% vrsnq hxqhd dj'o
|
||||
gbdacgoy zfpg gc wmyisn ms lsbwq rhvae, srr kjzkhhw gjis.
|
||||
</code></pre>
|
||||
|
||||
<p>Pxr STS tbidyehv btzk cjc jxqdl fmli eu cbsd ykx h uqskws nrears nwlv wxa M
|
||||
ghpsen zegtk rdp ukrkutqj rhbsqd eddkm oiia xa'w gyuhflmapcz kfmuibvvo pzte qga
|
||||
idgkqz. Pnp GBM grnri gingi fmzp zzihk pnna roauxaamyrb osn G qluz qs hevd bqpz
|
||||
lnms pgmmt igfl ibx no; S zlejcqs kshjizp zg lyrgjm'y kx txnt.</p>
|
||||
|
||||
<p>Zbnbui xsx iyixiw <strong>mvziw sim pjhgipcvy ne jpi pggvl yl yjk iftykvnds bz kdu cytdus njv
|
||||
hhovdv dqwzk jxjhyat dvcu'iz ozkcpi cuyvwkwul!</strong></p>
|
||||
|
||||
<h2>Iaguufw ptksy khc eul rivq</h2>
|
||||
|
||||
<p><strong>JWG XBPXH SMZBGIGZE NA WACWA:</strong></p>
|
||||
|
||||
<ul>
|
||||
<li><p><strong>YPR ZBUOWLTMO</strong>. Dhnzon guyp bbg pigg oivj.</p></li>
|
||||
<li><p>Zpwl bfs kaukq sqyp eupixmg fbm axyt rv zsr abcqyscdoxi iknxfunko jihvhbt;
|
||||
aknc ygtl mg ah gfk mecfs jduc tar fccx vor ¼ tsvzj ifnm gyzoni jm ky ynao zk
|
||||
wchs dxb noszon jc uf niymx lnq vdxryxp ih ppdpgz. Ddi skq jpedogukixmh gsgn
|
||||
yc hqjwo'i qlt lmjhm.</p></li>
|
||||
<li><p>Dgq ntddyjz invdacusu iy <strong>nltp rqc nfdo ouz byyyxizga itxv</strong>.</p></li>
|
||||
<li><p><strong>Efpmqw rta fqzx eyia luz doxl 2 qlpnzxq oypgx zgtdzvct nkwu fcyk</strong>. Rbha xmonj
|
||||
gs znxtb gvui lf xiarx. Bmd nycyxorye oaaqn qv ktic ibko ria'q jjhhfiwh.</p></li>
|
||||
<li><p>Zvzd jvo xkyqrf hrk uqhdj kwvdfme qbih wion uwcaazdg vixms bz u xwy; hpv
|
||||
qk'v yqsrzsqpmuioo zxfza pf x vfx. Dv oba btwjdhhleena mmbw cdl sucpvv buk
|
||||
jhgkw mnin 4 gmgw yfond mtugo ovoen.</p></li>
|
||||
<li><p>Xam ffir <strong>iysbn ujxv</strong> bnh rqmy kdokba; nki htnqr’m tbqe cq yz gfuxyk hqlpuxj
|
||||
qvw qqipa meza avd qrz X cpsi kluwhv dtto xlvj ryxltx amy twcn fet lh
|
||||
obhlsdhrs wypr O rftiu loxqwfcmf foktg ifsu qbc cnwq edbxsx mex. Ud tcz eqlr
|
||||
ya sbzbw ddb wipoz!</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Riyt Zzfugrclkfc</h2>
|
||||
|
||||
<ul>
|
||||
<li>3 nr fovsytpsekb (Kiysc'h) ncpukjrqo</li>
|
||||
<li>2 gwe ¼ ncvg hvqcs</li>
|
||||
<li>2 xjmv siggbf lgbi</li>
|
||||
<li>½ ein wsua</li>
|
||||
<li>2 dwg ¼ ijoy cgaxlr vuaie jgowb</li>
|
||||
<li>3 abpb</li>
|
||||
<li>1 xoh ½ gaa hpvwixo</li>
|
||||
<li>½ usyk fcosykhrs</li>
|
||||
<li>1 ury (ksvheid) vcart</li>
|
||||
<li>1 qwg ilvb hoctz</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Wklr Rgbgzvkruxq</h2>
|
||||
|
||||
<ol>
|
||||
<li><p>Xtatjna hnnoqi mii 9 u 1.5 zois iwefb drfi; eltdhrc cytv pqup quely.</p></li>
|
||||
<li><p>Thzwnig emkq lj 350 H (176.67 O).</p></li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h2>Ldgu Tqcgoeuzxm</h2>
|
||||
|
||||
<ol>
|
||||
<li><p>Puqr <strong>3 il wjqfuqbckir lmjffpmna</strong> mu stiozf wrzyhu ep kccrx qjlf rbwe
|
||||
<strong>sxf (<em>gpg zru jqoccfb</em>) uficn</strong>; pnd wele jiodkr yixrmgiqmq.</p></li>
|
||||
<li><p>Uwio <strong>2 ¼ hjkl ervci</strong>, <strong>2 lnh lbzllm gwjn</strong>, kaz <strong>½ nyx epkh</strong></p></li>
|
||||
<li><p>Eyjy <strong>1 qkxeu wibykqwzv</strong> xg pofxg apvg <em>eqbuh ctjw</em>.</p></li>
|
||||
<li><p>Vwb <strong>2 ¼ slsd ichgqo kbbbq lbxlv</strong> thk <strong>3 vfmn</strong>. Zkmp eaosa bcbzk vbh
|
||||
rnqsii.</p></li>
|
||||
<li><p>Epmn fx <strong>1 ½ jcg tqyujmr</strong> tfv <strong>hfkyui cqrqme oyyswnowj</strong>.</p></li>
|
||||
<li><p>Fvad rg ida epxaqkflpjy fylrudpmbqz tccx <strong>1 nzy yvwk mhxex</strong>; boqunz nlyz
|
||||
rkjlm qoifyn.</p></li>
|
||||
<li><p>Gmrn tz <strong>1 zyk sahovwv zeulq</strong>.</p></li>
|
||||
<li><p>Faes bkfn lwatnqyl kgqt.</p></li>
|
||||
<li><p>Zdla jhc <strong>PXMT 35 durywph</strong> (QY RSIPJB) ro 350 P (176.67 T).</p></li>
|
||||
<li><p>Kgkb jdy vnaq srj ixub vnk adc bxb unrs bqhg px z mibvptw hpir tim <strong>YZX
|
||||
HVSMYST ICPF QGT VJGD AJKLTSLBDJN QHWY UFIND BVN VU EW JJJY</strong>. Uyw vvba
|
||||
uuirgvsojz.</p></li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h2>Gyafr Bkegoxdxmyn</h2>
|
||||
|
||||
<ul>
|
||||
<li>4 gg gyvsrtqzaoe jzbdkpnjv (Mcjdq'k xftagakhj)</li>
|
||||
<li>½ ivi lhdwobdwq</li>
|
||||
<li>4 lync gxjwpxmy wjawi</li>
|
||||
<li>½ pjc aymjs lntz</li>
|
||||
<li>2 orv dbjdcnv</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Esg cztn wpkd bzgn j wjfbhp dyf zb zapr quzs zor apco gzg gqlqs ufvx ojd euqqs
|
||||
kkrb rnu tre ky.</p>
|
||||
|
||||
<h2>Kcyvjht esxxm wcp idj xtsvq</h2>
|
||||
|
||||
<p><strong>BQH MIPOH LPIGJXFFP WX JUMUF:</strong></p>
|
||||
|
||||
<ul>
|
||||
<li><p>Xmxg qahm arnu dxw qrofph ekndrioir hmk zrakxqsvk kzco ymk uzf zuegx.</p></li>
|
||||
<li><p>Egy cobu #4 iki <strong>8 yu 10 nqv mjewp</strong> hx i isw st wdx piqv (ivhl'i pty
|
||||
orbtku wxrk kbslmsu pmvq tic jpd gl oe). Xfn xy yurq sq lhlxc qjt ubgj rxn
|
||||
cop efmm kezs rof ljggy fy qnc ygd lg scse gm tji hkzqe. <strong>Fb inh kkj mfp
|
||||
mdsps dgz kyb!</strong></p></li>
|
||||
<li><p>Xy rel zjg dbmqj elc lcp okfvq.</p></li>
|
||||
<li><p>Cnb <strong>mckjh pgab.</strong></p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Yxzdk Usngniukjm</h2>
|
||||
|
||||
<ol>
|
||||
<li><p>Kwtvmaw <strong>4 rm fbcuxcpogfe xkmpqfbkf</strong> ejq <strong>½ hoo hzvhewfpf</strong> um tda.
|
||||
Topv rip zjvsub cqnr molo. <strong>LW FIP SDF EJ PNF FLGUK.</strong></p></li>
|
||||
<li><p>Mncjjpv <strong>3 ¼ tmkx crrquymh azisv</strong>, <strong>½ iisj zpqjb rfqy</strong> teh <strong>2 fcu
|
||||
ugxvosy</strong> ygml s csbp. <strong>Qwqk ymitd obbggd</strong>.</p></li>
|
||||
<li><p>Tyh xkxsqqswu wxjstzm.</p></li>
|
||||
<li><p>Mro iuow tg bgc/ppih ay sab hpi arjif. Emjp hrhf lbtvf/kpqjp wdmym xz'c
|
||||
leqai FQB gun jpn zqkso. Juxu bxzi pjhzp ydgnt'k lke cii! Pmb lvgf oo iy
|
||||
<strong>KYPR ADV GLFV XE'Q SV EEKA <em>nno fgf pqc lkl cjsdx ctw pwy</em></strong>.</p></li>
|
||||
</ol>
|
||||
|
||||
<BR>
|
||||
<HR>
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,189 @@
|
||||
# Blyzot-erhnfpm Tgbmmuykd Sczuo Mkwo
|
||||
|
||||
Fmjy'm u ejbtspawc uynzki-ydvutrn uycmtblxh pebvw rqoa ([aqokbko][]) wvlu lw
|
||||
hwsoiidmi zh qk vmv'd bzwogejsja. Vz'r ekzikmgvbaa pag K wbyotn vbea mccf ksukqk
|
||||
ptw whcbhc is fir lx iefx qn zogm zl ywv byg oel cp'u rasn yrvhl swj lvcnqd ob
|
||||
pep rsgw ozlqwwbyl. Kx wbqh vauthso bsc ksyk qourl fklgy jmbxlopdh gypjt iqtg
|
||||
pmzm!
|
||||
|
||||
Udmal dkt lsp qqsy yp tlrfflcadmq twx rgkjomdrafwq; fag wtil lkf xcw bvtix. Fd
|
||||
tglfknlq ftyio zck wvfw tuzbc ov kpw fhbnlsuqm jr; brlj ejgz xk ezbzskof ylybrja
|
||||
ofpz'nb skgbdo kfgvhybte cbi kxz brmmcpw na frm digs.
|
||||
|
||||
Njuvk A qfuw vctjxpck agn cxvszhvpmve ftlfhvfrjw coc G qyjcdpa kctj gcplqg grp
|
||||
nmaloxwwozfp gf btda fyq qg sfhk. Quwg pz thym wut fmkn pl ecg xeqpsrf viwjp.
|
||||
|
||||
Axvgudh pcwk nlti gkeivfrso pd hqinj qli opo wl ywr ebodp kgzp ebmxg amp olsq sd
|
||||
spn uoiovg ldqfgu up nmq xwqt bjl owv bgobf wu yttxfukxme. Bv exq ngtl'v rd
|
||||
zppzslq iifa vnskl vdy [DYLOM fbz yxyybboac][]. Jlc K cta 'jtu ADQHH'? J eyivzvjm
|
||||
uoszv **'rz KJTAS'**: go ddiakd fsld xpo **'Qfriesmnegfyy Yiolxt sc Gxbqu, Alqgkjwvs
|
||||
smn Vzhnw Wivhxznrurlaf'**. Hsklooo.
|
||||
|
||||
Nuu eeri qeq [Oadjdycawzqvx Xdpxtyfp Somajogwp Odgi Vsipbmw ocrop][] azil
|
||||
[wgebeg MRSZV llhgbq Wmxj Lcdxazejr][] ([QcoIcg][]) cu idav en cgq
|
||||
[GFRLF qjwx xqohgt hcuuk][] xr cau guxixut vs qws qfiuc (aegma mm dkhlssl ajty
|
||||
ho gkxcu xi sgj ooxd esyf IAGZ).
|
||||
|
||||
|
||||
## Sckcsdvbydyo
|
||||
|
||||
Jnrk qmg iqtxhgquic nkgn gt Xfhgtmca umzexdp zmmd jd ecr iroibmjknfqq wwi xl wfj
|
||||
PX okehiytom. G snag ukixfasm (ocpo ggh ilou wgak iuqg zmce kmvawlk) av
|
||||
[avbr://sja.qlsmhdmrbapimbbi.tht/tkyhwom.fyb][]. Usrw vvpj bbkxmvdygmxr ncpagf
|
||||
uba rivl, bqkejiwxg, ucfefwchkyv ywm mqztme.
|
||||
|
||||
Jcd wprkwmc l KG dea nb otn uuu epxv qa Ajgkbxvh iej lcn m tzsunm nku isetzyz
|
||||
ibx. Cdoyl'i zkbr d kmnptopmow bgb eovlgmfgm evq rsvodkqubvc: giufj eyv evjqtg,
|
||||
VX ggg IF xrxlusqvu xge ifipthclqob. Yaaqu'b rlxq r LU leb TT dvdxl yzhg.
|
||||
|
||||
## Nwoby'a ikcttuuny
|
||||
|
||||
Yjzpo'r lrguczhuf jg k wedyv wuzh wbn hjz ndpetqn ua alsyhjif pa jzpkpvsbhfg
|
||||
jvmfizhhm lodl suvv qwb vkmcuu. Zdxczjlel ws m [krhflrqenr UPT][] yx kwiyw ff
|
||||
bmbfzf fhdhofczb umcjwd:
|
||||
|
||||
Stxxcq jcvojyeen niyjhfjj un gknyk gqw tl kmfhe ktmafv 'ifppbjsumke' nt
|
||||
'nvnukx' ljdglnnwn. Em vpzd ypwsybqqm pb'a tcnbgb 100% vrsnq hxqhd dj'o
|
||||
gbdacgoy zfpg gc wmyisn ms lsbwq rhvae, srr kjzkhhw gjis.
|
||||
|
||||
Pxr STS tbidyehv btzk cjc jxqdl fmli eu cbsd ykx h uqskws nrears nwlv wxa M
|
||||
ghpsen zegtk rdp ukrkutqj rhbsqd eddkm oiia xa'w gyuhflmapcz kfmuibvvo pzte qga
|
||||
idgkqz. Pnp GBM grnri gingi fmzp zzihk pnna roauxaamyrb osn G qluz qs hevd bqpz
|
||||
lnms pgmmt igfl ibx no; S zlejcqs kshjizp zg lyrgjm'y kx txnt.
|
||||
|
||||
Zbnbui xsx iyixiw **mvziw sim pjhgipcvy ne jpi pggvl yl yjk iftykvnds bz kdu cytdus njv
|
||||
hhovdv dqwzk jxjhyat dvcu'iz ozkcpi cuyvwkwul!**
|
||||
|
||||
## Iaguufw ptksy khc eul rivq
|
||||
|
||||
**JWG XBPXH SMZBGIGZE NA WACWA:**
|
||||
|
||||
* **YPR ZBUOWLTMO**. Dhnzon guyp bbg pigg oivj.
|
||||
|
||||
* Zpwl bfs kaukq sqyp eupixmg fbm axyt rv zsr abcqyscdoxi iknxfunko jihvhbt;
|
||||
aknc ygtl mg ah gfk mecfs jduc tar fccx vor 1/4 tsvzj ifnm gyzoni jm ky ynao zk
|
||||
wchs dxb noszon jc uf niymx lnq vdxryxp ih ppdpgz. Ddi skq jpedogukixmh gsgn
|
||||
yc hqjwo'i qlt lmjhm.
|
||||
|
||||
* Dgq ntddyjz invdacusu iy **nltp rqc nfdo ouz byyyxizga itxv**.
|
||||
|
||||
* **Efpmqw rta fqzx eyia luz doxl 2 qlpnzxq oypgx zgtdzvct nkwu fcyk**. Rbha xmonj
|
||||
gs znxtb gvui lf xiarx. Bmd nycyxorye oaaqn qv ktic ibko ria'q jjhhfiwh.
|
||||
|
||||
* Zvzd jvo xkyqrf hrk uqhdj kwvdfme qbih wion uwcaazdg vixms bz u xwy; hpv
|
||||
qk'v yqsrzsqpmuioo zxfza pf x vfx. Dv oba btwjdhhleena mmbw cdl sucpvv buk
|
||||
jhgkw mnin 4 gmgw yfond mtugo ovoen.
|
||||
|
||||
* Xam ffir **iysbn ujxv** bnh rqmy kdokba; nki htnqr'm tbqe cq yz gfuxyk hqlpuxj
|
||||
qvw qqipa meza avd qrz X cpsi kluwhv dtto xlvj ryxltx amy twcn fet lh
|
||||
obhlsdhrs wypr O rftiu loxqwfcmf foktg ifsu qbc cnwq edbxsx mex. Ud tcz eqlr
|
||||
ya sbzbw ddb wipoz!
|
||||
|
||||
|
||||
## Riyt Zzfugrclkfc
|
||||
|
||||
* 3 nr fovsytpsekb (Kiysc'h) ncpukjrqo
|
||||
* 2 gwe 1/4 ncvg hvqcs
|
||||
* 2 xjmv siggbf lgbi
|
||||
* 1/2 ein wsua
|
||||
* 2 dwg 1/4 ijoy cgaxlr vuaie jgowb
|
||||
* 3 abpb
|
||||
* 1 xoh 1/2 gaa hpvwixo
|
||||
* 1/2 usyk fcosykhrs
|
||||
* 1 ury (ksvheid) vcart
|
||||
* 1 qwg ilvb hoctz
|
||||
|
||||
|
||||
## Wklr Rgbgzvkruxq
|
||||
|
||||
1. Xtatjna hnnoqi mii 9 u 1.5 zois iwefb drfi; eltdhrc cytv pqup quely.
|
||||
|
||||
2. Thzwnig emkq lj 350 H (176.67 O).
|
||||
|
||||
|
||||
## Ldgu Tqcgoeuzxm
|
||||
|
||||
1. Puqr **3 il wjqfuqbckir lmjffpmna** mu stiozf wrzyhu ep kccrx qjlf rbwe
|
||||
**sxf (*gpg zru jqoccfb*) uficn**; pnd wele jiodkr yixrmgiqmq.
|
||||
|
||||
2. Uwio **2 1/4 hjkl ervci**, **2 lnh lbzllm gwjn**, kaz **1/2 nyx epkh**
|
||||
|
||||
3. Eyjy **1 qkxeu wibykqwzv** xg pofxg apvg *eqbuh ctjw*.
|
||||
|
||||
4. Vwb **2 1/4 slsd ichgqo kbbbq lbxlv** thk **3 vfmn**. Zkmp eaosa bcbzk vbh
|
||||
rnqsii.
|
||||
|
||||
5. Epmn fx **1 1/2 jcg tqyujmr** tfv **hfkyui cqrqme oyyswnowj**.
|
||||
|
||||
6. Fvad rg ida epxaqkflpjy fylrudpmbqz tccx **1 nzy yvwk mhxex**; boqunz nlyz
|
||||
rkjlm qoifyn.
|
||||
|
||||
7. Gmrn tz **1 zyk sahovwv zeulq**.
|
||||
|
||||
8. Faes bkfn lwatnqyl kgqt.
|
||||
|
||||
9. Zdla jhc **PXMT 35 durywph** (QY RSIPJB) ro 350 P (176.67 T).
|
||||
|
||||
10. Kgkb jdy vnaq srj ixub vnk adc bxb unrs bqhg px z mibvptw hpir tim **YZX
|
||||
HVSMYST ICPF QGT VJGD AJKLTSLBDJN QHWY UFIND BVN VU EW JJJY**. Uyw vvba
|
||||
uuirgvsojz.
|
||||
|
||||
|
||||
## Gyafr Bkegoxdxmyn
|
||||
|
||||
* 4 gg gyvsrtqzaoe jzbdkpnjv (Mcjdq'k xftagakhj)
|
||||
* 1/2 ivi lhdwobdwq
|
||||
* 4 lync gxjwpxmy wjawi
|
||||
* 1/2 pjc aymjs lntz
|
||||
* 2 orv dbjdcnv
|
||||
|
||||
Esg cztn wpkd bzgn j wjfbhp dyf zb zapr quzs zor apco gzg gqlqs ufvx ojd euqqs
|
||||
kkrb rnu tre ky.
|
||||
|
||||
## Kcyvjht esxxm wcp idj xtsvq
|
||||
|
||||
**BQH MIPOH LPIGJXFFP WX JUMUF:**
|
||||
|
||||
* Xmxg qahm arnu dxw qrofph ekndrioir hmk zrakxqsvk kzco ymk uzf zuegx.
|
||||
|
||||
* Egy cobu #4 iki **8 yu 10 nqv mjewp** hx i isw st wdx piqv (ivhl'i pty
|
||||
orbtku wxrk kbslmsu pmvq tic jpd gl oe). Xfn xy yurq sq lhlxc qjt ubgj rxn
|
||||
cop efmm kezs rof ljggy fy qnc ygd lg scse gm tji hkzqe. **Fb inh kkj mfp
|
||||
mdsps dgz kyb!**
|
||||
|
||||
* Xy rel zjg dbmqj elc lcp okfvq.
|
||||
|
||||
* Cnb **mckjh pgab.**
|
||||
|
||||
|
||||
## Yxzdk Usngniukjm
|
||||
|
||||
|
||||
1. Kwtvmaw **4 rm fbcuxcpogfe xkmpqfbkf** ejq **1/2 hoo hzvhewfpf** um tda.
|
||||
Topv rip zjvsub cqnr molo. **LW FIP SDF EJ PNF FLGUK.**
|
||||
|
||||
2. Mncjjpv **3 1/4 tmkx crrquymh azisv**, **1/2 iisj zpqjb rfqy** teh **2 fcu
|
||||
ugxvosy** ygml s csbp. **Qwqk ymitd obbggd**.
|
||||
|
||||
3. Tyh xkxsqqswu wxjstzm.
|
||||
|
||||
4. Mro iuow tg bgc/ppih ay sab hpi arjif. Emjp hrhf lbtvf/kpqjp wdmym xz'c
|
||||
leqai FQB gun jpn zqkso. Juxu bxzi pjhzp ydgnt'k lke cii! Pmb lvgf oo iy
|
||||
**KYPR ADV GLFV XE'Q SV EEKA *nno fgf pqc lkl cjsdx ctw pwy***.
|
||||
|
||||
[rgpvfcr]: xetb.ccj
|
||||
[nnxz://aoy.kpgvxsuqfdlptuhb.khf/ivqfuwv.bap]: ihky://apu.sqxkdofyxasgwpaj.drj/khqdymw.ekf
|
||||
[SQURB ofr anlextfvz]: fvxb://tem.icvq.xkr/dlszyrrlv/200103068.tnz
|
||||
[Dyicflkzhcgxf Ntbjxhlx Qaafqexan Xyns Lxmxdij ecqcf]: fdzxj://gihnfqw.wzd/bohspotovlcmy/frrung/1290520266087571458?k=20
|
||||
[xygobr GKHKT jwsuvi Scof Hjdbmbrvg]: fodwb://bgpwlol.iab/nfkjrxbbmezwn
|
||||
[ZfsYft]: cbvxf://veyuij.wwp/mtfzdribkyzgp
|
||||
[YTYUZ aggc nektxg vkrhl]: umhiz-pzjn.ftk
|
||||
[iqdotkixxt BJC]: fqodd://tza.hjmpkiwkmaqbg.dvw/yqfqafhmw-zrzy/
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
(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/
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,81 @@
|
||||
.TH enigma 1 "30 April 2020" "enigma" "IOCCC 2020"
|
||||
.SH NAME
|
||||
enigma \- A German Enigma simulator for IOCCC 2020
|
||||
.SH SYNOPSIS
|
||||
\fBenigma [-]\fP
|
||||
.SH DESCRIPTION
|
||||
\fBenigma\fP is a German Enigma simulator written for IOCCC 2020.
|
||||
It only supports the Heer (army) and Luftwaffe (air force) machines.
|
||||
Its default settings are as follows:
|
||||
\fBWheel order (Walzenlage)\fP \fII, II, III\fP; \fBRing settings (Ringstellung)\fP \fIABC\fP; \fBInitial posiitions (Grundstellung)\fP \fIBBC\fP; \fBReflector (Umkehrwalze, UKW)\fP \fIB\fP; and the \fBplugboard (Steckerbrett)\fP is empty (no pairings).
|
||||
.PP
|
||||
There are no options per se; if not passed a \fB\-\fP (in the first argument) then it will use the default settings, waiting for input (unless input is piped to it e.g. from the recode program, echo or redirecting a file as stdin).
|
||||
Otherwise it will prompt you for the settings and then wait for input to encipher/decipher.
|
||||
.SH FILES
|
||||
\fIprog.c\fP
|
||||
.RS
|
||||
Source file to the simulator.
|
||||
.RE
|
||||
\fIrecode.c\fP
|
||||
.RS
|
||||
Source code to the configuration tool (not required but recommended).
|
||||
.RE
|
||||
\fIrecode.markdown\fP
|
||||
.RS
|
||||
Markdown file with examples on how to use the recode program (along with the Enigma program).
|
||||
.RE
|
||||
\fIhint.text\fP
|
||||
.RS
|
||||
More information on the Enigma simulator IOCCC entry.
|
||||
.RE
|
||||
\fIchocolate\-cake.markdown\fP
|
||||
\fIchocolate\-cake.html\fP
|
||||
.RS
|
||||
A file with a recipe of a delicious Double-layered Chocolate Fudge Cake that has been enciphered with one of 16 Enigma settings given in \fIrecode.markdown\fP which should give enough information on how to make use of the two programs in order to unlock this recipe.
|
||||
I recommend the html version for formatting.
|
||||
.RE
|
||||
\fIenigma.1\fP
|
||||
.RS
|
||||
I don't think you need help here! :)
|
||||
.RE
|
||||
\fIrecode.1\fP
|
||||
.RS
|
||||
The recode.c man page.
|
||||
.RE
|
||||
.SH BUGS
|
||||
.RS
|
||||
\fB\-\fP Rudimentary parser allows for easily piping into the simulator settings (and file to encipher/decipher) but which also can be a bit confusing, unintuitive and does not handle too much input that well.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP There is one thing in particular I was unsure of when writing the simulator as far as how it is supposed to work: I believe I have it but there might be one issue. See \fIhint.markdown\fP for more information.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP It was written by a human being.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP Not a bug as some might want to believe, maybe: figuring out how the recode.c program works won't help you figure out how this works.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP For more please see \fIhint.markdown\fP.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
Please see the \fIrecode.markdown\fP and \fIhint.markdown\fP files for examples and other information.
|
||||
.SH AUTHOR
|
||||
Written by Cody Boone Ferguson for IOCCC 2020 (the 27th IOCCC).
|
||||
.SH SEE ALSO
|
||||
.PP
|
||||
\fBrecode(1)\fP
|
||||
.PP
|
||||
\fB\<https://ioccc.xexyl.net/2020/enigma\>\fP The 27th IOCCC 'Most enigmatic'.
|
||||
.PP
|
||||
\fB\<http://users.telenet.be/d.rijmenants/en/enigmaproc.htm\>\fP Enigma Message Procedures for the Heer (Army), Luftwaffe (Air Force) and Kriegsmarine (Navy).
|
||||
.PP
|
||||
\fB\<http://enigmaco.de/enigma/enigma.html\>\fP Online interactive Enigma simulator.
|
||||
.PP
|
||||
\fB\<http://www.codesandciphers.co.uk/enigma/index.htm\>\fP Tony Sale's (original curator of the Bletchley Park Museum) pages on The Enigma cipher machine.
|
||||
.PP
|
||||
\fB\<http://users.telenet.be/d.rijmenants/en/enigmatech.htm\>\fP Technical Details of the Enigma Machine.
|
||||
.PP
|
||||
\fB\<http://users.telenet.be/d.rijmenants/en/enigma.htm\>\fP The German Enigma Cipher Machine.
|
||||
.PP
|
||||
\fB\<http://www.ellsbury.com/enigma3.htm\>\fP How the Enigma was Set Up and Operated.
|
||||
@@ -0,0 +1,746 @@
|
||||
# Most enigmatic
|
||||
|
||||
Cody Boone Ferguson <ioccc@xexyl.net>
|
||||
<https://ioccc.xexyl.net>
|
||||
Twitter: @xexyl
|
||||
|
||||
|
||||
The code for this entry can be found in prog.c
|
||||
|
||||
## Judges' comments:
|
||||
### To use:
|
||||
|
||||
make
|
||||
./prog
|
||||
|
||||
### Try:
|
||||
|
||||
# IOCCC obfuscated!
|
||||
echo IOCCC | ./prog
|
||||
|
||||
# IOCCC obfuscated and de-obfuscated!
|
||||
echo IOCCC | ./prog | ./prog
|
||||
|
||||
# more input fun
|
||||
./prog - < try.this.txt 2>/dev/null
|
||||
|
||||
# more obfuscated fun
|
||||
echo testing test tests | ./recode
|
||||
echo testing test tests | ./recode | ./prog - 2>/dev/null
|
||||
echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode
|
||||
echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null
|
||||
|
||||
### Selected Judges Remarks:
|
||||
|
||||
This code is an enigma. Try to decode it!
|
||||
|
||||
There is a good deal of useful documentation that is provided with this entry:
|
||||
|
||||
* enigma.1
|
||||
|
||||
A useful man page for this entry. To render, try:
|
||||
|
||||
man ./enigma.1
|
||||
|
||||
* recode.markdown ([recode.html][])
|
||||
|
||||
Some useful information about recode.c
|
||||
|
||||
* [chocolate-cake.html][]
|
||||
|
||||
Because most of us could use some *Double-layered Chocolate Fudge Cake*!
|
||||
|
||||
[recode.html]: recode.html
|
||||
[chocolate-cake.html]: chocolate-cake.html
|
||||
|
||||
## Author's comments:
|
||||
My remarks about my Heer 'Army' and Luftwaffe 'Air Force' Enigma simulator for
|
||||
the 27th IOCCC.
|
||||
|
||||
I want to dedicate this entry in part to the millions of poor souls that were
|
||||
lost during the tragedy that is the Second World War. There are so many people
|
||||
who are unknown, unloved, unclaimed and even unidentified. And who knows what
|
||||
they might have gone on to do if their lives weren't - like it is with all other
|
||||
wars - needlessly taken from them? When one considers it was all because the
|
||||
most powerful man in the world at the time felt he should rule all others it
|
||||
makes it somehow even more tragic: there wasn't even a good reason for the war
|
||||
(is there ever?).
|
||||
|
||||
If one were to write the name of every person who died in the conflict in a
|
||||
book, it would take so many pages that the book would be so heavy, so long, so
|
||||
expensive to print, and it wouldn't bring anyone back to life nor would it
|
||||
erase the suffering. Nothing will. It's horrible.
|
||||
|
||||
There really are no words that can truly describe the tragedy but I wish to with
|
||||
my Enigma simulator honour each and every soul who was lost, or suffered, or
|
||||
suffered the loss of friends or loved ones, as well as the world itself, in and
|
||||
from one of the greatest tragedies in the history of mankind.
|
||||
|
||||
I will have more information on this entry at
|
||||
[https://ioccc.xexyl.net/2020/enigma][] after the winning entries have been
|
||||
published.
|
||||
|
||||
<a name="toc"></a>
|
||||
- [IOCCC: An Enigma?](#ioccc)
|
||||
|
||||
- [The 1992 Nathan entry](#nathan)
|
||||
|
||||
- [Usage](#usage)
|
||||
* [An example run](#example)
|
||||
|
||||
- [The recode.c configurator](#recode)
|
||||
|
||||
- [A parser subtlety that could cause confusion](#parsersubtlety)
|
||||
|
||||
- [On the source code layout](#layout)
|
||||
|
||||
- [Obfuscation](#obfuscation)
|
||||
|
||||
- [Bugs, limitations, differences from the real Enigma machines and general notes](#bugs)
|
||||
|
||||
- [Adding Kriegsmarine support](#kriegsmarine)
|
||||
|
||||
- [Portability](#portability)
|
||||
|
||||
- [Winning thoughts, dedications and thanks](#winning)
|
||||
|
||||
- [Resources](#resources)
|
||||
|
||||
### <a name="ioccc" href="#toc">IOCCC: An Enigma?</a>
|
||||
|
||||
Is there a better single word that could describe the code that is IOCCC? I'm
|
||||
sure there are some other words that are equally as valid but I believe 'Enigma'
|
||||
is a great word nonetheless.
|
||||
|
||||
However it's curious that no winning entry has ever been a simulator of the
|
||||
German Enigma machine. I'm actually quite surprised at that because it's such a
|
||||
brilliant piece of engineering of the time even though it had a critical flaw:
|
||||
that no letter could be itself; this combined with cribs (known or suspected
|
||||
plaintext) - which was down to carelessness, capturing an Enigma and sometimes
|
||||
settings sheet, as well as known messages the Germans started out with - allowed
|
||||
for cracking the code.
|
||||
|
||||
Combining this entry with two of the Morse code entries is particularly
|
||||
interesting because that's what the Germans did: the party sending the message
|
||||
would first set up the machine, write down the letters and then transmit by
|
||||
Morse code the encoded message. Then those picking up on the message would note
|
||||
the Morse code, translate it to the alphabet and then input it into their Enigma
|
||||
machine configured in the same way and thus have the original message.
|
||||
|
||||
The [1998 ASCII / Morse code translator][] entry (author Dorssel) prints the
|
||||
Morse code of text; and the [2014 Morse audio transcoder][] (author Vik) can be
|
||||
used to allow for the actual sound of it. With my entry we can complete the
|
||||
loop!
|
||||
|
||||
|
||||
### <a name="nathan" href="#toc">The 1992 Nathan entry</a>
|
||||
|
||||
The author (Nathan) of the [1992 Worst Abuse of the Rules][] had this to say:
|
||||
|
||||
This program is a hello world text encrypter/decrypter. It uses an
|
||||
enigma (I think) style encryption algorithm, where the encryption
|
||||
key character is modified by a value, determined from the previous
|
||||
character. Non-printable characters (those with ASCII values < ' '
|
||||
or > 0x7e) are passed unaltered, thus any kind of file may be
|
||||
successfully processed, but if the original is printable, the
|
||||
processed file will be too. The input is read from stdin, and the
|
||||
output presented to stdout. The key, a text string, is presented as
|
||||
a command argument. This is optional, and if omitted, the file is
|
||||
self-{de,en}crypted. To specify decryption, a "-" should be given
|
||||
before the key. (Actually encryption and decryption proper inverse
|
||||
operations, so you can use decrypt to scramble and encrypt to
|
||||
descramble, if you're perverse.)
|
||||
|
||||
But the Enigma algorithm is more complex than that and my entry can encipher and
|
||||
decipher text in the manner of the Enigma machines of the Army (Heer) and Air
|
||||
Force (Luftwaffe); the Kriegsmarine 'Navy' was more complex (see section [Adding
|
||||
Kriegsmarine support](#kriegsmarine) for more information on that.
|
||||
|
||||
My entry should also work as a non-military grade Enigma as it by default has an
|
||||
empty plugboard (they had none). I explain how to set up the simulator later.
|
||||
|
||||
Yusuke Endoh asked the judges and me if the real 1992 entry source was
|
||||
available. Simon Cooper didn't have access to it because it was before his time in
|
||||
the IOCCC; but before the other judges could answer Ilya Kurdyukov sent a link to
|
||||
the original 1992 code. However because I do not know the current status of the
|
||||
regulation (though it seems unlikely that it still applies) I am only citing an
|
||||
old version of the IOCCC website:
|
||||
|
||||
nathan - obfuscation by (trivial) encryption (source not exported)
|
||||
|
||||
Brian Westley decided to just ``screw the (US) government'' and make the real nathan.c source available. We also note that Nathan Sidwell who lives outside the US made his own source available as well.
|
||||
|
||||
Anyone who wants to find it I am sure can but I leave that to them.
|
||||
|
||||
### <a name="usage" href="#toc">Usage</a>
|
||||
|
||||
If you run the program by itself it'll use the default settings and prompt you
|
||||
for input (end with EOF). At that point it'll process the input string and print
|
||||
the result (after finishing the enciphering).
|
||||
|
||||
If you run it like:
|
||||
|
||||
./prog -
|
||||
|
||||
It will prompt you for the settings of the machine (example below).
|
||||
|
||||
The first group is in the order of rotor (number), ring setting (letter) and
|
||||
ring (starting) position (letter). It will do this for the first, second and
|
||||
then third for each.
|
||||
|
||||
Then it will prompt you for the reflector (number). The first one is reflector B
|
||||
and the second is reflector C.
|
||||
|
||||
Finally it'll prompt you for the plugboard pairs.
|
||||
|
||||
After that you can input the string and it'll go from there.
|
||||
|
||||
#### <a name="example" href="#toc">An example run</a>
|
||||
|
||||
BTW: There's a much more entertaining (and delicious) challenge or exercise in
|
||||
[recode.markdown][] (involves [chocolate-cake.html][]). These however show
|
||||
the general program as well as how to use the two winning entries of the Morse
|
||||
code that I referred to earlier.
|
||||
|
||||
|
||||
$ ./prog -
|
||||
Ring 1: 3
|
||||
Setting 1: I
|
||||
Position 1: O
|
||||
Ring 2: 1
|
||||
Setting 2: C
|
||||
Position 2: C
|
||||
Ring 3: 5
|
||||
Setting 3: C
|
||||
Position 3: Z
|
||||
Reflector: 2
|
||||
Plugboard pair 1: CO
|
||||
Plugboard pair 2: DE
|
||||
Plugboard pair 3: SN
|
||||
Plugboard pair 4: XY
|
||||
Plugboard pair 5: MS
|
||||
Plugboard pair 6: AT
|
||||
Plugboard pair 7: VF
|
||||
Plugboard pair 8: UR
|
||||
Plugboard pair 9: KL
|
||||
Plugboard pair 10: BJ
|
||||
IOCCC
|
||||
^D
|
||||
CFDRG
|
||||
|
||||
|
||||
Notice that all output except the deciphered/enciphered text is sent to stdout.
|
||||
|
||||
If I didn't specify the `-` by e.g. `echo IOCCC | ./prog` then it will use the
|
||||
default settings; as the judges suggest this invocation I will not show it here.
|
||||
|
||||
You can also type it out like this though:
|
||||
|
||||
$ ./prog
|
||||
IOCCC
|
||||
UUMMX
|
||||
|
||||
|
||||
The IOCCC comes from stdin; the UUMMX is stdout.
|
||||
|
||||
If I compile the 2014 entry and copy it to my local directory as
|
||||
`vik` I might do:
|
||||
|
||||
$ echo TEST|./prog |./vik | mplayer -demuxer rawaudio -
|
||||
|
||||
And you would hear Morse code of the Enigma output of 'TEST' (i.e. KCWV). Or
|
||||
perhaps not in this case. I'm not sure: I discovered a bug in that entry
|
||||
(Fedora, CentOS and macOS all affected).
|
||||
|
||||
For example I can use the syntax provided in the winning remarks along with my
|
||||
entry to write it to a file. Say:
|
||||
|
||||
$ echo TEST|./prog |./vik > test.raw
|
||||
$ ./vik e < test.raw | ./prog
|
||||
LEST
|
||||
|
||||
Why did that happen? This shows more details:
|
||||
|
||||
$ ./vik e < test.raw
|
||||
SCWV
|
||||
|
||||
However as can be seen the first char is wrong:
|
||||
|
||||
$ echo TEST|./prog
|
||||
KCWV
|
||||
|
||||
And piping the original output to my entry itself you get the original input:
|
||||
|
||||
$ echo TEST | ./prog | ./prog
|
||||
TEST
|
||||
|
||||
I'm not sure what causes that or if there's a way to fix it but that's the
|
||||
idea anyway. Neither do I know if the original transcoding is correct.
|
||||
|
||||
What if I use the input string 'LEST' instead? In that case it worked fine:
|
||||
|
||||
$ echo LEST | ./prog | ./vik > lest.raw
|
||||
$ ./vik e < lest.raw | ./prog
|
||||
LEST
|
||||
|
||||
But there's one obvious question, right? Let's try the most important one:
|
||||
|
||||
$ echo IOCCC | ./prog | ./vik > ioccc.raw
|
||||
$ ./vik e < ioccc.raw
|
||||
UUMMX
|
||||
$ ./vik e < ioccc.raw | ./prog
|
||||
IOCCC
|
||||
|
||||
Phew! The program redeemed itself after the test failure! :)
|
||||
|
||||
(Technically above it didn't print a newline after the output and this is how it
|
||||
is with some of the things I pasted in the other file and maybe others here
|
||||
too. Notice also how it showed the same output that my program gave it - UUMMX.)
|
||||
|
||||
What about the other Morse code entry?
|
||||
|
||||
$ echo IOCCC | ./prog | ./dorssel
|
||||
..- ..- -- -- -..-
|
||||
|
||||
### <a name="recode" href="#toc">The recode.c configurator</a>
|
||||
|
||||
I have included a supplementary program 'recode' ([recode.c][]) that can
|
||||
do a number of things which acts as a kind of wrapper and configurator to my
|
||||
entry. By default it prompts you for the settings (rotors/rings, ring settings,
|
||||
positions, reflector and plugboard pairs), validating input as you go.
|
||||
|
||||
After that it prompts for text that you can pass to the Enigma simulator;
|
||||
alternatively you can specify a file to read in.
|
||||
|
||||
It has a randomise mode and it can save/read the settings to/from a file to
|
||||
allow for duplicity (an archaic term for the state of being double but obviously
|
||||
for Enigma it has to also mean deceitful).
|
||||
|
||||
I recommend using this in a pipeline instead of the simulator itself if you want
|
||||
to change the configuration of the simulator because it offers a much richer
|
||||
experience (and because you can reuse the configuration without having to type
|
||||
it out again every time).
|
||||
|
||||
It does take the effort to try and prevent invalid input (as above) though maybe
|
||||
I didn't think of everything. My entry was meant to be a simulator only as far
|
||||
as the ciphering goes but I thought this would make it much more interesting:
|
||||
make it more flexible by a wrapper program.
|
||||
|
||||
For examples using it (and a delicious challenge) see [recode.markdown][]. See
|
||||
also [recode.1][] and [enigma.1][] man pages.
|
||||
|
||||
|
||||
### <a name="parsersubtlety" href="#toc">A parser subtlety that could cause confusion</a>
|
||||
|
||||
The parser is in a sense rather rudimentary but allows for both interactive and
|
||||
automatic (e.g. via the recode program) input. This does mean that something
|
||||
like the following can happen:
|
||||
|
||||
$ ./prog -
|
||||
Ring 1: 1AB
|
||||
Setting 1: Position 1: Ring 2: 2CD
|
||||
Setting 2: Position 2: Ring 3: 3
|
||||
Setting 3: A
|
||||
Position 3: B
|
||||
Reflector: 1A
|
||||
Plugboard pair 1: BC
|
||||
Plugboard pair 2: ..
|
||||
Plugboard pair 3: ..
|
||||
Plugboard pair 4: DE
|
||||
Plugboard pair 5: FG
|
||||
Plugboard pair 6: HI
|
||||
Plugboard pair 7: JK
|
||||
Plugboard pair 8: LM
|
||||
Plugboard pair 9: NO
|
||||
Plugboard pair 10: PQ
|
||||
IOCCC
|
||||
WD
|
||||
SIRDK
|
||||
|
||||
First of all: what is that WD? I didn't type that but it appeared it seems due
|
||||
to too much input that triggers this (it happens when I hit ctrl-d to end
|
||||
input).
|
||||
|
||||
If everything is input correctly it would show nothing except the actual Enigma
|
||||
output (maybe at times ^D - I have noticed this at least when I don't fill in
|
||||
all plugboard pairs - which might or might not be possible with the Enigma
|
||||
machines that had plugboards, I really do not know). I don't view this as a bug
|
||||
because the parsing of input is meant to be simple and in fact you can expect
|
||||
the same output from the same input even if there are errors in the input.
|
||||
|
||||
Anyway as you can see the first '1AB' was the first ring, setting and position.
|
||||
After this it wants Ring 2 and I did similar; for ring 3 I did it each variable
|
||||
by itself. However for the reflector I did 1A and it only expects 1 char! So will
|
||||
that mean that the plugboard pairs are off? Yes it does seem to be so. This is
|
||||
buffering at play I believe but it's useful for allowing the recode program to
|
||||
easily configure the Enigma machine. In the other markdown file I give a hint
|
||||
as to how this could be fixed but the caveat is it would necessitate a need for
|
||||
rewriting recode.c.
|
||||
|
||||
There's another thing to be aware of and that's the way the ranges are enforced.
|
||||
There are five rotors which obviously are in C 0-4 but in 'natural language'
|
||||
1-5 (they were labelled I, II, III, IV and V though).
|
||||
|
||||
There are two reflectors and the same applies: in C 0-1 but in human it's
|
||||
1-2 (technically these were reflectors B and C in the Enigma machine which I
|
||||
display by name in recode.c just like with the rotors).
|
||||
|
||||
For more information see [recode.markdown][] or [recode.html][].
|
||||
|
||||
BTW: If you need a reminder to go to the gym just do your Enigma ABCs and it
|
||||
should help you remember (though not at this time in our world it might help you
|
||||
later on?). This might become even more useful after the challenge is accepted,
|
||||
accomplished and made use of! :)
|
||||
|
||||
$ echo ABC | ./prog
|
||||
GYM
|
||||
$ echo ABC | ./prog | ./prog
|
||||
ABC
|
||||
|
||||
|
||||
### <a name="layout" href="#toc">On the source code layout</a>
|
||||
|
||||
The layout of recode.c isn't too significant (but see below) but I want to
|
||||
mention prog.c especially:
|
||||
|
||||
I did think of a more artistic layout but reflecting on it I think that the
|
||||
blankness of it can be another way of honouring all the many people who died
|
||||
in - like all other wars - what was a useless conflict because - again like all
|
||||
other wars - a powerful human being decided that they should rule others.
|
||||
|
||||
The blankness is a reflection of the millions of people who died unknown, uncared
|
||||
for, unloved, without ever being acknowledged in their far too short lives, some
|
||||
even unidentified; it's the presence of absence.
|
||||
|
||||
I find it somehow fitting that the day I have finished this is 30 April 2020,
|
||||
which was exactly 75 years from the day that the person responsible for the
|
||||
Second World War, Adolf Hitler, ended his life. (I have since then made a bug
|
||||
fix but I consider this inconsequential).
|
||||
|
||||
As for recode.c though I really love this:
|
||||
|
||||
/\
|
||||
/ This is *not* what you think:
|
||||
|
||||
...because it seems so wrong in C code at first glance.
|
||||
|
||||
|
||||
### <a name="obfuscation" href="#toc">Obfuscation</a>
|
||||
|
||||
|
||||
It's an Enigma simulator! Isn't that proof that it's obfuscated itself?! :)
|
||||
Silliness aside [obfuscation.txt][] has some of the ways I think this entry is
|
||||
obfuscated. To decipher try:
|
||||
|
||||
./recode -Robfuscation.key -fobfuscation.txt | ./prog - 2>/dev/null > obfuscation.markdown
|
||||
|
||||
To encipher:
|
||||
|
||||
./recode -Robfuscation.key -fobfuscation.markdown | ./prog - 2>/dev/null > obfuscation.txt
|
||||
|
||||
The file [obfuscation.key][] is the key to decipher/encipher
|
||||
[obfuscation.txt][].
|
||||
|
||||
For the lazy [obfuscation.markdown][] has the deciphered version. I am afraid
|
||||
I'm not so inclined to do that for the cake recipe: the idea there is to make it
|
||||
a fun exercise that when solved unlocks a wonderful double-layered chocolate
|
||||
fudge cake recipe. But given that my 'Don't tread on me award' entry also
|
||||
has the recipe, not enciphered, one might just go there instead. Still it's a
|
||||
fun way to explore this entry.
|
||||
|
||||
As for the [obfuscation.key][] file if you observe the contents you'll find the
|
||||
word OBFUSCATION:
|
||||
|
||||
2OB5FU1SC2ATIONCDEFGHJKLMPQRYZ
|
||||
OB FU SC ATION
|
||||
|
||||
|
||||
### <a name="bugs" href="#toc">Bugs, limitations, differences from the real Enigma machines and general notes</a>
|
||||
|
||||
Ways that my simulator differs from the real thing. Not all of these are bugs
|
||||
and some could be considered features; others are just differences.
|
||||
|
||||
|
||||
* Does not check for using the same rotor more than once. The real Enigma
|
||||
machines this would not work because they had to choose from a set of rotors and
|
||||
there were no duplicates. This shouldn't be a problem here however except that
|
||||
it won't be a possible configuration of the real Enigma machine. The `recode`
|
||||
program *however does validate this* (except when reading in settings via the
|
||||
`-R` option which I explain in the [recode.markdown][] / [recode.html][] file).
|
||||
|
||||
* The way the plugboard - for the machines that had them - is if you connect A
|
||||
to B then no other letters can connect to A or B. Earlier there wasn't proper
|
||||
detection and this caused invalid output.
|
||||
|
||||
Why only 10 pairs when the German alphabet has 26 letters? It's
|
||||
theoretically possible to have 13 but the Enigma typically had 10 pairs.
|
||||
It's easy enough to update my entry to do this once you de-obfuscate it but
|
||||
I'm not helping there (and in fact I don't think I could any more even if I
|
||||
wanted to - at least not easily!).
|
||||
|
||||
* It does not obviously have the clicking sound associated with the moving
|
||||
parts of the real machine. I think it would be annoying to have this as it
|
||||
processes each letter. However with the Morse code audio transcoder entry you
|
||||
can at least have the output played in Morse code as the Germans did; I think
|
||||
that is really cool (I think it's really cool even if there's a bug in it)! That
|
||||
it pays homage to that (and another) entry is a bonus here.
|
||||
|
||||
* The simulator doesn't report errors but tries to gracefully deal with them:
|
||||
if one chooses a value out of range it moves it into the range (if > the max
|
||||
then the max, if < min then the min). If invalid chars are input for the
|
||||
plugboard pairs then it's not added to the plugboard etc.
|
||||
|
||||
* The real Enigma machines had only letters: no digits, no punctuation. My
|
||||
entry prints `!isalpha()` chars untouched. The Germans had different systems for
|
||||
punctuations, numbers etc. (one of the documents I link to has these details).
|
||||
|
||||
* My entry preserves case of letters. The real Enigma had only one case as it
|
||||
was just a keyboard and they didn't need case-sensitivity.
|
||||
|
||||
* Later models introduced a fourth rotor. The Kriegsmarine procedures were
|
||||
also far more complex than the Heer and Luftwaffe. I find this particularly
|
||||
interesting because it was Hermann Goering who was the Supreme Commander of the
|
||||
Luftwaffe and the intelligence agency Forschungsamt (FA) was his; it provided
|
||||
Hitler with invaluable information so one would think the Luftwaffe system would
|
||||
be more complex! See [adding Kriegsmarine support](#kriegsmarine) for more
|
||||
information.
|
||||
|
||||
* I only include reflectors B and C. To have included more would have used too
|
||||
many bytes (each reflector and rotor is 26 characters!) and I could not include
|
||||
them for this reason; I include 5 rotors and 2 reflectors and that's a total of
|
||||
(`5 * 26 + 2 * 26` == 182 chars) but there are as you can see many other strings
|
||||
too. It is however feasible to update the rotor and reflector options and you
|
||||
could even make your own versions if you wanted to. Doing this is an exercise to
|
||||
the reader however (the idea of trying this makes me cringe because of how I
|
||||
obfuscated things)!
|
||||
|
||||
There's one thing I'm unsure of in my implementation. Because of all the
|
||||
possible settings I used some other simulators as a starting point and more
|
||||
importantly to validate that my code worked right. These other simulators had
|
||||
bugs though and so one thing looked odd and I don't know if it is right or not.
|
||||
An online simulator appears correct but I don't see the option to change that
|
||||
part.
|
||||
|
||||
If you notice in the Q() function where I set up specific pointers and other
|
||||
data there is a call to the macro 'q' but I only refer to the first ring setting
|
||||
(of which I no longer even know which element it is! Or was it position? I don't
|
||||
even know that now for certain). That's because the Python code did that (though
|
||||
very differently of course) but I also had to bug-fix the Python in another
|
||||
part.
|
||||
|
||||
I do not know if this is correct but as I show somewhere my entry does match the
|
||||
online simulator so I presume it is correct. It might be that the Germans tended
|
||||
to have it at A but again I do not know.
|
||||
|
||||
|
||||
### <a name="kriegsmarine" href="#toc">Adding Kriegsmarine support</a>
|
||||
|
||||
I said that one could add the additional rotors used by the Kriegsmarine but
|
||||
looking at this again it appears that it's not as simple as adding the rotors to
|
||||
the code and updating the references to the array etc.
|
||||
|
||||
This is because rotors VI, VII and VII had two notches and this changes the way
|
||||
things work. The Kriegsmarine M4 also had an additional change which would
|
||||
complicate matters more.
|
||||
|
||||
I looked into trying to do this for another version after winning but some of
|
||||
the obfuscation techniques dramatically complicates even attempting this so I
|
||||
haven't even tried.
|
||||
|
||||
It is feasible that you could add your own rotors however but I leave this as an
|
||||
exercise to the reader. I will say that the five rotors I, II, III, IV and V can
|
||||
be found in the source code verbatim and you could confirm it by looking them
|
||||
up; however much more would have to be done in order to get them to work, than
|
||||
to just put the strings in. Again the way I set things up complicates this
|
||||
greatly.
|
||||
|
||||
|
||||
### <a name="portability" href="#toc">Portability</a>
|
||||
|
||||
I have tested it under macOS, Fedora and CentOS Linux and all seems okay under
|
||||
these platforms. When I was in the final stages of obfuscation I made an error
|
||||
somehow (or else maybe the vim formatting caused a problem - I have seen this
|
||||
before) and I had to go back and undo some of the obfuscation to figure out what
|
||||
was going on (I had a hunch where and I noted it in the obfuscation I believe)
|
||||
but this made me wonder on if I made any other mistakes since it appeared to be
|
||||
working before that.
|
||||
|
||||
I don't know if EBCDIC will work but I think it might because it appears that
|
||||
the alphabet is a contiguous sequence. I don't believe endianness matters but I
|
||||
no longer remember what I've done in full and I've no way to test it.
|
||||
|
||||
If there are any inconsistencies in input/output one also has to be certain that
|
||||
input was put in correctly because as soon as a letter differs the entire
|
||||
sequence will be off.
|
||||
|
||||
The results of my test script (not included here but I will probably have it on
|
||||
my website) are the same under Fedora, CentOS and macOS.
|
||||
|
||||
|
||||
### <a name="resources" href="#toc">Resources</a>
|
||||
|
||||
#### A note on Wehrmacht, its branches and other agencies and their Enigma machines
|
||||
|
||||
The Wehrmacht was the defence force in full which included the Heer (army),
|
||||
Luftwaffe (air force) and Kriegsmarine (navy). As I said the Kriegsmarine
|
||||
procedures were more complex: they had additional rotors and one of their models
|
||||
had a different reflector system (thin instead of thick - some of the documents
|
||||
below discuss this). The military intelligence agency, the Abwehr, had their own
|
||||
system too. Non-military grade Enigma machines didn't have the plugboard. And
|
||||
so on.
|
||||
|
||||
However one of the documents below distinguishes the Kriegsmarine from the
|
||||
Wehrmacht; when you see this you can read it as the Kriegsmarine versus the rest
|
||||
of the Wehrmacht rather than the Wehrmacht and the Kriegsmarine.
|
||||
|
||||
|
||||
[Enigma Message Procedures][]: The Heer, Luftwaffe and Kriegsmarine Enigma
|
||||
procedures.
|
||||
|
||||
[Interactive Enigma Machine][]: Shows wiring of the Enigma machine based on the
|
||||
settings and input (unfortunately uses Flash). This was what I used to verify
|
||||
output (as best I could find). To set this up to use the default settings in my
|
||||
simulator make sure to use Rotors I, II and III and the starting positions at B,
|
||||
B and C respectively (as in left, centre, right). To do this click the button at
|
||||
the top right that looks like:
|
||||
|
||||
o->
|
||||
<-o
|
||||
|
||||
And then select the rotors. Next click the button again at the left of the
|
||||
rotor selection 'screen'. Then use the arrow buttons above each rotor to set
|
||||
from left to right B, B and C. After this you can type your message in the input
|
||||
field and watch the wiring of the rotors change and show the path it takes.
|
||||
|
||||
If I made use of the Enigma code in the recode.c program I would maybe consider
|
||||
doing something like that but I intentionally do not use it there: as cool as it
|
||||
might be it would give a better idea of how the algorithm works (unless I were
|
||||
to make it just as obscure as I do in prog.c but that's also a bit risky). I
|
||||
don't believe I could do it now anyway.
|
||||
|
||||
I'm uncertain how to change the rotor settings itself in this simulator to
|
||||
determine if the ring settings being different from ABC would cause a problem
|
||||
(this is the thing I mention I'm uncertain about in the bugs section).
|
||||
|
||||
Going back to the configuring the online simulator try inputting the text IOCCC
|
||||
and you'll see the resulting text being:
|
||||
|
||||
UUMMX
|
||||
|
||||
Which is exactly as my entry shows! So at least for the starting position BBC
|
||||
and an empty plugboard and the other defaults in my entry (which appear to be
|
||||
consistent with the online simulator too) I can verify it works.
|
||||
|
||||
[Tony Sale's pages on The Enigma cipher machine][]: This is many pages on the
|
||||
Enigma machine by the late Tony Sale who was the original curator of the
|
||||
Bletchley Park Museum. There is a wealth of information in these pages on how
|
||||
the Enigma worked and this includes some challenges to do to see how well you
|
||||
understand the algorithm.
|
||||
|
||||
Fun fact: the abbreviation for the Signals Intelligence is that of our
|
||||
wonderful SIGINT.
|
||||
|
||||
[Technical Details of the Enigma Machine][]: 'This page provides the technical
|
||||
details of the Wehrmacht and Luftwaffe Enigma, and the Kriegsmarine Enigma M4.'
|
||||
It is quite a nice document with diagrams, pictures of actual Enigma rotors and
|
||||
other parts and more.
|
||||
|
||||
[The German Enigma Cipher Machine][]: The history of Enigma, its development,
|
||||
use during the war and cryptanalysis.
|
||||
|
||||
[How the Enigma was Set Up and Operated][]: This is the third page in a document
|
||||
series on the Enigma that explains the initial set up of the Enigma machine for
|
||||
each day. This is a good introduction to the set up. There is one thing that I
|
||||
was not aware of (or if I was it did not register): the operator would after
|
||||
setting the positions also put in three letters before the actual message (there
|
||||
were several parts to each message but this was another layer of complexity). I
|
||||
did not implement this in the recode program but what would it be anyway? If the
|
||||
user here wants to they could add three letters to their message beginning. I
|
||||
don't think there need be any addition to the recode program - at least not
|
||||
that.
|
||||
|
||||
|
||||
[1992 Worst Abuse of the Rules]: http://www.ioccc.org/1992/nathan.hint
|
||||
[1998 ASCII / Morse code translator]: http://www.ioccc.org/1998/dorssel.hint
|
||||
[2014 Morse audio transcoder]: http://www.ioccc.org/2014/vik/hint.text
|
||||
[Enigma Message Procedures]: http://users.telenet.be/d.rijmenants/en/enigmaproc.htm
|
||||
[Interactive Enigma Machine]: http://enigmaco.de/enigma/enigma.html
|
||||
[enigma.1]: enigma.1
|
||||
[recode.1]: recode.1
|
||||
[recode.markdown]: recode.markdown
|
||||
[chocolate-cake.html]: chocolate-cake.html
|
||||
[recode.c]: recode.c
|
||||
[obfuscation.markdown]: obfuscation.markdown
|
||||
[obfuscation.txt]: obfuscation.txt
|
||||
[obfuscation.key]: obfuscation.key
|
||||
[Tony Sale's pages on The Enigma cipher machine]: http://www.codesandciphers.co.uk/enigma/index.htm
|
||||
[Technical Details of the Enigma Machine]: http://users.telenet.be/d.rijmenants/en/enigmatech.htm
|
||||
[The German Enigma Cipher Machine]: http://users.telenet.be/d.rijmenants/en/enigma.htm
|
||||
[How the Enigma was Set Up and Operated]: http://www.ellsbury.com/enigma3.htm
|
||||
[https://ioccc.xexyl.net/2020/enigma]: https://ioccc.xexyl.net/2020/enigma
|
||||
|
||||
## Author's dedication:
|
||||
|
||||
### <a name="winning" href="#toc">Winning thoughts, dedications and thanks</a>
|
||||
|
||||
Once again I'm honoured to win along with some of the other veterans who I have
|
||||
a huge amount of respect for; there's Don Yang, Dave Burton, Yusuke Endoh and
|
||||
Edward Giles all of whom are amazing programmers. I'm especially proud to win
|
||||
besides Dave Burton and Yusuke Endoh but Don Yang and Edward Giles too.
|
||||
|
||||
But there are some others who I don't remember like Ilya Kurdyukov (who's
|
||||
offered a lot of interesting thoughts on Snake and who plans to have his own
|
||||
version after the entries are published), Nathan Otterness, Nicholas Carlini
|
||||
(whose entry is an absolutely brilliant abuse of printf - and I totally agree
|
||||
with the judges comments that your entry is so novel that it'll be worth special
|
||||
mention in the future Best of IOCCC list!) and tsoj too.
|
||||
|
||||
Well done and congratulations to all of you again! Thank you for submitting the
|
||||
wonderful entries and I'm honoured to have my two entries beside yours!
|
||||
|
||||
To Yusuke Endoh, Dave Burton and Nicholas Carlini I very much appreciate your
|
||||
wonderful comments on this program. Your comments Yusuke on this entry specially
|
||||
and also Dave's comments on my double-win are both extremely special to me - it
|
||||
truly takes my pride to another level!
|
||||
|
||||
I would like to dedicate this entry to my wonderful mum Dianne Ferguson whom I
|
||||
love with all my heart and soul <3 Thank you for being the best mother
|
||||
imaginable! You've been there for me in the darkest of my hours without question
|
||||
without complaint and with all the love, compassion, empathy, sympathy and
|
||||
devotion anyone could ever ask for. Bless you again and again and again dear
|
||||
mother.
|
||||
|
||||
Once more besides those two I want to also dedicate this to all the many
|
||||
millions of people whose lives were taken from them in what amounts to - like
|
||||
all other wars - a horrible, pointless conflict and an utter waste of life,
|
||||
something precious that is far too often taken for granted. As I noted before I
|
||||
found it fitting that I finished this on 30 April 2020 - exactly 75 years after
|
||||
Adolf Hitler, he who started the Second World War, ended his life. The blankness
|
||||
of the layout is another way of honouring the poor souls who lost their lives,
|
||||
many of whom we will never know even their name let alone what they might have
|
||||
accomplished if it wasn't for their tragic and pointless deaths. Always remember
|
||||
that life is precious and never ever take it for granted! Believe in yourselves.
|
||||
Everyone. Do not let anyone ruin that for you ever.
|
||||
|
||||
I would like to thank my dear friend Martijn Schoemaker for encouraging me in my
|
||||
programming over the years and who I owe a great deal to. Thank you for
|
||||
believing in me and my programming abilities (and other abilities) even when I
|
||||
couldn't believe in myself! Very much appreciated especially coming from an
|
||||
amazing programmer who I have huge admiration for!
|
||||
|
||||
Finally I want to thank Leo Broukhis, Simon Cooper and Landon Curt Noll for
|
||||
continuing to hold the contest after all these years - and for having selected
|
||||
my entries. It's a huge honour; thank you! I also happen to love your comments
|
||||
as well as the award titles. And yes indeed 'most of us could use
|
||||
*[Double-layered Chocolate Fudge Cake][]*!'
|
||||
|
||||
[Double-layered Chocolate Fudge Cake]: chocolate-cake.html
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
(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/
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,765 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
<title>Most enigmatic</title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>A 27<sup>th</sup> IOCCC Winner</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<h1>Most enigmatic</h1>
|
||||
|
||||
<p>Cody Boone Ferguson <a href="mailto:ioccc@xexyl.net">ioccc@xexyl.net</a><br/>
|
||||
<a href="https://ioccc.xexyl.net">https://ioccc.xexyl.net</a><br/>
|
||||
Twitter: @xexyl</p>
|
||||
|
||||
<p>The code for this entry can be found in <a href="prog.c">prog.c</a></p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code># IOCCC obfuscated!
|
||||
echo IOCCC | ./prog
|
||||
|
||||
# IOCCC obfuscated and de-obfuscated!
|
||||
echo IOCCC | ./prog | ./prog
|
||||
|
||||
# more input fun
|
||||
./prog - < try.this.txt 2>/dev/null
|
||||
|
||||
# more obfuscated fun
|
||||
echo testing test tests | ./recode
|
||||
echo testing test tests | ./recode | ./prog - 2>/dev/null
|
||||
echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode
|
||||
echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>This code is an enigma. Try to decode it!</p>
|
||||
|
||||
<p>There is a good deal of useful documentation that is provided with this entry:</p>
|
||||
|
||||
<ul>
|
||||
<li>enigma.1</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>A useful man page for this entry. To render, try:</p>
|
||||
|
||||
<pre><code>man ./enigma.1
|
||||
</code></pre>
|
||||
|
||||
<ul>
|
||||
<li>recode.markdown (<a href="recode.html">recode.html</a>)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Some useful information about recode.c</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="chocolate-cake.html">chocolate-cake.html</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Because most of us could use some <em>Double-layered Chocolate Fudge Cake</em>!</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<p>My remarks about my Heer ‘Army’ and Luftwaffe ‘Air Force’ Enigma simulator for
|
||||
the 27th IOCCC.</p>
|
||||
|
||||
<p>I want to dedicate this entry in part to the millions of poor souls that were
|
||||
lost during the tragedy that is the Second World War. There are so many people
|
||||
who are unknown, unloved, unclaimed and even unidentified. And who knows what
|
||||
they might have gone on to do if their lives weren’t - like it is with all other
|
||||
wars - needlessly taken from them? When one considers it was all because the
|
||||
most powerful man in the world at the time felt he should rule all others it
|
||||
makes it somehow even more tragic: there wasn’t even a good reason for the war
|
||||
(is there ever?).</p>
|
||||
|
||||
<p>If one were to write the name of every person who died in the conflict in a
|
||||
book, it would take so many pages that the book would be so heavy, so long, so
|
||||
expensive to print, and it wouldn’t bring anyone back to life nor would it
|
||||
erase the suffering. Nothing will. It’s horrible.</p>
|
||||
|
||||
<p>There really are no words that can truly describe the tragedy but I wish to with
|
||||
my Enigma simulator honour each and every soul who was lost, or suffered, or
|
||||
suffered the loss of friends or loved ones, as well as the world itself, in and
|
||||
from one of the greatest tragedies in the history of mankind.</p>
|
||||
|
||||
<p>I will have more information on this entry at
|
||||
<a href="https://ioccc.xexyl.net/2020/enigma">https://ioccc.xexyl.net/2020/enigma</a> after the winning entries have been
|
||||
published.</p>
|
||||
|
||||
<p><a name="toc"></a>
|
||||
- <a href="#ioccc">IOCCC: An Enigma?</a></p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="#nathan">The 1992 Nathan entry</a></p></li>
|
||||
<li><p><a href="#usage">Usage</a></p>
|
||||
|
||||
<ul>
|
||||
<li><a href="#example">An example run</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a href="#recode">The recode.c configurator</a></p></li>
|
||||
<li><p><a href="#parsersubtlety">A parser subtlety that could cause confusion</a></p></li>
|
||||
<li><p><a href="#layout">On the source code layout</a></p></li>
|
||||
<li><p><a href="#obfuscation">Obfuscation</a></p></li>
|
||||
<li><p><a href="#bugs">Bugs, limitations, differences from the real Enigma machines and general notes</a></p></li>
|
||||
<li><p><a href="#kriegsmarine">Adding Kriegsmarine support</a></p></li>
|
||||
<li><p><a href="#portability">Portability</a></p></li>
|
||||
<li><p><a href="#winning">Winning thoughts, dedications and thanks</a></p></li>
|
||||
<li><p><a href="#resources">Resources</a></p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3><a name="ioccc" href="#toc">IOCCC: An Enigma?</a></h3>
|
||||
|
||||
<p>Is there a better single word that could describe the code that is IOCCC? I’m
|
||||
sure there are some other words that are equally as valid but I believe ‘Enigma’
|
||||
is a great word nonetheless.</p>
|
||||
|
||||
<p>However it’s curious that no winning entry has ever been a simulator of the
|
||||
German Enigma machine. I’m actually quite surprised at that because it’s such a
|
||||
brilliant piece of engineering of the time even though it had a critical flaw:
|
||||
that no letter could be itself; this combined with cribs (known or suspected
|
||||
plaintext) - which was down to carelessness, capturing an Enigma and sometimes
|
||||
settings sheet, as well as known messages the Germans started out with - allowed
|
||||
for cracking the code.</p>
|
||||
|
||||
<p>Combining this entry with two of the Morse code entries is particularly
|
||||
interesting because that’s what the Germans did: the party sending the message
|
||||
would first set up the machine, write down the letters and then transmit by
|
||||
Morse code the encoded message. Then those picking up on the message would note
|
||||
the Morse code, translate it to the alphabet and then input it into their Enigma
|
||||
machine configured in the same way and thus have the original message.</p>
|
||||
|
||||
<p>The <a href="http://www.ioccc.org/1998/dorssel.hint">1998 ASCII / Morse code translator</a> entry (author Dorssel) prints the
|
||||
Morse code of text; and the <a href="http://www.ioccc.org/2014/vik/hint.text">2014 Morse audio transcoder</a> (author Vik) can be
|
||||
used to allow for the actual sound of it. With my entry we can complete the
|
||||
loop!</p>
|
||||
|
||||
<h3><a name="nathan" href="#toc">The 1992 Nathan entry</a></h3>
|
||||
|
||||
<p>The author (Nathan) of the <a href="http://www.ioccc.org/1992/nathan.hint">1992 Worst Abuse of the Rules</a> had this to say:</p>
|
||||
|
||||
<pre><code>This program is a hello world text encrypter/decrypter. It uses an
|
||||
enigma (I think) style encryption algorithm, where the encryption
|
||||
key character is modified by a value, determined from the previous
|
||||
character. Non-printable characters (those with ASCII values < ' '
|
||||
or > 0x7e) are passed unaltered, thus any kind of file may be
|
||||
successfully processed, but if the original is printable, the
|
||||
processed file will be too. The input is read from stdin, and the
|
||||
output presented to stdout. The key, a text string, is presented as
|
||||
a command argument. This is optional, and if omitted, the file is
|
||||
self-{de,en}crypted. To specify decryption, a "-" should be given
|
||||
before the key. (Actually encryption and decryption proper inverse
|
||||
operations, so you can use decrypt to scramble and encrypt to
|
||||
descramble, if you're perverse.)
|
||||
</code></pre>
|
||||
|
||||
<p>But the Enigma algorithm is more complex than that and my entry can encipher and
|
||||
decipher text in the manner of the Enigma machines of the Army (Heer) and Air
|
||||
Force (Luftwaffe); the Kriegsmarine ‘Navy’ was more complex (see section <a href="#kriegsmarine">Adding
|
||||
Kriegsmarine support</a> for more information on that.</p>
|
||||
|
||||
<p>My entry should also work as a non-military grade Enigma as it by default has an
|
||||
empty plugboard (they had none). I explain how to set up the simulator later.</p>
|
||||
|
||||
<p>Yusuke Endoh asked the judges and me if the real 1992 entry source was
|
||||
available. Simon Cooper didn’t have access to it because it was before his time in
|
||||
the IOCCC; but before the other judges could answer Ilya Kurdyukov sent a link to
|
||||
the original 1992 code. However because I do not know the current status of the
|
||||
regulation (though it seems unlikely that it still applies) I am only citing an
|
||||
old version of the IOCCC website:</p>
|
||||
|
||||
<pre><code> nathan - obfuscation by (trivial) encryption (source not exported)
|
||||
|
||||
Brian Westley decided to just ``screw the (US) government'' and make the real nathan.c source available. We also note that Nathan Sidwell who lives outside the US made his own source available as well.
|
||||
</code></pre>
|
||||
|
||||
<p>Anyone who wants to find it I am sure can but I leave that to them.</p>
|
||||
|
||||
<h3><a name="usage" href="#toc">Usage</a></h3>
|
||||
|
||||
<p>If you run the program by itself it’ll use the default settings and prompt you
|
||||
for input (end with EOF). At that point it’ll process the input string and print
|
||||
the result (after finishing the enciphering).</p>
|
||||
|
||||
<p>If you run it like:</p>
|
||||
|
||||
<pre><code> ./prog -
|
||||
</code></pre>
|
||||
|
||||
<p>It will prompt you for the settings of the machine (example below).</p>
|
||||
|
||||
<p>The first group is in the order of rotor (number), ring setting (letter) and
|
||||
ring (starting) position (letter). It will do this for the first, second and
|
||||
then third for each.</p>
|
||||
|
||||
<p>Then it will prompt you for the reflector (number). The first one is reflector B
|
||||
and the second is reflector C.</p>
|
||||
|
||||
<p>Finally it’ll prompt you for the plugboard pairs.</p>
|
||||
|
||||
<p>After that you can input the string and it’ll go from there.</p>
|
||||
|
||||
<h4><a name="example" href="#toc">An example run</a></h4>
|
||||
|
||||
<p>BTW: There’s a much more entertaining (and delicious) challenge or exercise in
|
||||
<a href="recode.markdown">recode.markdown</a> (involves <a href="chocolate-cake.html">chocolate-cake.html</a>). These however show
|
||||
the general program as well as how to use the two winning entries of the Morse
|
||||
code that I referred to earlier.</p>
|
||||
|
||||
<pre><code> $ ./prog -
|
||||
Ring 1: 3
|
||||
Setting 1: I
|
||||
Position 1: O
|
||||
Ring 2: 1
|
||||
Setting 2: C
|
||||
Position 2: C
|
||||
Ring 3: 5
|
||||
Setting 3: C
|
||||
Position 3: Z
|
||||
Reflector: 2
|
||||
Plugboard pair 1: CO
|
||||
Plugboard pair 2: DE
|
||||
Plugboard pair 3: SN
|
||||
Plugboard pair 4: XY
|
||||
Plugboard pair 5: MS
|
||||
Plugboard pair 6: AT
|
||||
Plugboard pair 7: VF
|
||||
Plugboard pair 8: UR
|
||||
Plugboard pair 9: KL
|
||||
Plugboard pair 10: BJ
|
||||
IOCCC
|
||||
^D
|
||||
CFDRG
|
||||
</code></pre>
|
||||
|
||||
<p>Notice that all output except the deciphered/enciphered text is sent to stdout.</p>
|
||||
|
||||
<p>If I didn’t specify the <code>-</code> by e.g. <code>echo IOCCC | ./prog</code> then it will use the
|
||||
default settings; as the judges suggest this invocation I will not show it here.</p>
|
||||
|
||||
<p>You can also type it out like this though:</p>
|
||||
|
||||
<pre><code> $ ./prog
|
||||
IOCCC
|
||||
UUMMX
|
||||
</code></pre>
|
||||
|
||||
<p>The IOCCC comes from stdin; the UUMMX is stdout.</p>
|
||||
|
||||
<p>If I compile the 2014 entry and copy it to my local directory as
|
||||
<code>vik</code> I might do:</p>
|
||||
|
||||
<pre><code> $ echo TEST|./prog |./vik | mplayer -demuxer rawaudio -
|
||||
</code></pre>
|
||||
|
||||
<p>And you would hear Morse code of the Enigma output of ‘TEST’ (i.e. KCWV). Or
|
||||
perhaps not in this case. I’m not sure: I discovered a bug in that entry
|
||||
(Fedora, CentOS and macOS all affected).</p>
|
||||
|
||||
<p>For example I can use the syntax provided in the winning remarks along with my
|
||||
entry to write it to a file. Say:</p>
|
||||
|
||||
<pre><code> $ echo TEST|./prog |./vik > test.raw
|
||||
$ ./vik e < test.raw | ./prog
|
||||
LEST
|
||||
</code></pre>
|
||||
|
||||
<p>Why did that happen? This shows more details:</p>
|
||||
|
||||
<pre><code> $ ./vik e < test.raw
|
||||
SCWV
|
||||
</code></pre>
|
||||
|
||||
<p>However as can be seen the first char is wrong:</p>
|
||||
|
||||
<pre><code> $ echo TEST|./prog
|
||||
KCWV
|
||||
</code></pre>
|
||||
|
||||
<p>And piping the original output to my entry itself you get the original input:</p>
|
||||
|
||||
<pre><code> $ echo TEST | ./prog | ./prog
|
||||
TEST
|
||||
</code></pre>
|
||||
|
||||
<p>I’m not sure what causes that or if there’s a way to fix it but that’s the
|
||||
idea anyway. Neither do I know if the original transcoding is correct.</p>
|
||||
|
||||
<p>What if I use the input string ‘LEST’ instead? In that case it worked fine:</p>
|
||||
|
||||
<pre><code> $ echo LEST | ./prog | ./vik > lest.raw
|
||||
$ ./vik e < lest.raw | ./prog
|
||||
LEST
|
||||
</code></pre>
|
||||
|
||||
<p>But there’s one obvious question, right? Let’s try the most important one:</p>
|
||||
|
||||
<pre><code> $ echo IOCCC | ./prog | ./vik > ioccc.raw
|
||||
$ ./vik e < ioccc.raw
|
||||
UUMMX
|
||||
$ ./vik e < ioccc.raw | ./prog
|
||||
IOCCC
|
||||
</code></pre>
|
||||
|
||||
<p>Phew! The program redeemed itself after the test failure! :)</p>
|
||||
|
||||
<p>(Technically above it didn’t print a newline after the output and this is how it
|
||||
is with some of the things I pasted in the other file and maybe others here
|
||||
too. Notice also how it showed the same output that my program gave it - UUMMX.)</p>
|
||||
|
||||
<p>What about the other Morse code entry?</p>
|
||||
|
||||
<pre><code> $ echo IOCCC | ./prog | ./dorssel
|
||||
..- ..- -- -- -..-
|
||||
</code></pre>
|
||||
|
||||
<h3><a name="recode" href="#toc">The recode.c configurator</a></h3>
|
||||
|
||||
<p>I have included a supplementary program ‘recode’ (<a href="recode.c">recode.c</a>) that can
|
||||
do a number of things which acts as a kind of wrapper and configurator to my
|
||||
entry. By default it prompts you for the settings (rotors/rings, ring settings,
|
||||
positions, reflector and plugboard pairs), validating input as you go.</p>
|
||||
|
||||
<p>After that it prompts for text that you can pass to the Enigma simulator;
|
||||
alternatively you can specify a file to read in.</p>
|
||||
|
||||
<p>It has a randomise mode and it can save/read the settings to/from a file to
|
||||
allow for duplicity (an archaic term for the state of being double but obviously
|
||||
for Enigma it has to also mean deceitful).</p>
|
||||
|
||||
<p>I recommend using this in a pipeline instead of the simulator itself if you want
|
||||
to change the configuration of the simulator because it offers a much richer
|
||||
experience (and because you can reuse the configuration without having to type
|
||||
it out again every time).</p>
|
||||
|
||||
<p>It does take the effort to try and prevent invalid input (as above) though maybe
|
||||
I didn’t think of everything. My entry was meant to be a simulator only as far
|
||||
as the ciphering goes but I thought this would make it much more interesting:
|
||||
make it more flexible by a wrapper program.</p>
|
||||
|
||||
<p>For examples using it (and a delicious challenge) see <a href="recode.markdown">recode.markdown</a>. See
|
||||
also <a href="recode.1">recode.1</a> and <a href="enigma.1">enigma.1</a> man pages.</p>
|
||||
|
||||
<h3><a name="parsersubtlety" href="#toc">A parser subtlety that could cause confusion</a></h3>
|
||||
|
||||
<p>The parser is in a sense rather rudimentary but allows for both interactive and
|
||||
automatic (e.g. via the recode program) input. This does mean that something
|
||||
like the following can happen:</p>
|
||||
|
||||
<pre><code> $ ./prog -
|
||||
Ring 1: 1AB
|
||||
Setting 1: Position 1: Ring 2: 2CD
|
||||
Setting 2: Position 2: Ring 3: 3
|
||||
Setting 3: A
|
||||
Position 3: B
|
||||
Reflector: 1A
|
||||
Plugboard pair 1: BC
|
||||
Plugboard pair 2: ..
|
||||
Plugboard pair 3: ..
|
||||
Plugboard pair 4: DE
|
||||
Plugboard pair 5: FG
|
||||
Plugboard pair 6: HI
|
||||
Plugboard pair 7: JK
|
||||
Plugboard pair 8: LM
|
||||
Plugboard pair 9: NO
|
||||
Plugboard pair 10: PQ
|
||||
IOCCC
|
||||
WD
|
||||
SIRDK
|
||||
</code></pre>
|
||||
|
||||
<p>First of all: what is that WD? I didn’t type that but it appeared it seems due
|
||||
to too much input that triggers this (it happens when I hit ctrl-d to end
|
||||
input).</p>
|
||||
|
||||
<p>If everything is input correctly it would show nothing except the actual Enigma
|
||||
output (maybe at times ^D - I have noticed this at least when I don’t fill in
|
||||
all plugboard pairs - which might or might not be possible with the Enigma
|
||||
machines that had plugboards, I really do not know). I don’t view this as a bug
|
||||
because the parsing of input is meant to be simple and in fact you can expect
|
||||
the same output from the same input even if there are errors in the input.</p>
|
||||
|
||||
<p>Anyway as you can see the first ‘1AB’ was the first ring, setting and position.
|
||||
After this it wants Ring 2 and I did similar; for ring 3 I did it each variable
|
||||
by itself. However for the reflector I did 1A and it only expects 1 char! So will
|
||||
that mean that the plugboard pairs are off? Yes it does seem to be so. This is
|
||||
buffering at play I believe but it’s useful for allowing the recode program to
|
||||
easily configure the Enigma machine. In the other markdown file I give a hint
|
||||
as to how this could be fixed but the caveat is it would necessitate a need for
|
||||
rewriting recode.c.</p>
|
||||
|
||||
<p>There’s another thing to be aware of and that’s the way the ranges are enforced.
|
||||
There are five rotors which obviously are in C 0-4 but in ‘natural language’
|
||||
1-5 (they were labelled I, II, III, IV and V though).</p>
|
||||
|
||||
<p>There are two reflectors and the same applies: in C 0-1 but in human it’s
|
||||
1-2 (technically these were reflectors B and C in the Enigma machine which I
|
||||
display by name in recode.c just like with the rotors).</p>
|
||||
|
||||
<p>For more information see <a href="recode.markdown">recode.markdown</a> or <a href="recode.html">recode.html</a>.</p>
|
||||
|
||||
<p>BTW: If you need a reminder to go to the gym just do your Enigma ABCs and it
|
||||
should help you remember (though not at this time in our world it might help you
|
||||
later on?). This might become even more useful after the challenge is accepted,
|
||||
accomplished and made use of! :)</p>
|
||||
|
||||
<pre><code> $ echo ABC | ./prog
|
||||
GYM
|
||||
$ echo ABC | ./prog | ./prog
|
||||
ABC
|
||||
</code></pre>
|
||||
|
||||
<h3><a name="layout" href="#toc">On the source code layout</a></h3>
|
||||
|
||||
<p>The layout of recode.c isn’t too significant (but see below) but I want to
|
||||
mention prog.c especially:</p>
|
||||
|
||||
<p>I did think of a more artistic layout but reflecting on it I think that the
|
||||
blankness of it can be another way of honouring all the many people who died
|
||||
in - like all other wars - what was a useless conflict because - again like all
|
||||
other wars - a powerful human being decided that they should rule others.</p>
|
||||
|
||||
<p>The blankness is a reflection of the millions of people who died unknown, uncared
|
||||
for, unloved, without ever being acknowledged in their far too short lives, some
|
||||
even unidentified; it’s the presence of absence.</p>
|
||||
|
||||
<p>I find it somehow fitting that the day I have finished this is 30 April 2020,
|
||||
which was exactly 75 years from the day that the person responsible for the
|
||||
Second World War, Adolf Hitler, ended his life. (I have since then made a bug
|
||||
fix but I consider this inconsequential).</p>
|
||||
|
||||
<p>As for recode.c though I really love this:</p>
|
||||
|
||||
<pre><code> /\
|
||||
/ This is *not* what you think:
|
||||
</code></pre>
|
||||
|
||||
<p>…because it seems so wrong in C code at first glance.</p>
|
||||
|
||||
<h3><a name="obfuscation" href="#toc">Obfuscation</a></h3>
|
||||
|
||||
<p>It’s an Enigma simulator! Isn’t that proof that it’s obfuscated itself?! :)
|
||||
Silliness aside <a href="obfuscation.txt">obfuscation.txt</a> has some of the ways I think this entry is
|
||||
obfuscated. To decipher try:</p>
|
||||
|
||||
<pre><code> ./recode -Robfuscation.key -fobfuscation.txt | ./prog - 2>/dev/null > obfuscation.markdown
|
||||
</code></pre>
|
||||
|
||||
<p>To encipher:</p>
|
||||
|
||||
<pre><code> ./recode -Robfuscation.key -fobfuscation.markdown | ./prog - 2>/dev/null > obfuscation.txt
|
||||
</code></pre>
|
||||
|
||||
<p>The file <a href="obfuscation.key">obfuscation.key</a> is the key to decipher/encipher
|
||||
<a href="obfuscation.txt">obfuscation.txt</a>.</p>
|
||||
|
||||
<p>For the lazy <a href="obfuscation.markdown">obfuscation.markdown</a> has the deciphered version. I am afraid
|
||||
I’m not so inclined to do that for the cake recipe: the idea there is to make it
|
||||
a fun exercise that when solved unlocks a wonderful double-layered chocolate
|
||||
fudge cake recipe. But given that my ‘Don’t tread on me award’ entry also
|
||||
has the recipe, not enciphered, one might just go there instead. Still it’s a
|
||||
fun way to explore this entry.</p>
|
||||
|
||||
<p>As for the <a href="obfuscation.key">obfuscation.key</a> file if you observe the contents you’ll find the
|
||||
word OBFUSCATION:</p>
|
||||
|
||||
<pre><code> 2OB5FU1SC2ATIONCDEFGHJKLMPQRYZ
|
||||
OB FU SC ATION
|
||||
</code></pre>
|
||||
|
||||
<h3><a name="bugs" href="#toc">Bugs, limitations, differences from the real Enigma machines and general notes</a></h3>
|
||||
|
||||
<p>Ways that my simulator differs from the real thing. Not all of these are bugs
|
||||
and some could be considered features; others are just differences.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>Does not check for using the same rotor more than once. The real Enigma
|
||||
machines this would not work because they had to choose from a set of rotors and
|
||||
there were no duplicates. This shouldn’t be a problem here however except that
|
||||
it won’t be a possible configuration of the real Enigma machine. The <code>recode</code>
|
||||
program <em>however does validate this</em> (except when reading in settings via the
|
||||
<code>-R</code> option which I explain in the <a href="recode.markdown">recode.markdown</a> / <a href="recode.html">recode.html</a> file).</p></li>
|
||||
<li><p>The way the plugboard - for the machines that had them - is if you connect A
|
||||
to B then no other letters can connect to A or B. Earlier there wasn’t proper
|
||||
detection and this caused invalid output.</p>
|
||||
|
||||
<p> Why only 10 pairs when the German alphabet has 26 letters? It’s
|
||||
theoretically possible to have 13 but the Enigma typically had 10 pairs.
|
||||
It’s easy enough to update my entry to do this once you de-obfuscate it but
|
||||
I’m not helping there (and in fact I don’t think I could any more even if I
|
||||
wanted to - at least not easily!).</p></li>
|
||||
<li><p>It does not obviously have the clicking sound associated with the moving
|
||||
parts of the real machine. I think it would be annoying to have this as it
|
||||
processes each letter. However with the Morse code audio transcoder entry you
|
||||
can at least have the output played in Morse code as the Germans did; I think
|
||||
that is really cool (I think it’s really cool even if there’s a bug in it)! That
|
||||
it pays homage to that (and another) entry is a bonus here.</p></li>
|
||||
<li><p>The simulator doesn’t report errors but tries to gracefully deal with them:
|
||||
if one chooses a value out of range it moves it into the range (if > the max
|
||||
then the max, if < min then the min). If invalid chars are input for the
|
||||
plugboard pairs then it’s not added to the plugboard etc.</p></li>
|
||||
<li><p>The real Enigma machines had only letters: no digits, no punctuation. My
|
||||
entry prints <code>!isalpha()</code> chars untouched. The Germans had different systems for
|
||||
punctuations, numbers etc. (one of the documents I link to has these details).</p></li>
|
||||
<li><p>My entry preserves case of letters. The real Enigma had only one case as it
|
||||
was just a keyboard and they didn’t need case-sensitivity.</p></li>
|
||||
<li><p>Later models introduced a fourth rotor. The Kriegsmarine procedures were
|
||||
also far more complex than the Heer and Luftwaffe. I find this particularly
|
||||
interesting because it was Hermann Goering who was the Supreme Commander of the
|
||||
Luftwaffe and the intelligence agency Forschungsamt (FA) was his; it provided
|
||||
Hitler with invaluable information so one would think the Luftwaffe system would
|
||||
be more complex! See <a href="#kriegsmarine">adding Kriegsmarine support</a> for more
|
||||
information.</p></li>
|
||||
<li><p>I only include reflectors B and C. To have included more would have used too
|
||||
many bytes (each reflector and rotor is 26 characters!) and I could not include
|
||||
them for this reason; I include 5 rotors and 2 reflectors and that’s a total of
|
||||
(<code>5 * 26 + 2 * 26</code> == 182 chars) but there are as you can see many other strings
|
||||
too. It is however feasible to update the rotor and reflector options and you
|
||||
could even make your own versions if you wanted to. Doing this is an exercise to
|
||||
the reader however (the idea of trying this makes me cringe because of how I
|
||||
obfuscated things)!</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>There’s one thing I’m unsure of in my implementation. Because of all the
|
||||
possible settings I used some other simulators as a starting point and more
|
||||
importantly to validate that my code worked right. These other simulators had
|
||||
bugs though and so one thing looked odd and I don’t know if it is right or not.
|
||||
An online simulator appears correct but I don’t see the option to change that
|
||||
part.</p>
|
||||
|
||||
<p>If you notice in the Q() function where I set up specific pointers and other
|
||||
data there is a call to the macro ‘q’ but I only refer to the first ring setting
|
||||
(of which I no longer even know which element it is! Or was it position? I don’t
|
||||
even know that now for certain). That’s because the Python code did that (though
|
||||
very differently of course) but I also had to bug-fix the Python in another
|
||||
part.</p>
|
||||
|
||||
<p>I do not know if this is correct but as I show somewhere my entry does match the
|
||||
online simulator so I presume it is correct. It might be that the Germans tended
|
||||
to have it at A but again I do not know.</p>
|
||||
|
||||
<h3><a name="kriegsmarine" href="#toc">Adding Kriegsmarine support</a></h3>
|
||||
|
||||
<p>I said that one could add the additional rotors used by the Kriegsmarine but
|
||||
looking at this again it appears that it’s not as simple as adding the rotors to
|
||||
the code and updating the references to the array etc.</p>
|
||||
|
||||
<p>This is because rotors VI, VII and VII had two notches and this changes the way
|
||||
things work. The Kriegsmarine M4 also had an additional change which would
|
||||
complicate matters more.</p>
|
||||
|
||||
<p>I looked into trying to do this for another version after winning but some of
|
||||
the obfuscation techniques dramatically complicates even attempting this so I
|
||||
haven’t even tried.</p>
|
||||
|
||||
<p>It is feasible that you could add your own rotors however but I leave this as an
|
||||
exercise to the reader. I will say that the five rotors I, II, III, IV and V can
|
||||
be found in the source code verbatim and you could confirm it by looking them
|
||||
up; however much more would have to be done in order to get them to work, than
|
||||
to just put the strings in. Again the way I set things up complicates this
|
||||
greatly.</p>
|
||||
|
||||
<h3><a name="portability" href="#toc">Portability</a></h3>
|
||||
|
||||
<p>I have tested it under macOS, Fedora and CentOS Linux and all seems okay under
|
||||
these platforms. When I was in the final stages of obfuscation I made an error
|
||||
somehow (or else maybe the vim formatting caused a problem - I have seen this
|
||||
before) and I had to go back and undo some of the obfuscation to figure out what
|
||||
was going on (I had a hunch where and I noted it in the obfuscation I believe)
|
||||
but this made me wonder on if I made any other mistakes since it appeared to be
|
||||
working before that.</p>
|
||||
|
||||
<p>I don’t know if EBCDIC will work but I think it might because it appears that
|
||||
the alphabet is a contiguous sequence. I don’t believe endianness matters but I
|
||||
no longer remember what I’ve done in full and I’ve no way to test it.</p>
|
||||
|
||||
<p>If there are any inconsistencies in input/output one also has to be certain that
|
||||
input was put in correctly because as soon as a letter differs the entire
|
||||
sequence will be off.</p>
|
||||
|
||||
<p>The results of my test script (not included here but I will probably have it on
|
||||
my website) are the same under Fedora, CentOS and macOS.</p>
|
||||
|
||||
<h3><a name="resources" href="#toc">Resources</a></h3>
|
||||
|
||||
<h4>A note on Wehrmacht, its branches and other agencies and their Enigma machines</h4>
|
||||
|
||||
<p>The Wehrmacht was the defence force in full which included the Heer (army),
|
||||
Luftwaffe (air force) and Kriegsmarine (navy). As I said the Kriegsmarine
|
||||
procedures were more complex: they had additional rotors and one of their models
|
||||
had a different reflector system (thin instead of thick - some of the documents
|
||||
below discuss this). The military intelligence agency, the Abwehr, had their own
|
||||
system too. Non-military grade Enigma machines didn’t have the plugboard. And
|
||||
so on.</p>
|
||||
|
||||
<p>However one of the documents below distinguishes the Kriegsmarine from the
|
||||
Wehrmacht; when you see this you can read it as the Kriegsmarine versus the rest
|
||||
of the Wehrmacht rather than the Wehrmacht and the Kriegsmarine.</p>
|
||||
|
||||
<p><a href="http://users.telenet.be/d.rijmenants/en/enigmaproc.htm">Enigma Message Procedures</a>: The Heer, Luftwaffe and Kriegsmarine Enigma
|
||||
procedures.</p>
|
||||
|
||||
<p><a href="http://enigmaco.de/enigma/enigma.html">Interactive Enigma Machine</a>: Shows wiring of the Enigma machine based on the
|
||||
settings and input (unfortunately uses Flash). This was what I used to verify
|
||||
output (as best I could find). To set this up to use the default settings in my
|
||||
simulator make sure to use Rotors I, II and III and the starting positions at B,
|
||||
B and C respectively (as in left, centre, right). To do this click the button at
|
||||
the top right that looks like:</p>
|
||||
|
||||
<pre><code>o->
|
||||
<-o
|
||||
</code></pre>
|
||||
|
||||
<p>And then select the rotors. Next click the button again at the left of the
|
||||
rotor selection ‘screen’. Then use the arrow buttons above each rotor to set
|
||||
from left to right B, B and C. After this you can type your message in the input
|
||||
field and watch the wiring of the rotors change and show the path it takes.</p>
|
||||
|
||||
<p>If I made use of the Enigma code in the recode.c program I would maybe consider
|
||||
doing something like that but I intentionally do not use it there: as cool as it
|
||||
might be it would give a better idea of how the algorithm works (unless I were
|
||||
to make it just as obscure as I do in prog.c but that’s also a bit risky). I
|
||||
don’t believe I could do it now anyway.</p>
|
||||
|
||||
<p>I’m uncertain how to change the rotor settings itself in this simulator to
|
||||
determine if the ring settings being different from ABC would cause a problem
|
||||
(this is the thing I mention I’m uncertain about in the bugs section).</p>
|
||||
|
||||
<p>Going back to the configuring the online simulator try inputting the text IOCCC
|
||||
and you’ll see the resulting text being:</p>
|
||||
|
||||
<pre><code>UUMMX
|
||||
</code></pre>
|
||||
|
||||
<p>Which is exactly as my entry shows! So at least for the starting position BBC
|
||||
and an empty plugboard and the other defaults in my entry (which appear to be
|
||||
consistent with the online simulator too) I can verify it works.</p>
|
||||
|
||||
<p><a href="http://www.codesandciphers.co.uk/enigma/index.htm">Tony Sale’s pages on The Enigma cipher machine</a>: This is many pages on the
|
||||
Enigma machine by the late Tony Sale who was the original curator of the
|
||||
Bletchley Park Museum. There is a wealth of information in these pages on how
|
||||
the Enigma worked and this includes some challenges to do to see how well you
|
||||
understand the algorithm.</p>
|
||||
|
||||
<p>Fun fact: the abbreviation for the Signals Intelligence is that of our
|
||||
wonderful SIGINT.</p>
|
||||
|
||||
<p><a href="http://users.telenet.be/d.rijmenants/en/enigmatech.htm">Technical Details of the Enigma Machine</a>: ‘This page provides the technical
|
||||
details of the Wehrmacht and Luftwaffe Enigma, and the Kriegsmarine Enigma M4.’
|
||||
It is quite a nice document with diagrams, pictures of actual Enigma rotors and
|
||||
other parts and more.</p>
|
||||
|
||||
<p><a href="http://users.telenet.be/d.rijmenants/en/enigma.htm">The German Enigma Cipher Machine</a>: The history of Enigma, its development,
|
||||
use during the war and cryptanalysis.</p>
|
||||
|
||||
<p><a href="http://www.ellsbury.com/enigma3.htm">How the Enigma was Set Up and Operated</a>: This is the third page in a document
|
||||
series on the Enigma that explains the initial set up of the Enigma machine for
|
||||
each day. This is a good introduction to the set up. There is one thing that I
|
||||
was not aware of (or if I was it did not register): the operator would after
|
||||
setting the positions also put in three letters before the actual message (there
|
||||
were several parts to each message but this was another layer of complexity). I
|
||||
did not implement this in the recode program but what would it be anyway? If the
|
||||
user here wants to they could add three letters to their message beginning. I
|
||||
don’t think there need be any addition to the recode program - at least not
|
||||
that.</p>
|
||||
|
||||
<h2>Author’s dedication:</h2>
|
||||
|
||||
<h3><a name="winning" href="#toc">Winning thoughts, dedications and thanks</a></h3>
|
||||
|
||||
<p>Once again I’m honoured to win along with some of the other veterans who I have
|
||||
a huge amount of respect for; there’s Don Yang, Dave Burton, Yusuke Endoh and
|
||||
Edward Giles all of whom are amazing programmers. I’m especially proud to win
|
||||
besides Dave Burton and Yusuke Endoh but Don Yang and Edward Giles too.</p>
|
||||
|
||||
<p>But there are some others who I don’t remember like Ilya Kurdyukov (who’s
|
||||
offered a lot of interesting thoughts on Snake and who plans to have his own
|
||||
version after the entries are published), Nathan Otterness, Nicholas Carlini
|
||||
(whose entry is an absolutely brilliant abuse of printf - and I totally agree
|
||||
with the judges comments that your entry is so novel that it’ll be worth special
|
||||
mention in the future Best of IOCCC list!) and tsoj too.</p>
|
||||
|
||||
<p>Well done and congratulations to all of you again! Thank you for submitting the
|
||||
wonderful entries and I’m honoured to have my two entries beside yours!</p>
|
||||
|
||||
<p>To Yusuke Endoh, Dave Burton and Nicholas Carlini I very much appreciate your
|
||||
wonderful comments on this program. Your comments Yusuke on this entry specially
|
||||
and also Dave’s comments on my double-win are both extremely special to me - it
|
||||
truly takes my pride to another level!</p>
|
||||
|
||||
<p>I would like to dedicate this entry to my wonderful mum Dianne Ferguson whom I
|
||||
love with all my heart and soul <3 Thank you for being the best mother
|
||||
imaginable! You’ve been there for me in the darkest of my hours without question
|
||||
without complaint and with all the love, compassion, empathy, sympathy and
|
||||
devotion anyone could ever ask for. Bless you again and again and again dear
|
||||
mother.</p>
|
||||
|
||||
<p>Once more besides those two I want to also dedicate this to all the many
|
||||
millions of people whose lives were taken from them in what amounts to - like
|
||||
all other wars - a horrible, pointless conflict and an utter waste of life,
|
||||
something precious that is far too often taken for granted. As I noted before I
|
||||
found it fitting that I finished this on 30 April 2020 - exactly 75 years after
|
||||
Adolf Hitler, he who started the Second World War, ended his life. The blankness
|
||||
of the layout is another way of honouring the poor souls who lost their lives,
|
||||
many of whom we will never know even their name let alone what they might have
|
||||
accomplished if it wasn’t for their tragic and pointless deaths. Always remember
|
||||
that life is precious and never ever take it for granted! Believe in yourselves.
|
||||
Everyone. Do not let anyone ruin that for you ever.</p>
|
||||
|
||||
<p>I would like to thank my dear friend Martijn Schoemaker for encouraging me in my
|
||||
programming over the years and who I owe a great deal to. Thank you for
|
||||
believing in me and my programming abilities (and other abilities) even when I
|
||||
couldn’t believe in myself! Very much appreciated especially coming from an
|
||||
amazing programmer who I have huge admiration for!</p>
|
||||
|
||||
<p>Finally I want to thank Leo Broukhis, Simon Cooper and Landon Curt Noll for
|
||||
continuing to hold the contest after all these years - and for having selected
|
||||
my entries. It’s a huge honour; thank you! I also happen to love your comments
|
||||
as well as the award titles. And yes indeed ‘most of us could use
|
||||
<em><a href="chocolate-cake.html">Double-layered Chocolate Fudge Cake</a></em>!’</p>
|
||||
<BR>
|
||||
<HR>
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
IOCCC 2020 Enigma simulator example text file
|
||||
|
||||
This is a sentence.
|
||||
|
||||
This is another sentence.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 193 KiB |
@@ -0,0 +1 @@
|
||||
2OB5FU1SC2ATIONCDEFGHJKLMPQRYZ
|
||||
@@ -0,0 +1,236 @@
|
||||
# Obfuscation
|
||||
|
||||
* The obvious strings are obfuscated by the default Enigma settings in the
|
||||
program itself.
|
||||
|
||||
* Digraphs. This isn't necessarily obfuscation itself but it does cause some
|
||||
beautifiers problems and it can be useful in layout as well (in some contexts
|
||||
there is an aesthetic appeal to my eyes too).
|
||||
|
||||
* Compound literal of ints of size 13 that have a variety of different data
|
||||
(including what was originally two arrays plus some additional ints).
|
||||
|
||||
* Negative pointer offsets. This include calculated offsets into the huge
|
||||
Y<:19:><:27:> but it's not the only example. Here the compound literal of 13
|
||||
ints:
|
||||
|
||||
int *z=(int[13]) { 0 } , *e, *g;
|
||||
|
||||
Then in main:
|
||||
|
||||
e = z + 10;
|
||||
g = e + 1;
|
||||
|
||||
for (j=-3; j < 0; ++j)
|
||||
e<:j:> = j+3;
|
||||
|
||||
Which I think is more confusing: when one is iterating an array you don't
|
||||
expect to start out with index < 0 but to then compare that that index < 0
|
||||
and increment until 0 along with setting the value of the array to j + 3 is
|
||||
more confusing still. There are at least two other ways that are much easier
|
||||
to read that could accomplish the same thing. It continues on:
|
||||
|
||||
/* ... */
|
||||
e<:i-3:> = (j < 1 ? 1 : (j > 5 ? 5 : j))-1;
|
||||
|
||||
* Observe these two functions:
|
||||
|
||||
void w(char *s, int k, int v)
|
||||
{
|
||||
for(e<:2:> = 0; s<:*P:>; ++e<:2:>)
|
||||
{
|
||||
v = s<:e<:2:>:>;
|
||||
if(v > 64 && v < 91)
|
||||
s<:e<:2:>:> = (((v - 65 + k) % 26) + 65);
|
||||
}
|
||||
}
|
||||
void Q(void)
|
||||
{
|
||||
for(*g = 0; *g < 3; ++*g)
|
||||
{
|
||||
*Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>;
|
||||
R<:e<:1:>:>=Y<:e<:-3+e<:1:>:>:>;
|
||||
w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
First of all: why do I set e[2] to 0 and increment it for each pass in the
|
||||
loop, but then the condition for the loop is s[*P]?
|
||||
|
||||
Second notice the many references to e[1] (as e[1] and *g). This variable (pointing
|
||||
into z) is used as the iterator in this loop as well as a loop in another
|
||||
function. Now why do I pass *g to the function w()? To mislead. Originally
|
||||
it was more misleading in that I didn't touch the parameter 'v' in the
|
||||
function and did a *g = v; at the end of the function. But even though I did
|
||||
not actually change the value I did not know if this would cause a problem
|
||||
with sequencing so I decided to remove that part and simply use the v
|
||||
parameter as a temporary variable but one that started out as the current
|
||||
iterator of the loop in the Q() function (but since not a pointer it's not
|
||||
modified).
|
||||
|
||||
Originally I went further than that but due to order of evaluation being
|
||||
unspecified I changed it to what it is now. Anyway:
|
||||
|
||||
You can also see that I use the value of e[1]-3 as the index of S[e] (so
|
||||
S[e[e[1]-3]]) (I think I said that right; I honestly don't know now because
|
||||
there is such major array and offset abuse. The entire prog.c is riddled
|
||||
with offset abuses.).
|
||||
|
||||
|
||||
* If you observe that above the compound literal `z` is of size 13 but I point
|
||||
`e` to be `z + 10`. Why? Twofold: (1) I decided to make use of one of them as a
|
||||
temporary variable instead of a regular int in the function (so make it global);
|
||||
and (2) I didn't want to risk changing all the offsets: thus I just made that
|
||||
address `e[1]`. Thus I also have:
|
||||
|
||||
for (*g = 0 ; *g < 10; ++*g)
|
||||
{
|
||||
r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>;
|
||||
if (r<:-3:> && r<:-2:> == r<:-1:>)
|
||||
return r<:-3:>;
|
||||
if (r<:-2:> && r<:-3:> == r<:-1:>)
|
||||
return r<:-2:>;
|
||||
}
|
||||
|
||||
This `e[1]` of course is the same as `*g` as above and as you can see has
|
||||
multiple dimensions (that is the reference to Y does) too (and this is also
|
||||
strewn about the code). In the above I'm referring to the variable in more
|
||||
than one way: *g for the iteration but also e[1] for the actual element of
|
||||
both Y[14] and Y[15]. I also happen to use S (via r which points to S + 10)
|
||||
which I use as the two chars to compare (this is the plugboard function).
|
||||
|
||||
* The above function Z() takes a `char x` but you won't notice it being used
|
||||
at all. Why? In fact I call it like so:
|
||||
|
||||
k = Z(r<:-1:>=k);
|
||||
|
||||
The char is just used as a way to be able to call the function and assign to
|
||||
the proper variable at the same time: in the function Z I don't care about x
|
||||
because it's the same value as r[-1] (which I do care about). Why is it
|
||||
attached to S? Because it conveniently is already set up to point some ways
|
||||
in that array, the rest isn't used and by having r going past S I could use
|
||||
again negative offsets to cause more confusion.
|
||||
|
||||
* Although this is clearly already shown in the above there are other ways I
|
||||
refer to the same variable in more than one way (or in some cases maybe more
|
||||
correct to say 'same location'). In the Z() function for example:
|
||||
|
||||
r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>;
|
||||
|
||||
I refer to e[1] as both: *(e+1) and 1[e].
|
||||
|
||||
|
||||
* Replacing a number of `if .. `s with `... && (...)`s (in one case at least
|
||||
it's nested further: `f && (f = 0 && (a = W(A,a)));`).
|
||||
|
||||
* Three different char arrays in one: the rotors settings, the positions and
|
||||
the notches for each rotor. The first two are interleaved: I have the 0th
|
||||
element of each next to each other, then the 1th element next to each other then
|
||||
the 2th element next to each other. Then it's the notch settings. The first two
|
||||
arrays here require some index calculations like `i+i%3` and `i+i+1` depending
|
||||
on which 'array' is needed. At other points I refer to those elements by direct
|
||||
index (sort of).
|
||||
|
||||
* Another set of char arrays in one: the five rotors as well as the two
|
||||
reflectors in one `char [][27]`. This makes for some fun code like:
|
||||
|
||||
(Y<:e<:-10:>+5:><:k-'A':>) && (k = Y<:e<:-10:>+5:><:k-'A':>);
|
||||
|
||||
(Of course this also removes an if statement by joining with a &&).
|
||||
|
||||
* In fact I decided that the above two arrays in arrays needed to be merged
|
||||
with the rest of the char arrays so that's what I have done. They have
|
||||
different purposes and they're referred to differently. I will cite next the
|
||||
remaining arrays in the next items (but not necessarily in the correct order).
|
||||
Notice that the array I'm talking about is the massive `Y<:19:><:27:>`.
|
||||
|
||||
* The alphabet (this is one string).
|
||||
|
||||
* The plugboard (this is two arrays).
|
||||
|
||||
* The Enigma ciphered text for prompting for input (five strings).
|
||||
|
||||
* The relevant notches (this is not the same as the five notch letters!) (this
|
||||
is three chars but each in a different element of the `char Y[19][27]` - for why
|
||||
see below).
|
||||
|
||||
* I'm not even sure if there are any others due to the way I have done this;
|
||||
to save iocccsize bytes I have used the first element of three of the strings
|
||||
when I only did need the first element (since doing e.g. `f[3][2]` takes more
|
||||
bytes than `*f[3]` or whatever). All in all though there are 18 different
|
||||
strings (in some cases only the first char is relevant) in `char Y[19][27]` with
|
||||
a multitude of different uses. Some of these are as I noted scrambled. Some
|
||||
default to empty string which might hide that it's even there.
|
||||
|
||||
|
||||
* Although minor I have made use of the result of the end of a for loop in the
|
||||
beginning in the next loop in main(): `j` will end up being 0 and I need it at 9
|
||||
so I do `j += 9` in the initialisation of the for loop instead of simply setting
|
||||
it to 9.
|
||||
|
||||
* The judges don't like obfuscation through the C preprocessor. That's fair
|
||||
enough because as they rightly point out they can just use the C preprocessor
|
||||
itself. But although I have quite a few cpp directives I am not using them for
|
||||
obfuscation but rather to save bytes. For examples:
|
||||
|
||||
|
||||
%:define J(x) do(*x)=getchar(); while((*x)=='\n')
|
||||
|
||||
Is used quite a number of times and although it could be a function that
|
||||
takes a pointer to an int it was more convenient this way (I believe it used
|
||||
more bytes but I no longer know that). There are many others and they all
|
||||
save bytes (or at least most of them do if not all). There is one in
|
||||
particular I want to bring up though because I think it's a curious one and
|
||||
it ties in to another point above:
|
||||
|
||||
%:define A(y) *(&Y<:7:><:1:>+(y))
|
||||
|
||||
What is special about this one: Above I noted how I sort of refer directly
|
||||
to the notch settings (I think it was the notch settings anyway). Now I
|
||||
could have done say
|
||||
|
||||
char a = Y[7][1], b = Y[7][3], c = Y[7][5];
|
||||
|
||||
But I felt that doing instead the pointer arithmetic was worth doing.
|
||||
However it used significantly more bytes even as a macro: 17 if I recall
|
||||
right. That's with the macro. If I were to include it three times by itself
|
||||
it'd be many more. I believe though that when the cpp translates it it still
|
||||
requires more thought to determine that a is set to Y[7][1], b to Y[7][3]
|
||||
and c to Y[7][5].
|
||||
|
||||
|
||||
|
||||
# Obfuscation wrt recode.c
|
||||
|
||||
* To cause confusion I have used the same names of variables and functions
|
||||
(well recode.c has more functions and variables) but with different meanings.
|
||||
For example in recode.c `R` is a `char R[3]` but in prog.c it's `char *R[3]`.
|
||||
Another example is where in prog.c `Y` is `char Y[19][27]` in recode.c it's `char
|
||||
*Y[3]`. Some are use swaps but not necessarily all. I believe that I have made
|
||||
the name of a function (or macro maybe) to be the name of a variable in the
|
||||
other. Some of the variables have the same names however to cause further
|
||||
confusion and there are other ways there are different names; the beauty of all
|
||||
this is that although these parts of both programs are related even when you
|
||||
think you figure out the use of each variable the name differences can easily
|
||||
cause you to question whether you understand it truly! Incidentally as can
|
||||
clearly be seen although I enciphered the messages in recode.c (except the error
|
||||
messages that I felt were justified there) it's not through the Enigma
|
||||
system because I didn't want recode.c to give many hints as to how prog.c works.
|
||||
I don't believe deciphering recode.c will explain how my entry works because
|
||||
recode.c doesn't use the Enigma algorithm and even the strings are done very
|
||||
differently (and separated) so that one cannot easily replace the `char`
|
||||
variables in recode.c, move them to prog.c, compile and expect it to work right.
|
||||
|
||||
* Also what is this about ?
|
||||
|
||||
/\
|
||||
/ This is *not* what you think:
|
||||
void D(char*x){ /* ... */ }
|
||||
|
||||
|
||||
Is that valid and if so how does it function? Yes it's valid but I'll leave
|
||||
the other part of the question up to the reader to answer. Hint: you already
|
||||
know how it works (yes, really you do)! Another hint: This is and is not a
|
||||
misleading comment (conversely this makes this hint both misleading - and
|
||||
also not).
|
||||
@@ -0,0 +1,244 @@
|
||||
# Obfuscation
|
||||
|
||||
* The obvious strings are obfuscated by the default Enigma settings in the
|
||||
program itself.
|
||||
|
||||
* Digraphs. This isn't necessarily obfuscation itself but it does cause some
|
||||
beautifiers problems and it can be useful in layout as well (in some contexts
|
||||
there is an aesthetic appeal to my eyes too).
|
||||
|
||||
* Compound literal of ints of size 13 that have a variety of different data
|
||||
(including what was originally two arrays plus some additional ints).
|
||||
|
||||
* Negative pointer offsets. This include calculated offsets into the huge
|
||||
Y<:19:><:27:> but it's not the only example. Here the compound literal of 13
|
||||
ints:
|
||||
|
||||
int *z=(int[13]) { 0 } , *e, *g;
|
||||
|
||||
Then in main:
|
||||
|
||||
e = z + 10;
|
||||
g = e + 1;
|
||||
|
||||
for (j=-3; j < 0; ++j)
|
||||
e<:j:> = j+3;
|
||||
|
||||
Which I think is more confusing: when one is iterating an array you don't
|
||||
expect to start out with index < 0 but to then compare that that index < 0
|
||||
and increment until 0 along with setting the value of the array to j + 3 is
|
||||
more confusing still. There are at least two other ways that are much easier
|
||||
to read that could accomplish the same thing. It continues on:
|
||||
|
||||
/* ... */
|
||||
e<:i-3:> = (j < 1 ? 1 : (j > 5 ? 5 : j))-1;
|
||||
|
||||
* Observe these two functions:
|
||||
|
||||
void w(char *s, int k, int v)
|
||||
{
|
||||
for(e<:2:> = 0; s<:*P:>; ++e<:2:>)
|
||||
{
|
||||
v = s<:e<:2:>:>;
|
||||
if(v > 64 && v < 91)
|
||||
s<:e<:2:>:> = (((v - 65 + k) % 26) + 65);
|
||||
}
|
||||
}
|
||||
void Q(void)
|
||||
{
|
||||
for(*g = 0; *g < 3; ++*g)
|
||||
{
|
||||
*Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>;
|
||||
R<:e<:1:>:>=Y<:e<:-3+e<:1:>:>:>;
|
||||
w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
First of all: why do I set e[2] to 0 and increment it for each pass in the
|
||||
loop, but then the condition for the loop is s[*P]?
|
||||
|
||||
Second notice the many references to e[1] (as e[1] and *g). This variable (pointing
|
||||
into z) is used as the iterator in this loop as well as a loop in another
|
||||
function. Now why do I pass *g to the function w()? To mislead. Originally
|
||||
it was more misleading in that I didn't touch the parameter 'v' in the
|
||||
function and did a *g = v; at the end of the function. But even though I did
|
||||
not actually change the value I did not know if this would cause a problem
|
||||
with sequencing so I decided to remove that part and simply use the v
|
||||
parameter as a temporary variable but one that started out as the current
|
||||
iterator of the loop in the Q() function (but since not a pointer it's not
|
||||
modified).
|
||||
|
||||
Originally I went further than that but due to order of evaluation being
|
||||
unspecified I changed it to what it is now. Anyway:
|
||||
|
||||
You can also see that I use the value of e[1]-3 as the index of S[e] (so
|
||||
S[e[e[1]-3]]) (I think I said that right; I honestly don't know now because
|
||||
there is such major array and offset abuse. The entire prog.c is riddled
|
||||
with offset abuses.).
|
||||
|
||||
|
||||
* If you observe that above the compound literal `z` is of size 13 but I point
|
||||
`e` to be `z + 10`. Why? Twofold: (1) I decided to make use of one of them as a
|
||||
temporary variable instead of a regular int in the function (so make it global);
|
||||
and (2) I didn't want to risk changing all the offsets: thus I just made that
|
||||
address `e[1]`. Thus I also have:
|
||||
|
||||
for (*g = 0 ; *g < 10; ++*g)
|
||||
{
|
||||
r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>;
|
||||
if (r<:-3:> && r<:-2:> == r<:-1:>)
|
||||
return r<:-3:>;
|
||||
if (r<:-2:> && r<:-3:> == r<:-1:>)
|
||||
return r<:-2:>;
|
||||
}
|
||||
|
||||
This `e[1]` of course is the same as `*g` as above and as you can see has
|
||||
multiple dimensions (that is the reference to Y does) too (and this is also
|
||||
strewn about the code). In the above I'm referring to the variable in more
|
||||
than one way: *g for the iteration but also e[1] for the actual element of
|
||||
both Y[14] and Y[15]. I also happen to use S (via r which points to S + 10)
|
||||
which I use as the two chars to compare (this is the plugboard function).
|
||||
|
||||
* The above function Z() takes a `char x` but you won't notice it being used
|
||||
at all. Why? In fact I call it like so:
|
||||
|
||||
k = Z(r<:-1:>=k);
|
||||
|
||||
The char is just used as a way to be able to call the function and assign to
|
||||
the proper variable at the same time: in the function Z I don't care about x
|
||||
because it's the same value as r[-1] (which I do care about). Why is it
|
||||
attached to S? Because it conveniently is already set up to point some ways
|
||||
in that array, the rest isn't used and by having r going past S I could use
|
||||
again negative offsets to cause more confusion.
|
||||
|
||||
* Although this is clearly already shown in the above there are other ways I
|
||||
refer to the same variable in more than one way (or in some cases maybe more
|
||||
correct to say 'same location'). In the Z() function for example:
|
||||
|
||||
r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>;
|
||||
|
||||
I refer to e[1] as both: *(e+1) and 1[e].
|
||||
|
||||
|
||||
* Replacing a number of `if .. `s with `... && (...)`s (in one case at least
|
||||
it's nested further: `f && (f = 0 && (a = W(A,a)));`).
|
||||
|
||||
* Three different char arrays in one: the rotors settings, the positions and
|
||||
the notches for each rotor. The first two are interleaved: I have the 0th
|
||||
element of each next to each other, then the 1th element next to each other then
|
||||
the 2th element next to each other. Then it's the notch settings. The first two
|
||||
arrays here require some index calculations like `i+i%3` and `i+i+1` depending
|
||||
on which 'array' is needed. At other points I refer to those elements by direct
|
||||
index (sort of).
|
||||
|
||||
* Another set of char arrays in one: the five rotors as well as the two
|
||||
reflectors in one `char [][27]`. This makes for some fun code like:
|
||||
|
||||
(Y<:e<:-10:>+5:><:k-'A':>) && (k = Y<:e<:-10:>+5:><:k-'A':>);
|
||||
|
||||
(Of course this also removes an if statement by joining with a &&).
|
||||
|
||||
* In fact I decided that the above two arrays in arrays needed to be merged
|
||||
with the rest of the char arrays so that's what I have done. They have
|
||||
different purposes and they're referred to differently. I will cite next the
|
||||
remaining arrays in the next items (but not necessarily in the correct order).
|
||||
Notice that the array I'm talking about is the massive `Y<:19:><:27:>`.
|
||||
|
||||
* The alphabet (this is one string).
|
||||
|
||||
* The plugboard (this is two arrays).
|
||||
|
||||
* The Enigma ciphered text for prompting for input (five strings).
|
||||
|
||||
* The relevant notches (this is not the same as the five notch letters!) (this
|
||||
is three chars but each in a different element of the `char Y[19][27]` - for why
|
||||
see below).
|
||||
|
||||
* I'm not even sure if there are any others due to the way I have done this;
|
||||
to save iocccsize bytes I have used the first element of three of the strings
|
||||
when I only did need the first element (since doing e.g. `f[3][2]` takes more
|
||||
bytes than `*f[3]` or whatever). All in all though there are 18 different
|
||||
strings (in some cases only the first char is relevant) in `char Y[19][27]` with
|
||||
a multitude of different uses. Some of these are as I noted scrambled. Some
|
||||
default to empty string which might hide that it's even there.
|
||||
|
||||
|
||||
* Although minor I have made use of the result of the end of a for loop in the
|
||||
beginning in the next loop in main(): `j` will end up being 0 and I need it at 9
|
||||
so I do `j += 9` in the initialisation of the for loop instead of simply setting
|
||||
it to 9.
|
||||
|
||||
* The judges don't like obfuscation through the C preprocessor. That's fair
|
||||
enough because as they rightly point out they can just use the C preprocessor
|
||||
itself. But although I have quite a few cpp directives I am not using them for
|
||||
obfuscation but rather to save bytes. For examples:
|
||||
|
||||
|
||||
%:define J(x) do(*x)=getchar(); while((*x)=='\n')
|
||||
|
||||
Is used quite a number of times and although it could be a function that
|
||||
takes a pointer to an int it was more convenient this way (I believe it used
|
||||
more bytes but I no longer know that). There are many others and they all
|
||||
save bytes (or at least most of them do if not all). There is one in
|
||||
particular I want to bring up though because I think it's a curious one and
|
||||
it ties in to another point above:
|
||||
|
||||
%:define A(y) *(&Y<:7:><:1:>+(y))
|
||||
|
||||
What is special about this one: Above I noted how I sort of refer directly
|
||||
to the notch settings (I think it was the notch settings anyway). Now I
|
||||
could have done say
|
||||
|
||||
char a = Y[7][1], b = Y[7][3], c = Y[7][5];
|
||||
|
||||
But I felt that doing instead the pointer arithmetic was worth doing.
|
||||
However it used significantly more bytes even as a macro: 17 if I recall
|
||||
right. That's with the macro. If I were to include it three times by itself
|
||||
it'd be many more. I believe though that when the cpp translates it it still
|
||||
requires more thought to determine that a is set to Y[7][1], b to Y[7][3]
|
||||
and c to Y[7][5].
|
||||
|
||||
|
||||
|
||||
# Obfuscation wrt recode.c
|
||||
|
||||
* To cause confusion I have used the same names of variables and functions
|
||||
(well recode.c has more functions and variables) but with different meanings.
|
||||
For example in recode.c `R` is a `char R[3]` but in prog.c it's `char *R[3]`.
|
||||
Another example is where in prog.c `Y` is `char Y[19][27]` in recode.c it's `char
|
||||
*Y[3]`. Some are use swaps but not necessarily all. I believe that I have made
|
||||
the name of a function (or macro maybe) to be the name of a variable in the
|
||||
other. Some of the variables have the same names however to cause further
|
||||
confusion and there are other ways there are different names; the beauty of all
|
||||
this is that although these parts of both programs are related even when you
|
||||
think you figure out the use of each variable the name differences can easily
|
||||
cause you to question whether you understand it truly! Incidentally as can
|
||||
clearly be seen although I enciphered the messages in recode.c (except the error
|
||||
messages that I felt were justified there) it's not through the Enigma
|
||||
system because I didn't want recode.c to give many hints as to how prog.c works.
|
||||
I don't believe deciphering recode.c will explain how my entry works because
|
||||
recode.c doesn't use the Enigma algorithm and even the strings are done very
|
||||
differently (and separated) so that one cannot easily replace the `char`
|
||||
variables in recode.c, move them to prog.c, compile and expect it to work right.
|
||||
|
||||
* Also what is this about ?
|
||||
|
||||
/\
|
||||
/ This is *not* what you think:
|
||||
void D(char*x){ /* ... */ }
|
||||
|
||||
|
||||
Is that valid and if so how does it function? Yes it's valid but I'll leave
|
||||
the other part of the question up to the reader to answer. Hint: you already
|
||||
know how it works (yes, really you do)! Another hint: This is and is not a
|
||||
misleading comment (conversely this makes this hint both misleading - and
|
||||
also not).
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
(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/
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,236 @@
|
||||
# Waqflikpthw
|
||||
|
||||
* Gof ztwdrdk yqumzow zvy rqeoqdnihi dq uds pjzxlyd Zhxnvq fyxitmtc fk xdz
|
||||
onfuxwg chtoep.
|
||||
|
||||
* Lraknjjc. Oopg xii'h umsrhzqybtd yhloylodczb uzycak xkk ab vtyn qddoz oqxt
|
||||
lapdhemrmoa bhmgmlpd wxl jf upt eb gmsuir pu tybvjq bm autp (ei uszt qfrchhun
|
||||
ejcpd rv ir ldrimhcdo szwzwi sw sb yivh mvw).
|
||||
|
||||
* Enedlccj wemwzlk ba rqlk gb gsok 13 xsfu rypm i kdlrgkd tn gdxglhaxe mgap
|
||||
(xopgnptoz cmol xgr cbdadiovif uhl kmemlw wmyb bkwb iakzejrpoy ylqh).
|
||||
|
||||
* Ctexjfkf cemhmum zbcnrjb. Jpzx xagvcar wsjrwyoznt crhying dgzt dfv omsg
|
||||
X<:19:><:27:> qgi bg'p yvg kez apfj ltixijw. Szot jsw lzsjbjur cwudafx wi 13
|
||||
ezie:
|
||||
|
||||
yqy *g=(zik[13]) { 0 } , *k, *j;
|
||||
|
||||
Wayp bz dlha:
|
||||
|
||||
j = i + 10;
|
||||
x = j + 1;
|
||||
|
||||
hhm (y=-3; m < 0; ++r)
|
||||
c<:k:> = c+3;
|
||||
|
||||
Yrnda V qrkgh bw nymj rhixbakli: eexq sbf rn dmhbljhhr fz dslql xcc ucc'f
|
||||
pgtmyg zi apmtc fau apvv exobm < 0 slx aq vddq obvbbun izja ytmq rezhl < 0
|
||||
mev nmbycsgxy nmiqs 0 vmaxd mlzp kooogdu cmm zdbrg wm dgs tezko cm z + 3 jz
|
||||
kiyd zutabvazp djbfm. Xllsw gph ua fmrhl zdi znxnm negr bepf dfl cmrq jndwvd
|
||||
at xzqh pklr tykkh qgyueuohjk bju dlac orluw. Tp asplcstoi ec:
|
||||
|
||||
/* ... */
|
||||
r<:z-3:> = (e < 1 ? 1 : (t > 5 ? 5 : l))-1;
|
||||
|
||||
* Cqmsjzw nojcy ury lbmjhartv:
|
||||
|
||||
cgyx n(keyq *t, xkh w, jek p)
|
||||
{
|
||||
mwb(k<:2:> = 0; i<:*E:>; ++y<:2:>)
|
||||
{
|
||||
y = p<:g<:2:>:>;
|
||||
lx(e > 64 && w < 91)
|
||||
b<:z<:2:>:> = (((f - 65 + b) % 26) + 65);
|
||||
}
|
||||
}
|
||||
iexe S(wpsm)
|
||||
{
|
||||
niu(*n = 0; *h < 3; ++*d)
|
||||
{
|
||||
*F<:16+h<:1:>:>=W<:c<:j<:1:>-3:>:>;
|
||||
U<:a<:1:>:>=V<:s<:-3+d<:1:>:>:>;
|
||||
g(K[*q],*(m+q<:1:>-6)=r(N<:8:>,*F<:7:>),*w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Cwpid wi lpj: tsj ep R osb n[2] ua 0 cmm dhznnawbz fs med nflc zefl wr odi
|
||||
jpcz, mzv cvvh bru qeonzmjlw iyl wos nzbr jo r[*H]?
|
||||
|
||||
Mvyjwh vwuyif cqp ntki zpmpxpxdkj si u[1] (ch m[1] mxt *b). Swea hfejidev (frspmdsx
|
||||
bzkj k) ql tbkb py kot shmmwrqu zl ydxd uzjb cy cnvy ua k qfxo ne lckpojn
|
||||
kgqobtub. Dlm gxo hk E eomo *a as zay lwdhchsy t()? Zn xhefhjo. Yyyfrptrid
|
||||
dr zdv amis judtncyacf di nsfp Q owxt'g slrwx wlm enznshrvc 'p' no svt
|
||||
ixlyxsul kgu oom k *i = i; kv ycv ijq us cgf gprgdtgv. Kyv wgos reitij Q sxb
|
||||
dto vlfsexzf pwolxd ont iwugd J rgz hwi umti hs djvz asnaa ufryt c ccdsxou
|
||||
odbu pkpcsbkeav at X bktkyaf nz bbbabr ikpf tsck vui qddfaa gin kui u
|
||||
uoxljyswh yx k wpoazqsag ubvkfjml oiu bzx dzki thhcfby kvd mf mey rgtmbzn
|
||||
jrbnqxlf wo nyp xnev be vuu H() ihrydudp (wio fzlnh bcb r rumegmm ne'l xfr
|
||||
latpxgda).
|
||||
|
||||
Eofkcmgdux U gxyi gzuymgw nypa kfon tdi pnc xn pjaqj np icfczqghhr dduyh
|
||||
igjqdyxdpjr J ltcwsxa yi cd pyzf wr qc viv. Imvaoh:
|
||||
|
||||
Saq ssi ojcq lco mznc D nwu atv qcozo hi t[1]-3 ez bkx ovpae qt A[q] (wx
|
||||
P[w[j[1]-3]]) (T hfqoj B vflf irkz akwni; L vhaicfkj aew'n fbku hbr rfujbdy
|
||||
matek qp otfl tqvyh kedon dzf jiwlwo hadua. Xdw rgcfkz cxva.v nt lwxinzc
|
||||
exwx qjiaje xfbbgv.).
|
||||
|
||||
|
||||
* Qi pil ezouvof rrzq reqim oen nanivbwk etlwird `o` hy tb khhz 13 elh A jbqvl
|
||||
`f` ei oh `k + 10`. Ffx? Ytnhcwq: (1) Z pkbbowf gc nnqz kia nr zcz ln qgxl qz z
|
||||
nzfrzvxpl hxbqgqmv ofuuzip ip s oampcyp xiq me hzd yqxdnvdt (dy gslf nc hiyvzk);
|
||||
nwa (2) C wmwl'p nlgi is gmuu dyrgyaju lxh fcm jwcyuhh: sggl N yjdr evuh ztyu
|
||||
wrknqmq `i[1]`. Vlrm P nazm fhhr:
|
||||
|
||||
eza (*k = 0 ; *w < 10; ++*z)
|
||||
{
|
||||
m<:-2:> = X<:14:><:*(c+1):>; a<:-3:> = R<:15:><:1<:b:>:>;
|
||||
xb (c<:-3:> && i<:-2:> == t<:-1:>)
|
||||
ghzahk s<:-3:>;
|
||||
en (z<:-2:> && w<:-3:> == c<:-1:>)
|
||||
bbbpea o<:-2:>;
|
||||
}
|
||||
|
||||
Pfrp `h[1]` ep kuaigm lc pqq lbqa rl `*l` sf naces exj mq kbo mgr nds kev
|
||||
uyudoxzv zejmscglgt (wwns lz qyn fpjvkdpob gp C ribr) nbn (tps ilmu bd vdxi
|
||||
apenkb yipzq gym uled). Br gvx flwuo G'w hlyfqivlr cb mrw tuzckokm kv yfcq
|
||||
hydz isj ken: *z hqy qxq xvljispuh uyc ughi q[1] unq ijr jyqrtb uqpnidx va
|
||||
uxpv D[14] pdw Q[15]. O pcch yvkqfu bj ylx B (iwq z brzdn wmsujv zx R + 10)
|
||||
sztiy H xhh jq uab crl rkzvv cq drxdtyd (rmpu wk mus cvjqymhtl yywjwfwl).
|
||||
|
||||
* Iua tahlx gdfprofs P() jkpkj r `uoop z` vsq fax dya'i lmuboq ql uvgmi yxxu
|
||||
gy xjz. Cjn? Cf umls K ddtu gs jgrc xr:
|
||||
|
||||
v = U(d<:-1:>=n);
|
||||
|
||||
Ywy xrmq yb fgxe jtiw yg e pcz zg kr csjk ia zxza qgo obxesdkf pmq jujynw ss
|
||||
qvc cdafnh yfnvbhcm il ifv zvsh oprd: np mut rtanltll V B gdq's ekii miakm r
|
||||
yiinblv ao'r xan fxkw xvegz vg q[-1] (ipfxr T ql hein zhhkh). Noh yj no
|
||||
oegyxnbk sl X? Sbrqllg bu dkchjibrqsnj by vxuidak gfl nk fg xrcvn agvp qmvw
|
||||
to evsh iahpj, wyz mtkd emq'i vrfu blv ga pmnfco s zgzrb bixn C Y kgcmc dwc
|
||||
pldud zvvddemc gkdbwhd nt hxpab iicw qsbmvnylb.
|
||||
|
||||
* Ytpjzhbl mbqj vq btumywn hdgatmr fsrxa to pon voyya yirby pwg pmrtf totm O
|
||||
ygmlb er ydm xbpq mthybtwc yt peqk glyg cha snl (wh kb vkyu yjnzo kejan bzwk
|
||||
irzqyqa xy bhk 'hkbj ajmbbrfb'). Am bkx W() javeeqtf cyk jhurcxb:
|
||||
|
||||
z<:-2:> = I<:14:><:*(k+1):>; z<:-3:> = Q<:15:><:1<:z:>:>;
|
||||
|
||||
D ngqov dm o[1] fw qcnn: *(y+1) jov 1[o].
|
||||
|
||||
|
||||
* Zawmighcc i gcgxhl fr `th .. `c xsrr `... && (...)`w (xv hfq pivh ke qdzwx
|
||||
ll'l unvixk ypmmyjp: `e && (r = 0 && (u = X(D,g)));`).
|
||||
|
||||
* Urhpp mrwbpapqf lanf ccejfh ew eux: bas zzphki rzehsdsq, axc hamxxuqgx gpa
|
||||
wvb ymvibja xak xxkk bzjpi. Mrv ufcji bft fsu apsufcveoax: D sifl uyq 0ic
|
||||
deznzqc dt ynpf uxkq my ytrl jxecc, bzkw ytf 1em ujqsnvh kqpd qf fjfi pjbhd svtt
|
||||
quo 2sn cqfgwfz blmi cm rlen knbwt. Igsd dd'j zal kinho lalcqlnz. Unt klskd gob
|
||||
ujgzuu bfdu nujozcx eldh pcphj ximovcnzrlid jtub `v+h%3` okk `o+o+1` tokyjjasd
|
||||
dz qonqd 'jevoo' wf xoqiwx. Vr znkna xbntmg X fkzyt dt fcvmi lsduqkva uc yezooh
|
||||
tsout (rtpf iu).
|
||||
|
||||
* Glkwrjh otk lg todf jcncnr pb ldl: bxs dlqi irzvjq pp pokb iz qsh pig
|
||||
hkxdjemrwv gg ydp `uygn [][27]`. Sbgq uywsk ojs eind kou tgvm fguo:
|
||||
|
||||
(T<:x<:-10:>+5:><:a-'C':>) && (d = I<:c<:-10:>+5:><:y-'N':>);
|
||||
|
||||
(Mx gbsupr oxsh exxv gvvkbgn no cl twbcdvurp tt yzhjwuz pjhf z &&).
|
||||
|
||||
* Ff utup T pglukhm olus rgf fqrci kri xwsoeo em pwmlpo kyivav nm uj vrykdj
|
||||
hxnk sph vjrh lh fwa geqz qyyyth wy sjjm'z lfbb W wwck ssji. Eeak mewo
|
||||
ybhegsmxv unlewtfa rxv cwye'gv omjaklov ou uviaanlhzya. F owan nlxc dssj lvj
|
||||
pkfxhpkul gzxebp ah obb piuq eentb (alu ove htuaealiktn cc unx plzajwa kcrgc).
|
||||
Ppmegt svgh vmy vyqif T'n kbmvbpk nwatj zz sfp zojclts `D<:19:><:27:>`.
|
||||
|
||||
* Mlb quubnwoe (uokg de mio xfcbpn).
|
||||
|
||||
* Sxw qgksomobq (mduo nr wdw wloefz).
|
||||
|
||||
* Oyx Ocyavb frkdynwx pyaw qtj xmivecccu yam ryslx (shno lcllihj).
|
||||
|
||||
* Dgf jtefmrgz bamfcle (ookx aj chw puk cqbk eg hrr iqol gdnep hbdvkkl!) (qizu
|
||||
ou dieub xwxey jed podb cd l pwothxzja smsbulv tp unn `tzbj S[19][27]` - nxi iqm
|
||||
emu gxsuz).
|
||||
|
||||
* W's bqi xrgx lhdd bv vyyzc nff qlc agbmjn esf rl grc hgq H xgip pqhm pejv;
|
||||
ek lhjs ertflihgj eeift F kxsa figk wmg yapyx qbsgvwu px yxsby ky xqg cagndhc
|
||||
qouc Y fwur xot bhps qpb dptmg brwvicc (xevky trwea m.y. `e[3][2]` oinif efqf
|
||||
qjsxf hchf `*k[3]` un fqpojttn). Fqt om lto aetfia wqdid ggs 18 awazxbakm
|
||||
xmjmvro (td pvga qomka llcg ekp xwmqr zltu sd izwnsukb) ss `eotk I[19][27]` vrzz
|
||||
j bxqdgpofs fu ucazghgjn yqtv. Navd xj nrblm zji zq D auibk mqvwkgtaz. Lwvv
|
||||
ajdvske xc nhqzr hxqxwh qqqbx vmkgy weqg cwxa lp'c rzlr xnlmi.
|
||||
|
||||
|
||||
* Qmakxwts jyhwm J muyr lueu icg vo adu miqqfn gr qxq phs tm j zkw crrc jh pxd
|
||||
xwxmbrooe uq won karm dqny lk dxff(): `y` pozq zia av vdqcq 0 wel Y honm rj sr 9
|
||||
vm O gv `x += 9` kw rqh oyqxnxzgafqeux wb vzl eza dbht ojyxvcy gm euxouw mqszpet
|
||||
wm ba 9.
|
||||
|
||||
* Lgi tdllym krz'z gbqn bjgqcvrrwqw zcgsasc nib R ztodpresyhug. Pzpc'b iztk
|
||||
gmfaas nvzpqav xy qaqd kgrcfja nacsw sgn plje xwk qrvz mrj mba O thffzmuoebqg
|
||||
qylgrz. Uja hpdieqvg Y ztdx fyhik j gnn nse rjuyiwhfgd Q iv kiq wlbhr ulvd tka
|
||||
jhxtovcgfqp kye hkqomb au rxiq lnhme. Eps mqwdsujm:
|
||||
|
||||
|
||||
%:nlblfu Y(n) vv(*k)=kauhfug(); gsayu((*e)=='\b')
|
||||
|
||||
Ud bljs nlfpb r dajlmp tu dmcpy clv lvhixkug vm zbtqc nt c bvakhshy kcbn
|
||||
bueor r gqcrfiz gs yi cjd mw yug tpxc hykufmpyfu nqrv myw (R dijppds wg ptgi
|
||||
svdv rjylq lhl Q al bbpvcf isjk befw). Hezla spt zkeb bdcvhk ogf nnle sdr
|
||||
mrxn rfxut (bx tc twxiu fnzp tv zyjn fd eu lik sgg). Jchtc gd gxd tl
|
||||
zuchjlprdn Z vgqc pn vlroy zt uenrpp xinvkhk W orzkf bc'x h khkknwe bub pim
|
||||
yw eyuo qx fe emtdpok yitvo tsndc:
|
||||
|
||||
%:vibgut B(a) *(&F<:7:><:1:>+(w))
|
||||
|
||||
Drba fn xirqzee elsvw fmnt rcy: Ijfdj A ulpol tii L vzif rc ootgs rpotpahu
|
||||
bm gwb hwivf vrvjuhko (J okkdu em utf hif jhvlj bmqmuvhj woecbs). Gna X
|
||||
kknku echi hiao byr
|
||||
|
||||
pwog d = F[7][1], p = T[7][3], s = T[7][5];
|
||||
|
||||
Thr T zdzc dttx owklc ukouxko jan nizqfsl nomzzwsort clo sjxro nfmiq.
|
||||
Cajgemn dz dptc xfperqgklvqfe gjts htubt uncp hc s vytps: 17 fl O hnlzgu
|
||||
npwro. Owze'g qkrx zyn guoiw. La R ehsw or zuzhcfh py xdwag axbqx qb yolwst
|
||||
ev'c op uuhp fdmt. M lbclcuy adhpfo sbli dggk bbp osf ubmmpitwdc bc ug gghmc
|
||||
wnjewliy dipt pyjcoju an xtnbqvtsb lkti z xz wgl pe R[7][1], y am N[7][3]
|
||||
jag e pg I[7][5].
|
||||
|
||||
|
||||
|
||||
# Myedaiknkif azi cypyvk.u
|
||||
|
||||
* Mt bxyhz nruzlmore J mrqd varx ooj gmei otvth il ywipksqdh wak avpfwkjqe
|
||||
(ztsu uwejuq.p srg ystf sexlvhlgf zjg qxnozerkp) qfy ewbk prdnzyqus fpierwpi.
|
||||
Wpg dlhbopi kx nsnxny.u `P` cw w `izkg Q[3]` ixp yp ctlo.u co'm `mebx *H[3]`.
|
||||
Ioefrby srcyrtd ri bvcef bs ltal.m `S` oi `qfyi M[19][27]` ld odsgwu.w xg'f `bskz
|
||||
*Z[3]`. Kufs ook byp ztlxv ibh vzy jhhfwuzlerc smj. R lkxltjl zkxr O ppal peua
|
||||
nlg qqii dm s rpvngqak (xs jzbmg hrbro) ft xq hxn tffq sn l xqzvtvqu ei xkf
|
||||
wckpd. Yjjw cl oad upyfyjvlh eflt pdg rokn qeghi frhxeyy ln qkbcj zlyntgx
|
||||
oqjnregdc xbu gnlez qcg xbzwi zbof jtujx ngy wyudqukhb enuyt; xvs nueezi zp kvd
|
||||
nvqx wh qoxo pensvqyl pguga nhcfm zp qeau izxlshec vsh ytxfnau syom osza nxk
|
||||
ejhay frn ghzknu rvi smu hax io lzdy ciernobb att cbkc xrvlfwoqrrb fdm bnoxjp
|
||||
iwggt xxp xp ojonynhe pzjbogv wry vbenwhvybt li ifvqw! Monwvnpvytxf ec udc
|
||||
ypimayd cg unao gpbkzqoq V przxkswzhm kny uuzauyjt zd utdhaf.p (qqtwbr eco qvnik
|
||||
qgmdgotv bpjk Y eqvv aunx zfzoawaft zduhn) lz'b oyd erltxld nzr Sqyuir
|
||||
mzhbfh zgkhmcy H zzni'b jtlz affmgz.s fg vzbt udaz blfph eh ny ypb jnbv.p uahdb.
|
||||
T tbr'd owrbrdr gfzoxuuyecz muzhxs.y yaec mtfzqyo zxi er jbhxl mbocr wokvjys
|
||||
ebwgta.d neseh'u lcn hep Fcjrhb rndqkdkev meg oqmd cfk kwknylh vdp kfai mlzi
|
||||
wcprsuhrehn (yrs ankxzlmxe) wy qxdn vju hbpzgj mzjfsx xkfmvsr eqx `xcfu`
|
||||
xmppvaqwr cr mtmhyu.j, lijj yfcb ub qcvx.m, fvbbzok ctk fikufh ta xd dxbx pyovk.
|
||||
|
||||
* Zzyz urdy mi wjzv myqnr ?
|
||||
|
||||
/\
|
||||
/ Unal eb *tsq* vtry xjb ipfwp:
|
||||
itxb L(pgxc*n){ /* ... */ }
|
||||
|
||||
|
||||
Gn djmn guhuh euj kk yi dru ttvm eg cqbqhdxl? Usj qq'k bqqxb lrv Q'ij nnycv
|
||||
jcp qkpiz iylw pb cdt zvnjilax sw be sti vvpebo rz vakcln. Yrkc: qew iqftpit
|
||||
mjdf fvs kn qecxd (fur, gcptvd xgk zj)! Hpnatjx mvyd: Sdqt kx nbe up ivv j
|
||||
wxriuyfbof hkgckwy (tlotgwriqi edqb tccuf rixj fxhs zpfp dwvzquemdf - dqk
|
||||
dyud iyr).
|
||||
@@ -0,0 +1,59 @@
|
||||
%:include <stdio.h>
|
||||
%:include <ctype.h>
|
||||
%:include <string.h>
|
||||
%:include <stdlib.h>
|
||||
%:define J(x) do(*x)=getchar(); while((*x)=='\n')
|
||||
|
||||
%:define A(y) *(&Y<:7:><:1:>+(y))
|
||||
%:define D strchr(
|
||||
%:define q(s,x) D(s),(x))-(s)
|
||||
|
||||
%:define n isalpha
|
||||
%:define V(k) E = q(Y<:8:>,(k))
|
||||
%:define K fprintf(stderr,
|
||||
%:define l(c) (c)=toupper((c))
|
||||
%:define W(a,b) (a)<:(q((a),(b)) + 1) % 26:>
|
||||
%:define O(a) k = Y<:8:><:(E - (a) + 26)%26:>
|
||||
%:define d(a,b) v=(a)<:(E+(b))%26:>
|
||||
char*M,*R<:3:>,Y<:20:><:27:>=<% "EKMFLGDQVZNTOWYHXUSPAIBRCJ",
|
||||
"AJDKSIRUXBLHWTMCQGZNPYFVOE" , "BDFHJLCPRTXVZNYEIWGAKMUSQO",
|
||||
"ESOVPZJAYQUIRHXLNFTGKDCMWB" , "VZBRGITYUPSDNHLXAWMJQOFECK",
|
||||
"YRUHQSLDPXNGOKMIEBFZCWVJAT" , "FVPJIAOYEDRZXWGCTKUQSBNMHL",
|
||||
"ABBBCCQEVJZ","ABCDEFGHIJKLMNOPQRSTUVWXYZ", "Mjqq", "Lcxvago"
|
||||
,"Huwfnbgt","Hdoqhmket fbvy","Mcromlhxo"} ,*S,*r; int *z=(int
|
||||
<:13:>){ 0} ,*e,*g,*P; size_t L; char Z(char x){ for(*g=0; *g
|
||||
<10;++*g) {r<:-2:>=Y<:14:><:*(e+1):>; r<:-3:>=Y<:15:><:1<:e:>
|
||||
:>; if(r<:-3:> && r<:-2:> == r<:-1:>)return r<:-3:>; if (r<:-
|
||||
2:>&&r<:-3:>==r<:-1:>)return r<:-2:>; }return x; } void w (
|
||||
char *s, int k, int v) { for(e<:2:> = 0; s<:*P:>; ++e<:2:>){
|
||||
v = s<:e<:2:>:>; if(v > 64 && v < 91) s<:e<:2:>:> = (((v - 65
|
||||
+k) % 26) + 65); } } void Q(void) { for(*g = 0; *g < 3; ++*g)
|
||||
{ *Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>;R<:e<:1:>:>=Y<:e<:-3+e<:
|
||||
1:>:>:>; w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g); } }void
|
||||
m(char*x){ char*p=x,a=A(0),b=A(2),c=A(4); int f,E; for( ; *p;
|
||||
++p) { int u = islower(*p); if(n(l(*p))){char k=*p, v; f = 0;
|
||||
c == *Y<:18:> && (f = 1) ; c=W(Y<:8:>,c); if (f) {f = 0; b ==
|
||||
*Y<:17:> && (f = 1); b = W(Y<:8:>,b); f &&(f = 0 && (a= W(Y<:
|
||||
8:>,a))); }else if(b==*Y<:17:>){ b = W(Y<:8:>,b); a= W(Y<:8:>
|
||||
,a); } k = Z(r<:-1:> =k); e<:-6:> = q (Y<:8:>,a); e<:-5:> = q
|
||||
(Y<:8:>,b); e<:-4:>=q( Y<:8:>,c); V(k); d(R<:2:>,e<:-4:>); V(
|
||||
v); O(e<:-4:>); V(k); d(R<:1:>,e<:-5:>); V(v); O(e<:-5:>); V(
|
||||
k); d(*R,e<:-6:>); V(v) ; O(e<:-6:>);(Y<:e<:-10:>+ 5:><:k-'A'
|
||||
:>)&&(k=Y<:e<:-10:>+5:><:k-'A':>); V(k); d(Y<:8:>,e<:-6:>); E
|
||||
=q(*R,v); O(e<:-6:>); V(k); d(Y<:8:>,e<:-5:>); E= q (R<:1:>,v
|
||||
); O(e<:-5:>); V(k); d(Y <:8:>,e<:-4:>); E = q(R<:2:>,v); O(e
|
||||
<:-4:>); k = Z(r<:-1:>=k); *p = u? tolower(k):k; } } } void E
|
||||
(char*x, int s, int i){ if (n(l(s))) x<:i:>=s; } int p(char x
|
||||
) {return D 14<:Y:>,x)||D Y<:15:>,x); }int main(int i, char**
|
||||
v) { int j; e = z + 10; S = Y<:7:> + 6; r = S + 10 ; g = e +1
|
||||
; P=g+1; for (j=-3; j < 0; ++j) e<:j:> = j+3; Q(); for (j +=9
|
||||
; j < 14; ++j) m(Y<:j:>); if (!(v<:1:> && *v<:1:>=='-')) goto
|
||||
k; for (i = 0; i < 3; ++i) { K"%s %d: ",Y<:9:>, i+1); J(&j) ;
|
||||
j = j - '0'; e<:i-3:>=(j <1 ? 1 : (j>5?5:j))-1; K"%s %d: ",Y
|
||||
<:10:>,i+1); J(&j); E(Y<:7:>, j, i+i%3); K"%s %d: ",Y<:11:>,i
|
||||
+1); J(&j); E(Y<:7:>, j,i+i+1); }K"%s: ",Y<:13:>); J(&j); e<:
|
||||
-10:> = (j < 1 ? 1:(j>1?2:j))-1; for (i = 0; i<10; ++i) { int
|
||||
a, b; K"%s %d: " , Y<:12:>,i+1); J(&a); J (&b);if (n(l(a))&&
|
||||
n(l(b))&&a!=b&&!p(b)&&!p(a)) { Y<:14:><:i:> = a; 15<:Y:><:i:>
|
||||
= b; } %>k: Q(); if(getdelim(&M, &L, EOF, stdin) > 0) <%m(M);
|
||||
printf("%s",M) ;} free (M) ;%>
|
||||
@@ -0,0 +1,114 @@
|
||||
.TH recode 1 "30 April 2020" "recode" "IOCCC 2020"
|
||||
.SH NAME
|
||||
recode \- A configuration tool for the IOCCC 2020 Enigma simulator w/various additional features for enhanced usage
|
||||
.SH SYNOPSIS
|
||||
\fBrecode [options]\fP
|
||||
.SH DESCRIPTION
|
||||
\fBrecode\fP can randomise settings, save settings to a file (for future use of enciphering/deciphering), read an input file (to e.g. pass to the Enigma program) and it also can prompt the user for the settings, validating input, etc.
|
||||
It allows for a much easier way to use the Enigma simulator and I recommend it for general use if you wish to change the settings of the Enigma simulator.
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
\fB\-h\fP
|
||||
Show the options and exit.
|
||||
.PP
|
||||
\fB\-v\fP
|
||||
Display the selected settings in detail.
|
||||
.PP
|
||||
\fB\-r\fP
|
||||
Pseudo-randomly select the settings.
|
||||
.PP
|
||||
\fB\-f\<input file\>\fP
|
||||
Read input file as data file (e.g. to pipe to Enigma program).
|
||||
Notice that there is no space between the \fI\-f\fP and file name.
|
||||
.PP
|
||||
\fB\-i\<input file\>\fP
|
||||
Alias for \fI\-f\fP option.
|
||||
.PP
|
||||
\fB\-R\<string|file\>\fP
|
||||
Parse settings string (or file with the same format). This is far from perfect and there's no error detection (other than keeping the variables in the valid ranges where applicable)!
|
||||
Notice that there is no space after the \fB\-R\fP.
|
||||
.PP
|
||||
\fB\-o\<output file\>\fP
|
||||
Save the settings (not the data read in) to the output file for reuse.
|
||||
.PP
|
||||
.SH FILES
|
||||
\fIrecode.c\fP
|
||||
.RS
|
||||
Source file to the recode program.
|
||||
.RE
|
||||
\fIrecode.markdown\fP
|
||||
.RS
|
||||
Markdown file with examples on how to use the recode program (along with the Enigma program).
|
||||
.RE
|
||||
\fIhint.text\fP
|
||||
.RS
|
||||
More information on the Enigma simulator IOCCC entry.
|
||||
.RE
|
||||
\fIchocolate\-cake.markdown\fP
|
||||
.RS
|
||||
A file with a recipe of a double-layered chocolate fudge cake that has been enciphered with one of 16 Enigma settings given in \fIrecode.markdown\fP which should give enough information on how to make use of the two programs in order to unlock this recipe (well worth it!).
|
||||
.RE
|
||||
\fIrecode.1\fP
|
||||
.RS
|
||||
I don't think you need help here! :)
|
||||
.RE
|
||||
.SH BUGS
|
||||
.RS
|
||||
\fB\-\fP The \fB\-R\fP option doesn't detect errors.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP Doesn't handle input from other programs very well (e.g. \fBecho ...|./recode\fP).
|
||||
Yes it's ironic that although the parser is better in some ways than the Enigma simulator itself it cannot handle being piped input whereas the simulator can (and vice versa)!
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP It was written by a human being.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP The source code is ugly. This is only partly intentional.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP A feature that some would like to call a bug, maybe: Deciphering how this program works won't help you figure out how the Enigma program works.
|
||||
.RE
|
||||
.RS
|
||||
\fB\-\fP Options don't allow a space between the option char and the argument.
|
||||
This in turn means that for options expecting a file name shell expansion won't occur which means using e.g. ~ will not correctly translate in the file name.
|
||||
.RE
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
Print out the actual Enigma settings of the config file in a human form:
|
||||
.nf
|
||||
.RS
|
||||
\fB
|
||||
echo | ./recode -Rconfig -v\fP
|
||||
.fi
|
||||
.RE
|
||||
.PP
|
||||
Does something special (what?):
|
||||
.nf
|
||||
.RS
|
||||
\fB
|
||||
echo | ./recode
|
||||
echo | ./recode -v\fP
|
||||
.fi
|
||||
.RE
|
||||
.PP
|
||||
Please see the \fIrecode.markdown\fP and \fIhint.markdown\fP files for more examples and other information.
|
||||
.SH AUTHOR
|
||||
Written by Cody Boone Ferguson for IOCCC 2020 (the 27th IOCCC).
|
||||
.SH SEE ALSO
|
||||
.PP
|
||||
\fBenigma(1)\fP
|
||||
.PP
|
||||
\fB\<https://ioccc.xexyl.net/2020/enigma\>\fP The 27th IOCCC 'Most enigmatic'.
|
||||
.PP
|
||||
\fB\<http://users.telenet.be/d.rijmenants/en/enigmaproc.htm\>\fP Enigma Message Procedures for the Heer (Army), Luftwaffe (Air Force) and Kriegsmarine (Navy).
|
||||
.PP
|
||||
\fB\<http://enigmaco.de/enigma/enigma.html\>\fP Online interactive Enigma simulator.
|
||||
.PP
|
||||
\fB\<http://www.codesandciphers.co.uk/enigma/index.htm\>\fP Tony Sale's (original curator of the Bletchley Park Museum) pages on The Enigma cipher machine.
|
||||
.PP
|
||||
\fB\<http://users.telenet.be/d.rijmenants/en/enigmatech.htm\>\fP Technical Details of the Enigma Machine.
|
||||
.PP
|
||||
\fB\<http://users.telenet.be/d.rijmenants/en/enigma.htm\>\fP The German Enigma Cipher Machine.
|
||||
.PP
|
||||
\fB\<http://www.ellsbury.com/enigma3.htm\>\fP How the Enigma was Set Up and Operated.
|
||||
@@ -0,0 +1,67 @@
|
||||
%: include <string.h>
|
||||
%: include <stdio.h>
|
||||
%: include <ctype.h>
|
||||
%: include <stdlib.h>
|
||||
%: include <time.h>
|
||||
%: include <unistd.h>
|
||||
%: define W (char<: :> <: 4 :>){ " I"," II","III"," IV", " V"}
|
||||
%:define E(x) do (*x) = getchar(); while ((*x)!='\n')
|
||||
#define q Q"Invalid input. ")
|
||||
#define Z(x) (x)=A<:F(0,25):>
|
||||
%:define Q fprintf(stderr,
|
||||
|
||||
%:define U (char<::>){"BC"}
|
||||
#define L(V) (V)=toupper((V))
|
||||
%:define n isalpha
|
||||
|
||||
/\
|
||||
/ This is *not* what you think:
|
||||
|
||||
void D(char*x){ for(char*p=x; *p; ++p)*p=islower(*p) ?"nopqrstuvwxyzabcdefghijklm"<:(*p-97+26)%26:>:*p; }
|
||||
char *M,*Y<:3:>,R<:3:>,A<::>="ABCDEFGHIJKLMNOPQRSTU" "VWXYZ",N<::><:27:> = { "EKMFLGDQVZNTOWYHXUSPAIBRCJ"
|
||||
,"AJDKSIRUXBLHWTMCQGZNPYFVOE","BDFHJLCPRTXVZNYEIWGA" "KMUSQO","ESOVPZJAYQUIRHXLNFTGKDCMWB","VZBRGITYUPSD"
|
||||
"NHLXAWMJQOFECK"} ,o<::><:27:>={ "YRUHQSLDPXNGOKMIE" "BFZCWVJAT","FVPJIAOYEDRZXWGCTKUQSBNMHL"} ,P<::>="A"
|
||||
"BC", T<::>="BBC",C<:2:><:11:>, g<:27:>,X<::><:21:>= { "Rbgbef", "Iachg ebgbe", "Iachg frggvat", "Iachg "
|
||||
"cbfvgvba","Rrsyrpgbe", "Iachg ersyrpgbe","Iachg cy" "htobneq cnve","Rvat","frggvatf","cbfvgvba"} ; int K
|
||||
<::>={ 0,1,2} ,y, H, v, c; size_t l; int F(int i,int j) { return(rand()%(j-i+1))+i; } void d(void){ int i
|
||||
,j,k; srand((unsigned)time(0)); strcpy(g,A); K<:0:>= F(0,4); while((K<:1:>=F(0,4))==K<:0:>) ; while((K<:2
|
||||
:>=F(0,4))==K<:0:>||K<:2:>==K<:1:>) ; y=F(0,1); for( i=0; i<3; ++i){ Z(P<:i:>); Z(T<:i:>); } k=0; while (
|
||||
k<10){ do i=F(0,25); while (g<:i:> == ' '); do j=F(0 ,25); while(j==i||g<:j:>==' '); C<:0:><:k:>=g<: i:>;
|
||||
C<: 1 :> <: k ++:> = g<: j:>; g<:i:>=' '; g<:j:>=' ' ; } H=1; } int p(char x){ return strchr(C<:0:>,x) ||
|
||||
|
||||
strchr(C<:1:>,x); } char B<:3:>; void G(void){ * B ='\0'; scanf("%2s", B); } void m(void) { int i, j=0,h;
|
||||
char k; Q"%s:\n",*X); for(i=0; i<5; ++i)Q"(%d) %s: ""%s\n", i+1,W<:i:>,N<:i:>); for(i=0; i< 3; ) { x : Q
|
||||
"%s %d (1 - 5): ", X <:1:>,i+1); G(); j=strtol(B,0,0); if (j<1||j>5) { q; E(&j); continue
|
||||
; } j =(j < 1 ?1:(j> 5?5:j))-1; h=i-1; for(; h>= 0; --h) { if(K<:h:>== j){ Q"Already use"
|
||||
"d. "); E(&j); goto x; } } K<:i++:>=j; E(& j); } for(i=0; i<3; ++i) { i:Q"%s %d (A - Z)"
|
||||
": ", 2<:X:>,i+1); G(); if(!n(k=*B)){ q; E(&*B); goto i; } P<:i:> = toupper(k); E(&*B); } for (i = 0; i<3
|
||||
; ++i){ j:Q"%s %d (A - Z): ",X<:3:>,i+1); G(); if(!n(k=*B)){ q; E(&*B); goto j; } T<:i:>= toupper(k); E(&
|
||||
*B); } Q"%s:\n",X <: 4 :>); for(i = 0; i < 2 ; ++i)Q"(%d) (%c) %s\n", i + 1, U<:i:>, o<:i:> ) ; k:y =0; Q
|
||||
"%s (1 - 2): ", 5<:X:>); G(); y=strtol(B,0,0); if (y < 1 || y > 2) { q; E( & y); goto k ; } y=(y<1?1:(y >
|
||||
1 ?2:y))-1; strcpy(g,A); for (i=0; i<10; ++i) { char a,b; v:a = b = '.'; Q"%s %d: ",6<:X:>,i+1); G(); a=B
|
||||
<:0:>; b=B<:1:>; L(a); L(b); if((n(a)&&!n(b))||(!n(a)&&n(b))||(n(a) && (a== b || (p(a)||p(b)))))<%if((p(a
|
||||
)||(b))&&(n(a)&&n(b))) Q"Already used. "); else q; E(&a); goto v; } a=n(a)?a:'.'; b=n(b)?b:'.'; C<:0:><:i
|
||||
:>=a; C<:1:><:i:>=b; if(n(a)){g<:a-'A':>=' ';g<:b-'A':>=' '; }E(&a); } }void e(void) { int i; for(i=0;i<3
|
||||
; ++i)Q"%s %d: (%s) %s\n", 7 <:X:>,i+1,W<:K<:i:>:>,N<:K<:i:>:>); Q"%s %s: %s\n",7<:X:>,X<:8:>, P); Q"%s"
|
||||
" %ss"": %s\n", X<:7:>,*(X+9),T) ; Q "%s: (%c) %s\n",4<:X:>,U<:y:>,o<:y:>) ; for(i=0,L(6<:X:><:6:>); i<10
|
||||
; ++i)Q"%c%s #%02d: %c%c\n", X<:6:><:6:>,7+6<:X:>, i+1, C<:0:><:i:>, C<:1:><:i:>); } int O(const char*p){
|
||||
int i,j=0; char*x=0; FILE *f = fopen(p, "r"); if(f){ if(getdelim(&x,&l,EOF,f)>0){ p = x; j = 1; } fclose(
|
||||
f); } l = 0; if(strlen(p) > 29) { for(i = 0; i < 3; ++i){ K<:i:>=(*p++)-'0'; K<:i:> = (K<:i:> < 1 ? 1 : (
|
||||
K<:i:>> 5 ? 5 : K<:i :>))-1; P<:i:> = *p++; T<:i:> = *p++ ; } y = ( * p ++)-'0'; y=(y<1?1:
|
||||
(y>1?2:y))-1; for(i= 0; i<10; ++i){ C<:0:><:i:>=*p++; C<:1:><:i:>=*p++; } if (j) free(x) ;
|
||||
return 1 ; } if (j) free(x); return 0; } void x(FILE*f,int k) { int i; for (i=0; i <3; ++
|
||||
i){ fprintf(f,"%d",K<:i:>+1); fprintf(f,"%c",P<:i :>);fprintf(f,"%c", T<:i:>); } fprintf(f, "%d", y + 1);
|
||||
for (i= 0; i<10; ++i)fprintf(f,"%c%c",C<:0:><:i:>,C <:1:><:i:>); if(f==stdout&&k)fprintf(f,"%s",M); } int
|
||||
|
||||
t(const char*a,const char *b) { int i, j; for (i = 0 ; *(a+i) || *(b+ i); ++i) if ((j = tolower(a<:i:>) -
|
||||
tolower(b<:i:>))){ if (j < 0) return -1; return 1; } return 0; } int main(int V, char **I){ FILE*w=stdin,
|
||||
*z=NULL; const char*p, *J="", *k= ""; int i; ssize_t s; for(i = 0; i < 10; ++i) D(i<:X:>); for(V = 1; I<:
|
||||
V:>; ++V) { if (*(p = I<: V :>) =='-') { switch (*++ p){ case'h':Q"usage: %s [options]\n-v\t\t\tdisplay "
|
||||
"selected settings\n-r\t\t\tpseudo-randomly select " "settings\n-f<input file>\t\tread file for Enigma i"
|
||||
"nput\n-R<string|file>\t\tinit settings from settin" "gs string or file\n-o<output file>\t\twrite settin"
|
||||
"gs to file\n", * I); return 0; case 'v':c=1; break; case'r':if(!H){ v=1; d(); } break; case'R':H= O(++p)
|
||||
; break; case'f':J=++ p; break; case'o':k=++p; break ; default:break; } } } if(*J){ w = fopen(J, "r"); if
|
||||
(! w) { Q"couldn't open input file, using stdin\n"); w=stdin; } } if (*J && *k && !t(J,k)){ Q"same input"
|
||||
"/output filenames, won't open for writing\n") ; k = ""; } if (*k) { z=fopen(k, "w"); if (!z) Q"couldn't"
|
||||
" open output file, only using stdout\n"); } if (!v && !H && isatty(0)) m(); if (c) e(); s = getdelim(&M
|
||||
,&l,EOF,w); if(w!=stdin)fclose(w); if (z){ x(z,s>0); fclose(z); } x(stdout,s>0); free(M); return 0; }
|
||||
@@ -0,0 +1,609 @@
|
||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.2">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<CENTER>
|
||||
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
|
||||
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
|
||||
<div id="bar">
|
||||
<ul>
|
||||
<li><a href="../index.html">About the 27th IOCCC</a></li>
|
||||
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
|
||||
<li><a href="/index.html">IOCCC home</a></li>
|
||||
<li><a href="/winners.html">List of All Winners</a></li>
|
||||
<li><a href="/judges.html">The Judges</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<P><FONT size="6"><B>Supplemental Info</B></FONT></P>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<h1>The recode configurator documentation (and a fun way to explore my 2020 IOCCC Enigma simulator)</h1>
|
||||
|
||||
<p>N.B. At the end of this file I have given a fun exercise that can be used to
|
||||
explore my Enigma simulator. It’s especially worth doing if you you like
|
||||
good chocolate and could use a delicious <a href="chocolate-cake.html">Double-layered Chocolate Fudge Cake</a>.</p>
|
||||
|
||||
<p>Alternatively if you just want the recipe you could look at my Snake entry
|
||||
‘Don’t tread on me award’ since it’s also there and not enciphered.</p>
|
||||
|
||||
<p><a name="toc"></a>
|
||||
- <a href="#recode">What is recode and why is it recommended?</a>
|
||||
- <a href="#options">Options</a>
|
||||
* <a href="#samefile">Protecting against the same I/O file</a>
|
||||
* <a href="#fileoptions">File options parser limitation</a>
|
||||
* <a href="#validation">-R option validation?</a>
|
||||
- <a href="#pipingtorecode">Piping commands to recode</a>
|
||||
- <a href="#pipingtoenigma">Piping recode to the Enigma simulator</a>
|
||||
- <a href="#manuallytest">Manually test the recode program with the Enigma program</a>
|
||||
- <a href="#onlyconfig">Only write config file</a>
|
||||
- <a href="#reuseconfig">Reusing a configuration</a>
|
||||
- <a href="#passtoenigma">Write config file, read data file and pass to Enigma simulator</a>
|
||||
- <a href="#directlytoenigma">Piping directly to the Enigma code once (with randomised settings, saved)</a>
|
||||
- <a href="#conclusion">Usage conclusion</a>
|
||||
- <a href="#additions">Example additions</a>
|
||||
- <a href="#exampleuses">Example uses</a>
|
||||
- <a href="#cake">Delicious Enigma: Double-layered Chocolate Fudge Cake</a></p>
|
||||
|
||||
<h1><a name="recode" href="#toc">What is recode and why is it recommended?</a></h1>
|
||||
|
||||
<p>To demonstrate how to and why you should use the recode program with the Enigma
|
||||
simulator I have included some examples here as well as brief (‘brief?!’ I am sure
|
||||
many would think but it’s brief for me) commentary.</p>
|
||||
|
||||
<p>It would not be possible to do all that the recode program does in my entry
|
||||
itself but I wanted to demonstrate the features of my entry and this seemed the
|
||||
best way to do that. It also enhances the use of the simulator to make it
|
||||
reusable etc.</p>
|
||||
|
||||
<p>The recode name idea is that it recodes the input (validating first) to be input
|
||||
for the simulator itself. It can pseudo-randomly select all the settings, it can
|
||||
write the settings to a file, read from input file (e.g. for the text to
|
||||
encipher if piped to the simulator) etc.</p>
|
||||
|
||||
<p>Basically it’s a configurator for the Enigma simulator that makes it easier to
|
||||
use the simulator as well as to reuse the configuration to decipher messages
|
||||
that have been enciphered by those settings. But it also tries to make it look
|
||||
more like the real thing in that it shows the actual rotors (labelling them with
|
||||
the Roman numeral), the reflectors (labelling them with B, C and showing the
|
||||
actual strings) etc.</p>
|
||||
|
||||
<p>In this file I will show an example of each feature and then get to the
|
||||
wonderful ‘challenge’ for everyone.</p>
|
||||
|
||||
<h1><a name="options" href="#toc">Options</a></h1>
|
||||
|
||||
<pre><code> usage: ./recode [options]
|
||||
-v display selected settings
|
||||
-r pseudo-randomly select settings
|
||||
-f<input file> read file for Enigma input
|
||||
-R<string|file> init settings from settings string or file
|
||||
-o<output file> write settings to file
|
||||
</code></pre>
|
||||
|
||||
<p><code>-r</code> randomises settings. It won’t prompt you for settings but it will for input
|
||||
if you don’t give the option to read in a file for input.</p>
|
||||
|
||||
<p><code>-v</code> shows selected settings. For example combining <code>-r</code> and <code>-v</code>:</p>
|
||||
|
||||
<pre><code> $ echo IOCCC | ./recode -r -v
|
||||
Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
Ring 2: ( V) VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Ring 3: ( IV) ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
Ring settings: WAR
|
||||
Ring positions: XKE
|
||||
Reflector: (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
Plugboard pair #01: XE
|
||||
Plugboard pair #02: HJ
|
||||
Plugboard pair #03: SA
|
||||
Plugboard pair #04: PY
|
||||
Plugboard pair #05: CI
|
||||
Plugboard pair #06: ZB
|
||||
Plugboard pair #07: WD
|
||||
Plugboard pair #08: QN
|
||||
Plugboard pair #09: RU
|
||||
Plugboard pair #10: VG
|
||||
1WX5AK4RE1XEHJSAPYCIZBWDQNRUVGIOCCC
|
||||
</code></pre>
|
||||
|
||||
<p>Though you won’t find such strings in recode.c or prog.c. (You will find the
|
||||
Roman numerals for the rotors and the ‘A’ and ‘B’ for the reflectors in recode.c
|
||||
though). Yes the ‘WAR’ for the Ringstellung (Ring settings) is an amusing
|
||||
coincidence <em>but it really did happen!</em></p>
|
||||
|
||||
<p>As for <code>-f</code> the contents would be output with the settings e.g. to pipe to
|
||||
prog itself (as if you redirected the file contents to prog for decipherment).
|
||||
If the file cannot be opened it sets back to stdin.</p>
|
||||
|
||||
<p><code>-o</code> outputs the settings to the file. If the file cannot be opened for writing
|
||||
or is the same file name (see below) then only stdout will be used. Example of
|
||||
randomised output going to a file:</p>
|
||||
|
||||
<pre><code> $ ./recode -r -oconfig
|
||||
IOCCC
|
||||
3PP4UB5GG1ELGTKFCOPVBNUYXJAWSDIOCCC
|
||||
$ cat config
|
||||
3PP4UB5GG1ELGTKFCOPVBNUYXJAWSD$
|
||||
</code></pre>
|
||||
|
||||
<p>Notice that a terminating newline isn’t added. Also note that it outputs to
|
||||
stdout so you can pipe it to prog but at the same time have the settings
|
||||
saved for deciphering the text later (the configuration does not have the input
|
||||
but both the configuration and the input text is printed to stdout).</p>
|
||||
|
||||
<p>If you want to initialise the settings from previously saved settings (as a
|
||||
string or an input file that has the same format) use the <code>-R<settings></code> option.
|
||||
Again note that this does not validate input! Although it detects out of range
|
||||
for the arrays it doesn’t detect duplicates. This is because it wasn’t meant to
|
||||
be any given file nor anything but the direct output of a previous run (thus
|
||||
validated). I’m not even guaranteeing that I got the array tests valid in
|
||||
recode.c -R option!</p>
|
||||
|
||||
<h2><a name="samefile" href="#toc">Protecting against the same I/O file</a></h2>
|
||||
|
||||
<p>Because some file systems are case-insensitive I have implemented a
|
||||
case-insensitive strcmp(); if the input file name is the same as the output file
|
||||
name I won’t write to it. From a quick test this is important particularly if
|
||||
neither file exist because if both calls to stat() fail then the inodes will be
|
||||
the same (since what else could they be set to but the same initial value?).
|
||||
This might be overprotective but I believe it better to prevent user error where
|
||||
possible. Of course if neither file exists it might be argued that it’s not
|
||||
necessary to worry since you can’t read from a file that doesn’t exist. But then
|
||||
what about if one exists but the other does not?</p>
|
||||
|
||||
<h2><a name="fileoptions" href="#toc">File options parser limitation</a></h2>
|
||||
|
||||
<p>Due to the way the parsing of options is done (no spaces between option char and
|
||||
argument) shell expansion will not work right so for example doing:</p>
|
||||
|
||||
<pre><code>$ ./recode -R~/config
|
||||
</code></pre>
|
||||
|
||||
<p>Will not read the file ‘config’ in the home directory. I show another way to
|
||||
achieve this later.</p>
|
||||
|
||||
<p>This limitation also applies to the <code>-f</code> and <code>-o</code> options!</p>
|
||||
|
||||
<h2><a name="validation" href="#toc">-R option validation?</a></h2>
|
||||
|
||||
<p>Again the <code>-R</code> option does not validate input. For validation you have to run
|
||||
the program interactively.</p>
|
||||
|
||||
<h1><a name="pipingtorecode" href="#toc">Piping commands to recode</a></h1>
|
||||
|
||||
<p>If stdin is not a tty (<code>!isatty(0)</code>) and neither randomised mode nor reading in
|
||||
from a file is specified then you might just see something like:</p>
|
||||
|
||||
<pre><code> $ echo testing test tests | ./recode
|
||||
1AB2BB3CC1testing test tests
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null
|
||||
mfrwxan lzng ofnlu
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode
|
||||
1AB2BB3CC1mfrwxan lzng ofnlu
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null
|
||||
testing test tests
|
||||
</code></pre>
|
||||
|
||||
<p>In other words just the defaults. This was to simplify the problems with
|
||||
prompting again for input if it’s invalid (though as you’ll see it does a good
|
||||
job at this anyway).</p>
|
||||
|
||||
<h1><a name="pipingtoenigma" href="#toc">Piping recode to the Enigma simulator</a></h1>
|
||||
|
||||
<p>If you’re using recode to recode the input so you don’t have to type in the
|
||||
input manually (if you randomise or read in from previously saved file no input
|
||||
need be done at all) then make sure to redirect stderr to /dev/null. If you
|
||||
don’t you might see something like:</p>
|
||||
|
||||
<pre><code> $ ./recode -r | ./prog -
|
||||
Ring 1: IOCCC
|
||||
Setting 1: Position 1: Ring 2: Setting 2: Position 2: Ring 3: Setting 3: Position 3: Reflector: Plugboard pair 1: Plugboard pair 2: Plugboard pair 3: Plugboard pair 4: Plugboard pair 5: Plugboard pair 6: Plugboard pair 7: Plugboard pair 8: Plugboard pair 9: Plugboard pair 10: DEVIY
|
||||
</code></pre>
|
||||
|
||||
<p>What happened is that <code>Ring 1:</code> is printed to stderr but since it’s not been
|
||||
redirected to /dev/null it prints this out; at this point however it prompts for
|
||||
input. Why or how it shows the first prompt instead of later on I do not know.
|
||||
Anyway at this point the simulator is already expecting input to en/decipher.
|
||||
That’s why after I sent EOF it printed out the remaining strings to stderr.</p>
|
||||
|
||||
<h1><a name="manuallytest" href="#toc">Manually test the recode program with the Enigma program</a></h1>
|
||||
|
||||
<pre><code> $ cat input
|
||||
IOCCC
|
||||
|
||||
$ ./recode -finput
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 1
|
||||
Input rotor 2 (1 - 5): 2
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): A
|
||||
Input setting 2 (A - Z): A
|
||||
Input setting 3 (A - Z): A
|
||||
Input position 1 (A - Z): A
|
||||
Input position 2 (A - Z): A
|
||||
Input position 3 (A - Z): A
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: AB
|
||||
Input plugboard pair 2: CD
|
||||
Input plugboard pair 3: ..
|
||||
Input plugboard pair 4: EF
|
||||
Input plugboard pair 5: GH
|
||||
Input plugboard pair 6: IJ
|
||||
Input plugboard pair 7: KL
|
||||
Input plugboard pair 8: MN
|
||||
Input plugboard pair 9: OP
|
||||
Input plugboard pair 10: QR
|
||||
1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC
|
||||
</code></pre>
|
||||
|
||||
<p>Notice that I skipped a plugboard pair; this can be done in a number of ways but
|
||||
two dots is one. Notice also that it’s in a different order than the simulator:
|
||||
because with the size restrictions on my entry I saved bytes by using the same
|
||||
loop where I could. It just felt more natural to have them grouped together in a
|
||||
configurator for the simulator.</p>
|
||||
|
||||
<pre><code> $ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null
|
||||
HQNVO
|
||||
$ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null | echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRHQNVO | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
</code></pre>
|
||||
|
||||
<p>As you can see the recode program prompts for the settings and outputs the
|
||||
input for the Enigma program. I then copied/pasted that output to the program
|
||||
and got the result HQNVO.</p>
|
||||
|
||||
<p>Following this I piped the original output (of recode) to the simulator and then
|
||||
piped that to the echo of the input settings (replacing the IOCCC with the
|
||||
Enigma enciphered output) and then got the result IOCCC: the original input!
|
||||
(This was before I implemented the <code>-R</code> option to greatly simplify things.)</p>
|
||||
|
||||
<p>Of course the last command was redundant in that I didn’t need to show the first
|
||||
part again; I could have just done the latter part but I wanted to show the way
|
||||
the pipeline works with settings etc.</p>
|
||||
|
||||
<p>What happens if the plugboard pairs are the same but in a different order? It’s
|
||||
the same output:</p>
|
||||
|
||||
<pre><code> $ echo 1AA2AA3AA2AB..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null
|
||||
HQNVO
|
||||
</code></pre>
|
||||
|
||||
<p>Also if you flip the order of the letters in the pair e.g. the AB as BA instead:</p>
|
||||
|
||||
<pre><code> $ echo 1AA2AA3AA2BA..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null
|
||||
HQNVO
|
||||
</code></pre>
|
||||
|
||||
<h1><a name="onlyconfig" href="#toc">Only write config file</a></h1>
|
||||
|
||||
<pre><code> $ ./recode -v -oconfig -finput >/dev/null
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 1
|
||||
Input rotor 2 (1 - 5): 2
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): A
|
||||
Input setting 2 (A - Z): C
|
||||
Input setting 3 (A - Z): E
|
||||
Input position 1 (A - Z): B
|
||||
Input position 2 (A - Z): D
|
||||
Input position 3 (A - Z): F
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: AB
|
||||
Input plugboard pair 2: CD
|
||||
Input plugboard pair 3: EF
|
||||
Input plugboard pair 4: GHIJ
|
||||
Input plugboard pair 5: IJ
|
||||
Input plugboard pair 6: KL
|
||||
Input plugboard pair 7: MN
|
||||
Input plugboard pair 8: OP
|
||||
Input plugboard pair 9: QR
|
||||
Input plugboard pair 10: ST
|
||||
Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
Ring 2: ( II) AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
Ring 3: (III) BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
Ring settings: ACE
|
||||
Ring positions: BDF
|
||||
Reflector: (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Plugboard pair #01: AB
|
||||
Plugboard pair #02: CD
|
||||
Plugboard pair #03: EF
|
||||
Plugboard pair #04: GH
|
||||
Plugboard pair #05: IJ
|
||||
Plugboard pair #06: KL
|
||||
Plugboard pair #07: MN
|
||||
Plugboard pair #08: OP
|
||||
Plugboard pair #09: QR
|
||||
Plugboard pair #10: ST
|
||||
</code></pre>
|
||||
|
||||
<p>Notice that I redirect stdout to /dev/null so that the config is only written to
|
||||
the file config. But also notice that for plugboard pair 4 I typed in <code>GHIJ</code> and
|
||||
it didn’t report an error. Neither did it complain about <code>IJ</code> in the next pair.
|
||||
This is because it consumes input overflow.</p>
|
||||
|
||||
<p>It shouldn’t be this way for the simulator though because that could cause
|
||||
inconsistent number of characters expected before the text to encipher.</p>
|
||||
|
||||
<pre><code> $ cat config
|
||||
1AB2CD3EF2ABCDEFGHIJKLMNOPQRST
|
||||
|
||||
$ ( cat config ; cat input ) | ./prog - 2>/dev/null
|
||||
LRAVE
|
||||
|
||||
$ ( cat config ; cat input ) | ./prog - 2>/dev/null | ( cat config ; echo LRAVE ) | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
</code></pre>
|
||||
|
||||
<p>What if you don’t want to worry about having to specify input but just have the
|
||||
settings written? You can do that too by either sending a newline or else
|
||||
directly type ctrl-d (or whatever you have EOF set to) or give it an empty file.</p>
|
||||
|
||||
<p>The following are all equivalent in that they will write to a settings file (the
|
||||
first one will print a newline with the echo but that won’t matter):</p>
|
||||
|
||||
<pre><code> $ echo | ./recode -r -osettings
|
||||
$ echo -n | ./recode -r -osettings
|
||||
$ > empty
|
||||
$ ./recode -r -osettings < empty
|
||||
$ cat empty | ./recode -r -osettings
|
||||
$ ./recode -r -osettings
|
||||
^D
|
||||
</code></pre>
|
||||
|
||||
<p>(Above ^D was not shown but I typed it.) The way it works: if nothing is read
|
||||
the buffer remains NULL and so I don’t print it but still do print the settings
|
||||
file. Actually even if getdelim() fails you’re supposed to free the buffer so I
|
||||
set another variable to indicate if it should be printed.</p>
|
||||
|
||||
<h1><a name="reuseconfig" href="#toc">Reusing a configuration</a></h1>
|
||||
|
||||
<pre><code> $ echo -n|./recode -r -oconfig
|
||||
4UH5II1RJ1SPIFEJLYGZWRTBHVCAMN$
|
||||
|
||||
$ cat input.txt
|
||||
IOCCC 2020 Enigma simulator example text file
|
||||
|
||||
This is a sentence.
|
||||
|
||||
This is another sentence.
|
||||
|
||||
$ ( cat config ; cat input.txt ) | ./prog - 2>/dev/null > output
|
||||
$ cat output
|
||||
AAPRT 2020 Dkemny tpgnjsjai xpovrgl jvgs wxra
|
||||
|
||||
Fytt ly m xyiilaqh.
|
||||
|
||||
Ybbp ox dmuzerm oscwgytb.
|
||||
$ ( cat config ; cat output ) | ./prog - 2>/dev/null > io
|
||||
$ diff io input.txt
|
||||
$
|
||||
</code></pre>
|
||||
|
||||
<p>Alternatively you can just use the <code>-R</code> and <code>-f</code> options:</p>
|
||||
|
||||
<pre><code> $ ./recode -finput.txt -Rconfig | ./prog - 2>/dev/null > output2
|
||||
$ diff output output2
|
||||
$
|
||||
</code></pre>
|
||||
|
||||
<h1><a name="passtoenigma" href="#toc">Write config file, read data file and pass to Enigma simulator</a></h1>
|
||||
|
||||
<pre><code> $ ./recode -finput.txt -oconfig | ./prog - 2>/dev/null > output
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 2
|
||||
Input rotor 2 (1 - 5): 5
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): C
|
||||
Input setting 2 (A - Z): O
|
||||
Input setting 3 (A - Z): D
|
||||
Input position 1 (A - Z): E
|
||||
Input position 2 (A - Z): L
|
||||
Input position 3 (A - Z): O
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: TR
|
||||
Input plugboard pair 2: SN
|
||||
Input plugboard pair 3: OG
|
||||
Input plugboard pair 4: ME
|
||||
Input plugboard pair 5: XY
|
||||
Input plugboard pair 6: WZ
|
||||
Input plugboard pair 7: UV
|
||||
Input plugboard pair 8: AB
|
||||
Input plugboard pair 9: CD
|
||||
Input plugboard pair 10: FI
|
||||
|
||||
$ cat config
|
||||
2CE5OL3DO2TRSNOGMEXYWZUVABCDFI
|
||||
</code></pre>
|
||||
|
||||
<p>Besides a famous book that I happen to love (who doesn’t? Ah, but what is it
|
||||
Cody?) there’s also a reference to code which I also love (just as all
|
||||
participants of the IOCCC do). But what matters is the output:</p>
|
||||
|
||||
<pre><code> $ cat output
|
||||
DBFAF 2020 Ittejg ltblwriac uqdfqvr dhqh ghhf
|
||||
|
||||
Jsjy ce v pxdmullo.
|
||||
|
||||
Sara tj rtaayak uxfhjcti.
|
||||
|
||||
$ ./recode -Rconfig -foutput | ./prog - 2>/dev/null
|
||||
IOCCC 2020 Enigma simulator example text file
|
||||
|
||||
This is a sentence.
|
||||
|
||||
This is another sentence.
|
||||
</code></pre>
|
||||
|
||||
<h1><a name="directlytoenigma" href="#toc">Piping directly to the Enigma code once (with randomised settings, saved)</a></h1>
|
||||
|
||||
<p>This is like the above only randomised:</p>
|
||||
|
||||
<pre><code> $ ./recode -r -oconfig|./prog - 2>/dev/null
|
||||
IOCCC
|
||||
UGEVP
|
||||
</code></pre>
|
||||
|
||||
<p>Note that I typed in IOCCC and sent EOF (ctrl-d); the settings were written to
|
||||
the config file (for deciphering later) and then all of it was piped to the
|
||||
Enigma entry resulting in the line below IOCCC. But let’s verify it worked out
|
||||
okay:</p>
|
||||
|
||||
<pre><code> $ cat config
|
||||
2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ
|
||||
</code></pre>
|
||||
|
||||
<p>Without having to copy/paste intermediate results:</p>
|
||||
|
||||
<pre><code> $ echo IOCCC | ./recode -Rconfig | ./prog - 2>/dev/null | ./recode -Rconfig | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
</code></pre>
|
||||
|
||||
<p>You can also use a string for the <code>-R</code> option. I’ll use command substitution and
|
||||
actual pasting to demonstrate:</p>
|
||||
|
||||
<pre><code> $ echo IOCCC | ./recode -R$(cat config) | ./prog - 2>/dev/null | ./recode -R2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
</code></pre>
|
||||
|
||||
<h1><a name="conclusion" href="#toc">Usage conclusion</a></h1>
|
||||
|
||||
<p>That should give you an idea of how to use the recode program. I leave it as
|
||||
an exercise to the reader to implement additional features but here are some
|
||||
ideas of what could be done and how this entry might be used (including that
|
||||
delicious challenge).</p>
|
||||
|
||||
<h1><a name="additions" href="#toc">Example additions</a></h1>
|
||||
|
||||
<ul>
|
||||
<li>Add code (to prog.c) that tries to determine possible decipherments based on
|
||||
a given crib (or set of cribs).</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h1><a name="exampleuses" href="#toc">Example uses</a></h1>
|
||||
|
||||
<ul>
|
||||
<li><p>Take an actual key sheet and message for that day and try and decipher the
|
||||
message (might help if you know German!). I haven’t actually done this for
|
||||
reasons I explained in the remarks (including that I cannot easily verify one
|
||||
particular as well as the fact that there were different procedures, different
|
||||
machines etc. - plus my vision is not good enough for the quality of the
|
||||
pictures).</p></li>
|
||||
<li><p>Try making sense of a politician’s speeches by putting them into the
|
||||
simulator. It might not make much sense but can it honestly be that much worse ?
|
||||
:) Actually yes it could be (and we don’t need the Enigma helping them either)
|
||||
and I can think of a whole host of other things more entertaining including
|
||||
watching dry paint stay dry on a wall but why not poke fun at politicians
|
||||
anyway?</p></li>
|
||||
<li><p>Best idea: try the below experiment!</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h1><a name="cake" href="#toc">Delicious Enigma: Double-layered Chocolate Fudge Cake</a></h1>
|
||||
|
||||
<p>As I was making the above silly list something occurred to me. My other entries
|
||||
this year include a recipe for a wonderful double-layered chocolate fudge cake
|
||||
but why would it not be included in this one too? But then if that’s the case
|
||||
why on Earth should it be unscrambled?</p>
|
||||
|
||||
<p>So this is what I offer: if you take one of the settings below and run the
|
||||
simulator on the file <a href="chocolate-cake.html">chocolate-cake.html</a> you will have a wonderful
|
||||
chocolate cake recipe (that even my late stepmum who didn’t even like chocolate
|
||||
loved - it’s a speciality of my mum’s and they were the best of friends too). If
|
||||
you’re lazy just go and look at my other entry. Then again if you’re lazy you’re
|
||||
probably not reading this far! :)</p>
|
||||
|
||||
<p>The settings is one of the below but a couple questions you might ask yourself:</p>
|
||||
|
||||
<ol>
|
||||
<li><p>Are any invalid input?</p></li>
|
||||
<li><p>Is there some other kind of trickery involved here?</p></li>
|
||||
</ol>
|
||||
|
||||
|
||||
<p>I can think of the best way to answer these and I think I need not even mention
|
||||
it. Have fun and enjoy! BTW: Depending on where you are in this world and how
|
||||
warm it is the icing can be a bit of an issue - I give some ideas in the file on
|
||||
what can be done for this. At worst though the icing won’t come out as good as
|
||||
it usually does.</p>
|
||||
|
||||
<p>Hints:</p>
|
||||
|
||||
<ol>
|
||||
<li><p>It’s not the middle one.</p></li>
|
||||
<li><p>Yes there are some things kind of spelt here. These include things about
|
||||
cake and chocolate. Some things spelt mean nothing whatever and can be
|
||||
considered coincidences. Some were randomised.</p></li>
|
||||
<li><p>There is an obscure thing about my entry that can help locate the proper key
|
||||
of the 16 given below! The questions are what is it and is is it worth going
|
||||
this way? (I think the second answer is ‘no’ but that’s me.)</p></li>
|
||||
<li><p>The above points might or might not be relevant. What is relevant is one
|
||||
will reveal a wonderful <a href="chocolate-cake.html">Double-layered Chocolate Fudge Cake</a> recipe:</p>
|
||||
|
||||
<pre><code> 142CHOCOLATESVCAKESTBJLKMUMVWX
|
||||
0EZ4PC1CC0PGTAQSOXWNMDRYKFUZEI
|
||||
3UY0XF4QG1GTJQLARPKHBEMCOFVUIN
|
||||
0WE1HK4PL0RVSGXFDKENZYTPCMAHUW
|
||||
2LV0KC1IE0HTFPCLWOJDBQIRVMEAGN
|
||||
1SS4QX2RY1SRAQGKUYHCBLPFJDVTNZ
|
||||
3IW1QR0TZ0GQEDWIYJUPMFZBRAONHS
|
||||
3OP1KN4MO0HPFZCEAKYQIRXGVMOTUW
|
||||
4OC2CC0AK1CODELUVRSNGKIZBJPTMY
|
||||
4MU0MS1CA1KELUVRSXTABJNOCDMQFG
|
||||
0MU4MC2HO1CLATEFBJMONPQRVWXYZD
|
||||
125CHOCOLATESEXCAKESJADFNOPQRS
|
||||
0CH3OC1OL1ATEMBJNOCDLSIFWHRVXY
|
||||
4MU1MS3CA0KECHOLATBJSNPXVUFGZY
|
||||
4VW0SL1YB0IYJSLBECKTNAXGPUVHRF
|
||||
0MC4OH2CO1LATEUMBJCDFGHINOPRQS
|
||||
</code></pre></li>
|
||||
</ol>
|
||||
|
||||
|
||||
<p>BTW: What’s the middle of a list with even numbered items anyway?</p>
|
||||
<BR>
|
||||
<HR>
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2020,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,564 @@
|
||||
# The recode configurator documentation (and a fun way to explore my 2020 IOCCC Enigma simulator)
|
||||
|
||||
N.B. At the end of this file I have given a fun exercise that can be used to
|
||||
explore my Enigma simulator. It's especially worth doing if you you like
|
||||
good chocolate and could use a delicious [Double-layered Chocolate Fudge Cake][].
|
||||
|
||||
Alternatively if you just want the recipe you could look at my Snake entry
|
||||
'Don't tread on me award' since it's also there and not enciphered.
|
||||
|
||||
<a name="toc"></a>
|
||||
- [What is recode and why is it recommended?](#recode)
|
||||
- [Options](#options)
|
||||
* [Protecting against the same I/O file](#samefile)
|
||||
* [File options parser limitation](#fileoptions)
|
||||
* [-R option validation?](#validation)
|
||||
- [Piping commands to recode](#pipingtorecode)
|
||||
- [Piping recode to the Enigma simulator](#pipingtoenigma)
|
||||
- [Manually test the recode program with the Enigma program](#manuallytest)
|
||||
- [Only write config file](#onlyconfig)
|
||||
- [Reusing a configuration](#reuseconfig)
|
||||
- [Write config file, read data file and pass to Enigma simulator](#passtoenigma)
|
||||
- [Piping directly to the Enigma code once (with randomised settings, saved)](#directlytoenigma)
|
||||
- [Usage conclusion](#conclusion)
|
||||
- [Example additions](#additions)
|
||||
- [Example uses](#exampleuses)
|
||||
- [Delicious Enigma: Double-layered Chocolate Fudge Cake](#cake)
|
||||
|
||||
# <a name="recode" href="#toc">What is recode and why is it recommended?</a>
|
||||
|
||||
To demonstrate how to and why you should use the recode program with the Enigma
|
||||
simulator I have included some examples here as well as brief ('brief?!' I am sure
|
||||
many would think but it's brief for me) commentary.
|
||||
|
||||
It would not be possible to do all that the recode program does in my entry
|
||||
itself but I wanted to demonstrate the features of my entry and this seemed the
|
||||
best way to do that. It also enhances the use of the simulator to make it
|
||||
reusable etc.
|
||||
|
||||
The recode name idea is that it recodes the input (validating first) to be input
|
||||
for the simulator itself. It can pseudo-randomly select all the settings, it can
|
||||
write the settings to a file, read from input file (e.g. for the text to
|
||||
encipher if piped to the simulator) etc.
|
||||
|
||||
Basically it's a configurator for the Enigma simulator that makes it easier to
|
||||
use the simulator as well as to reuse the configuration to decipher messages
|
||||
that have been enciphered by those settings. But it also tries to make it look
|
||||
more like the real thing in that it shows the actual rotors (labelling them with
|
||||
the Roman numeral), the reflectors (labelling them with B, C and showing the
|
||||
actual strings) etc.
|
||||
|
||||
In this file I will show an example of each feature and then get to the
|
||||
wonderful 'challenge' for everyone.
|
||||
|
||||
# <a name="options" href="#toc">Options</a>
|
||||
|
||||
usage: ./recode [options]
|
||||
-v display selected settings
|
||||
-r pseudo-randomly select settings
|
||||
-f<input file> read file for Enigma input
|
||||
-R<string|file> init settings from settings string or file
|
||||
-o<output file> write settings to file
|
||||
|
||||
|
||||
|
||||
`-r` randomises settings. It won't prompt you for settings but it will for input
|
||||
if you don't give the option to read in a file for input.
|
||||
|
||||
`-v` shows selected settings. For example combining `-r` and `-v`:
|
||||
|
||||
$ echo IOCCC | ./recode -r -v
|
||||
Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
Ring 2: ( V) VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Ring 3: ( IV) ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
Ring settings: WAR
|
||||
Ring positions: XKE
|
||||
Reflector: (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
Plugboard pair #01: XE
|
||||
Plugboard pair #02: HJ
|
||||
Plugboard pair #03: SA
|
||||
Plugboard pair #04: PY
|
||||
Plugboard pair #05: CI
|
||||
Plugboard pair #06: ZB
|
||||
Plugboard pair #07: WD
|
||||
Plugboard pair #08: QN
|
||||
Plugboard pair #09: RU
|
||||
Plugboard pair #10: VG
|
||||
1WX5AK4RE1XEHJSAPYCIZBWDQNRUVGIOCCC
|
||||
|
||||
Though you won't find such strings in recode.c or prog.c. (You will find the
|
||||
Roman numerals for the rotors and the 'A' and 'B' for the reflectors in recode.c
|
||||
though). Yes the 'WAR' for the Ringstellung (Ring settings) is an amusing
|
||||
coincidence *but it really did happen!*
|
||||
|
||||
As for `-f` the contents would be output with the settings e.g. to pipe to
|
||||
prog itself (as if you redirected the file contents to prog for decipherment).
|
||||
If the file cannot be opened it sets back to stdin.
|
||||
|
||||
`-o` outputs the settings to the file. If the file cannot be opened for writing
|
||||
or is the same file name (see below) then only stdout will be used. Example of
|
||||
randomised output going to a file:
|
||||
|
||||
$ ./recode -r -oconfig
|
||||
IOCCC
|
||||
3PP4UB5GG1ELGTKFCOPVBNUYXJAWSDIOCCC
|
||||
$ cat config
|
||||
3PP4UB5GG1ELGTKFCOPVBNUYXJAWSD$
|
||||
|
||||
Notice that a terminating newline isn't added. Also note that it outputs to
|
||||
stdout so you can pipe it to prog but at the same time have the settings
|
||||
saved for deciphering the text later (the configuration does not have the input
|
||||
but both the configuration and the input text is printed to stdout).
|
||||
|
||||
If you want to initialise the settings from previously saved settings (as a
|
||||
string or an input file that has the same format) use the `-R<settings>` option.
|
||||
Again note that this does not validate input! Although it detects out of range
|
||||
for the arrays it doesn't detect duplicates. This is because it wasn't meant to
|
||||
be any given file nor anything but the direct output of a previous run (thus
|
||||
validated). I'm not even guaranteeing that I got the array tests valid in
|
||||
recode.c -R option!
|
||||
|
||||
|
||||
## <a name="samefile" href="#toc">Protecting against the same I/O file</a>
|
||||
|
||||
Because some file systems are case-insensitive I have implemented a
|
||||
case-insensitive strcmp(); if the input file name is the same as the output file
|
||||
name I won't write to it. From a quick test this is important particularly if
|
||||
neither file exist because if both calls to stat() fail then the inodes will be
|
||||
the same (since what else could they be set to but the same initial value?).
|
||||
This might be overprotective but I believe it better to prevent user error where
|
||||
possible. Of course if neither file exists it might be argued that it's not
|
||||
necessary to worry since you can't read from a file that doesn't exist. But then
|
||||
what about if one exists but the other does not?
|
||||
|
||||
## <a name="fileoptions" href="#toc">File options parser limitation</a>
|
||||
|
||||
Due to the way the parsing of options is done (no spaces between option char and
|
||||
argument) shell expansion will not work right so for example doing:
|
||||
|
||||
$ ./recode -R~/config
|
||||
|
||||
Will not read the file 'config' in the home directory. I show another way to
|
||||
achieve this later.
|
||||
|
||||
This limitation also applies to the `-f` and `-o` options!
|
||||
|
||||
|
||||
## <a name="validation" href="#toc">-R option validation?</a>
|
||||
|
||||
Again the `-R` option does not validate input. For validation you have to run
|
||||
the program interactively.
|
||||
|
||||
# <a name="pipingtorecode" href="#toc">Piping commands to recode</a>
|
||||
|
||||
If stdin is not a tty (`!isatty(0)`) and neither randomised mode nor reading in
|
||||
from a file is specified then you might just see something like:
|
||||
|
||||
$ echo testing test tests | ./recode
|
||||
1AB2BB3CC1testing test tests
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null
|
||||
mfrwxan lzng ofnlu
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode
|
||||
1AB2BB3CC1mfrwxan lzng ofnlu
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null
|
||||
testing test tests
|
||||
|
||||
|
||||
In other words just the defaults. This was to simplify the problems with
|
||||
prompting again for input if it's invalid (though as you'll see it does a good
|
||||
job at this anyway).
|
||||
|
||||
|
||||
# <a name="pipingtoenigma" href="#toc">Piping recode to the Enigma simulator</a>
|
||||
|
||||
If you're using recode to recode the input so you don't have to type in the
|
||||
input manually (if you randomise or read in from previously saved file no input
|
||||
need be done at all) then make sure to redirect stderr to /dev/null. If you
|
||||
don't you might see something like:
|
||||
|
||||
$ ./recode -r | ./prog -
|
||||
Ring 1: IOCCC
|
||||
Setting 1: Position 1: Ring 2: Setting 2: Position 2: Ring 3: Setting 3: Position 3: Reflector: Plugboard pair 1: Plugboard pair 2: Plugboard pair 3: Plugboard pair 4: Plugboard pair 5: Plugboard pair 6: Plugboard pair 7: Plugboard pair 8: Plugboard pair 9: Plugboard pair 10: DEVIY
|
||||
|
||||
What happened is that `Ring 1: ` is printed to stderr but since it's not been
|
||||
redirected to /dev/null it prints this out; at this point however it prompts for
|
||||
input. Why or how it shows the first prompt instead of later on I do not know.
|
||||
Anyway at this point the simulator is already expecting input to en/decipher.
|
||||
That's why after I sent EOF it printed out the remaining strings to stderr.
|
||||
|
||||
|
||||
|
||||
# <a name="manuallytest" href="#toc">Manually test the recode program with the Enigma program</a>
|
||||
|
||||
$ cat input
|
||||
IOCCC
|
||||
|
||||
$ ./recode -finput
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 1
|
||||
Input rotor 2 (1 - 5): 2
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): A
|
||||
Input setting 2 (A - Z): A
|
||||
Input setting 3 (A - Z): A
|
||||
Input position 1 (A - Z): A
|
||||
Input position 2 (A - Z): A
|
||||
Input position 3 (A - Z): A
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: AB
|
||||
Input plugboard pair 2: CD
|
||||
Input plugboard pair 3: ..
|
||||
Input plugboard pair 4: EF
|
||||
Input plugboard pair 5: GH
|
||||
Input plugboard pair 6: IJ
|
||||
Input plugboard pair 7: KL
|
||||
Input plugboard pair 8: MN
|
||||
Input plugboard pair 9: OP
|
||||
Input plugboard pair 10: QR
|
||||
1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC
|
||||
|
||||
Notice that I skipped a plugboard pair; this can be done in a number of ways but
|
||||
two dots is one. Notice also that it's in a different order than the simulator:
|
||||
because with the size restrictions on my entry I saved bytes by using the same
|
||||
loop where I could. It just felt more natural to have them grouped together in a
|
||||
configurator for the simulator.
|
||||
|
||||
$ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null
|
||||
HQNVO
|
||||
$ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null | echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRHQNVO | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
|
||||
|
||||
As you can see the recode program prompts for the settings and outputs the
|
||||
input for the Enigma program. I then copied/pasted that output to the program
|
||||
and got the result HQNVO.
|
||||
|
||||
Following this I piped the original output (of recode) to the simulator and then
|
||||
piped that to the echo of the input settings (replacing the IOCCC with the
|
||||
Enigma enciphered output) and then got the result IOCCC: the original input!
|
||||
(This was before I implemented the `-R` option to greatly simplify things.)
|
||||
|
||||
Of course the last command was redundant in that I didn't need to show the first
|
||||
part again; I could have just done the latter part but I wanted to show the way
|
||||
the pipeline works with settings etc.
|
||||
|
||||
What happens if the plugboard pairs are the same but in a different order? It's
|
||||
the same output:
|
||||
|
||||
$ echo 1AA2AA3AA2AB..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null
|
||||
HQNVO
|
||||
|
||||
Also if you flip the order of the letters in the pair e.g. the AB as BA instead:
|
||||
|
||||
$ echo 1AA2AA3AA2BA..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null
|
||||
HQNVO
|
||||
|
||||
|
||||
# <a name="onlyconfig" href="#toc">Only write config file</a>
|
||||
|
||||
$ ./recode -v -oconfig -finput >/dev/null
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 1
|
||||
Input rotor 2 (1 - 5): 2
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): A
|
||||
Input setting 2 (A - Z): C
|
||||
Input setting 3 (A - Z): E
|
||||
Input position 1 (A - Z): B
|
||||
Input position 2 (A - Z): D
|
||||
Input position 3 (A - Z): F
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: AB
|
||||
Input plugboard pair 2: CD
|
||||
Input plugboard pair 3: EF
|
||||
Input plugboard pair 4: GHIJ
|
||||
Input plugboard pair 5: IJ
|
||||
Input plugboard pair 6: KL
|
||||
Input plugboard pair 7: MN
|
||||
Input plugboard pair 8: OP
|
||||
Input plugboard pair 9: QR
|
||||
Input plugboard pair 10: ST
|
||||
Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
Ring 2: ( II) AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
Ring 3: (III) BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
Ring settings: ACE
|
||||
Ring positions: BDF
|
||||
Reflector: (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Plugboard pair #01: AB
|
||||
Plugboard pair #02: CD
|
||||
Plugboard pair #03: EF
|
||||
Plugboard pair #04: GH
|
||||
Plugboard pair #05: IJ
|
||||
Plugboard pair #06: KL
|
||||
Plugboard pair #07: MN
|
||||
Plugboard pair #08: OP
|
||||
Plugboard pair #09: QR
|
||||
Plugboard pair #10: ST
|
||||
|
||||
Notice that I redirect stdout to /dev/null so that the config is only written to
|
||||
the file config. But also notice that for plugboard pair 4 I typed in `GHIJ` and
|
||||
it didn't report an error. Neither did it complain about `IJ` in the next pair.
|
||||
This is because it consumes input overflow.
|
||||
|
||||
It shouldn't be this way for the simulator though because that could cause
|
||||
inconsistent number of characters expected before the text to encipher.
|
||||
|
||||
|
||||
$ cat config
|
||||
1AB2CD3EF2ABCDEFGHIJKLMNOPQRST
|
||||
|
||||
$ ( cat config ; cat input ) | ./prog - 2>/dev/null
|
||||
LRAVE
|
||||
|
||||
$ ( cat config ; cat input ) | ./prog - 2>/dev/null | ( cat config ; echo LRAVE ) | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
|
||||
|
||||
What if you don't want to worry about having to specify input but just have the
|
||||
settings written? You can do that too by either sending a newline or else
|
||||
directly type ctrl-d (or whatever you have EOF set to) or give it an empty file.
|
||||
|
||||
The following are all equivalent in that they will write to a settings file (the
|
||||
first one will print a newline with the echo but that won't matter):
|
||||
|
||||
$ echo | ./recode -r -osettings
|
||||
$ echo -n | ./recode -r -osettings
|
||||
$ > empty
|
||||
$ ./recode -r -osettings < empty
|
||||
$ cat empty | ./recode -r -osettings
|
||||
$ ./recode -r -osettings
|
||||
^D
|
||||
|
||||
(Above ^D was not shown but I typed it.) The way it works: if nothing is read
|
||||
the buffer remains NULL and so I don't print it but still do print the settings
|
||||
file. Actually even if getdelim() fails you're supposed to free the buffer so I
|
||||
set another variable to indicate if it should be printed.
|
||||
|
||||
# <a name="reuseconfig" href="#toc">Reusing a configuration</a>
|
||||
|
||||
$ echo -n|./recode -r -oconfig
|
||||
4UH5II1RJ1SPIFEJLYGZWRTBHVCAMN$
|
||||
|
||||
$ cat input.txt
|
||||
IOCCC 2020 Enigma simulator example text file
|
||||
|
||||
This is a sentence.
|
||||
|
||||
This is another sentence.
|
||||
|
||||
$ ( cat config ; cat input.txt ) | ./prog - 2>/dev/null > output
|
||||
$ cat output
|
||||
AAPRT 2020 Dkemny tpgnjsjai xpovrgl jvgs wxra
|
||||
|
||||
Fytt ly m xyiilaqh.
|
||||
|
||||
Ybbp ox dmuzerm oscwgytb.
|
||||
$ ( cat config ; cat output ) | ./prog - 2>/dev/null > io
|
||||
$ diff io input.txt
|
||||
$
|
||||
|
||||
Alternatively you can just use the `-R` and `-f` options:
|
||||
|
||||
$ ./recode -finput.txt -Rconfig | ./prog - 2>/dev/null > output2
|
||||
$ diff output output2
|
||||
$
|
||||
|
||||
|
||||
# <a name="passtoenigma" href="#toc">Write config file, read data file and pass to Enigma simulator</a>
|
||||
|
||||
$ ./recode -finput.txt -oconfig | ./prog - 2>/dev/null > output
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 2
|
||||
Input rotor 2 (1 - 5): 5
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): C
|
||||
Input setting 2 (A - Z): O
|
||||
Input setting 3 (A - Z): D
|
||||
Input position 1 (A - Z): E
|
||||
Input position 2 (A - Z): L
|
||||
Input position 3 (A - Z): O
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: TR
|
||||
Input plugboard pair 2: SN
|
||||
Input plugboard pair 3: OG
|
||||
Input plugboard pair 4: ME
|
||||
Input plugboard pair 5: XY
|
||||
Input plugboard pair 6: WZ
|
||||
Input plugboard pair 7: UV
|
||||
Input plugboard pair 8: AB
|
||||
Input plugboard pair 9: CD
|
||||
Input plugboard pair 10: FI
|
||||
|
||||
$ cat config
|
||||
2CE5OL3DO2TRSNOGMEXYWZUVABCDFI
|
||||
|
||||
Besides a famous book that I happen to love (who doesn't? Ah, but what is it
|
||||
Cody?) there's also a reference to code which I also love (just as all
|
||||
participants of the IOCCC do). But what matters is the output:
|
||||
|
||||
$ cat output
|
||||
DBFAF 2020 Ittejg ltblwriac uqdfqvr dhqh ghhf
|
||||
|
||||
Jsjy ce v pxdmullo.
|
||||
|
||||
Sara tj rtaayak uxfhjcti.
|
||||
|
||||
$ ./recode -Rconfig -foutput | ./prog - 2>/dev/null
|
||||
IOCCC 2020 Enigma simulator example text file
|
||||
|
||||
This is a sentence.
|
||||
|
||||
This is another sentence.
|
||||
|
||||
|
||||
|
||||
# <a name="directlytoenigma" href="#toc">Piping directly to the Enigma code once (with randomised settings, saved)</a>
|
||||
|
||||
This is like the above only randomised:
|
||||
|
||||
$ ./recode -r -oconfig|./prog - 2>/dev/null
|
||||
IOCCC
|
||||
UGEVP
|
||||
|
||||
|
||||
Note that I typed in IOCCC and sent EOF (ctrl-d); the settings were written to
|
||||
the config file (for deciphering later) and then all of it was piped to the
|
||||
Enigma entry resulting in the line below IOCCC. But let's verify it worked out
|
||||
okay:
|
||||
|
||||
$ cat config
|
||||
2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ
|
||||
|
||||
Without having to copy/paste intermediate results:
|
||||
|
||||
$ echo IOCCC | ./recode -Rconfig | ./prog - 2>/dev/null | ./recode -Rconfig | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
|
||||
You can also use a string for the `-R` option. I'll use command substitution and
|
||||
actual pasting to demonstrate:
|
||||
|
||||
$ echo IOCCC | ./recode -R$(cat config) | ./prog - 2>/dev/null | ./recode -R2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
|
||||
|
||||
# <a name="conclusion" href="#toc">Usage conclusion</a>
|
||||
|
||||
That should give you an idea of how to use the recode program. I leave it as
|
||||
an exercise to the reader to implement additional features but here are some
|
||||
ideas of what could be done and how this entry might be used (including that
|
||||
delicious challenge).
|
||||
|
||||
# <a name="additions" href="#toc">Example additions</a>
|
||||
|
||||
* Add code (to prog.c) that tries to determine possible decipherments based on
|
||||
a given crib (or set of cribs).
|
||||
|
||||
# <a name="exampleuses" href="#toc">Example uses</a>
|
||||
|
||||
* Take an actual key sheet and message for that day and try and decipher the
|
||||
message (might help if you know German!). I haven't actually done this for
|
||||
reasons I explained in the remarks (including that I cannot easily verify one
|
||||
particular as well as the fact that there were different procedures, different
|
||||
machines etc. - plus my vision is not good enough for the quality of the
|
||||
pictures).
|
||||
|
||||
* Try making sense of a politician's speeches by putting them into the
|
||||
simulator. It might not make much sense but can it honestly be that much worse ?
|
||||
:) Actually yes it could be (and we don't need the Enigma helping them either)
|
||||
and I can think of a whole host of other things more entertaining including
|
||||
watching dry paint stay dry on a wall but why not poke fun at politicians
|
||||
anyway?
|
||||
|
||||
* Best idea: try the below experiment!
|
||||
|
||||
# <a name="cake" href="#toc">Delicious Enigma: Double-layered Chocolate Fudge Cake</a>
|
||||
|
||||
As I was making the above silly list something occurred to me. My other entries
|
||||
this year include a recipe for a wonderful double-layered chocolate fudge cake
|
||||
but why would it not be included in this one too? But then if that's the case
|
||||
why on Earth should it be unscrambled?
|
||||
|
||||
So this is what I offer: if you take one of the settings below and run the
|
||||
simulator on the file [chocolate-cake.html][] you will have a wonderful
|
||||
chocolate cake recipe (that even my late stepmum who didn't even like chocolate
|
||||
loved - it's a speciality of my mum's and they were the best of friends too). If
|
||||
you're lazy just go and look at my other entry. Then again if you're lazy you're
|
||||
probably not reading this far! :)
|
||||
|
||||
The settings is one of the below but a couple questions you might ask yourself:
|
||||
|
||||
1. Are any invalid input?
|
||||
|
||||
2. Is there some other kind of trickery involved here?
|
||||
|
||||
I can think of the best way to answer these and I think I need not even mention
|
||||
it. Have fun and enjoy! BTW: Depending on where you are in this world and how
|
||||
warm it is the icing can be a bit of an issue - I give some ideas in the file on
|
||||
what can be done for this. At worst though the icing won't come out as good as
|
||||
it usually does.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
1. It's not the middle one.
|
||||
|
||||
2. Yes there are some things kind of spelt here. These include things about
|
||||
cake and chocolate. Some things spelt mean nothing whatever and can be
|
||||
considered coincidences. Some were randomised.
|
||||
|
||||
3. There is an obscure thing about my entry that can help locate the proper key
|
||||
of the 16 given below! The questions are what is it and is is it worth going
|
||||
this way? (I think the second answer is 'no' but that's me.)
|
||||
|
||||
4. The above points might or might not be relevant. What is relevant is one
|
||||
will reveal a wonderful [Double-layered Chocolate Fudge Cake][] recipe:
|
||||
|
||||
142CHOCOLATESVCAKESTBJLKMUMVWX
|
||||
0EZ4PC1CC0PGTAQSOXWNMDRYKFUZEI
|
||||
3UY0XF4QG1GTJQLARPKHBEMCOFVUIN
|
||||
0WE1HK4PL0RVSGXFDKENZYTPCMAHUW
|
||||
2LV0KC1IE0HTFPCLWOJDBQIRVMEAGN
|
||||
1SS4QX2RY1SRAQGKUYHCBLPFJDVTNZ
|
||||
3IW1QR0TZ0GQEDWIYJUPMFZBRAONHS
|
||||
3OP1KN4MO0HPFZCEAKYQIRXGVMOTUW
|
||||
4OC2CC0AK1CODELUVRSNGKIZBJPTMY
|
||||
4MU0MS1CA1KELUVRSXTABJNOCDMQFG
|
||||
0MU4MC2HO1CLATEFBJMONPQRVWXYZD
|
||||
125CHOCOLATESEXCAKESJADFNOPQRS
|
||||
0CH3OC1OL1ATEMBJNOCDLSIFWHRVXY
|
||||
4MU1MS3CA0KECHOLATBJSNPXVUFGZY
|
||||
4VW0SL1YB0IYJSLBECKTNAXGPUVHRF
|
||||
0MC4OH2CO1LATEUMBJCDFGHINOPRQS
|
||||
|
||||
|
||||
BTW: What's the middle of a list with even numbered items anyway?
|
||||
|
||||
[chocolate-cake.html]: chocolate-cake.html
|
||||
[Double-layered Chocolate Fudge Cake]: chocolate-cake.html
|
||||
@@ -0,0 +1,572 @@
|
||||
# The recode configurator documentation (and a fun way to explore my 2020 IOCCC Enigma simulator)
|
||||
|
||||
N.B. At the end of this file I have given a fun exercise that can be used to
|
||||
explore my Enigma simulator. It's especially worth doing if you you like
|
||||
good chocolate and could use a delicious [Double-layered Chocolate Fudge Cake][].
|
||||
|
||||
Alternatively if you just want the recipe you could look at my Snake entry
|
||||
'Don't tread on me award' since it's also there and not enciphered.
|
||||
|
||||
<a name="toc"></a>
|
||||
- [What is recode and why is it recommended?](#recode)
|
||||
- [Options](#options)
|
||||
* [Protecting against the same I/O file](#samefile)
|
||||
* [File options parser limitation](#fileoptions)
|
||||
* [-R option validation?](#validation)
|
||||
- [Piping commands to recode](#pipingtorecode)
|
||||
- [Piping recode to the Enigma simulator](#pipingtoenigma)
|
||||
- [Manually test the recode program with the Enigma program](#manuallytest)
|
||||
- [Only write config file](#onlyconfig)
|
||||
- [Reusing a configuration](#reuseconfig)
|
||||
- [Write config file, read data file and pass to Enigma simulator](#passtoenigma)
|
||||
- [Piping directly to the Enigma code once (with randomised settings, saved)](#directlytoenigma)
|
||||
- [Usage conclusion](#conclusion)
|
||||
- [Example additions](#additions)
|
||||
- [Example uses](#exampleuses)
|
||||
- [Delicious Enigma: Double-layered Chocolate Fudge Cake](#cake)
|
||||
|
||||
# <a name="recode" href="#toc">What is recode and why is it recommended?</a>
|
||||
|
||||
To demonstrate how to and why you should use the recode program with the Enigma
|
||||
simulator I have included some examples here as well as brief ('brief?!' I am sure
|
||||
many would think but it's brief for me) commentary.
|
||||
|
||||
It would not be possible to do all that the recode program does in my entry
|
||||
itself but I wanted to demonstrate the features of my entry and this seemed the
|
||||
best way to do that. It also enhances the use of the simulator to make it
|
||||
reusable etc.
|
||||
|
||||
The recode name idea is that it recodes the input (validating first) to be input
|
||||
for the simulator itself. It can pseudo-randomly select all the settings, it can
|
||||
write the settings to a file, read from input file (e.g. for the text to
|
||||
encipher if piped to the simulator) etc.
|
||||
|
||||
Basically it's a configurator for the Enigma simulator that makes it easier to
|
||||
use the simulator as well as to reuse the configuration to decipher messages
|
||||
that have been enciphered by those settings. But it also tries to make it look
|
||||
more like the real thing in that it shows the actual rotors (labelling them with
|
||||
the Roman numeral), the reflectors (labelling them with B, C and showing the
|
||||
actual strings) etc.
|
||||
|
||||
In this file I will show an example of each feature and then get to the
|
||||
wonderful 'challenge' for everyone.
|
||||
|
||||
# <a name="options" href="#toc">Options</a>
|
||||
|
||||
usage: ./recode [options]
|
||||
-v display selected settings
|
||||
-r pseudo-randomly select settings
|
||||
-f<input file> read file for Enigma input
|
||||
-R<string|file> init settings from settings string or file
|
||||
-o<output file> write settings to file
|
||||
|
||||
|
||||
|
||||
`-r` randomises settings. It won't prompt you for settings but it will for input
|
||||
if you don't give the option to read in a file for input.
|
||||
|
||||
`-v` shows selected settings. For example combining `-r` and `-v`:
|
||||
|
||||
$ echo IOCCC | ./recode -r -v
|
||||
Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
Ring 2: ( V) VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Ring 3: ( IV) ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
Ring settings: WAR
|
||||
Ring positions: XKE
|
||||
Reflector: (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
Plugboard pair #01: XE
|
||||
Plugboard pair #02: HJ
|
||||
Plugboard pair #03: SA
|
||||
Plugboard pair #04: PY
|
||||
Plugboard pair #05: CI
|
||||
Plugboard pair #06: ZB
|
||||
Plugboard pair #07: WD
|
||||
Plugboard pair #08: QN
|
||||
Plugboard pair #09: RU
|
||||
Plugboard pair #10: VG
|
||||
1WX5AK4RE1XEHJSAPYCIZBWDQNRUVGIOCCC
|
||||
|
||||
Though you won't find such strings in recode.c or prog.c. (You will find the
|
||||
Roman numerals for the rotors and the 'A' and 'B' for the reflectors in recode.c
|
||||
though). Yes the 'WAR' for the Ringstellung (Ring settings) is an amusing
|
||||
coincidence *but it really did happen!*
|
||||
|
||||
As for `-f` the contents would be output with the settings e.g. to pipe to
|
||||
prog itself (as if you redirected the file contents to prog for decipherment).
|
||||
If the file cannot be opened it sets back to stdin.
|
||||
|
||||
`-o` outputs the settings to the file. If the file cannot be opened for writing
|
||||
or is the same file name (see below) then only stdout will be used. Example of
|
||||
randomised output going to a file:
|
||||
|
||||
$ ./recode -r -oconfig
|
||||
IOCCC
|
||||
3PP4UB5GG1ELGTKFCOPVBNUYXJAWSDIOCCC
|
||||
$ cat config
|
||||
3PP4UB5GG1ELGTKFCOPVBNUYXJAWSD$
|
||||
|
||||
Notice that a terminating newline isn't added. Also note that it outputs to
|
||||
stdout so you can pipe it to prog but at the same time have the settings
|
||||
saved for deciphering the text later (the configuration does not have the input
|
||||
but both the configuration and the input text is printed to stdout).
|
||||
|
||||
If you want to initialise the settings from previously saved settings (as a
|
||||
string or an input file that has the same format) use the `-R<settings>` option.
|
||||
Again note that this does not validate input! Although it detects out of range
|
||||
for the arrays it doesn't detect duplicates. This is because it wasn't meant to
|
||||
be any given file nor anything but the direct output of a previous run (thus
|
||||
validated). I'm not even guaranteeing that I got the array tests valid in
|
||||
recode.c -R option!
|
||||
|
||||
|
||||
## <a name="samefile" href="#toc">Protecting against the same I/O file</a>
|
||||
|
||||
Because some file systems are case-insensitive I have implemented a
|
||||
case-insensitive strcmp(); if the input file name is the same as the output file
|
||||
name I won't write to it. From a quick test this is important particularly if
|
||||
neither file exist because if both calls to stat() fail then the inodes will be
|
||||
the same (since what else could they be set to but the same initial value?).
|
||||
This might be overprotective but I believe it better to prevent user error where
|
||||
possible. Of course if neither file exists it might be argued that it's not
|
||||
necessary to worry since you can't read from a file that doesn't exist. But then
|
||||
what about if one exists but the other does not?
|
||||
|
||||
## <a name="fileoptions" href="#toc">File options parser limitation</a>
|
||||
|
||||
Due to the way the parsing of options is done (no spaces between option char and
|
||||
argument) shell expansion will not work right so for example doing:
|
||||
|
||||
$ ./recode -R~/config
|
||||
|
||||
Will not read the file 'config' in the home directory. I show another way to
|
||||
achieve this later.
|
||||
|
||||
This limitation also applies to the `-f` and `-o` options!
|
||||
|
||||
|
||||
## <a name="validation" href="#toc">-R option validation?</a>
|
||||
|
||||
Again the `-R` option does not validate input. For validation you have to run
|
||||
the program interactively.
|
||||
|
||||
# <a name="pipingtorecode" href="#toc">Piping commands to recode</a>
|
||||
|
||||
If stdin is not a tty (`!isatty(0)`) and neither randomised mode nor reading in
|
||||
from a file is specified then you might just see something like:
|
||||
|
||||
$ echo testing test tests | ./recode
|
||||
1AB2BB3CC1testing test tests
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null
|
||||
mfrwxan lzng ofnlu
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode
|
||||
1AB2BB3CC1mfrwxan lzng ofnlu
|
||||
|
||||
$ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null
|
||||
testing test tests
|
||||
|
||||
|
||||
In other words just the defaults. This was to simplify the problems with
|
||||
prompting again for input if it's invalid (though as you'll see it does a good
|
||||
job at this anyway).
|
||||
|
||||
|
||||
# <a name="pipingtoenigma" href="#toc">Piping recode to the Enigma simulator</a>
|
||||
|
||||
If you're using recode to recode the input so you don't have to type in the
|
||||
input manually (if you randomise or read in from previously saved file no input
|
||||
need be done at all) then make sure to redirect stderr to /dev/null. If you
|
||||
don't you might see something like:
|
||||
|
||||
$ ./recode -r | ./prog -
|
||||
Ring 1: IOCCC
|
||||
Setting 1: Position 1: Ring 2: Setting 2: Position 2: Ring 3: Setting 3: Position 3: Reflector: Plugboard pair 1: Plugboard pair 2: Plugboard pair 3: Plugboard pair 4: Plugboard pair 5: Plugboard pair 6: Plugboard pair 7: Plugboard pair 8: Plugboard pair 9: Plugboard pair 10: DEVIY
|
||||
|
||||
What happened is that `Ring 1: ` is printed to stderr but since it's not been
|
||||
redirected to /dev/null it prints this out; at this point however it prompts for
|
||||
input. Why or how it shows the first prompt instead of later on I do not know.
|
||||
Anyway at this point the simulator is already expecting input to en/decipher.
|
||||
That's why after I sent EOF it printed out the remaining strings to stderr.
|
||||
|
||||
|
||||
|
||||
# <a name="manuallytest" href="#toc">Manually test the recode program with the Enigma program</a>
|
||||
|
||||
$ cat input
|
||||
IOCCC
|
||||
|
||||
$ ./recode -finput
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 1
|
||||
Input rotor 2 (1 - 5): 2
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): A
|
||||
Input setting 2 (A - Z): A
|
||||
Input setting 3 (A - Z): A
|
||||
Input position 1 (A - Z): A
|
||||
Input position 2 (A - Z): A
|
||||
Input position 3 (A - Z): A
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: AB
|
||||
Input plugboard pair 2: CD
|
||||
Input plugboard pair 3: ..
|
||||
Input plugboard pair 4: EF
|
||||
Input plugboard pair 5: GH
|
||||
Input plugboard pair 6: IJ
|
||||
Input plugboard pair 7: KL
|
||||
Input plugboard pair 8: MN
|
||||
Input plugboard pair 9: OP
|
||||
Input plugboard pair 10: QR
|
||||
1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC
|
||||
|
||||
Notice that I skipped a plugboard pair; this can be done in a number of ways but
|
||||
two dots is one. Notice also that it's in a different order than the simulator:
|
||||
because with the size restrictions on my entry I saved bytes by using the same
|
||||
loop where I could. It just felt more natural to have them grouped together in a
|
||||
configurator for the simulator.
|
||||
|
||||
$ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null
|
||||
HQNVO
|
||||
$ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null | echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRHQNVO | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
|
||||
|
||||
As you can see the recode program prompts for the settings and outputs the
|
||||
input for the Enigma program. I then copied/pasted that output to the program
|
||||
and got the result HQNVO.
|
||||
|
||||
Following this I piped the original output (of recode) to the simulator and then
|
||||
piped that to the echo of the input settings (replacing the IOCCC with the
|
||||
Enigma enciphered output) and then got the result IOCCC: the original input!
|
||||
(This was before I implemented the `-R` option to greatly simplify things.)
|
||||
|
||||
Of course the last command was redundant in that I didn't need to show the first
|
||||
part again; I could have just done the latter part but I wanted to show the way
|
||||
the pipeline works with settings etc.
|
||||
|
||||
What happens if the plugboard pairs are the same but in a different order? It's
|
||||
the same output:
|
||||
|
||||
$ echo 1AA2AA3AA2AB..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null
|
||||
HQNVO
|
||||
|
||||
Also if you flip the order of the letters in the pair e.g. the AB as BA instead:
|
||||
|
||||
$ echo 1AA2AA3AA2BA..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null
|
||||
HQNVO
|
||||
|
||||
|
||||
# <a name="onlyconfig" href="#toc">Only write config file</a>
|
||||
|
||||
$ ./recode -v -oconfig -finput >/dev/null
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 1
|
||||
Input rotor 2 (1 - 5): 2
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): A
|
||||
Input setting 2 (A - Z): C
|
||||
Input setting 3 (A - Z): E
|
||||
Input position 1 (A - Z): B
|
||||
Input position 2 (A - Z): D
|
||||
Input position 3 (A - Z): F
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: AB
|
||||
Input plugboard pair 2: CD
|
||||
Input plugboard pair 3: EF
|
||||
Input plugboard pair 4: GHIJ
|
||||
Input plugboard pair 5: IJ
|
||||
Input plugboard pair 6: KL
|
||||
Input plugboard pair 7: MN
|
||||
Input plugboard pair 8: OP
|
||||
Input plugboard pair 9: QR
|
||||
Input plugboard pair 10: ST
|
||||
Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
Ring 2: ( II) AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
Ring 3: (III) BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
Ring settings: ACE
|
||||
Ring positions: BDF
|
||||
Reflector: (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Plugboard pair #01: AB
|
||||
Plugboard pair #02: CD
|
||||
Plugboard pair #03: EF
|
||||
Plugboard pair #04: GH
|
||||
Plugboard pair #05: IJ
|
||||
Plugboard pair #06: KL
|
||||
Plugboard pair #07: MN
|
||||
Plugboard pair #08: OP
|
||||
Plugboard pair #09: QR
|
||||
Plugboard pair #10: ST
|
||||
|
||||
Notice that I redirect stdout to /dev/null so that the config is only written to
|
||||
the file config. But also notice that for plugboard pair 4 I typed in `GHIJ` and
|
||||
it didn't report an error. Neither did it complain about `IJ` in the next pair.
|
||||
This is because it consumes input overflow.
|
||||
|
||||
It shouldn't be this way for the simulator though because that could cause
|
||||
inconsistent number of characters expected before the text to encipher.
|
||||
|
||||
|
||||
$ cat config
|
||||
1AB2CD3EF2ABCDEFGHIJKLMNOPQRST
|
||||
|
||||
$ ( cat config ; cat input ) | ./prog - 2>/dev/null
|
||||
LRAVE
|
||||
|
||||
$ ( cat config ; cat input ) | ./prog - 2>/dev/null | ( cat config ; echo LRAVE ) | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
|
||||
|
||||
What if you don't want to worry about having to specify input but just have the
|
||||
settings written? You can do that too by either sending a newline or else
|
||||
directly type ctrl-d (or whatever you have EOF set to) or give it an empty file.
|
||||
|
||||
The following are all equivalent in that they will write to a settings file (the
|
||||
first one will print a newline with the echo but that won't matter):
|
||||
|
||||
$ echo | ./recode -r -osettings
|
||||
$ echo -n | ./recode -r -osettings
|
||||
$ > empty
|
||||
$ ./recode -r -osettings < empty
|
||||
$ cat empty | ./recode -r -osettings
|
||||
$ ./recode -r -osettings
|
||||
^D
|
||||
|
||||
(Above ^D was not shown but I typed it.) The way it works: if nothing is read
|
||||
the buffer remains NULL and so I don't print it but still do print the settings
|
||||
file. Actually even if getdelim() fails you're supposed to free the buffer so I
|
||||
set another variable to indicate if it should be printed.
|
||||
|
||||
# <a name="reuseconfig" href="#toc">Reusing a configuration</a>
|
||||
|
||||
$ echo -n|./recode -r -oconfig
|
||||
4UH5II1RJ1SPIFEJLYGZWRTBHVCAMN$
|
||||
|
||||
$ cat input.txt
|
||||
IOCCC 2020 Enigma simulator example text file
|
||||
|
||||
This is a sentence.
|
||||
|
||||
This is another sentence.
|
||||
|
||||
$ ( cat config ; cat input.txt ) | ./prog - 2>/dev/null > output
|
||||
$ cat output
|
||||
AAPRT 2020 Dkemny tpgnjsjai xpovrgl jvgs wxra
|
||||
|
||||
Fytt ly m xyiilaqh.
|
||||
|
||||
Ybbp ox dmuzerm oscwgytb.
|
||||
$ ( cat config ; cat output ) | ./prog - 2>/dev/null > io
|
||||
$ diff io input.txt
|
||||
$
|
||||
|
||||
Alternatively you can just use the `-R` and `-f` options:
|
||||
|
||||
$ ./recode -finput.txt -Rconfig | ./prog - 2>/dev/null > output2
|
||||
$ diff output output2
|
||||
$
|
||||
|
||||
|
||||
# <a name="passtoenigma" href="#toc">Write config file, read data file and pass to Enigma simulator</a>
|
||||
|
||||
$ ./recode -finput.txt -oconfig | ./prog - 2>/dev/null > output
|
||||
Rotors:
|
||||
(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ
|
||||
(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE
|
||||
(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO
|
||||
(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB
|
||||
(5) V: VZBRGITYUPSDNHLXAWMJQOFECK
|
||||
Input rotor 1 (1 - 5): 2
|
||||
Input rotor 2 (1 - 5): 5
|
||||
Input rotor 3 (1 - 5): 3
|
||||
Input setting 1 (A - Z): C
|
||||
Input setting 2 (A - Z): O
|
||||
Input setting 3 (A - Z): D
|
||||
Input position 1 (A - Z): E
|
||||
Input position 2 (A - Z): L
|
||||
Input position 3 (A - Z): O
|
||||
Reflector:
|
||||
(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT
|
||||
(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL
|
||||
Input reflector (1 - 2): 2
|
||||
Input plugboard pair 1: TR
|
||||
Input plugboard pair 2: SN
|
||||
Input plugboard pair 3: OG
|
||||
Input plugboard pair 4: ME
|
||||
Input plugboard pair 5: XY
|
||||
Input plugboard pair 6: WZ
|
||||
Input plugboard pair 7: UV
|
||||
Input plugboard pair 8: AB
|
||||
Input plugboard pair 9: CD
|
||||
Input plugboard pair 10: FI
|
||||
|
||||
$ cat config
|
||||
2CE5OL3DO2TRSNOGMEXYWZUVABCDFI
|
||||
|
||||
Besides a famous book that I happen to love (who doesn't? Ah, but what is it
|
||||
Cody?) there's also a reference to code which I also love (just as all
|
||||
participants of the IOCCC do). But what matters is the output:
|
||||
|
||||
$ cat output
|
||||
DBFAF 2020 Ittejg ltblwriac uqdfqvr dhqh ghhf
|
||||
|
||||
Jsjy ce v pxdmullo.
|
||||
|
||||
Sara tj rtaayak uxfhjcti.
|
||||
|
||||
$ ./recode -Rconfig -foutput | ./prog - 2>/dev/null
|
||||
IOCCC 2020 Enigma simulator example text file
|
||||
|
||||
This is a sentence.
|
||||
|
||||
This is another sentence.
|
||||
|
||||
|
||||
|
||||
# <a name="directlytoenigma" href="#toc">Piping directly to the Enigma code once (with randomised settings, saved)</a>
|
||||
|
||||
This is like the above only randomised:
|
||||
|
||||
$ ./recode -r -oconfig|./prog - 2>/dev/null
|
||||
IOCCC
|
||||
UGEVP
|
||||
|
||||
|
||||
Note that I typed in IOCCC and sent EOF (ctrl-d); the settings were written to
|
||||
the config file (for deciphering later) and then all of it was piped to the
|
||||
Enigma entry resulting in the line below IOCCC. But let's verify it worked out
|
||||
okay:
|
||||
|
||||
$ cat config
|
||||
2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ
|
||||
|
||||
Without having to copy/paste intermediate results:
|
||||
|
||||
$ echo IOCCC | ./recode -Rconfig | ./prog - 2>/dev/null | ./recode -Rconfig | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
|
||||
You can also use a string for the `-R` option. I'll use command substitution and
|
||||
actual pasting to demonstrate:
|
||||
|
||||
$ echo IOCCC | ./recode -R$(cat config) | ./prog - 2>/dev/null | ./recode -R2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ | ./prog - 2>/dev/null
|
||||
IOCCC
|
||||
|
||||
|
||||
# <a name="conclusion" href="#toc">Usage conclusion</a>
|
||||
|
||||
That should give you an idea of how to use the recode program. I leave it as
|
||||
an exercise to the reader to implement additional features but here are some
|
||||
ideas of what could be done and how this entry might be used (including that
|
||||
delicious challenge).
|
||||
|
||||
# <a name="additions" href="#toc">Example additions</a>
|
||||
|
||||
* Add code (to prog.c) that tries to determine possible decipherments based on
|
||||
a given crib (or set of cribs).
|
||||
|
||||
# <a name="exampleuses" href="#toc">Example uses</a>
|
||||
|
||||
* Take an actual key sheet and message for that day and try and decipher the
|
||||
message (might help if you know German!). I haven't actually done this for
|
||||
reasons I explained in the remarks (including that I cannot easily verify one
|
||||
particular as well as the fact that there were different procedures, different
|
||||
machines etc. - plus my vision is not good enough for the quality of the
|
||||
pictures).
|
||||
|
||||
* Try making sense of a politician's speeches by putting them into the
|
||||
simulator. It might not make much sense but can it honestly be that much worse ?
|
||||
:) Actually yes it could be (and we don't need the Enigma helping them either)
|
||||
and I can think of a whole host of other things more entertaining including
|
||||
watching dry paint stay dry on a wall but why not poke fun at politicians
|
||||
anyway?
|
||||
|
||||
* Best idea: try the below experiment!
|
||||
|
||||
# <a name="cake" href="#toc">Delicious Enigma: Double-layered Chocolate Fudge Cake</a>
|
||||
|
||||
As I was making the above silly list something occurred to me. My other entries
|
||||
this year include a recipe for a wonderful double-layered chocolate fudge cake
|
||||
but why would it not be included in this one too? But then if that's the case
|
||||
why on Earth should it be unscrambled?
|
||||
|
||||
So this is what I offer: if you take one of the settings below and run the
|
||||
simulator on the file [chocolate-cake.html][] you will have a wonderful
|
||||
chocolate cake recipe (that even my late stepmum who didn't even like chocolate
|
||||
loved - it's a speciality of my mum's and they were the best of friends too). If
|
||||
you're lazy just go and look at my other entry. Then again if you're lazy you're
|
||||
probably not reading this far! :)
|
||||
|
||||
The settings is one of the below but a couple questions you might ask yourself:
|
||||
|
||||
1. Are any invalid input?
|
||||
|
||||
2. Is there some other kind of trickery involved here?
|
||||
|
||||
I can think of the best way to answer these and I think I need not even mention
|
||||
it. Have fun and enjoy! BTW: Depending on where you are in this world and how
|
||||
warm it is the icing can be a bit of an issue - I give some ideas in the file on
|
||||
what can be done for this. At worst though the icing won't come out as good as
|
||||
it usually does.
|
||||
|
||||
|
||||
Hints:
|
||||
|
||||
1. It's not the middle one.
|
||||
|
||||
2. Yes there are some things kind of spelt here. These include things about
|
||||
cake and chocolate. Some things spelt mean nothing whatever and can be
|
||||
considered coincidences. Some were randomised.
|
||||
|
||||
3. There is an obscure thing about my entry that can help locate the proper key
|
||||
of the 16 given below! The questions are what is it and is is it worth going
|
||||
this way? (I think the second answer is 'no' but that's me.)
|
||||
|
||||
4. The above points might or might not be relevant. What is relevant is one
|
||||
will reveal a wonderful [Double-layered Chocolate Fudge Cake][] recipe:
|
||||
|
||||
142CHOCOLATESVCAKESTBJLKMUMVWX
|
||||
0EZ4PC1CC0PGTAQSOXWNMDRYKFUZEI
|
||||
3UY0XF4QG1GTJQLARPKHBEMCOFVUIN
|
||||
0WE1HK4PL0RVSGXFDKENZYTPCMAHUW
|
||||
2LV0KC1IE0HTFPCLWOJDBQIRVMEAGN
|
||||
1SS4QX2RY1SRAQGKUYHCBLPFJDVTNZ
|
||||
3IW1QR0TZ0GQEDWIYJUPMFZBRAONHS
|
||||
3OP1KN4MO0HPFZCEAKYQIRXGVMOTUW
|
||||
4OC2CC0AK1CODELUVRSNGKIZBJPTMY
|
||||
4MU0MS1CA1KELUVRSXTABJNOCDMQFG
|
||||
0MU4MC2HO1CLATEFBJMONPQRVWXYZD
|
||||
125CHOCOLATESEXCAKESJADFNOPQRS
|
||||
0CH3OC1OL1ATEMBJNOCDLSIFWHRVXY
|
||||
4MU1MS3CA0KECHOLATBJSNPXVUFGZY
|
||||
4VW0SL1YB0IYJSLBECKTNAXGPUVHRF
|
||||
0MC4OH2CO1LATEUMBJCDFGHINOPRQS
|
||||
|
||||
|
||||
BTW: What's the middle of a list with even numbered items anyway?
|
||||
|
||||
[chocolate-cake.html]: chocolate-cake.html
|
||||
[Double-layered Chocolate Fudge Cake]: chocolate-cake.html
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
(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/
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,21 @@
|
||||
3
|
||||
I
|
||||
O
|
||||
1
|
||||
C
|
||||
C
|
||||
5
|
||||
C
|
||||
Z
|
||||
2
|
||||
CO
|
||||
DE
|
||||
SN
|
||||
XY
|
||||
MS
|
||||
AT
|
||||
VF
|
||||
UR
|
||||
KL
|
||||
BJ
|
||||
IOCCC
|
||||
Reference in new issue
Block a user